UNPKG

leap-node

Version:

[![codecov](https://codecov.io/gh/leapdao/leap-node/branch/master/graph/badge.svg)](https://codecov.io/gh/leapdao/leap-node) [![Docker Repository on Quay](https://quay.io/repository/leapdao/leap-node/status "Docker Repository on Quay")](https://quay.io/re

106 lines (88 loc) 3.08 kB
/** * Copyright (c) 2018-present, Leap DAO (leapdao.org) * * This source code is licensed under the Mozilla Public License Version 2.0 * found in the LICENSE file in the root directory of this source tree. */ const { getSlotsByAddr, sendTransaction, buildCas } = require('../../utils'); const { logPeriod } = require('../../utils/debug'); const checkEnoughVotes = require('./checkEnoughVotes'); const submitPeriodVote = require('./submitPeriodVote'); const isAlreadyVoted = require('./isAlreadyVoted'); module.exports = async (periodProposal, bridgeState, opts = {}) => { const defaultResponse = { receiptPromise: Promise.resolve() }; const { proposerSlotId, blocksRoot, prevPeriodRoot } = periodProposal; const { currentState } = bridgeState; const { slots } = currentState; logPeriod( '[submitPeriod] proposerSlot:%d blocksRoot:%s prevPeriodRoot:%s', proposerSlotId, blocksRoot, prevPeriodRoot ); if (await bridgeState.db.getPeriodDataByBlocksRoot(blocksRoot)) { logPeriod('[submitPeriod] already seen onchain', blocksRoot); return { receiptPromise: Promise.resolve({ status: true }) }; } const mySlots = getSlotsByAddr(slots, bridgeState.account.address); if (!mySlots.length) { logPeriod('[submitPeriod] No slots. Not a validator'); return defaultResponse; } const mySlotToSubmit = mySlots.find(slot => slot.id === proposerSlotId); if (!isAlreadyVoted(blocksRoot, mySlots[0].id, periodProposal)) { await submitPeriodVote(blocksRoot, periodProposal, bridgeState); } // check if it is our turn to submit period if (!mySlotToSubmit) { logPeriod('[submitPeriod] Not a proposer. Skipping'); return defaultResponse; } // check if we have enough period votes for submission const { result, votes, needed } = checkEnoughVotes( blocksRoot, periodProposal, bridgeState.currentState.slots ); if (!result) { logPeriod( `[submitPeriod] Not enough period votes collected: ${votes}/${needed}. Waiting..` ); return defaultResponse; } const quorumOfVotes = periodProposal.votes.slice(0, needed); const cas = buildCas(quorumOfVotes); logPeriod('[submitPeriod] CAS:%s', `0x${cas.toString(16)}`); if (periodProposal.txHash) { logPeriod( '[submitPeriod] Already submitted. txHash: %s', periodProposal.txHash ); return defaultResponse; } const { receiptPromise } = await sendTransaction( bridgeState.web3, bridgeState.operatorContract.methods.submitPeriodWithCas( mySlotToSubmit.id, prevPeriodRoot, blocksRoot, `0x${cas.toString(16)}` ), bridgeState.operatorContract.options.address, bridgeState.account, opts ); receiptPromise .on('transactionHash', hash => { logPeriod('[submitPeriod] txHash: ', hash); periodProposal.txHash = hash; }) .then(receipt => { logPeriod('[submitPeriod] Receipt', receipt); }) .catch(e => { // istanbul ignore next logPeriod('[submitPeriod] Error', e); }); return { receiptPromise }; };