🎨 improved scripts for updating events and trees
This commit is contained in:
parent
8fbbe4c67b
commit
f0e38035e7
28
README.md
28
README.md
@ -28,3 +28,31 @@ For detailed explanation on how things work, checkout [Nuxt.js docs](https://nux
|
||||
## Audit
|
||||
|
||||
[TornadoCash_Сlassic_dApp_audit_Decurity.pdf](https://tornado.cash/audits/TornadoCash_Сlassic_dApp_audit_Decurity.pdf)
|
||||
|
||||
## Update cached files
|
||||
|
||||
- For update deposits and withdrawals events use `yarn update:events {chainId}`
|
||||
- For update encrypted notes use `yarn update:encrypted {chainId}`
|
||||
- For update merkle tree use `yarn update:tree {chainId}`
|
||||
|
||||
#### NOTE!
|
||||
|
||||
After update cached files do not forget to use `yarn update:zip`
|
||||
|
||||
### Example for Ethereum Mainnet:
|
||||
|
||||
```
|
||||
yarn update:events 1
|
||||
yarn update:encrypted 1
|
||||
yarn update:tree 1
|
||||
|
||||
yarn update:zip
|
||||
```
|
||||
|
||||
### Example for Binance Smart Chain:
|
||||
|
||||
```
|
||||
yarn update:events 56
|
||||
|
||||
yarn update:zip
|
||||
```
|
||||
|
@ -50,10 +50,10 @@ export const addressType = { type: 'string', pattern: '^0x[a-fA-F0-9]{40}$' }
|
||||
// TODO auto update in yarn updateCache
|
||||
export const cachedEventsLength = {
|
||||
mainnet: {
|
||||
ENCRYPTED_NOTES: 14550
|
||||
ENCRYPTED_NOTES: 16890
|
||||
},
|
||||
goerli: {
|
||||
ENCRYPTED_NOTES: 1350
|
||||
ENCRYPTED_NOTES: 1366
|
||||
}
|
||||
}
|
||||
|
||||
|
14
package.json
14
package.json
@ -10,13 +10,13 @@
|
||||
"dev": "NODE_OPTIONS='--max-old-space-size=8192' nuxt",
|
||||
"build": "nuxt build",
|
||||
"start": "nuxt start",
|
||||
"update:encrypted": "node --experimental-json-modules updateEncryptedEvents.js",
|
||||
"update:common": "node --experimental-json-modules updateEvents.js",
|
||||
"update:zip": "node updateZip.js",
|
||||
"updateCache": "yarn update:encrypted && yarn update:common && yarn update:zip",
|
||||
"update:zip": "node -r esm scripts/updateZip.js",
|
||||
"update:events": "node -r esm scripts/updateEvents.js --network",
|
||||
"update:encrypted": "node -r esm scripts/updateEncryptedEvents.js --network",
|
||||
"update:tree": "node -r esm scripts/updateTree.js --network",
|
||||
"generate": "NODE_OPTIONS='--max-old-space-size=8192' nuxt generate && cp dist/404.html dist/ipfs-404.html",
|
||||
"ipfsUpload": "node ipfsUpload.js",
|
||||
"deploy-ipfs": "yarn generate && yarn ipfsUpload"
|
||||
"ipfsUpload": "node scripts/ipfsUpload.js",
|
||||
"deploy:ipfs": "yarn generate && yarn ipfsUpload"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.3.20",
|
||||
@ -43,6 +43,7 @@
|
||||
"idb": "^6.0.0",
|
||||
"jspdf": "^1.5.3",
|
||||
"jszip": "^3.5.0",
|
||||
"lodash": "^4.17.21",
|
||||
"node-fetch": "^2.6.1",
|
||||
"numbro": "^2.3.2",
|
||||
"nuxt": "2.14.7",
|
||||
@ -79,6 +80,7 @@
|
||||
"eslint-plugin-promise": ">=4.2.1",
|
||||
"eslint-plugin-standard": ">=4.0.1",
|
||||
"eslint-plugin-vue": "^6.0.1",
|
||||
"esm": "^3.2.25",
|
||||
"jest": "^24.9.0",
|
||||
"node-stream-zip": "^1.15.0",
|
||||
"nodemon": "^2.0.0",
|
||||
|
97
scripts/helpers/download.js
Normal file
97
scripts/helpers/download.js
Normal file
@ -0,0 +1,97 @@
|
||||
import fs from 'fs'
|
||||
import Jszip from 'jszip'
|
||||
import Web3 from 'web3'
|
||||
|
||||
const jszip = new Jszip()
|
||||
|
||||
export async function download({ name, directory, contentType }) {
|
||||
const path = `${directory}${name}.zip`.toLowerCase()
|
||||
|
||||
const data = fs.readFileSync(path)
|
||||
const zip = await jszip.loadAsync(data)
|
||||
|
||||
const file = zip.file(
|
||||
path
|
||||
.replace(directory, '')
|
||||
.slice(0, -4)
|
||||
.toLowerCase()
|
||||
)
|
||||
|
||||
const content = await file.async(contentType)
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
export async function loadCachedEvents({ name, directory, deployedBlock }) {
|
||||
try {
|
||||
const module = await download({ contentType: 'string', directory, name })
|
||||
|
||||
if (module) {
|
||||
const events = JSON.parse(module)
|
||||
|
||||
const [lastEvent] = JSON.parse(module).sort(
|
||||
(a, b) => (b.block || b.blockNumber) - (a.block || a.blockNumber)
|
||||
)
|
||||
const lastBlock = lastEvent.block || lastEvent.blockNumber
|
||||
|
||||
return {
|
||||
events,
|
||||
lastBlock
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`Method loadCachedEvents has error: ${err.message}`)
|
||||
return {
|
||||
events: [],
|
||||
lastBlock: deployedBlock
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function getPastEvents({ type, fromBlock, netId, events, rpcUrl, contractAttrs }) {
|
||||
let downloadedEvents = events
|
||||
|
||||
const provider = new Web3.providers.HttpProvider(rpcUrl)
|
||||
const web3 = new Web3(provider)
|
||||
const contract = new web3.eth.Contract(...contractAttrs)
|
||||
|
||||
const currentBlockNumber = await web3.eth.getBlockNumber()
|
||||
const blockDifference = Math.ceil(currentBlockNumber - fromBlock)
|
||||
|
||||
const blockRange = Number(netId) === 56 ? 4950 : blockDifference / 20
|
||||
|
||||
let chunksCount = blockDifference === 0 ? 1 : Math.ceil(blockDifference / blockRange)
|
||||
const chunkSize = Math.ceil(blockDifference / chunksCount)
|
||||
|
||||
let toBlock = fromBlock + chunkSize
|
||||
|
||||
if (fromBlock < currentBlockNumber) {
|
||||
if (toBlock >= currentBlockNumber) {
|
||||
toBlock = currentBlockNumber
|
||||
chunksCount = 1
|
||||
}
|
||||
|
||||
console.log(`Fetching ${type}, chainId - ${netId}`, `chunksCount - ${chunksCount}`)
|
||||
for (let i = 0; i < chunksCount; i++)
|
||||
try {
|
||||
await new Promise((resolve) => setTimeout(resolve, 200))
|
||||
|
||||
console.log(`fromBlock - ${fromBlock}`)
|
||||
console.log(`toBlock - ${toBlock}`)
|
||||
|
||||
const eventsChunk = await contract.getPastEvents(type, { fromBlock, toBlock })
|
||||
|
||||
if (eventsChunk) {
|
||||
downloadedEvents = downloadedEvents.concat(eventsChunk)
|
||||
console.log('downloaded events count - ', eventsChunk.length)
|
||||
console.log('____________________________________________')
|
||||
}
|
||||
fromBlock = toBlock
|
||||
toBlock += chunkSize
|
||||
} catch (err) {
|
||||
console.log('getPastEvents events', `chunk number - ${i}, has error: ${err.message}`)
|
||||
chunksCount = chunksCount + 1
|
||||
}
|
||||
}
|
||||
return downloadedEvents
|
||||
}
|
2
scripts/helpers/index.js
Normal file
2
scripts/helpers/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
export { download, loadCachedEvents, getPastEvents } from './download'
|
||||
export { save } from './save'
|
17
scripts/helpers/save.js
Normal file
17
scripts/helpers/save.js
Normal file
@ -0,0 +1,17 @@
|
||||
import fs from 'fs'
|
||||
import zipper from 'zip-local'
|
||||
|
||||
export function save(fileName) {
|
||||
try {
|
||||
zipper.sync
|
||||
.zip(`${fileName}`)
|
||||
.compress()
|
||||
.save(`${fileName}.zip`)
|
||||
|
||||
fs.unlinkSync(fileName)
|
||||
return true
|
||||
} catch (err) {
|
||||
console.log('on save error', fileName, err.message)
|
||||
return false
|
||||
}
|
||||
}
|
79
scripts/updateEncryptedEvents.js
Normal file
79
scripts/updateEncryptedEvents.js
Normal file
@ -0,0 +1,79 @@
|
||||
import 'dotenv/config'
|
||||
|
||||
import fs from 'fs'
|
||||
import { uniqBy } from 'lodash'
|
||||
|
||||
import networkConfig from '../networkConfig'
|
||||
import ABI from '../abis/TornadoProxy.abi.json'
|
||||
import { getPastEvents, loadCachedEvents } from './helpers'
|
||||
|
||||
const EVENTS_PATH = './static/events/'
|
||||
const enabledChains = ['1', '5', '56']
|
||||
|
||||
async function saveEncryptedNote(netId) {
|
||||
const {
|
||||
constants,
|
||||
'tornado-proxy.contract.tornadocash.eth': tornadoProxy,
|
||||
'tornado-router.contract.tornadocash.eth': tornadoRouter,
|
||||
'tornado-proxy-light.contract.tornadocash.eth': lightProxy
|
||||
} = networkConfig[`netId${netId}`]
|
||||
|
||||
let [{ url: rpcUrl }] = Object.values(networkConfig[`netId${netId}`].rpcUrls)
|
||||
|
||||
if (netId === '5') {
|
||||
rpcUrl = `https://goerli.infura.io/v3/${process.env.INFURA_KEY}`
|
||||
}
|
||||
|
||||
const contractAddress = tornadoRouter || tornadoProxy || lightProxy
|
||||
|
||||
let encryptedEvents = []
|
||||
const name = `encrypted_notes_${netId}.json`
|
||||
|
||||
const cachedEvents = await loadCachedEvents({
|
||||
name,
|
||||
directory: EVENTS_PATH,
|
||||
deployedBlock: constants.ENCRYPTED_NOTES_BLOCK
|
||||
})
|
||||
|
||||
console.log('cachedEvents', cachedEvents.events.length)
|
||||
|
||||
encryptedEvents = await getPastEvents({
|
||||
netId,
|
||||
rpcUrl,
|
||||
type: 'EncryptedNote',
|
||||
events: encryptedEvents,
|
||||
fromBlock: cachedEvents.lastBlock + 1,
|
||||
contractAttrs: [ABI, contractAddress]
|
||||
})
|
||||
|
||||
console.log('Encrypted note', netId, encryptedEvents.length)
|
||||
|
||||
encryptedEvents = encryptedEvents.reduce((acc, curr) => {
|
||||
if (curr.returnValues.encryptedNote) {
|
||||
acc.push({
|
||||
txHash: curr.transactionHash,
|
||||
blockNumber: Number(curr.blockNumber),
|
||||
encryptedNote: curr.returnValues.encryptedNote
|
||||
})
|
||||
}
|
||||
return acc
|
||||
}, [])
|
||||
|
||||
let freshEvents = cachedEvents.events.concat(encryptedEvents)
|
||||
|
||||
freshEvents = uniqBy(freshEvents, 'encryptedNote').sort((a, b) => b.blockNumber - a.blockNumber)
|
||||
|
||||
const eventsJson = JSON.stringify(freshEvents, null, 2) + '\n'
|
||||
fs.writeFileSync(`${EVENTS_PATH}${name}`, eventsJson)
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const [, , , chain] = process.argv
|
||||
if (!enabledChains.includes(chain)) {
|
||||
throw new Error(`Supported chain ids ${enabledChains.join(', ')}`)
|
||||
}
|
||||
|
||||
await saveEncryptedNote(chain)
|
||||
}
|
||||
|
||||
main()
|
95
scripts/updateEvents.js
Normal file
95
scripts/updateEvents.js
Normal file
@ -0,0 +1,95 @@
|
||||
import 'dotenv/config'
|
||||
|
||||
import fs from 'fs'
|
||||
import { uniqBy } from 'lodash'
|
||||
|
||||
import networkConfig from '../networkConfig'
|
||||
import ABI from '../abis/Instance.abi.json'
|
||||
import { loadCachedEvents, getPastEvents } from './helpers'
|
||||
|
||||
const EVENTS_PATH = './static/events/'
|
||||
const EVENTS = ['Deposit', 'Withdrawal']
|
||||
const enabledChains = ['1', '56']
|
||||
|
||||
async function main(type, netId) {
|
||||
const { tokens, nativeCurrency, deployedBlock } = networkConfig[`netId${netId}`]
|
||||
const CONTRACTS = tokens[nativeCurrency].instanceAddress
|
||||
|
||||
for (const [instance, _contract] of Object.entries(CONTRACTS)) {
|
||||
const cachedEvents = await loadCachedEvents({
|
||||
name: `${type.toLowerCase()}s_${nativeCurrency}_${instance}.json`,
|
||||
directory: EVENTS_PATH,
|
||||
deployedBlock
|
||||
})
|
||||
|
||||
console.log('cachedEvents count - ', cachedEvents.events.length)
|
||||
console.log('lastBlock - ', cachedEvents.lastBlock)
|
||||
|
||||
let [{ url: rpcUrl }] = Object.values(networkConfig[`netId${netId}`].rpcUrls)
|
||||
|
||||
if (netId === '5') {
|
||||
rpcUrl = `https://goerli.infura.io/v3/${process.env.INFURA_KEY}`
|
||||
}
|
||||
|
||||
let events = []
|
||||
|
||||
events = await getPastEvents({
|
||||
type,
|
||||
netId,
|
||||
rpcUrl,
|
||||
events,
|
||||
contractAttrs: [ABI, _contract],
|
||||
fromBlock: cachedEvents.lastBlock + 1
|
||||
})
|
||||
|
||||
if (type === 'Deposit') {
|
||||
events = events.map(({ blockNumber, transactionHash, returnValues }) => {
|
||||
const { commitment, leafIndex, timestamp } = returnValues
|
||||
return {
|
||||
timestamp,
|
||||
commitment,
|
||||
blockNumber,
|
||||
transactionHash,
|
||||
leafIndex: Number(leafIndex)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (type === 'Withdrawal') {
|
||||
events = events.map(({ blockNumber, transactionHash, returnValues }) => {
|
||||
const { nullifierHash, to, fee } = returnValues
|
||||
return {
|
||||
to,
|
||||
fee,
|
||||
blockNumber,
|
||||
nullifierHash,
|
||||
transactionHash
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let freshEvents = cachedEvents.events.concat(events)
|
||||
|
||||
if (type === 'Withdrawal') {
|
||||
freshEvents = uniqBy(freshEvents, 'nullifierHash').sort((a, b) => b.blockNumber - a.blockNumber)
|
||||
} else {
|
||||
freshEvents = freshEvents.filter((e, index) => Number(e.leafIndex) === index)
|
||||
}
|
||||
|
||||
const eventsJson = JSON.stringify(freshEvents, null, 2) + '\n'
|
||||
fs.writeFileSync(`${EVENTS_PATH}${type.toLowerCase()}s_${nativeCurrency}_${instance}.json`, eventsJson)
|
||||
}
|
||||
}
|
||||
|
||||
async function start() {
|
||||
const [, , , chain] = process.argv
|
||||
if (!enabledChains.includes(chain)) {
|
||||
throw new Error(`Supported chain ids ${enabledChains.join(', ')}`)
|
||||
}
|
||||
|
||||
for await (const event of EVENTS) {
|
||||
await main(event, chain)
|
||||
}
|
||||
}
|
||||
|
||||
start()
|
@ -1,19 +1,20 @@
|
||||
const fs = require('fs')
|
||||
const Jszip = require('jszip')
|
||||
const zipper = require('zip-local')
|
||||
const BloomFilter = require('bloomfilter.js')
|
||||
import 'dotenv/config'
|
||||
|
||||
import fs from 'fs'
|
||||
import BloomFilter from 'bloomfilter.js'
|
||||
import { MerkleTree } from 'fixed-merkle-tree'
|
||||
import { buildMimcSponge } from 'circomlibjs'
|
||||
|
||||
import networkConfig from '../networkConfig'
|
||||
|
||||
import { loadCachedEvents, save } from './helpers'
|
||||
|
||||
const TREES_FOLDER = 'static/trees'
|
||||
const TREES_PATH = './static/trees/'
|
||||
const EVENTS_PATH = './static/events/'
|
||||
|
||||
const jszip = new Jszip()
|
||||
const EVENTS = ['deposit']
|
||||
|
||||
const { MerkleTree } = require('fixed-merkle-tree')
|
||||
const { buildMimcSponge } = require('circomlibjs')
|
||||
|
||||
const networkConfig = require('./networkConfig')
|
||||
|
||||
const treesPath = './static/trees/'
|
||||
const eventsPath = './static/events/'
|
||||
|
||||
const enabledChains = ['1']
|
||||
let mimcHash
|
||||
|
||||
const trees = {
|
||||
@ -25,7 +26,6 @@ function getName({ path, type, instance, format = '.json', currName = 'eth' }) {
|
||||
return `${path}${type.toLowerCase()}s_${currName}_${instance}${format}`
|
||||
}
|
||||
|
||||
const TREES_FOLDER = 'static/trees'
|
||||
function createTreeZip(netId) {
|
||||
try {
|
||||
const config = networkConfig[`netId${netId}`]
|
||||
@ -37,23 +37,18 @@ function createTreeZip(netId) {
|
||||
type,
|
||||
instance,
|
||||
format: '',
|
||||
path: treesPath,
|
||||
path: TREES_PATH,
|
||||
currName: config.currencyName.toLowerCase()
|
||||
})
|
||||
|
||||
const treesFolder = fs.readdirSync(TREES_FOLDER)
|
||||
|
||||
treesFolder.forEach((fileName) => {
|
||||
fileName = `${treesPath}${fileName}`
|
||||
fileName = `${TREES_PATH}${fileName}`
|
||||
const isInstanceFile = !fileName.includes('.zip') && fileName.includes(baseFilename)
|
||||
|
||||
if (isInstanceFile) {
|
||||
zipper.sync
|
||||
.zip(`${fileName}`)
|
||||
.compress()
|
||||
.save(`${fileName}.zip`)
|
||||
|
||||
fs.unlinkSync(fileName)
|
||||
save(fileName)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -63,10 +58,10 @@ function createTreeZip(netId) {
|
||||
|
||||
async function createTree(netId) {
|
||||
try {
|
||||
const config = networkConfig[`netId${netId}`]
|
||||
const { currencyName, tokens, deployedBlock } = networkConfig[`netId${netId}`]
|
||||
|
||||
const currName = config.currencyName.toLowerCase()
|
||||
const { instanceAddress: CONTRACTS } = config.tokens.eth
|
||||
const currName = currencyName.toLowerCase()
|
||||
const { instanceAddress: CONTRACTS } = tokens.eth
|
||||
|
||||
for (const type of EVENTS) {
|
||||
for (const [instance] of Object.entries(CONTRACTS)) {
|
||||
@ -75,12 +70,17 @@ async function createTree(netId) {
|
||||
instance,
|
||||
currName,
|
||||
format: '',
|
||||
path: treesPath
|
||||
path: TREES_PATH
|
||||
})
|
||||
|
||||
console.log('createTree', { type, instance })
|
||||
|
||||
const events = await loadCachedEvents({ type, amount: instance, currName })
|
||||
const { events } = await loadCachedEvents({
|
||||
name: `${type}s_${currName}_${instance}.json`,
|
||||
directory: EVENTS_PATH,
|
||||
deployedBlock
|
||||
})
|
||||
|
||||
console.log('events', events.length)
|
||||
|
||||
const bloom = new BloomFilter(events.length) // to reduce the number of false positives
|
||||
@ -88,7 +88,7 @@ async function createTree(netId) {
|
||||
const eventsData = events.reduce(
|
||||
(acc, { leafIndex, commitment, ...rest }, i) => {
|
||||
if (leafIndex !== i) {
|
||||
throw new Error('leafIndex !== i', i, leafIndex)
|
||||
throw new Error(`leafIndex (${leafIndex}) !== i (${i})`)
|
||||
}
|
||||
|
||||
const leave = commitment.toString()
|
||||
@ -127,40 +127,7 @@ async function createTree(netId) {
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e.message)
|
||||
}
|
||||
}
|
||||
|
||||
async function download({ name, contentType }) {
|
||||
const path = `${name}.zip`
|
||||
|
||||
const data = fs.readFileSync(path)
|
||||
const zip = await jszip.loadAsync(data)
|
||||
|
||||
const file = zip.file(
|
||||
path
|
||||
.replace(eventsPath, '')
|
||||
.slice(0, -4)
|
||||
.toLowerCase()
|
||||
)
|
||||
|
||||
const content = await file.async(contentType)
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
async function loadCachedEvents({ type, amount, currName = 'eth', path = '' }) {
|
||||
try {
|
||||
const module = await download({
|
||||
contentType: 'string',
|
||||
name: path || getName({ path: eventsPath, type, instance: amount, currName })
|
||||
})
|
||||
|
||||
if (module) {
|
||||
return JSON.parse(module)
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(`Method loadCachedEvents has error: ${err.message}`)
|
||||
console.error(e.message)
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,14 +137,14 @@ async function initMimc() {
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const [, , , chain] = process.argv
|
||||
if (!enabledChains.includes(chain)) {
|
||||
throw new Error(`Supported chain ids ${enabledChains.join(', ')}`)
|
||||
}
|
||||
await initMimc()
|
||||
|
||||
const NETWORKS = [1]
|
||||
|
||||
for await (const netId of NETWORKS) {
|
||||
await createTree(netId)
|
||||
await createTreeZip(netId)
|
||||
}
|
||||
await createTree(chain)
|
||||
await createTreeZip(chain)
|
||||
}
|
||||
|
||||
main()
|
71
scripts/updateZip.js
Normal file
71
scripts/updateZip.js
Normal file
@ -0,0 +1,71 @@
|
||||
import { uniqBy } from 'lodash'
|
||||
|
||||
import networkConfig from '../networkConfig'
|
||||
import { loadCachedEvents, save } from './helpers'
|
||||
|
||||
const EVENTS_PATH = './static/events/'
|
||||
const EVENTS = ['Deposit', 'Withdrawal']
|
||||
|
||||
function updateEncrypted(netId) {
|
||||
try {
|
||||
const file = `${EVENTS_PATH}encrypted_notes_${netId}.json`
|
||||
|
||||
save(file)
|
||||
} catch {
|
||||
console.warn('Not detected any events files for chainId - ', netId)
|
||||
}
|
||||
}
|
||||
async function updateCommon(netId) {
|
||||
const { nativeCurrency, tokens } = networkConfig[`netId${netId}`]
|
||||
|
||||
console.log(Object.keys(tokens[nativeCurrency].instanceAddress))
|
||||
for await (const type of EVENTS) {
|
||||
for await (const instance of Object.keys(tokens[nativeCurrency].instanceAddress)) {
|
||||
console.warn('instance', instance)
|
||||
const filename = `${type.toLowerCase()}s_${nativeCurrency}_${instance}.json`
|
||||
const isSaved = save(`${EVENTS_PATH}${filename}`)
|
||||
if (isSaved) {
|
||||
try {
|
||||
await testCommon(netId, type, filename)
|
||||
} catch (err) {
|
||||
console.error(err.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function testCommon(netId, type, filename) {
|
||||
const { deployedBlock } = networkConfig[`netId${netId}`]
|
||||
|
||||
const cachedEvents = await loadCachedEvents({
|
||||
name: filename,
|
||||
directory: EVENTS_PATH,
|
||||
deployedBlock
|
||||
})
|
||||
|
||||
console.log('cachedEvents', cachedEvents.events.length, type)
|
||||
|
||||
let events = cachedEvents.events
|
||||
if (type === 'Withdrawal') {
|
||||
events = uniqBy(cachedEvents.events, 'nullifierHash')
|
||||
} else if (type === 'Deposit') {
|
||||
events = cachedEvents.events.filter((e, index) => Number(e.leafIndex) === index)
|
||||
}
|
||||
if (events.length !== cachedEvents.events.length) {
|
||||
console.error('events.length', events.length)
|
||||
console.error('cachedEvents.events.length', cachedEvents.events.length)
|
||||
throw new Error(`Duplicates was detected in ${filename} (${events.length - cachedEvents.events.length})`)
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const NETWORKS = [1, 5, 56]
|
||||
|
||||
for await (const netId of NETWORKS) {
|
||||
updateEncrypted(netId)
|
||||
await updateCommon(netId)
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
static/events/encrypted_notes_56.json.zip
Normal file
BIN
static/events/encrypted_notes_56.json.zip
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -451,7 +451,7 @@ const actions = {
|
||||
|
||||
let cachedEvents = await dispatch('getEncryptedEventsFromDb', { netId })
|
||||
|
||||
const networksWithCache = [1, 5]
|
||||
const networksWithCache = [1, 5, 56]
|
||||
|
||||
const LENGTH_CACHE =
|
||||
Number(netId) === 1
|
||||
|
@ -1,119 +0,0 @@
|
||||
const fs = require('fs')
|
||||
const Web3 = require('web3')
|
||||
const Jszip = require('jszip')
|
||||
const networkConfig = require('./networkConfig')
|
||||
|
||||
const MAIN_NET_RPC_URL = networkConfig.netId1.rpcUrls.Infura.url
|
||||
const GOERLI_RPC_URL = networkConfig.netId5.rpcUrls.Alchemy.url
|
||||
const ABI = require('./abis/TornadoProxy.abi.json')
|
||||
|
||||
const jszip = new Jszip()
|
||||
|
||||
function getWeb3(netId) {
|
||||
const rpc = Number(netId) === 1 ? MAIN_NET_RPC_URL : GOERLI_RPC_URL
|
||||
const provider = new Web3.providers.HttpProvider(rpc)
|
||||
const web3 = new Web3(provider)
|
||||
|
||||
return web3
|
||||
}
|
||||
|
||||
async function download({ name, contentType }) {
|
||||
const path = `${name}.zip`
|
||||
|
||||
const data = fs.readFileSync(path)
|
||||
const zip = await jszip.loadAsync(data)
|
||||
const file = zip.file(path.replace('./static/events/', '').slice(0, -4))
|
||||
|
||||
const content = await file.async(contentType)
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
async function loadCachedEvents(file) {
|
||||
try {
|
||||
const module = await download({
|
||||
contentType: 'string',
|
||||
name: file
|
||||
})
|
||||
|
||||
if (module) {
|
||||
const events = JSON.parse(module)
|
||||
|
||||
const lastEvent = events[events.length - 1]
|
||||
const lastBlock = lastEvent.block || lastEvent.blockNumber
|
||||
|
||||
return {
|
||||
events,
|
||||
lastBlock
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(`Method loadCachedEvents has error: ${err.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function saveEncryptedNote(netId) {
|
||||
const web3 = getWeb3(netId)
|
||||
|
||||
const {
|
||||
'tornado-proxy.contract.tornadocash.eth': tornadoProxy,
|
||||
'tornado-router.contract.tornadocash.eth': tornadoRouter
|
||||
} = networkConfig[`netId${netId}`]
|
||||
|
||||
const contractAddress = tornadoRouter || tornadoProxy
|
||||
|
||||
const contract = new web3.eth.Contract(ABI, contractAddress)
|
||||
const currentBlockNumber = await web3.eth.getBlockNumber()
|
||||
|
||||
const file = `./static/events/encrypted_notes_${netId}.json`
|
||||
|
||||
let encryptedEvents = []
|
||||
|
||||
const cachedEvents = await loadCachedEvents(file)
|
||||
console.log('cachedEvents', cachedEvents.events.length)
|
||||
|
||||
const startBlock = cachedEvents.lastBlock + 1
|
||||
|
||||
const NUMBER_PARTS = 20
|
||||
const part = parseInt((currentBlockNumber - startBlock) / NUMBER_PARTS)
|
||||
|
||||
let fromBlock = startBlock
|
||||
let toBlock = startBlock + part
|
||||
|
||||
for (let i = 0; i <= NUMBER_PARTS; i++) {
|
||||
const partOfEvents = await contract.getPastEvents('EncryptedNote', {
|
||||
toBlock,
|
||||
fromBlock
|
||||
})
|
||||
if (partOfEvents) {
|
||||
encryptedEvents = encryptedEvents.concat(partOfEvents)
|
||||
}
|
||||
fromBlock = toBlock
|
||||
toBlock += part
|
||||
}
|
||||
|
||||
console.log('Encrypted note', netId, encryptedEvents.length)
|
||||
|
||||
encryptedEvents = encryptedEvents
|
||||
.filter((e) => e.returnValues.encryptedNote)
|
||||
.map((item) => {
|
||||
return {
|
||||
txHash: item.transactionHash,
|
||||
blockNumber: Number(item.blockNumber),
|
||||
encryptedNote: item.returnValues.encryptedNote
|
||||
}
|
||||
})
|
||||
|
||||
const eventsJson = JSON.stringify(cachedEvents.events.concat(encryptedEvents), null, 2) + '\n'
|
||||
fs.writeFileSync(file, eventsJson)
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const NETWORKS = [1]
|
||||
|
||||
for await (const netId of NETWORKS) {
|
||||
await saveEncryptedNote(netId)
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
166
updateEvents.js
166
updateEvents.js
@ -1,166 +0,0 @@
|
||||
const fs = require('fs')
|
||||
const Web3 = require('web3')
|
||||
const Jszip = require('jszip')
|
||||
const networkConfig = require('./networkConfig')
|
||||
|
||||
const ABI = require('./abis/Instance.abi.json')
|
||||
|
||||
const EVENTS = ['Deposit', 'Withdrawal']
|
||||
const CHAINS = [56]
|
||||
const jszip = new Jszip()
|
||||
|
||||
async function download({ name, contentType }) {
|
||||
const path = `${name}.zip`
|
||||
|
||||
const data = fs.readFileSync(path)
|
||||
const zip = await jszip.loadAsync(data)
|
||||
|
||||
const file = zip.file(
|
||||
path
|
||||
.replace('./static/events/', '')
|
||||
.slice(0, -4)
|
||||
.toLowerCase()
|
||||
)
|
||||
|
||||
const content = await file.async(contentType)
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
async function loadCachedEvents({ type, amount, nativeCurrency, deployedBlock }) {
|
||||
try {
|
||||
const module = await download({
|
||||
contentType: 'string',
|
||||
name: `./static/events/${type}s_${nativeCurrency}_${amount}.json`
|
||||
})
|
||||
|
||||
if (module) {
|
||||
const events = JSON.parse(module)
|
||||
|
||||
return {
|
||||
events,
|
||||
lastBlock: events[events.length - 1].blockNumber
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`Method loadCachedEvents has error: ${err.message}`)
|
||||
return {
|
||||
events: [],
|
||||
lastBlock: deployedBlock
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function main(type, netId) {
|
||||
const { tokens, nativeCurrency, deployedBlock } = networkConfig[`netId${netId}`]
|
||||
const CONTRACTS = tokens[nativeCurrency].instanceAddress
|
||||
|
||||
for (const [instance, _contract] of Object.entries(CONTRACTS)) {
|
||||
const cachedEvents = await loadCachedEvents({ type, amount: instance, nativeCurrency, deployedBlock })
|
||||
console.log('cachedEvents', cachedEvents.events.length)
|
||||
|
||||
let startBlock = cachedEvents.lastBlock + 1
|
||||
console.log('startBlock', startBlock)
|
||||
|
||||
const rpcUrl =
|
||||
netId === 1
|
||||
? networkConfig[`netId${netId}`].rpcUrls.Infura.url
|
||||
: networkConfig[`netId${netId}`].rpcUrls.publicRpc3.url
|
||||
|
||||
const provider = new Web3.providers.HttpProvider(rpcUrl)
|
||||
const web3 = new Web3(provider)
|
||||
|
||||
const contract = new web3.eth.Contract(ABI, _contract)
|
||||
|
||||
let events = []
|
||||
|
||||
console.log(netId)
|
||||
if (netId === 56) {
|
||||
const blockRange = 4950
|
||||
const currentBlockNumber = await web3.eth.getBlockNumber()
|
||||
const blockDifference = Math.ceil(currentBlockNumber - startBlock)
|
||||
|
||||
let numberParts = blockDifference === 0 ? 1 : Math.ceil(blockDifference / blockRange)
|
||||
const part = Math.ceil(blockDifference / numberParts)
|
||||
|
||||
console.log('numberParts', numberParts)
|
||||
|
||||
let toBlock = startBlock + part
|
||||
|
||||
if (startBlock < currentBlockNumber) {
|
||||
if (toBlock >= currentBlockNumber) {
|
||||
toBlock = 'latest'
|
||||
numberParts = 1
|
||||
}
|
||||
|
||||
for (let i = 0; i < numberParts; i++) {
|
||||
try {
|
||||
await new Promise((resolve) => setTimeout(resolve, 200))
|
||||
console.log({ startBlock, toBlock })
|
||||
const partOfEvents = await contract.getPastEvents(type, {
|
||||
fromBlock: startBlock,
|
||||
toBlock
|
||||
})
|
||||
|
||||
if (partOfEvents) {
|
||||
events = events.concat(partOfEvents)
|
||||
console.log({
|
||||
events: events.length
|
||||
})
|
||||
}
|
||||
startBlock = toBlock
|
||||
toBlock += part
|
||||
} catch {
|
||||
numberParts = numberParts + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
events = await contract.getPastEvents(type, {
|
||||
fromBlock: startBlock,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
}
|
||||
|
||||
console.log('events', events.length)
|
||||
|
||||
if (type === 'Deposit') {
|
||||
events = events.map(({ blockNumber, transactionHash, returnValues }) => {
|
||||
const { commitment, leafIndex, timestamp } = returnValues
|
||||
return {
|
||||
blockNumber,
|
||||
transactionHash,
|
||||
commitment,
|
||||
leafIndex: Number(leafIndex),
|
||||
timestamp
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (type === 'Withdrawal') {
|
||||
events = events.map(({ blockNumber, transactionHash, returnValues }) => {
|
||||
const { nullifierHash, to, fee } = returnValues
|
||||
return {
|
||||
blockNumber,
|
||||
transactionHash,
|
||||
nullifierHash,
|
||||
to,
|
||||
fee
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const eventsJson = JSON.stringify(cachedEvents.events.concat(events), null, 2) + '\n'
|
||||
fs.writeFileSync(`./static/events/${type.toLowerCase()}s_${nativeCurrency}_${instance}.json`, eventsJson)
|
||||
}
|
||||
}
|
||||
|
||||
async function start() {
|
||||
for await (const chain of CHAINS) {
|
||||
for await (const event of EVENTS) {
|
||||
await main(event, chain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
start()
|
113
updateZip.js
113
updateZip.js
@ -1,113 +0,0 @@
|
||||
const fs = require('fs')
|
||||
const Jszip = require('jszip')
|
||||
const zipper = require('zip-local')
|
||||
|
||||
const jszip = new Jszip()
|
||||
const EVENTS = ['Deposit', 'Withdrawal']
|
||||
|
||||
const networkConfig = require('./networkConfig')
|
||||
|
||||
function updateEncryptedNote(netId) {
|
||||
try {
|
||||
const file = `./static/events/encrypted_notes_${netId}.json`
|
||||
zipper.sync
|
||||
.zip(file)
|
||||
.compress()
|
||||
.save(`${file}.zip`)
|
||||
fs.unlinkSync(file)
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function updateCommon(netId) {
|
||||
try {
|
||||
const CURRENCY = networkConfig[`netId${netId}`].nativeCurrency
|
||||
const CONTRACTS = networkConfig[`netId${netId}`].tokens[CURRENCY].instanceAddress
|
||||
|
||||
for (const type of EVENTS) {
|
||||
for (const [instance] of Object.entries(CONTRACTS)) {
|
||||
const file = `./static/events/${type.toLowerCase()}s_${CURRENCY}_${instance}.json`
|
||||
|
||||
zipper.sync
|
||||
.zip(file)
|
||||
.compress()
|
||||
.save(`${file}.zip`)
|
||||
|
||||
fs.unlinkSync(file)
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
async function download({ name, contentType }) {
|
||||
const path = `${name}.zip`
|
||||
|
||||
const data = fs.readFileSync(path)
|
||||
const zip = await jszip.loadAsync(data)
|
||||
|
||||
const file = zip.file(
|
||||
path
|
||||
.replace('./static/events/', '')
|
||||
.slice(0, -4)
|
||||
.toLowerCase()
|
||||
)
|
||||
|
||||
const content = await file.async(contentType)
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
async function loadCachedEvents({ type, amount, CURRENCY, path = '' }) {
|
||||
try {
|
||||
const module = await download({
|
||||
contentType: 'string',
|
||||
name: path || `./static/events/${type}s_${CURRENCY}_${amount}.json`
|
||||
})
|
||||
|
||||
if (module) {
|
||||
const events = JSON.parse(module)
|
||||
|
||||
return {
|
||||
events,
|
||||
lastBlock: events[events.length - 1].blockNumber
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(`Method loadCachedEvents has error: ${err.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function testCommon(netId) {
|
||||
for (const type of EVENTS) {
|
||||
if (type === 'Withdrawal') {
|
||||
return
|
||||
}
|
||||
|
||||
const CURRENCY = networkConfig[`netId${netId}`].nativeCurrency
|
||||
const CONTRACTS = networkConfig[`netId${netId}`].tokens[CURRENCY].instanceAddress
|
||||
|
||||
for (const [instance, _contract] of Object.entries(CONTRACTS)) {
|
||||
console.log('update', { type, instance, contract: _contract })
|
||||
|
||||
const cachedEvents = await loadCachedEvents({ type, amount: instance, CURRENCY })
|
||||
console.log('cachedEvents', cachedEvents.events.length)
|
||||
|
||||
cachedEvents.events.forEach((e, index) => {
|
||||
if (Number(e.leafIndex) !== index) {
|
||||
throw new Error(index)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const NETWORKS = [1, 5, 56]
|
||||
|
||||
for await (const netId of NETWORKS) {
|
||||
await updateEncryptedNote(netId)
|
||||
await updateCommon(netId)
|
||||
await testCommon(netId)
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
@ -10485,7 +10485,7 @@ lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
|
||||
lodash@^4.17.12:
|
||||
lodash@^4.17.12, lodash@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
Loading…
Reference in New Issue
Block a user