Skip to content

Commit 618ec39

Browse files
pslaskikapke
authored andcommitted
etcm-193 added possibility to configure target PoW time (#773)
1 parent 852c3f9 commit 618ec39

17 files changed

+93
-28
lines changed

src/ets/scala/io/iohk/ethereum/ets/blockchain/EthashTestBlockHeaderValidator.scala

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package io.iohk.ethereum.ets.blockchain
22

33
import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
4-
import io.iohk.ethereum.consensus.ethash.difficulty.EthashDifficultyCalculator
54
import io.iohk.ethereum.consensus.ethash.validators.EthashBlockHeaderValidator
65
import io.iohk.ethereum.consensus.validators.{ BlockHeaderError, BlockHeaderValid, BlockHeaderValidatorSkeleton }
76
import io.iohk.ethereum.domain.BlockHeader
@@ -14,7 +13,7 @@ class EthashTestBlockHeaderValidator(blockchainConfig: BlockchainConfig) extends
1413
// we need concurrent map since validators can be used from multiple places
1514
protected val powCaches: java.util.concurrent.ConcurrentMap[Long, PowCacheData] = new java.util.concurrent.ConcurrentHashMap[Long, PowCacheData]()
1615

17-
protected def difficulty: DifficultyCalculator = new EthashDifficultyCalculator(blockchainConfig)
16+
protected def difficulty: DifficultyCalculator = DifficultyCalculator(blockchainConfig)
1817

1918
def validateEvenMore(blockHeader: BlockHeader, parentHeader: BlockHeader): Either[BlockHeaderError, BlockHeaderValid] =
2019
Right(BlockHeaderValid)

src/main/resources/chains/etc-chain.conf

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
# 1 - mainnet, 3 - ropsten, 7 - mordor
44
network-id = 1
55

6+
# Possibility to set Proof of Work target time for testing purposes.
7+
# null means that the standard difficulty calculation rules are used
8+
pow-target-time = null
9+
610
# Frontier block number
711
frontier-block-number = "0"
812

src/main/resources/chains/eth-chain.conf

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
# 1 - mainnet, 3 - ropsten, 7 - mordor
44
network-id = 1
55

6+
# Possibility to set Proof of Work target time for testing purposes.
7+
# null means that the standard difficulty calculation rules are used
8+
pow-target-time = null
9+
610
# Frontier block number
711
frontier-block-number = "0"
812

src/main/resources/chains/mordor-chain.conf

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
# 1 - mainnet, 3 - ropsten, 7 - mordor
44
network-id = 7
55

6+
# Possibility to set Proof of Work target time for testing purposes.
7+
# null means that the standard difficulty calculation rules are used
8+
pow-target-time = null
9+
610
# Frontier block number
711
frontier-block-number = "0"
812

src/main/resources/chains/ropsten-chain.conf

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
# 1 - mainnet, 3 - ropsten, 7 - mordor
44
network-id = 3
55

6+
# Possibility to set Proof of Work target time for testing purposes.
7+
# null means that the standard difficulty calculation rules are used
8+
pow-target-time = null
9+
610
# Frontier block number
711
frontier-block-number = "0"
812

src/main/resources/chains/test-chain.conf

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
# 1 - mainnet, 7 - mordor
44
network-id = 1
55

6+
# Possibility to set Proof of Work target time for testing purposes.
7+
# null means that the standard difficulty calculation rules are used
8+
pow-target-time = null
9+
610
# Frontier block number
711
frontier-block-number = "0"
812

src/main/resources/chains/testnet-internal-chain.conf

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
# 1 - mainnet, 3 - ropsten, 7 - mordor
44
network-id = 42
55

6+
# Possibility to set Proof of Work target time for testing purposes.
7+
# null means that the standard difficulty calculation rules are used
8+
pow-target-time = null
9+
610
# Frontier block number
711
frontier-block-number = "0"
812

src/main/scala/io/iohk/ethereum/consensus/difficulty/ConstantDifficulty.scala

-7
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
11
package io.iohk.ethereum.consensus.difficulty
22

3+
import io.iohk.ethereum.consensus.ethash.difficulty.{TargetTimeDifficultyCalculator, EthashDifficultyCalculator}
34
import io.iohk.ethereum.domain.BlockHeader
5+
import io.iohk.ethereum.utils.BlockchainConfig
46

57
trait DifficultyCalculator {
68
def calculateDifficulty(blockNumber: BigInt, blockTimestamp: Long, parent: BlockHeader): BigInt
79
}
10+
11+
object DifficultyCalculator {
12+
def apply(blockchainConfig: BlockchainConfig): DifficultyCalculator = {
13+
blockchainConfig.powTargetTime match {
14+
case Some(targetTime) => new TargetTimeDifficultyCalculator(targetTime)
15+
case None => new EthashDifficultyCalculator(blockchainConfig)
16+
}
17+
}
18+
19+
val DifficultyBoundDivision: Int = 2048
20+
val FrontierTimestampDiffLimit: Int = -99
21+
val MinimumDifficulty: BigInt = 131072
22+
}

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

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ package io.iohk.ethereum
22
package consensus
33
package ethash
44

5+
import java.util.concurrent.atomic.AtomicReference
6+
57
import akka.actor.ActorRef
68
import akka.util.Timeout
79
import io.iohk.ethereum.consensus.Protocol.{Ethash, MockedPow}
810
import io.iohk.ethereum.consensus.blocks.TestBlockGenerator
11+
import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
912
import io.iohk.ethereum.consensus.ethash.MinerResponses.MinerNotExist
1013
import io.iohk.ethereum.consensus.ethash.blocks.{EthashBlockGenerator, EthashBlockGeneratorImpl}
1114
import io.iohk.ethereum.consensus.ethash.validators.ValidatorsExecutor
@@ -15,9 +18,6 @@ import io.iohk.ethereum.ledger.BlockPreparator
1518
import io.iohk.ethereum.ledger.Ledger.VMImpl
1619
import io.iohk.ethereum.nodebuilder.Node
1720
import io.iohk.ethereum.utils.{BlockchainConfig, Logger}
18-
import java.util.concurrent.atomic.AtomicReference
19-
20-
import io.iohk.ethereum.consensus.ethash.difficulty.EthashDifficultyCalculator
2121

2222
import scala.concurrent.Future
2323
import scala.concurrent.duration._
@@ -32,7 +32,7 @@ class EthashConsensus private (
3232
val config: FullConsensusConfig[EthashConfig],
3333
val validators: ValidatorsExecutor,
3434
val blockGenerator: EthashBlockGenerator,
35-
val difficultyCalculator: EthashDifficultyCalculator
35+
val difficultyCalculator: DifficultyCalculator
3636
) extends TestConsensus
3737
with Logger {
3838

@@ -178,7 +178,7 @@ object EthashConsensus {
178178
validators: ValidatorsExecutor
179179
): EthashConsensus = {
180180

181-
val difficultyCalculator = new EthashDifficultyCalculator(blockchainConfig)
181+
val difficultyCalculator = DifficultyCalculator(blockchainConfig)
182182

183183
val blockPreparator = new BlockPreparator(
184184
vm = vm,

src/main/scala/io/iohk/ethereum/consensus/ethash/difficulty/EthashDifficultyCalculator.scala

+4-6
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@ import io.iohk.ethereum.utils.BlockchainConfig
66

77
class EthashDifficultyCalculator(blockchainConfig: BlockchainConfig) extends DifficultyCalculator {
88
import blockchainConfig._
9+
import DifficultyCalculator._
910

10-
val DifficultyBoundDivision: Int = 2048
11-
val FrontierTimestampDiffLimit: Int = -99
12-
val ExpDifficultyPeriod: Int = 100000
13-
val MinimumDifficulty: BigInt = 131072
14-
val ByzantiumRelaxDifficulty: BigInt = 3000000
15-
val ConstantinopleRelaxDifficulty: BigInt = 5000000
11+
private val ExpDifficultyPeriod: Int = 100000
12+
private val ByzantiumRelaxDifficulty: BigInt = 3000000
13+
private val ConstantinopleRelaxDifficulty: BigInt = 5000000
1614

1715
def calculateDifficulty(blockNumber: BigInt, blockTimestamp: Long, parentHeader: BlockHeader): BigInt = {
1816
lazy val timestampDiff = blockTimestamp - parentHeader.unixTimestamp
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.iohk.ethereum.consensus.ethash.difficulty
2+
3+
import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
4+
import io.iohk.ethereum.domain.BlockHeader
5+
6+
class TargetTimeDifficultyCalculator(powTargetTime: Long) extends DifficultyCalculator {
7+
8+
import DifficultyCalculator._
9+
10+
/**
11+
* The lowerBoundExpectedRatio (l for abbreviation below) divides the timestamp diff into ranges:
12+
* [0, l) => c = 1, difficulty increases
13+
* [l, 2*l) => c = 0. difficulty stays the same
14+
* ...
15+
* [l*i, l*(i+1) ) => c = 1-i, difficulty decreases
16+
*
17+
* example:
18+
* powTargetTime := 45 seconds
19+
* l := 30 seconds
20+
* [0, 0.5 min) => difficulty increases
21+
* [0.5 min, 1 min) => difficulty stays the same (the average should be powTargetTime)
22+
* [1 min, +infinity) => difficulty decreases
23+
*/
24+
private val lowerBoundExpectedRatio: Long = (powTargetTime / 1.5).toLong
25+
26+
def calculateDifficulty(blockNumber: BigInt, blockTimestamp: Long, parentHeader: BlockHeader): BigInt = {
27+
val timestampDiff = blockTimestamp - parentHeader.unixTimestamp
28+
29+
val x: BigInt = parentHeader.difficulty / DifficultyBoundDivision
30+
val c: BigInt = math.max(1 - (timestampDiff / lowerBoundExpectedRatio), FrontierTimestampDiffLimit)
31+
32+
MinimumDifficulty.max(parentHeader.difficulty + x * c)
33+
}
34+
}

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package validators
33

44
import akka.util.ByteString
55
import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
6-
import io.iohk.ethereum.consensus.ethash.difficulty.EthashDifficultyCalculator
76
import io.iohk.ethereum.consensus.validators.BlockHeaderError.HeaderPoWError
87
import io.iohk.ethereum.consensus.validators.{BlockHeaderError, BlockHeaderValid, BlockHeaderValidatorSkeleton}
98
import io.iohk.ethereum.crypto
@@ -22,7 +21,7 @@ class EthashBlockHeaderValidator(blockchainConfig: BlockchainConfig)
2221
// we need atomic since validators can be used from multiple places
2322
protected val powCaches: AtomicAny[List[PowCacheData]] = Atomic(List.empty[PowCacheData])
2423

25-
protected def difficulty: DifficultyCalculator = new EthashDifficultyCalculator(blockchainConfig)
24+
protected def difficulty: DifficultyCalculator = DifficultyCalculator(blockchainConfig)
2625

2726
def validateEvenMore(
2827
blockHeader: BlockHeader,

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ package io.iohk.ethereum.consensus.ethash
22
package validators
33

44
import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
5-
import io.iohk.ethereum.consensus.ethash.difficulty.EthashDifficultyCalculator
65
import io.iohk.ethereum.consensus.validators.{BlockHeaderError, BlockHeaderValid, BlockHeaderValidatorSkeleton}
76
import io.iohk.ethereum.domain.BlockHeader
87
import io.iohk.ethereum.utils.BlockchainConfig
98

109
class MockedPowBlockHeaderValidator(blockchainConfig: BlockchainConfig)
1110
extends BlockHeaderValidatorSkeleton(blockchainConfig) {
1211

13-
protected def difficulty: DifficultyCalculator = new EthashDifficultyCalculator(blockchainConfig)
12+
protected def difficulty: DifficultyCalculator = DifficultyCalculator(blockchainConfig)
1413

1514
def validateEvenMore(
1615
blockHeader: BlockHeader,

src/main/scala/io/iohk/ethereum/testmode/TestmodeConsensus.scala

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import io.iohk.ethereum.consensus._
55
import io.iohk.ethereum.consensus.blocks.{BlockTimestampProvider, NoOmmersBlockGenerator, TestBlockGenerator}
66
import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
77
import io.iohk.ethereum.consensus.ethash.MinerResponses.MinerNotExist
8-
import io.iohk.ethereum.consensus.ethash.difficulty.EthashDifficultyCalculator
98
import io.iohk.ethereum.consensus.ethash.{MinerProtocol, MinerResponse}
109
import io.iohk.ethereum.consensus.validators._
1110
import io.iohk.ethereum.consensus.validators.std.{StdBlockValidator, StdSignedTransactionValidator}
@@ -99,6 +98,6 @@ trait TestmodeConsensusBuilder extends ConsensusBuilder {
9998
blockchain,
10099
blockchainConfig,
101100
consensusConfig,
102-
new EthashDifficultyCalculator(blockchainConfig)
101+
DifficultyCalculator(blockchainConfig)
103102
)
104103
}

src/main/scala/io/iohk/ethereum/utils/BlockchainConfig.scala

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package io.iohk.ethereum.utils
22

33
import akka.util.ByteString
4+
import com.typesafe.config.{Config => TypesafeConfig}
45
import io.iohk.ethereum.domain.{Address, UInt256}
56
import io.iohk.ethereum.utils.NumericUtils._
67

78
import scala.collection.JavaConverters._
8-
import com.typesafe.config.{Config => TypesafeConfig}
9-
109
import scala.util.Try
1110

1211
case class BlockchainConfig(
12+
powTargetTime: Option[Long] = None,
1313
frontierBlockNumber: BigInt,
1414
homesteadBlockNumber: BigInt,
1515
eip106BlockNumber: BigInt,
@@ -50,6 +50,9 @@ object BlockchainConfig {
5050

5151
// scalastyle:off method.length
5252
def fromRawConfig(blockchainConfig: TypesafeConfig): BlockchainConfig = {
53+
val powTargetTime: Option[Long] =
54+
ConfigUtils
55+
.getOptionalValue(blockchainConfig, "pow-target-time", _.getDuration("pow-target-time").getSeconds)
5356
val frontierBlockNumber: BigInt = BigInt(blockchainConfig.getString("frontier-block-number"))
5457
val homesteadBlockNumber: BigInt = BigInt(blockchainConfig.getString("homestead-block-number"))
5558
val eip106BlockNumber: BigInt = BigInt(blockchainConfig.getString("eip106-block-number"))
@@ -105,6 +108,7 @@ object BlockchainConfig {
105108
val ecip1099BlockNumber: BigInt = BigInt(blockchainConfig.getString("ecip1099-block-number"))
106109

107110
BlockchainConfig(
111+
powTargetTime = powTargetTime,
108112
frontierBlockNumber = frontierBlockNumber,
109113
homesteadBlockNumber = homesteadBlockNumber,
110114
eip106BlockNumber = eip106BlockNumber,

src/test/resources/application.conf

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ mantis {
2222
network = "test"
2323

2424
test {
25+
pow-target-time = null
2526
frontier-block-number = "0"
2627
eip106-block-number = "1000000000000000000"
2728
eip150-block-number = "2463000"

0 commit comments

Comments
 (0)