Skip to content

Commit 8ea4dae

Browse files
committed
Merge branch 'phase/etc_forks' into etcm-17-blake2-pre-compile
2 parents a64605f + a7d2b5c commit 8ea4dae

File tree

23 files changed

+118
-28
lines changed

23 files changed

+118
-28
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ trait BlockchainTestConfig extends BlockchainConfig {
3939
override val atlantisBlockNumber: BigInt = Long.MaxValue
4040
override val aghartaBlockNumber: BigInt = Long.MaxValue
4141
override val phoenixBlockNumber: BigInt = Long.MaxValue
42+
override val petersburgBlockNumber: BigInt = Long.MaxValue
4243
}
4344

4445
object FrontierConfig extends BlockchainTestConfig {

src/it/scala/io/iohk/ethereum/txExecTest/ECIP1017Test.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class ECIP1017Test extends FlatSpec with Matchers {
4545
override val atlantisBlockNumber: BigInt = Long.MaxValue
4646
override val aghartaBlockNumber: BigInt = Long.MaxValue
4747
override val phoenixBlockNumber: BigInt = Long.MaxValue
48+
override val petersburgBlockNumber: BigInt = Long.MaxValue
4849
}
4950
val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(4))
5051

src/it/scala/io/iohk/ethereum/txExecTest/ForksTest.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class ForksTest extends FlatSpec with Matchers {
4242
override val atlantisBlockNumber: BigInt = Long.MaxValue
4343
override val aghartaBlockNumber: BigInt = Long.MaxValue
4444
override val phoenixBlockNumber: BigInt = Long.MaxValue
45+
override val petersburgBlockNumber: BigInt = Long.MaxValue
4546
}
4647

4748
val noErrors = a[Right[_, Seq[Receipt]]]

src/main/resources/chains/base.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@
7070
# https://github.com/ethereum/pm/issues/53
7171
constantinople-block-number = "1000000000000000000"
7272

