diff --git a/eth/common/eth_types.nim b/eth/common/eth_types.nim index f081ed9..b846176 100644 --- a/eth/common/eth_types.nim +++ b/eth/common/eth_types.nim @@ -96,24 +96,31 @@ type status*: TransactionStatus data*: Blob + Withdrawal* = object # EIP-4895 + index* : uint64 + validatorIndex*: uint64 + address* : EthAddress + amount* : UInt256 + BlockHeader* = object - parentHash*: Hash256 - ommersHash*: Hash256 - coinbase*: EthAddress - stateRoot*: Hash256 - txRoot*: Hash256 - receiptRoot*: Hash256 - bloom*: BloomFilter - difficulty*: DifficultyInt - blockNumber*: BlockNumber - gasLimit*: GasInt - gasUsed*: GasInt - timestamp*: EthTime - extraData*: Blob - mixDigest*: Hash256 - nonce*: BlockNonce + parentHash*: Hash256 + ommersHash*: Hash256 + coinbase*: EthAddress + stateRoot*: Hash256 + txRoot*: Hash256 + receiptRoot*: Hash256 + bloom*: BloomFilter + difficulty*: DifficultyInt + blockNumber*: BlockNumber + gasLimit*: GasInt + gasUsed*: GasInt + timestamp*: EthTime + extraData*: Blob + mixDigest*: Hash256 + nonce*: BlockNonce # `baseFee` is the get/set of `fee` - fee*: Option[UInt256] # EIP-1559 + fee*: Option[UInt256] # EIP-1559 + withdrawalsRoot*: Option[Hash256] # EIP-4895 BlockBody* = object transactions*: seq[Transaction] diff --git a/eth/common/eth_types_rlp.nim b/eth/common/eth_types_rlp.nim index 10a5df4..b6cb4aa 100644 --- a/eth/common/eth_types_rlp.nim +++ b/eth/common/eth_types_rlp.nim @@ -113,6 +113,13 @@ proc append*(w: var RlpWriter, tx: Transaction) = of TxEip1559: w.appendTxEip1559(tx) +proc append*(w: var RlpWriter, withdrawal: Withdrawal) = + w.startList(4) + w.append(withdrawal.index) + w.append(withdrawal.validatorIndex) + w.append(withdrawal.address) + w.append(withdrawal.amount) + template read[T](rlp: var Rlp, val: var T)= val = rlp.read(type val) @@ -308,28 +315,36 @@ proc append*(rlpWriter: var RlpWriter, t: Time) {.inline.} = rlpWriter.append(t.toUnix()) proc append*(w: var RlpWriter, h: BlockHeader) = - w.startList(if h.fee.isSome: 16 else: 15) + var len = 15 + if h.fee.isSome: inc len + if h.withdrawalsRoot.isSome: inc len + w.startList(len) for k, v in fieldPairs(h): - when k != "fee": + when k notin ["fee", "withdrawalsRoot"]: w.append(v) if h.fee.isSome: w.append(h.fee.get()) + if h.withdrawalsRoot.isSome: + w.append(h.withdrawalsRoot.get()) proc read*(rlp: var Rlp, T: type BlockHeader): T = let len = rlp.listLen - if len notin {15, 16}: + if len notin {15, 16, 17}: raise newException(UnsupportedRlpError, - "BlockHeader elems should be 15 or 16 got " & $len) + "BlockHeader elems should be 15, 16, or 17 got " & $len) rlp.tryEnterList() for k, v in fieldPairs(result): - when k != "fee": + when k notin ["fee", "withdrawalsRoot"]: v = rlp.read(type v) - if len == 16: + if len >= 16: # EIP-1559 result.baseFee = rlp.read(UInt256) + if len >= 17: + # EIP-4895 + result.withdrawalsRoot = some rlp.read(Hash256) proc rlpHash*[T](v: T): Hash256 = keccakHash(rlp.encode(v)) diff --git a/tests/rlp/test_common.nim b/tests/rlp/test_common.nim index 3d20c8e..44ebfa4 100644 --- a/tests/rlp/test_common.nim +++ b/tests/rlp/test_common.nim @@ -79,6 +79,19 @@ proc suite1() = check aa == a check bb == b + test "EIP 4895 roundtrip": + let a = Withdrawal( + index: 1, + validatorIndex: 2, + address: EthAddress [ + 0.byte, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19], + amount: 4.u256 * 1_000_000_000.u256) + + let abytes = rlp.encode(a) + let aa = rlp.decode(abytes, Withdrawal) + check aa == a + proc suite2() = suite "eip 2718 transaction": for i in 0..<10: