forked from zmitton/eth-proof
-
Notifications
You must be signed in to change notification settings - Fork 0
/
getProof.js
98 lines (79 loc) · 3.34 KB
/
getProof.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
const { encode, toBuffer } = require('eth-util-lite')
const { promisfy } = require('promisfy')
const Tree = require('merkle-patricia-tree')
const Rpc = require('isomorphic-rpc')
const { Header, Proof, Receipt, Transaction } = require('eth-object')
module.exports = class GetProof{
constructor(rpcProvider = "https://mainnet.infura.io"){
this.rpc = new Rpc(rpcProvider)
this.eth_getProof = this.rpc.eth_getProof
}
async transactionProof(txHash){
let targetTx = await this.rpc.eth_getTransactionByHash(txHash)
if(!targetTx){ throw new Error("Tx not found. Use archive node")}
let rpcBlock = await this.rpc.eth_getBlockByHash(targetTx.blockHash, true)
let tree = new Tree();
await Promise.all(rpcBlock.transactions.map((siblingTx, index) => {
let siblingPath = encode(index)
let serializedSiblingTx = Transaction.fromRpc(siblingTx).serialize()
return promisfy(tree.put, tree)(siblingPath, serializedSiblingTx)
}))
let [_,__,stack] = await promisfy(tree.findPath, tree)(encode(targetTx.transactionIndex))
return {
header: Header.fromRpc(rpcBlock),
txProof: Proof.fromStack(stack),
txIndex: targetTx.transactionIndex,
}
}
async receiptProof(txHash){
let targetReceipt = await this.rpc.eth_getTransactionReceipt(txHash)
if(!targetReceipt){ throw new Error("txhash/targetReceipt not found. (use Archive node)")}
let rpcBlock = await this.rpc.eth_getBlockByHash(targetReceipt.blockHash, false)
let receipts = await Promise.all(rpcBlock.transactions.map((siblingTxHash) => {
return this.rpc.eth_getTransactionReceipt(siblingTxHash)
}))
let tree = new Tree();
await Promise.all(receipts.map((siblingReceipt, index) => {
let siblingPath = encode(index)
let serializedReceipt = Receipt.fromRpc(siblingReceipt).serialize()
// Add typed transactions for newer tx versions -> https://eips.ethereum.org/EIPS/eip-2718
if (siblingReceipt.type !== '0x0') {
serializedReceipt = Buffer.concat([toBuffer(siblingReceipt.type), serializedReceipt])
}
return promisfy(tree.put, tree)(siblingPath, serializedReceipt)
}))
let [_,__,stack] = await promisfy(tree.findPath, tree)(encode(targetReceipt.transactionIndex))
return {
header: Header.fromRpc(rpcBlock),
receiptProof: Proof.fromStack(stack),
txIndex: targetReceipt.transactionIndex,
}
}
async accountProof(address, blockHash = null){
let rpcBlock, rpcProof
if(blockHash){
rpcBlock = await this.rpc.eth_getBlockByHash(blockHash, false)
}else{
rpcBlock = await this.rpc.eth_getBlockByNumber('latest', false)
}
rpcProof = await this.eth_getProof(address, [], rpcBlock.number)
return {
header: Header.fromRpc(rpcBlock),
accountProof: Proof.fromRpc(rpcProof.accountProof),
}
}
async storageProof(address, storageAddress, blockHash = null){
let rpcBlock, rpcProof
if(blockHash){
rpcBlock = await this.rpc.eth_getBlockByHash(blockHash, false)
}else{
rpcBlock = await this.rpc.eth_getBlockByNumber('latest', false)
}
rpcProof = await this.eth_getProof(address, [storageAddress], rpcBlock.number)
return {
header: Header.fromRpc(rpcBlock),
accountProof: Proof.fromRpc(rpcProof.accountProof),
storageProof: Proof.fromRpc(rpcProof.storageProof[0].proof),
}
}
}