73+
# Petersburg fork block number (ETH only)
74+
# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1716.md
75+
petersburg-block-number = "1000000000000000000"
76+
7377
# DAO fork configuration (Ethereum HF/Classic split)
7478
# https://blog.ethereum.org/2016/07/20/hard-fork-completed/
7579
dao {

src/main/resources/chains/eth.conf

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
# Constantinople fork block number (ETH only)
1414
# https://github.com/ethereum/pm/issues/53
15-
constantinople-block-number = "7080000"
15+
constantinople-block-number = "7280000"
1616

1717
# EIP-170 max code size (Enabled from eip161-block-number)
1818
max-code-size = "24576"
@@ -37,6 +37,10 @@
3737
# https://ecips.ethereumclassic.org/ECIPs/ecip-1088
3838
phoenix-block-number = "1000000000000000000"
3939

40+
# Petersburg fork block number (ETH only)
41+
# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1716.md
42+
petersburg-block-number = "7280000"
43+
4044
monetary-policy {
4145

4246
# Setting era-duration for eth and ropsten chain to big number is necessery to ensure

src/main/scala/io/iohk/ethereum/extvm/VMServer.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ class VMServer(messageHandler: MessageHandler)
188188
accountStartNonce = conf.accountStartNonce,
189189
atlantisBlockNumber = BigInt(8772000), //TODO include atlantis block number in protobuf
190190
aghartaBlockNumber = BigInt(9573000), //TODO include agharta block number in protobuf
191+
petersburgBlockNumber = BigInt(10000000), //TODO include petersburg block number in protobuf
191192
phoenixBlockNumber = BigInt(10500839), //TODO include phoenix block number in protobuf
192193
chainId = 0x3d.toByte //TODO include chainId in protobuf
193194
)

src/main/scala/io/iohk/ethereum/jsonrpc/TestService.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class TestService(
6161

6262
private var etherbase: Address = consensusConfig.coinbase
6363

64+
// scalastyle:off method.length
6465
def setChainParams(request: SetChainParamsRequest): ServiceResponse[SetChainParamsResponse] = {
6566
val newBlockchainConfig = new BlockchainConfig {
6667
override val frontierBlockNumber: BigInt = testLedgerWrapper.blockchainConfig.frontierBlockNumber
@@ -88,7 +89,9 @@ class TestService(
8889
override val atlantisBlockNumber: BigInt = testLedgerWrapper.blockchainConfig.atlantisBlockNumber
8990
override val aghartaBlockNumber: BigInt = testLedgerWrapper.blockchainConfig.aghartaBlockNumber
9091
override val phoenixBlockNumber: BigInt = testLedgerWrapper.blockchainConfig.phoenixBlockNumber
92+
override val petersburgBlockNumber: BigInt = testLedgerWrapper.blockchainConfig.petersburgBlockNumber
9193
}
94+
// scalastyle:on method.length
9295

9396
val genesisData = GenesisData(
9497
nonce = ByteString(Hex.decode("00")),

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ trait BlockchainConfig {
373373
val atlantisBlockNumber: BigInt
374374
val aghartaBlockNumber: BigInt
375375
val phoenixBlockNumber: BigInt
376+
val petersburgBlockNumber: BigInt
376377
}
377378

378379
object BlockchainConfig {
@@ -419,6 +420,8 @@ object BlockchainConfig {
419420
override val aghartaBlockNumber: BigInt = BigInt(blockchainConfig.getString("agharta-block-number"))
420421

421422
override val phoenixBlockNumber: BigInt = BigInt(blockchainConfig.getString("phoenix-block-number"))
423+
424+
override val petersburgBlockNumber: BigInt = BigInt(blockchainConfig.getString("petersburg-block-number"))
422425
}
423426
}
424427
}

src/main/scala/io/iohk/ethereum/vm/BlockchainConfigForEvm.scala

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package io.iohk.ethereum.vm
22

33
import io.iohk.ethereum.domain.UInt256
44
import io.iohk.ethereum.utils.BlockchainConfig
5+
import io.iohk.ethereum.vm.BlockchainConfigForEvm.EtcForks.{Agharta, Atlantis, BeforeAtlantis, EtcFork, Phoenix}
6+
import io.iohk.ethereum.vm.BlockchainConfigForEvm.EthForks.{BeforeByzantium, Byzantium, Constantinople, Petersburg}
57

68
/**
79
* A subset of [[io.iohk.ethereum.utils.BlockchainConfig]] that is required for instantiating an [[EvmConfig]]
@@ -20,11 +22,39 @@ case class BlockchainConfigForEvm(
2022
accountStartNonce: UInt256,
2123
atlantisBlockNumber: BigInt,
2224
aghartaBlockNumber: BigInt,
25+
petersburgBlockNumber: BigInt,
2326
phoenixBlockNumber: BigInt,
2427
chainId: Byte
25-
)
28+
){
29+
def etcForkForBlockNumber(blockNumber: BigInt): EtcFork = blockNumber match {
30+
case _ if blockNumber < atlantisBlockNumber => BeforeAtlantis
31+
case _ if blockNumber < aghartaBlockNumber => Atlantis
32+
case _ if blockNumber < phoenixBlockNumber => Agharta
33+
case _ if blockNumber >= phoenixBlockNumber => Phoenix
34+
}
35+
36+
def ethForkForBlockNumber(blockNumber: BigInt): BlockchainConfigForEvm.EthForks.Value = blockNumber match {
37+
case _ if blockNumber < byzantiumBlockNumber => BeforeByzantium
38+
case _ if blockNumber < constantinopleBlockNumber => Byzantium
39+
case _ if blockNumber < petersburgBlockNumber => Constantinople
40+
case _ if blockNumber >= petersburgBlockNumber => Petersburg
41+
// TODO add Istanbul
42+
}
43+
}
2644

2745
object BlockchainConfigForEvm {
46+
47+
object EtcForks extends Enumeration {
48+
type EtcFork = Value
49+
val BeforeAtlantis, Atlantis, Agharta, Phoenix = Value
50+
}
51+
52+
object EthForks extends Enumeration {
53+
type EthFork = Value
54+
val BeforeByzantium, Byzantium, Constantinople, Petersburg, Istanbul = Value
55+
}
56+
57+
2858
def apply(blockchainConfig: BlockchainConfig): BlockchainConfigForEvm = {
2959
import blockchainConfig._
3060
BlockchainConfigForEvm(
@@ -39,6 +69,7 @@ object BlockchainConfigForEvm {
3969
accountStartNonce = accountStartNonce,
4070
atlantisBlockNumber = atlantisBlockNumber,
4171
aghartaBlockNumber = aghartaBlockNumber,
72+
petersburgBlockNumber = petersburgBlockNumber,
4273
phoenixBlockNumber = phoenixBlockNumber,
4374
chainId = chainId
4475
)

src/main/scala/io/iohk/ethereum/vm/EvmConfig.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ object EvmConfig {
3838
blockchainConfig.constantinopleBlockNumber -> ConstantinopleConfigBuilder,
3939
blockchainConfig.atlantisBlockNumber -> AtlantisConfigBuilder,
4040
blockchainConfig.aghartaBlockNumber -> AghartaConfigBuilder,
41+
blockchainConfig.petersburgBlockNumber -> PetersburgConfigBuilder,
4142
blockchainConfig.phoenixBlockNumber -> PhoenixConfigBuilder
4243
)
4344

@@ -96,6 +97,8 @@ object EvmConfig {
9697
opCodeList = ConstantinopleOpCodes
9798
)
9899

100+
val PetersburgConfigBuilder: EvmConfigBuilder = config => ConstantinopleConfigBuilder(config)
101+
99102
// Ethereum classic forks only
100103
val AtlantisConfigBuilder: EvmConfigBuilder = config => PostEIP160ConfigBuilder(config).copy(
101104
feeSchedule = new FeeSchedule.AtlantisFeeSchedule,

src/main/scala/io/iohk/ethereum/vm/OpCode.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import akka.util.ByteString
44
import io.iohk.ethereum.crypto.kec256
55
import io.iohk.ethereum.domain.{Account, Address, TxLogEntry, UInt256}
66
import io.iohk.ethereum.domain.UInt256._
7+
import io.iohk.ethereum.vm.BlockchainConfigForEvm.EthForks
78

89
// scalastyle:off magic.number
910
// scalastyle:off number.of.types
@@ -594,7 +595,7 @@ case object SSTORE extends OpCode(0x55, 2, 0, _.G_zero) {
594595
protected def exec[W <: WorldStateProxy[W, S], S <: Storage[S]](state: ProgramState[W, S]): ProgramState[W, S] = {
595596
val (Seq(offset, newValue), stack1) = state.stack.pop(2)
596597
val currentValue = state.storage.load(offset)
597-
val refund: BigInt = if (isAfterConstantinopleFork(state)) {
598+
val refund: BigInt = if (isEip1283Enabled(state)) {
598599
val originalValue = state.originalWorld.getStorage(state.ownAddress).load(offset)
599600
if (currentValue != newValue.toBigInt) {
600601
if (originalValue == currentValue) { // fresh slot
@@ -636,7 +637,7 @@ case object SSTORE extends OpCode(0x55, 2, 0, _.G_zero) {
636637
protected def varGas[W <: WorldStateProxy[W, S], S <: Storage[S]](state: ProgramState[W, S]): BigInt = {
637638
val (Seq(offset, newValue), _) = state.stack.pop(2)
638639
val currentValue = state.storage.load(offset)
639-
if (isAfterConstantinopleFork(state)) {
640+
if (isEip1283Enabled(state)) {
640641
// https://eips.ethereum.org/EIPS/eip-1283
641642
if (currentValue == newValue.toBigInt) { // no-op
642643
state.config.feeSchedule.G_sload
@@ -662,8 +663,10 @@ case object SSTORE extends OpCode(0x55, 2, 0, _.G_zero) {
662663

663664
override protected def availableInContext[W <: WorldStateProxy[W, S], S <: Storage[S]]: ProgramState[W, S] => Boolean = !_.staticCtx
664665

665-
private def isAfterConstantinopleFork[W <: WorldStateProxy[W, S], S <: Storage[S]](state: ProgramState[W, S]): Boolean =
666-
state.env.blockHeader.number >= state.config.blockchainConfig.constantinopleBlockNumber
666+
private def isEip1283Enabled[W <: WorldStateProxy[W, S], S <: Storage[S]](state: ProgramState[W, S]): Boolean = {
667+
val blockNumber = state.env.blockHeader.number
668+
state.config.blockchainConfig.ethForkForBlockNumber(blockNumber) == EthForks.Constantinople
669+
}
667670
}
668671

669672
case object JUMP extends OpCode(0x56, 1, 0, _.G_mid) with ConstGas {

src/main/scala/io/iohk/ethereum/vm/PrecompiledContracts.scala

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import io.iohk.ethereum.crypto.zksnark.{BN128Fp, PairingCheck}
77
import io.iohk.ethereum.crypto.zksnark.PairingCheck.G1G2Pair
88
import io.iohk.ethereum.domain.Address
99
import io.iohk.ethereum.utils.ByteUtils
10-
10+
import io.iohk.ethereum.vm.BlockchainConfigForEvm.EtcForks.EtcFork
11+
import io.iohk.ethereum.vm.BlockchainConfigForEvm.EthForks.EthFork
12+
import io.iohk.ethereum.vm.BlockchainConfigForEvm.{EtcForks, EthForks}
1113
import scala.util.Try
1214

1315
// scalastyle:off magic.number
@@ -29,7 +31,7 @@ object PrecompiledContracts {
2931
IdAddr -> Identity
3032
)
3133

32-
val byzantiumContracts = contracts ++ Map(
34+
val byzantiumAtlantisContracts = contracts ++ Map(
3335
ModExpAddr -> ModExp,
3436
Bn128AddAddr -> Bn128Add,
3537
Bn128MulAddr -> Bn128Mul,
@@ -51,21 +53,25 @@ object PrecompiledContracts {
5153

5254
private def getContract(context: ProgramContext[_, _]): Option[PrecompiledContract] = {
5355
context.recipientAddr.flatMap{ addr =>
54-
if (context.blockHeader.number >= context.evmConfig.blockchainConfig.byzantiumBlockNumber ||
55-
context.blockHeader.number >= context.evmConfig.blockchainConfig.atlantisBlockNumber) {
56+
if (context.evmConfig.blockchainConfig.ethForkForBlockNumber(context.blockHeader.number) >= EthForks.Byzantium ||
57+
context.evmConfig.blockchainConfig.etcForkForBlockNumber(context.blockHeader.number) >= EtcForks.Atlantis) {
5658
// byzantium and atlantis hard fork introduce the same set of precompiled contracts
57-
byzantiumContracts.get(addr)
59+
byzantiumAtlantisContracts.get(addr)
5860
} else
5961
contracts.get(addr)
6062
}
6163
}
6264

6365
sealed trait PrecompiledContract {
6466
protected def exec(inputData: ByteString): Option[ByteString]
65-
protected def gas(inputData: ByteString): BigInt
67+
protected def gas(inputData: ByteString, etcFork: EtcFork, ethFork: EthFork): BigInt
6668

6769
def run[W <: WorldStateProxy[W, S], S <: Storage[S]](context: ProgramContext[W, S]): ProgramResult[W, S] = {
68-
val g = gas(context.inputData)
70+
71+
val ethFork = context.evmConfig.blockchainConfig.ethForkForBlockNumber(context.blockHeader.number)
72+
val etcFork = context.evmConfig.blockchainConfig.etcForkForBlockNumber(context.blockHeader.number)
73+
74+
val g = gas(context.inputData, etcFork, ethFork)
6975

7076
val (result, error, gasRemaining): (ByteString, Option[ProgramError], BigInt) =
7177
if (g <= context.startGas)
@@ -108,8 +114,7 @@ object PrecompiledContracts {
108114

109115
}
110116

111-
def gas(inputData: ByteString): BigInt =
112-
3000
117+
def gas(inputData: ByteString, etcFork: EtcFork, ethFork: EthFork): BigInt = 3000
113118

114119
private def hasOnlyLastByteSet(v: ByteString): Boolean =
115120
v.dropWhile(_ == 0).size == 1
@@ -119,23 +124,23 @@ object PrecompiledContracts {
119124
def exec(inputData: ByteString): Option[ByteString] =
120125
Some(sha256(inputData))
121126

122-
def gas(inputData: ByteString): BigInt =
127+
def gas(inputData: ByteString, etcFork: EtcFork, ethFork: EthFork): BigInt =
123128
60 + 12 * wordsForBytes(inputData.size)
124129
}
125130

126131
object Ripemp160 extends PrecompiledContract {
127132
def exec(inputData: ByteString): Option[ByteString] =
128133
Some(ByteUtils.padLeft(ripemd160(inputData), 32))
129134

130-
def gas(inputData: ByteString): BigInt =
135+
def gas(inputData: ByteString, etcFork: EtcFork, ethFork: EthFork): BigInt =
131136
600 + 120 * wordsForBytes(inputData.size)
132137
}
133138

134139
object Identity extends PrecompiledContract {
135140
def exec(inputData: ByteString): Option[ByteString] =
136141
Some(inputData)
137142

138-
def gas(inputData: ByteString): BigInt =
143+
def gas(inputData: ByteString, etcFork: EtcFork, ethFork: EthFork): BigInt =
139144
15 + 3 * wordsForBytes(inputData.size)
140145
}
141146

@@ -168,7 +173,7 @@ object PrecompiledContracts {
168173
Some(ByteString(ByteUtils.bigIntegerToBytes(result.bigInteger, modLength)))
169174
}
170175

171-
def gas(inputData: ByteString): BigInt = {
176+
def gas(inputData: ByteString, etcFork: EtcFork, ethFork: EthFork): BigInt = {
172177
val baseLength = getLength(inputData, 0)
173178
val expLength = getLength(inputData, 1)
174179
val modLength = getLength(inputData, 2)
@@ -256,8 +261,11 @@ object PrecompiledContracts {
256261
}
257262

258263

259-
def gas(inputData: ByteString): BigInt =
260-
BigInt(500)
264+
def gas(inputData: ByteString, etcFork: EtcFork, ethFork: EthFork): BigInt =
265+
if(etcFork >= EtcForks.Phoenix || ethFork >= EthForks.Istanbul)
266+
BigInt(150) // https://eips.ethereum.org/EIPS/eip-1108
267+
else
268+
BigInt(500)
261269

262270

263271
private def getCurvePointsBytes(input: ByteString): (ByteString, ByteString, ByteString, ByteString) = {
@@ -293,8 +301,11 @@ object PrecompiledContracts {
293301
}
294302
}
295303

296-
def gas(inputData: ByteString): BigInt =
297-
40000
304+
def gas(inputData: ByteString, etcFork: EtcFork, ethFork: EthFork): BigInt =
305+
if(etcFork >= EtcForks.Phoenix || ethFork >= EthForks.Istanbul)
306+
6000 // https://eips.ethereum.org/EIPS/eip-1108
307+
else
308+
40000
298309

299310
private def getCurvePointsBytes(input: ByteString): (ByteString, ByteString, ByteString) = {
300311
(input.slice(0, 32),
@@ -325,8 +336,13 @@ object PrecompiledContracts {
325336
}
326337
}
327338

328-
def gas(inputData: ByteString): BigInt = {
329-
80000 * (inputData.length / inputLength) + 100000
339+
def gas(inputData: ByteString, etcFork: EtcFork, ethFork: EthFork): BigInt = {
340+
val k = inputData.length / inputLength
341+
if(etcFork >= EtcForks.Phoenix || ethFork >= EthForks.Istanbul){ // https://eips.ethereum.org/EIPS/eip-1108
342+
34000 * k + 45000
343+
} else {
344+
80000 * k + 100000
345+
}
330346
}
331347

332348
// Method which stops reading another points if one of earlier ones failed (had invalid coordinates, or was not on

src/test/scala/io/iohk/ethereum/consensus/BlockGeneratorSpec.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ class BlockGeneratorSpec extends FlatSpec with Matchers with PropertyChecks with
169169
override val atlantisBlockNumber: BigInt = Long.MaxValue
170170
override val aghartaBlockNumber: BigInt = Long.MaxValue
171171
override val phoenixBlockNumber: BigInt = Long.MaxValue
172+
override val petersburgBlockNumber: BigInt = Long.MaxValue
172173
}
173174

174175
override lazy val blockExecution = new BlockExecution(blockchain, blockchainConfig, consensus.blockPreparator, blockValidation)
@@ -339,6 +340,8 @@ class BlockGeneratorSpec extends FlatSpec with Matchers with PropertyChecks with
339340
override val atlantisBlockNumber: BigInt = Long.MaxValue
340341
override val aghartaBlockNumber: BigInt = Long.MaxValue
341342
override val phoenixBlockNumber: BigInt = Long.MaxValue
343+
override val petersburgBlockNumber: BigInt = Long.MaxValue
344+
342345
}
343346

344347
val genesisDataLoader = new GenesisDataLoader(blockchain, blockchainConfig)

src/test/scala/io/iohk/ethereum/consensus/validators/BlockHeaderValidatorSpec.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ class BlockHeaderValidatorSpec
387387
override val atlantisBlockNumber: BigInt = Long.MaxValue
388388
override val aghartaBlockNumber: BigInt = Long.MaxValue
389389
override val phoenixBlockNumber: BigInt = Long.MaxValue
390+
override val petersburgBlockNumber: BigInt = Long.MaxValue
390391
}
391392

392393
val ProDaoBlock1920008Header = BlockHeader(

src/test/scala/io/iohk/ethereum/extvm/VMClientSpec.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ class VMClientSpec extends FlatSpec with Matchers with MockFactory {
177177
accountStartNonce = 0,
178178
atlantisBlockNumber = 0,
179179
aghartaBlockNumber = 0,
180+
petersburgBlockNumber = 0,
180181
phoenixBlockNumber = 0,
181182
chainId = 0x3d.toByte
182183
)

src/test/scala/io/iohk/ethereum/jsonrpc/EthServiceSpec.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,7 @@ class EthServiceSpec extends FlatSpec with Matchers with ScalaFutures with MockF
896896
override val atlantisBlockNumber: BigInt = 0
897897
override val aghartaBlockNumber: BigInt = 0
898898
override val phoenixBlockNumber: BigInt = 0
899+
override val petersburgBlockNumber: BigInt = 0
899900
}
900901

901902
override lazy val consensus: TestConsensus = buildTestConsensus().withBlockGenerator(blockGenerator)

0 commit comments

Comments
 (0)