implement EIP-1559 Transaction and BlockHeader

This commit is contained in:
jangko 2021-06-26 15:18:42 +07:00
parent 601fa7ff66
commit a10d301085
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
3 changed files with 322 additions and 298 deletions

View File

@ -4,7 +4,7 @@ import
../rlp, ../trie/[trie_defs, db] ../rlp, ../trie/[trie_defs, db]
export export
stint, read, append, KeccakHash, rlp stint, read, append, KeccakHash, rlp, options
type type
Hash256* = MDigest[256] Hash256* = MDigest[256]
@ -44,46 +44,31 @@ type
storageRoot*: Hash256 storageRoot*: Hash256
codeHash*: Hash256 codeHash*: Hash256
LegacyTx* = object
nonce* : AccountNonce
gasPrice*: GasInt
gasLimit*: GasInt
to* {.rlpCustomSerialization.}: EthAddress
value* : UInt256
payload* : Blob
V* : int64
R*, S* : UInt256
isContractCreation* {.rlpIgnore.}: bool
AccessPair* = object AccessPair* = object
address* : EthAddress address* : EthAddress
storageKeys*: seq[StorageKey] storageKeys*: seq[StorageKey]
AccessList* = seq[AccessPair] AccessList* = seq[AccessPair]
AccessListTx* = object
chainId* {.rlpCustomSerialization.}: ChainId
nonce* : AccountNonce
gasPrice* : GasInt
gasLimit* : GasInt
to* {.rlpCustomSerialization.}: EthAddress
value* : UInt256
payload* : Blob
accessList*: AccessList
V* : int64
R*, S* : UInt256
isContractCreation* {.rlpIgnore.}: bool
TxType* = enum TxType* = enum
LegacyTxType TxLegacy
AccessListTxType TxEip2930
TxEip1559
Transaction* = object Transaction* = object
case txType*: TxType txType* : TxType # EIP-2718
of LegacyTxType: chainId* : ChainId # EIP-2930
legacyTx*: LegacyTx nonce* : AccountNonce
of AccessListTxType: gasPrice* : GasInt
accessListTx*: AccessListTx maxPriorityFee*: GasInt # EIP-1559
maxFee* : GasInt # EIP-1559
gasLimit* : GasInt
to* : Option[EthAddress]
value* : UInt256
payload* : Blob
accessList* : AccessList # EIP-2930
V* : int64
R*, S* : UInt256
TransactionStatus* = enum TransactionStatus* = enum
Unknown, Unknown,
@ -112,6 +97,8 @@ type
extraData*: Blob extraData*: Blob
mixDigest*: Hash256 mixDigest*: Hash256
nonce*: BlockNonce nonce*: BlockNonce
# `baseFee` is the get/set of `fee`
fee*: Option[UInt256] # EIP-1559
BlockBody* = object BlockBody* = object
transactions*{.rlpCustomSerialization.}: seq[Transaction] transactions*{.rlpCustomSerialization.}: seq[Transaction]
@ -122,36 +109,22 @@ type
topics*: seq[Topic] topics*: seq[Topic]
data*: Blob data*: Blob
HashOrStatus* = object # easily convertible between
case isHash*: bool # ReceiptType and TxType
of true: ReceiptType* = TxType
hash*: Hash256 # LegacyReceipt = TxLegacy
else: # Eip2930Receipt = TxEip2930
status*: bool # Eip1559Receipt = TxEip1559
LegacyReceipt* = object Receipt* = object
stateRootOrStatus*: HashOrStatus receiptType* : ReceiptType
cumulativeGasUsed*: GasInt isHash* : bool # hash or status
bloom*: BloomFilter status* : bool # EIP-658
logs* : seq[Log] hash* : Hash256
AccessListReceipt* = object
status*: bool
cumulativeGasUsed*: GasInt cumulativeGasUsed*: GasInt
bloom* : BloomFilter bloom* : BloomFilter
logs* : seq[Log] logs* : seq[Log]
ReceiptType* = enum
LegacyReceiptType
AccessListReceiptType
Receipt* = object
case receiptType*: ReceiptType
of LegacyReceiptType:
legacyReceipt*: LegacyReceipt
of AccessListReceiptType:
accessListReceipt*: AccessListReceipt
EthBlock* = object EthBlock* = object
header*: BlockHeader header*: BlockHeader
txs* {.rlpCustomSerialization.}: seq[Transaction] txs* {.rlpCustomSerialization.}: seq[Transaction]
@ -222,6 +195,11 @@ type
OK OK
Error Error
const
LegacyReceipt* = TxLegacy
Eip2930Receipt* = TxEip2930
Eip1559Receipt* = TxEip1559
when BlockNumber is int64: when BlockNumber is int64:
## The goal of these templates is to make it easier to switch ## The goal of these templates is to make it easier to switch
## the block number type to a different representation ## the block number type to a different representation
@ -256,6 +234,16 @@ else:
template u256*(n: BlockNumber): UInt256 = template u256*(n: BlockNumber): UInt256 =
n n
# EIP-1559 conveniences
func baseFee*(h: BlockHeader | BlockHeaderRef): UInt256 =
if h.fee.isSome:
h.fee.get()
else:
0.u256
template `baseFee=`*(h: BlockHeader | BlockHeaderRef, data: UInt256) =
h.fee = some(data)
func toBlockNonce*(n: uint64): BlockNonce = func toBlockNonce*(n: uint64): BlockNonce =
n.toBytesBE() n.toBytesBE()
@ -268,25 +256,24 @@ proc newAccount*(nonce: AccountNonce = 0, balance: UInt256 = 0.u256): Account =
result.storageRoot = emptyRlpHash result.storageRoot = emptyRlpHash
result.codeHash = blankStringHash result.codeHash = blankStringHash
proc hashOrStatus*(hash: Hash256): HashOrStatus = proc hasStatus*(rec: Receipt): bool {.inline.} =
HashOrStatus(isHash: true, hash: hash) rec.isHash == false
proc hashOrStatus*(status: bool): HashOrStatus = proc hasStateRoot*(rec: Receipt): bool {.inline.} =
HashOrStatus(isHash: false, status: status) rec.isHash == true
proc hasStatus*(rec: LegacyReceipt): bool {.inline.} = proc stateRoot*(rec: Receipt): Hash256 {.inline.} =
rec.stateRootOrStatus.isHash == false
proc hasStateRoot*(rec: LegacyReceipt): bool {.inline.} =
rec.stateRootOrStatus.isHash == true
proc stateRoot*(rec: LegacyReceipt): Hash256 {.inline.} =
doAssert(rec.hasStateRoot) doAssert(rec.hasStateRoot)
rec.stateRootOrStatus.hash rec.hash
proc status*(rec: LegacyReceipt): int {.inline.} = template contractCreation*(tx: Transaction): bool =
doAssert(rec.hasStatus) tx.to.isNone
if rec.stateRootOrStatus.status: 1 else: 0
func destination*(tx: Transaction): EthAddress =
# use getRecipient if you also want to get
# the contract address
if tx.to.isSome:
return tx.to.get
# #
# Rlp serialization: # Rlp serialization:
@ -329,52 +316,132 @@ proc append*(rlpWriter: var RlpWriter, value: Stint) =
{.fatal: "RLP serialization of signed integers is not allowed".} {.fatal: "RLP serialization of signed integers is not allowed".}
discard discard
type proc append*[T](w: var RlpWriter, val: Option[T]) =
TxTypes* = LegacyTx | AccessListTx if val.isSome:
w.append(val.get())
else:
w.append("")
proc read*(rlp: var Rlp, t: var TxTypes, _: type EthAddress): EthAddress {.inline.} = proc appendTxLegacy(w: var RlpWriter, tx: Transaction) =
w.startList(9)
w.append(tx.nonce)
w.append(tx.gasPrice)
w.append(tx.gasLimit)
w.append(tx.to)
w.append(tx.value)
w.append(tx.payload)
w.append(tx.V)
w.append(tx.R)
w.append(tx.S)
proc appendTxEip2930(w: var RlpWriter, tx: Transaction) =
w.append(1)
w.startList(11)
w.append(tx.chainId.uint64)
w.append(tx.nonce)
w.append(tx.gasPrice)
w.append(tx.gasLimit)
w.append(tx.to)
w.append(tx.value)
w.append(tx.payload)
w.append(tx.accessList)
w.append(tx.V)
w.append(tx.R)
w.append(tx.S)
proc appendTxEip1559(w: var RlpWriter, tx: Transaction) =
w.append(2)
w.startList(12)
w.append(tx.chainId.uint64)
w.append(tx.nonce)
w.append(tx.maxPriorityFee)
w.append(tx.maxFee)
w.append(tx.gasLimit)
w.append(tx.to)
w.append(tx.value)
w.append(tx.payload)
w.append(tx.accessList)
w.append(tx.V)
w.append(tx.R)
w.append(tx.S)
proc append*(w: var RlpWriter, tx: Transaction) =
case tx.txType
of TxLegacy:
w.appendTxLegacy(tx)
of TxEip2930:
w.appendTxEip2930(tx)
of TxEip1559:
w.appendTxEip1559(tx)
template read[T](rlp: var Rlp, val: var T)=
val = rlp.read(type val)
proc read[T](rlp: var Rlp, val: var Option[T])=
if rlp.blobLen != 0: if rlp.blobLen != 0:
result = rlp.read(EthAddress) val = some(rlp.read(T))
else: else:
t.isContractCreation = true rlp.skipElem
rlp.skipElem()
proc append*(rlpWriter: var RlpWriter, t: TxTypes, a: EthAddress) {.inline.} = proc readTxLegacy(rlp: var Rlp, tx: var Transaction)=
if t.isContractCreation: tx.txType = TxLegacy
rlpWriter.append("") rlp.tryEnterList()
else: rlp.read(tx.nonce)
rlpWriter.append(a) rlp.read(tx.gasPrice)
rlp.read(tx.gasLimit)
rlp.read(tx.to)
rlp.read(tx.value)
rlp.read(tx.payload)
rlp.read(tx.V)
rlp.read(tx.R)
rlp.read(tx.S)
proc read*(rlp: var Rlp, t: var AccessListTx, _: type ChainId): ChainId {.inline.} = proc readTxEip2930(rlp: var Rlp, tx: var Transaction)=
rlp.read(uint64).ChainId tx.txType = TxEip2930
rlp.tryEnterList()
tx.chainId = rlp.read(uint64).ChainId
rlp.read(tx.nonce)
rlp.read(tx.gasPrice)
rlp.read(tx.gasLimit)
rlp.read(tx.to)
rlp.read(tx.value)
rlp.read(tx.payload)
rlp.read(tx.accessList)
rlp.read(tx.V)
rlp.read(tx.R)
rlp.read(tx.S)
proc append*(rlpWriter: var RlpWriter, t: AccessListTx, a: ChainId) {.inline.} = proc readTxEip1559(rlp: var Rlp, tx: var Transaction)=
rlpWriter.append(a.uint64) tx.txType = TxEip1559
rlp.tryEnterList()
proc append*(rlpWriter: var RlpWriter, tx: Transaction) = tx.chainId = rlp.read(uint64).ChainId
if tx.txType == LegacyTxType: rlp.read(tx.nonce)
rlpWriter.append(tx.legacyTx) rlp.read(tx.maxPriorityFee)
else: rlp.read(tx.maxFee)
# EIP 2718/2930 rlp.read(tx.gasLimit)
rlpWriter.append(1) rlp.read(tx.to)
rlpWriter.append(tx.accessListTx) rlp.read(tx.value)
rlp.read(tx.payload)
rlp.read(tx.accessList)
rlp.read(tx.V)
rlp.read(tx.R)
rlp.read(tx.S)
proc read*(rlp: var Rlp, T: type Transaction): T = proc read*(rlp: var Rlp, T: type Transaction): T =
if rlp.isList: if rlp.isList:
return Transaction( rlp.readTxLegacy(result)
txType: LegacyTxType, return
legacyTx: rlp.read(LegacyTx)
)
# EIP 2718/2930 # EIP 2718
let txType = rlp.read(int) let txType = rlp.read(int)
if txType != 1: if txType notin {1, 2}:
raise newException(UnsupportedRlpError, raise newException(UnsupportedRlpError,
"TxType expect 1 got " & $txType) "TxType expect 1 or 2 got " & $txType)
return Transaction(
txType: AccessListTxType, if TxType(txType) == TxEip2930:
accessListTx: rlp.read(AccessListTx) rlp.readTxEip2930(result)
) else:
rlp.readTxEip1559(result)
proc read*(rlp: var Rlp, t: var (EthBlock | BlockBody), _: type seq[Transaction]): seq[Transaction] {.inline.} = proc read*(rlp: var Rlp, t: var (EthBlock | BlockBody), _: type seq[Transaction]): seq[Transaction] {.inline.} =
# EIP 2718/2930: we have to override this field # EIP 2718/2930: we have to override this field
@ -395,21 +462,11 @@ proc append*(rlpWriter: var RlpWriter, blk: EthBlock | BlockBody, txs: seq[Trans
# not rlp(txType, txPayload) -> two list elem, wrong! # not rlp(txType, txPayload) -> two list elem, wrong!
rlpWriter.startList(txs.len) rlpWriter.startList(txs.len)
for tx in txs: for tx in txs:
if tx.txType == LegacyTxType: if tx.txType == TxLegacy:
rlpWriter.append(tx) rlpWriter.append(tx)
else: else:
rlpWriter.append(rlp.encode(tx)) rlpWriter.append(rlp.encode(tx))
proc read*(rlp: var Rlp, T: type HashOrStatus): T {.inline.} =
if rlp.isBlob() and (rlp.blobLen() == 32 or rlp.blobLen() == 1):
if rlp.blobLen == 1:
result = hashOrStatus(rlp.read(uint8) == 1)
else:
result = hashOrStatus(rlp.read(Hash256))
else:
raise newException(RlpTypeMismatch,
"HashOrStatus expected, but the source RLP is not a blob of right size.")
func init*(T: type BlockHashOrNumber, str: string): T func init*(T: type BlockHashOrNumber, str: string): T
{.raises: [ValueError, Defect].} = {.raises: [ValueError, Defect].} =
if str.startsWith "0x": if str.startsWith "0x":
@ -428,36 +485,45 @@ func `$`*(x: BlockHashOrNumber): string =
else: else:
$x.number $x.number
proc append*(rlpWriter: var RlpWriter, value: HashOrStatus) {.inline.} = proc append*(w: var RlpWriter, rec: Receipt) =
if value.isHash: if rec.receiptType in {Eip2930Receipt, Eip1559Receipt}:
rlpWriter.append(value.hash) w.append(rec.receiptType.int)
else:
rlpWriter.append(if value.status: 1'u8 else: 0'u8)
proc append*(rlpWriter: var RlpWriter, rec: Receipt) = w.startList(4)
if rec.receiptType == LegacyReceiptType: if rec.isHash:
rlpWriter.append(rec.legacyReceipt) w.append(rec.hash)
else: else:
# EIP 2718/2930 w.append(rec.status.uint8)
rlpWriter.append(1)
rlpWriter.append(rec.accessListReceipt) w.append(rec.cumulativeGasUsed)
w.append(rec.bloom)
w.append(rec.logs)
proc read*(rlp: var Rlp, T: type Receipt): T = proc read*(rlp: var Rlp, T: type Receipt): T =
if rlp.isList: if rlp.isList:
return Receipt( result.receiptType = LegacyReceipt
receiptType: LegacyReceiptType, else:
legacyReceipt: rlp.read(LegacyReceipt) # EIP 2718
)
# EIP 2718/2930
let recType = rlp.read(int) let recType = rlp.read(int)
if recType != 1: if recType notin {1, 2}:
raise newException(UnsupportedRlpError, raise newException(UnsupportedRlpError,
"TxType expect 1 got " & $recType) "TxType expect 1 or 2 got " & $recType)
return Receipt( result.receiptType = ReceiptType(recType)
receiptType: AccessListReceiptType,
accessListReceipt: rlp.read(AccessListReceipt) rlp.tryEnterList()
) if rlp.isBlob and rlp.blobLen in {0, 1}:
result.isHash = false
result.status = rlp.read(uint8) == 1
elif rlp.isBlob and rlp.blobLen == 32:
result.isHash = true
result.hash = rlp.read(Hash256)
else:
raise newException(RlpTypeMismatch,
"HashOrStatus expected, but the source RLP is not a blob of right size.")
rlp.read(result.cumulativeGasUsed)
rlp.read(result.bloom)
rlp.read(result.logs)
proc read*(rlp: var Rlp, T: type Time): T {.inline.} = proc read*(rlp: var Rlp, T: type Time): T {.inline.} =
result = fromUnix(rlp.read(int64)) result = fromUnix(rlp.read(int64))
@ -478,6 +544,30 @@ proc read*(rlp: var Rlp, T: type HashOrNum): T =
proc append*(rlpWriter: var RlpWriter, t: Time) {.inline.} = proc append*(rlpWriter: var RlpWriter, t: Time) {.inline.} =
rlpWriter.append(t.toUnix()) rlpWriter.append(t.toUnix())
proc append*(w: var RlpWriter, h: BlockHeader) =
w.startList(if h.fee.isSome: 16 else: 15)
for k, v in fieldPairs(h):
when k != "fee":
w.append(v)
if h.fee.isSome:
w.append(h.fee.get())
proc read*(rlp: var Rlp, T: type BlockHeader): T =
let len = rlp.listLen
if len notin {15, 16}:
raise newException(UnsupportedRlpError,
"BlockHeader elems should be 15 or 16 got " & $len)
rlp.tryEnterList()
for k, v in fieldPairs(result):
when k != "fee":
v = rlp.read(type v)
if len == 16:
# EIP-1559
result.baseFee = rlp.read(UInt256)
proc rlpHash*[T](v: T): Hash256 = proc rlpHash*[T](v: T): Hash256 =
keccak256.digest(rlp.encode(v)) keccak256.digest(rlp.encode(v))

View File

@ -2,118 +2,76 @@ import
nimcrypto/keccak, nimcrypto/keccak,
".."/[common, rlp, keys] ".."/[common, rlp, keys]
proc initLegacyTx*(nonce: AccountNonce, gasPrice, gasLimit: GasInt, to: EthAddress,
value: UInt256, payload: Blob, V: int64, R, S: UInt256, isContractCreation = false): LegacyTx =
result.nonce = nonce
result.gasPrice = gasPrice
result.gasLimit = gasLimit
result.to = to
result.value = value
result.payload = payload
result.V = V
result.R = R
result.S = S
result.isContractCreation = isContractCreation
type
LegacyUnsignedTx* = object
nonce*: AccountNonce
gasPrice*: GasInt
gasLimit*: GasInt
to* {.rlpCustomSerialization.}: EthAddress
value*: UInt256
payload*: Blob
isContractCreation* {.rlpIgnore.}: bool
AccessListUnsignedTx* = object
chainId* {.rlpCustomSerialization.}: ChainId
nonce* : AccountNonce
gasPrice* : GasInt
gasLimit* : GasInt
to* {.rlpCustomSerialization.}: EthAddress
value* : UInt256
payload* : Blob
accessList*: AccessList
isContractCreation* {.rlpIgnore.}: bool
UnsignedTxTypes* = LegacyUnsignedTx | AccessListUnsignedTx
proc read*(rlp: var Rlp, t: var UnsignedTxTypes, _: type EthAddress): EthAddress {.inline.} =
if rlp.blobLen != 0:
result = rlp.read(EthAddress)
else:
t.isContractCreation = true
proc append*(rlpWriter: var RlpWriter, t: UnsignedTxTypes, a: EthAddress) {.inline.} =
if t.isContractCreation:
rlpWriter.append("")
else:
rlpWriter.append(a)
proc read*(rlp: var Rlp, t: var AccessListUnsignedTx, _: type ChainId): ChainId {.inline.} =
rlp.read(uint64).ChainId
proc append*(rlpWriter: var RlpWriter, t: AccessListUnsignedTx, a: ChainId) {.inline.} =
rlpWriter.append(a.uint64)
const const
EIP155_CHAIN_ID_OFFSET* = 35'i64 EIP155_CHAIN_ID_OFFSET* = 35'i64
func rlpEncode*(tx: LegacyTx): auto = func rlpEncodeLegacy(tx: Transaction): auto =
# Encode transaction without signature var w = initRlpWriter()
return rlp.encode(LegacyUnsignedTx( w.startList(6)
nonce: tx.nonce, w.append(tx.nonce)
gasPrice: tx.gasPrice, w.append(tx.gasPrice)
gasLimit: tx.gasLimit, w.append(tx.gasLimit)
to: tx.to, w.append(tx.to)
value: tx.value, w.append(tx.value)
payload: tx.payload, w.append(tx.payload)
isContractCreation: tx.isContractCreation w.finish()
))
func rlpEncodeEIP155*(tx: LegacyTx): auto = func rlpEncodeEip155(tx: Transaction): auto =
let V = (tx.V - EIP155_CHAIN_ID_OFFSET) div 2 let chainId = (tx.V - EIP155_CHAIN_ID_OFFSET) div 2
# Encode transaction without signature var w = initRlpWriter()
return rlp.encode(LegacyTx( w.startList(9)
nonce: tx.nonce, w.append(tx.nonce)
gasPrice: tx.gasPrice, w.append(tx.gasPrice)
gasLimit: tx.gasLimit, w.append(tx.gasLimit)
to: tx.to, w.append(tx.to)
value: tx.value, w.append(tx.value)
payload: tx.payload, w.append(tx.payload)
isContractCreation: tx.isContractCreation, w.append(chainId)
V: V, w.append(0)
R: 0.u256, w.append(0)
S: 0.u256 w.finish()
))
func rlpEncode*(tx: AccessListTx): auto = func rlpEncodeEip2930(tx: Transaction): auto =
# EIP 2718/2930 var w = initRlpWriter()
let unsignedTx = AccessListUnsignedTx( w.append(1)
chainId: tx.chainId, w.startList(8)
nonce: tx.nonce, w.append(tx.chainId.uint64)
gasPrice: tx.gasPrice, w.append(tx.nonce)
gasLimit: tx.gasLimit, w.append(tx.gasPrice)
to: tx.to, w.append(tx.gasLimit)
value: tx.value, w.append(tx.to)
payload: tx.payload, w.append(tx.value)
accessList: tx.accessList, w.append(tx.payload)
isContractCreation: tx.isContractCreation w.append(tx.accessList)
) w.finish()
var rw = initRlpWriter()
rw.append(1)
rw.append(unsignedTx)
rw.finish()
func txHashNoSignature*(tx: LegacyTx): Hash256 = func rlpEncodeEip1559(tx: Transaction): auto =
# Hash transaction without signature var w = initRlpWriter()
keccak256.digest(if tx.V >= EIP155_CHAIN_ID_OFFSET: tx.rlpEncodeEIP155 else: tx.rlpEncode) w.append(2)
w.startList(9)
w.append(tx.chainId.uint64)
w.append(tx.nonce)
w.append(tx.maxPriorityFee)
w.append(tx.maxFee)
w.append(tx.gasLimit)
w.append(tx.to)
w.append(tx.value)
w.append(tx.payload)
w.append(tx.accessList)
w.finish()
func txHashNoSignature*(tx: AccessListTx): Hash256 = func rlpEncode*(tx: Transaction): auto =
keccak256.digest(tx.rlpEncode) case tx.txType
of TxLegacy:
if tx.V >= EIP155_CHAIN_ID_OFFSET:
tx.rlpEncodeEIP155
else:
tx.rlpEncodeLegacy
of TxEip2930:
tx.rlpEncodeEip2930
of TxEip1559:
tx.rlpEncodeEip1559
func txHashNoSignature*(tx: Transaction): Hash256 = func txHashNoSignature*(tx: Transaction): Hash256 =
if tx.txType == LegacyTxType: # Hash transaction without signature
txHashNoSignature(tx.legacyTx) keccak256.digest(rlpEncode(tx))
else:
txHashNoSignature(tx.accessListTx)

View File

@ -9,33 +9,9 @@ type
EthHeader = object EthHeader = object
header: BlockHeader header: BlockHeader
proc `==`(a, b: HashOrStatus): bool =
result = a.isHash == b.isHash
if not result: return
if a.isHash:
result = result and a.hash == b.hash
else:
result = result and a.status == b.status
func `==`(a, b: ChainId): bool = func `==`(a, b: ChainId): bool =
a.uint64 == b.uint64 a.uint64 == b.uint64
func `==`(a, b: Transaction): bool =
if a.txType != b.txType:
return false
if a.txType == LegacyTxType:
return a.legacyTx == b.legacyTx
else:
return a.accessListTx == b.accessListTx
func `==`(a, b: Receipt): bool =
if a.receiptType != b.receiptType:
return false
if a.receiptType == LegacyReceiptType:
return a.legacyReceipt == b.legacyReceipt
else:
return a.accessListReceipt == b.accessListReceipt
proc loadFile(x: int) = proc loadFile(x: int) =
let fileName = "tests" / "rlp" / "eip2718" / "acl_block_" & $x & ".json" let fileName = "tests" / "rlp" / "eip2718" / "acl_block_" & $x & ".json"
test fileName: test fileName:
@ -62,21 +38,19 @@ proc suite1() =
suite "rlp encoding": suite "rlp encoding":
test "receipt roundtrip": test "receipt roundtrip":
let a = Receipt( let a = Receipt(
receiptType: LegacyReceiptType, receiptType: LegacyReceipt,
legacyReceipt: LegacyReceipt( isHash: false,
stateRootOrStatus: hashOrStatus(true), status: false,
cumulativeGasUsed: 51000 cumulativeGasUsed: 51000
) )
)
let hash = rlpHash(a) let hash = rlpHash(a)
let b = Receipt( let b = Receipt(
receiptType: LegacyReceiptType, receiptType: LegacyReceipt,
legacyReceipt: LegacyReceipt( isHash: true,
stateRootOrStatus: hashOrStatus(hash), hash: hash,
cumulativeGasUsed: 21000 cumulativeGasUsed: 21000
) )
)
let abytes = rlp.encode(a) let abytes = rlp.encode(a)
let bbytes = rlp.encode(b) let bbytes = rlp.encode(b)
@ -85,21 +59,17 @@ proc suite1() =
check aa == a check aa == a
check bb == b check bb == b
test "access list receipt": test "EIP 2930 receipt":
let a = Receipt( let a = Receipt(
receiptType: AccessListReceiptType, receiptType: Eip2930Receipt,
accessListReceipt: AccessListReceipt(
status: true status: true
) )
)
let b = Receipt( let b = Receipt(
receiptType: AccessListReceiptType, receiptType: Eip2930Receipt,
accessListReceipt: AccessListReceipt(
status: false, status: false,
cumulativeGasUsed: 21000 cumulativeGasUsed: 21000
) )
)
let abytes = rlp.encode(a) let abytes = rlp.encode(a)
let bbytes = rlp.encode(b) let bbytes = rlp.encode(b)
@ -113,5 +83,11 @@ proc suite2() =
for i in 0..<10: for i in 0..<10:
loadFile(i) loadFile(i)
test "rlp roundtrip EIP1559":
var h: BlockHeader
let xy = rlp.encode(h)
let hh = rlp.decode(xy, BlockHeader)
check h == hh
suite1() suite1()
suite2() suite2()