mirror of https://github.com/status-im/nim-eth.git
implement eip2718: transaction type envelope
also add more test cases for both tx and receipt rlp encoding decoding
This commit is contained in:
parent
8890175b6a
commit
61d5327f55
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
@ -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"
|
||||||
|
}
|
|
@ -9,205 +9,209 @@ 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
|
||||||
|
|
||||||
test "empty bytes are not a proper RLP":
|
proc suite() =
|
||||||
var rlp = rlpFromBytes seq[byte](@[])
|
suite "test api usage":
|
||||||
|
test "empty bytes are not a proper RLP":
|
||||||
|
var rlp = rlpFromBytes seq[byte](@[])
|
||||||
|
|
||||||
check:
|
check:
|
||||||
not rlp.hasData
|
not rlp.hasData
|
||||||
not rlp.isBlob
|
not rlp.isBlob
|
||||||
not rlp.isList
|
not rlp.isList
|
||||||
not rlp.isEmpty
|
not rlp.isEmpty
|
||||||
|
|
||||||
expect Exception:
|
expect Exception:
|
||||||
rlp.skipElem
|
rlp.skipElem
|
||||||
|
|
||||||
expect Exception:
|
expect Exception:
|
||||||
discard rlp.getType
|
discard rlp.getType
|
||||||
|
|
||||||
expect Exception:
|
expect Exception:
|
||||||
for e in rlp:
|
for e in rlp:
|
||||||
discard e.getType
|
discard e.getType
|
||||||
|
|
||||||
test "you cannot finish a list without appending enough elements":
|
test "you cannot finish a list without appending enough elements":
|
||||||
var writer = initRlpList(3)
|
var writer = initRlpList(3)
|
||||||
writer.append "foo"
|
writer.append "foo"
|
||||||
writer.append "bar"
|
writer.append "bar"
|
||||||
|
|
||||||
expect Defect:
|
expect Defect:
|
||||||
discard writer.finish
|
discard writer.finish
|
||||||
|
|
||||||
test "encode/decode object":
|
test "encode/decode object":
|
||||||
type
|
type
|
||||||
MyEnum = enum
|
MyEnum = enum
|
||||||
foo,
|
foo,
|
||||||
bar
|
bar
|
||||||
|
|
||||||
MyObj = object
|
MyObj = object
|
||||||
a: array[3, char]
|
a: array[3, char]
|
||||||
b: int
|
b: int
|
||||||
c: MyEnum
|
c: MyEnum
|
||||||
|
|
||||||
var input: MyObj
|
var input: MyObj
|
||||||
input.a = ['e', 't', 'h']
|
input.a = ['e', 't', 'h']
|
||||||
input.b = 63
|
input.b = 63
|
||||||
input.c = bar
|
input.c = bar
|
||||||
|
|
||||||
var writer = initRlpWriter()
|
var writer = initRlpWriter()
|
||||||
writer.append(input)
|
writer.append(input)
|
||||||
let bytes = writer.finish()
|
let bytes = writer.finish()
|
||||||
var rlp = rlpFromBytes(bytes)
|
var rlp = rlpFromBytes(bytes)
|
||||||
|
|
||||||
var output = rlp.read(MyObj)
|
var output = rlp.read(MyObj)
|
||||||
check:
|
check:
|
||||||
input == output
|
input == output
|
||||||
|
|
||||||
test "encode and decode lists":
|
test "encode and decode lists":
|
||||||
var writer = initRlpList(3)
|
var writer = initRlpList(3)
|
||||||
writer.append "foo"
|
writer.append "foo"
|
||||||
writer.append ["bar", "baz"]
|
writer.append ["bar", "baz"]
|
||||||
writer.append [30, 40, 50]
|
writer.append [30, 40, 50]
|
||||||
|
|
||||||
var
|
var
|
||||||
bytes = writer.finish
|
bytes = writer.finish
|
||||||
rlp = rlpFromBytes bytes
|
rlp = rlpFromBytes bytes
|
||||||
|
|
||||||
check:
|
check:
|
||||||
bytes.toHex == "d183666f6fc8836261728362617ac31e2832"
|
bytes.toHex == "d183666f6fc8836261728362617ac31e2832"
|
||||||
rlp.inspectMatch """
|
rlp.inspectMatch """
|
||||||
{
|
{
|
||||||
"foo"
|
"foo"
|
||||||
{
|
{
|
||||||
"bar"
|
"bar"
|
||||||
"baz"
|
"baz"
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
byte 30
|
byte 30
|
||||||
byte 40
|
byte 40
|
||||||
byte 50
|
byte 50
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
bytes = encodeList(6000,
|
bytes = encodeList(6000,
|
||||||
"Lorem ipsum dolor sit amet",
|
"Lorem ipsum dolor sit amet",
|
||||||
"Donec ligula tortor, egestas eu est vitae")
|
"Donec ligula tortor, egestas eu est vitae")
|
||||||
|
|
||||||
rlp = rlpFromBytes bytes
|
rlp = rlpFromBytes bytes
|
||||||
check:
|
check:
|
||||||
rlp.listLen == 3
|
rlp.listLen == 3
|
||||||
rlp.listElem(0).toInt(int) == 6000
|
rlp.listElem(0).toInt(int) == 6000
|
||||||
rlp.listElem(1).toString == "Lorem ipsum dolor sit amet"
|
rlp.listElem(1).toString == "Lorem ipsum dolor sit amet"
|
||||||
rlp.listElem(2).toString == "Donec ligula tortor, egestas eu est vitae"
|
rlp.listElem(2).toString == "Donec ligula tortor, egestas eu est vitae"
|
||||||
|
|
||||||
# test creating RLPs from other RLPs
|
# test creating RLPs from other RLPs
|
||||||
var list = rlpFromBytes encodeList(rlp.listELem(1), rlp.listELem(0))
|
var list = rlpFromBytes encodeList(rlp.listELem(1), rlp.listELem(0))
|
||||||
|
|
||||||
# test that iteration with enterList/skipElem works as expected
|
# test that iteration with enterList/skipElem works as expected
|
||||||
doAssert list.enterList # We already know that we are working with a list
|
doAssert list.enterList # We already know that we are working with a list
|
||||||
check list.toString == "Lorem ipsum dolor sit amet"
|
check list.toString == "Lorem ipsum dolor sit amet"
|
||||||
list.skipElem
|
list.skipElem
|
||||||
|
|
||||||
check list.toInt(int32) == 6000.int32
|
check list.toInt(int32) == 6000.int32
|
||||||
var intVar: int
|
var intVar: int
|
||||||
list >> intVar
|
list >> intVar
|
||||||
check intVar == 6000
|
check intVar == 6000
|
||||||
|
|
||||||
check(not list.hasData)
|
check(not list.hasData)
|
||||||
expect Exception: list.skipElem
|
expect Exception: list.skipElem
|
||||||
|
|
||||||
test "toBytes":
|
test "toBytes":
|
||||||
let rlp = rlpFromHex("f2cb847f000001827666827666a040ef02798f211da2e8173d37f255be908871ae65060dbb2f77fb29c0421447f4845ab90b50")
|
let rlp = rlpFromHex("f2cb847f000001827666827666a040ef02798f211da2e8173d37f255be908871ae65060dbb2f77fb29c0421447f4845ab90b50")
|
||||||
let tok = rlp.listElem(1).toBytes()
|
let tok = rlp.listElem(1).toBytes()
|
||||||
check:
|
check:
|
||||||
tok.len == 32
|
tok.len == 32
|
||||||
tok.toHex == "40ef02798f211da2e8173d37f255be908871ae65060dbb2f77fb29c0421447f4"
|
tok.toHex == "40ef02798f211da2e8173d37f255be908871ae65060dbb2f77fb29c0421447f4"
|
||||||
|
|
||||||
test "nested lists":
|
test "nested lists":
|
||||||
let listBytes = encode([[1, 2, 3], [5, 6, 7]])
|
let listBytes = encode([[1, 2, 3], [5, 6, 7]])
|
||||||
let listRlp = rlpFromBytes listBytes
|
let listRlp = rlpFromBytes listBytes
|
||||||
let sublistRlp0 = listRlp.listElem(0)
|
let sublistRlp0 = listRlp.listElem(0)
|
||||||
let sublistRlp1 = listRlp.listElem(1)
|
let sublistRlp1 = listRlp.listElem(1)
|
||||||
check sublistRlp0.listElem(0).toInt(int) == 1
|
check sublistRlp0.listElem(0).toInt(int) == 1
|
||||||
check sublistRlp0.listElem(1).toInt(int) == 2
|
check sublistRlp0.listElem(1).toInt(int) == 2
|
||||||
check sublistRlp0.listElem(2).toInt(int) == 3
|
check sublistRlp0.listElem(2).toInt(int) == 3
|
||||||
check sublistRlp1.listElem(0).toInt(int) == 5
|
check sublistRlp1.listElem(0).toInt(int) == 5
|
||||||
check sublistRlp1.listElem(1).toInt(int) == 6
|
check sublistRlp1.listElem(1).toInt(int) == 6
|
||||||
check sublistRlp1.listElem(2).toInt(int) == 7
|
check sublistRlp1.listElem(2).toInt(int) == 7
|
||||||
|
|
||||||
test "encoding length":
|
test "encoding length":
|
||||||
let listBytes = encode([1,2,3,4,5])
|
let listBytes = encode([1,2,3,4,5])
|
||||||
let listRlp = rlpFromBytes listBytes
|
let listRlp = rlpFromBytes listBytes
|
||||||
check listRlp.listLen == 5
|
check listRlp.listLen == 5
|
||||||
|
|
||||||
let emptyListBytes = encode ""
|
let emptyListBytes = encode ""
|
||||||
check emptyListBytes.len == 1
|
check emptyListBytes.len == 1
|
||||||
let emptyListRlp = rlpFromBytes emptyListBytes
|
let emptyListRlp = rlpFromBytes emptyListBytes
|
||||||
check emptyListRlp.blobLen == 0
|
check emptyListRlp.blobLen == 0
|
||||||
|
|
||||||
test "basic decoding":
|
test "basic decoding":
|
||||||
var rlp1 = rlpFromHex("856d6f6f7365")
|
var rlp1 = rlpFromHex("856d6f6f7365")
|
||||||
var rlp2 = rlpFromHex("0x856d6f6f7365")
|
var rlp2 = rlpFromHex("0x856d6f6f7365")
|
||||||
|
|
||||||
check:
|
check:
|
||||||
rlp1.inspect == q"moose"
|
rlp1.inspect == q"moose"
|
||||||
rlp2.inspect == q"moose"
|
rlp2.inspect == q"moose"
|
||||||
|
|
||||||
test "malformed/truncated RLP":
|
test "malformed/truncated RLP":
|
||||||
var rlp = rlpFromHex("b8056d6f6f7365")
|
var rlp = rlpFromHex("b8056d6f6f7365")
|
||||||
expect MalformedRlpError:
|
expect MalformedRlpError:
|
||||||
discard rlp.inspect
|
discard rlp.inspect
|
||||||
|
|
||||||
test "encode byte arrays":
|
test "encode byte arrays":
|
||||||
var b1 = [byte(1), 2, 5, 7, 8]
|
var b1 = [byte(1), 2, 5, 7, 8]
|
||||||
var b2 = [byte(6), 8, 12, 123]
|
var b2 = [byte(6), 8, 12, 123]
|
||||||
var b3 = @[byte(122), 56, 65, 12]
|
var b3 = @[byte(122), 56, 65, 12]
|
||||||
|
|
||||||
let rlp = rlpFromBytes(encode((b1, b2, b3)))
|
let rlp = rlpFromBytes(encode((b1, b2, b3)))
|
||||||
check:
|
check:
|
||||||
rlp.listLen == 3
|
rlp.listLen == 3
|
||||||
rlp.listElem(0).toBytes() == b1
|
rlp.listElem(0).toBytes() == b1
|
||||||
rlp.listElem(1).toBytes() == b2
|
rlp.listElem(1).toBytes() == b2
|
||||||
rlp.listElem(2).toBytes() == b3
|
rlp.listElem(2).toBytes() == b3
|
||||||
|
|
||||||
# The first byte here is the length of the datum (132 - 128 => 4)
|
# The first byte here is the length of the datum (132 - 128 => 4)
|
||||||
$(rlp.listElem(1).rawData) == "[132, 6, 8, 12, 123]"
|
$(rlp.listElem(1).rawData) == "[132, 6, 8, 12, 123]"
|
||||||
|
|
||||||
test "empty byte arrays":
|
test "empty byte arrays":
|
||||||
var
|
var
|
||||||
rlp = rlpFromBytes rlp.encode("")
|
rlp = rlpFromBytes rlp.encode("")
|
||||||
b = rlp.toBytes
|
b = rlp.toBytes
|
||||||
check $b == "@[]"
|
check $b == "@[]"
|
||||||
|
|
||||||
test "encode/decode floats":
|
test "encode/decode floats":
|
||||||
for f in [high(float64), low(float64), 0.1, 122.23,
|
for f in [high(float64), low(float64), 0.1, 122.23,
|
||||||
103487315.128934,
|
103487315.128934,
|
||||||
1943935743563457201.391754032785692,
|
1943935743563457201.391754032785692,
|
||||||
0, -0,
|
0, -0,
|
||||||
Inf, NegInf, NaN]:
|
Inf, NegInf, NaN]:
|
||||||
|
|
||||||
template isNaN(n): bool =
|
template isNaN(n): bool =
|
||||||
classify(n) == fcNaN
|
classify(n) == fcNaN
|
||||||
|
|
||||||
template chk(input) =
|
template chk(input) =
|
||||||
let restored = decode(encode(input), float64)
|
let restored = decode(encode(input), float64)
|
||||||
check restored == input or (input.isNaN and restored.isNaN)
|
check restored == input or (input.isNaN and restored.isNaN)
|
||||||
|
|
||||||
chk f
|
chk f
|
||||||
chk -f
|
chk -f
|
||||||
|
|
||||||
test "invalid enum":
|
test "invalid enum":
|
||||||
type
|
type
|
||||||
MyEnum = enum
|
MyEnum = enum
|
||||||
foo,
|
foo,
|
||||||
bar
|
bar
|
||||||
|
|
||||||
var writer = initRlpWriter()
|
var writer = initRlpWriter()
|
||||||
writer.append(2)
|
writer.append(2)
|
||||||
writer.append(-1)
|
writer.append(-1)
|
||||||
let bytes = writer.finish()
|
let bytes = writer.finish()
|
||||||
var rlp = rlpFromBytes(bytes)
|
var rlp = rlpFromBytes(bytes)
|
||||||
expect RlpTypeMismatch:
|
expect RlpTypeMismatch:
|
||||||
discard rlp.read(MyEnum)
|
discard rlp.read(MyEnum)
|
||||||
rlp.skipElem()
|
rlp.skipElem()
|
||||||
expect RlpTypeMismatch:
|
expect RlpTypeMismatch:
|
||||||
discard rlp.read(MyEnum)
|
discard rlp.read(MyEnum)
|
||||||
|
|
||||||
|
suite()
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
suite "rlp encoding":
|
func `==`(a, b: ChainId): bool =
|
||||||
|
a.uint64 == b.uint64
|
||||||
|
|
||||||
test "receipt roundtrip":
|
func `==`(a, b: Transaction): bool =
|
||||||
var a, b, c, d: Receipt
|
if a.txType != b.txType:
|
||||||
|
return false
|
||||||
|
if a.txType == LegacyTxType:
|
||||||
|
return a.legacyTx == b.legacyTx
|
||||||
|
else:
|
||||||
|
return a.accessListTx == b.accessListTx
|
||||||
|
|
||||||
var hash = rlpHash(a)
|
func `==`(a, b: Receipt): bool =
|
||||||
a.stateRootOrStatus = hashOrStatus(hash)
|
if a.receiptType != b.receiptType:
|
||||||
a.cumulativeGasUsed = 21000
|
return false
|
||||||
a.logs = @[]
|
if a.receiptType == LegacyReceiptType:
|
||||||
|
return a.legacyReceipt == b.legacyReceipt
|
||||||
|
else:
|
||||||
|
return a.accessListReceipt == b.accessListReceipt
|
||||||
|
|
||||||
b.stateRootOrStatus = hashOrStatus(true)
|
proc loadFile(x: int) =
|
||||||
b.cumulativeGasUsed = 52000
|
let fileName = "tests" / "rlp" / "eip2718" / "acl_block_" & $x & ".json"
|
||||||
b.logs = @[]
|
test fileName:
|
||||||
|
let n = json.parseFile(fileName)
|
||||||
|
let data = n["rlp"].getStr()
|
||||||
|
var bytes = hexToSeqByte(data)
|
||||||
|
var blk = rlp.decode(bytes, EthBlock)
|
||||||
|
|
||||||
var x = rlp.encode(a)
|
let rlpbytes = rlp.encode(blk)
|
||||||
var y = rlp.encode(b)
|
var blk2 = rlp.decode(rlpbytes, EthBlock)
|
||||||
|
check blk == blk2
|
||||||
|
check bytes == rlpbytes
|
||||||
|
|
||||||
c = x.decode(Receipt)
|
proc suite1() =
|
||||||
d = y.decode(Receipt)
|
suite "rlp encoding":
|
||||||
check c == a
|
test "receipt roundtrip":
|
||||||
check d == b
|
let a = Receipt(
|
||||||
|
receiptType: LegacyReceiptType,
|
||||||
|
legacyReceipt: LegacyReceipt(
|
||||||
|
stateRootOrStatus: hashOrStatus(true),
|
||||||
|
cumulativeGasUsed: 51000
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
check c.hasStateRoot
|
let hash = rlpHash(a)
|
||||||
check c.stateRoot == hash
|
let b = Receipt(
|
||||||
check d.hasStatus
|
receiptType: LegacyReceiptType,
|
||||||
check d.status == 1
|
legacyReceipt: LegacyReceipt(
|
||||||
|
stateRootOrStatus: hashOrStatus(hash),
|
||||||
|
cumulativeGasUsed: 21000
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
let abytes = rlp.encode(a)
|
||||||
|
let bbytes = rlp.encode(b)
|
||||||
|
let aa = rlp.decode(abytes, Receipt)
|
||||||
|
let bb = rlp.decode(bbytes, Receipt)
|
||||||
|
check aa == a
|
||||||
|
check bb == b
|
||||||
|
|
||||||
|
test "access list receipt":
|
||||||
|
let a = Receipt(
|
||||||
|
receiptType: AccessListReceiptType,
|
||||||
|
accessListReceipt: AccessListReceipt(
|
||||||
|
status: true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
let b = Receipt(
|
||||||
|
receiptType: AccessListReceiptType,
|
||||||
|
accessListReceipt: AccessListReceipt(
|
||||||
|
status: false,
|
||||||
|
cumulativeGasUsed: 21000
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
let abytes = rlp.encode(a)
|
||||||
|
let bbytes = rlp.encode(b)
|
||||||
|
let aa = rlp.decode(abytes, Receipt)
|
||||||
|
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()
|
|
@ -43,41 +43,45 @@ 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
|
||||||
|
|
||||||
test "encoding and decoding an object":
|
proc suite() =
|
||||||
var originalBar = Bar(b: "abracadabra",
|
suite "object serialization":
|
||||||
f: Foo(x: 5'u64, y: "hocus pocus", z: @[100, 200, 300]))
|
test "encoding and decoding an object":
|
||||||
|
var originalBar = Bar(b: "abracadabra",
|
||||||
|
f: Foo(x: 5'u64, y: "hocus pocus", z: @[100, 200, 300]))
|
||||||
|
|
||||||
var bytes = encode(originalBar)
|
var bytes = encode(originalBar)
|
||||||
var r = rlpFromBytes(bytes)
|
var r = rlpFromBytes(bytes)
|
||||||
var restoredBar = r.read(Bar)
|
var restoredBar = r.read(Bar)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
originalBar == restoredBar
|
originalBar == restoredBar
|
||||||
|
|
||||||
var t1 = Transaction(time: getTime(), amount: 1000, sender: "Alice", receiver: "Bob")
|
var t1 = Transaction(time: getTime(), amount: 1000, sender: "Alice", receiver: "Bob")
|
||||||
bytes = encode(t1)
|
bytes = encode(t1)
|
||||||
var t2 = bytes.decode(Transaction)
|
var t2 = bytes.decode(Transaction)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
bytes.toHex == "cd85416c69636583426f628203e8" # verifies that Alice comes first
|
bytes.toHex == "cd85416c69636583426f628203e8" # verifies that Alice comes first
|
||||||
t2.time == default(Time)
|
t2.time == default(Time)
|
||||||
t2.sender == "Alice"
|
t2.sender == "Alice"
|
||||||
t2.receiver == "Bob"
|
t2.receiver == "Bob"
|
||||||
t2.amount == 1000
|
t2.amount == 1000
|
||||||
|
|
||||||
test "custom field serialization":
|
test "custom field serialization":
|
||||||
var origVal = CustomSerialized(customFoo: Foo(x: 10'u64, y: "y", z: @[]), ignored: 5)
|
var origVal = CustomSerialized(customFoo: Foo(x: 10'u64, y: "y", z: @[]), ignored: 5)
|
||||||
var bytes = encode(origVal)
|
var bytes = encode(origVal)
|
||||||
var r = rlpFromBytes(bytes)
|
var r = rlpFromBytes(bytes)
|
||||||
var restored = r.read(CustomSerialized)
|
var restored = r.read(CustomSerialized)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
origVal.customFoo.x == restored.customFoo.x
|
origVal.customFoo.x == restored.customFoo.x
|
||||||
origVal.customFoo.y.len == restored.customFoo.y.len
|
origVal.customFoo.y.len == restored.customFoo.y.len
|
||||||
restored.ignored == 10
|
restored.ignored == 10
|
||||||
|
|
||||||
test "RLP fields count":
|
test "RLP fields count":
|
||||||
check:
|
check:
|
||||||
Bar.rlpFieldsCount == 2
|
Bar.rlpFieldsCount == 2
|
||||||
Foo.rlpFieldsCount == 3
|
Foo.rlpFieldsCount == 3
|
||||||
Transaction.rlpFieldsCount == 3
|
Transaction.rlpFieldsCount == 3
|
||||||
|
|
||||||
|
suite()
|
||||||
|
|
Loading…
Reference in New Issue