Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const valid_withdrawals = await withdraw_search(argv.slot, true, argv.accountId, argv.tokenId)
console.log(valid_withdrawals)
if (valid_withdrawals.length == 0) {
callback(`Error: No valid withdraw found in slot ${argv.slot}`)
}
console.log("Reconstructing Merkle Tree from leaf nodes")
const all_withdraws = await withdraw_search(argv.slot)
const withdraw_hashes = Array(2 ** 7).fill(Buffer.alloc(32))
for (let i = 0; i < all_withdraws.length; i++) {
const withdraw = all_withdraws[i]
if (withdraw.valid) {
withdraw_hashes[i] = encodePacked_16_8_128(parseInt(withdraw.accountId, 16), withdraw.tokenId, parseInt(withdraw.amount))
}
}
const tree = new MerkleTree(withdraw_hashes, sha256)
const claimable_root = await instance.getClaimableWithdrawHash(argv.slot)
// Verify merkle roots agree
if (claimable_root != toHex(tree.getRoot())) {
callback(`Merkle Roots disagree: ${claimable_root} != ${toHex(tree.getRoot())}`)
}
for (let i = 0; i < valid_withdrawals.length; i++) {
const toClaim = valid_withdrawals[i]
if (await instance.hasWithdrawBeenClaimed.call(argv.slot, toClaim.slotIndex)) {
console.log("Already claimed:", toClaim)
} else {
console.log("Attempting to claim:", toClaim)
const leaf = encodePacked_16_8_128(argv.accountId, argv.tokenId, parseInt(toClaim.amount))
const proof = Buffer.concat(tree.getProof(leaf).map(x => x.data))
// Could also check if leaf if contained in withdraw_hashes
// Our specific Merkle tree implementation requires that the number of leaves is a power of 2.
// If the number of given leaves is less than a power of 2, we need to round up to the next
// available power of 2. We fill the remaining space with the hash of bytes32(0).
const correctedTreeSize = Math.pow(2, Math.ceil(Math.log2(leaves.length)))
const parsedLeaves = []
for (let i = 0; i < correctedTreeSize; i++) {
if (i < leaves.length) {
parsedLeaves.push(leaves[i])
} else {
parsedLeaves.push(ethers.utils.keccak256('0x' + '00'.repeat(32)))
}
}
// merkletreejs prefers things to be Buffers.
const bufLeaves = parsedLeaves.map(fromHexString)
const tree = new MerkleTree(
bufLeaves,
(el: Buffer | string): Buffer => {
return fromHexString(ethers.utils.keccak256(el))
}
)
const proof = tree.getProof(bufLeaves[index], index).map((element: any) => {
return toHexString(element.data)
})
return proof
}
const _generateMerkleTree = function(...args) {
const txs = Array(2 ** 7).fill(sha256(0x0))
for (let i = 0; i < args.length; i += 2) {
txs[args[i]] = args[i + 1]
}
return new MerkleTree(txs, sha256)
}
const generateMerkleTree = memoize(_generateMerkleTree, {
const mkMerkleProof = (content /*:Buffer*/, ident /*:number*/) => {
if (content.length <= 32) { throw new Error("Content is too short to make a tree"); }
const arr = split(content);
const blocknum = ident % arr.length;
const mt = new MerkleTree(arr, Util.b2hash32);
return mkProof(mt, arr, blocknum);
};
if (i < header.stateRoots.length) {
elements.push(header.stateRoots[i])
} else {
elements.push(ethers.utils.keccak256('0x' + '00'.repeat(32)))
}
}
const hash = (el: Buffer | string): Buffer => {
return Buffer.from(ethers.utils.keccak256(el).slice(2), 'hex')
}
const leaves = elements.map((element) => {
return fromHexString(element)
})
const tree = new MerkleTree(leaves, hash)
const index =
message.parentTransactionIndex - header.batch.prevTotalElements.toNumber()
const treeProof = tree.getProof(leaves[index], index).map((element) => {
return element.data
})
return {
stateRoot: header.stateRoots[index],
stateRootBatchHeader: header.batch,
stateRootProof: {
index,
siblings: treeProof,
},
stateTrieWitness: rlp.encode(proof.accountProof),
storageTrieWitness: rlp.encode(proof.storageProof[0].proof),
}
asMerkleTree () {
return new MerkleTree(this.asArray(), this.sha256, {
isBitcoinTree: true
});
}