Skip to content

Commit fec4c6b

Browse files
author
Christos KK Loverdos
committed
Make difficulty consensus-polymorphic (part II)
A continuation of the original commit @ f8f3689
1 parent 49bd7f6 commit fec4c6b

24 files changed

+166
-91
lines changed

src/main/scala/io/iohk/ethereum/consensus/ConsensusConfig.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package io.iohk.ethereum.consensus
22

33
import akka.util.ByteString
44
import com.typesafe.config.{Config TypesafeConfig}
5-
import io.iohk.ethereum.consensus.validators.std.StdBlockHeaderValidator
5+
import io.iohk.ethereum.consensus.validators.BlockHeaderValidator
66
import io.iohk.ethereum.domain.Address
77
import io.iohk.ethereum.nodebuilder.ShutdownHookBuilder
88
import io.iohk.ethereum.utils.Logger
@@ -66,7 +66,7 @@ object ConsensusConfig extends Logger {
6666
val coinbase = Address(config.getString(Keys.Coinbase))
6767

6868
val headerExtraData = ByteString(config.getString(Keys.HeaderExtraData).getBytes)
69-
.take(StdBlockHeaderValidator.MaxExtraDataSize)
69+
.take(BlockHeaderValidator.MaxExtraDataSize)
7070
val blockCacheSize = config.getInt(Keys.BlockCacheSize)
7171
val miningEnabled = config.getBoolean(Keys.MiningEnabled)
7272

src/main/scala/io/iohk/ethereum/consensus/atomixraft/AtomixRaftConsensus.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ import io.atomix.utils.concurrent.ThreadModel
1717
import io.atomix.utils.serializer.{KryoNamespace, Serializer}
1818
import io.iohk.ethereum.consensus.atomixraft.AtomixRaftForger.{IAmTheLeader, Init}
1919
import io.iohk.ethereum.consensus.atomixraft.blocks.AtomixRaftBlockGenerator
20+
import io.iohk.ethereum.consensus.atomixraft.validators.AtomixRaftValidators
2021
import io.iohk.ethereum.consensus.blocks.TestBlockGenerator
2122
import io.iohk.ethereum.consensus.validators.Validators
22-
import io.iohk.ethereum.consensus.validators.std.StdValidators
2323
import io.iohk.ethereum.domain.BlockchainImpl
2424
import io.iohk.ethereum.ledger.BlockPreparator
2525
import io.iohk.ethereum.ledger.Ledger.VMImpl
@@ -219,7 +219,7 @@ object AtomixRaftConsensus {
219219
config: FullConsensusConfig[AtomixRaftConfig]
220220
): AtomixRaftConsensus = {
221221

222-
val validators = StdValidators(blockchainConfig)
222+
val validators = AtomixRaftValidators(blockchainConfig)
223223

224224
val blockPreparator = new BlockPreparator(
225225
vm = vm,

src/main/scala/io/iohk/ethereum/consensus/atomixraft/blocks/AtomixRaftBlockGenerator.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.iohk.ethereum.consensus.atomixraft.blocks
22

33
import io.iohk.ethereum.consensus.ConsensusConfig
4+
import io.iohk.ethereum.consensus.atomixraft.difficulty.AtomixRaftDifficulty
45
import io.iohk.ethereum.consensus.blocks._
56
import io.iohk.ethereum.domain._
67
import io.iohk.ethereum.ledger.BlockPreparator
@@ -20,7 +21,7 @@ class AtomixRaftBlockGenerator(
2021
blockTimestampProvider
2122
) {
2223

23-
protected def calculateDifficulty(blockNumber: BigInt, parent: Block, blockTimestamp: Long): BigInt = 0
24+
protected val difficulty = AtomixRaftDifficulty
2425

2526
def withBlockTimestampProvider(blockTimestampProvider: BlockTimestampProvider): AtomixRaftBlockGenerator =
2627
new AtomixRaftBlockGenerator(
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package io.iohk.ethereum.consensus.atomixraft.difficulty
2+
3+
import io.iohk.ethereum.consensus.difficulty.ConstantDifficulty
4+
5+
object AtomixRaftDifficulty extends ConstantDifficulty(0)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.iohk.ethereum.consensus.atomixraft.validators
2+
3+
import io.iohk.ethereum.consensus.atomixraft.difficulty.AtomixRaftDifficulty
4+
import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
5+
import io.iohk.ethereum.consensus.validators.{BlockHeaderError, BlockHeaderValid, BlockHeaderValidatorSkeleton}
6+
import io.iohk.ethereum.domain.BlockHeader
7+
import io.iohk.ethereum.utils.BlockchainConfig
8+
9+
class AtomixRaftBlockHeaderValidator(blockchainConfig: BlockchainConfig)
10+
extends BlockHeaderValidatorSkeleton(blockchainConfig) {
11+
12+
protected def difficulty: DifficultyCalculator = AtomixRaftDifficulty
13+
14+
protected def validateEvenMore(
15+
blockHeader: BlockHeader,
16+
parentHeader: BlockHeader
17+
): Either[BlockHeaderError, BlockHeaderValid] = Right(BlockHeaderValid) // mo more than the standard validation
18+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.iohk.ethereum.consensus.atomixraft.validators
2+
3+
import io.iohk.ethereum.consensus.validators.std.{StdBlockValidator, StdSignedTransactionValidator, StdValidators}
4+
import io.iohk.ethereum.utils.BlockchainConfig
5+
6+
7+
object AtomixRaftValidators {
8+
def apply(blockchainConfig: BlockchainConfig): AtomixRaftValidators = {
9+
new StdValidators(
10+
StdBlockValidator,
11+
new AtomixRaftBlockHeaderValidator(blockchainConfig),
12+
new StdSignedTransactionValidator(blockchainConfig)
13+
)
14+
}
15+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package io.iohk.ethereum.consensus.atomixraft
2+
3+
import io.iohk.ethereum.consensus.validators.std.StdValidators
4+
5+
package object validators {
6+
final type AtomixRaftValidators = StdValidators
7+
}

src/main/scala/io/iohk/ethereum/consensus/blocks/BlockGeneratorSkeleton.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import java.util.concurrent.atomic.AtomicReference
44

55
import akka.util.ByteString
66
import io.iohk.ethereum.consensus.ConsensusConfig
7+
import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
78
import io.iohk.ethereum.consensus.ethash.blocks.Ommers
89
import io.iohk.ethereum.consensus.validators.std.MptListValidator.intByteArraySerializable
910
import io.iohk.ethereum.crypto.kec256
@@ -42,7 +43,7 @@ abstract class BlockGeneratorSkeleton(
4243

4344
protected def newBlockBody(transactions: Seq[SignedTransaction], x: X): BlockBody
4445

45-
protected def calculateDifficulty(blockNumber: BigInt, parent: Block, blockTimestamp: Long): BigInt
46+
protected def difficulty: DifficultyCalculator
4647

4748
protected def defaultPrepareHeader(
4849
blockNumber: BigInt,
@@ -60,7 +61,7 @@ abstract class BlockGeneratorSkeleton(
6061
transactionsRoot = ByteString.empty,
6162
receiptsRoot = ByteString.empty,
6263
logsBloom = ByteString.empty,
63-
difficulty = calculateDifficulty(blockNumber, parent, blockTimestamp),
64+
difficulty = difficulty.calculateDifficulty(blockNumber, blockTimestamp, parent.header),
6465
number = blockNumber,
6566
gasLimit = calculateGasLimit(parent.header.gasLimit),
6667
gasUsed = 0,
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.iohk.ethereum.consensus.difficulty
2+
3+
import io.iohk.ethereum.domain.BlockHeader
4+
5+
class ConstantDifficulty(c: BigInt) extends DifficultyCalculator {
6+
final def calculateDifficulty(blockNumber: BigInt, blockTimestamp: Long, parentHeader: BlockHeader): BigInt = c
7+
}
8+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package io.iohk.ethereum.consensus.difficulty
2+
3+
import io.iohk.ethereum.domain.BlockHeader
4+
5+
trait DifficultyCalculator {
6+
def calculateDifficulty(blockNumber: BigInt, blockTimestamp: Long, parentHeader: BlockHeader): BigInt
7+
}

src/main/scala/io/iohk/ethereum/consensus/ethash/EthashConsensus.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import akka.actor.ActorRef
88
import io.iohk.ethereum.consensus.blocks.TestBlockGenerator
99
import io.iohk.ethereum.consensus.ethash.EthashMiner.MinerMsg
1010
import io.iohk.ethereum.consensus.ethash.blocks.{EthashBlockGenerator, EthashBlockGeneratorImpl}
11-
import io.iohk.ethereum.consensus.ethash.validators.{EthashValidators, StdEthashValidators}
11+
import io.iohk.ethereum.consensus.ethash.validators.EthashValidators
1212
import io.iohk.ethereum.consensus.validators.Validators
1313
import io.iohk.ethereum.domain.BlockchainImpl
1414
import io.iohk.ethereum.ledger.BlockPreparator
@@ -157,7 +157,7 @@ object EthashConsensus {
157157
config: FullConsensusConfig[EthashConfig]
158158
): EthashConsensus = {
159159

160-
val validators = StdEthashValidators(blockchainConfig)
160+
val validators = EthashValidators(blockchainConfig)
161161

162162
val blockPreparator = new BlockPreparator(
163163
vm = vm,

src/main/scala/io/iohk/ethereum/consensus/ethash/blocks/EthashBlockGenerator.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import java.util.function.UnaryOperator
55
import akka.util.ByteString
66
import io.iohk.ethereum.consensus.ConsensusConfig
77
import io.iohk.ethereum.consensus.blocks._
8+
import io.iohk.ethereum.consensus.ethash.difficulty.EthashDifficultyCalculator
89
import io.iohk.ethereum.consensus.ethash.validators.EthashValidators
910
import io.iohk.ethereum.crypto.kec256
1011
import io.iohk.ethereum.domain._
@@ -38,10 +39,7 @@ class EthashBlockGeneratorImpl(
3839
blockTimestampProvider
3940
) with EthashBlockGenerator {
4041

41-
protected val difficulty = new DifficultyCalculator(blockchainConfig)
42-
43-
protected def calculateDifficulty(blockNumber: BigInt, parent: Block, blockTimestamp: Long): BigInt =
44-
difficulty.calculateDifficulty(blockNumber, blockTimestamp, parent.header)
42+
protected val difficulty = new EthashDifficultyCalculator(blockchainConfig)
4543

4644
protected def newBlockBody(transactions: Seq[SignedTransaction], x: Ommers): BlockBody =
4745
BlockBody(transactions, x)

src/main/scala/io/iohk/ethereum/domain/DifficultyCalculator.scala renamed to src/main/scala/io/iohk/ethereum/consensus/ethash/difficulty/EthashDifficultyCalculator.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
package io.iohk.ethereum.domain
1+
package io.iohk.ethereum.consensus.ethash.difficulty
22

3+
import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
4+
import io.iohk.ethereum.domain.BlockHeader
35
import io.iohk.ethereum.utils.BlockchainConfig
46

5-
class DifficultyCalculator(blockchainConfig: BlockchainConfig) {
7+
class EthashDifficultyCalculator(blockchainConfig: BlockchainConfig) extends DifficultyCalculator {
68
val DifficultyBoundDivision: Int = 2048
79
val FrontierTimestampDiffLimit: Int = -99
810
val ExpDifficultyPeriod: Int = 100000
911
val MinimumDifficulty: BigInt = 131072
1012

1113
def calculateDifficulty(blockNumber: BigInt, blockTimestamp: Long, parentHeader: BlockHeader): BigInt = {
12-
import blockchainConfig.{homesteadBlockNumber, difficultyBombPauseBlockNumber, difficultyBombContinueBlockNumber}
14+
import blockchainConfig.{difficultyBombContinueBlockNumber, difficultyBombPauseBlockNumber, homesteadBlockNumber}
1315

1416
val x: BigInt = parentHeader.difficulty / DifficultyBoundDivision
1517
val c: BigInt =

src/main/scala/io/iohk/ethereum/consensus/ethash/validators/EthashBlockHeaderValidator.scala

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,28 @@
11
package io.iohk.ethereum.consensus.ethash
22
package validators
33

4+
import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
5+
import io.iohk.ethereum.consensus.ethash.difficulty.EthashDifficultyCalculator
46
import io.iohk.ethereum.consensus.validators.BlockHeaderError.HeaderPoWError
5-
import io.iohk.ethereum.consensus.validators.std.StdBlockHeaderValidator
6-
import io.iohk.ethereum.consensus.validators.std.StdBlockHeaderValidator.PowCacheData
7-
import io.iohk.ethereum.consensus.validators.{BlockHeaderError, BlockHeaderValid}
7+
import io.iohk.ethereum.consensus.validators.{BlockHeaderError, BlockHeaderValid, BlockHeaderValidatorSkeleton}
88
import io.iohk.ethereum.crypto
99
import io.iohk.ethereum.domain.BlockHeader
1010
import io.iohk.ethereum.utils.BlockchainConfig
1111

1212
/**
1313
* A block header validator for Ethash.
1414
*/
15-
class EthashBlockHeaderValidator(blockchainConfig: BlockchainConfig) extends StdBlockHeaderValidator(blockchainConfig) {
15+
class EthashBlockHeaderValidator(blockchainConfig: BlockchainConfig) extends BlockHeaderValidatorSkeleton(blockchainConfig) {
1616
import EthashBlockHeaderValidator._
1717

18-
/** This method allows validate a BlockHeader (stated on
19-
* section 4.4.4 of http://paper.gavwood.com/).
20-
*
21-
* @param blockHeader BlockHeader to validate.
22-
* @param parentHeader BlockHeader of the parent of the block to validate.
23-
*/
24-
override def validate(blockHeader: BlockHeader, parentHeader: BlockHeader): Either[BlockHeaderError, BlockHeaderValid] = {
25-
for {
26-
_ super.validate(blockHeader, parentHeader)
27-
_ validatePoW(blockHeader)
28-
} yield BlockHeaderValid
29-
}
18+
// NOTE the below comment is from before PoW decoupling
19+
// we need concurrent map since validators can be used from multiple places
20+
protected val powCaches: java.util.concurrent.ConcurrentMap[Long, PowCacheData] = new java.util.concurrent.ConcurrentHashMap[Long, PowCacheData]()
21+
22+
protected def difficulty: DifficultyCalculator = new EthashDifficultyCalculator(blockchainConfig)
23+
24+
def validateEvenMore(blockHeader: BlockHeader, parentHeader: BlockHeader): Either[BlockHeaderError, BlockHeaderValid] =
25+
validatePoW(blockHeader)
3026

3127
/**
3228
* Validates [[io.iohk.ethereum.domain.BlockHeader.nonce]] and [[io.iohk.ethereum.domain.BlockHeader.mixHash]] are correct
@@ -72,6 +68,8 @@ class EthashBlockHeaderValidator(blockchainConfig: BlockchainConfig) extends Std
7268
object EthashBlockHeaderValidator {
7369
final val MaxPowCaches: Int = 2 // maximum number of epochs for which PoW cache is stored in memory
7470

71+
class PowCacheData(val cache: Array[Int], val dagSize: Long)
72+
7573
// NOTE The below is from before PoW decoupling.
7674
// FIXME [EC-331]: this is used to speed up ETS Blockchain tests. All blocks in those tests have low numbers (1, 2, 3 ...)
7775
// so keeping the cache for epoch 0 avoids recalculating it for each individual test. The difference in test runtime

src/main/scala/io/iohk/ethereum/consensus/ethash/validators/EthashValidators.scala

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ package ethash.validators
33

44
import akka.util.ByteString
55
import io.iohk.ethereum.consensus.validators.Validators
6-
import io.iohk.ethereum.consensus.validators.std.StdValidators
6+
import io.iohk.ethereum.consensus.validators.std.{StdBlockValidator, StdSignedTransactionValidator, StdValidators}
77
import io.iohk.ethereum.domain.{Block, Receipt}
88
import io.iohk.ethereum.ledger.BlockExecutionError.ValidationBeforeExecError
99
import io.iohk.ethereum.ledger.{BlockExecutionError, BlockExecutionSuccess}
10+
import io.iohk.ethereum.utils.BlockchainConfig
1011

1112
trait EthashValidators extends Validators {
1213
def ommersValidator: OmmersValidator
@@ -43,6 +44,17 @@ trait EthashValidators extends Validators {
4344
}
4445

4546
object EthashValidators {
47+
def apply(blockchainConfig: BlockchainConfig): EthashValidators = {
48+
val blockHeaderValidator = new EthashBlockHeaderValidator(blockchainConfig)
49+
50+
new StdEthashValidators(
51+
StdBlockValidator,
52+
blockHeaderValidator,
53+
new StdSignedTransactionValidator(blockchainConfig),
54+
new StdOmmersValidator(blockchainConfig, blockHeaderValidator)
55+
)
56+
}
57+
4658
def validateBlockBeforeExecution(
4759
self: EthashValidators,
4860
block: Block,
Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,15 @@
11
package io.iohk.ethereum.consensus.ethash.validators
22

3-
import io.iohk.ethereum.consensus.validators.std.{StdBlockValidator, StdSignedTransactionValidator}
43
import io.iohk.ethereum.consensus.validators.{BlockValidator, SignedTransactionValidator}
5-
import io.iohk.ethereum.utils.BlockchainConfig
64

7-
class StdEthashValidators(
5+
/**
6+
* Implements validators that adhere to the PoW-specific
7+
* [[io.iohk.ethereum.consensus.ethash.validators.EthashValidators EthashValidators]]
8+
* interface.
9+
*/
10+
final class StdEthashValidators private[validators](
811
val blockValidator: BlockValidator,
912
val blockHeaderValidator: EthashBlockHeaderValidator,
1013
val signedTransactionValidator: SignedTransactionValidator,
1114
val ommersValidator: OmmersValidator
1215
) extends EthashValidators
13-
14-
object StdEthashValidators {
15-
def apply(blockchainConfig: BlockchainConfig): StdEthashValidators = {
16-
val blockHeaderValidator = new EthashBlockHeaderValidator(blockchainConfig)
17-
18-
new StdEthashValidators(
19-
StdBlockValidator,
20-
blockHeaderValidator,
21-
new StdSignedTransactionValidator(blockchainConfig),
22-
new StdOmmersValidator(blockchainConfig, blockHeaderValidator)
23-
)
24-
}
25-
}

src/main/scala/io/iohk/ethereum/consensus/validators/BlockHeaderValidator.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ trait BlockHeaderValidator {
1313
): Either[BlockHeaderError, BlockHeaderValid]
1414
}
1515

16+
object BlockHeaderValidator {
17+
val MaxExtraDataSize: Int = 32
18+
val GasLimitBoundDivisor: Int = 1024
19+
val MinGasLimit: BigInt = 5000 //Although the paper states this value is 125000, on the different clients 5000 is used
20+
val MaxGasLimit: Long = Long.MaxValue // max gasLimit is equal 2^63-1 according to EIP106
21+
}
22+
1623
sealed trait BlockHeaderError
1724

1825
object BlockHeaderError {

0 commit comments

Comments
 (0)