mirror of
https://github.com/status-im/nim-eth.git
synced 2025-01-15 00:54:36 +00:00
4ea11b9fb9
Transaction signing is something that happens in a lot of places - this PR introduces primitives for transaction signing in `transaction_utils` such that we can use the same logic across web3/eth1/etc for this simple operation. `transaction_utils` also contains a few more "spec-derived" helpers for working with transactions, such as the computation of a contract address etc that cannot easily be introduced in `transactions` itself without bringing in dependencies like secp and rlp, so they end up in a separate module. Finally, since these modules collect "versions" of these transaction types across different eips, some tests are moved to follow the same structure.
199 lines
10 KiB
Nim
199 lines
10 KiB
Nim
# Copyright (c) 2019-2024 Status Research & Development GmbH
|
|
# Licensed and distributed under either of
|
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
{.used.}
|
|
|
|
import
|
|
std/[os, json],
|
|
unittest2,
|
|
stew/byteutils,
|
|
../../eth/[common, rlp]
|
|
|
|
type
|
|
EthHeader = object
|
|
header: Header
|
|
|
|
proc loadFile(x: int) =
|
|
let fileName = currentSourcePath.parentDir / "eip2718" / "acl_block_" & $x & ".json"
|
|
test fileName:
|
|
let n = json.parseFile(fileName)
|
|
let data = n["rlp"].getStr()
|
|
var bytes1 = hexToSeqByte(data)
|
|
var blk1 = rlp.decode(bytes1, EthBlock)
|
|
|
|
let bytes2 = rlp.encode(blk1)
|
|
var blk2 = rlp.decode(bytes2, EthBlock)
|
|
check blk1 == blk2
|
|
check bytes1 == bytes2
|
|
|
|
var r = rlpFromBytes(bytes1)
|
|
let header = r.read(EthHeader).header
|
|
let body = r.readRecordType(BlockBody, false)
|
|
|
|
let blk3 = EthBlock(header: header, transactions: body.transactions, uncles: body.uncles)
|
|
let bytes3 = rlp.encode(blk3)
|
|
check blk1 == blk3
|
|
check bytes1 == bytes3
|
|
|
|
suite "RLP encoding":
|
|
test "Receipt roundtrip":
|
|
let a = Receipt(
|
|
receiptType: LegacyReceipt,
|
|
isHash: false,
|
|
status: false,
|
|
cumulativeGasUsed: 51000
|
|
)
|
|
|
|
let hash = rlpHash(a)
|
|
let b = Receipt(
|
|
receiptType: LegacyReceipt,
|
|
isHash: true,
|
|
hash: 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 "EIP-2930 receipt":
|
|
let a = Receipt(
|
|
receiptType: Eip2930Receipt,
|
|
status: true
|
|
)
|
|
|
|
let b = Receipt(
|
|
receiptType: Eip2930Receipt,
|
|
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
|
|
|
|
test "EIP-4895 roundtrip":
|
|
let a = Withdrawal(
|
|
index: 1,
|
|
validatorIndex: 2,
|
|
address: Address [
|
|
0.byte, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
|
11, 12, 13, 14, 15, 16, 17, 18, 19],
|
|
amount: 4)
|
|
|
|
let abytes = rlp.encode(a)
|
|
let aa = rlp.decode(abytes, Withdrawal)
|
|
check aa == a
|
|
|
|
suite "EIP-2718 transaction / receipt":
|
|
for i in 0..<10:
|
|
loadFile(i)
|
|
|
|
test "Header: rlp roundtrip EIP-1559 / EIP-4895 / EIP-4844":
|
|
proc doTest(h: Header) =
|
|
let xy = rlp.encode(h)
|
|
let hh = rlp.decode(xy, Header)
|
|
check h == hh
|
|
|
|
var h: Header
|
|
doTest h
|
|
|
|
# EIP-1559
|
|
h.baseFeePerGas = Opt.some 1234.u256
|
|
doTest h
|
|
|
|
# EIP-4895
|
|
h.withdrawalsRoot = Opt.some hash32"0x7a64245f7f95164f6176d90bd4903dbdd3e5433d555dd1385e81787f9672c588"
|
|
doTest h
|
|
|
|
# EIP-4844
|
|
h.blobGasUsed = Opt.some 1234'u64
|
|
h.excessBlobGas = Opt.some 1234'u64
|
|
doTest h
|
|
|
|
test "Receipts EIP-2718 + EIP-2976 encoding":
|
|
const
|
|
# Test payload from
|
|
# https://github.com/ethereum/go-ethereum/blob/253447a4f5e5f7f65c0605d490360bb58fb5f8e0/core/types/receipt_test.go#L370
|
|
payload = "f9043eb9010c01f90108018262d4b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0b9010c01f901080182cd14b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0b9010d01f901090183013754b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0b9010d01f90109018301a194b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0"
|
|
receiptsBytes = hexToSeqByte(payload)
|
|
let receipts = rlp.decode(receiptsBytes, seq[Receipt])
|
|
|
|
check receipts.len() == 4
|
|
for receipt in receipts:
|
|
check receipt.receiptType == TxEip2930
|
|
|
|
let encoded = rlp.encode(receipts)
|
|
|
|
check receiptsBytes == encoded
|
|
|
|
test "Receipts EIP-2718 encoding - invalid - empty":
|
|
let receiptBytes: seq[byte] = @[]
|
|
expect MalformedRlpError:
|
|
let _ = rlp.decode(receiptBytes, Receipt)
|
|
|
|
test "Receipts EIP-2718 encoding - invalid - unsupported tx type":
|
|
let receiptBytes: seq[byte] = @[0x05]
|
|
expect UnsupportedRlpError:
|
|
let _ = rlp.decode(receiptBytes, Receipt)
|
|
|
|
test "Receipts EIP-2718 encoding - invalid - legacy tx type":
|
|
let receiptBytes: seq[byte] = @[0x00]
|
|
expect MalformedRlpError:
|
|
let _ = rlp.decode(receiptBytes, Receipt)
|
|
|
|
test "Receipts EIP-2718 encoding - invalid - out of bounds tx type":
|
|
let receiptBytes: seq[byte] = @[0x81, 0x80]
|
|
expect MalformedRlpError:
|
|
let _ = rlp.decode(receiptBytes, Receipt)
|
|
|
|
test "Receipts EIP-2718 encoding - invalid - empty receipt payload":
|
|
let receiptBytes: seq[byte] = @[0x02]
|
|
expect RlpTypeMismatch:
|
|
let _ = rlp.decode(receiptBytes, Receipt)
|
|
|
|
test "Receipt legacy":
|
|
const
|
|
# Test payload from
|
|
# https://github.com/ethereum/go-ethereum/blob/253447a4f5e5f7f65c0605d490360bb58fb5f8e0/core/types/receipt_test.go#L417
|
|
payload = "f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"
|
|
receiptsBytes = hexToSeqByte(payload)
|
|
|
|
let receipt = rlp.decode(receiptsBytes, Receipt)
|
|
check receipt.receiptType == LegacyReceipt
|
|
let encoded = rlp.encode(receipt)
|
|
check receiptsBytes == encoded
|
|
|
|
test "Receipt EIP-2930":
|
|
const
|
|
# Test payload from
|
|
# https://github.com/ethereum/go-ethereum/blob/253447a4f5e5f7f65c0605d490360bb58fb5f8e0/core/types/receipt_test.go#L435
|
|
payload = "01f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"
|
|
receiptsBytes = hexToSeqByte(payload)
|
|
|
|
let receipt = rlp.decode(receiptsBytes, Receipt)
|
|
check receipt.receiptType == Eip2930Receipt
|
|
let encoded = rlp.encode(receipt)
|
|
check receiptsBytes == encoded
|
|
|
|
test "Receipt EIP-1559":
|
|
const
|
|
# Test payload from
|
|
# https://github.com/ethereum/go-ethereum/blob/253447a4f5e5f7f65c0605d490360bb58fb5f8e0/core/types/receipt_test.go#L453
|
|
payload = "02f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"
|
|
receiptsBytes = hexToSeqByte(payload)
|
|
|
|
let receipt = rlp.decode(receiptsBytes, Receipt)
|
|
check receipt.receiptType == Eip1559Receipt
|
|
let encoded = rlp.encode(receipt)
|
|
check receiptsBytes == encoded
|