use merkle tree from npm

This commit is contained in:
poma 2020-07-31 18:38:50 +01:00
parent 801f29a4b7
commit 0c6e638852
No known key found for this signature in database
GPG Key ID: BA20CB01FE165657
10 changed files with 396 additions and 420 deletions

10
cli.js
View File

@ -10,7 +10,7 @@ const snarkjs = require('snarkjs')
const crypto = require('crypto')
const circomlib = require('circomlib')
const bigInt = snarkjs.bigInt
const merkleTree = require('./lib/MerkleTree')
const merkleTree = require('fixed-merkle-tree')
const Web3 = require('web3')
const buildGroth16 = require('websnark/src/groth16')
const websnarkUtils = require('websnark/src/utils')
@ -126,7 +126,7 @@ async function generateMerkleProof(deposit) {
const leafIndex = depositEvent ? depositEvent.returnValues.leafIndex : -1
// Validate that our data is correct
const root = await tree.root()
const root = tree.root()
const isValidRoot = await tornado.methods.isKnownRoot(toHex(root)).call()
const isSpent = await tornado.methods.isSpent(toHex(deposit.nullifierHash)).call()
assert(isValidRoot === true, 'Merkle tree is corrupted')
@ -147,7 +147,7 @@ async function generateMerkleProof(deposit) {
*/
async function generateProof({ deposit, recipient, relayerAddress = 0, fee = 0, refund = 0 }) {
// Compute merkle proof of our commitment
const { root, path_elements, path_index } = await generateMerkleProof(deposit)
const { root, pathElements, pathIndices } = await generateMerkleProof(deposit)
// Prepare circuit input
const input = {
@ -162,8 +162,8 @@ async function generateProof({ deposit, recipient, relayerAddress = 0, fee = 0,
// Private snark inputs
nullifier: deposit.nullifier,
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
}
console.log('Generating SNARK proof')

View File

@ -1,186 +0,0 @@
const jsStorage = require('./Storage')
const hasherImpl = require('./MiMC')
class MerkleTree {
constructor(n_levels, defaultElements, prefix, storage, hasher) {
this.prefix = prefix
this.storage = storage || new jsStorage()
this.hasher = hasher || new hasherImpl()
this.n_levels = n_levels
this.zero_values = []
this.totalElements = 0
let current_zero_value = '21663839004416932945382355908790599225266501822907911457504978515578255421292'
this.zero_values.push(current_zero_value)
for (let i = 0; i < n_levels; i++) {
current_zero_value = this.hasher.hash(i, current_zero_value, current_zero_value)
this.zero_values.push(current_zero_value.toString())
}
if (defaultElements) {
let level = 0
this.totalElements = defaultElements.length
defaultElements.forEach((element, i) => {
this.storage.put(MerkleTree.index_to_key(prefix, level, i), element)
})
level++
let numberOfElementsInLevel = Math.ceil(defaultElements.length / 2)
for (level; level <= this.n_levels; level++) {
for (let i = 0; i < numberOfElementsInLevel; i++) {
const leftKey = MerkleTree.index_to_key(prefix, level - 1, 2 * i)
const rightKey = MerkleTree.index_to_key(prefix, level - 1, 2 * i + 1)
const left = this.storage.get(leftKey)
const right = this.storage.get_or_element(rightKey, this.zero_values[level - 1])
const subRoot = this.hasher.hash(null, left, right)
this.storage.put(MerkleTree.index_to_key(prefix, level, i), subRoot)
}
numberOfElementsInLevel = Math.ceil(numberOfElementsInLevel / 2)
}
}
}
static index_to_key(prefix, level, index) {
const key = `${prefix}_tree_${level}_${index}`
return key
}
async root() {
let root = await this.storage.get_or_element(
MerkleTree.index_to_key(this.prefix, this.n_levels, 0),
this.zero_values[this.n_levels],
)
return root
}
async path(index) {
class PathTraverser {
constructor(prefix, storage, zero_values) {
this.prefix = prefix
this.storage = storage
this.zero_values = zero_values
this.path_elements = []
this.path_index = []
}
async handle_index(level, element_index, sibling_index) {
const sibling = await this.storage.get_or_element(
MerkleTree.index_to_key(this.prefix, level, sibling_index),
this.zero_values[level],
)
this.path_elements.push(sibling)
this.path_index.push(element_index % 2)
}
}
index = Number(index)
let traverser = new PathTraverser(this.prefix, this.storage, this.zero_values)
const root = await this.storage.get_or_element(
MerkleTree.index_to_key(this.prefix, this.n_levels, 0),
this.zero_values[this.n_levels],
)
const element = await this.storage.get_or_element(
MerkleTree.index_to_key(this.prefix, 0, index),
this.zero_values[0],
)
await this.traverse(index, traverser)
return {
root,
path_elements: traverser.path_elements,
path_index: traverser.path_index,
element,
}
}
async update(index, element, insert = false) {
if (!insert && index >= this.totalElements) {
throw Error('Use insert method for new elements.')
} else if (insert && index < this.totalElements) {
throw Error('Use update method for existing elements.')
}
try {
class UpdateTraverser {
constructor(prefix, storage, hasher, element, zero_values) {
this.prefix = prefix
this.current_element = element
this.zero_values = zero_values
this.storage = storage
this.hasher = hasher
this.key_values_to_put = []
}
async handle_index(level, element_index, sibling_index) {
if (level == 0) {
this.original_element = await this.storage.get_or_element(
MerkleTree.index_to_key(this.prefix, level, element_index),
this.zero_values[level],
)
}
const sibling = await this.storage.get_or_element(
MerkleTree.index_to_key(this.prefix, level, sibling_index),
this.zero_values[level],
)
let left, right
if (element_index % 2 == 0) {
left = this.current_element
right = sibling
} else {
left = sibling
right = this.current_element
}
this.key_values_to_put.push({
key: MerkleTree.index_to_key(this.prefix, level, element_index),
value: this.current_element,
})
this.current_element = this.hasher.hash(level, left, right)
}
}
let traverser = new UpdateTraverser(this.prefix, this.storage, this.hasher, element, this.zero_values)
await this.traverse(index, traverser)
traverser.key_values_to_put.push({
key: MerkleTree.index_to_key(this.prefix, this.n_levels, 0),
value: traverser.current_element,
})
await this.storage.put_batch(traverser.key_values_to_put)
} catch (e) {
console.error(e)
}
}
async insert(element) {
const index = this.totalElements
await this.update(index, element, true)
this.totalElements++
}
async traverse(index, handler) {
let current_index = index
for (let i = 0; i < this.n_levels; i++) {
let sibling_index = current_index
if (current_index % 2 == 0) {
sibling_index += 1
} else {
sibling_index -= 1
}
await handler.handle_index(i, current_index, sibling_index)
current_index = Math.floor(current_index / 2)
}
}
getIndexByElement(element) {
for (let i = this.totalElements - 1; i >= 0; i--) {
const elementFromTree = this.storage.get(MerkleTree.index_to_key(this.prefix, 0, i))
if (elementFromTree === element) {
return i
}
}
return false
}
}
module.exports = MerkleTree

View File

@ -1,13 +0,0 @@
const circomlib = require('circomlib')
const mimcsponge = circomlib.mimcsponge
const snarkjs = require('snarkjs')
const bigInt = snarkjs.bigInt
class MimcSpongeHasher {
hash(level, left, right) {
return mimcsponge.multiHash([bigInt(left), bigInt(right)]).toString()
}
}
module.exports = MimcSpongeHasher

View File

@ -1,37 +0,0 @@
class JsStorage {
constructor() {
this.db = {}
}
get(key) {
return this.db[key]
}
get_or_element(key, defaultElement) {
const element = this.db[key]
if (element === undefined) {
return defaultElement
} else {
return element
}
}
put(key, value) {
if (key === undefined || value === undefined) {
throw Error('key or value is undefined')
}
this.db[key] = value
}
del(key) {
delete this.db[key]
}
put_batch(key_values) {
key_values.forEach((element) => {
this.db[element.key] = element.value
})
}
}
module.exports = JsStorage

View File

@ -3,7 +3,7 @@ const assert = require('assert')
const { bigInt } = require('snarkjs')
const crypto = require('crypto')
const circomlib = require('circomlib')
const merkleTree = require('./lib/MerkleTree')
const merkleTree = require('fixed-merkle-tree')
const Web3 = require('web3')
const buildGroth16 = require('websnark/src/groth16')
const websnarkUtils = require('websnark/src/utils')
@ -99,14 +99,14 @@ async function generateMerkleProof(deposit) {
let leafIndex = depositEvent ? depositEvent.returnValues.leafIndex : -1
// Validate that our data is correct (optional)
const isValidRoot = await contract.methods.isKnownRoot(toHex(await tree.root())).call()
const isValidRoot = await contract.methods.isKnownRoot(toHex(tree.root())).call()
const isSpent = await contract.methods.isSpent(toHex(deposit.nullifierHash)).call()
assert(isValidRoot === true, 'Merkle tree is corrupted')
assert(isSpent === false, 'The note is already spent')
assert(leafIndex >= 0, 'The deposit is not found in the tree')
// Compute merkle proof of our commitment
return await tree.path(leafIndex)
return tree.path(leafIndex)
}
/**
@ -116,7 +116,7 @@ async function generateMerkleProof(deposit) {
*/
async function generateSnarkProof(deposit, recipient) {
// Compute merkle proof of our commitment
const { root, path_elements, path_index } = await generateMerkleProof(deposit)
const { root, pathElements, pathIndices } = generateMerkleProof(deposit)
// Prepare circuit input
const input = {
@ -131,8 +131,8 @@ async function generateSnarkProof(deposit, recipient) {
// Private snark inputs
nullifier: deposit.nullifier,
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
}
console.log('Generating SNARK proof...')

View File

@ -47,6 +47,7 @@
"eslint-config-prettier": "^7.2.0",
"eslint-plugin-prettier": "^3.3.1",
"eth-json-rpc-filters": "^4.1.1",
"fixed-merkle-tree": "^0.6.0",
"ganache-cli": "^6.7.0",
"prettier": "^2.2.1",
"prettier-plugin-solidity": "^1.0.0-beta.3",

View File

@ -18,7 +18,7 @@ const snarkjs = require('snarkjs')
const bigInt = snarkjs.bigInt
const crypto = require('crypto')
const circomlib = require('circomlib')
const MerkleTree = require('../lib/MerkleTree')
const MerkleTree = require('fixed-merkle-tree')
const rbigint = (nbytes) => snarkjs.bigInt.leBuff2int(crypto.randomBytes(nbytes))
const pedersenHash = (data) => circomlib.babyJub.unpackPoint(circomlib.pedersenHash.hash(data))[0]
@ -49,7 +49,6 @@ contract('ERC20Tornado', (accounts) => {
const levels = MERKLE_TREE_HEIGHT || 16
let tokenDenomination = TOKEN_AMOUNT || '1000000000000000000' // 1 ether
let snapshotId
let prefix = 'test'
let tree
const fee = bigInt(ETH_AMOUNT).shr(1) || bigInt(1e17)
const refund = ETH_AMOUNT || '1000000000000000000' // 1 ether
@ -60,7 +59,7 @@ contract('ERC20Tornado', (accounts) => {
let proving_key
before(async () => {
tree = new MerkleTree(levels, null, prefix)
tree = new MerkleTree(levels)
tornado = await Tornado.deployed()
if (ERC20_TOKEN) {
token = await Token.at(ERC20_TOKEN)
@ -108,7 +107,7 @@ contract('ERC20Tornado', (accounts) => {
it('should work', async () => {
const deposit = generateDeposit()
const user = accounts[4]
await tree.insert(deposit.commitment)
tree.insert(deposit.commitment)
await token.mint(user, tokenDenomination)
const balanceUserBefore = await token.balanceOf(user)
@ -121,11 +120,11 @@ contract('ERC20Tornado', (accounts) => {
const balanceUserAfter = await token.balanceOf(user)
balanceUserAfter.should.be.eq.BN(toBN(balanceUserBefore).sub(toBN(tokenDenomination)))
const { root, path_elements, path_index } = await tree.path(0)
const { pathElements, pathIndices } = tree.path(0)
// Circuit input
const input = stringifyBigInts({
// public
root,
root: tree.root(),
nullifierHash: pedersenHash(deposit.nullifier.leInt2Buff(31)),
relayer,
recipient,
@ -135,8 +134,8 @@ contract('ERC20Tornado', (accounts) => {
// private
nullifier: deposit.nullifier,
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
@ -193,7 +192,7 @@ contract('ERC20Tornado', (accounts) => {
const deposit = generateDeposit()
const user = accounts[4]
recipient = bigInt(badRecipient.address)
await tree.insert(deposit.commitment)
tree.insert(deposit.commitment)
await token.mint(user, tokenDenomination)
const balanceUserBefore = await token.balanceOf(user)
@ -203,11 +202,11 @@ contract('ERC20Tornado', (accounts) => {
const balanceUserAfter = await token.balanceOf(user)
balanceUserAfter.should.be.eq.BN(toBN(balanceUserBefore).sub(toBN(tokenDenomination)))
const { root, path_elements, path_index } = await tree.path(0)
const { pathElements, pathIndices } = tree.path(0)
// Circuit input
const input = stringifyBigInts({
// public
root,
root: tree.root(),
nullifierHash: pedersenHash(deposit.nullifier.leInt2Buff(31)),
relayer,
recipient,
@ -217,8 +216,8 @@ contract('ERC20Tornado', (accounts) => {
// private
nullifier: deposit.nullifier,
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
@ -272,16 +271,16 @@ contract('ERC20Tornado', (accounts) => {
it('should reject with wrong refund value', async () => {
const deposit = generateDeposit()
const user = accounts[4]
await tree.insert(deposit.commitment)
tree.insert(deposit.commitment)
await token.mint(user, tokenDenomination)
await token.approve(tornado.address, tokenDenomination, { from: user })
await tornado.deposit(toFixedHex(deposit.commitment), { from: user, gasPrice: '0' })
const { root, path_elements, path_index } = await tree.path(0)
const { pathElements, pathIndices } = tree.path(0)
// Circuit input
const input = stringifyBigInts({
// public
root,
root: tree.root(),
nullifierHash: pedersenHash(deposit.nullifier.leInt2Buff(31)),
relayer,
recipient,
@ -291,8 +290,8 @@ contract('ERC20Tornado', (accounts) => {
// private
nullifier: deposit.nullifier,
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
@ -329,7 +328,7 @@ contract('ERC20Tornado', (accounts) => {
console.log('userBal', userBal.toString())
const senderBal = await usdtToken.balanceOf(sender)
console.log('senderBal', senderBal.toString())
await tree.insert(deposit.commitment)
tree.insert(deposit.commitment)
await usdtToken.transfer(user, tokenDenomination, { from: sender })
console.log('transfer done')
@ -345,12 +344,12 @@ contract('ERC20Tornado', (accounts) => {
const balanceUserAfter = await usdtToken.balanceOf(user)
balanceUserAfter.should.be.eq.BN(toBN(balanceUserBefore).sub(toBN(tokenDenomination)))
const { root, path_elements, path_index } = await tree.path(0)
const { pathElements, pathIndices } = tree.path(0)
// Circuit input
const input = stringifyBigInts({
// public
root,
root: tree.root(),
nullifierHash: pedersenHash(deposit.nullifier.leInt2Buff(31)),
relayer: operator,
recipient,
@ -360,8 +359,8 @@ contract('ERC20Tornado', (accounts) => {
// private
nullifier: deposit.nullifier,
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
@ -418,7 +417,7 @@ contract('ERC20Tornado', (accounts) => {
console.log('userBal', userBal.toString())
const senderBal = await token.balanceOf(sender)
console.log('senderBal', senderBal.toString())
await tree.insert(deposit.commitment)
tree.insert(deposit.commitment)
await token.transfer(user, tokenDenomination, { from: sender })
console.log('transfer done')
@ -432,12 +431,12 @@ contract('ERC20Tornado', (accounts) => {
const balanceUserAfter = await token.balanceOf(user)
balanceUserAfter.should.be.eq.BN(toBN(balanceUserBefore).sub(toBN(tokenDenomination)))
const { root, path_elements, path_index } = await tree.path(0)
const { pathElements, pathIndices } = tree.path(0)
// Circuit input
const input = stringifyBigInts({
// public
root,
root: tree.root(),
nullifierHash: pedersenHash(deposit.nullifier.leInt2Buff(31)),
relayer: operator,
recipient,
@ -447,8 +446,8 @@ contract('ERC20Tornado', (accounts) => {
// private
nullifier: deposit.nullifier,
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
@ -501,6 +500,6 @@ contract('ERC20Tornado', (accounts) => {
await revertSnapshot(snapshotId.result)
// eslint-disable-next-line require-atomic-updates
snapshotId = await takeSnapshot()
tree = new MerkleTree(levels, null, prefix)
tree = new MerkleTree(levels)
})
})

View File

@ -16,7 +16,7 @@ const snarkjs = require('snarkjs')
const bigInt = snarkjs.bigInt
const crypto = require('crypto')
const circomlib = require('circomlib')
const MerkleTree = require('../lib/MerkleTree')
const MerkleTree = require('fixed-merkle-tree')
const rbigint = (nbytes) => snarkjs.bigInt.leBuff2int(crypto.randomBytes(nbytes))
const pedersenHash = (data) => circomlib.babyJub.unpackPoint(circomlib.pedersenHash.hash(data))[0]
@ -59,7 +59,6 @@ contract('ETHTornado', (accounts) => {
const levels = MERKLE_TREE_HEIGHT || 16
const value = ETH_AMOUNT || '1000000000000000000' // 1 ether
let snapshotId
let prefix = 'test'
let tree
const fee = bigInt(ETH_AMOUNT).shr(1) || bigInt(1e17)
const refund = bigInt(0)
@ -70,7 +69,7 @@ contract('ETHTornado', (accounts) => {
let proving_key
before(async () => {
tree = new MerkleTree(levels, null, prefix)
tree = new MerkleTree(levels)
tornado = await Tornado.deployed()
snapshotId = await takeSnapshot()
groth16 = await buildGroth16()
@ -113,11 +112,11 @@ contract('ETHTornado', (accounts) => {
describe('snark proof verification on js side', () => {
it('should detect tampering', async () => {
const deposit = generateDeposit()
await tree.insert(deposit.commitment)
const { root, path_elements, path_index } = await tree.path(0)
tree.insert(deposit.commitment)
const { pathElements, pathIndices } = tree.path(0)
const input = stringifyBigInts({
root,
root: tree.root(),
nullifierHash: pedersenHash(deposit.nullifier.leInt2Buff(31)),
nullifier: deposit.nullifier,
relayer: operator,
@ -125,8 +124,8 @@ contract('ETHTornado', (accounts) => {
fee,
refund,
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
})
let proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
@ -159,7 +158,7 @@ contract('ETHTornado', (accounts) => {
it('should work', async () => {
const deposit = generateDeposit()
const user = accounts[4]
await tree.insert(deposit.commitment)
tree.insert(deposit.commitment)
const balanceUserBefore = await web3.eth.getBalance(user)
@ -171,12 +170,12 @@ contract('ETHTornado', (accounts) => {
const balanceUserAfter = await web3.eth.getBalance(user)
balanceUserAfter.should.be.eq.BN(toBN(balanceUserBefore).sub(toBN(value)))
const { root, path_elements, path_index } = await tree.path(0)
const { pathElements, pathIndices } = tree.path(0)
// Circuit input
const input = stringifyBigInts({
// public
root,
root: tree.root(),
nullifierHash: pedersenHash(deposit.nullifier.leInt2Buff(31)),
relayer: operator,
recipient,
@ -186,8 +185,8 @@ contract('ETHTornado', (accounts) => {
// private
nullifier: deposit.nullifier,
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
@ -233,13 +232,13 @@ contract('ETHTornado', (accounts) => {
it('should prevent double spend', async () => {
const deposit = generateDeposit()
await tree.insert(deposit.commitment)
tree.insert(deposit.commitment)
await tornado.deposit(toFixedHex(deposit.commitment), { value, from: sender })
const { root, path_elements, path_index } = await tree.path(0)
const { pathElements, pathIndices } = tree.path(0)
const input = stringifyBigInts({
root,
root: tree.root(),
nullifierHash: pedersenHash(deposit.nullifier.leInt2Buff(31)),
nullifier: deposit.nullifier,
relayer: operator,
@ -247,8 +246,8 @@ contract('ETHTornado', (accounts) => {
fee,
refund,
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
const { proof } = websnarkUtils.toSolidityInput(proofData)
@ -267,13 +266,13 @@ contract('ETHTornado', (accounts) => {
it('should prevent double spend with overflow', async () => {
const deposit = generateDeposit()
await tree.insert(deposit.commitment)
tree.insert(deposit.commitment)
await tornado.deposit(toFixedHex(deposit.commitment), { value, from: sender })
const { root, path_elements, path_index } = await tree.path(0)
const { pathElements, pathIndices } = tree.path(0)
const input = stringifyBigInts({
root,
root: tree.root(),
nullifierHash: pedersenHash(deposit.nullifier.leInt2Buff(31)),
nullifier: deposit.nullifier,
relayer: operator,
@ -281,8 +280,8 @@ contract('ETHTornado', (accounts) => {
fee,
refund,
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
const { proof } = websnarkUtils.toSolidityInput(proofData)
@ -304,13 +303,13 @@ contract('ETHTornado', (accounts) => {
it('fee should be less or equal transfer value', async () => {
const deposit = generateDeposit()
await tree.insert(deposit.commitment)
tree.insert(deposit.commitment)
await tornado.deposit(toFixedHex(deposit.commitment), { value, from: sender })
const { root, path_elements, path_index } = await tree.path(0)
const { pathElements, pathIndices } = tree.path(0)
const largeFee = bigInt(value).add(bigInt(1))
const input = stringifyBigInts({
root,
root: tree.root(),
nullifierHash: pedersenHash(deposit.nullifier.leInt2Buff(31)),
nullifier: deposit.nullifier,
relayer: operator,
@ -318,8 +317,8 @@ contract('ETHTornado', (accounts) => {
fee: largeFee,
refund,
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
@ -338,22 +337,22 @@ contract('ETHTornado', (accounts) => {
it('should throw for corrupted merkle tree root', async () => {
const deposit = generateDeposit()
await tree.insert(deposit.commitment)
tree.insert(deposit.commitment)
await tornado.deposit(toFixedHex(deposit.commitment), { value, from: sender })
const { root, path_elements, path_index } = await tree.path(0)
const { pathElements, pathIndices } = tree.path(0)
const input = stringifyBigInts({
nullifierHash: pedersenHash(deposit.nullifier.leInt2Buff(31)),
root,
root: tree.root(),
nullifier: deposit.nullifier,
relayer: operator,
recipient,
fee,
refund,
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
@ -373,13 +372,13 @@ contract('ETHTornado', (accounts) => {
it('should reject with tampered public inputs', async () => {
const deposit = generateDeposit()
await tree.insert(deposit.commitment)
tree.insert(deposit.commitment)
await tornado.deposit(toFixedHex(deposit.commitment), { value, from: sender })
let { root, path_elements, path_index } = await tree.path(0)
let { pathElements, pathIndices } = tree.path(0)
const input = stringifyBigInts({
root,
root: tree.root(),
nullifierHash: pedersenHash(deposit.nullifier.leInt2Buff(31)),
nullifier: deposit.nullifier,
relayer: operator,
@ -387,8 +386,8 @@ contract('ETHTornado', (accounts) => {
fee,
refund,
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
let { proof } = websnarkUtils.toSolidityInput(proofData)
@ -449,22 +448,22 @@ contract('ETHTornado', (accounts) => {
it('should reject with non zero refund', async () => {
const deposit = generateDeposit()
await tree.insert(deposit.commitment)
tree.insert(deposit.commitment)
await tornado.deposit(toFixedHex(deposit.commitment), { value, from: sender })
const { root, path_elements, path_index } = await tree.path(0)
const { pathElements, pathIndices } = tree.path(0)
const input = stringifyBigInts({
nullifierHash: pedersenHash(deposit.nullifier.leInt2Buff(31)),
root,
root: tree.root(),
nullifier: deposit.nullifier,
relayer: operator,
recipient,
fee,
refund: bigInt(1),
secret: deposit.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
@ -487,17 +486,17 @@ contract('ETHTornado', (accounts) => {
it('should work', async () => {
const deposit1 = generateDeposit()
const deposit2 = generateDeposit()
await tree.insert(deposit1.commitment)
await tree.insert(deposit2.commitment)
tree.insert(deposit1.commitment)
tree.insert(deposit2.commitment)
await tornado.deposit(toFixedHex(deposit1.commitment), { value, gasPrice: '0' })
await tornado.deposit(toFixedHex(deposit2.commitment), { value, gasPrice: '0' })
const { root, path_elements, path_index } = await tree.path(1)
const { pathElements, pathIndices } = tree.path(1)
// Circuit input
const input = stringifyBigInts({
// public
root,
root: tree.root(),
nullifierHash: pedersenHash(deposit2.nullifier.leInt2Buff(31)),
relayer: operator,
recipient,
@ -507,8 +506,8 @@ contract('ETHTornado', (accounts) => {
// private
nullifier: deposit2.nullifier,
secret: deposit2.secret,
pathElements: path_elements,
pathIndices: path_index,
pathElements: pathElements,
pathIndices: pathIndices,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
@ -536,6 +535,6 @@ contract('ETHTornado', (accounts) => {
await revertSnapshot(snapshotId.result)
// eslint-disable-next-line require-atomic-updates
snapshotId = await takeSnapshot()
tree = new MerkleTree(levels, null, prefix)
tree = new MerkleTree(levels)
})
})

View File

@ -1,4 +1,4 @@
/* global artifacts, web3, contract, assert */
/* global artifacts, web3, contract */
require('chai').use(require('bn-chai')(web3.utils.BN)).use(require('chai-as-promised')).should()
const { takeSnapshot, revertSnapshot } = require('../lib/ganacheHelper')
@ -6,8 +6,7 @@ const { takeSnapshot, revertSnapshot } = require('../lib/ganacheHelper')
const MerkleTreeWithHistory = artifacts.require('./MerkleTreeWithHistoryMock.sol')
const hasherContract = artifacts.require('./Hasher.sol')
const MerkleTree = require('../lib/MerkleTree')
const hasherImpl = require('../lib/MiMC')
const MerkleTree = require('fixed-merkle-tree')
const snarkjs = require('snarkjs')
const bigInt = snarkjs.bigInt
@ -38,12 +37,10 @@ contract('MerkleTreeWithHistory', (accounts) => {
// eslint-disable-next-line no-unused-vars
const value = ETH_AMOUNT || '1000000000000000000'
let snapshotId
let prefix = 'test'
let tree
let hasher
before(async () => {
tree = new MerkleTree(levels, null, prefix)
tree = new MerkleTree(levels)
hasherInstance = await hasherContract.deployed()
merkleTreeWithHistory = await MerkleTreeWithHistory.new(levels, hasherInstance.address)
snapshotId = await takeSnapshot()
@ -59,94 +56,15 @@ contract('MerkleTreeWithHistory', (accounts) => {
})
})
describe('merkleTreeLib', () => {
it('index_to_key', () => {
assert.equal(MerkleTree.index_to_key('test', 5, 20), 'test_tree_5_20')
})
it('tests insert', async () => {
hasher = new hasherImpl()
tree = new MerkleTree(2, null, prefix)
await tree.insert(toFixedHex('5'))
let { root, path_elements } = await tree.path(0)
const calculated_root = hasher.hash(null, hasher.hash(null, '5', path_elements[0]), path_elements[1])
// console.log(root)
assert.equal(root, calculated_root)
})
it('creation odd elements count', async () => {
const elements = [12, 13, 14, 15, 16, 17, 18, 19, 20]
for (const [, el] of Object.entries(elements)) {
await tree.insert(el)
}
const batchTree = new MerkleTree(levels, elements, prefix)
for (const [i] of Object.entries(elements)) {
const pathViaConstructor = await batchTree.path(i)
const pathViaUpdate = await tree.path(i)
pathViaConstructor.should.be.deep.equal(pathViaUpdate)
}
})
it('should find an element', async () => {
const elements = [12, 13, 14, 15, 16, 17, 18, 19, 20]
for (const [, el] of Object.entries(elements)) {
await tree.insert(el)
}
let index = tree.getIndexByElement(13)
index.should.be.equal(1)
index = tree.getIndexByElement(19)
index.should.be.equal(7)
index = tree.getIndexByElement(12)
index.should.be.equal(0)
index = tree.getIndexByElement(20)
index.should.be.equal(8)
index = tree.getIndexByElement(42)
index.should.be.equal(false)
})
it('creation even elements count', async () => {
const elements = [12, 13, 14, 15, 16, 17]
for (const [, el] of Object.entries(elements)) {
await tree.insert(el)
}
const batchTree = new MerkleTree(levels, elements, prefix)
for (const [i] of Object.entries(elements)) {
const pathViaConstructor = await batchTree.path(i)
const pathViaUpdate = await tree.path(i)
pathViaConstructor.should.be.deep.equal(pathViaUpdate)
}
})
it.skip('creation using 30000 elements', () => {
const elements = []
for (let i = 1000; i < 31001; i++) {
elements.push(i)
}
console.time('MerkleTree')
tree = new MerkleTree(levels, elements, prefix)
console.timeEnd('MerkleTree')
// 2,7 GHz Intel Core i7
// 1000 : 1949.084ms
// 10000: 19456.220ms
// 30000: 63406.679ms
})
})
describe('#insert', () => {
it('should insert', async () => {
let rootFromContract
for (let i = 1; i < 11; i++) {
await merkleTreeWithHistory.insert(toFixedHex(i), { from: sender })
await tree.insert(i)
let { root } = await tree.path(i - 1)
tree.insert(i)
rootFromContract = await merkleTreeWithHistory.getLastRoot()
toFixedHex(root).should.be.equal(rootFromContract.toString())
toFixedHex(tree.root()).should.be.equal(rootFromContract.toString())
}
})
@ -177,19 +95,16 @@ contract('MerkleTreeWithHistory', (accounts) => {
describe('#isKnownRoot', () => {
it('should work', async () => {
let path
for (let i = 1; i < 5; i++) {
await merkleTreeWithHistory.insert(toFixedHex(i), { from: sender }).should.be.fulfilled
await tree.insert(i)
path = await tree.path(i - 1)
let isKnown = await merkleTreeWithHistory.isKnownRoot(toFixedHex(path.root))
let isKnown = await merkleTreeWithHistory.isKnownRoot(toFixedHex(tree.root()))
isKnown.should.be.equal(true)
}
await merkleTreeWithHistory.insert(toFixedHex(42), { from: sender }).should.be.fulfilled
// check outdated root
let isKnown = await merkleTreeWithHistory.isKnownRoot(toFixedHex(path.root))
let isKnown = await merkleTreeWithHistory.isKnownRoot(toFixedHex(tree.root()))
isKnown.should.be.equal(true)
})
@ -204,7 +119,6 @@ contract('MerkleTreeWithHistory', (accounts) => {
await revertSnapshot(snapshotId.result)
// eslint-disable-next-line require-atomic-updates
snapshotId = await takeSnapshot()
hasher = new hasherImpl()
tree = new MerkleTree(levels, null, prefix, null, hasher)
tree = new MerkleTree(levels)
})
})

299
yarn.lock
View File

@ -622,6 +622,22 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
"@ethereumjs/common@^2.3.0", "@ethereumjs/common@^2.4.0", "@ethereumjs/common@^2.5.0":
version "2.5.0"
resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.5.0.tgz#ec61551b31bef7a69d1dc634d8932468866a4268"
integrity sha512-DEHjW6e38o+JmB/NO3GZBpW4lpaiBpkFgXF6jLcJ6gETBYpEyaA5nTimsWBUJR3Vmtm/didUEbNjajskugZORg==
dependencies:
crc-32 "^1.2.0"
ethereumjs-util "^7.1.1"
"@ethereumjs/tx@^3.2.1":
version "3.3.2"
resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.3.2.tgz#348d4624bf248aaab6c44fec2ae67265efe3db00"
integrity sha512-6AaJhwg4ucmwTvw/1qLaZUX5miWrwZ4nLOUsKyb/HtzS3BMw/CasKhdi1ims9mBKeK9sOJCH4qGKOBGyJCeeog==
dependencies:
"@ethereumjs/common" "^2.5.0"
ethereumjs-util "^7.1.2"
"@ethersproject/abi@5.0.0-beta.153":
version "5.0.0-beta.153"
resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee"
@ -1643,6 +1659,13 @@
dependencies:
"@types/node" "*"
"@types/bn.js@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68"
integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==
dependencies:
"@types/node" "*"
"@types/body-parser@*", "@types/body-parser@1.19.0":
version "1.19.0"
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f"
@ -3313,6 +3336,16 @@ circom@^0.0.35:
optimist "^0.6.1"
yargs "^12.0.2"
"circomlib@git+https://github.com/tornadocash/circomlib.git#5beb6aee94923052faeecea40135d45b6ce6172c":
version "0.0.20"
resolved "git+https://github.com/tornadocash/circomlib.git#5beb6aee94923052faeecea40135d45b6ce6172c"
dependencies:
blake-hash "^1.1.0"
blake2b "^2.1.3"
snarkjs "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5"
typedarray-to-buffer "^3.1.5"
web3 "^1.2.11"
"circomlib@git+https://github.com/tornadocash/circomlib.git#c372f14d324d57339c88451834bf2824e73bbdbc":
version "0.0.20"
resolved "git+https://github.com/tornadocash/circomlib.git#c372f14d324d57339c88451834bf2824e73bbdbc"
@ -3624,6 +3657,14 @@ cors@^2.8.1, cors@^2.8.4:
object-assign "^4"
vary "^1"
crc-32@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208"
integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==
dependencies:
exit-on-epipe "~1.0.1"
printj "~1.1.0"
create-ecdh@^4.0.0:
version "4.0.4"
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e"
@ -4931,6 +4972,17 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereum
rlp "^2.0.0"
safe-buffer "^5.1.1"
ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2:
version "7.1.3"
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz#b55d7b64dde3e3e45749e4c41288238edec32d23"
integrity sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw==
dependencies:
"@types/bn.js" "^5.1.0"
bn.js "^5.1.2"
create-hash "^1.1.2"
ethereum-cryptography "^0.1.3"
rlp "^2.2.4"
ethereumjs-util@^7.0.2:
version "7.0.7"
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.0.7.tgz#484fb9c03b766b2ee64821281070616562fb5a59"
@ -5063,6 +5115,11 @@ execa@^1.0.0:
signal-exit "^3.0.0"
strip-eof "^1.0.0"
exit-on-epipe@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692"
integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==
expand-brackets@^0.1.4:
version "0.1.5"
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
@ -5383,6 +5440,14 @@ first-chunk-stream@^1.0.0:
resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e"
integrity sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=
fixed-merkle-tree@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/fixed-merkle-tree/-/fixed-merkle-tree-0.6.0.tgz#523afc95836999bc7962ad3871afd2a1f2f78e04"
integrity sha512-qxY7IQuiIE7l/bKIFcgS8ZdHUwNapaE+HwELw6h0QBZ4V+6tqdea6z8iAFKO7B90ZgVfyoj4evAIMsd+J9HN0g==
dependencies:
circomlib "git+https://github.com/tornadocash/circomlib.git#5beb6aee94923052faeecea40135d45b6ce6172c"
snarkjs "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5"
flat-cache@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0"
@ -8962,6 +9027,11 @@ prettier@^2.2.1:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5"
integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==
printj@~1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==
process-nextick-args@~1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
@ -11127,6 +11197,15 @@ web3-bzz@1.3.4:
swarm-js "^0.1.40"
underscore "1.9.1"
web3-bzz@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.6.0.tgz#584b51339f21eedff159abc9239b4b7ef6ded840"
integrity sha512-ugYV6BsinwhIi0CsLWINBz4mqN9wR9vNG0WmyEbdECjxcPyr6vkaWt4qi0zqlUxEnYAwGj4EJXNrbjPILntQTQ==
dependencies:
"@types/node" "^12.12.6"
got "9.6.0"
swarm-js "^0.1.40"
web3-core-helpers@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.9.tgz#6381077c3e01c127018cb9e9e3d1422697123315"
@ -11154,6 +11233,14 @@ web3-core-helpers@1.3.4:
web3-eth-iban "1.3.4"
web3-utils "1.3.4"
web3-core-helpers@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.6.0.tgz#77e161b6ba930a4008a0df804ab379e0aa7e1e7f"
integrity sha512-H/IAH/0mrgvad/oxVKiAMC7qDzMrPPe/nRKmJOoIsupRg9/frvL62kZZiHhqVD1HMyyswbQFC69QRl7JqWzvxg==
dependencies:
web3-eth-iban "1.6.0"
web3-utils "1.6.0"
web3-core-method@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.9.tgz#3fb538751029bea570e4f86731e2fa5e4945e462"
@ -11190,6 +11277,18 @@ web3-core-method@1.3.4:
web3-core-subscriptions "1.3.4"
web3-utils "1.3.4"
web3-core-method@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.6.0.tgz#ebe4ea51f5a4fa809bb68185576186359d3982e9"
integrity sha512-cHekyEil4mtcCOk6Q1Zh4y+2o5pTwsLIxP6Bpt4BRtZgdsyPiadYJpkLAVT/quch5xN7Qs5ZwG5AvRCS3VwD2g==
dependencies:
"@ethereumjs/common" "^2.4.0"
"@ethersproject/transactions" "^5.0.0-beta.135"
web3-core-helpers "1.6.0"
web3-core-promievent "1.6.0"
web3-core-subscriptions "1.6.0"
web3-utils "1.6.0"
web3-core-promievent@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.9.tgz#bb1c56aa6fac2f4b3c598510f06554d25c11c553"
@ -11211,6 +11310,13 @@ web3-core-promievent@1.3.4:
dependencies:
eventemitter3 "4.0.4"
web3-core-promievent@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.6.0.tgz#8b6053ae83cb47164540167fc361469fc604d2dd"
integrity sha512-ZzsevjMXWkhqW9dnVfTfb1OUcK7jKcKPvPIbQ4boJccNgvNZPZKlo8xB4pkAX38n4c59O5mC7Lt/z2QL/M5CeQ==
dependencies:
eventemitter3 "4.0.4"
web3-core-requestmanager@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.9.tgz#dd6d855256c4dd681434fe0867f8cd742fe10503"
@ -11246,6 +11352,17 @@ web3-core-requestmanager@1.3.4:
web3-providers-ipc "1.3.4"
web3-providers-ws "1.3.4"
web3-core-requestmanager@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.6.0.tgz#8ef3a3b89cd08983bd94574f9c5893f70a8a6aea"
integrity sha512-CY5paPdiDXKTXPWaEUZekDfUXSuoE2vPxolwqzsvKwFWH5+H1NaXgrc+D5HpufgSvTXawTw0fy7IAicg8+PWqA==
dependencies:
util "^0.12.0"
web3-core-helpers "1.6.0"
web3-providers-http "1.6.0"
web3-providers-ipc "1.6.0"
web3-providers-ws "1.6.0"
web3-core-subscriptions@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.9.tgz#335fd7d15dfce5d78b4b7bef05ce4b3d7237b0e4"
@ -11273,6 +11390,14 @@ web3-core-subscriptions@1.3.4:
underscore "1.9.1"
web3-core-helpers "1.3.4"
web3-core-subscriptions@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.6.0.tgz#8c23b15b434a7c9f937652ecca45d7108e2c54df"
integrity sha512-kY9WZUY/m1URSOv3uTLshoZD9ZDiFKReIzHuPUkxFpD5oYNmr1/aPQNPCrrMxKODR7UVX/D90FxWwCYqHhLaxQ==
dependencies:
eventemitter3 "4.0.4"
web3-core-helpers "1.6.0"
web3-core@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.9.tgz#2cba57aa259b6409db532d21bdf57db8d504fd3e"
@ -11312,6 +11437,19 @@ web3-core@1.3.4:
web3-core-requestmanager "1.3.4"
web3-utils "1.3.4"
web3-core@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.6.0.tgz#144eb00f651c9812faf7176abd7ee99d5f45e212"
integrity sha512-o0WsLrJ2yD+HAAc29lGMWJef/MutTyuzpJC0UzLJtIAQJqtpDalzWINEu4j8XYXGk34N/V6vudtzRPo23QEE6g==
dependencies:
"@types/bn.js" "^4.11.5"
"@types/node" "^12.12.6"
bignumber.js "^9.0.0"
web3-core-helpers "1.6.0"
web3-core-method "1.6.0"
web3-core-requestmanager "1.6.0"
web3-utils "1.6.0"
web3-eth-abi@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.9.tgz#14bedd7e4be04fcca35b2ac84af1400574cd8280"
@ -11339,6 +11477,14 @@ web3-eth-abi@1.3.4:
underscore "1.9.1"
web3-utils "1.3.4"
web3-eth-abi@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.6.0.tgz#4225608f61ebb0607d80849bb2b20f910780253d"
integrity sha512-fImomGE9McuTMJLwK8Tp0lTUzXqCkWeMm00qPVIwpJ/h7lCw9UFYV9+4m29wSqW6FF+FIZKwc6UBEf9dlx3orA==
dependencies:
"@ethersproject/abi" "5.0.7"
web3-utils "1.6.0"
web3-eth-accounts@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.9.tgz#7ec422df90fecb5243603ea49dc28726db7bdab6"
@ -11390,6 +11536,23 @@ web3-eth-accounts@1.3.4:
web3-core-method "1.3.4"
web3-utils "1.3.4"
web3-eth-accounts@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.6.0.tgz#530927f4c5b78df93b3ea1203abbb467de29cd04"
integrity sha512-2f6HS4KIH4laAsNCOfbNX3dRiQosqSY2TRK86C8jtAA/QKGdx+5qlPfYzbI2RjG81iayb2+mVbHIaEaBGZ8sGw==
dependencies:
"@ethereumjs/common" "^2.3.0"
"@ethereumjs/tx" "^3.2.1"
crypto-browserify "3.12.0"
eth-lib "0.2.8"
ethereumjs-util "^7.0.10"
scrypt-js "^3.0.1"
uuid "3.3.2"
web3-core "1.6.0"
web3-core-helpers "1.6.0"
web3-core-method "1.6.0"
web3-utils "1.6.0"
web3-eth-contract@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.9.tgz#713d9c6d502d8c8f22b696b7ffd8e254444e6bfd"
@ -11435,6 +11598,20 @@ web3-eth-contract@1.3.4:
web3-eth-abi "1.3.4"
web3-utils "1.3.4"
web3-eth-contract@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.6.0.tgz#deb946867ad86d32bcbba899d733b681b25ea674"
integrity sha512-ZUtO77zFnxuFtrc+D+iJ3AzNgFXAVcKnhEYN7f1PNz/mFjbtE6dJ+ujO0mvMbxIZF02t9IZv0CIXRpK0rDvZAw==
dependencies:
"@types/bn.js" "^4.11.5"
web3-core "1.6.0"
web3-core-helpers "1.6.0"
web3-core-method "1.6.0"
web3-core-promievent "1.6.0"
web3-core-subscriptions "1.6.0"
web3-eth-abi "1.6.0"
web3-utils "1.6.0"
web3-eth-ens@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.9.tgz#577b9358c036337833fb2bdc59c11be7f6f731b6"
@ -11480,6 +11657,20 @@ web3-eth-ens@1.3.4:
web3-eth-contract "1.3.4"
web3-utils "1.3.4"
web3-eth-ens@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.6.0.tgz#af13852168d56fa71b9198eb097e96fb93831c2a"
integrity sha512-AG24PNv9qbYHSpjHcU2pViOII0jvIR7TeojJ2bxXSDqfcgHuRp3NZGKv6xFvT4uNI4LEQHUhSC7bzHoNF5t8CA==
dependencies:
content-hash "^2.5.2"
eth-ens-namehash "2.0.8"
web3-core "1.6.0"
web3-core-helpers "1.6.0"
web3-core-promievent "1.6.0"
web3-eth-abi "1.6.0"
web3-eth-contract "1.6.0"
web3-utils "1.6.0"
web3-eth-iban@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.9.tgz#4ebf3d8783f34d04c4740dc18938556466399f7a"
@ -11504,6 +11695,14 @@ web3-eth-iban@1.3.4:
bn.js "^4.11.9"
web3-utils "1.3.4"
web3-eth-iban@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.6.0.tgz#edbe46cedc5b148d53fa455edea6b4eef53b2be7"
integrity sha512-HM/bKBS/e8qg0+Eh7B8C/JVG+GkR4AJty17DKRuwMtrh78YsonPj7GKt99zS4n5sDLFww1Imu/ZIk3+K5uJCjw==
dependencies:
bn.js "^4.11.9"
web3-utils "1.6.0"
web3-eth-personal@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.9.tgz#9b95eb159b950b83cd8ae15873e1d57711b7a368"
@ -11540,6 +11739,18 @@ web3-eth-personal@1.3.4:
web3-net "1.3.4"
web3-utils "1.3.4"
web3-eth-personal@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.6.0.tgz#b75a61c0737b8b8bcc11d05db2ed7bfce7e4b262"
integrity sha512-8ohf4qAwbShf4RwES2tLHVqa+pHZnS5Q6tV80sU//bivmlZeyO1W4UWyNn59vu9KPpEYvLseOOC6Muxuvr8mFQ==
dependencies:
"@types/node" "^12.12.6"
web3-core "1.6.0"
web3-core-helpers "1.6.0"
web3-core-method "1.6.0"
web3-net "1.6.0"
web3-utils "1.6.0"
web3-eth@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.9.tgz#e40e7b88baffc9b487193211c8b424dc944977b3"
@ -11597,6 +11808,24 @@ web3-eth@1.3.4:
web3-net "1.3.4"
web3-utils "1.3.4"
web3-eth@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.6.0.tgz#4c9d5fb4eccf9f8744828281757e6ea76af58cbd"
integrity sha512-qJMvai//r0be6I9ghU24/152f0zgJfYC23TMszN3Y6jse1JtjCBP2TlTibFcvkUN1RRdIUY5giqO7ZqAYAmp7w==
dependencies:
web3-core "1.6.0"
web3-core-helpers "1.6.0"
web3-core-method "1.6.0"
web3-core-subscriptions "1.6.0"
web3-eth-abi "1.6.0"
web3-eth-accounts "1.6.0"
web3-eth-contract "1.6.0"
web3-eth-ens "1.6.0"
web3-eth-iban "1.6.0"
web3-eth-personal "1.6.0"
web3-net "1.6.0"
web3-utils "1.6.0"
web3-net@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.9.tgz#51d248ed1bc5c37713c4ac40c0073d9beacd87d3"
@ -11624,6 +11853,15 @@ web3-net@1.3.4:
web3-core-method "1.3.4"
web3-utils "1.3.4"
web3-net@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.6.0.tgz#2c28f8787073110a7c2310336889d2dad647e500"
integrity sha512-LFfG95ovTT2sNHkO1TEfsaKpYcxOSUtbuwHQ0K3G0e5nevKDJkPEFIqIcob40yiwcWoqEjENJP9Bjk8CRrZ99Q==
dependencies:
web3-core "1.6.0"
web3-core-method "1.6.0"
web3-utils "1.6.0"
web3-providers-http@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.9.tgz#e698aa5377e2019c24c5a1e6efa0f51018728934"
@ -11648,6 +11886,14 @@ web3-providers-http@1.3.4:
web3-core-helpers "1.3.4"
xhr2-cookies "1.1.0"
web3-providers-http@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.6.0.tgz#8db4e589abf7197f5d65b12af1bf9726c45f4160"
integrity sha512-sNxHFNv3lnxpmULt34AS6M36IYB/Hzm2Et4yPNzdP1XE644D8sQBZQZaJQdTaza5HfrlwoqU6AOK935armqGuA==
dependencies:
web3-core-helpers "1.6.0"
xhr2-cookies "1.1.0"
web3-providers-ipc@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.9.tgz#6159eacfcd7ac31edc470d93ef10814fe874763b"
@ -11675,6 +11921,14 @@ web3-providers-ipc@1.3.4:
underscore "1.9.1"
web3-core-helpers "1.3.4"
web3-providers-ipc@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.6.0.tgz#6a3410fd47a67c4a36719fb97f99534ae12aac98"
integrity sha512-ETYdfhpGiGoWpmmSJnONvnPfd3TPivHEGjXyuX+L5FUsbMOVZj9MFLNIS19Cx/YGL8UWJ/8alLJoTcWSIdz/aA==
dependencies:
oboe "2.1.5"
web3-core-helpers "1.6.0"
web3-providers-ws@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.9.tgz#22c2006655ec44b4ad2b41acae62741a6ae7a88c"
@ -11705,6 +11959,15 @@ web3-providers-ws@1.3.4:
web3-core-helpers "1.3.4"
websocket "^1.0.32"
web3-providers-ws@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.6.0.tgz#dc15dc18c30089efda992015fd5254bd2b77af5f"
integrity sha512-eNRmlhOPCpuVYwBrKBBQRLGPFb4U1Uo44r9EWV69Cpo4gP6XeBTl6nkawhLz6DS0fq79apyPfItJVuSfAy77pA==
dependencies:
eventemitter3 "4.0.4"
web3-core-helpers "1.6.0"
websocket "^1.0.32"
web3-shh@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.9.tgz#c4ba70d6142cfd61341a50752d8cace9a0370911"
@ -11735,6 +11998,16 @@ web3-shh@1.3.4:
web3-core-subscriptions "1.3.4"
web3-net "1.3.4"
web3-shh@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.6.0.tgz#838a3435dce1039f669a48e53e948062de197931"
integrity sha512-ymN0OFL81WtEeSyb+PFpuUv39fR3frGwsZnIg5EVPZvrOIdaDSFcGSLDmafUt0vKSubvLMVYIBOCskRD6YdtEQ==
dependencies:
web3-core "1.6.0"
web3-core-method "1.6.0"
web3-core-subscriptions "1.6.0"
web3-net "1.6.0"
web3-utils@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.9.tgz#abe11735221627da943971ef1a630868fb9c61f3"
@ -11777,6 +12050,19 @@ web3-utils@1.3.4, web3-utils@^1.3.4:
underscore "1.9.1"
utf8 "3.0.0"
web3-utils@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.6.0.tgz#1975c5ee5b7db8a0836eb7004848a7cd962d1ddc"
integrity sha512-bgCAWAeQnJF035YTFxrcHJ5mGEfTi/McsjqldZiXRwlHK7L1PyOqvXiQLE053dlzvy1kdAxWl/sSSfLMyNUAXg==
dependencies:
bn.js "^4.11.9"
ethereum-bloom-filters "^1.0.6"
ethereumjs-util "^7.1.0"
ethjs-unit "0.1.6"
number-to-bn "1.7.0"
randombytes "^2.1.0"
utf8 "3.0.0"
web3@*, web3@^1.0.0-beta.34, web3@^1.0.0-beta.55:
version "1.3.1"
resolved "https://registry.yarnpkg.com/web3/-/web3-1.3.1.tgz#f780138c92ae3c42ea45e1a3c6ae8844e0aa5054"
@ -11803,6 +12089,19 @@ web3@1.2.9:
web3-shh "1.2.9"
web3-utils "1.2.9"
web3@^1.2.11:
version "1.6.0"
resolved "https://registry.yarnpkg.com/web3/-/web3-1.6.0.tgz#d8fa0cd9e7bf252f9fe43bb77dc42bc6671affde"
integrity sha512-rWpXnO88MiVX5yTRqMBCVKASxc7QDkXZZUl1D48sKlbX4dt3BAV+nVMVUKCBKiluZ5Bp8pDrVCUdPx/jIYai5Q==
dependencies:
web3-bzz "1.6.0"
web3-core "1.6.0"
web3-eth "1.6.0"
web3-eth-personal "1.6.0"
web3-net "1.6.0"
web3-shh "1.6.0"
web3-utils "1.6.0"
web3@^1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/web3/-/web3-1.3.4.tgz#31e014873360aa5840eb17f9f171190c967cffb7"