Moved proxy totally on ethers js
This commit is contained in:
parent
a36b0435ae
commit
19e42d90ce
File diff suppressed because one or more lines are too long
|
@ -7,6 +7,5 @@ COPY ./proxy/package.json /proxy/
|
|||
RUN npm install
|
||||
|
||||
COPY ./proxy/index.js ./proxy/encode.js ./proxy/decode.js ./proxy/sendTx.js ./shared/logger.js ./shared/crypto.js ./shared/wait.js /proxy/
|
||||
COPY ./proxy/Bridge.json ./proxy/IERC20.json ./proxy/SharedDB.json /proxy/contracts_data/
|
||||
|
||||
ENTRYPOINT ["node", "index.js"]
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,8 @@
|
|||
const express = require('express')
|
||||
const Web3 = require('web3')
|
||||
const AsyncLock = require('async-lock')
|
||||
const axios = require('axios')
|
||||
const BN = require('bignumber.js')
|
||||
const { utils } = require('ethers')
|
||||
const ethers = require('ethers')
|
||||
|
||||
const encode = require('./encode')
|
||||
const decode = require('./decode')
|
||||
|
@ -15,16 +14,54 @@ const {
|
|||
HOME_RPC_URL, HOME_BRIDGE_ADDRESS, SIDE_RPC_URL, SIDE_SHARED_DB_ADDRESS, VALIDATOR_PRIVATE_KEY,
|
||||
HOME_TOKEN_ADDRESS, FOREIGN_URL, FOREIGN_ASSET
|
||||
} = process.env
|
||||
const abiSharedDb = require('./contracts_data/SharedDB.json').abi
|
||||
const abiBridge = require('./contracts_data/Bridge.json').abi
|
||||
const abiToken = require('./contracts_data/IERC20.json').abi
|
||||
|
||||
const homeWeb3 = new Web3(HOME_RPC_URL, null, { transactionConfirmationBlocks: 1 })
|
||||
const sideWeb3 = new Web3(SIDE_RPC_URL, null, { transactionConfirmationBlocks: 1 })
|
||||
const bridge = new homeWeb3.eth.Contract(abiBridge, HOME_BRIDGE_ADDRESS)
|
||||
const token = new homeWeb3.eth.Contract(abiToken, HOME_TOKEN_ADDRESS)
|
||||
const sharedDb = new sideWeb3.eth.Contract(abiSharedDb, SIDE_SHARED_DB_ADDRESS)
|
||||
const validatorAddress = homeWeb3.eth.accounts.privateKeyToAccount(`0x${VALIDATOR_PRIVATE_KEY}`).address
|
||||
const tokenAbi = [
|
||||
'function balanceOf(address account) view returns (uint256)'
|
||||
]
|
||||
const bridgeAbi = [
|
||||
'function getX() view returns (uint)',
|
||||
'function getY() view returns (uint)',
|
||||
'function epoch() view returns (uint)',
|
||||
'function getRangeSize() view returns (uint)',
|
||||
'function getNextRangeSize() view returns (uint)',
|
||||
'function getStartBlock() view returns (uint)',
|
||||
'function getNonce() view returns (uint)',
|
||||
'function nextEpoch() view returns (uint)',
|
||||
'function getThreshold() view returns (uint)',
|
||||
'function getNextThreshold() view returns (uint)',
|
||||
'function getValidators() view returns (address[])',
|
||||
'function getNextValidators() view returns (address[])',
|
||||
'function status() view returns (uint)',
|
||||
'function votesCount(bytes32) view returns (uint)',
|
||||
'function getNextPartyId(address a) view returns (uint)',
|
||||
'function confirmKeygen(uint x, uint y)',
|
||||
'function confirmFundsTransfer()',
|
||||
'function startVoting()',
|
||||
'function voteStartKeygen()',
|
||||
'function voteCancelKeygen()',
|
||||
'function voteAddValidator(address validator)',
|
||||
'function voteRemoveValidator(address validator)',
|
||||
'function voteChangeThreshold(uint threshold)',
|
||||
'function transfer(bytes32 hash, address to, uint value)'
|
||||
]
|
||||
const sharedDbAbi = [
|
||||
'function getSignupAddress(bytes32 hash, address[] validators, uint signupNumber) view returns (address)',
|
||||
'function getData(address from, bytes32 hash, bytes32 key) view returns (bytes)',
|
||||
'function getSignupNumber(bytes32 hash, address[] validators, address validator) view returns (uint)',
|
||||
'function setData(bytes32 hash, bytes32 key, bytes data)',
|
||||
'function signupSign(bytes32 hash)'
|
||||
]
|
||||
|
||||
const homeProvider = new ethers.providers.JsonRpcProvider(HOME_RPC_URL)
|
||||
const sideProvider = new ethers.providers.JsonRpcProvider(SIDE_RPC_URL)
|
||||
const homeWallet = new ethers.Wallet(VALIDATOR_PRIVATE_KEY, homeProvider)
|
||||
const sideWallet = new ethers.Wallet(VALIDATOR_PRIVATE_KEY, sideProvider)
|
||||
|
||||
const token = new ethers.Contract(HOME_TOKEN_ADDRESS, tokenAbi, homeWallet)
|
||||
const bridge = new ethers.Contract(HOME_BRIDGE_ADDRESS, bridgeAbi, homeWallet)
|
||||
const sharedDb = new ethers.Contract(SIDE_SHARED_DB_ADDRESS, sharedDbAbi, sideWallet)
|
||||
|
||||
const validatorAddress = homeWallet.address
|
||||
|
||||
const httpClient = axios.create({ baseURL: FOREIGN_URL })
|
||||
|
||||
|
@ -42,8 +79,8 @@ app.use(express.urlencoded({ extended: true }))
|
|||
const votesProxyApp = express()
|
||||
|
||||
async function main() {
|
||||
homeValidatorNonce = await homeWeb3.eth.getTransactionCount(validatorAddress)
|
||||
sideValidatorNonce = await sideWeb3.eth.getTransactionCount(validatorAddress)
|
||||
homeValidatorNonce = await homeWallet.getTransactionCount()
|
||||
sideValidatorNonce = await sideWallet.getTransactionCount()
|
||||
|
||||
homeSender = await createSender(HOME_RPC_URL, VALIDATOR_PRIVATE_KEY)
|
||||
sideSender = await createSender(SIDE_RPC_URL, VALIDATOR_PRIVATE_KEY)
|
||||
|
@ -72,9 +109,8 @@ function Err(data) {
|
|||
function sideSendQuery(query) {
|
||||
return lock.acquire('home', async () => {
|
||||
logger.debug('Sending side query')
|
||||
const encodedABI = query.encodeABI()
|
||||
const senderResponse = await sideSender({
|
||||
data: encodedABI,
|
||||
data: query,
|
||||
to: SIDE_SHARED_DB_ADDRESS,
|
||||
nonce: sideValidatorNonce
|
||||
})
|
||||
|
@ -88,9 +124,8 @@ function sideSendQuery(query) {
|
|||
function homeSendQuery(query) {
|
||||
return lock.acquire('home', async () => {
|
||||
logger.debug('Sending home query')
|
||||
const encodedABI = query.encodeABI()
|
||||
const senderResponse = await homeSender({
|
||||
data: encodedABI,
|
||||
data: query,
|
||||
to: HOME_BRIDGE_ADDRESS,
|
||||
nonce: homeValidatorNonce
|
||||
})
|
||||
|
@ -107,22 +142,19 @@ async function get(req, res) {
|
|||
const uuid = req.body.key.third
|
||||
let from
|
||||
if (uuid.startsWith('k')) {
|
||||
from = (await bridge.methods.getNextValidators()
|
||||
.call())[parseInt(req.body.key.first, 10) - 1]
|
||||
from = (await bridge.getNextValidators())[parseInt(req.body.key.first, 10) - 1]
|
||||
} else {
|
||||
const validators = await bridge.methods.getValidators()
|
||||
.call()
|
||||
from = await sharedDb.methods.getSignupAddress(
|
||||
const validators = await bridge.getValidators()
|
||||
from = await sharedDb.getSignupAddress(
|
||||
uuid,
|
||||
validators, parseInt(req.body.key.first, 10)
|
||||
validators,
|
||||
parseInt(req.body.key.first, 10)
|
||||
)
|
||||
.call()
|
||||
}
|
||||
const to = Number(req.body.key.fourth) // 0 if empty
|
||||
const key = homeWeb3.utils.sha3(`${round}_${to}`)
|
||||
const key = ethers.utils.id(`${round}_${to}`)
|
||||
|
||||
const data = await sharedDb.methods.getData(from, sideWeb3.utils.sha3(uuid), key)
|
||||
.call()
|
||||
const data = await sharedDb.getData(from, ethers.utils.id(uuid), key)
|
||||
|
||||
if (data.length > 2) {
|
||||
logger.trace(`Received encoded data: ${data}`)
|
||||
|
@ -144,13 +176,13 @@ async function set(req, res) {
|
|||
const round = req.body.key.second
|
||||
const uuid = req.body.key.third
|
||||
const to = Number(req.body.key.fourth)
|
||||
const key = homeWeb3.utils.sha3(`${round}_${to}`)
|
||||
const key = ethers.utils.id(`${round}_${to}`)
|
||||
|
||||
logger.trace('Received data: %o', req.body.value)
|
||||
const encoded = encode(uuid[0] === 'k', round, req.body.value)
|
||||
logger.trace(`Encoded data: ${encoded.toString('hex')}`)
|
||||
logger.trace(`Received data: ${req.body.value.length} bytes, encoded data: ${encoded.length} bytes`)
|
||||
const query = sharedDb.methods.setData(sideWeb3.utils.sha3(uuid), key, encoded)
|
||||
const query = sharedDb.interface.functions.setData.encode([ethers.utils.id(uuid), key, encoded])
|
||||
await sideSendQuery(query)
|
||||
|
||||
res.send(Ok(null))
|
||||
|
@ -159,8 +191,8 @@ async function set(req, res) {
|
|||
|
||||
async function signupKeygen(req, res) {
|
||||
logger.debug('SignupKeygen call')
|
||||
const epoch = (await bridge.methods.nextEpoch().call()).toNumber()
|
||||
const partyId = (await bridge.methods.getNextPartyId(validatorAddress).call()).toNumber()
|
||||
const epoch = (await bridge.nextEpoch()).toNumber()
|
||||
const partyId = (await bridge.getNextPartyId(validatorAddress)).toNumber()
|
||||
|
||||
if (partyId === 0) {
|
||||
res.send(Err({ message: 'Not a validator' }))
|
||||
|
@ -176,8 +208,8 @@ async function signupKeygen(req, res) {
|
|||
|
||||
async function signupSign(req, res) {
|
||||
logger.debug('SignupSign call')
|
||||
const hash = sideWeb3.utils.sha3(`0x${req.body.third}`)
|
||||
const query = sharedDb.methods.signupSign(hash)
|
||||
const hash = ethers.utils.id(req.body.third)
|
||||
const query = sharedDb.interface.functions.signupSign.encode([hash])
|
||||
const { txHash } = await sideSendQuery(query)
|
||||
const receipt = await waitForReceipt(SIDE_RPC_URL, txHash)
|
||||
|
||||
|
@ -191,9 +223,8 @@ async function signupSign(req, res) {
|
|||
return
|
||||
}
|
||||
|
||||
const validators = await bridge.methods.getValidators().call()
|
||||
const id = (await sharedDb.methods.getSignupNumber(hash, validators, validatorAddress).call())
|
||||
.toNumber()
|
||||
const validators = await bridge.getValidators()
|
||||
const id = (await sharedDb.getSignupNumber(hash, validators, validatorAddress)).toNumber()
|
||||
|
||||
res.send(Ok({
|
||||
uuid: hash,
|
||||
|
@ -205,7 +236,7 @@ async function signupSign(req, res) {
|
|||
async function confirmKeygen(req, res) {
|
||||
logger.debug('Confirm keygen call')
|
||||
const { x, y } = req.body[5]
|
||||
const query = bridge.methods.confirmKeygen(`0x${x}`, `0x${y}`)
|
||||
const query = bridge.interface.functions.confirmKeygen.encode([`0x${x}`, `0x${y}`])
|
||||
await homeSendQuery(query)
|
||||
res.send()
|
||||
logger.debug('Confirm keygen end')
|
||||
|
@ -213,7 +244,7 @@ async function confirmKeygen(req, res) {
|
|||
|
||||
async function confirmFundsTransfer(req, res) {
|
||||
logger.debug('Confirm funds transfer call')
|
||||
const query = bridge.methods.confirmFundsTransfer()
|
||||
const query = bridge.interface.functions.confirmFundsTransfer.encode([])
|
||||
await homeSendQuery(query)
|
||||
res.send()
|
||||
logger.debug('Confirm funds transfer end')
|
||||
|
@ -255,37 +286,37 @@ async function sendVote(query, req, res, waitFlag = false) {
|
|||
|
||||
async function voteStartVoting(req, res) {
|
||||
logger.info('Voting for starting new epoch voting process')
|
||||
const query = bridge.methods.startVoting()
|
||||
const query = bridge.interface.functions.startVoting.encode([])
|
||||
await sendVote(query, req, res, true)
|
||||
}
|
||||
|
||||
async function voteStartKeygen(req, res) {
|
||||
logger.info('Voting for starting new epoch keygen')
|
||||
const query = bridge.methods.voteStartKeygen()
|
||||
const query = bridge.interface.functions.voteStartKeygen.encode([])
|
||||
await sendVote(query, req, res)
|
||||
}
|
||||
|
||||
async function voteCancelKeygen(req, res) {
|
||||
logger.info('Voting for cancelling new epoch keygen')
|
||||
const query = bridge.methods.voteCancelKeygen()
|
||||
const query = bridge.interface.functions.voteCancelKeygen.encode([])
|
||||
await sendVote(query, req, res)
|
||||
}
|
||||
|
||||
async function voteAddValidator(req, res) {
|
||||
logger.info('Voting for adding new validator')
|
||||
const query = bridge.methods.voteAddValidator(req.params.validator)
|
||||
const query = bridge.interface.functions.voteAddValidator.encode([req.params.validator])
|
||||
await sendVote(query, req, res)
|
||||
}
|
||||
|
||||
async function voteChangeThreshold(req, res) {
|
||||
logger.info('Voting for changing threshold')
|
||||
const query = bridge.methods.voteChangeThreshold(req.params.threshold)
|
||||
const query = bridge.interface.functions.voteChangeThreshold.encode([req.params.threshold])
|
||||
await sendVote(query, req, res)
|
||||
}
|
||||
|
||||
async function voteRemoveValidator(req, res) {
|
||||
logger.info('Voting for removing validator')
|
||||
const query = bridge.methods.voteRemoveValidator(req.params.validator)
|
||||
const query = bridge.interface.functions.voteRemoveValidator.encode([req.params.validator])
|
||||
await sendVote(query, req, res, true)
|
||||
}
|
||||
|
||||
|
@ -315,9 +346,9 @@ function boundX(x) {
|
|||
async function transfer(req, res) {
|
||||
logger.info('Transfer start')
|
||||
const { hash, to, value } = req.body
|
||||
if (homeWeb3.utils.isAddress(to)) {
|
||||
if (ethers.utils.isHexString(to, 20)) {
|
||||
logger.info(`Calling transfer to ${to}, ${value} tokens`)
|
||||
const query = bridge.methods.transfer(hash, to, `0x${new BN(value).toString(16)}`)
|
||||
const query = bridge.interface.functions.transfer.encode([hash, to, `0x${new BN(value).toString(16)}`])
|
||||
await homeSendQuery(query)
|
||||
}
|
||||
res.send()
|
||||
|
@ -335,6 +366,12 @@ function getForeignBalances(address) {
|
|||
.catch(() => ({}))
|
||||
}
|
||||
|
||||
function getVotesCount(nextEpoch, voteType) {
|
||||
return bridge.votesCount(
|
||||
ethers.utils.keccak256(ethers.utils.solidityPack(['uint8', 'uint256'], [voteType, nextEpoch]))
|
||||
).then(boundX)
|
||||
}
|
||||
|
||||
async function info(req, res) {
|
||||
logger.debug('Info start')
|
||||
try {
|
||||
|
@ -342,37 +379,29 @@ async function info(req, res) {
|
|||
x, y, epoch, rangeSize, nextRangeSize, epochStartBlock, foreignNonce, nextEpoch,
|
||||
threshold, nextThreshold, validators, nextValidators, status, homeBalance
|
||||
] = await Promise.all([
|
||||
bridge.methods.getX().call().then((value) => new BN(value).toString(16)),
|
||||
bridge.methods.getY().call().then((value) => new BN(value).toString(16)),
|
||||
bridge.methods.epoch().call().then(boundX),
|
||||
bridge.methods.getRangeSize().call().then(boundX),
|
||||
bridge.methods.getNextRangeSize().call().then(boundX),
|
||||
bridge.methods.getStartBlock().call().then(boundX),
|
||||
bridge.methods.getNonce().call().then(boundX),
|
||||
bridge.methods.nextEpoch().call().then(boundX),
|
||||
bridge.methods.getThreshold().call().then(boundX),
|
||||
bridge.methods.getNextThreshold().call().then(boundX),
|
||||
bridge.methods.getValidators().call(),
|
||||
bridge.methods.getNextValidators().call(),
|
||||
bridge.methods.status().call(),
|
||||
token.methods.balanceOf(HOME_BRIDGE_ADDRESS).call()
|
||||
bridge.getX().then((value) => new BN(value).toString(16)),
|
||||
bridge.getY().then((value) => new BN(value).toString(16)),
|
||||
bridge.epoch().then(boundX),
|
||||
bridge.getRangeSize().then(boundX),
|
||||
bridge.getNextRangeSize().then(boundX),
|
||||
bridge.getStartBlock().then(boundX),
|
||||
bridge.getNonce().then(boundX),
|
||||
bridge.nextEpoch().then(boundX),
|
||||
bridge.getThreshold().then(boundX),
|
||||
bridge.getNextThreshold().then(boundX),
|
||||
bridge.getValidators(),
|
||||
bridge.getNextValidators(),
|
||||
bridge.status().then(boundX),
|
||||
token.balanceOf(HOME_BRIDGE_ADDRESS)
|
||||
.then((value) => parseFloat(new BN(value).dividedBy(10 ** 18).toFixed(8, 3)))
|
||||
])
|
||||
const [
|
||||
confirmationsForFundsTransfer, votesForVoting, votesForKeygen, votesForCancelKeygen
|
||||
] = await Promise.all([
|
||||
bridge.methods.votesCount(
|
||||
homeWeb3.utils.sha3(utils.solidityPack(['uint8', 'uint256'], [1, nextEpoch]))
|
||||
).call().then(boundX),
|
||||
bridge.methods.votesCount(
|
||||
homeWeb3.utils.sha3(utils.solidityPack(['uint8', 'uint256'], [2, nextEpoch]))
|
||||
).call().then(boundX),
|
||||
bridge.methods.votesCount(
|
||||
homeWeb3.utils.sha3(utils.solidityPack(['uint8', 'uint256'], [7, nextEpoch]))
|
||||
).call().then(boundX),
|
||||
bridge.methods.votesCount(
|
||||
homeWeb3.utils.sha3(utils.solidityPack(['uint8', 'uint256'], [8, nextEpoch]))
|
||||
).call().then(boundX)
|
||||
getVotesCount(nextEpoch, 1),
|
||||
getVotesCount(nextEpoch, 2),
|
||||
getVotesCount(nextEpoch, 7),
|
||||
getVotesCount(nextEpoch, 8)
|
||||
])
|
||||
const foreignAddress = publicKeyToAddress({
|
||||
x,
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
"name": "proxy",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"web3": "1.0.0-beta.55",
|
||||
"bech32": "1.1.3",
|
||||
"express": "4.17.1",
|
||||
"async-lock": "1.2.0",
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
const Web3 = require('web3')
|
||||
const axios = require('axios')
|
||||
const ethers = require('ethers')
|
||||
const BN = require('bignumber.js')
|
||||
|
@ -21,10 +20,10 @@ async function sendRpcRequest(url, method, params) {
|
|||
}
|
||||
|
||||
async function createSender(url, privateKey) {
|
||||
const web3 = new Web3(url, null, { transactionConfirmationBlocks: 1 })
|
||||
const signer = new ethers.utils.SigningKey(privateKey)
|
||||
const provider = new ethers.providers.JsonRpcProvider(url)
|
||||
const wallet = new ethers.Wallet(privateKey, provider)
|
||||
|
||||
const chainId = await web3.eth.net.getId()
|
||||
const { chainId } = await provider.getNetwork()
|
||||
return async function send(tx) {
|
||||
const newTx = {
|
||||
data: tx.data,
|
||||
|
@ -38,7 +37,7 @@ async function createSender(url, privateKey) {
|
|||
try {
|
||||
logger.trace(`Preparing and sending transaction %o on ${url}`, newTx)
|
||||
const estimate = await sendRpcRequest(url, 'eth_estimateGas', [{
|
||||
from: signer.address,
|
||||
from: wallet.address,
|
||||
to: newTx.to,
|
||||
data: newTx.data,
|
||||
gasPrice: newTx.gasPrice,
|
||||
|
@ -50,14 +49,14 @@ async function createSender(url, privateKey) {
|
|||
logger.debug('Gas estimate failed %o, skipping tx, reverting nonce', estimate.error)
|
||||
return true
|
||||
}
|
||||
const gasLimit = BN.min(new BN(estimate.result, 16)
|
||||
.multipliedBy(GAS_LIMIT_FACTOR), MAX_GAS_LIMIT)
|
||||
const gasLimit = BN.min(
|
||||
new BN(estimate.result, 16).multipliedBy(GAS_LIMIT_FACTOR),
|
||||
MAX_GAS_LIMIT
|
||||
)
|
||||
newTx.gasLimit = `0x${new BN(gasLimit).toString(16)}`
|
||||
logger.trace(`Estimated gas to ${gasLimit}`)
|
||||
|
||||
const hash = web3.utils.sha3(ethers.utils.serializeTransaction(newTx))
|
||||
const signature = signer.signDigest(hash)
|
||||
const signedTx = ethers.utils.serializeTransaction(newTx, signature)
|
||||
const signedTx = await wallet.sign(newTx)
|
||||
|
||||
const { result, error } = await sendRpcRequest(url, 'eth_sendRawTransaction', [signedTx])
|
||||
// handle nonce error
|
||||
|
@ -79,14 +78,15 @@ async function createSender(url, privateKey) {
|
|||
}
|
||||
|
||||
async function waitForReceipt(url, txHash) {
|
||||
const provider = new ethers.providers.JsonRpcProvider(url)
|
||||
while (true) {
|
||||
const { result, error } = await sendRpcRequest(url, 'eth_getTransactionReceipt', [txHash])
|
||||
const receipt = await provider.getTransactionReceipt(txHash)
|
||||
|
||||
if (result === null || error) {
|
||||
await delay(1000)
|
||||
} else {
|
||||
return result
|
||||
if (receipt) {
|
||||
return receipt
|
||||
}
|
||||
|
||||
await delay(1000)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue