Skip to content

Commit cbc9336

Browse files
authored
eth_config impl (#3534)
* intial setup for eth_config * basic impl without system contracts * add forkid support * minute fixes * fix crash * shift to header * add debug points * more debug logs with fixes * fix crashes due to nil pointer * shift to JsonNumber * shift to timestamp * fix: system contracts forking * shift to numbers * fix forkId calculation * add tests * remove unwanted logscope * nim-web bump * bump nim-web4 to 81ee8ce479d86acb73be7c4f365328e238d9b4a3
1 parent 670e689 commit cbc9336

File tree

7 files changed

+178
-11
lines changed

7 files changed

+178
-11
lines changed

execution_chain/common/common.nim

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ func toHardFork*(
292292
toHardFork(com.forkTransitionTable, forkDeterminer)
293293

294294
func toHardFork*(com: CommonRef, timestamp: EthTime): HardFork =
295-
for fork in countdown(com.forkTransitionTable.timeThresholds.high, Shanghai):
295+
for fork in countdown(HardFork.high, Shanghai):
296296
if com.forkTransitionTable.timeThresholds[fork].isSome and timestamp >= com.forkTransitionTable.timeThresholds[fork].get:
297297
return fork
298298

@@ -306,6 +306,27 @@ func toEVMFork*(com: CommonRef, forkDeterminer: ForkDeterminationInfo): EVMFork
306306
let fork = com.toHardFork(forkDeterminer)
307307
ToEVMFork[fork]
308308

309+
func nextFork*(com: CommonRef, currentFork: HardFork): Opt[HardFork] =
310+
## Returns the next hard fork after the given one
311+
## The next fork can also be the last fork
312+
if currentFork < Shanghai:
313+
return Opt.none(HardFork)
314+
for fork in currentFork .. HardFork.high:
315+
if fork > currentFork and com.forkTransitionTable.timeThresholds[fork].isSome:
316+
return Opt.some(fork)
317+
return Opt.none(HardFork)
318+
319+
func lastFork*(com: CommonRef, currentFork: HardFork): Opt[HardFork] =
320+
## Returns the last hard fork before the given one
321+
for fork in countdown(HardFork.high, currentFork):
322+
if fork > currentFork and com.forkTransitionTable.timeThresholds[fork].isSome:
323+
return Opt.some(HardFork(fork))
324+
return Opt.none(HardFork)
325+
326+
func activationTime*(com: CommonRef, fork: HardFork): Opt[EthTime] =
327+
## Returns the activation time of the given hard fork
328+
com.forkTransitionTable.timeThresholds[fork]
329+
309330
func toEVMFork*(com: CommonRef, header: Header): EVMFork =
310331
com.toEVMFork(forkDeterminationInfo(header))
311332

@@ -323,6 +344,10 @@ func forkId*(com: CommonRef, head, time: uint64): ForkID {.gcsafe.} =
323344
## EIP 2364/2124
324345
com.forkIdCalculator.newID(head, time)
325346

347+
func forkId*(com: CommonRef, forkActivationTime: EthTime): ForkID {.gcsafe.} =
348+
# Only works for timestamp based forks
349+
com.forkIdCalculator.newID(0'u64, forkActivationTime.uint64)
350+
326351
func forkId*(com: CommonRef, head: BlockNumber, time: EthTime): ForkID {.gcsafe.} =
327352
## EIP 2364/2124
328353
com.forkIdCalculator.newID(head, time.uint64)

execution_chain/evm/precompiles.nim

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,19 +110,32 @@ const
110110
paP256VerifyAddress # paP256Verify
111111
]
112112

113+
precompileNames*: array[Precompiles, string] = [
114+
"ECREC",
115+
"SHA256",
116+
"RIPEMD160",
117+
"ID",
118+
"MODEXP",
119+
"BN254_ADD",
120+
"BN254_MUL",
121+
"BN254_PAIRING",
122+
"BLAKE2F",
123+
"KZG_POINT_EVALUATION",
124+
"BLS12_G1ADD",
125+
"BLS12_G1MSM",
126+
"BLS12_G2ADD",
127+
"BLS12_G2MSM",
128+
"BLS12_PAIRING_CHECK",
129+
"BLS12_MAP_FP_TO_G1",
130+
"BLS12_MAP_FP2_TO_G2",
131+
"P256_VERIFY"
132+
]
133+
113134

114135
# ------------------------------------------------------------------------------
115136
# Private functions
116137
# ------------------------------------------------------------------------------
117138

118-
func getMaxPrecompile(fork: EVMFork): Precompiles =
119-
if fork < FkByzantium: paIdentity
120-
elif fork < FkIstanbul: paPairing
121-
elif fork < FkCancun: paBlake2bf
122-
elif fork < FkPrague: paPointEvaluation
123-
elif fork < FkOsaka: paBlsMapG2
124-
else: Precompiles.high
125-
126139
func getSignature(c: Computation): EvmResult[SigRes] =
127140
# input is Hash, V, R, S
128141
template data: untyped = c.msg.data
@@ -796,6 +809,14 @@ proc p256verify(c: Computation): EvmResultVoid =
796809
# Public functions
797810
# ------------------------------------------------------------------------------
798811

812+
func getMaxPrecompile*(fork: EVMFork): Precompiles =
813+
if fork < FkByzantium: paIdentity
814+
elif fork < FkIstanbul: paPairing
815+
elif fork < FkCancun: paBlake2bf
816+
elif fork < FkPrague: paPointEvaluation
817+
elif fork < FkOsaka: paBlsMapG2
818+
else: Precompiles.high
819+
799820
iterator activePrecompiles*(fork: EVMFork): Address =
800821
let maxPrecompile = getMaxPrecompile(fork)
801822
for c in Precompiles.low..maxPrecompile:

execution_chain/rpc/rpc_utils.nim

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
{.push raises: [].}
1111

1212
import
13+
stew/endians2,
1314
std/[sequtils, algorithm],
1415
./rpc_types,
1516
./params,
@@ -308,3 +309,85 @@ proc createAccessList*(header: Header,
308309
)
309310

310311
prevTracer = tracer
312+
313+
proc populateConfigObject*(com: CommonRef, fork: HardFork): ConfigObject =
314+
let
315+
cancunSystemContracts: seq[SystemContractPair] = @[
316+
SystemContractPair(
317+
address: BEACON_ROOTS_ADDRESS,
318+
name: "BEACON_ROOTS_ADDRESS"
319+
)
320+
]
321+
pragueSystemContracts: seq[SystemContractPair] = @[
322+
SystemContractPair(
323+
address: SYSTEM_ADDRESS,
324+
name: "CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS"
325+
),
326+
SystemContractPair(
327+
address: com.depositContractAddress(),
328+
name: "DEPOSIT_CONTRACT_ADDRESS"
329+
),
330+
SystemContractPair(
331+
address: HISTORY_STORAGE_ADDRESS,
332+
name: "HISTORY_STORAGE_ADDRESS"
333+
),
334+
SystemContractPair(
335+
address: WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS,
336+
name: "WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS"
337+
)
338+
]
339+
340+
var configObject = ConfigObject()
341+
342+
configObject.activationTime = Number com.activationTime(fork).get(EthTime(0))
343+
configObject.chainId = com.chainId
344+
configObject.forkId = FixedBytes[4] com.forkId(
345+
com.activationTime(fork).get(EthTime(0))
346+
).crc.toBytesBE
347+
configObject.blobSchedule.max = Number com.maxBlobsPerBlock(fork)
348+
configObject.blobSchedule.target = Number com.targetBlobsPerBlock(fork)
349+
configObject.blobSchedule.baseFeeUpdateFraction = Number com.baseFeeUpdateFraction(fork)
350+
351+
# Precompiles
352+
let
353+
evmFork = ToEVMFork[fork]
354+
lastPrecompile = getMaxPrecompile(evmFork)
355+
356+
for i in Precompiles.low..lastPrecompile:
357+
configObject.precompiles.add PrecompilePair(
358+
address: precompileAddrs[i],
359+
name: precompileNames[i],
360+
)
361+
362+
# System Contracts
363+
if fork == Cancun:
364+
configObject.systemContracts = cancunSystemContracts
365+
elif fork >= Prague:
366+
configObject.systemContracts = cancunSystemContracts & pragueSystemContracts
367+
else:
368+
configObject.systemContracts = @[]
369+
370+
return configObject
371+
372+
proc getEthConfigObject*(com: CommonRef,
373+
chain: ForkedChainRef,
374+
fork: HardFork,
375+
nextFork: Opt[HardFork],
376+
lastFork: Opt[HardFork]): EthConfigObject =
377+
## Returns the EthConfigObject for the given chain.
378+
## This is used to return the `eth_config` object in the JSON-RPC API.
379+
var res = EthConfigObject()
380+
res.current = com.populateConfigObject(fork)
381+
382+
if nextFork.isSome:
383+
res.next = Opt.some(com.populateConfigObject(nextFork.get))
384+
else:
385+
res.next = Opt.none(ConfigObject)
386+
387+
if lastFork.isSome:
388+
res.last = Opt.some(com.populateConfigObject(lastFork.get))
389+
else:
390+
res.last = Opt.none(ConfigObject)
391+
392+
return res
393+

execution_chain/rpc/server_api.nim

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,3 +714,16 @@ proc setupServerAPI*(api: ServerAPIRef, server: RpcServer, ctx: EthContext) =
714714
return populateBlockObject(
715715
uncleHash, uncle, api.getTotalDifficulty(uncleHash), false, true
716716
)
717+
718+
server.rpc("eth_config") do() -> EthConfigObject:
719+
## Returns the current, next and last configuration
720+
let currentFork = api.com.toHardFork(api.chain.latestHeader.forkDeterminationInfo)
721+
722+
if currentFork < Shanghai:
723+
return nil
724+
725+
let
726+
nextFork = api.com.nextFork(currentFork)
727+
lastFork = api.com.lastFork(currentFork)
728+
729+
return api.com.getEthConfigObject(api.chain, currentFork, nextFork, lastFork)

tests/customgenesis/cancun123.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@
2727
"alloc": {
2828
"0x73cf19657412508833f618a15e8251306b3e6ee5": {
2929
"balance": "0x6d6172697573766477000000"
30+
},
31+
"0x00000961Ef480Eb55e80D19ad83579A64c007002": {
32+
"balance": "0",
33+
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460cb5760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101f457600182026001905f5b5f82111560685781019083028483029004916001019190604d565b909390049250505036603814608857366101f457346101f4575f5260205ff35b34106101f457600154600101600155600354806003026004013381556001015f35815560010160203590553360601b5f5260385f601437604c5fa0600101600355005b6003546002548082038060101160df575060105b5f5b8181146101835782810160030260040181604c02815460601b8152601401816001015481526020019060020154807fffffffffffffffffffffffffffffffff00000000000000000000000000000000168252906010019060401c908160381c81600701538160301c81600601538160281c81600501538160201c81600401538160181c81600301538160101c81600201538160081c81600101535360010160e1565b910180921461019557906002556101a0565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14156101cd57505f5b6001546002828201116101e25750505f6101e8565b01600290035b5f555f600155604c025ff35b5f5ffd"
34+
},
35+
"0x0000BBdDc7CE488642fb579F8B00f3a590007251": {
36+
"balance": "0",
37+
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460d35760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1461019a57600182026001905f5b5f82111560685781019083028483029004916001019190604d565b9093900492505050366060146088573661019a573461019a575f5260205ff35b341061019a57600154600101600155600354806004026004013381556001015f358155600101602035815560010160403590553360601b5f5260605f60143760745fa0600101600355005b6003546002548082038060021160e7575060025b5f5b8181146101295782810160040260040181607402815460601b815260140181600101548152602001816002015481526020019060030154905260010160e9565b910180921461013b5790600255610146565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff141561017357505f5b6001546001828201116101885750505f61018e565b01600190035b5f555f6001556074025ff35b5f5ffd"
3038
}
3139
},
3240
"number": "0x0",

tests/test_rpc.nim

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ proc makeBlobTx(env: var TestEnv, nonce: int): PooledTransaction =
184184
PooledTransaction(
185185
tx: tx,
186186
blobsBundle: BlobsBundle(
187+
wrapperVersion: WrapperVersionEIP4844,
187188
blobs: blobs,
188189
commitments: @[pooled_txs.KzgCommitment(commitment.bytes)],
189190
proofs: @[pooled_txs.KzgProof(proof.bytes)]))
@@ -221,6 +222,9 @@ proc setupEnv(envFork: HardFork = MergeFork): TestEnv =
221222

222223
if envFork >= Prague:
223224
conf.networkParams.config.pragueTime = Opt.some(0.EthTime)
225+
conf.networkParams.config.osakaTime = Opt.some(3805601325.EthTime)
226+
conf.networkParams.config.bpo1Time = Opt.some(3805701325.EthTime)
227+
conf.networkParams.config.bpo2Time = Opt.some(3805801325.EthTime)
224228

225229
let
226230
com = setupCom(conf)
@@ -313,7 +317,7 @@ createRpcSigsFromNim(RpcClient):
313317

314318
proc rpcMain*() =
315319
suite "Remote Procedure Calls":
316-
var env = setupEnv()
320+
var env = setupEnv(Prague)
317321
env.generateBlock()
318322
let
319323
client = env.client
@@ -372,6 +376,19 @@ proc rpcMain*() =
372376
let res = await client.eth_chainId()
373377
check res == com.chainId
374378

379+
test "eth_config":
380+
let res = await client.eth_config()
381+
check res.current.chainId == com.chainId
382+
check res.current.activationTime.uint64 == 0'u64
383+
384+
check res.next.isSome() and res.last.isSome()
385+
386+
check res.next.get().chainId == com.chainId
387+
check res.next.get().activationTime.uint64 == 3805601325'u64
388+
389+
check res.last.get().chainId == com.chainId
390+
check res.last.get().activationTime.uint64 == 3805801325'u64
391+
375392
test "eth_syncing":
376393
let res = await client.eth_syncing()
377394
if res.syncing == false:

0 commit comments

Comments
 (0)