From a19168dcef90cf75fe80073668c3692e80b334b1 Mon Sep 17 00:00:00 2001 From: jangko Date: Wed, 16 Aug 2023 17:05:14 +0700 Subject: [PATCH] rpc: fix missing EIP-4895 and EIP-4844 fields of marshalled objects --- nimbus/common/common.nim | 42 ++++++++++++++++---------- nimbus/rpc/engine_api.nim | 5 ++-- nimbus/rpc/execution_types.nim | 19 ++++++++++++ nimbus/rpc/merge/mergeutils.nim | 6 ++++ nimbus/rpc/rpc_types.nim | 16 +++++++++- nimbus/rpc/rpc_utils.nim | 52 +++++++++++++++++++++++++++++++++ 6 files changed, 122 insertions(+), 18 deletions(-) diff --git a/nimbus/common/common.nim b/nimbus/common/common.nim index aa462abd1..6ecfada63 100644 --- a/nimbus/common/common.nim +++ b/nimbus/common/common.nim @@ -145,21 +145,6 @@ proc init(com : CommonRef, com.networkId = networkId com.syncProgress= SyncProgress() - # com.currentFork and com.consensusType - # is set by hardForkTransition. - # set it before creating genesis block - # TD need to be some(0.u256) because it can be the genesis - # already at the MergeFork - const TimeZero = fromUnix(0) - com.hardForkTransition(ForkDeterminationInfo(blockNumber: 0.toBlockNumber, td: some(0.u256), time: some(TimeZero))) - - # com.forkIds and com.blockZeroHash is set - # by setForkId - if genesis.isNil.not: - com.genesisHeader = toGenesisHeader(genesis, - com.currentFork, com.db) - com.setForkId(com.genesisHeader) - # Initalise the PoA state regardless of whether it is needed on the current # network. For non-PoA networks this descriptor is ignored. com.poa = newClique(com.db, com.cliquePeriod, com.cliqueEpoch) @@ -168,6 +153,32 @@ proc init(com : CommonRef, com.pow = PowRef.new com.pos = CasperRef.new + # com.currentFork and com.consensusType + # is set by hardForkTransition. + # set it before creating genesis block + # TD need to be some(0.u256) because it can be the genesis + # already at the MergeFork + const TimeZero = fromUnix(0) + + # com.forkIds and com.blockZeroHash is set + # by setForkId + if genesis.isNil.not: + com.hardForkTransition(ForkDeterminationInfo( + blockNumber: 0.toBlockNumber, + td: some(0.u256), + time: some(genesis.timestamp) + )) + com.genesisHeader = toGenesisHeader(genesis, + com.currentFork, com.db) + com.setForkId(com.genesisHeader) + com.pos.timestamp = genesis.timestamp + else: + com.hardForkTransition(ForkDeterminationInfo( + blockNumber: 0.toBlockNumber, + td: some(0.u256), + time: some(TimeZero) + )) + # By default, history begins at genesis. com.startOfHistory = GENESIS_PARENT_HASH @@ -266,6 +277,7 @@ proc hardForkTransition( ## at that time, TD is no longer needed to find a fork ## TD only needed during transition from POW/POA to POS. ## Same thing happen before London block, TD can be ignored. + let fork = com.toHardFork(forkDeterminer) com.currentFork = fork com.consensusTransition(fork) diff --git a/nimbus/rpc/engine_api.nim b/nimbus/rpc/engine_api.nim index 56b1f380c..ba5b1aa39 100644 --- a/nimbus/rpc/engine_api.nim +++ b/nimbus/rpc/engine_api.nim @@ -331,10 +331,11 @@ proc handle_forkchoiceUpdated(sealingEngine: SealingEngineRef, payloadAttributes: SomeOptionalPayloadAttributes): ForkchoiceUpdatedResponse {.raises: [CatchableError].} = if payloadAttributes.isSome: - if com.isCancunOrLater(fromUnix(payloadAttributes.get.timestamp.unsafeQuantityToInt64)): + let attr = payloadAttributes.get + if com.isCancunOrLater(fromUnix(attr.timestamp.unsafeQuantityToInt64)): when not(payloadAttributes is Option[PayloadAttributesV3]): raise invalidParams("if timestamp is Cancun or later, payloadAttributes must be PayloadAttributesV3") - elif com.isShanghaiOrLater(fromUnix(payloadAttributes.get.timestamp.unsafeQuantityToInt64)): + elif com.isShanghaiOrLater(fromUnix(attr.timestamp.unsafeQuantityToInt64)): when not(payloadAttributes is Option[PayloadAttributesV2]): raise invalidParams("if timestamp is Shanghai or later, payloadAttributes must be PayloadAttributesV2") else: diff --git a/nimbus/rpc/execution_types.nim b/nimbus/rpc/execution_types.nim index 8382f4c9c..81e34fe56 100644 --- a/nimbus/rpc/execution_types.nim +++ b/nimbus/rpc/execution_types.nim @@ -232,3 +232,22 @@ func executionPayload*(p: ExecutionPayloadV3): ExecutionPayload = blobGasUsed: some(p.blobGasUsed), excessBlobGas: some(p.excessBlobGas) ) + +func executionPayload*(p: ExecutionPayloadV1OrV2): ExecutionPayload = + ExecutionPayload( + parentHash: p.parentHash, + feeRecipient: p.feeRecipient, + stateRoot: p.stateRoot, + receiptsRoot: p.receiptsRoot, + logsBloom: p.logsBloom, + prevRandao: p.prevRandao, + blockNumber: p.blockNumber, + gasLimit: p.gasLimit, + gasUsed: p.gasUsed, + timestamp: p.timestamp, + extraData: p.extraData, + baseFeePerGas: p.baseFeePerGas, + blockHash: p.blockHash, + transactions: p.transactions, + withdrawals: p.withdrawals + ) diff --git a/nimbus/rpc/merge/mergeutils.nim b/nimbus/rpc/merge/mergeutils.nim index 1d7215cb4..71f548c27 100644 --- a/nimbus/rpc/merge/mergeutils.nim +++ b/nimbus/rpc/merge/mergeutils.nim @@ -126,6 +126,12 @@ proc toBlockHeader*(payload: SomeExecutionPayload): EthBlockHeader = excessBlobGas : payload.maybeExcessBlobGas, # EIP-4844 ) +proc toBlockHeader*(payload: ExecutionPayload): EthBlockHeader = + case payload.version + of Version.V1: toBlockHeader(payload.V1) + of Version.V2: toBlockHeader(payload.V2) + of Version.V3: toBlockHeader(payload.V3) + proc toTypedTransaction*(tx: Transaction): TypedTransaction = TypedTransaction(rlp.encode(tx)) diff --git a/nimbus/rpc/rpc_types.nim b/nimbus/rpc/rpc_types.nim index e33e5e61f..78359ffa6 100644 --- a/nimbus/rpc/rpc_types.nim +++ b/nimbus/rpc/rpc_types.nim @@ -74,7 +74,10 @@ type baseFeePerGas*: Option[HexQuantityStr] transactions*: seq[JsonNode] # list of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter. uncles*: seq[Hash256] # list of uncle hashes. - withdrawals*: seq[WithdrawalObject] # list of validator withdrawals + withdrawals*: Option[seq[WithdrawalObject]] # list of validator withdrawals + withdrawalsRoot*: Option[Hash256] # EIP-4895 + blobGasUsed*: Option[HexQuantityStr] # EIP-4844 + excessBlobGas*: Option[HexQuantityStr] # EIP-4844 TransactionObject* = object # A transaction object, or null when no transaction was found: # Returned to user @@ -92,6 +95,17 @@ type v*: HexQuantityStr # ECDSA recovery id r*: HexQuantityStr # 32 Bytes - ECDSA signature r s*: HexQuantityStr # 32 Bytes - ECDSA signature s + `type`*: Option[HexQuantityStr] # EIP-2718, with 0x0 for Legacy + chainId*: Option[HexQuantityStr] # EIP-159 + accessList*: Option[seq[AccessTuple]] # EIP-2930 + maxFeePerGas*: Option[HexQuantityStr] # EIP-1559 + maxPriorityFeePerGas*: Option[HexQuantityStr] # EIP-1559 + maxFeePerBlobGas*: Option[HexQuantityStr] # EIP-4844 + versionedHashes*: Option[VersionedHashes] # EIP-4844 + + AccessTuple* = object + address*: EthAddress + storageKeys*: seq[Hash256] WithdrawalObject* = object index*: HexQuantityStr diff --git a/nimbus/rpc/rpc_utils.nim b/nimbus/rpc/rpc_utils.nim index 1ffec1283..767252acc 100644 --- a/nimbus/rpc/rpc_utils.nim +++ b/nimbus/rpc/rpc_utils.nim @@ -135,6 +135,35 @@ proc callData*(call: EthCall): RpcCallData optionalU256(call.value, result.value) optionalBytes(call.data, result.data) +proc toWd(wd: Withdrawal): WithdrawalObject = + WithdrawalObject( + index: encodeQuantity(wd.index), + validatorIndex: encodeQuantity(wd.validatorIndex), + address: wd.address, + amount: encodeQuantity(wd.amount), + ) + +proc toWdList(list: openArray[Withdrawal]): seq[WithdrawalObject] = + result = newSeqOfCap[WithdrawalObject](list.len) + for x in list: + result.add toWd(x) + +proc toHashList(list: openArray[StorageKey]): seq[Hash256] = + result = newSeqOfCap[Hash256](list.len) + for x in list: + result.add Hash256(data: x) + +proc toAccessTuple(ac: AccessPair): AccessTuple = + AccessTuple( + address: ac.address, + storageKeys: toHashList(ac.storageKeys) + ) + +proc toAccessTupleList(list: openArray[AccessPair]): seq[AccessTuple] = + result = newSeqOfCap[AccessTuple](list.len) + for x in list: + result.add toAccessTuple(x) + proc populateTransactionObject*(tx: Transaction, header: BlockHeader, txIndex: int): TransactionObject {.gcsafe, raises: [ValidationError].} = result.blockHash = some(header.hash) @@ -152,6 +181,19 @@ proc populateTransactionObject*(tx: Transaction, header: BlockHeader, txIndex: i result.r = encodeQuantity(tx.R) result.s = encodeQuantity(tx.S) + if tx.txType >= TxEip2930: + result.chainId = some(encodeQuantity(tx.chainId.uint64)) + result.`type` = some(encodeQuantity(tx.txType.uint64)) + result.accessList = some(toAccessTupleList(tx.accessList)) + + if tx.txType >= TxEIP1559: + result.maxFeePerGas = some(encodeQuantity(tx.maxFee.uint64)) + result.maxPriorityFeePerGas = some(encodeQuantity(tx.maxPriorityFee.uint64)) + + if tx.txType >= TxEIP4844: + result.maxFeePerBlobGas = some(encodeQuantity(tx.maxFeePerBlobGas.uint64)) + #result.versionedHashes = some(tx.versionedHashes) + proc populateBlockObject*(header: BlockHeader, chain: CoreDbRef, fullTx: bool, isUncle = false): BlockObject {.gcsafe, raises: [CatchableError].} = let blockHash = header.blockHash @@ -194,6 +236,16 @@ proc populateBlockObject*(header: BlockHeader, chain: CoreDbRef, fullTx: bool, i for x in chain.getBlockTransactionHashes(header): result.transactions.add %(x) + if header.withdrawalsRoot.isSome: + result.withdrawalsRoot = header.withdrawalsRoot + result.withdrawals = some(toWdList(chain.getWithdrawals(header.withdrawalsRoot.get))) + + if header.blobGasUsed.isSome: + result.blobGasUsed = some(encodeQuantity(header.blobGasUsed.get)) + + if header.excessBlobGas.isSome: + result.excessBlobGas = some(encodeQuantity(header.excessBlobGas.get)) + proc populateReceipt*(receipt: Receipt, gasUsed: GasInt, tx: Transaction, txIndex: int, header: BlockHeader, fork: EVMFork): ReceiptObject {.gcsafe, raises: [ValidationError].} =