From 2d444a8cd27855bb1577eb7ab9020c712282ca1c Mon Sep 17 00:00:00 2001 From: Kirill Fedoseev Date: Tue, 26 Nov 2019 16:53:35 +0300 Subject: [PATCH] Simplier approach for attempts tracking in signer --- .../deploy-side/contracts/SignupStorage.sol | 25 ++++++++++++----- src/oracle/proxy/contractsAbi.js | 1 + src/oracle/proxy/index.js | 19 ++++++++++++- src/oracle/tss-sign/signer.js | 28 ++++++------------- tests/test/ethToBncWithRestart.js | 6 ++-- tests/test/index.js | 4 +-- tests/test/utils/signerController.js | 4 +-- 7 files changed, 53 insertions(+), 34 deletions(-) diff --git a/src/deploy/deploy-side/contracts/SignupStorage.sol b/src/deploy/deploy-side/contracts/SignupStorage.sol index 911adf1..69d1477 100644 --- a/src/deploy/deploy-side/contracts/SignupStorage.sol +++ b/src/deploy/deploy-side/contracts/SignupStorage.sol @@ -1,13 +1,24 @@ pragma solidity ^0.5.0; contract SignupStorage { - mapping(bytes32 => uint16) public signupsCount; - mapping(bytes32 => mapping(address => uint16)) public signups; + struct SignupsCounter { + uint16 count; + mapping(address => uint16) id; + } + mapping(bytes32 => SignupsCounter) public signups; function signup(bytes32 hash) public { - require(signups[hash][msg.sender] == 0, "Already signuped"); + require(signups[hash].id[msg.sender] == 0, "Already signuped"); - signups[hash][msg.sender] = ++signupsCount[hash]; + signups[hash].id[msg.sender] = ++signups[hash].count; + } + + function isSignuped(bytes32 hash) public view returns (bool) { + return isSignuped(hash, msg.sender); + } + + function isSignuped(bytes32 hash, address validator) public view returns (bool) { + return signups[hash].id[validator] > 0; } function getSignupNumber( @@ -15,12 +26,12 @@ contract SignupStorage { address[] memory validators, address validator ) view public returns (uint16) { - if (signups[hash][validator] == 0) + if (signups[hash].id[validator] == 0) return 0; uint16 id = 1; for (uint i = 0; i < validators.length; i++) { - uint16 vid = signups[hash][validators[i]]; - if (vid > 0 && vid < signups[hash][validator]) + uint16 vid = signups[hash].id[validators[i]]; + if (vid > 0 && vid < signups[hash].id[validator]) id++; } return id; diff --git a/src/oracle/proxy/contractsAbi.js b/src/oracle/proxy/contractsAbi.js index 6199fa1..1a63694 100644 --- a/src/oracle/proxy/contractsAbi.js +++ b/src/oracle/proxy/contractsAbi.js @@ -24,6 +24,7 @@ const sharedDbAbi = [ 'function getSignupAddress(bytes32 hash, address[] validators, uint16 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 (uint16)', + 'function isSignuped(bytes32 hash) view returns (bool)', 'function setData(bytes32 hash, bytes32 key, bytes data)', 'function signup(bytes32 hash)', 'function addSignature(bytes message, bytes rsv)', diff --git a/src/oracle/proxy/index.js b/src/oracle/proxy/index.js index 466956d..6a12894 100644 --- a/src/oracle/proxy/index.js +++ b/src/oracle/proxy/index.js @@ -172,7 +172,24 @@ async function signupKeygen(req, res) { async function signupSign(req, res) { logger.debug('SignupSign call') - const hash = ethers.utils.id(req.body.third) + const msgHash = req.body.third + + logger.debug('Checking previous attempts') + let attempt = 1 + let uuid + let hash + while (true) { + uuid = `${msgHash}_${attempt}` + hash = ethers.utils.id(uuid) + const data = await sharedDb.isSignuped(hash) + if (!data) { + break + } + logger.trace(`Attempt ${attempt} is already used`) + attempt += 1 + } + logger.debug(`Using attempt ${attempt}`) + const query = sharedDb.interface.functions.signup.encode([hash]) const { txHash } = await sideSendQuery(query) const receipt = await waitForReceipt(SIDE_RPC_URL, txHash) diff --git a/src/oracle/tss-sign/signer.js b/src/oracle/tss-sign/signer.js index b380ca5..b7e0d14 100644 --- a/src/oracle/tss-sign/signer.js +++ b/src/oracle/tss-sign/signer.js @@ -27,7 +27,6 @@ const SIGN_OK = 0 const SIGN_NONCE_INTERRUPT = 1 const SIGN_FAILED = 2 -let nextAttempt = null let cancelled let ready = false let exchangeQueue @@ -58,13 +57,10 @@ function killSigner() { } function restart(req, res) { - if (/^[0-9]+$/.test(req.params.attempt)) { - logger.info(`Manual cancelling current sign attempt, starting ${req.params.attempt} attempt`) - nextAttempt = parseInt(req.params.attempt, 10) - killSigner() - cancelled = true - res.send('Done') - } + logger.info('Manual cancelling current sign attempt') + killSigner() + cancelled = true + res.send('Done') } async function confirmFundsTransfer(epoch) { @@ -225,15 +221,14 @@ function getAccountBalance(account, asset) { return account.balances.find((token) => token.symbol === asset).free } -async function buildTx(from, account, data, txAttempt) { +async function buildTx(from, account, data) { const { closeEpoch, newEpoch, nonce } = data const txOptions = { from, accountNumber: account.account_number, sequence: nonce, - asset: FOREIGN_ASSET, - memo: `Attempt ${txAttempt}` + asset: FOREIGN_ASSET } let exchanges @@ -309,9 +304,8 @@ async function consumer(msg) { } writeParams(parties, threshold) - let attempt = 1 - const { tx, exchanges } = await buildTx(from, account, data, attempt) + const { tx, exchanges } = await buildTx(from, account, data) while (tx !== null) { const signResult = await sign(keysFile, tx, publicKey, from) @@ -328,11 +322,7 @@ async function consumer(msg) { break } - // signer either failed, or timed out after parties signup - attempt = nextAttempt || attempt + 1 - nextAttempt = null - logger.warn(`Sign failed, starting next attempt ${attempt}`) - tx.tx.memo = `Attempt ${attempt}` + logger.warn('Sign failed, starting next attempt') await delay(1000) } logger.info('Acking message') @@ -354,7 +344,7 @@ async function main() { signQueue.consume(consumer) } -app.get('/restart/:attempt', restart) +app.get('/restart', restart) app.get('/start', (req, res) => { logger.info('Ready to start') ready = true diff --git a/tests/test/ethToBncWithRestart.js b/tests/test/ethToBncWithRestart.js index ed6c3f9..8f5aa1e 100644 --- a/tests/test/ethToBncWithRestart.js +++ b/tests/test/ethToBncWithRestart.js @@ -11,7 +11,7 @@ const { validators } = require('../config') const { HOME_BRIDGE_ADDRESS } = process.env -module.exports = (getUsers, newAttempt) => { +module.exports = (getUsers) => { describe('exchange of tokens in eth => bnc direction with restart', function () { let info let users @@ -53,9 +53,9 @@ module.exports = (getUsers, newAttempt) => { it('should restart signature generation and regenerate signature properly', async function () { this.timeout(360000) if (newValidatorNonces[0] > validatorNonces[0] + 2) { - await signerController1.restart(newAttempt) + await signerController1.restart() } else { - await signerController2.restart(newAttempt) + await signerController2.restart() } await waitPromise( () => getBncSequence(info.foreignBridgeAddress), diff --git a/tests/test/index.js b/tests/test/index.js index b5bb877..52841d4 100644 --- a/tests/test/index.js +++ b/tests/test/index.js @@ -72,12 +72,12 @@ describe('bridge tests', function () { testEthToBnc(() => users) testBncToEth(() => users) - testEthToBncWithRestart(() => users, 99) + testEthToBncWithRestart(() => users) testChangeThreshold(3) testEthToBnc(() => users) testBncToEth(() => users) - testEthToBncWithRestart(() => users, 2) + testEthToBncWithRestart(() => users) testEthToBnc(() => users) }) diff --git a/tests/test/utils/signerController.js b/tests/test/utils/signerController.js index 12cfb1c..6a22a84 100644 --- a/tests/test/utils/signerController.js +++ b/tests/test/utils/signerController.js @@ -9,8 +9,8 @@ function createController(validatorId) { }) return { - async restart(attempt) { - return (await sideClient.get(`/restart/${attempt}`)).data + async restart() { + await sideClient.get('/restart') } } }