implement eip2718: transaction type envelope

also add more test cases for both tx and receipt
rlp encoding decoding
This commit is contained in:
jangko 2021-05-14 21:48:21 +07:00
parent 8890175b6a
commit 61d5327f55
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
16 changed files with 3606 additions and 261 deletions

View File

@ -8,11 +8,8 @@ export
type type
Hash256* = MDigest[256] Hash256* = MDigest[256]
EthTime* = Time EthTime* = Time
VMWord* = UInt256 VMWord* = UInt256
BlockNonce* = array[8, byte] BlockNonce* = array[8, byte]
AccountNonce* = uint64 AccountNonce* = uint64
Blob* = seq[byte] Blob* = seq[byte]
@ -33,23 +30,61 @@ type
ForkID* = tuple[crc: uint32, nextFork: uint64] ForkID* = tuple[crc: uint32, nextFork: uint64]
# EIP 2364/2124 # EIP 2364/2124
BlockNumber* = UInt256
StorageKey* = array[32, byte]
# beware that although in some cases
# chainId have identical value to networkId
# they are separate entity
ChainId* = distinct uint64
Account* = object Account* = object
nonce*: AccountNonce nonce*: AccountNonce
balance*: UInt256 balance*: UInt256
storageRoot*: Hash256 storageRoot*: Hash256
codeHash*: Hash256 codeHash*: Hash256
Transaction* = object LegacyTx* = object
accountNonce*: AccountNonce nonce* : AccountNonce
gasPrice*: GasInt gasPrice*: GasInt
gasLimit*: GasInt gasLimit*: GasInt
to* {.rlpCustomSerialization.}: EthAddress to* {.rlpCustomSerialization.}: EthAddress
value* : UInt256 value* : UInt256
payload* : Blob payload* : Blob
V*: byte V* : int64
R*, S* : UInt256 R*, S* : UInt256
isContractCreation* {.rlpIgnore.}: bool isContractCreation* {.rlpIgnore.}: bool
AccessPair* = object
address* : EthAddress
storageKeys*: seq[StorageKey]
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
LegacyTxType
AccessListTxType
Transaction* = object
case txType*: TxType
of LegacyTxType:
legacyTx*: LegacyTx
of AccessListTxType:
accessListTx*: AccessListTx
TransactionStatus* = enum TransactionStatus* = enum
Unknown, Unknown,
Queued, Queued,
@ -61,8 +96,6 @@ type
status*: TransactionStatus status*: TransactionStatus
data*: Blob data*: Blob
BlockNumber* = UInt256
BlockHeader* = object BlockHeader* = object
parentHash*: Hash256 parentHash*: Hash256
ommersHash*: Hash256 ommersHash*: Hash256
@ -96,24 +129,33 @@ type
else: else:
status*: bool status*: bool
Receipt* = object LegacyReceipt* = object
stateRootOrStatus*: HashOrStatus stateRootOrStatus*: HashOrStatus
cumulativeGasUsed*: GasInt cumulativeGasUsed*: GasInt
bloom*: BloomFilter bloom*: BloomFilter
logs* : seq[Log] logs* : seq[Log]
AccessList* = object AccessListReceipt* = object
# XXX: Specify the structure of this status*: bool
cumulativeGasUsed*: GasInt
bloom* : BloomFilter
logs* : seq[Log]
ShardTransaction* = object ReceiptType* = enum
chain*: uint LegacyReceiptType
shard*: uint AccessListReceiptType
to*: EthAddress
data*: Blob Receipt* = object
gas*: GasInt case receiptType*: ReceiptType
accessList*: AccessList of LegacyReceiptType:
code*: Blob legacyReceipt*: LegacyReceipt
salt*: Hash256 of AccessListReceiptType:
accessListReceipt*: AccessListReceipt
EthBlock* = object
header*: BlockHeader
txs* : seq[Transaction]
uncles*: seq[BlockHeader]
CollationHeader* = object CollationHeader* = object
shard*: uint shard*: uint
@ -232,17 +274,17 @@ proc hashOrStatus*(hash: Hash256): HashOrStatus =
proc hashOrStatus*(status: bool): HashOrStatus = proc hashOrStatus*(status: bool): HashOrStatus =
HashOrStatus(isHash: false, status: status) HashOrStatus(isHash: false, status: status)
proc hasStatus*(rec: Receipt): bool {.inline.} = proc hasStatus*(rec: LegacyReceipt): bool {.inline.} =
rec.stateRootOrStatus.isHash == false rec.stateRootOrStatus.isHash == false
proc hasStateRoot*(rec: Receipt): bool {.inline.} = proc hasStateRoot*(rec: LegacyReceipt): bool {.inline.} =
rec.stateRootOrStatus.isHash == true rec.stateRootOrStatus.isHash == true
proc stateRoot*(rec: Receipt): Hash256 {.inline.} = proc stateRoot*(rec: LegacyReceipt): Hash256 {.inline.} =
doAssert(rec.hasStateRoot) doAssert(rec.hasStateRoot)
rec.stateRootOrStatus.hash rec.stateRootOrStatus.hash
proc status*(rec: Receipt): int {.inline.} = proc status*(rec: LegacyReceipt): int {.inline.} =
doAssert(rec.hasStatus) doAssert(rec.hasStatus)
if rec.stateRootOrStatus.status: 1 else: 0 if rec.stateRootOrStatus.status: 1 else: 0
@ -250,7 +292,7 @@ proc status*(rec: Receipt): int {.inline.} =
# Rlp serialization: # Rlp serialization:
# #
proc read*(rlp: var Rlp, T: typedesc[StUint]): T {.inline.} = proc read*(rlp: var Rlp, T: type StUint): T {.inline.} =
if rlp.isBlob: if rlp.isBlob:
let bytes = rlp.toBytes let bytes = rlp.toBytes
if bytes.len > 0: if bytes.len > 0:
@ -275,7 +317,7 @@ proc append*(rlpWriter: var RlpWriter, value: StUint) =
else: else:
rlpWriter.append(value.truncate(int)) rlpWriter.append(value.truncate(int))
proc read*(rlp: var Rlp, T: typedesc[Stint]): T {.inline.} = proc read*(rlp: var Rlp, T: type Stint): T {.inline.} =
# The Ethereum Yellow Paper defines the RLP serialization only # The Ethereum Yellow Paper defines the RLP serialization only
# for unsigned integers: # for unsigned integers:
{.fatal: "RLP serialization of signed integers is not allowed".} {.fatal: "RLP serialization of signed integers is not allowed".}
@ -287,20 +329,53 @@ 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
proc read*(rlp: var Rlp, t: var Transaction, _: type EthAddress): EthAddress {.inline.} = type
TxTypes = LegacyTx | AccessListTx
proc read*(rlp: var Rlp, t: var TxTypes, _: type EthAddress): EthAddress {.inline.} =
if rlp.blobLen != 0: if rlp.blobLen != 0:
result = rlp.read(EthAddress) result = rlp.read(EthAddress)
else: else:
t.isContractCreation = true t.isContractCreation = true
rlp.skipElem() rlp.skipElem()
proc append*(rlpWriter: var RlpWriter, t: Transaction, a: EthAddress) {.inline.} = proc append*(rlpWriter: var RlpWriter, t: TxTypes, a: EthAddress) {.inline.} =
if t.isContractCreation: if t.isContractCreation:
rlpWriter.append("") rlpWriter.append("")
else: else:
rlpWriter.append(a) rlpWriter.append(a)
proc read*(rlp: var Rlp, T: typedesc[HashOrStatus]): T {.inline.} = proc read*(rlp: var Rlp, t: var AccessListTx, _: type ChainId): ChainId {.inline.} =
rlp.read(uint64).ChainId
proc append*(rlpWriter: var RlpWriter, t: AccessListTx, a: ChainId) {.inline.} =
rlpWriter.append(a.uint64)
proc append*(rlpWriter: var RlpWriter, tx: Transaction) =
if tx.txType == LegacyTxType:
rlpWriter.append(tx.legacyTx)
else:
var rw = initRlpWriter()
rw.append(1)
rw.append(tx.accessListTx)
rlpWriter.append(rw.finish())
proc read*(rlp: var Rlp, T: type Transaction): T =
if rlp.isList:
result = Transaction(
txType: LegacyTxType,
legacyTx: rlp.read(LegacyTx)
)
else:
let bytes = rlp.read(Blob)
var rr = rlpFromBytes(bytes)
assert(rr.read(int) == 1)
result = Transaction(
txType: AccessListTxType,
accessListTx: rr.read(AccessListTx)
)
proc read*(rlp: var Rlp, T: type HashOrStatus): T {.inline.} =
if rlp.isBlob() and (rlp.blobLen() == 32 or rlp.blobLen() == 1): if rlp.isBlob() and (rlp.blobLen() == 32 or rlp.blobLen() == 1):
if rlp.blobLen == 1: if rlp.blobLen == 1:
result = hashOrStatus(rlp.read(uint8) == 1) result = hashOrStatus(rlp.read(uint8) == 1)
@ -334,7 +409,31 @@ proc append*(rlpWriter: var RlpWriter, value: HashOrStatus) {.inline.} =
else: else:
rlpWriter.append(if value.status: 1'u8 else: 0'u8) rlpWriter.append(if value.status: 1'u8 else: 0'u8)
proc read*(rlp: var Rlp, T: typedesc[Time]): T {.inline.} = proc append*(rlpWriter: var RlpWriter, rec: Receipt) =
if rec.receiptType == LegacyReceiptType:
rlpWriter.append(rec.legacyReceipt)
else:
var rw = initRlpWriter()
rw.append(1)
rw.append(rec.accessListReceipt)
rlpWriter.append(rw.finish())
proc read*(rlp: var Rlp, T: type Receipt): T =
if rlp.isList:
result = Receipt(
receiptType: LegacyReceiptType,
legacyReceipt: rlp.read(LegacyReceipt)
)
else:
let bytes = rlp.read(Blob)
var rr = rlpFromBytes(bytes)
assert(rr.read(int) == 1)
result = Receipt(
receiptType: AccessListReceiptType,
accessListReceipt: rr.read(AccessListReceipt)
)
proc read*(rlp: var Rlp, T: type Time): T {.inline.} =
result = fromUnix(rlp.read(int64)) result = fromUnix(rlp.read(int64))
proc append*(rlpWriter: var RlpWriter, value: HashOrNum) = proc append*(rlpWriter: var RlpWriter, value: HashOrNum) =
@ -344,7 +443,7 @@ proc append*(rlpWriter: var RlpWriter, value: HashOrNum) =
else: else:
rlpWriter.append(value.number) rlpWriter.append(value.number)
proc read*(rlp: var Rlp, T: typedesc[HashOrNum]): T = proc read*(rlp: var Rlp, T: type HashOrNum): T =
if rlp.blobLen == 32: if rlp.blobLen == 32:
result = HashOrNum(isHash: true, hash: rlp.read(Hash256)) result = HashOrNum(isHash: true, hash: rlp.read(Hash256))
else: else:

View File

@ -2,8 +2,8 @@ import
nimcrypto/keccak, nimcrypto/keccak,
".."/[common, rlp, keys] ".."/[common, rlp, keys]
proc initTransaction*(nonce: AccountNonce, gasPrice, gasLimit: GasInt, to: EthAddress, proc initLegacyTx*(nonce: AccountNonce, gasPrice, gasLimit: GasInt, to: EthAddress,
value: UInt256, payload: Blob, V: byte, R, S: UInt256, isContractCreation = false): Transaction = value: UInt256, payload: Blob, V: uint64, R, S: UInt256, isContractCreation = false): LegacyTx =
result.accountNonce = nonce result.accountNonce = nonce
result.gasPrice = gasPrice result.gasPrice = gasPrice
result.gasLimit = gasLimit result.gasLimit = gasLimit
@ -40,7 +40,7 @@ proc append(rlpWriter: var RlpWriter, t: TransHashObj, a: EthAddress) {.inline.}
const const
EIP155_CHAIN_ID_OFFSET* = 35 EIP155_CHAIN_ID_OFFSET* = 35
func rlpEncode*(transaction: Transaction): auto = func rlpEncode*(transaction: LegacyTx): auto =
# Encode transaction without signature # Encode transaction without signature
return rlp.encode(TransHashObj( return rlp.encode(TransHashObj(
accountNonce: transaction.accountNonce, accountNonce: transaction.accountNonce,
@ -52,7 +52,7 @@ func rlpEncode*(transaction: Transaction): auto =
mIsContractCreation: transaction.isContractCreation mIsContractCreation: transaction.isContractCreation
)) ))
func rlpEncodeEIP155*(tx: Transaction): auto = func rlpEncodeEIP155*(tx: LegacyTx): auto =
let V = (tx.V.int - EIP155_CHAIN_ID_OFFSET) div 2 let V = (tx.V.int - EIP155_CHAIN_ID_OFFSET) div 2
# Encode transaction without signature # Encode transaction without signature
return rlp.encode(Transaction( return rlp.encode(Transaction(
@ -63,11 +63,11 @@ func rlpEncodeEIP155*(tx: Transaction): auto =
value: tx.value, value: tx.value,
payload: tx.payload, payload: tx.payload,
isContractCreation: tx.isContractCreation, isContractCreation: tx.isContractCreation,
V: V.byte, V: V.uint64,
R: 0.u256, R: 0.u256,
S: 0.u256 S: 0.u256
)) ))
func txHashNoSignature*(tx: Transaction): Hash256 = func txHashNoSignature*(tx: LegacyTx): Hash256 =
# Hash transaction without signature # Hash transaction without signature
return keccak256.digest(if tx.V.int >= EIP155_CHAIN_ID_OFFSET: tx.rlpEncodeEIP155 else: tx.rlpEncode) return keccak256.digest(if tx.V.int >= EIP155_CHAIN_ID_OFFSET: tx.rlpEncodeEIP155 else: tx.rlpEncode)

View File

@ -0,0 +1,42 @@
{
"rlp": "f90263f901f5a0151b04645af991f513d5e11f8ed62e12b73f080af9c7a6a3d98fd6b1503f23faa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0968408b8a2f170bc78230cc2fac3881120a93f7392cf26b609566d8648abfd79a0e8137f2b67ac4680d8103f8b1cd7c05c49f56e4df464b0a79253679f38df9ab4a07f53535270d749f41b9d783aa1abcfceb73cc2a16ecde789cd3bc97a42fbda2ab901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018347e7c48262740a80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f868f866800a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec88a0e7545c5664e63873d7aeb4bb5f92152c3366a9095c9140e5f8453af0998194bea04d24143ac9bc97c0aa07a7074c12ab60484d83d3b447b1e5e6ba5cbf421675bfc0",
"json": {
"header": {
"parentHash": "0x151b04645af991f513d5e11f8ed62e12b73f080af9c7a6a3d98fd6b1503f23fa",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"miner": "0x0100000000000000000000000000000000000000",
"stateRoot": "0x968408b8a2f170bc78230cc2fac3881120a93f7392cf26b609566d8648abfd79",
"transactionsRoot": "0xe8137f2b67ac4680d8103f8b1cd7c05c49f56e4df464b0a79253679f38df9ab4",
"receiptsRoot": "0x7f53535270d749f41b9d783aa1abcfceb73cc2a16ecde789cd3bc97a42fbda2a",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"difficulty": "0x20000",
"number": "0x1",
"gasLimit": "0x47e7c4",
"gasUsed": "0x6274",
"timestamp": "0xa",
"extraData": "0x",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"hash": "0x9aa9cdb2afc4ebf893c32b67dedf1dea4291673bf4e80d3227a4e7f8d0feaf68"
},
"transactions": [
{
"type": "0x0",
"chainId": null,
"nonce": "0x0",
"gasPrice": "0xa",
"gas": "0x1e241",
"to": "0x000000000000000000000000000000000000aaaa",
"value": "0x0",
"input": "0x",
"accessList": null,
"v": "0xf2ded8deec88",
"r": "0xe7545c5664e63873d7aeb4bb5f92152c3366a9095c9140e5f8453af0998194be",
"s": "0x4d24143ac9bc97c0aa07a7074c12ab60484d83d3b447b1e5e6ba5cbf421675bf",
"hash": "0x7e122173adcc02b9a3c94da426f65c7d46e724e8e3fdb16be73d5e0405e280b6"
}
],
"uncles": null,
"receipts": null
}
}

View File

@ -0,0 +1,65 @@
{
"rlp": "f9032df901f5a09aa9cdb2afc4ebf893c32b67dedf1dea4291673bf4e80d3227a4e7f8d0feaf68a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0fb70f6c0512e7979903607bba8a4f1b18c2dd1060a8eff1b777a2182d05af524a0dfcad019a36acdf0f3fac6b3db02bf1d70012a0bd3eadabea87b856be9a6f1cca0a7a57ba954834e69b55d9115305f14f7faff9beb83443f7bb5526585848c6aefb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000028347e7c482dd201480a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f90131b8c701f8c486796f6c6f7632010a8301e24194000000000000000000000000000000000000aaaa8080f85bf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000001a0a9efa6b5fd3c2f210c4ec7232058d8dd30c93a456b4f6074429fb09bbd73eb4fa070632eff8bf0933381917c9161a98494e34fc7b836ee150445cae9ab151d267bf866020a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec88a055a39da3ce02c75e976ad84f608771080811a5ef322c6b6536c362f716c60985a018ab5df4198436eacd0e991f59bdeb8da9a75c678067db6b1a4d07881555c7a8c0",
"json": {
"header": {
"parentHash": "0x9aa9cdb2afc4ebf893c32b67dedf1dea4291673bf4e80d3227a4e7f8d0feaf68",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"miner": "0x0100000000000000000000000000000000000000",
"stateRoot": "0xfb70f6c0512e7979903607bba8a4f1b18c2dd1060a8eff1b777a2182d05af524",
"transactionsRoot": "0xdfcad019a36acdf0f3fac6b3db02bf1d70012a0bd3eadabea87b856be9a6f1cc",
"receiptsRoot": "0xa7a57ba954834e69b55d9115305f14f7faff9beb83443f7bb5526585848c6aef",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"difficulty": "0x20000",
"number": "0x2",
"gasLimit": "0x47e7c4",
"gasUsed": "0xdd20",
"timestamp": "0x14",
"extraData": "0x",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"hash": "0xe1807e7366284bc72d34c8f02318f81c6598454dbff4c6cdd71e872cd8d5748c"
},
"transactions": [
{
"type": "0x1",
"chainId": "0x796f6c6f7632",
"nonce": "0x1",
"gasPrice": "0xa",
"gas": "0x1e241",
"to": "0x000000000000000000000000000000000000aaaa",
"value": "0x0",
"input": "0x",
"accessList": [
{
"address": "0x0000000000000000000000000000000000000000",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000"
]
}
],
"v": "0x1",
"r": "0xa9efa6b5fd3c2f210c4ec7232058d8dd30c93a456b4f6074429fb09bbd73eb4f",
"s": "0x70632eff8bf0933381917c9161a98494e34fc7b836ee150445cae9ab151d267b",
"hash": "0x1916413ac8d1d5ee4eda786e5fe29509a109910f800894e0e18eb84abb7564cb"
},
{
"type": "0x0",
"chainId": null,
"nonce": "0x2",
"gasPrice": "0xa",
"gas": "0x1e241",
"to": "0x000000000000000000000000000000000000aaaa",
"value": "0x0",
"input": "0x",
"accessList": null,
"v": "0xf2ded8deec88",
"r": "0x55a39da3ce02c75e976ad84f608771080811a5ef322c6b6536c362f716c60985",
"s": "0x18ab5df4198436eacd0e991f59bdeb8da9a75c678067db6b1a4d07881555c7a8",
"hash": "0x54c6cfb51cbbe2c562e17a0d6ee1324f1b50013a9b9d47589cedcf0ec4ac342a"
}
],
"uncles": null,
"receipts": null
}
}

View File

@ -0,0 +1,102 @@
{
"rlp": "f904b1f901f6a0e1807e7366284bc72d34c8f02318f81c6598454dbff4c6cdd71e872cd8d5748ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a025e5b4b7668760c0aa01d44c061d77e24b53f6d247d3e1d85a91e23646c1d679a0be53a36dd90786b4cd30fb0f3677ad3ce5f804a5615872a7b0512b6be82639a2a076946d9f034a6657c6832a6ad4df3ef0ddf3fa9f3f8be98ea64880fb23bd23e3b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000038347e7c48301883c1e80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f902b4b9012301f9011f86796f6c6f7632030a8301e24194000000000000000000000000000000000000aaaa8080f8b6f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0010000000000000000000000000000000000000000000000000000000000000001a0635c44b8110989ef84c77de11a377f19cbd84660559ed76b37ba0f7fdee1fb40a012e1576d168301614720c68f1a9e9d5ed20e23622dab6c3587b11177155d59f4b9012301f9011f86796f6c6f7632040a8301e24194000000000000000000000000000000000000aaaa8080f8b6f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0010000000000000000000000000000000000000000000000000000000000000001a00380e446bf3992ee1df44b8177a11e948dc52cc3faa8eae059a52b7183126c0fa05206f0f35648d3b8f23092d4d7bdccb926967d840a269cf65b706a8a359b9029f866050a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec87a0ea5de382dbf422aa1bd156547a2bc3a9357d745a68cdc9203b14812307068567a0388f7425b873ae204d43d91f4997ca41d2af6759be49538b174a06f67d5741b5c0",
"json": {
"header": {
"parentHash": "0xe1807e7366284bc72d34c8f02318f81c6598454dbff4c6cdd71e872cd8d5748c",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"miner": "0x0100000000000000000000000000000000000000",
"stateRoot": "0x25e5b4b7668760c0aa01d44c061d77e24b53f6d247d3e1d85a91e23646c1d679",
"transactionsRoot": "0xbe53a36dd90786b4cd30fb0f3677ad3ce5f804a5615872a7b0512b6be82639a2",
"receiptsRoot": "0x76946d9f034a6657c6832a6ad4df3ef0ddf3fa9f3f8be98ea64880fb23bd23e3",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"difficulty": "0x20000",
"number": "0x3",
"gasLimit": "0x47e7c4",
"gasUsed": "0x1883c",
"timestamp": "0x1e",
"extraData": "0x",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"hash": "0x1615129d2aa7b437cd40e3aa1a5794af9e40b07b9b017014e4123cefeef785ce"
},
"transactions": [
{
"type": "0x1",
"chainId": "0x796f6c6f7632",
"nonce": "0x3",
"gasPrice": "0xa",
"gas": "0x1e241",
"to": "0x000000000000000000000000000000000000aaaa",
"value": "0x0",
"input": "0x",
"accessList": [
{
"address": "0x0000000000000000000000000000000000000000",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"address": "0x0100000000000000000000000000000000000000",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0100000000000000000000000000000000000000000000000000000000000000"
]
}
],
"v": "0x1",
"r": "0x635c44b8110989ef84c77de11a377f19cbd84660559ed76b37ba0f7fdee1fb40",
"s": "0x12e1576d168301614720c68f1a9e9d5ed20e23622dab6c3587b11177155d59f4",
"hash": "0x54471f503901f2c2fe392e43df0377a11f9a1cd9cde0ec5c68c89eac1723e02a"
},
{
"type": "0x1",
"chainId": "0x796f6c6f7632",
"nonce": "0x4",
"gasPrice": "0xa",
"gas": "0x1e241",
"to": "0x000000000000000000000000000000000000aaaa",
"value": "0x0",
"input": "0x",
"accessList": [
{
"address": "0x0000000000000000000000000000000000000000",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"address": "0x0100000000000000000000000000000000000000",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0100000000000000000000000000000000000000000000000000000000000000"
]
}
],
"v": "0x1",
"r": "0x380e446bf3992ee1df44b8177a11e948dc52cc3faa8eae059a52b7183126c0f",
"s": "0x5206f0f35648d3b8f23092d4d7bdccb926967d840a269cf65b706a8a359b9029",
"hash": "0xe3a1354e84d22ebbca0c55751937b075083f0f0e3a47c65fc7249d86f872f268"
},
{
"type": "0x0",
"chainId": null,
"nonce": "0x5",
"gasPrice": "0xa",
"gas": "0x1e241",
"to": "0x000000000000000000000000000000000000aaaa",
"value": "0x0",
"input": "0x",
"accessList": null,
"v": "0xf2ded8deec87",
"r": "0xea5de382dbf422aa1bd156547a2bc3a9357d745a68cdc9203b14812307068567",
"s": "0x388f7425b873ae204d43d91f4997ca41d2af6759be49538b174a06f67d5741b5",
"hash": "0x44b1e9999ac02a3b0daf1391be16bb00a262079706418697094bab5f37b522d7"
}
],
"uncles": null,
"receipts": null
}
}

View File

@ -0,0 +1,153 @@
{
"rlp": "f906ebf901f6a01615129d2aa7b437cd40e3aa1a5794af9e40b07b9b017014e4123cefeef785cea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0e2c895d53740e942c84623e1612189e72eea9e767b150cc0d8802b490f2574b2a060b6fa13cd50ea3732f59eb726368639dea2006ab4b67dc5730ea27b0cd75732a058ac726e0fc55cd550539c38baf3f6023615e2657ceedccc21ce7edd6516bc31b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000048347e7c4830263c82880a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f904eeb9017f01f9017b86796f6c6f7632060a8301e24194000000000000000000000000000000000000aaaa8080f90111f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0020000000000000000000000000000000000000000000000000000000000000001a0587b3fd59a84469be7c918ae73047141027d27c47cc63f3cf13c6161bf92efaaa0453d3cd2dffd1f048a58fb1046917327f5e95cc8aedc47f82d41bffebfe31bbdb9017f01f9017b86796f6c6f7632070a8301e24194000000000000000000000000000000000000aaaa8080f90111f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0020000000000000000000000000000000000000000000000000000000000000080a0b1944f4797bf4da4d041a66be9c41c317b40d158894103ccd50de5e4ca174b4aa079d6834c013b40d0039ca6755cecc72938461e5b8cd8d3619ddcdfb15c15b866b9017f01f9017b86796f6c6f7632080a8301e24194000000000000000000000000000000000000aaaa8080f90111f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0020000000000000000000000000000000000000000000000000000000000000001a0793cd38309611e0117269275243fc3761fe233dc371918e450b547c70132c033a07276d4b20788938ca0ff7e4e921aec7739103dc73d3b953f47947ef194720757f866090a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec88a0a6528544064aef10d166e16d3968ae83aa29161beb57f2756dfd1151682adbe7a0507fe2d475ffab209e718345a3ad9fb20fee6e15a8c4980df3ed8ff0a714367ac0",
"json": {
"header": {
"parentHash": "0x1615129d2aa7b437cd40e3aa1a5794af9e40b07b9b017014e4123cefeef785ce",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"miner": "0x0100000000000000000000000000000000000000",
"stateRoot": "0xe2c895d53740e942c84623e1612189e72eea9e767b150cc0d8802b490f2574b2",
"transactionsRoot": "0x60b6fa13cd50ea3732f59eb726368639dea2006ab4b67dc5730ea27b0cd75732",
"receiptsRoot": "0x58ac726e0fc55cd550539c38baf3f6023615e2657ceedccc21ce7edd6516bc31",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"difficulty": "0x20000",
"number": "0x4",
"gasLimit": "0x47e7c4",
"gasUsed": "0x263c8",
"timestamp": "0x28",
"extraData": "0x",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"hash": "0xc6340ac0a1b76cae78479a4bc6211031550719fa9b58ae42d773dce7ff7409ce"
},
"transactions": [
{
"type": "0x1",
"chainId": "0x796f6c6f7632",
"nonce": "0x6",
"gasPrice": "0xa",
"gas": "0x1e241",
"to": "0x000000000000000000000000000000000000aaaa",
"value": "0x0",
"input": "0x",
"accessList": [
{
"address": "0x0000000000000000000000000000000000000000",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"address": "0x0100000000000000000000000000000000000000",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0100000000000000000000000000000000000000000000000000000000000000"
]
},
{
"address": "0x0200000000000000000000000000000000000000",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0200000000000000000000000000000000000000000000000000000000000000"
]
}
],
"v": "0x1",
"r": "0x587b3fd59a84469be7c918ae73047141027d27c47cc63f3cf13c6161bf92efaa",
"s": "0x453d3cd2dffd1f048a58fb1046917327f5e95cc8aedc47f82d41bffebfe31bbd",
"hash": "0xbc9b06b5d31e6e257a3c25048e935ba433c68fdd5fa5d0ddd726d5ab7356aafd"
},
{
"type": "0x1",
"chainId": "0x796f6c6f7632",
"nonce": "0x7",
"gasPrice": "0xa",
"gas": "0x1e241",
"to": "0x000000000000000000000000000000000000aaaa",
"value": "0x0",
"input": "0x",
"accessList": [
{
"address": "0x0000000000000000000000000000000000000000",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"address": "0x0100000000000000000000000000000000000000",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0100000000000000000000000000000000000000000000000000000000000000"
]
},
{
"address": "0x0200000000000000000000000000000000000000",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0200000000000000000000000000000000000000000000000000000000000000"
]
}
],
"v": "0x0",
"r": "0xb1944f4797bf4da4d041a66be9c41c317b40d158894103ccd50de5e4ca174b4a",
"s": "0x79d6834c013b40d0039ca6755cecc72938461e5b8cd8d3619ddcdfb15c15b866",
"hash": "0x474ec2766068f9e9d0548aca3769ca406fdde21ba87c254d9230c18be35fe99a"
},
{
"type": "0x1",
"chainId": "0x796f6c6f7632",
"nonce": "0x8",
"gasPrice": "0xa",
"gas": "0x1e241",
"to": "0x000000000000000000000000000000000000aaaa",
"value": "0x0",
"input": "0x",
"accessList": [
{
"address": "0x0000000000000000000000000000000000000000",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"address": "0x0100000000000000000000000000000000000000",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0100000000000000000000000000000000000000000000000000000000000000"
]
},
{
"address": "0x0200000000000000000000000000000000000000",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0200000000000000000000000000000000000000000000000000000000000000"
]
}
],
"v": "0x1",
"r": "0x793cd38309611e0117269275243fc3761fe233dc371918e450b547c70132c033",
"s": "0x7276d4b20788938ca0ff7e4e921aec7739103dc73d3b953f47947ef194720757",
"hash": "0xe46963eb63cd75a120990ca597532020bc2dcefc4588025c0d50901681a7aae9"
},
{
"type": "0x0",
"chainId": null,
"nonce": "0x9",
"gasPrice": "0xa",
"gas": "0x1e241",
"to": "0x000000000000000000000000000000000000aaaa",
"value": "0x0",
"input": "0x",
"accessList": null,
"v": "0xf2ded8deec88",
"r": "0xa6528544064aef10d166e16d3968ae83aa29161beb57f2756dfd1151682adbe7",
"s": "0x507fe2d475ffab209e718345a3ad9fb20fee6e15a8c4980df3ed8ff0a714367a",
"hash": "0x61fc16fea6b57d81f269e733cdd15d994bbc10dc6e9b0acbedbe32e6fe70a06c"
}
],
"uncles": null,
"receipts": null
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,39 @@
{
"config": {
"chainId": 133519467574834,
"homesteadBlock": 0,
"daoForkSupport": true,
"eip150Block": 0,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"yoloV2Block": 0,
"clique": {
"period": 15,
"epoch": 30000
}
},
"nonce": "0x0",
"timestamp": "0x0",
"extraData": "0x",
"gasLimit": "0x0",
"difficulty": null,
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"000000000000000000000000000000000000aaaa": {
"code": "0x58585454",
"balance": "0x0"
},
"71562b71999873db5b286df957af199ec94617f7": {
"balance": "0x3b9aca00"
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}

View File

@ -9,6 +9,8 @@ proc q(s: string): string = "\"" & s & "\""
proc i(s: string): string = s.replace(" ").replace("\n") proc i(s: string): string = s.replace(" ").replace("\n")
proc inspectMatch(r: Rlp, s: string): bool = r.inspect.i == s.i proc inspectMatch(r: Rlp, s: string): bool = r.inspect.i == s.i
proc suite() =
suite "test api usage":
test "empty bytes are not a proper RLP": test "empty bytes are not a proper RLP":
var rlp = rlpFromBytes seq[byte](@[]) var rlp = rlpFromBytes seq[byte](@[])
@ -211,3 +213,5 @@ test "invalid enum":
rlp.skipElem() rlp.skipElem()
expect RlpTypeMismatch: expect RlpTypeMismatch:
discard rlp.read(MyEnum) discard rlp.read(MyEnum)
suite()

View File

@ -1,7 +1,8 @@
{.used.} {.used.}
import import
std/unittest, std/[unittest, os, json],
stew/byteutils,
../../eth/[common, rlp] ../../eth/[common, rlp]
proc `==`(a, b: HashOrStatus): bool = proc `==`(a, b: HashOrStatus): bool =
@ -12,29 +13,92 @@ proc `==`(a, b: HashOrStatus): bool =
else: else:
result = result and a.status == b.status result = result and a.status == b.status
func `==`(a, b: ChainId): bool =
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) =
let fileName = "tests" / "rlp" / "eip2718" / "acl_block_" & $x & ".json"
test fileName:
let n = json.parseFile(fileName)
let data = n["rlp"].getStr()
var bytes = hexToSeqByte(data)
var blk = rlp.decode(bytes, EthBlock)
let rlpbytes = rlp.encode(blk)
var blk2 = rlp.decode(rlpbytes, EthBlock)
check blk == blk2
check bytes == rlpbytes
proc suite1() =
suite "rlp encoding": suite "rlp encoding":
test "receipt roundtrip": test "receipt roundtrip":
var a, b, c, d: Receipt let a = Receipt(
receiptType: LegacyReceiptType,
legacyReceipt: LegacyReceipt(
stateRootOrStatus: hashOrStatus(true),
cumulativeGasUsed: 51000
)
)
var hash = rlpHash(a) let hash = rlpHash(a)
a.stateRootOrStatus = hashOrStatus(hash) let b = Receipt(
a.cumulativeGasUsed = 21000 receiptType: LegacyReceiptType,
a.logs = @[] legacyReceipt: LegacyReceipt(
stateRootOrStatus: hashOrStatus(hash),
cumulativeGasUsed: 21000
)
)
b.stateRootOrStatus = hashOrStatus(true) let abytes = rlp.encode(a)
b.cumulativeGasUsed = 52000 let bbytes = rlp.encode(b)
b.logs = @[] let aa = rlp.decode(abytes, Receipt)
let bb = rlp.decode(bbytes, Receipt)
check aa == a
check bb == b
var x = rlp.encode(a) test "access list receipt":
var y = rlp.encode(b) let a = Receipt(
receiptType: AccessListReceiptType,
accessListReceipt: AccessListReceipt(
status: true
)
)
c = x.decode(Receipt) let b = Receipt(
d = y.decode(Receipt) receiptType: AccessListReceiptType,
check c == a accessListReceipt: AccessListReceipt(
check d == b status: false,
cumulativeGasUsed: 21000
)
)
check c.hasStateRoot let abytes = rlp.encode(a)
check c.stateRoot == hash let bbytes = rlp.encode(b)
check d.hasStatus let aa = rlp.decode(abytes, Receipt)
check d.status == 1 let bb = rlp.decode(bbytes, Receipt)
check aa == a
check bb == b
proc suite2() =
suite "eip 2718 transaction":
for i in 0..<10:
loadFile(i)
suite1()
suite2()

View File

@ -43,6 +43,8 @@ proc read*(rlp: var Rlp, holder: var CustomSerialized, T: type Foo): Foo =
result.y = newString(rlp.read(int)) result.y = newString(rlp.read(int))
holder.ignored = rlp.read(int) * 2 holder.ignored = rlp.read(int) * 2
proc suite() =
suite "object serialization":
test "encoding and decoding an object": test "encoding and decoding an object":
var originalBar = Bar(b: "abracadabra", var originalBar = Bar(b: "abracadabra",
f: Foo(x: 5'u64, y: "hocus pocus", z: @[100, 200, 300])) f: Foo(x: 5'u64, y: "hocus pocus", z: @[100, 200, 300]))
@ -81,3 +83,5 @@ test "RLP fields count":
Bar.rlpFieldsCount == 2 Bar.rlpFieldsCount == 2
Foo.rlpFieldsCount == 3 Foo.rlpFieldsCount == 3
Transaction.rlpFieldsCount == 3 Transaction.rlpFieldsCount == 3
suite()