2023-05-23 07:07:16 +00:00
|
|
|
{.used.}
|
|
|
|
|
|
|
|
import
|
|
|
|
std/[os, strutils],
|
2023-06-11 12:14:10 +00:00
|
|
|
stew/[io2, results],
|
2023-05-23 07:07:16 +00:00
|
|
|
unittest2,
|
|
|
|
../../eth/[rlp, common]
|
|
|
|
|
|
|
|
proc importBlock(blocksRlp: openArray[byte]): bool =
|
|
|
|
var
|
|
|
|
# the encoded rlp can contains one or more blocks
|
|
|
|
rlp = rlpFromBytes(blocksRlp)
|
|
|
|
|
|
|
|
while rlp.hasData:
|
2023-05-30 13:02:02 +00:00
|
|
|
let blk = rlp.read(EthBlock)
|
|
|
|
if blk.withdrawals.isSome:
|
|
|
|
# all of these blocks are pre shanghai blocks
|
|
|
|
return false
|
2023-05-23 07:07:16 +00:00
|
|
|
|
|
|
|
true
|
|
|
|
|
|
|
|
proc runTest(importFile: string): bool =
|
|
|
|
let res = io2.readAllBytes(importFile)
|
|
|
|
if res.isErr:
|
|
|
|
echo "failed to import", importFile
|
|
|
|
return
|
|
|
|
|
|
|
|
importBlock(res.get)
|
|
|
|
|
2023-05-30 13:02:02 +00:00
|
|
|
suite "Decode multiple EthBlock from bytes":
|
2023-05-23 07:07:16 +00:00
|
|
|
for filename in walkDirRec("tests/rlp/rlps"):
|
|
|
|
if not filename.endsWith(".rlp"):
|
|
|
|
continue
|
|
|
|
test filename:
|
|
|
|
check runTest(filename)
|
|
|
|
|
|
|
|
func `==`(a, b: ChainId): bool =
|
|
|
|
a.uint == b.uint
|
|
|
|
|
2023-05-30 13:02:02 +00:00
|
|
|
template roundTrip(x) =
|
|
|
|
type TT = type(x)
|
|
|
|
let bytes = rlp.encode(x)
|
|
|
|
let xx = rlp.decode(bytes, TT)
|
|
|
|
check xx == x
|
2023-05-23 07:07:16 +00:00
|
|
|
|
|
|
|
suite "BlockHeader roundtrip test":
|
|
|
|
test "Empty header":
|
|
|
|
let h = BlockHeader()
|
|
|
|
roundTrip(h)
|
|
|
|
|
|
|
|
test "Header with gas":
|
|
|
|
let h = BlockHeader(gasLimit: 10.GasInt, gasUsed: 11.GasInt)
|
|
|
|
roundTrip(h)
|
2023-05-30 13:02:02 +00:00
|
|
|
|
2023-05-23 07:07:16 +00:00
|
|
|
test "Header + some(baseFee)":
|
|
|
|
let h = BlockHeader(fee: some(1.u256))
|
|
|
|
roundTrip(h)
|
2023-05-30 13:02:02 +00:00
|
|
|
|
2023-05-23 07:07:16 +00:00
|
|
|
test "Header + none(baseFee) + some(withdrawalsRoot)":
|
|
|
|
let h = BlockHeader(withdrawalsRoot: some(Hash256()))
|
2023-05-25 08:27:37 +00:00
|
|
|
expect AssertionDefect:
|
2023-05-23 07:07:16 +00:00
|
|
|
roundTrip(h)
|
2023-05-30 13:02:02 +00:00
|
|
|
|
2023-07-28 03:19:00 +00:00
|
|
|
test "Header + none(baseFee) + some(withdrawalsRoot) + some(excessBlobGas)":
|
2023-05-23 07:07:16 +00:00
|
|
|
let h = BlockHeader(
|
2023-05-30 13:02:02 +00:00
|
|
|
withdrawalsRoot: some(Hash256()),
|
2023-07-28 03:19:00 +00:00
|
|
|
blobGasUsed: some(1'u64),
|
|
|
|
excessBlobGas: some(1'u64)
|
2023-05-23 07:07:16 +00:00
|
|
|
)
|
2023-05-25 08:27:37 +00:00
|
|
|
expect AssertionDefect:
|
2023-05-23 07:07:16 +00:00
|
|
|
roundTrip(h)
|
2023-05-30 13:02:02 +00:00
|
|
|
|
2023-07-28 03:19:00 +00:00
|
|
|
test "Header + none(baseFee) + none(withdrawalsRoot) + some(excessBlobGas)":
|
2023-05-30 13:02:02 +00:00
|
|
|
let h = BlockHeader(
|
2023-07-28 03:19:00 +00:00
|
|
|
blobGasUsed: some(1'u64),
|
|
|
|
excessBlobGas: some(1'u64)
|
2023-05-23 07:07:16 +00:00
|
|
|
)
|
2023-05-25 08:27:37 +00:00
|
|
|
expect AssertionDefect:
|
2023-05-23 07:07:16 +00:00
|
|
|
roundTrip(h)
|
2023-05-30 13:02:02 +00:00
|
|
|
|
2023-07-28 03:19:00 +00:00
|
|
|
test "Header + some(baseFee) + none(withdrawalsRoot) + some(excessBlobGas)":
|
2023-05-23 07:07:16 +00:00
|
|
|
let h = BlockHeader(
|
|
|
|
fee: some(2.u256),
|
2023-07-28 03:19:00 +00:00
|
|
|
blobGasUsed: some(1'u64),
|
|
|
|
excessBlobGas: some(1'u64)
|
2023-05-23 07:07:16 +00:00
|
|
|
)
|
2023-05-25 08:27:37 +00:00
|
|
|
expect AssertionDefect:
|
2023-05-23 07:07:16 +00:00
|
|
|
roundTrip(h)
|
2023-05-30 13:02:02 +00:00
|
|
|
|
2023-05-23 07:07:16 +00:00
|
|
|
test "Header + some(baseFee) + some(withdrawalsRoot)":
|
|
|
|
let h = BlockHeader(
|
|
|
|
fee: some(2.u256),
|
|
|
|
withdrawalsRoot: some(Hash256())
|
|
|
|
)
|
|
|
|
roundTrip(h)
|
2023-05-30 13:02:02 +00:00
|
|
|
|
2023-07-28 03:19:00 +00:00
|
|
|
test "Header + some(baseFee) + some(withdrawalsRoot) + some(excessBlobGas)":
|
2023-05-23 07:07:16 +00:00
|
|
|
let h = BlockHeader(
|
|
|
|
fee: some(2.u256),
|
|
|
|
withdrawalsRoot: some(Hash256()),
|
2023-07-28 03:19:00 +00:00
|
|
|
blobGasUsed: some(1'u64),
|
|
|
|
excessBlobGas: some(1'u64)
|
2023-05-23 07:07:16 +00:00
|
|
|
)
|
2023-05-30 13:02:02 +00:00
|
|
|
roundTrip(h)
|
|
|
|
|
|
|
|
template roundTrip2(a1, a2, body: untyped) =
|
|
|
|
type TT = type(a1)
|
|
|
|
when type(a2) isnot TT:
|
|
|
|
{.error: "mismatch type".}
|
|
|
|
var bytes = rlp.encode(a1)
|
|
|
|
bytes.add rlp.encode(a2)
|
|
|
|
var r = rlpFromBytes(bytes)
|
|
|
|
let
|
|
|
|
b1 {.inject.} = r.read(TT)
|
|
|
|
b2 {.inject.} = r.read(TT)
|
|
|
|
check b1 == a1
|
|
|
|
check b2 == a2
|
|
|
|
body
|
|
|
|
|
|
|
|
|
|
|
|
template genTest(TT) =
|
|
|
|
const TTS = astToStr(TT)
|
|
|
|
suite TTS & " roundtrip test":
|
|
|
|
test "Empty " & TTS:
|
|
|
|
let blk = TT()
|
|
|
|
roundTrip(blk)
|
|
|
|
|
|
|
|
test TTS & " with withdrawals":
|
|
|
|
let blk = TT(withdrawals: some(@[Withdrawal()]))
|
|
|
|
roundTrip(blk)
|
|
|
|
|
|
|
|
test "2 " & TTS & " none(Withdrawal)+none(Withdrawal)":
|
|
|
|
let blk = TT()
|
|
|
|
roundTrip2(blk, blk):
|
|
|
|
check b1.withdrawals.isNone
|
|
|
|
check b2.withdrawals.isNone
|
|
|
|
|
|
|
|
test "2 " & TTS & " none(Withdrawal)+some(Withdrawal)":
|
|
|
|
let blk1 = TT()
|
|
|
|
let blk2 = TT(withdrawals: some(@[Withdrawal()]))
|
|
|
|
roundTrip2(blk1, blk2):
|
|
|
|
check b1.withdrawals.isNone
|
|
|
|
check b2.withdrawals.isSome
|
|
|
|
|
|
|
|
test "2 " & TTS & " some(Withdrawal)+none(Withdrawal)":
|
|
|
|
let blk1 = TT()
|
|
|
|
let blk2 = TT(withdrawals: some(@[Withdrawal()]))
|
|
|
|
roundTrip2(blk2, blk1):
|
|
|
|
check b1.withdrawals.isSome
|
|
|
|
check b2.withdrawals.isNone
|
|
|
|
|
|
|
|
test "2 " & TTS & " some(Withdrawal)+some(Withdrawal)":
|
|
|
|
let blk = TT(withdrawals: some(@[Withdrawal()]))
|
|
|
|
roundTrip2(blk, blk):
|
|
|
|
check b1.withdrawals.isSome
|
|
|
|
check b2.withdrawals.isSome
|
|
|
|
|
|
|
|
genTest(EthBlock)
|
|
|
|
genTest(BlockBody)
|
|
|
|
|
|
|
|
type
|
|
|
|
BlockHeaderOpt* = 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
|
|
|
|
fee*: Opt[UInt256]
|
|
|
|
withdrawalsRoot*: Opt[Hash256]
|
2023-07-28 03:19:00 +00:00
|
|
|
blobGasUsed*: Opt[GasInt]
|
|
|
|
excessBlobGas*: Opt[GasInt]
|
2023-05-30 13:02:02 +00:00
|
|
|
|
|
|
|
BlockBodyOpt* = object
|
|
|
|
transactions*: seq[Transaction]
|
|
|
|
uncles*: seq[BlockHeaderOpt]
|
|
|
|
withdrawals*: Opt[seq[Withdrawal]]
|
|
|
|
|
|
|
|
EthBlockOpt* = object
|
|
|
|
header* : BlockHeader
|
|
|
|
txs* : seq[Transaction]
|
|
|
|
uncles* : seq[BlockHeaderOpt]
|
|
|
|
withdrawals*: Opt[seq[Withdrawal]]
|
|
|
|
|
|
|
|
template genTestOpt(TT) =
|
|
|
|
const TTS = astToStr(TT)
|
|
|
|
suite TTS & " roundtrip test":
|
|
|
|
test "Empty " & TTS:
|
|
|
|
let blk = TT()
|
|
|
|
roundTrip(blk)
|
|
|
|
|
|
|
|
test TTS & " with withdrawals":
|
|
|
|
let blk = TT(withdrawals: Opt.some(@[Withdrawal()]))
|
|
|
|
roundTrip(blk)
|
|
|
|
|
|
|
|
test "2 " & TTS & " none(Withdrawal)+none(Withdrawal)":
|
|
|
|
let blk = TT()
|
|
|
|
roundTrip2(blk, blk):
|
|
|
|
check b1.withdrawals.isNone
|
|
|
|
check b2.withdrawals.isNone
|
|
|
|
|
|
|
|
test "2 " & TTS & " none(Withdrawal)+some(Withdrawal)":
|
|
|
|
let blk1 = TT()
|
|
|
|
let blk2 = TT(withdrawals: Opt.some(@[Withdrawal()]))
|
|
|
|
roundTrip2(blk1, blk2):
|
|
|
|
check b1.withdrawals.isNone
|
|
|
|
check b2.withdrawals.isSome
|
|
|
|
|
|
|
|
test "2 " & TTS & " some(Withdrawal)+none(Withdrawal)":
|
|
|
|
let blk1 = TT()
|
|
|
|
let blk2 = TT(withdrawals: Opt.some(@[Withdrawal()]))
|
|
|
|
roundTrip2(blk2, blk1):
|
|
|
|
check b1.withdrawals.isSome
|
|
|
|
check b2.withdrawals.isNone
|
|
|
|
|
|
|
|
test "2 " & TTS & " some(Withdrawal)+some(Withdrawal)":
|
|
|
|
let blk = TT(withdrawals: Opt.some(@[Withdrawal()]))
|
|
|
|
roundTrip2(blk, blk):
|
|
|
|
check b1.withdrawals.isSome
|
|
|
|
check b2.withdrawals.isSome
|
|
|
|
|
|
|
|
genTestOpt(BlockBodyOpt)
|
|
|
|
genTestOpt(EthBlockOpt)
|