extend `BlockHeader` for Capella (#562)

Adds `Withdrawal` type according to EIP-4895, and extends `BlockHeader`
accordingly. Also adds RLP encoding support for `Withdrawal` to enable
building `BlockHeader` (used by Nimbus-CL in empty block prod fallback).
This commit is contained in:
Etan Kissling 2022-11-25 11:07:51 +01:00 committed by GitHub
parent f4ef9181c7
commit 6499ee2bc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 22 deletions

View File

@ -96,6 +96,12 @@ type
status*: TransactionStatus status*: TransactionStatus
data*: Blob data*: Blob
Withdrawal* = object # EIP-4895
index* : uint64
validatorIndex*: uint64
address* : EthAddress
amount* : UInt256
BlockHeader* = object BlockHeader* = object
parentHash*: Hash256 parentHash*: Hash256
ommersHash*: Hash256 ommersHash*: Hash256
@ -114,6 +120,7 @@ type
nonce*: BlockNonce nonce*: BlockNonce
# `baseFee` is the get/set of `fee` # `baseFee` is the get/set of `fee`
fee*: Option[UInt256] # EIP-1559 fee*: Option[UInt256] # EIP-1559
withdrawalsRoot*: Option[Hash256] # EIP-4895
BlockBody* = object BlockBody* = object
transactions*: seq[Transaction] transactions*: seq[Transaction]

View File

@ -113,6 +113,13 @@ proc append*(w: var RlpWriter, tx: Transaction) =
of TxEip1559: of TxEip1559:
w.appendTxEip1559(tx) 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)= template read[T](rlp: var Rlp, val: var T)=
val = rlp.read(type val) val = rlp.read(type val)
@ -308,28 +315,36 @@ proc append*(rlpWriter: var RlpWriter, t: Time) {.inline.} =
rlpWriter.append(t.toUnix()) rlpWriter.append(t.toUnix())
proc append*(w: var RlpWriter, h: BlockHeader) = 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): for k, v in fieldPairs(h):
when k != "fee": when k notin ["fee", "withdrawalsRoot"]:
w.append(v) w.append(v)
if h.fee.isSome: if h.fee.isSome:
w.append(h.fee.get()) w.append(h.fee.get())
if h.withdrawalsRoot.isSome:
w.append(h.withdrawalsRoot.get())
proc read*(rlp: var Rlp, T: type BlockHeader): T = proc read*(rlp: var Rlp, T: type BlockHeader): T =
let len = rlp.listLen let len = rlp.listLen
if len notin {15, 16}: if len notin {15, 16, 17}:
raise newException(UnsupportedRlpError, raise newException(UnsupportedRlpError,
"BlockHeader elems should be 15 or 16 got " & $len) "BlockHeader elems should be 15, 16, or 17 got " & $len)
rlp.tryEnterList() rlp.tryEnterList()
for k, v in fieldPairs(result): for k, v in fieldPairs(result):
when k != "fee": when k notin ["fee", "withdrawalsRoot"]:
v = rlp.read(type v) v = rlp.read(type v)
if len == 16: if len >= 16:
# EIP-1559 # EIP-1559
result.baseFee = rlp.read(UInt256) result.baseFee = rlp.read(UInt256)
if len >= 17:
# EIP-4895
result.withdrawalsRoot = some rlp.read(Hash256)
proc rlpHash*[T](v: T): Hash256 = proc rlpHash*[T](v: T): Hash256 =
keccakHash(rlp.encode(v)) keccakHash(rlp.encode(v))

View File

@ -79,6 +79,19 @@ proc suite1() =
check aa == a check aa == a
check bb == b 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() = proc suite2() =
suite "eip 2718 transaction": suite "eip 2718 transaction":
for i in 0..<10: for i in 0..<10: