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
|
||||
Hash256* = MDigest[256]
|
||||
|
||||
EthTime* = Time
|
||||
|
||||
VMWord* = UInt256
|
||||
|
||||
BlockNonce* = array[8, byte]
|
||||
AccountNonce* = uint64
|
||||
Blob* = seq[byte]
|
||||
|
@ -33,23 +30,61 @@ type
|
|||
ForkID* = tuple[crc: uint32, nextFork: uint64]
|
||||
# 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
|
||||
nonce*: AccountNonce
|
||||
balance*: UInt256
|
||||
storageRoot*: Hash256
|
||||
codeHash*: Hash256
|
||||
|
||||
Transaction* = object
|
||||
accountNonce*: AccountNonce
|
||||
gasPrice*: GasInt
|
||||
gasLimit*: GasInt
|
||||
LegacyTx* = object
|
||||
nonce* : AccountNonce
|
||||
gasPrice*: GasInt
|
||||
gasLimit*: GasInt
|
||||
to* {.rlpCustomSerialization.}: EthAddress
|
||||
value*: UInt256
|
||||
payload*: Blob
|
||||
V*: byte
|
||||
R*, S*: UInt256
|
||||
value* : UInt256
|
||||
payload* : Blob
|
||||
V* : int64
|
||||
R*, S* : UInt256
|
||||
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
|
||||
Unknown,
|
||||
Queued,
|
||||
|
@ -61,8 +96,6 @@ type
|
|||
status*: TransactionStatus
|
||||
data*: Blob
|
||||
|
||||
BlockNumber* = UInt256
|
||||
|
||||
BlockHeader* = object
|
||||
parentHash*: Hash256
|
||||
ommersHash*: Hash256
|
||||
|
@ -96,24 +129,33 @@ type
|
|||
else:
|
||||
status*: bool
|
||||
|
||||
Receipt* = object
|
||||
LegacyReceipt* = object
|
||||
stateRootOrStatus*: HashOrStatus
|
||||
cumulativeGasUsed*: GasInt
|
||||
bloom*: BloomFilter
|
||||
logs*: seq[Log]
|
||||
bloom*: BloomFilter
|
||||
logs* : seq[Log]
|
||||
|
||||
AccessList* = object
|
||||
# XXX: Specify the structure of this
|
||||
AccessListReceipt* = object
|
||||
status*: bool
|
||||
cumulativeGasUsed*: GasInt
|
||||
bloom* : BloomFilter
|
||||
logs* : seq[Log]
|
||||
|
||||
ShardTransaction* = object
|
||||
chain*: uint
|
||||
shard*: uint
|
||||
to*: EthAddress
|
||||
data*: Blob
|
||||
gas*: GasInt
|
||||
accessList*: AccessList
|
||||
code*: Blob
|
||||
salt*: Hash256
|
||||
ReceiptType* = enum
|
||||
LegacyReceiptType
|
||||
AccessListReceiptType
|
||||
|
||||
Receipt* = object
|
||||
case receiptType*: ReceiptType
|
||||
of LegacyReceiptType:
|
||||
legacyReceipt*: LegacyReceipt
|
||||
of AccessListReceiptType:
|
||||
accessListReceipt*: AccessListReceipt
|
||||
|
||||
EthBlock* = object
|
||||
header*: BlockHeader
|
||||
txs* : seq[Transaction]
|
||||
uncles*: seq[BlockHeader]
|
||||
|
||||
CollationHeader* = object
|
||||
shard*: uint
|
||||
|
@ -232,17 +274,17 @@ proc hashOrStatus*(hash: Hash256): HashOrStatus =
|
|||
proc hashOrStatus*(status: bool): HashOrStatus =
|
||||
HashOrStatus(isHash: false, status: status)
|
||||
|
||||
proc hasStatus*(rec: Receipt): bool {.inline.} =
|
||||
proc hasStatus*(rec: LegacyReceipt): bool {.inline.} =
|
||||
rec.stateRootOrStatus.isHash == false
|
||||
|
||||
proc hasStateRoot*(rec: Receipt): bool {.inline.} =
|
||||
proc hasStateRoot*(rec: LegacyReceipt): bool {.inline.} =
|
||||
rec.stateRootOrStatus.isHash == true
|
||||
|
||||
proc stateRoot*(rec: Receipt): Hash256 {.inline.} =
|
||||
proc stateRoot*(rec: LegacyReceipt): Hash256 {.inline.} =
|
||||
doAssert(rec.hasStateRoot)
|
||||
rec.stateRootOrStatus.hash
|
||||
|
||||
proc status*(rec: Receipt): int {.inline.} =
|
||||
proc status*(rec: LegacyReceipt): int {.inline.} =
|
||||
doAssert(rec.hasStatus)
|
||||
if rec.stateRootOrStatus.status: 1 else: 0
|
||||
|
||||
|
@ -250,7 +292,7 @@ proc status*(rec: Receipt): int {.inline.} =
|
|||
# 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:
|
||||
let bytes = rlp.toBytes
|
||||
if bytes.len > 0:
|
||||
|
@ -275,7 +317,7 @@ proc append*(rlpWriter: var RlpWriter, value: StUint) =
|
|||
else:
|
||||
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
|
||||
# for unsigned integers:
|
||||
{.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".}
|
||||
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:
|
||||
result = rlp.read(EthAddress)
|
||||
else:
|
||||
t.isContractCreation = true
|
||||
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:
|
||||
rlpWriter.append("")
|
||||
else:
|
||||
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.blobLen == 1:
|
||||
result = hashOrStatus(rlp.read(uint8) == 1)
|
||||
|
@ -334,7 +409,31 @@ proc append*(rlpWriter: var RlpWriter, value: HashOrStatus) {.inline.} =
|
|||
else:
|
||||
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))
|
||||
|
||||
proc append*(rlpWriter: var RlpWriter, value: HashOrNum) =
|
||||
|
@ -344,7 +443,7 @@ proc append*(rlpWriter: var RlpWriter, value: HashOrNum) =
|
|||
else:
|
||||
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:
|
||||
result = HashOrNum(isHash: true, hash: rlp.read(Hash256))
|
||||
else:
|
||||
|
|
|
@ -2,8 +2,8 @@ import
|
|||
nimcrypto/keccak,
|
||||
".."/[common, rlp, keys]
|
||||
|
||||
proc initTransaction*(nonce: AccountNonce, gasPrice, gasLimit: GasInt, to: EthAddress,
|
||||
value: UInt256, payload: Blob, V: byte, R, S: UInt256, isContractCreation = false): Transaction =
|
||||
proc initLegacyTx*(nonce: AccountNonce, gasPrice, gasLimit: GasInt, to: EthAddress,
|
||||
value: UInt256, payload: Blob, V: uint64, R, S: UInt256, isContractCreation = false): LegacyTx =
|
||||
result.accountNonce = nonce
|
||||
result.gasPrice = gasPrice
|
||||
result.gasLimit = gasLimit
|
||||
|
@ -40,7 +40,7 @@ proc append(rlpWriter: var RlpWriter, t: TransHashObj, a: EthAddress) {.inline.}
|
|||
const
|
||||
EIP155_CHAIN_ID_OFFSET* = 35
|
||||
|
||||
func rlpEncode*(transaction: Transaction): auto =
|
||||
func rlpEncode*(transaction: LegacyTx): auto =
|
||||
# Encode transaction without signature
|
||||
return rlp.encode(TransHashObj(
|
||||
accountNonce: transaction.accountNonce,
|
||||
|
@ -52,7 +52,7 @@ func rlpEncode*(transaction: Transaction): auto =
|
|||
mIsContractCreation: transaction.isContractCreation
|
||||
))
|
||||
|
||||
func rlpEncodeEIP155*(tx: Transaction): auto =
|
||||
func rlpEncodeEIP155*(tx: LegacyTx): auto =
|
||||
let V = (tx.V.int - EIP155_CHAIN_ID_OFFSET) div 2
|
||||
# Encode transaction without signature
|
||||
return rlp.encode(Transaction(
|
||||
|
@ -63,11 +63,11 @@ func rlpEncodeEIP155*(tx: Transaction): auto =
|
|||
value: tx.value,
|
||||
payload: tx.payload,
|
||||
isContractCreation: tx.isContractCreation,
|
||||
V: V.byte,
|
||||
V: V.uint64,
|
||||
R: 0.u256,
|
||||
S: 0.u256
|
||||
))
|
||||
|
||||
func txHashNoSignature*(tx: Transaction): Hash256 =
|
||||
func txHashNoSignature*(tx: LegacyTx): Hash256 =
|
||||
# Hash transaction without signature
|
||||
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 inspectMatch(r: Rlp, s: string): bool = r.inspect.i == s.i
|
||||
|
||||
test "empty bytes are not a proper RLP":
|
||||
var rlp = rlpFromBytes seq[byte](@[])
|
||||
proc suite() =
|
||||
suite "test api usage":
|
||||
test "empty bytes are not a proper RLP":
|
||||
var rlp = rlpFromBytes seq[byte](@[])
|
||||
|
||||
check:
|
||||
not rlp.hasData
|
||||
not rlp.isBlob
|
||||
not rlp.isList
|
||||
not rlp.isEmpty
|
||||
check:
|
||||
not rlp.hasData
|
||||
not rlp.isBlob
|
||||
not rlp.isList
|
||||
not rlp.isEmpty
|
||||
|
||||
expect Exception:
|
||||
rlp.skipElem
|
||||
expect Exception:
|
||||
rlp.skipElem
|
||||
|
||||
expect Exception:
|
||||
discard rlp.getType
|
||||
expect Exception:
|
||||
discard rlp.getType
|
||||
|
||||
expect Exception:
|
||||
for e in rlp:
|
||||
discard e.getType
|
||||
expect Exception:
|
||||
for e in rlp:
|
||||
discard e.getType
|
||||
|
||||
test "you cannot finish a list without appending enough elements":
|
||||
var writer = initRlpList(3)
|
||||
writer.append "foo"
|
||||
writer.append "bar"
|
||||
test "you cannot finish a list without appending enough elements":
|
||||
var writer = initRlpList(3)
|
||||
writer.append "foo"
|
||||
writer.append "bar"
|
||||
|
||||
expect Defect:
|
||||
discard writer.finish
|
||||
expect Defect:
|
||||
discard writer.finish
|
||||
|
||||
test "encode/decode object":
|
||||
type
|
||||
MyEnum = enum
|
||||
foo,
|
||||
bar
|
||||
test "encode/decode object":
|
||||
type
|
||||
MyEnum = enum
|
||||
foo,
|
||||
bar
|
||||
|
||||
MyObj = object
|
||||
a: array[3, char]
|
||||
b: int
|
||||
c: MyEnum
|
||||
MyObj = object
|
||||
a: array[3, char]
|
||||
b: int
|
||||
c: MyEnum
|
||||
|
||||
var input: MyObj
|
||||
input.a = ['e', 't', 'h']
|
||||
input.b = 63
|
||||
input.c = bar
|
||||
var input: MyObj
|
||||
input.a = ['e', 't', 'h']
|
||||
input.b = 63
|
||||
input.c = bar
|
||||
|
||||
var writer = initRlpWriter()
|
||||
writer.append(input)
|
||||
let bytes = writer.finish()
|
||||
var rlp = rlpFromBytes(bytes)
|
||||
var writer = initRlpWriter()
|
||||
writer.append(input)
|
||||
let bytes = writer.finish()
|
||||
var rlp = rlpFromBytes(bytes)
|
||||
|
||||
var output = rlp.read(MyObj)
|
||||
check:
|
||||
input == output
|
||||
var output = rlp.read(MyObj)
|
||||
check:
|
||||
input == output
|
||||
|
||||
test "encode and decode lists":
|
||||
var writer = initRlpList(3)
|
||||
writer.append "foo"
|
||||
writer.append ["bar", "baz"]
|
||||
writer.append [30, 40, 50]
|
||||
test "encode and decode lists":
|
||||
var writer = initRlpList(3)
|
||||
writer.append "foo"
|
||||
writer.append ["bar", "baz"]
|
||||
writer.append [30, 40, 50]
|
||||
|
||||
var
|
||||
bytes = writer.finish
|
||||
rlp = rlpFromBytes bytes
|
||||
var
|
||||
bytes = writer.finish
|
||||
rlp = rlpFromBytes bytes
|
||||
|
||||
check:
|
||||
bytes.toHex == "d183666f6fc8836261728362617ac31e2832"
|
||||
rlp.inspectMatch """
|
||||
{
|
||||
"foo"
|
||||
{
|
||||
"bar"
|
||||
"baz"
|
||||
}
|
||||
{
|
||||
byte 30
|
||||
byte 40
|
||||
byte 50
|
||||
}
|
||||
}
|
||||
"""
|
||||
check:
|
||||
bytes.toHex == "d183666f6fc8836261728362617ac31e2832"
|
||||
rlp.inspectMatch """
|
||||
{
|
||||
"foo"
|
||||
{
|
||||
"bar"
|
||||
"baz"
|
||||
}
|
||||
{
|
||||
byte 30
|
||||
byte 40
|
||||
byte 50
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
bytes = encodeList(6000,
|
||||
"Lorem ipsum dolor sit amet",
|
||||
"Donec ligula tortor, egestas eu est vitae")
|
||||
bytes = encodeList(6000,
|
||||
"Lorem ipsum dolor sit amet",
|
||||
"Donec ligula tortor, egestas eu est vitae")
|
||||
|
||||
rlp = rlpFromBytes bytes
|
||||
check:
|
||||
rlp.listLen == 3
|
||||
rlp.listElem(0).toInt(int) == 6000
|
||||
rlp.listElem(1).toString == "Lorem ipsum dolor sit amet"
|
||||
rlp.listElem(2).toString == "Donec ligula tortor, egestas eu est vitae"
|
||||
rlp = rlpFromBytes bytes
|
||||
check:
|
||||
rlp.listLen == 3
|
||||
rlp.listElem(0).toInt(int) == 6000
|
||||
rlp.listElem(1).toString == "Lorem ipsum dolor sit amet"
|
||||
rlp.listElem(2).toString == "Donec ligula tortor, egestas eu est vitae"
|
||||
|
||||
# test creating RLPs from other RLPs
|
||||
var list = rlpFromBytes encodeList(rlp.listELem(1), rlp.listELem(0))
|
||||
# test creating RLPs from other RLPs
|
||||
var list = rlpFromBytes encodeList(rlp.listELem(1), rlp.listELem(0))
|
||||
|
||||
# test that iteration with enterList/skipElem works as expected
|
||||
doAssert list.enterList # We already know that we are working with a list
|
||||
check list.toString == "Lorem ipsum dolor sit amet"
|
||||
list.skipElem
|
||||
# test that iteration with enterList/skipElem works as expected
|
||||
doAssert list.enterList # We already know that we are working with a list
|
||||
check list.toString == "Lorem ipsum dolor sit amet"
|
||||
list.skipElem
|
||||
|
||||
check list.toInt(int32) == 6000.int32
|
||||
var intVar: int
|
||||
list >> intVar
|
||||
check intVar == 6000
|
||||
check list.toInt(int32) == 6000.int32
|
||||
var intVar: int
|
||||
list >> intVar
|
||||
check intVar == 6000
|
||||
|
||||
check(not list.hasData)
|
||||
expect Exception: list.skipElem
|
||||
check(not list.hasData)
|
||||
expect Exception: list.skipElem
|
||||
|
||||
test "toBytes":
|
||||
let rlp = rlpFromHex("f2cb847f000001827666827666a040ef02798f211da2e8173d37f255be908871ae65060dbb2f77fb29c0421447f4845ab90b50")
|
||||
let tok = rlp.listElem(1).toBytes()
|
||||
check:
|
||||
tok.len == 32
|
||||
tok.toHex == "40ef02798f211da2e8173d37f255be908871ae65060dbb2f77fb29c0421447f4"
|
||||
test "toBytes":
|
||||
let rlp = rlpFromHex("f2cb847f000001827666827666a040ef02798f211da2e8173d37f255be908871ae65060dbb2f77fb29c0421447f4845ab90b50")
|
||||
let tok = rlp.listElem(1).toBytes()
|
||||
check:
|
||||
tok.len == 32
|
||||
tok.toHex == "40ef02798f211da2e8173d37f255be908871ae65060dbb2f77fb29c0421447f4"
|
||||
|
||||
test "nested lists":
|
||||
let listBytes = encode([[1, 2, 3], [5, 6, 7]])
|
||||
let listRlp = rlpFromBytes listBytes
|
||||
let sublistRlp0 = listRlp.listElem(0)
|
||||
let sublistRlp1 = listRlp.listElem(1)
|
||||
check sublistRlp0.listElem(0).toInt(int) == 1
|
||||
check sublistRlp0.listElem(1).toInt(int) == 2
|
||||
check sublistRlp0.listElem(2).toInt(int) == 3
|
||||
check sublistRlp1.listElem(0).toInt(int) == 5
|
||||
check sublistRlp1.listElem(1).toInt(int) == 6
|
||||
check sublistRlp1.listElem(2).toInt(int) == 7
|
||||
test "nested lists":
|
||||
let listBytes = encode([[1, 2, 3], [5, 6, 7]])
|
||||
let listRlp = rlpFromBytes listBytes
|
||||
let sublistRlp0 = listRlp.listElem(0)
|
||||
let sublistRlp1 = listRlp.listElem(1)
|
||||
check sublistRlp0.listElem(0).toInt(int) == 1
|
||||
check sublistRlp0.listElem(1).toInt(int) == 2
|
||||
check sublistRlp0.listElem(2).toInt(int) == 3
|
||||
check sublistRlp1.listElem(0).toInt(int) == 5
|
||||
check sublistRlp1.listElem(1).toInt(int) == 6
|
||||
check sublistRlp1.listElem(2).toInt(int) == 7
|
||||
|
||||
test "encoding length":
|
||||
let listBytes = encode([1,2,3,4,5])
|
||||
let listRlp = rlpFromBytes listBytes
|
||||
check listRlp.listLen == 5
|
||||
test "encoding length":
|
||||
let listBytes = encode([1,2,3,4,5])
|
||||
let listRlp = rlpFromBytes listBytes
|
||||
check listRlp.listLen == 5
|
||||
|
||||
let emptyListBytes = encode ""
|
||||
check emptyListBytes.len == 1
|
||||
let emptyListRlp = rlpFromBytes emptyListBytes
|
||||
check emptyListRlp.blobLen == 0
|
||||
let emptyListBytes = encode ""
|
||||
check emptyListBytes.len == 1
|
||||
let emptyListRlp = rlpFromBytes emptyListBytes
|
||||
check emptyListRlp.blobLen == 0
|
||||
|
||||
test "basic decoding":
|
||||
var rlp1 = rlpFromHex("856d6f6f7365")
|
||||
var rlp2 = rlpFromHex("0x856d6f6f7365")
|
||||
test "basic decoding":
|
||||
var rlp1 = rlpFromHex("856d6f6f7365")
|
||||
var rlp2 = rlpFromHex("0x856d6f6f7365")
|
||||
|
||||
check:
|
||||
rlp1.inspect == q"moose"
|
||||
rlp2.inspect == q"moose"
|
||||
check:
|
||||
rlp1.inspect == q"moose"
|
||||
rlp2.inspect == q"moose"
|
||||
|
||||
test "malformed/truncated RLP":
|
||||
var rlp = rlpFromHex("b8056d6f6f7365")
|
||||
expect MalformedRlpError:
|
||||
discard rlp.inspect
|
||||
test "malformed/truncated RLP":
|
||||
var rlp = rlpFromHex("b8056d6f6f7365")
|
||||
expect MalformedRlpError:
|
||||
discard rlp.inspect
|
||||
|
||||
test "encode byte arrays":
|
||||
var b1 = [byte(1), 2, 5, 7, 8]
|
||||
var b2 = [byte(6), 8, 12, 123]
|
||||
var b3 = @[byte(122), 56, 65, 12]
|
||||
test "encode byte arrays":
|
||||
var b1 = [byte(1), 2, 5, 7, 8]
|
||||
var b2 = [byte(6), 8, 12, 123]
|
||||
var b3 = @[byte(122), 56, 65, 12]
|
||||
|
||||
let rlp = rlpFromBytes(encode((b1, b2, b3)))
|
||||
check:
|
||||
rlp.listLen == 3
|
||||
rlp.listElem(0).toBytes() == b1
|
||||
rlp.listElem(1).toBytes() == b2
|
||||
rlp.listElem(2).toBytes() == b3
|
||||
let rlp = rlpFromBytes(encode((b1, b2, b3)))
|
||||
check:
|
||||
rlp.listLen == 3
|
||||
rlp.listElem(0).toBytes() == b1
|
||||
rlp.listElem(1).toBytes() == b2
|
||||
rlp.listElem(2).toBytes() == b3
|
||||
|
||||
# The first byte here is the length of the datum (132 - 128 => 4)
|
||||
$(rlp.listElem(1).rawData) == "[132, 6, 8, 12, 123]"
|
||||
# The first byte here is the length of the datum (132 - 128 => 4)
|
||||
$(rlp.listElem(1).rawData) == "[132, 6, 8, 12, 123]"
|
||||
|
||||
test "empty byte arrays":
|
||||
var
|
||||
rlp = rlpFromBytes rlp.encode("")
|
||||
b = rlp.toBytes
|
||||
check $b == "@[]"
|
||||
test "empty byte arrays":
|
||||
var
|
||||
rlp = rlpFromBytes rlp.encode("")
|
||||
b = rlp.toBytes
|
||||
check $b == "@[]"
|
||||
|
||||
test "encode/decode floats":
|
||||
for f in [high(float64), low(float64), 0.1, 122.23,
|
||||
103487315.128934,
|
||||
1943935743563457201.391754032785692,
|
||||
0, -0,
|
||||
Inf, NegInf, NaN]:
|
||||
test "encode/decode floats":
|
||||
for f in [high(float64), low(float64), 0.1, 122.23,
|
||||
103487315.128934,
|
||||
1943935743563457201.391754032785692,
|
||||
0, -0,
|
||||
Inf, NegInf, NaN]:
|
||||
|
||||
template isNaN(n): bool =
|
||||
classify(n) == fcNaN
|
||||
template isNaN(n): bool =
|
||||
classify(n) == fcNaN
|
||||
|
||||
template chk(input) =
|
||||
let restored = decode(encode(input), float64)
|
||||
check restored == input or (input.isNaN and restored.isNaN)
|
||||
template chk(input) =
|
||||
let restored = decode(encode(input), float64)
|
||||
check restored == input or (input.isNaN and restored.isNaN)
|
||||
|
||||
chk f
|
||||
chk -f
|
||||
chk f
|
||||
chk -f
|
||||
|
||||
test "invalid enum":
|
||||
type
|
||||
MyEnum = enum
|
||||
foo,
|
||||
bar
|
||||
test "invalid enum":
|
||||
type
|
||||
MyEnum = enum
|
||||
foo,
|
||||
bar
|
||||
|
||||
var writer = initRlpWriter()
|
||||
writer.append(2)
|
||||
writer.append(-1)
|
||||
let bytes = writer.finish()
|
||||
var rlp = rlpFromBytes(bytes)
|
||||
expect RlpTypeMismatch:
|
||||
discard rlp.read(MyEnum)
|
||||
rlp.skipElem()
|
||||
expect RlpTypeMismatch:
|
||||
discard rlp.read(MyEnum)
|
||||
var writer = initRlpWriter()
|
||||
writer.append(2)
|
||||
writer.append(-1)
|
||||
let bytes = writer.finish()
|
||||
var rlp = rlpFromBytes(bytes)
|
||||
expect RlpTypeMismatch:
|
||||
discard rlp.read(MyEnum)
|
||||
rlp.skipElem()
|
||||
expect RlpTypeMismatch:
|
||||
discard rlp.read(MyEnum)
|
||||
|
||||
suite()
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
{.used.}
|
||||
|
||||
import
|
||||
std/unittest,
|
||||
std/[unittest, os, json],
|
||||
stew/byteutils,
|
||||
../../eth/[common, rlp]
|
||||
|
||||
proc `==`(a, b: HashOrStatus): bool =
|
||||
|
@ -12,29 +13,92 @@ proc `==`(a, b: HashOrStatus): bool =
|
|||
else:
|
||||
result = result and a.status == b.status
|
||||
|
||||
suite "rlp encoding":
|
||||
func `==`(a, b: ChainId): bool =
|
||||
a.uint64 == b.uint64
|
||||
|
||||
test "receipt roundtrip":
|
||||
var a, b, c, d: Receipt
|
||||
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
|
||||
|
||||
var hash = rlpHash(a)
|
||||
a.stateRootOrStatus = hashOrStatus(hash)
|
||||
a.cumulativeGasUsed = 21000
|
||||
a.logs = @[]
|
||||
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
|
||||
|
||||
b.stateRootOrStatus = hashOrStatus(true)
|
||||
b.cumulativeGasUsed = 52000
|
||||
b.logs = @[]
|
||||
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)
|
||||
|
||||
var x = rlp.encode(a)
|
||||
var y = rlp.encode(b)
|
||||
let rlpbytes = rlp.encode(blk)
|
||||
var blk2 = rlp.decode(rlpbytes, EthBlock)
|
||||
check blk == blk2
|
||||
check bytes == rlpbytes
|
||||
|
||||
c = x.decode(Receipt)
|
||||
d = y.decode(Receipt)
|
||||
check c == a
|
||||
check d == b
|
||||
proc suite1() =
|
||||
suite "rlp encoding":
|
||||
test "receipt roundtrip":
|
||||
let a = Receipt(
|
||||
receiptType: LegacyReceiptType,
|
||||
legacyReceipt: LegacyReceipt(
|
||||
stateRootOrStatus: hashOrStatus(true),
|
||||
cumulativeGasUsed: 51000
|
||||
)
|
||||
)
|
||||
|
||||
check c.hasStateRoot
|
||||
check c.stateRoot == hash
|
||||
check d.hasStatus
|
||||
check d.status == 1
|
||||
let hash = rlpHash(a)
|
||||
let b = Receipt(
|
||||
receiptType: LegacyReceiptType,
|
||||
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))
|
||||
holder.ignored = rlp.read(int) * 2
|
||||
|
||||
test "encoding and decoding an object":
|
||||
var originalBar = Bar(b: "abracadabra",
|
||||
f: Foo(x: 5'u64, y: "hocus pocus", z: @[100, 200, 300]))
|
||||
proc suite() =
|
||||
suite "object serialization":
|
||||
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 r = rlpFromBytes(bytes)
|
||||
var restoredBar = r.read(Bar)
|
||||
var bytes = encode(originalBar)
|
||||
var r = rlpFromBytes(bytes)
|
||||
var restoredBar = r.read(Bar)
|
||||
|
||||
check:
|
||||
originalBar == restoredBar
|
||||
check:
|
||||
originalBar == restoredBar
|
||||
|
||||
var t1 = Transaction(time: getTime(), amount: 1000, sender: "Alice", receiver: "Bob")
|
||||
bytes = encode(t1)
|
||||
var t2 = bytes.decode(Transaction)
|
||||
var t1 = Transaction(time: getTime(), amount: 1000, sender: "Alice", receiver: "Bob")
|
||||
bytes = encode(t1)
|
||||
var t2 = bytes.decode(Transaction)
|
||||
|
||||
check:
|
||||
bytes.toHex == "cd85416c69636583426f628203e8" # verifies that Alice comes first
|
||||
t2.time == default(Time)
|
||||
t2.sender == "Alice"
|
||||
t2.receiver == "Bob"
|
||||
t2.amount == 1000
|
||||
check:
|
||||
bytes.toHex == "cd85416c69636583426f628203e8" # verifies that Alice comes first
|
||||
t2.time == default(Time)
|
||||
t2.sender == "Alice"
|
||||
t2.receiver == "Bob"
|
||||
t2.amount == 1000
|
||||
|
||||
test "custom field serialization":
|
||||
var origVal = CustomSerialized(customFoo: Foo(x: 10'u64, y: "y", z: @[]), ignored: 5)
|
||||
var bytes = encode(origVal)
|
||||
var r = rlpFromBytes(bytes)
|
||||
var restored = r.read(CustomSerialized)
|
||||
test "custom field serialization":
|
||||
var origVal = CustomSerialized(customFoo: Foo(x: 10'u64, y: "y", z: @[]), ignored: 5)
|
||||
var bytes = encode(origVal)
|
||||
var r = rlpFromBytes(bytes)
|
||||
var restored = r.read(CustomSerialized)
|
||||
|
||||
check:
|
||||
origVal.customFoo.x == restored.customFoo.x
|
||||
origVal.customFoo.y.len == restored.customFoo.y.len
|
||||
restored.ignored == 10
|
||||
check:
|
||||
origVal.customFoo.x == restored.customFoo.x
|
||||
origVal.customFoo.y.len == restored.customFoo.y.len
|
||||
restored.ignored == 10
|
||||
|
||||
test "RLP fields count":
|
||||
check:
|
||||
Bar.rlpFieldsCount == 2
|
||||
Foo.rlpFieldsCount == 3
|
||||
Transaction.rlpFieldsCount == 3
|
||||
test "RLP fields count":
|
||||
check:
|
||||
Bar.rlpFieldsCount == 2
|
||||
Foo.rlpFieldsCount == 3
|
||||
Transaction.rlpFieldsCount == 3
|
||||
|
||||
suite()
|
||||
|
|
Loading…
Reference in New Issue