Nice logging support in all services

This commit is contained in:
Kirill Fedoseev 2019-10-06 13:36:29 +03:00
parent 869adea706
commit 6e36718f01
11 changed files with 156 additions and 159 deletions

View File

@ -6,6 +6,8 @@ const fs = require('fs')
const crypto = require('crypto')
const { computeAddress } = require('ethers').utils
const logger = require('./logger')
const { FOREIGN_URL, PROXY_URL, FOREIGN_ASSET } = process.env
const foreignHttpClient = axios.create({ baseURL: FOREIGN_URL })
@ -13,7 +15,7 @@ const proxyHttpClient = axios.create({ baseURL: PROXY_URL })
async function initialize () {
if (await redis.get('foreignTime') === null) {
console.log('Set default foreign time')
logger.info('Set default foreign time')
await redis.set('foreignTime', 1562306990672)
}
}
@ -26,7 +28,10 @@ async function main () {
return
}
console.log(`Found ${newTransactions.length} new transactions`)
if (newTransactions.length)
logger.info(`Found ${newTransactions.length} new transactions`)
else
logger.debug(`Found 0 new transactions`)
for (const tx of newTransactions.reverse()) {
if (tx.memo !== 'funding') {
@ -54,12 +59,12 @@ function getTx(hash) {
}
async function fetchNewTransactions () {
console.log('Fetching new transactions')
logger.debug('Fetching new transactions')
const startTime = parseInt(await redis.get('foreignTime')) + 1
const address = await getLastForeignAddress()
if (address === null)
return null
console.log('Sending api transactions request')
logger.debug('Sending api transactions request')
return foreignHttpClient
.get('/api/v1/transactions', {
params: {

View File

@ -16,6 +16,7 @@ services:
- VALIDATOR_PRIVATE_KEY
- FOREIGN_URL
- FOREIGN_ASSET
- 'LOG_LEVEL=info'
volumes:
- '../deploy/deploy-test/build/contracts/IERC20.json:/proxy/contracts_data/IERC20.json'
- '../deploy/deploy-home/build/contracts/Bridge.json:/proxy/contracts_data/Bridge.json'
@ -34,6 +35,7 @@ services:
environment:
- 'RABBITMQ_URL=amqp://rabbitmq:5672'
- 'PROXY_URL=http://proxy:8001'
- 'LOG_LEVEL=info'
volumes:
- '${PWD}/${TARGET_NETWORK}/keys:/keys'
networks:
@ -49,6 +51,7 @@ services:
- FOREIGN_CHAIN_ID
- FOREIGN_URL
- FOREIGN_ASSET
- 'LOG_LEVEL=info'
volumes:
- '${PWD}/${TARGET_NETWORK}/keys:/keys'
ports:
@ -82,6 +85,7 @@ services:
- HOME_CHAIN_ID
- HOME_START_BLOCK
- 'RABBITMQ_URL=amqp://rabbitmq:5672'
- 'LOG_LEVEL=info'
volumes:
- '../deploy/deploy-home/build/contracts/Bridge.json:/watcher/contracts_data/Bridge.json'
- '../deploy/deploy-test/build/contracts/IERC20.json:/watcher/contracts_data/IERC20.json'
@ -98,6 +102,7 @@ services:
- FOREIGN_ASSET
- 'RABBITMQ_URL=amqp://rabbitmq:5672'
- 'PROXY_URL=http://proxy:8001'
- 'LOG_LEVEL=info'
volumes:
- '${PWD}/${TARGET_NETWORK}/keys:/keys'
networks:

View File

@ -16,6 +16,7 @@ services:
- VALIDATOR_PRIVATE_KEY
- FOREIGN_URL
- FOREIGN_ASSET
- 'LOG_LEVEL=info'
volumes:
- '../deploy/deploy-test/build/contracts/IERC20.json:/proxy/contracts_data/IERC20.json'
- '../deploy/deploy-home/build/contracts/Bridge.json:/proxy/contracts_data/Bridge.json'
@ -34,6 +35,7 @@ services:
environment:
- 'RABBITMQ_URL=amqp://rabbitmq:5672'
- 'PROXY_URL=http://proxy:8001'
- 'LOG_LEVEL=info'
volumes:
- '${PWD}/${TARGET_NETWORK}/keys:/keys'
networks:
@ -51,6 +53,7 @@ services:
- FOREIGN_CHAIN_ID
- FOREIGN_URL
- FOREIGN_ASSET
- 'LOG_LEVEL=info'
volumes:
- '${PWD}/${TARGET_NETWORK}/keys:/keys'
ports:
@ -92,6 +95,7 @@ services:
- HOME_CHAIN_ID
- HOME_START_BLOCK
- 'RABBITMQ_URL=amqp://rabbitmq:5672'
- 'LOG_LEVEL=info'
volumes:
- '../deploy/deploy-home/build/contracts/Bridge.json:/watcher/contracts_data/Bridge.json'
- '../deploy/deploy-test/build/contracts/IERC20.json:/watcher/contracts_data/IERC20.json'
@ -108,6 +112,7 @@ services:
- FOREIGN_ASSET
- 'RABBITMQ_URL=amqp://rabbitmq:5672'
- 'PROXY_URL=http://proxy:8001'
- 'LOG_LEVEL=info'
volumes:
- '${PWD}/${TARGET_NETWORK}/keys:/keys'
networks:

View File

@ -8,8 +8,9 @@ const bech32 = require('bech32')
const abiBridge = require('./contracts_data/Bridge.json').abi
const abiToken = require('./contracts_data/IERC20.json').abi
const logger = require('./logger')
const { HOME_RPC_URL, HOME_CHAIN_ID, HOME_BRIDGE_ADDRESS, RABBITMQ_URL, HOME_TOKEN_ADDRESS, HOME_START_BLOCK } = process.env
const { HOME_RPC_URL, HOME_BRIDGE_ADDRESS, RABBITMQ_URL, HOME_TOKEN_ADDRESS, HOME_START_BLOCK } = process.env
const web3Home = new Web3(HOME_RPC_URL)
const bridge = new web3Home.eth.Contract(abiBridge, HOME_BRIDGE_ADDRESS)
@ -26,7 +27,7 @@ let redisTx
async function connectRabbit (url) {
return amqp.connect(url).catch(() => {
console.log('Failed to connect, reconnecting')
logger.debug('Failed to connect, reconnecting')
return new Promise(resolve =>
setTimeout(() => resolve(connectRabbit(url)), 1000)
)
@ -44,12 +45,12 @@ async function initialize () {
fromBlock: 1
})
epoch = events.length ? events[events.length - 1].returnValues.epoch.toNumber() : 0
console.log(`Current epoch ${epoch}`)
logger.info(`Current epoch ${epoch}`)
const epochStart = events.length ? events[events.length - 1].blockNumber : 1
const saved = (parseInt(await redis.get('homeBlock')) + 1) || parseInt(HOME_START_BLOCK)
console.log(epochStart, saved)
logger.debug(epochStart, saved)
if (epochStart > saved) {
console.log(`Data in db is outdated, starting from epoch ${epoch}, block #${epochStart}`)
logger.info(`Data in db is outdated, starting from epoch ${epoch}, block #${epochStart}`)
blockNumber = epochStart
await redis.multi()
.set('homeBlock', blockNumber - 1)
@ -57,16 +58,16 @@ async function initialize () {
.exec()
foreignNonce[epoch] = 0
} else {
console.log('Restoring epoch and block number from local db')
logger.info('Restoring epoch and block number from local db')
blockNumber = saved
foreignNonce[epoch] = parseInt(await redis.get(`foreignNonce${epoch}`)) || 0
}
}
async function main () {
console.log(`Watching events in block #${blockNumber}`)
logger.debug(`Watching events in block #${blockNumber}`)
if (await web3Home.eth.getBlock(blockNumber) === null) {
console.log('No block')
logger.debug('No block')
await new Promise(r => setTimeout(r, 1000))
return
}
@ -91,7 +92,7 @@ async function main () {
break
case 'EpochStart':
epoch = event.returnValues.epoch.toNumber()
console.log(`Epoch ${epoch} started`)
logger.info(`Epoch ${epoch} started`)
foreignNonce[epoch] = 0
break
}
@ -129,7 +130,7 @@ async function sendKeygen (event) {
})), {
persistent: true
})
console.log('Sent keygen start event')
logger.debug('Sent keygen start event')
}
function sendKeygenCancelation (event) {
@ -139,7 +140,7 @@ function sendKeygenCancelation (event) {
})), {
persistent: true
})
console.log('Sent keygen cancellation event')
logger.debug('Sent keygen cancellation event')
}
async function sendSignFundsTransfer (event) {
@ -154,7 +155,7 @@ async function sendSignFundsTransfer (event) {
})), {
persistent: true
})
console.log('Sent sign funds transfer event')
logger.debug('Sent sign funds transfer event')
foreignNonce[oldEpoch]++
redisTx.incr(`foreignNonce${oldEpoch}`)
}
@ -187,8 +188,7 @@ async function sendSign (event) {
channel.sendToQueue(signQueue.queue, Buffer.from(msgToQueue), {
persistent: true
})
console.log('Sent new sign event')
console.log(msgToQueue)
logger.debug('Sent new sign event: %o', msgToQueue)
redisTx.incr(`foreignNonce${epoch}`)
foreignNonce[epoch]++

View File

@ -225,6 +225,5 @@ module.exports = function (isKeygen, round, value) {
const roundNumber = parseInt(round[round.length - 1])
const decoder = (isKeygen ? keygenDecoders : signDecoders)[roundNumber]
const decoded = JSON.stringify(decoder(tokenizer))
console.log(decoded)
return decoded
}

View File

@ -137,7 +137,5 @@ module.exports = function (isKeygen, round, value) {
break
buffers.push(next.value)
}
const encoded = Buffer.concat(buffers)
console.log(`Raw data: ${value.length} bytes, encoded data: ${encoded.length} bytes`)
return encoded
return Buffer.concat(buffers)
}

