From b2e956d1d4c21b68ea724d01efe459f8e7744bf3 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Sat, 21 Nov 2020 01:29:30 +0400 Subject: [PATCH] Fix issue with consensus payload signature and slightly fix pre_prepare consensus code handling --- consensus/consensus.go | 96 ++++++++++++++++++++++++++++++----------- consensus/miner.go | 7 ++- node/ethereum.go | 2 +- sigs/ed25519/ed25519.go | 7 ++- 4 files changed, 82 insertions(+), 30 deletions(-) diff --git a/consensus/consensus.go b/consensus/consensus.go index 82a5a54..9979c00 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -2,6 +2,9 @@ package consensus import ( "math/big" + "sync" + + "github.com/Secured-Finance/dione/sigs" "github.com/Secured-Finance/dione/consensus/types" @@ -11,29 +14,29 @@ import ( "github.com/sirupsen/logrus" "github.com/Secured-Finance/dione/pubsub" + types2 "github.com/Secured-Finance/dione/types" ) type PBFTConsensusManager struct { - psb *pubsub.PubSubRouter - //Consensuses map[string]*ConsensusData - //maxFaultNodes int - minApprovals int - privKey []byte - prePreparePool *PrePreparePool - preparePool *PreparePool - commitPool *CommitPool - consensusLeaders map[string]bool - ethereumClient *ethclient.EthereumClient + psb *pubsub.PubSubRouter + minApprovals int + privKey []byte + prePreparePool *PrePreparePool + preparePool *PreparePool + commitPool *CommitPool + consensusInfo map[string]*ConsensusData + ethereumClient *ethclient.EthereumClient } -//type ConsensusData struct { -// preparedCount int -// commitCount int -// mutex sync.Mutex -// result string -// test bool -// onConsensusFinishCallback func(finalData string) -//} +type ConsensusData struct { + // preparedCount int + // commitCount int + mutex sync.Mutex + alreadySubmitted bool + // result string + // test bool + // onConsensusFinishCallback func(finalData string) +} func NewPBFTConsensusManager(psb *pubsub.PubSubRouter, minApprovals int, privKey []byte, ethereumClient *ethclient.EthereumClient) *PBFTConsensusManager { pcm := &PBFTConsensusManager{} @@ -44,7 +47,7 @@ func NewPBFTConsensusManager(psb *pubsub.PubSubRouter, minApprovals int, privKey pcm.minApprovals = minApprovals pcm.privKey = privKey pcm.ethereumClient = ethereumClient - pcm.consensusLeaders = map[string]bool{} + pcm.consensusInfo = map[string]*ConsensusData{} pcm.psb.Hook(types.MessageTypePrePrepare, pcm.handlePrePrepare) pcm.psb.Hook(types.MessageTypePrepare, pcm.handlePrepare) pcm.psb.Hook(types.MessageTypeCommit, pcm.handleCommit) @@ -185,7 +188,7 @@ func NewPBFTConsensusManager(psb *pubsub.PubSubRouter, minApprovals int, privKey //} func (pcm *PBFTConsensusManager) Propose(consensusID, data string, requestID *big.Int, callbackAddress common.Address) error { - pcm.consensusLeaders[consensusID] = true + pcm.consensusInfo[consensusID] = &ConsensusData{} reqIDRaw := requestID.String() callbackAddressHex := callbackAddress.Hex() prePrepareMsg, err := pcm.prePreparePool.CreatePrePrepare(consensusID, data, reqIDRaw, callbackAddressHex, pcm.privKey) @@ -206,7 +209,19 @@ func (pcm *PBFTConsensusManager) handlePrePrepare(message *types.Message) { return } - pcm.psb.BroadcastToServiceTopic(message) + pcm.prePreparePool.AddPrePrepare(message) + + err := pcm.resignMessage(message) + if err != nil { + logrus.Errorf(err.Error()) + return + } + err = pcm.psb.BroadcastToServiceTopic(message) + if err != nil { + logrus.Errorf(err.Error()) + return + } + prepareMsg, err := pcm.preparePool.CreatePrepare(message, pcm.privKey) if err != nil { logrus.Errorf("failed to create prepare message: %w", err) @@ -225,7 +240,16 @@ func (pcm *PBFTConsensusManager) handlePrepare(message *types.Message) { } pcm.preparePool.AddPrepare(message) - pcm.psb.BroadcastToServiceTopic(message) + err := pcm.resignMessage(message) + if err != nil { + logrus.Errorf(err.Error()) + return + } + err = pcm.psb.BroadcastToServiceTopic(message) + if err != nil { + logrus.Errorf(err.Error()) + return + } if pcm.preparePool.PrepareSize(message.Payload.ConsensusID) >= pcm.minApprovals { commitMsg, err := pcm.commitPool.CreateCommit(message, pcm.privKey) @@ -247,11 +271,25 @@ func (pcm *PBFTConsensusManager) handleCommit(message *types.Message) { } pcm.commitPool.AddCommit(message) - pcm.psb.BroadcastToServiceTopic(message) + err := pcm.resignMessage(message) + if err != nil { + logrus.Errorf(err.Error()) + return + } + err = pcm.psb.BroadcastToServiceTopic(message) + if err != nil { + logrus.Errorf(err.Error()) + return + } consensusMsg := message.Payload if pcm.commitPool.CommitSize(consensusMsg.ConsensusID) >= pcm.minApprovals { - if pcm.consensusLeaders[consensusMsg.ConsensusID] { + if info, ok := pcm.consensusInfo[consensusMsg.ConsensusID]; ok { + info.mutex.Lock() + defer info.mutex.Unlock() + if info.alreadySubmitted { + return + } logrus.Infof("Submitting on-chain result for consensus ID: %s", consensusMsg.ConsensusID) reqID, ok := new(big.Int).SetString(consensusMsg.RequestID, 10) if !ok { @@ -262,6 +300,16 @@ func (pcm *PBFTConsensusManager) handleCommit(message *types.Message) { if err != nil { logrus.Errorf("Failed to submit on-chain result: %w", err) } + info.alreadySubmitted = true } } } + +func (pcm *PBFTConsensusManager) resignMessage(msg *types.Message) error { + sig, err := sigs.Sign(types2.SigTypeEd25519, pcm.privKey, []byte(msg.Payload.Data)) + if err != nil { + return err + } + msg.Payload.Signature = sig.Data + return nil +} diff --git a/consensus/miner.go b/consensus/miner.go index 8198b1d..bed4618 100644 --- a/consensus/miner.go +++ b/consensus/miner.go @@ -106,13 +106,12 @@ func (m *Miner) MineTask(ctx context.Context, event *oracleEmitter.OracleEmitter if err != nil { return nil, xerrors.Errorf("Couldn't get solana request: %w", err) } - response := res.Body() var txRes solTypes.TxResponse - if err = json.Unmarshal(response, &txRes); err != nil { + if err = json.Unmarshal(res, &txRes); err != nil { return nil, xerrors.Errorf("Couldn't unmarshal solana response: %w", err) } blockHash := txRes.Result.Transaction.Message.RecentBlockhash - signature, err := sign(ctx, m.address, response) + signature, err := sign(ctx, m.address, res) if err != nil { return nil, xerrors.Errorf("Couldn't sign solana response: %w", err) } @@ -122,7 +121,7 @@ func (m *Miner) MineTask(ctx context.Context, event *oracleEmitter.OracleEmitter Ticket: ticket, ElectionProof: winner, BeaconEntries: bvals, - Payload: response, + Payload: res, BlockHash: blockHash, Signature: signature, DrandRound: types.DrandRound(rbase.Round), diff --git a/node/ethereum.go b/node/ethereum.go index 13d3797..8442c45 100644 --- a/node/ethereum.go +++ b/node/ethereum.go @@ -41,7 +41,7 @@ func (n *Node) subscribeOnEthContracts(ctx context.Context) { // } //}) - err = n.ConsensusManager.Propose(task.BlockHash, task.BlockHash, event.RequestID, event.CallbackAddress) + err = n.ConsensusManager.Propose(event.RequestID.String(), task.BlockHash, event.RequestID, event.CallbackAddress) if err != nil { logrus.Errorf("Failed to propose task: %w", err) } diff --git a/sigs/ed25519/ed25519.go b/sigs/ed25519/ed25519.go index d4eeb84..b51fd2a 100644 --- a/sigs/ed25519/ed25519.go +++ b/sigs/ed25519/ed25519.go @@ -38,7 +38,12 @@ func (ed25519Signer) Verify(sig []byte, a peer.ID, msg []byte) error { return err } - if valid, err := pubKey.Verify(msg, sig); err != nil || !valid { + pKeyRaw, err := pubKey.Raw() + if err != nil { + return err + } + + if valid := ed25519.Verify(pKeyRaw, msg, sig); !valid { return xerrors.Errorf("failed to verify signature") } return nil