Skip to content

Commit 433e75b

Browse files
committed
add test helper
1 parent 0e19973 commit 433e75b

File tree

2 files changed

+98
-36
lines changed

2 files changed

+98
-36
lines changed

test/helpers/trie.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
const { ethers } = require('ethers');
2+
const { MerklePatriciaTrie, createMerkleProof } = require('@ethereumjs/mpt');
3+
4+
class BlockTries {
5+
constructor(block) {
6+
this.block = block;
7+
8+
this.transactionTrie = new MerklePatriciaTrie();
9+
this.receiptTrie = new MerklePatriciaTrie();
10+
11+
this._ready = Promise.all(
12+
block.transactions.map(hash =>
13+
block.getTransaction(hash).then(tx =>
14+
Promise.all([
15+
// Transaction
16+
this.transactionTrie.put(BlockTries.indexToKeyBytes(tx.index), BlockTries.serializeTransaction(tx)),
17+
// Receipt
18+
tx
19+
.wait()
20+
.then(receipt =>
21+
this.receiptTrie.put(BlockTries.indexToKeyBytes(tx.index), BlockTries.serializeReceipt(receipt)),
22+
),
23+
]),
24+
),
25+
),
26+
).then(() => this);
27+
}
28+
29+
ready() {
30+
return this._ready;
31+
}
32+
33+
getTransactionProof(index) {
34+
return this.ready().then(() => createMerkleProof(this.transactionTrie, BlockTries.indexToKeyBytes(index)));
35+
}
36+
37+
getReceiptProof(index) {
38+
return this.ready().then(() => createMerkleProof(this.receiptTrie, BlockTries.indexToKeyBytes(index)));
39+
}
40+
41+
get transactionTrieRoot() {
42+
return ethers.hexlify(this.transactionTrie.root());
43+
}
44+
45+
get receiptTrieRoot() {
46+
return ethers.hexlify(this.receiptTrie.root());
47+
}
48+
49+
static from(block) {
50+
const instance = new BlockTries(block);
51+
return instance.ready().then(() => instance);
52+
}
53+
54+
// Serialize a transaction into its RLP encoded form
55+
static serializeTransaction(tx) {
56+
return ethers.Transaction.from(tx).serialized;
57+
}
58+
59+
// Serialize a receipt into its RLP encoded form
60+
static serializeReceipt(receipt) {
61+
return ethers.concat([
62+
receipt.type === 0 ? '0x' : ethers.toBeHex(receipt.type),
63+
ethers.encodeRlp([
64+
receipt.status === 0 ? '0x' : '0x01',
65+
ethers.toBeHex(receipt.cumulativeGasUsed),
66+
receipt.logsBloom,
67+
receipt.logs.map(log => [log.address, log.topics, log.data]),
68+
]),
69+
]);
70+
}
71+
72+
static indexToKey(index) {
73+
return ethers.encodeRlp(ethers.stripZerosLeft(ethers.toBeHex(index)));
74+
}
75+
76+
static indexToKeyBytes(index) {
77+
return ethers.getBytes(BlockTries.indexToKey(index));
78+
}
79+
}
80+
81+
module.exports = { BlockTries };

test/utils/cryptography/TrieProof.test.js

Lines changed: 17 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
const { ethers } = require('hardhat');
22
const { expect } = require('chai');
33
const { spawn } = require('child_process');
4-
const { MerklePatriciaTrie, createMerkleProof } = require('@ethereumjs/mpt');
54

65
const { Enum } = require('../../helpers/enums');
76
const { zip } = require('../../helpers/iterate');
87
const { generators } = require('../../helpers/random');
8+
const { BlockTries } = require('../../helpers/trie');
99
const { batchInBlock } = require('../../helpers/txpool');
1010

1111
const ProofError = Enum(
@@ -82,44 +82,25 @@ describe('TrieProof', function () {
8282
false,
8383
]);
8484

85-
// Rebuild tries
86-
const transactionTrie = new MerklePatriciaTrie();
87-
const receiptTrie = new MerklePatriciaTrie();
88-
89-
for (const tx of txs) {
90-
const key = ethers.encodeRlp(ethers.stripZerosLeft(ethers.toBeHex(tx.index)));
91-
92-
// Transaction
93-
const encodedTransaction = await tx.getTransaction().then(tx => ethers.Transaction.from(tx).serialized);
94-
await transactionTrie.put(ethers.getBytes(key), encodedTransaction);
95-
96-
// Receipt
97-
const encodedReceipt = ethers.concat([
98-
tx.type === 0 ? '0x' : ethers.toBeHex(tx.type),
99-
ethers.encodeRlp([
100-
tx.status === 0 ? '0x' : '0x01',
101-
ethers.toBeHex(tx.cumulativeGasUsed),
102-
tx.logsBloom,
103-
tx.logs.map(log => [log.address, log.topics, log.data]),
104-
]),
105-
]);
106-
await receiptTrie.put(ethers.getBytes(key), encodedReceipt);
107-
108-
Object.assign(tx, { key, encodedTransaction, encodedReceipt });
109-
}
85+
const blockTries = await this.provider.getBlock(txs.at(0).blockNumber).then(BlockTries.from);
11086

11187
// Sanity check trie roots
112-
expect(ethers.hexlify(transactionTrie.root())).to.equal(transactionsRoot);
113-
expect(ethers.hexlify(receiptTrie.root())).to.equal(receiptsRoot);
88+
expect(blockTries.transactionTrieRoot).to.equal(transactionsRoot);
89+
expect(blockTries.receiptTrieRoot).to.equal(receiptsRoot);
11490

115-
// Verify transaction inclusion in the block's transaction trie
116-
for (const { key, encodedTransaction, encodedReceipt } of txs) {
117-
const transactionProof = await createMerkleProof(transactionTrie, ethers.getBytes(key));
118-
await expect(this.mock.$verify(encodedTransaction, transactionsRoot, key, transactionProof)).to.eventually.be
119-
.true;
120-
121-
const receiptProof = await createMerkleProof(receiptTrie, ethers.getBytes(key));
122-
await expect(this.mock.$verify(encodedReceipt, receiptsRoot, key, receiptProof)).to.eventually.be.true;
91+
for (const tx of txs) {
92+
// verify transaction inclusion in the block's transaction trie
93+
const transaction = await tx.getTransaction().then(BlockTries.serializeTransaction);
94+
const transactionProof = await blockTries.getTransactionProof(tx.index);
95+
await expect(
96+
this.mock.$verify(transaction, transactionsRoot, BlockTries.indexToKey(tx.index), transactionProof),
97+
).to.eventually.be.true;
98+
99+
// verify receipt inclusion in the block's receipt trie
100+
const receipt = BlockTries.serializeReceipt(tx);
101+
const receiptProof = await blockTries.getReceiptProof(tx.index);
102+
await expect(this.mock.$verify(receipt, receiptsRoot, BlockTries.indexToKey(tx.index), receiptProof)).to
103+
.eventually.be.true;
123104
}
124105
});
125106

0 commit comments

Comments
 (0)