View File

@ -9,6 +9,7 @@ const { utils } = require('ethers')
const encode = require('./encode')
const decode = require('./decode')
const logger = require('./logger')
const {
HOME_RPC_URL, HOME_BRIDGE_ADDRESS, SIDE_RPC_URL, SIDE_SHARED_DB_ADDRESS, VALIDATOR_PRIVATE_KEY, HOME_CHAIN_ID,
@ -66,14 +67,14 @@ async function main () {
homeBlockGasLimit = (await homeWeb3.eth.getBlock('latest', false)).gasLimit
sideBlockGasLimit = (await sideWeb3.eth.getBlock('latest', false)).gasLimit
console.log(`My validator address in home and side networks is ${validatorAddress}`)
logger.warn(`My validator address in home and side networks is ${validatorAddress}`)
app.listen(8001, () => {
console.log('Proxy is listening on port 8001')
logger.debug('Proxy is listening on port 8001')
})
votesProxyApp.listen(8002, () => {
console.log('Votes proxy is listening on port 8001')
logger.debug('Votes proxy is listening on port 8001')
})
}
@ -88,8 +89,7 @@ function Err (data) {
}
async function get (req, res) {
console.log('Get call')
console.log(req.body.key)
logger.debug('Get call, %o', req.body.key)
const round = req.body.key.second
const uuid = req.body.key.third
let from
@ -105,58 +105,59 @@ async function get (req, res) {
const data = await sharedDb.methods.getData(from, sideWeb3.utils.sha3(uuid), key).call()
if (data.length > 2) {
console.log(data)
logger.trace(`Received encoded data: ${data}`)
const decoded = decode(uuid[0] === 'k', round, data)
console.log(decoded)
logger.trace('Decoded data: %o', decoded)
res.send(Ok({ key: req.body.key, value: decoded }))
} else {
setTimeout(() => res.send(Err(null)), 1000)
}
console.log('Get end')
logger.debug('Get end')
}
async function set (req, res) {
console.log('Set call')
logger.debug('Set call')
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}`)
console.log(req.body.value)
logger.trace('Received data: %o', req.body.value)
const encoded = encode(uuid[0] === 'k', round, req.body.value)
console.log(encoded.toString('hex'))
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)
await sideSendQuery(query)
res.send(Ok(null))
console.log('Set end')
logger.debug('Set end')
}
async function signupKeygen (req, res) {
console.log('SignupKeygen call')
logger.debug('SignupKeygen call')
const epoch = (await bridge.methods.nextEpoch().call()).toNumber()
const partyId = (await bridge.methods.getNextPartyId(validatorAddress).call()).toNumber()
if (partyId === 0) {
res.send(Err({ message: 'Not a validator' }))
logger.debug('Not a validator')
} else {
res.send(Ok({ uuid: `k${epoch}`, number: partyId }))
console.log('SignupKeygen end')
logger.debug('SignupKeygen end')
}
}
async function signupSign (req, res) {
console.log('SignupSign call')
logger.debug('SignupSign call')
const hash = sideWeb3.utils.sha3(`0x${req.body.third}`)
const query = sharedDb.methods.signupSign(hash)
const receipt = await sideSendQuery(query)
// Already have signup
if (receipt === false) {
console.log('Already have signup')
res.send(Ok({ uuid: hash, number: 0 }))
logger.debug('Already have signup')
return
}
@ -164,29 +165,29 @@ async function signupSign (req, res) {
const id = (await sharedDb.methods.getSignupNumber(hash, validators, validatorAddress).call()).toNumber()
res.send(Ok({ uuid: hash, number: id }))
console.log('SignupSign end')
logger.debug('SignupSign end')
}
async function confirmKeygen (req, res) {
console.log('Confirm keygen call')
logger.debug('Confirm keygen call')
const { x, y } = req.body[5]
const query = bridge.methods.confirmKeygen(`0x${x}`, `0x${y}`)
await homeSendQuery(query)
res.send()
console.log('Confirm keygen end')
logger.debug('Confirm keygen end')
}
async function confirmFundsTransfer (req, res) {
console.log('Confirm funds transfer call')
logger.debug('Confirm funds transfer call')
const query = bridge.methods.confirmFundsTransfer()
await homeSendQuery(query)
res.send()
console.log('Confirm funds transfer end')
logger.debug('Confirm funds transfer end')
}
function sideSendQuery (query) {
return lock.acquire('side', async () => {
console.log('Sending query')
logger.debug('Sending query')
const encodedABI = query.encodeABI()
const tx = {
data: encodedABI,
@ -205,13 +206,13 @@ function sideSendQuery (query) {
const error = parseError(e.message)
const reason = parseReason(e.message)
if (error === 'revert' && reason.length) {
console.log(reason)
logger.debug(reason)
return false
} else if (error === 'out of gas') {
console.log('Out of gas, retrying')
logger.debug('Out of gas, retrying')
return true
} else {
console.log('Side tx failed, retrying', e.message)
logger.debug('Side tx failed, retrying, %o', e.message)
return true
}
})
@ -219,12 +220,13 @@ function sideSendQuery (query) {
.then(result => {
if (result === true)
return sideSendQuery(query)
return result
return result !== false
})
}
function homeSendQuery (query) {
return lock.acquire('home', async () => {
logger.debug('Sending query')
const encodedABI = query.encodeABI()
const tx = {
data: encodedABI,
@ -243,13 +245,13 @@ function homeSendQuery (query) {
const error = parseError(e.message)
const reason = parseReason(e.message)
if (error === 'revert' && reason.length) {
console.log(reason)
logger.debug(reason)
return false
} else if (error === 'out of gas') {
console.log('Out of gas, retrying')
logger.debug('Out of gas, retrying')
return true
} else {
console.log('Home tx failed, retrying', e.message)
logger.debug('Home tx failed, retrying, %o', e.message)
return true
}
})
@ -257,7 +259,7 @@ function homeSendQuery (query) {
.then(result => {
if (result === true)
return homeSendQuery(query)
return result
return result !== false
})
}
@ -271,76 +273,54 @@ function parseError (message) {
return result ? result[0] : ''
}
async function voteStartVoting (req, res) {
console.log('Voting for starting new epoch voting process')
const query = bridge.methods.startVoting()
async function sendVote(query, req, res) {
try {
await homeSendQuery(query)
if (await homeSendQuery(query)) {
res.send('Voted\n')
logger.info('Voted successfully')
} else {
res.send('Failed\n')
logger.info('Failed to vote')
}
} catch (e) {
console.log(e)
logger.debug(e)
}
res.send('Voted')
console.log('Voted successfully')
}
async function voteStartVoting (req, res) {
logger.info('Voting for starting new epoch voting process')
const query = bridge.methods.startVoting()
sendVote(query, req, res)
}
async function voteStartKeygen (req, res) {
console.log('Voting for starting new epoch keygen')
logger.info('Voting for starting new epoch keygen')
const query = bridge.methods.voteStartKeygen()
try {
await homeSendQuery(query)
} catch (e) {
console.log(e)
}
res.send('Voted')
console.log('Voted successfully')
sendVote(query, req, res)
}
async function voteCancelKeygen (req, res) {
console.log('Voting for cancelling new epoch keygen')
logger.info('Voting for cancelling new epoch keygen')
const query = bridge.methods.voteCancelKeygen()
try {
await homeSendQuery(query)
} catch (e) {
console.log(e)
}
res.send('Voted')
console.log('Voted successfully')
sendVote(query, req, res)
}
async function voteAddValidator (req, res) {
console.log('Voting for adding new validator')
logger.info('Voting for adding new validator')
const query = bridge.methods.voteAddValidator(req.params.validator)
try {
await homeSendQuery(query)
} catch (e) {
console.log(e)
}
res.send('Voted')
console.log('Voted successfully')
sendVote(query, req, res)
}
async function voteChangeThreshold (req, res) {
console.log('Voting for changing threshold')
logger.info('Voting for changing threshold')
const query = bridge.methods.voteChangeThreshold(req.params.threshold)
try {
await homeSendQuery(query)
} catch (e) {
console.log(e)
}
res.send('Voted')
console.log('Voted successfully')
sendVote(query, req, res)
}
async function voteRemoveValidator (req, res) {
console.log('Voting for removing validator')
logger.info('Voting for removing validator')
const query = bridge.methods.voteRemoveValidator(req.params.validator)
try {
await homeSendQuery(query)
} catch (e) {
console.log(e)
}
res.send('Voted')
console.log('Voted successfully')
sendVote(query, req, res)
}
function decodeStatus (status) {
@ -357,7 +337,7 @@ function decodeStatus (status) {
}
async function info (req, res) {
console.log('Info start')
logger.debug('Info start')
const [ x, y, epoch, nextEpoch, threshold, nextThreshold, validators, nextValidators, homeBalance, status ] = await Promise.all([
bridge.methods.getX().call().then(x => new BN(x).toString(16)),
bridge.methods.getY().call().then(x => new BN(x).toString(16)),
@ -403,21 +383,21 @@ async function info (req, res) {
votesForCancelKeygen,
confirmationsForFundsTransfer
})
console.log('Info end')
logger.debug('Info end')
}
async function transfer (req, res) {
console.log('Transfer start')
logger.info('Transfer start')
const { hash, to, value } = req.body
if (homeWeb3.utils.isAddress(to)) {
console.log(`Calling transfer to ${to}, ${value} tokens`)
logger.info(`Calling transfer to ${to}, ${value} tokens`)
const query = bridge.methods.transfer(hash, to, '0x' + (new BN(value).toString(16)))
await homeSendQuery(query)
} else {
// return funds ?
}
res.send()
console.log('Transfer end')
logger.info('Transfer end')
}
function getForeignBalances (address) {

View File

@ -1,6 +1,7 @@
const Redis = require('ioredis')
console.log('Connecting to redis')
const logger = require('./logger')
logger.info('Connecting to redis')
const redis = new Redis({
port: 6379,
@ -10,11 +11,11 @@ const redis = new Redis({
})
redis.on('connect', () => {
console.log('Connected to redis')
logger.info('Connected to redis')
})
redis.on('error', () => {
console.log('Redis error')
logger.warn('Redis error')
})
module.exports = redis

View File

@ -4,14 +4,16 @@ const crypto = require('crypto')
const bech32 = require('bech32')
const amqp = require('amqplib')
const logger = require('./logger')
const { RABBITMQ_URL, PROXY_URL } = process.env
let currentKeygenEpoch = null
async function main () {
console.log('Connecting to RabbitMQ server')
logger.info('Connecting to RabbitMQ server')
const connection = await connectRabbit(RABBITMQ_URL)
console.log('Connecting to epoch events queue')
logger.info('Connecting to epoch events queue')
const channel = await connection.createChannel()
const keygenQueue = await channel.assertQueue('keygenQueue')
const cancelKeygenQueue = await channel.assertQueue('cancelKeygenQueue')
@ -19,39 +21,39 @@ async function main () {
channel.prefetch(1)
channel.consume(keygenQueue.queue, msg => {
const { epoch, parties, threshold } = JSON.parse(msg.content)
console.log(`Consumed new epoch event, starting keygen for epoch ${epoch}`)
logger.info(`Consumed new epoch event, starting keygen for epoch ${epoch}`)
const keysFile = `/keys/keys${epoch}.store`
console.log('Running ./keygen-entrypoint.sh')
logger.info('Running ./keygen-entrypoint.sh')
currentKeygenEpoch = epoch
console.log('Writing params')
logger.debug('Writing params')
fs.writeFileSync('./params', JSON.stringify({ parties: parties.toString(), threshold: threshold.toString() }))
const cmd = exec.execFile('./keygen-entrypoint.sh', [PROXY_URL, keysFile], async () => {
currentKeygenEpoch = null
if (fs.existsSync(keysFile)) {
console.log(`Finished keygen for epoch ${epoch}`)
logger.info(`Finished keygen for epoch ${epoch}`)
const publicKey = JSON.parse(fs.readFileSync(keysFile))[5]
console.log(`Generated multisig account in binance chain: ${publicKeyToAddress(publicKey)}`)
logger.warn(`Generated multisig account in binance chain: ${publicKeyToAddress(publicKey)}`)
console.log('Sending keys confirmation')
logger.info('Sending keys confirmation')
await confirmKeygen(keysFile)
} else {
console.log(`Keygen for epoch ${epoch} failed`)
logger.warn(`Keygen for epoch ${epoch} failed`)
}
console.log('Ack for keygen message')
logger.debug('Ack for keygen message')
channel.ack(msg)
})
cmd.stdout.on('data', data => console.log(data.toString()))
cmd.stderr.on('data', data => console.error(data.toString()))
cmd.stdout.on('data', data => logger.debug(data.toString()))
cmd.stderr.on('data', data => logger.debug(data.toString()))
})
channel.consume(cancelKeygenQueue.queue, async msg => {
const { epoch } = JSON.parse(msg.content)
console.log(`Consumed new cancel event for epoch ${epoch} keygen`)
logger.info(`Consumed new cancel event for epoch ${epoch} keygen`)
if (currentKeygenEpoch === epoch) {
console.log('Cancelling current keygen')
logger.info('Cancelling current keygen')
exec.execSync('pkill gg18_keygen || true')
}
channel.ack(msg)
@ -62,7 +64,7 @@ main()
async function connectRabbit (url) {
return amqp.connect(url).catch(() => {
console.log('Failed to connect, reconnecting')
logger.debug('Failed to connect, reconnecting')
return new Promise(resolve =>
setTimeout(() => resolve(connectRabbit(url)), 1000)
)

View File

@ -6,9 +6,11 @@ const bech32 = require('bech32')
const BN = require('bignumber.js')
const express = require('express')
const logger = require('./logger')
const app = express()
app.get('/restart/:attempt', restart)
app.listen(8001, () => console.log('Listening on 8001'))
app.listen(8001, () => logger.debug('Listening on 8001'))
const { RABBITMQ_URL, FOREIGN_URL, PROXY_URL, FOREIGN_ASSET } = process.env
const Transaction = require('./tx')
@ -21,9 +23,9 @@ let nextAttempt = null
let cancelled
async function main () {
console.log('Connecting to RabbitMQ server')
logger.info('Connecting to RabbitMQ server')
const connection = await connectRabbit(RABBITMQ_URL)
console.log('Connecting to signature events queue')
logger.info('Connecting to signature events queue')
const channel = await connection.createChannel()
const signQueue = await channel.assertQueue('signQueue')
@ -31,27 +33,26 @@ async function main () {
channel.consume(signQueue.queue, async msg => {
const data = JSON.parse(msg.content)
console.log('Consumed sign event')
console.log(data)
logger.info('Consumed sign event: %o', data)
const { recipient, value, nonce, epoch, newEpoch, parties, threshold } = data
const keysFile = `/keys/keys${epoch}.store`
const { address: from, publicKey } = getAccountFromFile(keysFile)
if (from === '') {
console.log('Acking message')
logger.info('No keys found, acking message')
channel.ack(msg)
return
}
const account = await getAccount(from)
console.log('Writing params')
logger.debug('Writing params')
fs.writeFileSync('./params', JSON.stringify({ parties: parties.toString(), threshold: threshold.toString() }))
attempt = 1
if (recipient && account.sequence <= nonce) {
while (true) {
console.log(`Building corresponding transfer transaction, nonce ${nonce}, recipient ${recipient}`)
logger.info(`Building corresponding transfer transaction, nonce ${nonce}, recipient ${recipient}`)
const tx = new Transaction({
from,
accountNumber: account.account_number,
@ -63,14 +64,14 @@ async function main () {
})
const hash = crypto.createHash('sha256').update(tx.getSignBytes()).digest('hex')
console.log(`Starting signature generation for transaction hash ${hash}`)
logger.info(`Starting signature generation for transaction hash ${hash}`)
const done = await sign(keysFile, hash, tx, publicKey) && await waitForAccountNonce(from, nonce + 1)
if (done) {
break
}
attempt = nextAttempt ? nextAttempt : attempt + 1
console.log(`Sign failed, starting next attempt ${attempt}`)
logger.warn(`Sign failed, starting next attempt ${attempt}`)
nextAttempt = null
await new Promise(resolve => setTimeout(resolve, 1000))
}
@ -79,7 +80,7 @@ async function main () {
const { address: to } = getAccountFromFile(newKeysFile)
while (to !== '') {
console.log(`Building corresponding transaction for transferring all funds, nonce ${nonce}, recipient ${to}`)
logger.info(`Building corresponding transaction for transferring all funds, nonce ${nonce}, recipient ${to}`)
const tx = new Transaction({
from,
accountNumber: account.account_number,
@ -92,7 +93,7 @@ async function main () {
})
const hash = crypto.createHash('sha256').update(tx.getSignBytes()).digest('hex')
console.log(`Starting signature generation for transaction hash ${hash}`)
logger.info(`Starting signature generation for transaction hash ${hash}`)
const done = await sign(keysFile, hash, tx, publicKey) && await waitForAccountNonce(from, nonce + 1)
if (done) {
@ -100,14 +101,14 @@ async function main () {
break
}
attempt = nextAttempt ? nextAttempt : attempt + 1
console.log(`Sign failed, starting next attempt ${attempt}`)
logger.warn(`Sign failed, starting next attempt ${attempt}`)
nextAttempt = null
await new Promise(resolve => setTimeout(resolve, 1000))
}
} else {
console.log('Tx has been already sent')
logger.debug('Tx has been already sent')
}
console.log('Acking message')
logger.info('Acking message')
channel.ack(msg)
})
}
@ -118,31 +119,31 @@ function sign (keysFile, hash, tx, publicKey) {
return new Promise(resolve => {
const cmd = exec.execFile('./sign-entrypoint.sh', [ PROXY_URL, keysFile, hash ], async (error) => {
if (fs.existsSync('signature')) {
console.log('Finished signature generation')
logger.info('Finished signature generation')
const signature = JSON.parse(fs.readFileSync('signature'))
console.log(signature)
logger.debug('%o', signature)
console.log('Building signed transaction')
logger.info('Building signed transaction')
const signedTx = tx.addSignature(publicKey, { r: signature[1], s: signature[3] })
console.log('Sending transaction')
console.log(signedTx)
logger.info('Sending transaction')
logger.debug(signedTx)
await sendTx(signedTx)
resolve(true)
} else if (error === null || error.code === 0) {
resolve(true)
} else {
console.log('Sign failed')
logger.warn('Sign failed')
resolve(false)
}
})
cmd.stdout.on('data', data => console.log(data.toString()))
cmd.stderr.on('data', data => console.error(data.toString()))
cmd.stdout.on('data', data => logger.debug(data.toString()))
cmd.stderr.on('data', data => logger.debug(data.toString()))
})
}
function restart (req, res) {
console.log('Cancelling current sign')
logger.info('Cancelling current sign')
nextAttempt = req.params.attempt
exec.execSync('pkill gg18_sign || true')
cancelled = true
@ -151,7 +152,7 @@ function restart (req, res) {
function connectRabbit (url) {
return amqp.connect(url).catch(() => {
console.log('Failed to connect, reconnecting')
logger.debug('Failed to connect, reconnecting')
return new Promise(resolve =>
setTimeout(() => resolve(connectRabbit(url)), 1000)
)
@ -163,9 +164,9 @@ function confirmFundsTransfer () {
}
function getAccountFromFile (file) {
console.log(`Reading ${file}`)
logger.debug(`Reading ${file}`)
if (!fs.existsSync(file)) {
console.log('No keys found, skipping')
logger.debug('No keys found, skipping')
return { address: '' }
}
const publicKey = JSON.parse(fs.readFileSync(file))[5]
@ -177,25 +178,25 @@ function getAccountFromFile (file) {
async function waitForAccountNonce (address, nonce) {
cancelled = false
console.log(`Waiting for account ${address} to have nonce ${nonce}`)
logger.info(`Waiting for account ${address} to have nonce ${nonce}`)
while (!cancelled) {
const sequence = (await getAccount(address)).sequence
if (sequence >= nonce)
break
await new Promise(resolve => setTimeout(resolve, 1000))
console.log('Waiting for needed account nonce')
logger.debug('Waiting for needed account nonce')
}
console.log('Account nonce is OK')
logger.info('Account nonce is OK')
return !cancelled
}
function getAccount (address) {
console.log(`Getting account ${address} data`)
logger.info(`Getting account ${address} data`)
return httpClient
.get(`/api/v1/account/${address}`)
.then(res => res.data)
.catch(() => {
console.log('Retrying')
logger.debug('Retrying')
return getAccount(address)
})
}
@ -209,10 +210,9 @@ function sendTx (tx) {
})
.catch(err => {
if (err.response.data.message.includes('Tx already exists in cache'))
console.log('Tx already exists in cache')
logger.debug('Tx already exists in cache')
else {
console.log(err.response)
console.log('Something failed, restarting')
logger.info('Something failed, restarting: %o', err.response)
return new Promise(resolve => setTimeout(() => resolve(sendTx(tx)), 1000))
}
})

View File

@ -2,6 +2,8 @@ const TransactionBnc = require('@binance-chain/javascript-sdk/lib/tx').default
const { crypto } = require('@binance-chain/javascript-sdk')
const BN = require('bignumber.js')
const logger = require('./logger')
const { FOREIGN_CHAIN_ID } = process.env
class Transaction {
@ -69,7 +71,7 @@ class Transaction {
const n = new BN('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', 16)
const s = new BN(signature.s, 16)
if (s.gt(n.div(2))) {
console.log('Normalizing s')
logger.debug('Normalizing s')
signature.s = n.minus(s).toString(16)
}
const publicKeyEncoded = Buffer.from('eb5ae98721' + (yLast % 2 ? '03' : '02') + padZeros(publicKey.x, 64), 'hex')