Skip to content

Commit

Permalink
etcm-193 added possibility to configure target PoW time
Browse files Browse the repository at this point in the history
  • Loading branch information
pslaski committed Nov 6, 2020
1 parent d6a38d6 commit b20ae80
Show file tree
Hide file tree
Showing 17 changed files with 93 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.iohk.ethereum.ets.blockchain

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

protected def difficulty: DifficultyCalculator = new EthashDifficultyCalculator(blockchainConfig)
protected def difficulty: DifficultyCalculator = DifficultyCalculator(blockchainConfig)

def validateEvenMore(blockHeader: BlockHeader, parentHeader: BlockHeader): Either[BlockHeaderError, BlockHeaderValid] =
Right(BlockHeaderValid)
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/chains/etc-chain.conf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
# 1 - mainnet, 3 - ropsten, 7 - mordor
network-id = 1

# Possibility to set Proof of Work target time for testing purposes.
# null means that the standard difficulty calculation rules are used
pow-target-time = null

# Frontier block number
frontier-block-number = "0"

Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/chains/eth-chain.conf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
# 1 - mainnet, 3 - ropsten, 7 - mordor
network-id = 1

# Possibility to set Proof of Work target time for testing purposes.
# null means that the standard difficulty calculation rules are used
pow-target-time = null

# Frontier block number
frontier-block-number = "0"

Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/chains/mordor-chain.conf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
# 1 - mainnet, 3 - ropsten, 7 - mordor
network-id = 7

# Possibility to set Proof of Work target time for testing purposes.
# null means that the standard difficulty calculation rules are used
pow-target-time = null

# Frontier block number
frontier-block-number = "0"

Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/chains/ropsten-chain.conf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
# 1 - mainnet, 3 - ropsten, 7 - mordor
network-id = 3

# Possibility to set Proof of Work target time for testing purposes.
# null means that the standard difficulty calculation rules are used
pow-target-time = null

# Frontier block number
frontier-block-number = "0"

Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/chains/test-chain.conf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
# 1 - mainnet, 7 - mordor
network-id = 1

# Possibility to set Proof of Work target time for testing purposes.
# null means that the standard difficulty calculation rules are used
pow-target-time = null

# Frontier block number
frontier-block-number = "0"

Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/chains/testnet-internal-chain.conf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
# 1 - mainnet, 3 - ropsten, 7 - mordor
network-id = 42

# Possibility to set Proof of Work target time for testing purposes.
# null means that the standard difficulty calculation rules are used
pow-target-time = null

# Frontier block number
frontier-block-number = "0"

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
package io.iohk.ethereum.consensus.difficulty

import io.iohk.ethereum.consensus.ethash.difficulty.{TargetTimeDifficultyCalculator, EthashDifficultyCalculator}
import io.iohk.ethereum.domain.BlockHeader
import io.iohk.ethereum.utils.BlockchainConfig

trait DifficultyCalculator {
def calculateDifficulty(blockNumber: BigInt, blockTimestamp: Long, parent: BlockHeader): BigInt
}

object DifficultyCalculator {
def apply(blockchainConfig: BlockchainConfig): DifficultyCalculator = {
blockchainConfig.powTargetTime match {
case Some(targetTime) => new TargetTimeDifficultyCalculator(targetTime)
case None => new EthashDifficultyCalculator(blockchainConfig)
}
}

val DifficultyBoundDivision: Int = 2048
val FrontierTimestampDiffLimit: Int = -99
val MinimumDifficulty: BigInt = 131072
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ package io.iohk.ethereum
package consensus
package ethash

import java.util.concurrent.atomic.AtomicReference

import akka.actor.ActorRef
import akka.util.Timeout
import io.iohk.ethereum.consensus.Protocol.{Ethash, MockedPow}
import io.iohk.ethereum.consensus.blocks.TestBlockGenerator
import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
import io.iohk.ethereum.consensus.ethash.MinerResponses.MinerNotExist
import io.iohk.ethereum.consensus.ethash.blocks.{EthashBlockGenerator, EthashBlockGeneratorImpl}
import io.iohk.ethereum.consensus.ethash.validators.ValidatorsExecutor
Expand All @@ -15,9 +18,6 @@ import io.iohk.ethereum.ledger.BlockPreparator
import io.iohk.ethereum.ledger.Ledger.VMImpl
import io.iohk.ethereum.nodebuilder.Node
import io.iohk.ethereum.utils.{BlockchainConfig, Logger}
import java.util.concurrent.atomic.AtomicReference

import io.iohk.ethereum.consensus.ethash.difficulty.EthashDifficultyCalculator

import scala.concurrent.Future
import scala.concurrent.duration._
Expand All @@ -32,7 +32,7 @@ class EthashConsensus private (
val config: FullConsensusConfig[EthashConfig],
val validators: ValidatorsExecutor,
val blockGenerator: EthashBlockGenerator,
val difficultyCalculator: EthashDifficultyCalculator
val difficultyCalculator: DifficultyCalculator
) extends TestConsensus
with Logger {

Expand Down Expand Up @@ -178,7 +178,7 @@ object EthashConsensus {
validators: ValidatorsExecutor
): EthashConsensus = {

val difficultyCalculator = new EthashDifficultyCalculator(blockchainConfig)
val difficultyCalculator = DifficultyCalculator(blockchainConfig)

val blockPreparator = new BlockPreparator(
vm = vm,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ import io.iohk.ethereum.utils.BlockchainConfig

class EthashDifficultyCalculator(blockchainConfig: BlockchainConfig) extends DifficultyCalculator {
import blockchainConfig._
import DifficultyCalculator._

val DifficultyBoundDivision: Int = 2048
val FrontierTimestampDiffLimit: Int = -99
val ExpDifficultyPeriod: Int = 100000
val MinimumDifficulty: BigInt = 131072
val ByzantiumRelaxDifficulty: BigInt = 3000000
val ConstantinopleRelaxDifficulty: BigInt = 5000000
private val ExpDifficultyPeriod: Int = 100000
private val ByzantiumRelaxDifficulty: BigInt = 3000000
private val ConstantinopleRelaxDifficulty: BigInt = 5000000

def calculateDifficulty(blockNumber: BigInt, blockTimestamp: Long, parentHeader: BlockHeader): BigInt = {
lazy val timestampDiff = blockTimestamp - parentHeader.unixTimestamp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.iohk.ethereum.consensus.ethash.difficulty

import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
import io.iohk.ethereum.domain.BlockHeader

class TargetTimeDifficultyCalculator(powTargetTime: Long) extends DifficultyCalculator {

import DifficultyCalculator._

/**
* The lowerBoundExpectedRatio (l for abbreviation below) divides the timestamp diff into ranges:
* [0, l) => c = 1, difficulty increases
* [l, 2*l) => c = 0. difficulty stays the same
* ...
* [l*i, l*(i+1) ) => c = 1-i, difficulty decreases
*
* example:
* powTargetTime := 45 seconds
* l := 30 seconds
* [0, 0.5 min) => difficulty increases
* [0.5 min, 1 min) => difficulty stays the same (the average should be powTargetTime)
* [1 min, +infinity) => difficulty decreases
*/
private val lowerBoundExpectedRatio: Long = (powTargetTime / 1.5).toLong

def calculateDifficulty(blockNumber: BigInt, blockTimestamp: Long, parentHeader: BlockHeader): BigInt = {
val timestampDiff = blockTimestamp - parentHeader.unixTimestamp

val x: BigInt = parentHeader.difficulty / DifficultyBoundDivision
val c: BigInt = math.max(1 - (timestampDiff / lowerBoundExpectedRatio), FrontierTimestampDiffLimit)

MinimumDifficulty.max(parentHeader.difficulty + x * c)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package validators

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

protected def difficulty: DifficultyCalculator = new EthashDifficultyCalculator(blockchainConfig)
protected def difficulty: DifficultyCalculator = DifficultyCalculator(blockchainConfig)

def validateEvenMore(
blockHeader: BlockHeader,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ package io.iohk.ethereum.consensus.ethash
package validators

import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
import io.iohk.ethereum.consensus.ethash.difficulty.EthashDifficultyCalculator
import io.iohk.ethereum.consensus.validators.{BlockHeaderError, BlockHeaderValid, BlockHeaderValidatorSkeleton}
import io.iohk.ethereum.domain.BlockHeader
import io.iohk.ethereum.utils.BlockchainConfig

class MockedPowBlockHeaderValidator(blockchainConfig: BlockchainConfig)
extends BlockHeaderValidatorSkeleton(blockchainConfig) {

protected def difficulty: DifficultyCalculator = new EthashDifficultyCalculator(blockchainConfig)
protected def difficulty: DifficultyCalculator = DifficultyCalculator(blockchainConfig)

def validateEvenMore(
blockHeader: BlockHeader,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import io.iohk.ethereum.consensus._
import io.iohk.ethereum.consensus.blocks.{BlockTimestampProvider, NoOmmersBlockGenerator, TestBlockGenerator}
import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
import io.iohk.ethereum.consensus.ethash.MinerResponses.MinerNotExist
import io.iohk.ethereum.consensus.ethash.difficulty.EthashDifficultyCalculator
import io.iohk.ethereum.consensus.ethash.{MinerProtocol, MinerResponse}
import io.iohk.ethereum.consensus.validators._
import io.iohk.ethereum.consensus.validators.std.{StdBlockValidator, StdSignedTransactionValidator}
Expand Down Expand Up @@ -99,6 +98,6 @@ trait TestmodeConsensusBuilder extends ConsensusBuilder {
blockchain,
blockchainConfig,
consensusConfig,
new EthashDifficultyCalculator(blockchainConfig)
DifficultyCalculator(blockchainConfig)
)
}
8 changes: 6 additions & 2 deletions src/main/scala/io/iohk/ethereum/utils/BlockchainConfig.scala
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package io.iohk.ethereum.utils

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

import scala.collection.JavaConverters._
import com.typesafe.config.{Config => TypesafeConfig}

import scala.util.Try

case class BlockchainConfig(
powTargetTime: Option[Long] = None,
frontierBlockNumber: BigInt,
homesteadBlockNumber: BigInt,
eip106BlockNumber: BigInt,
Expand Down Expand Up @@ -50,6 +50,9 @@ object BlockchainConfig {

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

BlockchainConfig(
powTargetTime = powTargetTime,
frontierBlockNumber = frontierBlockNumber,
homesteadBlockNumber = homesteadBlockNumber,
eip106BlockNumber = eip106BlockNumber,
Expand Down
1 change: 1 addition & 0 deletions src/test/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ mantis {
network = "test"

test {
pow-target-time = null
frontier-block-number = "0"
eip106-block-number = "1000000000000000000"
eip150-block-number = "2463000"
Expand Down

0 comments on commit b20ae80

Please sign in to comment.