From e83bcc1097d49b46b79131e546f1270b9192cc05 Mon Sep 17 00:00:00 2001 From: Jimmy Hu Date: Wed, 27 Feb 2019 10:41:01 +0800 Subject: core: sync to latest core (#214) * vendor: sync to latest core * fix for single chain --- core/blockchain.go | 2 +- core/governance.go | 15 +- core/vm/oracle_contracts.go | 10 + dex/app.go | 75 ++---- dex/app_test.go | 18 +- dex/governance.go | 21 +- dex/handler.go | 15 +- dex/helper_test.go | 14 +- dex/peer.go | 37 ++- dex/peer_test.go | 97 ++------ dex/protocol.go | 4 +- dex/protocol_test.go | 64 ++--- params/config.go | 2 +- .../dexon-consensus/common/event.go | 75 +++--- .../dexon-consensus/core/agreement-mgr.go | 158 +++++------- .../dexon-consensus/core/agreement.go | 4 +- .../dexon-consensus/core/blockchain.go | 65 +++-- .../dexon-consensus/core/consensus.go | 267 ++++++++++----------- .../dexon-consensus/core/constant.go | 12 + .../dexon-consensus/core/interfaces.go | 6 + .../dexon-consensus/core/round-based-config.go | 29 ++- .../dexon-consensus/core/syncer/agreement.go | 9 +- .../dexon-consensus/core/syncer/consensus.go | 54 ++--- .../dexon-consensus/core/ticker.go | 56 ++++- .../dexon-consensus/core/types/block.go | 36 +-- .../dexon-consensus/core/types/config.go | 33 +-- .../dexon-consensus/core/types/position.go | 23 +- .../dexon-consensus/core/types/vote.go | 2 +- .../dexon-foundation/dexon-consensus/core/utils.go | 9 +- .../dexon-consensus/core/utils/crypto.go | 11 - .../dexon-consensus/core/utils/nodeset-cache.go | 34 +-- .../dexon-consensus/core/utils/utils.go | 7 + vendor/vendor.json | 50 ++-- 33 files changed, 555 insertions(+), 759 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 5e3b4b30a..34235c10b 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -293,7 +293,7 @@ type blockInfo struct { } func (bc *BlockChain) AddConfirmedBlock(block *coreTypes.Block) error { - chainID := block.Position.ChainID + chainID := uint32(0) bc.confirmedBlockInitMu.Lock() _, exist := bc.confirmedBlocks[chainID] if !exist { diff --git a/core/governance.go b/core/governance.go index 9929867c9..03f53ae6b 100644 --- a/core/governance.go +++ b/core/governance.go @@ -91,12 +91,11 @@ func (g *Governance) Configuration(round uint64) *coreTypes.Config { configHelper := g.GetGovStateHelperAtRound(round) c := configHelper.Configuration() return &coreTypes.Config{ - LambdaBA: time.Duration(c.LambdaBA) * time.Millisecond, - LambdaDKG: time.Duration(c.LambdaDKG) * time.Millisecond, - NotarySetSize: c.NotarySetSize, - DKGSetSize: c.DKGSetSize, - // TODO(jimmyhu): remove MinBlockInterval after coreTypes.Config update. - RoundInterval: time.Duration(c.RoundLength) * time.Duration(c.MinBlockInterval) * time.Millisecond, + LambdaBA: time.Duration(c.LambdaBA) * time.Millisecond, + LambdaDKG: time.Duration(c.LambdaDKG) * time.Millisecond, + NotarySetSize: c.NotarySetSize, + DKGSetSize: c.DKGSetSize, + RoundLength: c.RoundLength, MinBlockInterval: time.Duration(c.MinBlockInterval) * time.Millisecond, } } @@ -138,3 +137,7 @@ func (g *Governance) IsDKGFinal(round uint64) bool { func (g *Governance) MinGasPrice(round uint64) *big.Int { return g.GetGovStateHelperAtRound(round).MinGasPrice() } + +func (g *Governance) DKGResetCount(round uint64) uint64 { + return g.GetHeadHelper().DKGResetCount(big.NewInt(int64(round))).Uint64() +} diff --git a/core/vm/oracle_contracts.go b/core/vm/oracle_contracts.go index 826e0396c..aa93c97fb 100644 --- a/core/vm/oracle_contracts.go +++ b/core/vm/oracle_contracts.go @@ -2469,6 +2469,16 @@ func PackReportForkBlock(block1, block2 *coreTypes.Block) ([]byte, error) { return data, nil } +func PackResetDKG(newSignedCRS []byte) ([]byte, error) { + method := GovernanceABI.Name2Method["resetDKG"] + res, err := method.Inputs.Pack(newSignedCRS) + if err != nil { + return nil, err + } + data := append(method.Id(), res...) + return data, nil +} + // NodeInfoOracleContract representing a oracle providing the node information. type NodeInfoOracleContract struct { } diff --git a/dex/app.go b/dex/app.go index ab4e80058..6ef20684f 100644 --- a/dex/app.go +++ b/dex/app.go @@ -29,7 +29,6 @@ import ( "github.com/dexon-foundation/dexon/common" "github.com/dexon-foundation/dexon/core" - "github.com/dexon-foundation/dexon/core/rawdb" "github.com/dexon-foundation/dexon/core/types" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/event" @@ -178,8 +177,8 @@ func (d *DexconApp) PreparePayload(position coreTypes.Position) (payload []byte, func (d *DexconApp) preparePayload(ctx context.Context, position coreTypes.Position) ( payload []byte, err error) { - d.chainRLock(position.ChainID) - defer d.chainRUnlock(position.ChainID) + d.chainRLock(uint32(0)) + defer d.chainRUnlock(uint32(0)) select { // This case will hit if previous RLock took too much time. case <-ctx.Done(): @@ -187,25 +186,9 @@ func (d *DexconApp) preparePayload(ctx context.Context, position coreTypes.Posit default: } - if position.Round > 0 { - // If round chain number changed but new round is not delivered yet, payload must be nil. - previousNumChains := d.gov.Configuration(position.Round - 1).NumChains - currentNumChains := d.gov.Configuration(position.Round).NumChains - if previousNumChains != currentNumChains { - deliveredRound, err := rawdb.ReadLastRoundNumber(d.chainDB) - if err != nil { - panic(fmt.Errorf("read current round error: %v", err)) - } - - if deliveredRound < position.Round { - return nil, nil - } - } - } - if position.Height != 0 { // Check if chain block height is strictly increamental. - chainLastHeight, ok := d.blockchain.GetChainLastConfirmedHeight(position.ChainID) + chainLastHeight, ok := d.blockchain.GetChainLastConfirmedHeight(uint32(0)) if !ok || chainLastHeight != position.Height-1 { log.Debug("Previous confirmed block not exists", "current pos", position.String(), "prev height", chainLastHeight, "ok", ok) @@ -213,7 +196,7 @@ func (d *DexconApp) preparePayload(ctx context.Context, position coreTypes.Posit } } - root, exist := d.chainRoot.Load(position.ChainID) + root, exist := d.chainRoot.Load(uint32(0)) if !exist { return nil, nil } @@ -222,14 +205,14 @@ func (d *DexconApp) preparePayload(ctx context.Context, position coreTypes.Posit if err != nil { return nil, err } - log.Debug("Prepare payload", "chain", position.ChainID, "height", position.Height) + log.Debug("Prepare payload", "chain", uint32(0), "height", position.Height) txsMap, err := d.txPool.Pending() if err != nil { return } - chainID := new(big.Int).SetUint64(uint64(position.ChainID)) + chainID := new(big.Int).SetUint64(uint64(uint32(0))) chainNums := new(big.Int).SetUint64(uint64(d.gov.GetNumChains(position.Round))) blockGasLimit := new(big.Int).SetUint64(d.gov.DexconConfiguration(position.Round).BlockGasLimit) blockGasUsed := new(big.Int) @@ -248,13 +231,13 @@ addressMap: } balance := currentState.GetBalance(address) - cost, exist := d.blockchain.GetCostInConfirmedBlocks(position.ChainID, address) + cost, exist := d.blockchain.GetCostInConfirmedBlocks(uint32(0), address) if exist { balance = new(big.Int).Sub(balance, cost) } var expectNonce uint64 - lastConfirmedNonce, exist := d.blockchain.GetLastNonceInConfirmedBlocks(position.ChainID, address) + lastConfirmedNonce, exist := d.blockchain.GetLastNonceInConfirmedBlocks(uint32(0), address) if !exist { expectNonce = currentState.GetNonce(address) } else { @@ -354,13 +337,13 @@ func (d *DexconApp) VerifyBlock(block *coreTypes.Block) coreTypes.BlockVerifySta return coreTypes.VerifyInvalidBlock } - d.chainRLock(block.Position.ChainID) - defer d.chainRUnlock(block.Position.ChainID) + d.chainRLock(uint32(0)) + defer d.chainRUnlock(uint32(0)) if block.Position.Height != 0 { // Check if target block is the next height to be verified, we can only // verify the next block in a given chain. - chainLastHeight, ok := d.blockchain.GetChainLastConfirmedHeight(block.Position.ChainID) + chainLastHeight, ok := d.blockchain.GetChainLastConfirmedHeight(uint32(0)) if !ok || chainLastHeight != block.Position.Height-1 { log.Debug("Previous confirmed block not exists", "current pos", block.Position.String(), "prev height", chainLastHeight, "ok", ok) @@ -368,34 +351,14 @@ func (d *DexconApp) VerifyBlock(block *coreTypes.Block) coreTypes.BlockVerifySta } } - if block.Position.Round > 0 { - // If round chain number changed but new round is not delivered yet, payload must be nil. - previousNumChains := d.gov.Configuration(block.Position.Round - 1).NumChains - currentNumChains := d.gov.Configuration(block.Position.Round).NumChains - if previousNumChains != currentNumChains { - deliveredRound, err := rawdb.ReadLastRoundNumber(d.chainDB) - if err != nil { - panic(fmt.Errorf("read current round error: %v", err)) - } - - if deliveredRound < block.Position.Round { - if len(block.Payload) > 0 { - return coreTypes.VerifyInvalidBlock - } - - return coreTypes.VerifyOK - } - } - } - // Get latest state with current chain. - root, exist := d.chainRoot.Load(block.Position.ChainID) + root, exist := d.chainRoot.Load(uint32(0)) if !exist { return coreTypes.VerifyRetryLater } currentState, err := d.blockchain.StateAt(*root.(*common.Hash)) - log.Debug("Verify block", "chain", block.Position.ChainID, "height", block.Position.Height) + log.Debug("Verify block", "chain", uint32(0), "height", block.Position.Height) if err != nil { log.Debug("Invalid state root", "root", *root.(*common.Hash), "err", err) return coreTypes.VerifyInvalidBlock @@ -428,7 +391,7 @@ func (d *DexconApp) VerifyBlock(block *coreTypes.Block) coreTypes.BlockVerifySta } // Check if nonce is strictly increasing for every address. - chainID := big.NewInt(int64(block.Position.ChainID)) + chainID := big.NewInt(int64(uint32(0))) chainNums := big.NewInt(int64(d.gov.GetNumChains(block.Position.Round))) for address, firstNonce := range addressNonce { @@ -438,7 +401,7 @@ func (d *DexconApp) VerifyBlock(block *coreTypes.Block) coreTypes.BlockVerifySta } var expectNonce uint64 - lastConfirmedNonce, exist := d.blockchain.GetLastNonceInConfirmedBlocks(block.Position.ChainID, address) + lastConfirmedNonce, exist := d.blockchain.GetLastNonceInConfirmedBlocks(uint32(0), address) if exist { expectNonce = lastConfirmedNonce + 1 } else { @@ -454,7 +417,7 @@ func (d *DexconApp) VerifyBlock(block *coreTypes.Block) coreTypes.BlockVerifySta // Calculate balance in last state (including pending state). addressesBalance := map[common.Address]*big.Int{} for address := range addressNonce { - cost, exist := d.blockchain.GetCostInConfirmedBlocks(block.Position.ChainID, address) + cost, exist := d.blockchain.GetCostInConfirmedBlocks(uint32(0), address) if exist { addressesBalance[address] = new(big.Int).Sub(currentState.GetBalance(address), cost) } else { @@ -509,7 +472,7 @@ func (d *DexconApp) BlockDelivered( log.Debug("DexconApp block deliver", "height", result.Height, "hash", blockHash, "position", blockPosition.String()) defer log.Debug("DexconApp block delivered", "height", result.Height, "hash", blockHash, "position", blockPosition.String()) - chainID := blockPosition.ChainID + chainID := uint32(0) d.chainLock(chainID) defer d.chainUnlock(chainID) @@ -567,8 +530,8 @@ func (d *DexconApp) BlockDelivered( // BlockConfirmed is called when a block is confirmed and added to lattice. func (d *DexconApp) BlockConfirmed(block coreTypes.Block) { - d.chainLock(block.Position.ChainID) - defer d.chainUnlock(block.Position.ChainID) + d.chainLock(uint32(0)) + defer d.chainUnlock(uint32(0)) log.Debug("DexconApp block confirmed", "block", block.String()) if err := d.blockchain.AddConfirmedBlock(&block); err != nil { diff --git a/dex/app_test.go b/dex/app_test.go index 73d952f31..221c55e0d 100644 --- a/dex/app_test.go +++ b/dex/app_test.go @@ -52,7 +52,7 @@ func TestPreparePayload(t *testing.T) { chainNum := uint32(0) root := dex.blockchain.CurrentBlock().Root() dex.app.chainRoot.Store(chainNum, &root) - payload, err := dex.app.PreparePayload(coreTypes.Position{ChainID: chainNum}) + payload, err := dex.app.PreparePayload(coreTypes.Position{}) if err != nil { t.Fatalf("prepare payload error: %v", err) } @@ -152,7 +152,6 @@ func TestVerifyBlock(t *testing.T) { // Prepare normal block. block := &coreTypes.Block{} block.Hash = coreCommon.NewRandomHash() - block.Position.ChainID = uint32(chainID.Uint64()) block.Position.Height = 1 block.ProposerID = coreTypes.NodeID{coreCommon.Hash{1, 2, 3}} block.Payload, block.Witness, err = prepareDataWithoutTxPool(dex, key, 0, 100) @@ -169,7 +168,6 @@ func TestVerifyBlock(t *testing.T) { // Prepare invalid nonce tx. block = &coreTypes.Block{} block.Hash = coreCommon.NewRandomHash() - block.Position.ChainID = uint32(chainID.Uint64()) block.Position.Height = 1 block.ProposerID = coreTypes.NodeID{coreCommon.Hash{1, 2, 3}} block.Payload, block.Witness, err = prepareDataWithoutTxPool(dex, key, 1, 100) @@ -186,7 +184,6 @@ func TestVerifyBlock(t *testing.T) { // Prepare invalid block height. block = &coreTypes.Block{} block.Hash = coreCommon.NewRandomHash() - block.Position.ChainID = uint32(chainID.Uint64()) block.Position.Height = 2 block.ProposerID = coreTypes.NodeID{coreCommon.Hash{1, 2, 3}} block.Payload, block.Witness, err = prepareDataWithoutTxPool(dex, key, 0, 100) @@ -203,7 +200,6 @@ func TestVerifyBlock(t *testing.T) { // Prepare reach block limit. block = &coreTypes.Block{} block.Hash = coreCommon.NewRandomHash() - block.Position.ChainID = uint32(chainID.Uint64()) block.Position.Height = 1 block.ProposerID = coreTypes.NodeID{coreCommon.Hash{1, 2, 3}} block.Payload, block.Witness, err = prepareDataWithoutTxPool(dex, key, 0, 10000) @@ -220,7 +216,6 @@ func TestVerifyBlock(t *testing.T) { // Prepare insufficient funds. block = &coreTypes.Block{} block.Hash = coreCommon.NewRandomHash() - block.Position.ChainID = uint32(chainID.Uint64()) block.Position.Height = 1 block.ProposerID = coreTypes.NodeID{coreCommon.Hash{1, 2, 3}} _, block.Witness, err = prepareDataWithoutTxPool(dex, key, 0, 0) @@ -255,7 +250,6 @@ func TestVerifyBlock(t *testing.T) { // Prepare invalid intrinsic gas. block = &coreTypes.Block{} block.Hash = coreCommon.NewRandomHash() - block.Position.ChainID = uint32(chainID.Uint64()) block.Position.Height = 1 block.ProposerID = coreTypes.NodeID{coreCommon.Hash{1, 2, 3}} _, block.Witness, err = prepareDataWithoutTxPool(dex, key, 0, 0) @@ -290,7 +284,6 @@ func TestVerifyBlock(t *testing.T) { // Prepare invalid transactions with nonce. block = &coreTypes.Block{} block.Hash = coreCommon.NewRandomHash() - block.Position.ChainID = uint32(chainID.Uint64()) block.Position.Height = 1 block.ProposerID = coreTypes.NodeID{coreCommon.Hash{1, 2, 3}} _, block.Witness, err = prepareDataWithoutTxPool(dex, key, 0, 0) @@ -398,7 +391,6 @@ func TestBlockConfirmed(t *testing.T) { block.Witness = witness block.Payload = payload block.ProposerID = coreTypes.NodeID{coreCommon.Hash{1, 2, 3}} - block.Position.ChainID = uint32(chainID.Uint64()) dex.app.BlockConfirmed(*block) expectCounter++ @@ -573,7 +565,6 @@ func addTx(dex *Dexon, nonce int, signer types.Signer, key *ecdsa.PrivateKey) ( func prepareData(dex *Dexon, key *ecdsa.PrivateKey, startNonce, txNum int) ( payload []byte, witness coreTypes.Witness, cost big.Int, nonce uint64, err error) { signer := types.NewEIP155Signer(dex.chainConfig.ChainID) - chainID := big.NewInt(0) for n := startNonce; n < startNonce+txNum; n++ { var tx *types.Transaction @@ -586,7 +577,7 @@ func prepareData(dex *Dexon, key *ecdsa.PrivateKey, startNonce, txNum int) ( nonce = uint64(n) } - payload, err = dex.app.PreparePayload(coreTypes.Position{ChainID: uint32(chainID.Uint64())}) + payload, err = dex.app.PreparePayload(coreTypes.Position{}) if err != nil { return } @@ -624,7 +615,7 @@ func prepareConfirmedBlockWithTxAndData(dex *Dexon, key *ecdsa.PrivateKey, data witness coreTypes.Witness ) - payload, err = dex.app.PreparePayload(coreTypes.Position{Round: round, ChainID: uint32(0)}) + payload, err = dex.app.PreparePayload(coreTypes.Position{Round: round}) if err != nil { return } @@ -638,7 +629,6 @@ func prepareConfirmedBlockWithTxAndData(dex *Dexon, key *ecdsa.PrivateKey, data block.Hash = coreCommon.NewRandomHash() block.Witness = witness block.Payload = payload - block.Position.ChainID = uint32(0) block.Position.Round = round block.ProposerID = coreTypes.NodeID{coreCommon.Hash{1, 2, 3}} @@ -692,7 +682,6 @@ func prepareConfirmedBlocks(dex *Dexon, keys []*ecdsa.PrivateKey, txNum int) (bl }, err error) { for _, key := range keys { address := crypto.PubkeyToAddress(key.PublicKey) - chainID := big.NewInt(0) // Prepare one block for pending. var ( @@ -712,7 +701,6 @@ func prepareConfirmedBlocks(dex *Dexon, keys []*ecdsa.PrivateKey, txNum int) (bl block.Hash = coreCommon.NewRandomHash() block.Witness = witness block.Payload = payload - block.Position.ChainID = uint32(chainID.Uint64()) block.ProposerID = coreTypes.NodeID{coreCommon.Hash{1, 2, 3}} status := dex.app.VerifyBlock(block) diff --git a/dex/governance.go b/dex/governance.go index 8b20cda19..56d08975e 100644 --- a/dex/governance.go +++ b/dex/governance.go @@ -229,12 +229,8 @@ func (d *DexconGovernance) ReportForkBlock(block1, block2 *coreTypes.Block) { } } -func (d *DexconGovernance) GetNumChains(round uint64) uint32 { - return 1 -} - -func (d *DexconGovernance) NotarySet(round uint64, chainID uint32) (map[string]struct{}, error) { - notarySet, err := d.nodeSetCache.GetNotarySet(round, chainID) +func (d *DexconGovernance) NotarySet(round uint64) (map[string]struct{}, error) { + notarySet, err := d.nodeSetCache.GetNotarySet(round) if err != nil { return nil, err } @@ -262,3 +258,16 @@ func (d *DexconGovernance) DKGSet(round uint64) (map[string]struct{}, error) { } return r, nil } + +func (d *DexconGovernance) ResetDKG(newSignedCRS []byte) { + data, err := vm.PackResetDKG(newSignedCRS) + if err != nil { + log.Error("failed to pack resetDKG input", "err", err) + return + } + + err = d.sendGovTx(context.Background(), data) + if err != nil { + log.Error("failed to send resetDKG tx", "err", err) + } +} diff --git a/dex/handler.go b/dex/handler.go index 474852913..4ffa01244 100644 --- a/dex/handler.go +++ b/dex/handler.go @@ -1005,9 +1005,8 @@ func (pm *ProtocolManager) BroadcastVote(vote *coreTypes.Vote) { pm.cache.addVote(vote) } label := peerLabel{ - set: notaryset, - chainID: vote.Position.ChainID, - round: vote.Position.Round, + set: notaryset, + round: vote.Position.Round, } for _, peer := range pm.peers.PeersWithLabel(label) { peer.AsyncSendVotes([]*coreTypes.Vote{vote}) @@ -1038,9 +1037,8 @@ func (pm *ProtocolManager) BroadcastRandomnessResult( pm.cache.addRandomness(randomness) // send to notary nodes first (direct) label := peerLabel{ - set: notaryset, - chainID: randomness.Position.ChainID, - round: randomness.Position.Round, + set: notaryset, + round: randomness.Position.Round, } randomnesses := []*coreTypes.BlockRandomnessResult{randomness} for _, peer := range pm.peers.PeersWithLabel(label) { @@ -1104,9 +1102,8 @@ func (pm *ProtocolManager) BroadcastPullBlocks( func (pm *ProtocolManager) BroadcastPullVotes( pos coreTypes.Position) { label := peerLabel{ - set: notaryset, - chainID: pos.ChainID, - round: pos.Round, + set: notaryset, + round: pos.Round, } for idx, peer := range pm.peers.PeersWithLabel(label) { if idx >= maxPullVotePeers { diff --git a/dex/helper_test.go b/dex/helper_test.go index e3d6aa3b7..3f901e6ec 100644 --- a/dex/helper_test.go +++ b/dex/helper_test.go @@ -130,10 +130,9 @@ func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func } tgov := &testGovernance{ - numChainsFunc: func(uint64) uint32 { return 3 }, lenCRSFunc: func() uint64 { return 1 }, dkgSetFunc: func(uint64) (map[string]struct{}, error) { return nil, nil }, - notarySetFunc: func(uint64, uint32) (map[string]struct{}, error) { return nil, nil }, + notarySetFunc: func(uint64) (map[string]struct{}, error) { return nil, nil }, } pm, err := NewProtocolManager(gspec.Config, mode, DefaultConfig.NetworkId, dMoment, evmux, &testTxPool{added: newtx}, engine, blockchain, db, true, tgov, &testApp{}) @@ -211,23 +210,18 @@ func newTestTransaction(from *ecdsa.PrivateKey, nonce uint64, datasize int) *typ // testGovernance is a fake, helper governance for testing purposes type testGovernance struct { - numChainsFunc func(uint64) uint32 lenCRSFunc func() uint64 - notarySetFunc func(uint64, uint32) (map[string]struct{}, error) + notarySetFunc func(uint64) (map[string]struct{}, error) dkgSetFunc func(uint64) (map[string]struct{}, error) } -func (g *testGovernance) GetNumChains(round uint64) uint32 { - return g.numChainsFunc(round) -} - func (g *testGovernance) LenCRS() uint64 { return g.lenCRSFunc() } func (g *testGovernance) NotarySet( - round uint64, chainID uint32) (map[string]struct{}, error) { - return g.notarySetFunc(round, chainID) + round uint64) (map[string]struct{}, error) { + return g.notarySetFunc(round) } func (g *testGovernance) DKGSet(round uint64) (map[string]struct{}, error) { diff --git a/dex/peer.go b/dex/peer.go index a157709f0..8ade9f152 100644 --- a/dex/peer.go +++ b/dex/peer.go @@ -119,9 +119,8 @@ const ( ) type peerLabel struct { - set setType - chainID uint32 - round uint64 + set setType + round uint64 } func (p peerLabel) String() string { @@ -130,7 +129,7 @@ func (p peerLabel) String() string { case dkgset: t = fmt.Sprintf("DKGSet round: %d", p.round) case notaryset: - t = fmt.Sprintf("NotarySet round: %d chain: %d", p.round, p.chainID) + t = fmt.Sprintf("NotarySet round: %d", p.round) } return t } @@ -962,24 +961,22 @@ func (ps *peerSet) BuildConnection(round uint64) { } } - for chainID := uint32(0); chainID < ps.gov.GetNumChains(round); chainID++ { - notaryLabel := peerLabel{set: notaryset, chainID: chainID, round: round} - if _, ok := ps.label2Nodes[notaryLabel]; !ok { - notaryPKs, err := ps.gov.NotarySet(round, chainID) - if err != nil { - log.Error("get notary set fail", - "round", round, "chainID", chainID, "err", err) - continue - } + notaryLabel := peerLabel{set: notaryset, round: round} + if _, ok := ps.label2Nodes[notaryLabel]; !ok { + notaryPKs, err := ps.gov.NotarySet(round) + if err != nil { + log.Error("get notary set fail", + "round", round, "err", err) + return + } - nodes := ps.pksToNodes(notaryPKs) - ps.label2Nodes[notaryLabel] = nodes + nodes := ps.pksToNodes(notaryPKs) + ps.label2Nodes[notaryLabel] = nodes - if _, exists := nodes[ps.srvr.Self().ID().String()]; exists { - ps.buildDirectConn(notaryLabel) - } else { - ps.buildGroupConn(notaryLabel) - } + if _, exists := nodes[ps.srvr.Self().ID().String()]; exists { + ps.buildDirectConn(notaryLabel) + } else { + ps.buildGroupConn(notaryLabel) } } } diff --git a/dex/peer_test.go b/dex/peer_test.go index 29b4971c5..76a28b1ef 100644 --- a/dex/peer_test.go +++ b/dex/peer_test.go @@ -19,41 +19,25 @@ func TestPeerSetBuildAndForgetConn(t *testing.T) { self := server.Self() table := newNodeTable() - gov := &testGovernance{ - numChainsFunc: func(uint64) uint32 { - return 3 - }, - } + gov := &testGovernance{} var nodes []*enode.Node for i := 0; i < 9; i++ { nodes = append(nodes, randomV4CompactNode()) } - round10 := [][]*enode.Node{ - {self, nodes[1], nodes[2]}, - {nodes[1], nodes[3]}, - {nodes[2], nodes[4]}, - } - round11 := [][]*enode.Node{ - {self, nodes[1], nodes[5]}, - {nodes[5], nodes[6]}, - {self, nodes[2], nodes[4]}, - } - round12 := [][]*enode.Node{ - {self, nodes[3], nodes[5]}, - {self, nodes[7], nodes[8]}, - {self, nodes[2], nodes[6]}, - } + round10 := []*enode.Node{self, nodes[1], nodes[2]} + round11 := []*enode.Node{self, nodes[1], nodes[5]} + round12 := []*enode.Node{self, nodes[3], nodes[5]} gov.notarySetFunc = func( - round uint64, cid uint32) (map[string]struct{}, error) { - m := map[uint64][][]*enode.Node{ + round uint64) (map[string]struct{}, error) { + m := map[uint64][]*enode.Node{ 10: round10, 11: round11, 12: round12, } - return newTestNodeSet(m[round][cid]), nil + return newTestNodeSet(m[round]), nil } gov.dkgSetFunc = func(round uint64) (map[string]struct{}, error) { @@ -73,58 +57,31 @@ func TestPeerSetBuildAndForgetConn(t *testing.T) { ps.BuildConnection(12) expectedlabel2Nodes := map[peerLabel]map[string]*enode.Node{ - {set: notaryset, round: 10, chainID: 0}: { + {set: notaryset, round: 10}: { self.ID().String(): self, nodes[1].ID().String(): nodes[1], nodes[2].ID().String(): nodes[2], }, - {set: notaryset, round: 10, chainID: 1}: { - nodes[1].ID().String(): nodes[1], - nodes[3].ID().String(): nodes[3], - }, - {set: notaryset, round: 10, chainID: 2}: { - nodes[2].ID().String(): nodes[2], - nodes[4].ID().String(): nodes[4], - }, {set: dkgset, round: 10}: { self.ID().String(): self, nodes[1].ID().String(): nodes[1], nodes[3].ID().String(): nodes[3], }, - {set: notaryset, round: 11, chainID: 0}: { + {set: notaryset, round: 11}: { self.ID().String(): self, nodes[1].ID().String(): nodes[1], nodes[5].ID().String(): nodes[5], }, - {set: notaryset, round: 11, chainID: 1}: { - nodes[5].ID().String(): nodes[5], - nodes[6].ID().String(): nodes[6], - }, - {set: notaryset, round: 11, chainID: 2}: { - self.ID().String(): self, - nodes[2].ID().String(): nodes[2], - nodes[4].ID().String(): nodes[4], - }, {set: dkgset, round: 11}: { nodes[1].ID().String(): nodes[1], nodes[2].ID().String(): nodes[2], nodes[5].ID().String(): nodes[5], }, - {set: notaryset, round: 12, chainID: 0}: { + {set: notaryset, round: 12}: { self.ID().String(): self, nodes[3].ID().String(): nodes[3], nodes[5].ID().String(): nodes[5], }, - {set: notaryset, round: 12, chainID: 1}: { - self.ID().String(): self, - nodes[7].ID().String(): nodes[7], - nodes[8].ID().String(): nodes[8], - }, - {set: notaryset, round: 12, chainID: 2}: { - self.ID().String(): self, - nodes[2].ID().String(): nodes[2], - nodes[6].ID().String(): nodes[6], - }, {set: dkgset, round: 12}: { self.ID().String(): self, nodes[3].ID().String(): nodes[3], @@ -137,14 +94,11 @@ func TestPeerSetBuildAndForgetConn(t *testing.T) { } expectedDirectConn := map[peerLabel]struct{}{ - {set: notaryset, round: 10, chainID: 0}: {}, - {set: notaryset, round: 11, chainID: 0}: {}, - {set: notaryset, round: 11, chainID: 2}: {}, - {set: notaryset, round: 12, chainID: 0}: {}, - {set: notaryset, round: 12, chainID: 1}: {}, - {set: notaryset, round: 12, chainID: 2}: {}, - {set: dkgset, round: 10}: {}, - {set: dkgset, round: 12}: {}, + {set: notaryset, round: 10}: {}, + {set: notaryset, round: 11}: {}, + {set: notaryset, round: 12}: {}, + {set: dkgset, round: 10}: {}, + {set: dkgset, round: 12}: {}, } if !reflect.DeepEqual(ps.directConn, expectedDirectConn) { @@ -152,9 +106,6 @@ func TestPeerSetBuildAndForgetConn(t *testing.T) { } expectedGroupConn := []peerLabel{ - {set: notaryset, round: 10, chainID: 1}, - {set: notaryset, round: 10, chainID: 2}, - {set: notaryset, round: 11, chainID: 1}, {set: dkgset, round: 11}, } @@ -196,21 +147,11 @@ func TestPeerSetBuildAndForgetConn(t *testing.T) { ps.ForgetConnection(11) expectedlabel2Nodes = map[peerLabel]map[string]*enode.Node{ - {set: notaryset, round: 12, chainID: 0}: { + {set: notaryset, round: 12}: { self.ID().String(): self, nodes[3].ID().String(): nodes[3], nodes[5].ID().String(): nodes[5], }, - {set: notaryset, round: 12, chainID: 1}: { - self.ID().String(): self, - nodes[7].ID().String(): nodes[7], - nodes[8].ID().String(): nodes[8], - }, - {set: notaryset, round: 12, chainID: 2}: { - self.ID().String(): self, - nodes[2].ID().String(): nodes[2], - nodes[6].ID().String(): nodes[6], - }, {set: dkgset, round: 12}: { self.ID().String(): self, nodes[3].ID().String(): nodes[3], @@ -223,10 +164,8 @@ func TestPeerSetBuildAndForgetConn(t *testing.T) { } expectedDirectConn = map[peerLabel]struct{}{ - {set: notaryset, round: 12, chainID: 0}: {}, - {set: notaryset, round: 12, chainID: 1}: {}, - {set: notaryset, round: 12, chainID: 2}: {}, - {set: dkgset, round: 12}: {}, + {set: notaryset, round: 12}: {}, + {set: dkgset, round: 12}: {}, } if !reflect.DeepEqual(ps.directConn, expectedDirectConn) { diff --git a/dex/protocol.go b/dex/protocol.go index 6ee02959a..0e3f50eba 100644 --- a/dex/protocol.go +++ b/dex/protocol.go @@ -152,11 +152,9 @@ type txPool interface { type governance interface { GetRoundHeight(uint64) uint64 - GetNumChains(uint64) uint32 - LenCRS() uint64 - NotarySet(uint64, uint32) (map[string]struct{}, error) + NotarySet(uint64) (map[string]struct{}, error) DKGSet(uint64) (map[string]struct{}, error) } diff --git a/dex/protocol_test.go b/dex/protocol_test.go index aa06d7293..fb414613e 100644 --- a/dex/protocol_test.go +++ b/dex/protocol_test.go @@ -327,15 +327,11 @@ func TestRecvLatticeBlocks(t *testing.T) { ParentHash: coreCommon.Hash{1, 1, 1, 1, 1}, Hash: coreCommon.Hash{2, 2, 2, 2, 2}, Position: coreTypes.Position{ - ChainID: 11, - Round: 12, - Height: 13, + Round: 12, + Height: 13, }, Timestamp: time.Now().UTC(), - Acks: coreCommon.NewSortedHashes(coreCommon.Hashes([]coreCommon.Hash{ - {101}, {100}, {102}, - })), - Payload: []byte{3, 3, 3, 3, 3}, + Payload: []byte{3, 3, 3, 3, 3}, Witness: coreTypes.Witness{ Height: 13, Data: []byte{4, 4, 4, 4, 4}, @@ -382,15 +378,11 @@ func TestSendLatticeBlocks(t *testing.T) { ParentHash: coreCommon.Hash{1, 1, 1, 1, 1}, Hash: coreCommon.Hash{2, 2, 2, 2, 2}, Position: coreTypes.Position{ - ChainID: 11, - Round: 12, - Height: 13, + Round: 12, + Height: 13, }, Timestamp: time.Now().UTC(), - Acks: coreCommon.NewSortedHashes(coreCommon.Hashes([]coreCommon.Hash{ - {101}, {100}, {102}, - })), - Payload: []byte{3, 3, 3, 3, 3}, + Payload: []byte{3, 3, 3, 3, 3}, Witness: coreTypes.Witness{ Height: 13, Data: []byte{4, 4, 4, 4, 4}, @@ -440,9 +432,8 @@ func TestRecvVotes(t *testing.T) { ProposerID: coreTypes.NodeID{coreCommon.Hash{1, 2, 3}}, Period: 10, Position: coreTypes.Position{ - ChainID: 11, - Round: 12, - Height: 13, + Round: 12, + Height: 13, }, }, Signature: coreCrypto.Signature{ @@ -477,9 +468,8 @@ func TestSendVotes(t *testing.T) { ProposerID: coreTypes.NodeID{coreCommon.Hash{1, 2, 3}}, Period: 10, Position: coreTypes.Position{ - ChainID: 1, - Round: 10, - Height: 13, + Round: 10, + Height: 13, }, }, Signature: coreCrypto.Signature{ @@ -528,11 +518,7 @@ func TestSendVotes(t *testing.T) { isReceiver bool }{ { - label: &peerLabel{set: notaryset, chainID: 1, round: 10}, - isReceiver: true, - }, - { - label: &peerLabel{set: notaryset, chainID: 1, round: 10}, + label: &peerLabel{set: notaryset, round: 10}, isReceiver: true, }, { @@ -540,15 +526,11 @@ func TestSendVotes(t *testing.T) { isReceiver: false, }, { - label: &peerLabel{set: notaryset, chainID: 1, round: 11}, + label: &peerLabel{set: notaryset, round: 11}, isReceiver: false, }, { - label: &peerLabel{set: notaryset, chainID: 2, round: 10}, - isReceiver: false, - }, - { - label: &peerLabel{set: dkgset, chainID: 1, round: 10}, + label: &peerLabel{set: dkgset, round: 10}, isReceiver: false, }, } @@ -678,9 +660,8 @@ func TestRecvAgreement(t *testing.T) { ProposerID: coreTypes.NodeID{coreCommon.Hash{1, 2, 3}}, Period: 10, Position: coreTypes.Position{ - ChainID: 1, - Round: 10, - Height: 13, + Round: 10, + Height: 13, }, }, Signature: coreCrypto.Signature{ @@ -723,9 +704,8 @@ func TestSendAgreement(t *testing.T) { ProposerID: coreTypes.NodeID{coreCommon.Hash{1, 2, 3}}, Period: 10, Position: coreTypes.Position{ - ChainID: 1, - Round: 10, - Height: 13, + Round: 10, + Height: 13, }, }, Signature: coreCrypto.Signature{ @@ -769,9 +749,8 @@ func TestRecvRandomnesses(t *testing.T) { randomness := coreTypes.BlockRandomnessResult{ BlockHash: coreCommon.Hash{8, 8, 8}, Position: coreTypes.Position{ - ChainID: 1, - Round: 10, - Height: 13, + Round: 10, + Height: 13, }, Randomness: []byte{7, 7, 7, 7}, } @@ -802,9 +781,8 @@ func TestSendRandomnesses(t *testing.T) { randomness := coreTypes.BlockRandomnessResult{ BlockHash: coreCommon.Hash{8, 8, 8}, Position: coreTypes.Position{ - ChainID: 1, - Round: 10, - Height: 13, + Round: 10, + Height: 13, }, Randomness: []byte{7, 7, 7, 7}, } diff --git a/params/config.go b/params/config.go index 6971e1a72..a1fa0f6d8 100644 --- a/params/config.go +++ b/params/config.go @@ -142,7 +142,7 @@ var ( LambdaDKG: 10000, NotarySetSize: 4, DKGSetSize: 4, - RoundLength: 1200000, + RoundLength: 1200, MinBlockInterval: 1000, FineValues: []*big.Int{ new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e4)), diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/common/event.go b/vendor/github.com/dexon-foundation/dexon-consensus/common/event.go index 6c6bf49d4..4e4e23bf3 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/common/event.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/common/event.go @@ -20,26 +20,25 @@ package common import ( "container/heap" "sync" - "time" ) -type timeEventFn func(time.Time) +type heightEventFn func(uint64) -type timeEvent struct { - t time.Time - fn timeEventFn +type heightEvent struct { + h uint64 + fn heightEventFn } -// timeEvents implements a Min-Heap structure. -type timeEvents []timeEvent +// heightEvents implements a Min-Heap structure. +type heightEvents []heightEvent -func (h timeEvents) Len() int { return len(h) } -func (h timeEvents) Less(i, j int) bool { return h[i].t.Before(h[j].t) } -func (h timeEvents) Swap(i, j int) { h[i], h[j] = h[j], h[i] } -func (h *timeEvents) Push(x interface{}) { - *h = append(*h, x.(timeEvent)) +func (h heightEvents) Len() int { return len(h) } +func (h heightEvents) Less(i, j int) bool { return h[i].h < h[j].h } +func (h heightEvents) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *heightEvents) Push(x interface{}) { + *h = append(*h, x.(heightEvent)) } -func (h *timeEvents) Pop() interface{} { +func (h *heightEvents) Pop() interface{} { old := *h n := len(old) x := old[n-1] @@ -49,54 +48,54 @@ func (h *timeEvents) Pop() interface{} { // Event implements the Observer pattern. type Event struct { - timeEvents timeEvents - timeEventsLock sync.Mutex + heightEvents heightEvents + heightEventsLock sync.Mutex } // NewEvent creates a new event instance. func NewEvent() *Event { - te := timeEvents{} - heap.Init(&te) + he := heightEvents{} + heap.Init(&he) return &Event{ - timeEvents: te, + heightEvents: he, } } -// RegisterTime to get notified on and after specific time. -func (e *Event) RegisterTime(t time.Time, fn timeEventFn) { - e.timeEventsLock.Lock() - defer e.timeEventsLock.Unlock() - heap.Push(&e.timeEvents, timeEvent{ - t: t, +// RegisterHeight to get notified on a specific height. +func (e *Event) RegisterHeight(h uint64, fn heightEventFn) { + e.heightEventsLock.Lock() + defer e.heightEventsLock.Unlock() + heap.Push(&e.heightEvents, heightEvent{ + h: h, fn: fn, }) } -// NotifyTime and trigger function callback. -func (e *Event) NotifyTime(t time.Time) { - fns := func() (fns []timeEventFn) { - e.timeEventsLock.Lock() - defer e.timeEventsLock.Unlock() - if len(e.timeEvents) == 0 { +// NotifyHeight and trigger function callback. +func (e *Event) NotifyHeight(h uint64) { + fns := func() (fns []heightEventFn) { + e.heightEventsLock.Lock() + defer e.heightEventsLock.Unlock() + if len(e.heightEvents) == 0 { return } - for !t.Before(e.timeEvents[0].t) { - te := heap.Pop(&e.timeEvents).(timeEvent) - fns = append(fns, te.fn) - if len(e.timeEvents) == 0 { + for h >= e.heightEvents[0].h { + he := heap.Pop(&e.heightEvents).(heightEvent) + fns = append(fns, he.fn) + if len(e.heightEvents) == 0 { return } } return }() for _, fn := range fns { - fn(t) + fn(h) } } // Reset clears all pending event func (e *Event) Reset() { - e.timeEventsLock.Lock() - defer e.timeEventsLock.Unlock() - e.timeEvents = timeEvents{} + e.heightEventsLock.Lock() + defer e.heightEventsLock.Unlock() + e.heightEvents = heightEvents{} } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go index 5f5b9ae5f..88cc432ff 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go @@ -65,13 +65,29 @@ func genValidLeader( } type agreementMgrConfig struct { - beginTime time.Time - roundInterval time.Duration + roundBasedConfig + notarySetSize uint32 lambdaBA time.Duration crs common.Hash } +func (c *agreementMgrConfig) from( + round uint64, config *types.Config, crs common.Hash) { + c.notarySetSize = config.NotarySetSize + c.lambdaBA = config.LambdaBA + c.crs = crs + c.setupRoundBasedFields(round, config) +} + +func newAgreementMgrConfig(prev agreementMgrConfig, config *types.Config, + crs common.Hash) (c agreementMgrConfig) { + c = agreementMgrConfig{} + c.from(prev.roundID+1, config, crs) + c.setRoundBeginHeight(prev.roundEndHeight) + return +} + type baRoundSetting struct { notarySet map[types.NodeID]struct{} agr *agreement @@ -92,9 +108,8 @@ type agreementMgr struct { signer *utils.Signer bcModule *blockChain ctx context.Context - lastEndTime time.Time initRound uint64 - configs []*agreementMgrConfig + configs []agreementMgrConfig baModule *agreement processedBAResult map[types.Position]struct{} voteFilter *utils.VoteFilter @@ -104,8 +119,8 @@ type agreementMgr struct { } func newAgreementMgr(con *Consensus, initRound uint64, - initRoundBeginTime time.Time) *agreementMgr { - return &agreementMgr{ + initConfig agreementMgrConfig) (mgr *agreementMgr, err error) { + mgr = &agreementMgr{ con: con, ID: con.ID, app: con.app, @@ -117,9 +132,33 @@ func newAgreementMgr(con *Consensus, initRound uint64, bcModule: con.bcModule, ctx: con.ctx, initRound: initRound, - lastEndTime: initRoundBeginTime, processedBAResult: make(map[types.Position]struct{}, maxResultCache), + configs: []agreementMgrConfig{initConfig}, + voteFilter: utils.NewVoteFilter(), } + recv := &consensusBAReceiver{ + consensus: con, + restartNotary: make(chan types.Position, 1), + roundValue: &atomic.Value{}, + } + recv.roundValue.Store(uint64(0)) + agr := newAgreement( + mgr.ID, + recv, + newLeaderSelector(genValidLeader(mgr), mgr.logger), + mgr.signer, + mgr.logger) + // Hacky way to initialize first notarySet. + nodes, err := mgr.cache.GetNodeSet(initRound) + if err != nil { + return + } + agr.notarySet = nodes.GetSubSet( + int(initConfig.notarySetSize), types.NewNotarySetTarget(initConfig.crs)) + // Hacky way to make agreement module self contained. + recv.agreementModule = agr + mgr.baModule = agr + return } func (mgr *agreementMgr) run() { @@ -136,7 +175,7 @@ func (mgr *agreementMgr) run() { }() } -func (mgr *agreementMgr) getConfig(round uint64) *agreementMgrConfig { +func (mgr *agreementMgr) config(round uint64) *agreementMgrConfig { mgr.lock.RLock() defer mgr.lock.RUnlock() if round < mgr.initRound { @@ -146,7 +185,7 @@ func (mgr *agreementMgr) getConfig(round uint64) *agreementMgrConfig { if roundIndex >= uint64(len(mgr.configs)) { return nil } - return mgr.configs[roundIndex] + return &mgr.configs[roundIndex] } func (mgr *agreementMgr) appendConfig( @@ -156,52 +195,12 @@ func (mgr *agreementMgr) appendConfig( if round != uint64(len(mgr.configs))+mgr.initRound { return ErrRoundNotIncreasing } - newConfig := &agreementMgrConfig{ - beginTime: mgr.lastEndTime, - roundInterval: config.RoundInterval, - notarySetSize: config.NotarySetSize, - lambdaBA: config.LambdaBA, - crs: crs, - } - mgr.configs = append(mgr.configs, newConfig) - mgr.lastEndTime = mgr.lastEndTime.Add(config.RoundInterval) - // Prepare modules. - if mgr.baModule != nil { - return nil - } - recv := &consensusBAReceiver{ - consensus: mgr.con, - restartNotary: make(chan types.Position, 1), - roundValue: &atomic.Value{}, - } - recv.roundValue.Store(uint64(0)) - agrModule := newAgreement( - mgr.con.ID, - recv, - newLeaderSelector(genValidLeader(mgr), mgr.logger), - mgr.signer, - mgr.logger) - // Hacky way to initialize first notarySet. - nodes, err := mgr.cache.GetNodeSet(round) - if err != nil { - return err - } - agrModule.notarySet = nodes.GetSubSet( - int(config.NotarySetSize), types.NewNotarySetTarget(crs)) - // Hacky way to make agreement module self contained. - recv.agreementModule = agrModule - mgr.baModule = agrModule - mgr.voteFilter = utils.NewVoteFilter() + mgr.configs = append(mgr.configs, newAgreementMgrConfig( + mgr.configs[len(mgr.configs)-1], config, crs)) return nil } func (mgr *agreementMgr) processVote(v *types.Vote) (err error) { - if v.Position.ChainID > 0 { - mgr.logger.Error("Process vote for unknown chain to BA", - "position", v.Position, - "initRound", mgr.initRound) - return utils.ErrInvalidChainID - } if mgr.voteFilter.Filter(v) { return nil } @@ -212,13 +211,6 @@ func (mgr *agreementMgr) processVote(v *types.Vote) (err error) { } func (mgr *agreementMgr) processBlock(b *types.Block) error { - if b.Position.ChainID > 0 { - mgr.logger.Error("Process block for unknown chain to BA", - "position", b.Position, - "baRound", len(mgr.configs), - "initRound", mgr.initRound) - return utils.ErrInvalidChainID - } return mgr.baModule.processBlock(b) } @@ -247,13 +239,6 @@ func (mgr *agreementMgr) untouchAgreementResult( func (mgr *agreementMgr) processAgreementResult( result *types.AgreementResult) error { - if result.Position.ChainID > 0 { - mgr.logger.Error("Process unknown result for unknown chain to BA", - "position", result.Position, - "baRound", len(mgr.configs), - "initRound", mgr.initRound) - return utils.ErrInvalidChainID - } aID := mgr.baModule.agreementID() if isStop(aID) { return nil @@ -310,13 +295,12 @@ func (mgr *agreementMgr) runBA(initRound uint64) { var ( currentRound uint64 nextRound = initRound + curConfig = mgr.config(initRound) setting = baRoundSetting{ agr: mgr.baModule, recv: mgr.baModule.data.recv.(*consensusBAReceiver), } - roundBeginTime time.Time - roundEndTime time.Time - tickDuration time.Duration + tickDuration time.Duration ) // Check if this routine needs to awake in this round and prepare essential @@ -327,24 +311,20 @@ func (mgr *agreementMgr) runBA(initRound uint64) { nextRound++ }() // Wait until the configuartion for next round is ready. - var config *agreementMgrConfig for { - if config = mgr.getConfig(nextRound); config != nil { + if curConfig = mgr.config(nextRound); curConfig != nil { break } else { mgr.logger.Debug("round is not ready", "round", nextRound) time.Sleep(1 * time.Second) } } - // Set next checkpoint. - roundBeginTime = config.beginTime - roundEndTime = config.beginTime.Add(config.roundInterval) // Check if this node in notary set of this chain in this round. - notarySet, err := mgr.cache.GetNotarySet(nextRound, 0) + notarySet, err := mgr.cache.GetNotarySet(nextRound) if err != nil { panic(err) } - setting.crs = config.crs + setting.crs = curConfig.crs setting.notarySet = notarySet _, isNotary = setting.notarySet[mgr.ID] if isNotary { @@ -357,12 +337,12 @@ func (mgr *agreementMgr) runBA(initRound uint64) { "round", nextRound) } // Setup ticker - if tickDuration != config.lambdaBA { + if tickDuration != curConfig.lambdaBA { if setting.ticker != nil { setting.ticker.Stop() } setting.ticker = newTicker(mgr.gov, nextRound, TickerBA) - tickDuration = config.lambdaBA + tickDuration = curConfig.lambdaBA } return } @@ -373,29 +353,13 @@ Loop: break Loop default: } - now := time.Now().UTC() setting.recv.isNotary = checkRound() - // Sleep until round begin. Here a biased round begin time would be - // used instead of the one in config. The reason it to disperse the load - // of fullnodes to verify confirmed blocks from each chain. - if now.Before(pickBiasedTime(roundBeginTime, 4*tickDuration)) { - select { - case <-mgr.ctx.Done(): - break Loop - case <-time.After(roundBeginTime.Sub(now)): - } - // Clean the tick channel after awake: the tick would be queued in - // channel, thus the first few ticks would not tick on expected - // interval. - <-setting.ticker.Tick() - <-setting.ticker.Tick() - } // Run BA for this round. setting.recv.roundValue.Store(currentRound) - setting.recv.changeNotaryTime = roundEndTime + setting.recv.changeNotaryHeight = curConfig.roundEndHeight setting.recv.restartNotary <- types.Position{ - Round: setting.recv.round(), - ChainID: math.MaxUint32, + Round: setting.recv.round(), + Height: math.MaxUint64, } mgr.voteFilter = utils.NewVoteFilter() if err := mgr.baRoutineForOneRound(&setting); err != nil { @@ -450,7 +414,7 @@ func (mgr *agreementMgr) baRoutineForOneRound( if isStop(oldPos) && nextHeight == 0 { break } - if isStop(restartPos) && nextHeight == 0 { + if isStop(restartPos) { break } if nextHeight > restartPos.Height { diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go index 579cea8c3..43fddd0a0 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go @@ -254,12 +254,12 @@ func (a *agreement) restart( func (a *agreement) stop() { a.restart(make(map[types.NodeID]struct{}), types.Position{ - ChainID: math.MaxUint32, + Height: math.MaxUint64, }, types.NodeID{}, common.Hash{}) } func isStop(aID types.Position) bool { - return aID.ChainID == math.MaxUint32 + return aID.Height == math.MaxUint64 } // clocks returns how many time this state is required. diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go index d1aa644a5..03c8561c5 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go @@ -110,7 +110,7 @@ func newBlockChainConfig(prev blockChainConfig, config *types.Config) ( c blockChainConfig) { c = blockChainConfig{} c.fromConfig(prev.roundID+1, config) - c.setRoundBeginTime(prev.roundEndTime) + c.setRoundBeginHeight(prev.roundEndHeight) return } @@ -131,9 +131,10 @@ type blockChain struct { configs []blockChainConfig pendingBlocks pendingBlockRecords confirmedBlocks types.BlocksByPosition + dMoment time.Time } -func newBlockChain(nID types.NodeID, initBlock *types.Block, +func newBlockChain(nID types.NodeID, dMoment time.Time, initBlock *types.Block, initConfig blockChainConfig, app Application, vGetter tsigVerifierGetter, signer *utils.Signer, logger common.Logger) *blockChain { if initBlock != nil { @@ -156,6 +157,7 @@ func newBlockChain(nID types.NodeID, initBlock *types.Block, app: app, logger: logger, configs: []blockChainConfig{initConfig}, + dMoment: dMoment, pendingRandomnesses: make( map[types.Position]*types.BlockRandomnessResult), } @@ -186,7 +188,7 @@ func (bc *blockChain) extractBlocks() (ret []*types.Block) { defer bc.lock.Unlock() for len(bc.confirmedBlocks) > 0 { c := bc.confirmedBlocks[0] - if c.Position.Round > 0 && len(c.Finalization.Randomness) == 0 { + if c.Position.Round >= DKGDelayRound && len(c.Finalization.Randomness) == 0 { break } c, bc.confirmedBlocks = bc.confirmedBlocks[0], bc.confirmedBlocks[1:] @@ -203,9 +205,6 @@ func (bc *blockChain) extractBlocks() (ret []*types.Block) { } func (bc *blockChain) sanityCheck(b *types.Block) error { - if b.Position.ChainID != 0 { - panic(fmt.Errorf("attempt to process block from non-zero chainID")) - } if b.IsEmpty() { panic(fmt.Errorf("pass empty block to sanity check: %s", b)) } @@ -228,7 +227,7 @@ func (bc *blockChain) sanityCheck(b *types.Block) error { } return ErrInvalidBlockHeight } - tipConfig := bc.getTipConfig() + tipConfig := bc.tipConfig() if tipConfig.isLastBlock(bc.lastConfirmed) { if b.Position.Round != bc.lastConfirmed.Position.Round+1 { return ErrRoundNotSwitch @@ -250,9 +249,6 @@ func (bc *blockChain) sanityCheck(b *types.Block) error { // addEmptyBlock is called when an empty block is confirmed by BA. func (bc *blockChain) addEmptyBlock(position types.Position) ( *types.Block, error) { - if position.ChainID != 0 { - panic(fmt.Errorf("attempt to process block from non-zero chainID")) - } bc.lock.Lock() defer bc.lock.Unlock() add := func() *types.Block { @@ -286,9 +282,6 @@ func (bc *blockChain) addEmptyBlock(position types.Position) ( // addBlock should be called when the block is confirmed by BA, we won't perform // sanity check against this block, it's ok to add block with skipping height. func (bc *blockChain) addBlock(b *types.Block) error { - if b.Position.ChainID != 0 { - panic(fmt.Errorf("attempt to process block from non-zero chainID")) - } bc.lock.Lock() defer bc.lock.Unlock() confirmed := false @@ -314,9 +307,6 @@ func (bc *blockChain) addBlock(b *types.Block) error { } func (bc *blockChain) addRandomness(r *types.BlockRandomnessResult) error { - if r.Position.ChainID != 0 { - panic(fmt.Errorf("attempt to process block from non-zero chainID")) - } if func() bool { bc.lock.RLock() defer bc.lock.RUnlock() @@ -361,8 +351,8 @@ func (bc *blockChain) tipRound() uint64 { if bc.lastConfirmed == nil { return 0 } - offset := uint64(0) - if bc.lastConfirmed.Timestamp.After(bc.getTipConfig().roundEndTime) { + offset, tipConfig := uint64(0), bc.tipConfig() + if tipConfig.isLastBlock(bc.lastConfirmed) { offset++ } return bc.lastConfirmed.Position.Round + offset @@ -392,7 +382,7 @@ func (bc *blockChain) nextBlock() (uint64, time.Time) { // lastConfirmed block in the scenario of "nextBlock" method. tip, config := bc.lastConfirmed, bc.configs[0] if tip == nil { - return 0, config.roundBeginTime + return 0, bc.dMoment } return tip.Position.Height + 1, tip.Timestamp.Add(config.minBlockInterval) } @@ -461,6 +451,11 @@ func (bc *blockChain) findPendingBlock(p types.Position) *types.Block { func (bc *blockChain) addPendingBlockRecord(p pendingBlockRecord) { if err := bc.pendingBlocks.insert(p); err != nil { + if err == ErrDuplicatedPendingBlock { + // TODO(mission): panic directly once our BA can confirm blocks + // uniquely and in sequence. + return + } panic(err) } if p.block != nil { @@ -507,7 +502,7 @@ func (bc *blockChain) purgeConfig() { func (bc *blockChain) verifyRandomness( blockHash common.Hash, round uint64, randomness []byte) (bool, error) { - if round == 0 { + if round < DKGDelayRound { return len(randomness) == 0, nil } v, ok, err := bc.vGetter.UpdateAndGet(round) @@ -528,26 +523,31 @@ func (bc *blockChain) prepareBlock(position types.Position, b = &types.Block{Position: position, Timestamp: proposeTime} tip := bc.lastConfirmed // Make sure we can propose a block at expected position for callers. - expectedPosition := types.Position{} if tip == nil { // The case for genesis block. - if !position.Equal(expectedPosition) { + if !position.Equal(types.Position{}) { b, err = nil, ErrNotGenesisBlock + return } else if empty { - b.Timestamp = bc.configs[0].roundBeginTime + b.Timestamp = bc.dMoment } } else { - expectedPosition.Height = tip.Position.Height + 1 - tipConfig := bc.getTipConfig() - if tipConfig.isLastBlock(tip) { - expectedPosition.Round = tip.Position.Round + 1 - } else { - expectedPosition.Round = tip.Position.Round - } - if !expectedPosition.Equal(position) { + tipConfig := bc.tipConfig() + if tip.Position.Height+1 != position.Height { b, err = nil, ErrNotFollowTipPosition return } + if tipConfig.isLastBlock(tip) { + if tip.Position.Round+1 != position.Round { + b, err = nil, ErrRoundNotSwitch + return + } + } else { + if tip.Position.Round != position.Round { + b, err = nil, ErrInvalidRoundID + return + } + } b.ParentHash = tip.Hash if !empty { bc.logger.Debug("Calling Application.PreparePayload", @@ -564,7 +564,6 @@ func (bc *blockChain) prepareBlock(position types.Position, if !b.Timestamp.After(tip.Timestamp) { b.Timestamp = tip.Timestamp.Add(tipConfig.minBlockInterval) } - } else { b.Witness.Height = tip.Witness.Height b.Witness.Data = make([]byte, len(tip.Witness.Data)) @@ -585,7 +584,7 @@ func (bc *blockChain) prepareBlock(position types.Position, return } -func (bc *blockChain) getTipConfig() blockChainConfig { +func (bc *blockChain) tipConfig() blockChainConfig { if bc.lastConfirmed == nil { panic(fmt.Errorf("attempting to access config without tip")) } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go index f4c0a372d..370df72cf 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go @@ -58,12 +58,12 @@ var ( // consensusBAReceiver implements agreementReceiver. type consensusBAReceiver struct { // TODO(mission): consensus would be replaced by blockChain and network. - consensus *Consensus - agreementModule *agreement - changeNotaryTime time.Time - roundValue *atomic.Value - isNotary bool - restartNotary chan types.Position + consensus *Consensus + agreementModule *agreement + changeNotaryHeight uint64 + roundValue *atomic.Value + isNotary bool + restartNotary chan types.Position } func (recv *consensusBAReceiver) round() uint64 { @@ -241,10 +241,17 @@ CleanChannelLoop: } } newPos := block.Position - if block.Timestamp.After(recv.changeNotaryTime) { + if block.Position.Height+1 == recv.changeNotaryHeight { newPos.Round++ recv.roundValue.Store(newPos.Round) } + currentRound := recv.round() + if block.Position.Height > recv.changeNotaryHeight && + block.Position.Round <= currentRound { + panic(fmt.Errorf( + "round not switch when confirmig: %s, %d, should switch at %d", + block, currentRound, recv.changeNotaryHeight)) + } recv.restartNotary <- newPos } @@ -383,7 +390,6 @@ type Consensus struct { bcModule *blockChain dMoment time.Time nodeSetCache *utils.NodeSetCache - round uint64 roundForNewConfig uint64 lock sync.RWMutex ctx context.Context @@ -412,7 +418,7 @@ func NewConsensus( prv crypto.PrivateKey, logger common.Logger) *Consensus { return newConsensusForRound( - nil, dMoment, app, gov, db, network, prv, logger, true) + nil, 0, dMoment, app, gov, db, network, prv, logger, true) } // NewConsensusForSimulation creates an instance of Consensus for simulation, @@ -426,7 +432,7 @@ func NewConsensusForSimulation( prv crypto.PrivateKey, logger common.Logger) *Consensus { return newConsensusForRound( - nil, dMoment, app, gov, db, network, prv, logger, false) + nil, 0, dMoment, app, gov, db, network, prv, logger, false) } // NewConsensusFromSyncer constructs an Consensus instance from information @@ -440,7 +446,8 @@ func NewConsensusForSimulation( // their positions, in ascending order. func NewConsensusFromSyncer( initBlock *types.Block, - initRoundBeginTime time.Time, + initRoundBeginHeight uint64, + dMoment time.Time, app Application, gov Governance, db db.Database, @@ -451,8 +458,8 @@ func NewConsensusFromSyncer( cachedMessages []interface{}, logger common.Logger) (*Consensus, error) { // Setup Consensus instance. - con := newConsensusForRound(initBlock, initRoundBeginTime, app, gov, db, - networkModule, prv, logger, true) + con := newConsensusForRound(initBlock, initRoundBeginHeight, dMoment, app, + gov, db, networkModule, prv, logger, true) // Launch a dummy receiver before we start receiving from network module. con.dummyMsgBuffer = cachedMessages con.dummyCancel, con.dummyFinished = utils.LaunchDummyReceiver( @@ -486,9 +493,11 @@ func NewConsensusFromSyncer( } // newConsensusForRound creates a Consensus instance. +// TODO(mission): remove dMoment, it's no longer one part of consensus. func newConsensusForRound( initBlock *types.Block, - initRoundBeginTime time.Time, + initRoundBeginHeight uint64, + dMoment time.Time, app Application, gov Governance, db db.Database, @@ -511,6 +520,7 @@ func newConsensusForRound( initRound = initBlock.Position.Round } initConfig := utils.GetConfigWithPanic(gov, initRound, logger) + initCRS := utils.GetCRSWithPanic(gov, initRound, logger) // Init configuration chain. ID := types.NewNodeID(prv.PublicKey()) recv := &consensusDKGReceiver{ @@ -529,8 +539,8 @@ func newConsensusForRound( } bcConfig := blockChainConfig{} bcConfig.fromConfig(initRound, initConfig) - bcConfig.setRoundBeginTime(initRoundBeginTime) - bcModule := newBlockChain(ID, initBlock, bcConfig, appModule, + bcConfig.setRoundBeginHeight(initRoundBeginHeight) + bcModule := newBlockChain(ID, dMoment, initBlock, bcConfig, appModule, NewTSigVerifierCache(gov, 7), signer, logger) // Construct Consensus instance. con := &Consensus{ @@ -544,7 +554,7 @@ func newConsensusForRound( dkgReady: sync.NewCond(&sync.Mutex{}), cfgModule: cfgModule, bcModule: bcModule, - dMoment: initRoundBeginTime, + dMoment: dMoment, nodeSetCache: nodeSetCache, signer: signer, event: common.NewEvent(), @@ -555,8 +565,15 @@ func newConsensusForRound( processBlockChan: make(chan *types.Block, 1024), } con.ctx, con.ctxCancel = context.WithCancel(context.Background()) - con.baMgr = newAgreementMgr(con, initRound, initRoundBeginTime) - if err := con.prepare(initBlock); err != nil { + baConfig := agreementMgrConfig{} + baConfig.from(initRound, initConfig, initCRS) + baConfig.setRoundBeginHeight(initRoundBeginHeight) + var err error + con.baMgr, err = newAgreementMgr(con, initRound, baConfig) + if err != nil { + panic(err) + } + if err = con.prepare(initRoundBeginHeight, initBlock); err != nil { panic(err) } return con @@ -566,53 +583,28 @@ func newConsensusForRound( // 'initBlock' could be either: // - nil // - the last finalized block -func (con *Consensus) prepare(initBlock *types.Block) (err error) { +func (con *Consensus) prepare( + initRoundBeginHeight uint64, initBlock *types.Block) (err error) { // The block past from full node should be delivered already or known by // full node. We don't have to notify it. initRound := uint64(0) if initBlock != nil { initRound = initBlock.Position.Round } + // Setup blockChain module. con.roundForNewConfig = initRound + 1 initConfig := utils.GetConfigWithPanic(con.gov, initRound, con.logger) - // Setup context. - con.logger.Debug("Calling Governance.CRS", "round", initRound) - initCRS := con.gov.CRS(initRound) - if (initCRS == common.Hash{}) { - err = ErrCRSNotReady - return - } - if err = con.baMgr.appendConfig(initRound, initConfig, initCRS); err != nil { - return - } - // Setup blockChain module. initPlusOneCfg := utils.GetConfigWithPanic(con.gov, initRound+1, con.logger) if err = con.bcModule.appendConfig(initRound+1, initPlusOneCfg); err != nil { return } if initRound == 0 { - dkgSet, err := con.nodeSetCache.GetDKGSet(initRound) - if err != nil { - return err - } - if _, exist := dkgSet[con.ID]; exist { - con.logger.Info("Selected as DKG set", "round", initRound) - go func() { - // Sleep until dMoment come. - time.Sleep(con.dMoment.Sub(time.Now().UTC())) - // Network is not stable upon starting. Wait some time to ensure first - // DKG would success. Three is a magic number. - time.Sleep(initConfig.MinBlockInterval * 3) - con.cfgModule.registerDKG(initRound, getDKGThreshold(initConfig)) - con.event.RegisterTime(con.dMoment.Add(initConfig.RoundInterval/4), - func(time.Time) { - con.runDKG(initRound, initConfig) - }) - }() + if DKGDelayRound == 0 { + panic("not implemented yet") } } // Register events. - con.initialRound(con.dMoment, initRound, initConfig) + con.initialRound(initRoundBeginHeight, initRound, initConfig) return } @@ -672,18 +664,11 @@ func (con *Consensus) runDKG(round uint64, config *types.Config) { } con.dkgRunning = 1 go func() { - startTime := time.Now().UTC() defer func() { con.dkgReady.L.Lock() defer con.dkgReady.L.Unlock() con.dkgReady.Broadcast() con.dkgRunning = 2 - DKGTime := time.Now().Sub(startTime) - if DKGTime.Nanoseconds() >= - config.RoundInterval.Nanoseconds()/2 { - con.logger.Warn("Your computer cannot finish DKG on time!", - "nodeID", con.ID.String()) - } }() if err := con.cfgModule.runDKG(round); err != nil { con.logger.Error("Failed to runDKG", "error", err) @@ -739,25 +724,28 @@ func (con *Consensus) runCRS(round uint64) { } func (con *Consensus) initialRound( - startTime time.Time, round uint64, config *types.Config) { + startHeight uint64, round uint64, config *types.Config) { select { case <-con.ctx.Done(): return default: } - curDkgSet, err := con.nodeSetCache.GetDKGSet(round) - if err != nil { - con.logger.Error("Error getting DKG set", "round", round, "error", err) - curDkgSet = make(map[types.NodeID]struct{}) - } - // Initiate CRS routine. - if _, exist := curDkgSet[con.ID]; exist { - con.event.RegisterTime(startTime.Add(config.RoundInterval/2), - func(time.Time) { - go func() { - con.runCRS(round) - }() - }) + if round >= DKGDelayRound { + curDkgSet, err := con.nodeSetCache.GetDKGSet(round) + if err != nil { + con.logger.Error("Error getting DKG set", "round", round, "error", err) + curDkgSet = make(map[types.NodeID]struct{}) + } + // Initiate CRS routine. + if _, exist := curDkgSet[con.ID]; exist { + con.event.RegisterHeight( + startHeight+config.RoundLength/2, + func(uint64) { + go func() { + con.runCRS(round) + }() + }) + } } // checkCRS is a generator of checker to check if CRS for that round is // ready or not. @@ -774,76 +762,75 @@ func (con *Consensus) initialRound( } } // Initiate BA modules. - con.event.RegisterTime( - startTime.Add(config.RoundInterval/2+config.LambdaDKG), - func(time.Time) { - go func(nextRound uint64) { - if !checkWithCancel( - con.ctx, 500*time.Millisecond, checkCRS(nextRound)) { - con.logger.Debug("unable to prepare CRS for baMgr", - "round", nextRound) - return - } - // Notify BA for new round. - nextConfig := utils.GetConfigWithPanic( - con.gov, nextRound, con.logger) - nextCRS := utils.GetCRSWithPanic( - con.gov, nextRound, con.logger) - con.logger.Info("appendConfig for baMgr", "round", nextRound) - if err := con.baMgr.appendConfig( - nextRound, nextConfig, nextCRS); err != nil { - panic(err) - } - }(round + 1) - }) + con.event.RegisterHeight(startHeight+config.RoundLength/2, func(uint64) { + go func(nextRound uint64) { + if !checkWithCancel( + con.ctx, 500*time.Millisecond, checkCRS(nextRound)) { + con.logger.Debug("unable to prepare CRS for baMgr", + "round", nextRound) + return + } + // Notify BA for new round. + nextConfig := utils.GetConfigWithPanic( + con.gov, nextRound, con.logger) + nextCRS := utils.GetCRSWithPanic( + con.gov, nextRound, con.logger) + con.logger.Info("appendConfig for baMgr", "round", nextRound) + if err := con.baMgr.appendConfig( + nextRound, nextConfig, nextCRS); err != nil { + panic(err) + } + }(round + 1) + }) // Initiate DKG for this round. - con.event.RegisterTime(startTime.Add(config.RoundInterval/2+config.LambdaDKG), - func(time.Time) { - go func(nextRound uint64) { - // Normally, gov.CRS would return non-nil. Use this for in case of - // unexpected network fluctuation and ensure the robustness. - if !checkWithCancel( - con.ctx, 500*time.Millisecond, checkCRS(nextRound)) { - con.logger.Debug("unable to prepare CRS for DKG set", - "round", nextRound) - return - } - nextDkgSet, err := con.nodeSetCache.GetDKGSet(nextRound) - if err != nil { - con.logger.Error("Error getting DKG set", - "round", nextRound, - "error", err) - return - } - if _, exist := nextDkgSet[con.ID]; !exist { - return - } - con.logger.Info("Selected as DKG set", "round", nextRound) - con.cfgModule.registerDKG(nextRound, getDKGThreshold(config)) - con.event.RegisterTime( - startTime.Add(config.RoundInterval*2/3), - func(time.Time) { - func() { - con.dkgReady.L.Lock() - defer con.dkgReady.L.Unlock() - con.dkgRunning = 0 - }() - nextConfig := utils.GetConfigWithPanic( - con.gov, nextRound, con.logger) - con.runDKG(nextRound, nextConfig) - }) - }(round + 1) - }) + con.event.RegisterHeight(startHeight+config.RoundLength/2, func(uint64) { + go func(nextRound uint64) { + if nextRound < DKGDelayRound { + con.logger.Info("Skip runDKG for round", "round", nextRound) + return + } + // Normally, gov.CRS would return non-nil. Use this for in case of + // unexpected network fluctuation and ensure the robustness. + if !checkWithCancel( + con.ctx, 500*time.Millisecond, checkCRS(nextRound)) { + con.logger.Debug("unable to prepare CRS for DKG set", + "round", nextRound) + return + } + nextDkgSet, err := con.nodeSetCache.GetDKGSet(nextRound) + if err != nil { + con.logger.Error("Error getting DKG set", + "round", nextRound, + "error", err) + return + } + if _, exist := nextDkgSet[con.ID]; !exist { + return + } + con.logger.Info("Selected as DKG set", "round", nextRound) + con.cfgModule.registerDKG(nextRound, getDKGThreshold(config)) + con.event.RegisterHeight(startHeight+config.RoundLength*2/3, + func(uint64) { + func() { + con.dkgReady.L.Lock() + defer con.dkgReady.L.Unlock() + con.dkgRunning = 0 + }() + nextConfig := utils.GetConfigWithPanic( + con.gov, nextRound, con.logger) + con.runDKG(nextRound, nextConfig) + }) + }(round + 1) + }) // Prepare blockChain module for next round and next "initialRound" routine. - con.event.RegisterTime(startTime.Add(config.RoundInterval), - func(time.Time) { - // Change round. - // Get configuration for next round. - nextRound := round + 1 - nextConfig := utils.GetConfigWithPanic(con.gov, nextRound, con.logger) - con.initialRound( - startTime.Add(config.RoundInterval), nextRound, nextConfig) - }) + con.event.RegisterHeight(startHeight+config.RoundLength, func(uint64) { + // Change round. + // Get configuration for next round. + nextRound := round + 1 + nextConfig := utils.GetConfigWithPanic(con.gov, nextRound, con.logger) + con.initialRound( + startHeight+config.RoundLength, nextRound, nextConfig) + }) } // Stop the Consensus core. @@ -1194,7 +1181,7 @@ func (con *Consensus) deliverFinalizedBlocksWithoutLock() (err error) { "pending", con.bcModule.lastPendingBlock()) for _, b := range deliveredBlocks { con.deliverBlock(b) - go con.event.NotifyTime(b.Finalization.Timestamp) + go con.event.NotifyHeight(b.Finalization.Height) } return } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go index 563a321f5..f80e1b9d8 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go @@ -17,9 +17,21 @@ package core +import "github.com/dexon-foundation/dexon-consensus/core/utils" + // ConfigRoundShift refers to the difference between block's round and config // round derived from its state. // // For example, when round shift is 2, a block in round 0 should derive config // for round 2. const ConfigRoundShift uint64 = 2 + +// DKGDelayRound refers to the round that first DKG is run. +// +// For example, when delay round is 1, new DKG will run at round 1. Round 0 will +// have neither DKG nor CRS. +const DKGDelayRound uint64 = 1 + +func init() { + utils.SetDKGDelayRound(DKGDelayRound) +} diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go index 3879e36a5..b7e000ae6 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go @@ -143,6 +143,12 @@ type Governance interface { // ReportForkBlock reports a node for forking blocks. ReportForkBlock(block1, block2 *types.Block) + + // ResetDKG resets latest DKG data and propose new CRS. + ResetDKG(newSignedCRS []byte) + + // DKGResetCount returns the reset count for DKG of given round. + DKGResetCount(round uint64) uint64 } // Ticker define the capability to tick by interval. diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/round-based-config.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/round-based-config.go index 67779a63c..4f3a4cbf9 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/round-based-config.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/round-based-config.go @@ -18,35 +18,34 @@ package core import ( - "time" + "fmt" "github.com/dexon-foundation/dexon-consensus/core/types" ) type roundBasedConfig struct { - roundID uint64 - - // roundBeginTime is the beginning of round, as local time. - roundBeginTime time.Time - roundInterval time.Duration - - // roundEndTime is a cache for begin + interval. - roundEndTime time.Time + roundID uint64 + roundBeginHeight uint64 + roundEndHeight uint64 + roundInterval uint64 } func (config *roundBasedConfig) setupRoundBasedFields( roundID uint64, cfg *types.Config) { config.roundID = roundID - config.roundInterval = cfg.RoundInterval + config.roundInterval = cfg.RoundLength } -func (config *roundBasedConfig) setRoundBeginTime(begin time.Time) { - config.roundBeginTime = begin - config.roundEndTime = begin.Add(config.roundInterval) +func (config *roundBasedConfig) setRoundBeginHeight(begin uint64) { + config.roundBeginHeight = begin + config.roundEndHeight = begin + config.roundInterval } // isLastBlock checks if a block is the last block of this round. func (config *roundBasedConfig) isLastBlock(b *types.Block) bool { - return b.Position.Round == config.roundID && - b.Timestamp.After(config.roundEndTime) + if b.Position.Round != config.roundID { + panic(fmt.Errorf("attempt to compare by different round: %s, %d", + b, config.roundID)) + } + return b.Position.Height+1 == config.roundEndHeight } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/agreement.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/agreement.go index acc4f1c6c..9f1abcaf5 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/agreement.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/agreement.go @@ -160,8 +160,10 @@ func (a *agreement) processNewCRS(round uint64) { if round <= a.latestCRSRound { return } + prevRound := a.latestCRSRound + 1 + a.latestCRSRound = round // Verify all pending results. - for r := a.latestCRSRound + 1; r <= round; r++ { + for r := prevRound; r <= a.latestCRSRound; r++ { pendingsForRound := a.pendings[r] if pendingsForRound == nil { continue @@ -169,7 +171,9 @@ func (a *agreement) processNewCRS(round uint64) { delete(a.pendings, r) for _, res := range pendingsForRound { if err := core.VerifyAgreementResult(res, a.cache); err != nil { - a.logger.Error("invalid agreement result", "result", res) + a.logger.Error("invalid agreement result", + "result", res, + "error", err) continue } a.logger.Error("flush agreement result", "result", res) @@ -177,7 +181,6 @@ func (a *agreement) processNewCRS(round uint64) { break } } - a.latestCRSRound = round } // confirm notifies consensus the confirmation of a block in BA. diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/consensus.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/consensus.go index 618d90e8c..7ba659f27 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/consensus.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/consensus.go @@ -67,12 +67,13 @@ type Consensus struct { blocks types.BlocksByPosition agreementModule *agreement configs []*types.Config - roundBeginTimes []time.Time + roundBeginHeights []uint64 agreementRoundCut uint64 // lock for accessing all fields. lock sync.RWMutex duringBuffering bool + latestCRSRound uint64 moduleWaitGroup sync.WaitGroup agreementWaitGroup sync.WaitGroup pullChan chan common.Hash @@ -109,7 +110,7 @@ func NewConsensus( configs: []*types.Config{ utils.GetConfigWithPanic(gov, 0, logger), }, - roundBeginTimes: []time.Time{dMoment}, + roundBeginHeights: []uint64{0}, receiveChan: make(chan *types.Block, 1000), pullChan: make(chan common.Hash, 1000), randomnessResults: make(map[common.Hash]*types.BlockRandomnessResult), @@ -280,7 +281,8 @@ func (con *Consensus) GetSyncedConsensus() (*core.Consensus, error) { var err error con.syncedConsensus, err = core.NewConsensusFromSyncer( con.syncedLastBlock, - con.roundBeginTimes[con.syncedLastBlock.Position.Round], + con.roundBeginHeights[con.syncedLastBlock.Position.Round], + con.dMoment, con.app, con.gov, con.db, @@ -336,7 +338,6 @@ func (con *Consensus) buildEmptyBlock(b *types.Block, parent *types.Block) { b.Witness.Height = parent.Witness.Height b.Witness.Data = make([]byte, len(parent.Witness.Data)) copy(b.Witness.Data, parent.Witness.Data) - b.Acks = common.NewSortedHashes(common.Hashes{parent.Hash}) } // setupConfigs is called by SyncBlocks with blocks from compaction chain. In @@ -368,9 +369,9 @@ func (con *Consensus) setupConfigsUntilRound(round uint64) { for r := uint64(len(con.configs)); r <= round; r++ { cfg := utils.GetConfigWithPanic(con.gov, r, con.logger) con.configs = append(con.configs, cfg) - con.roundBeginTimes = append( - con.roundBeginTimes, - con.roundBeginTimes[r-1].Add(con.configs[r-1].RoundInterval)) + con.roundBeginHeights = append( + con.roundBeginHeights, + con.roundBeginHeights[r-1]+con.configs[r-1].RoundLength) } } @@ -416,6 +417,11 @@ func (con *Consensus) cacheRandomnessResult(r *types.BlockRandomnessResult) { if len(con.blocks) > 0 && r.Position.Older(con.blocks[0].Position) { return true } + if r.Position.Round > con.latestCRSRound { + // We can't process randomness from rounds that its CRS is still + // unknown. + return true + } _, exists := con.randomnessResults[r.BlockHash] return exists }() { @@ -453,41 +459,22 @@ func (con *Consensus) startNetwork() { con.moduleWaitGroup.Add(1) go func() { defer con.moduleWaitGroup.Done() - Loop: + loop: for { select { case val := <-con.network.ReceiveChan(): - var pos types.Position switch v := val.(type) { case *types.Block: - pos = v.Position case *types.AgreementResult: - pos = v.Position case *types.BlockRandomnessResult: con.cacheRandomnessResult(v) - continue Loop + continue loop default: - continue Loop - } - if func() bool { - con.lock.RLock() - defer con.lock.RUnlock() - if pos.ChainID > 0 { - // This error might be easily encountered when the - // "latest" parameter of SyncBlocks is turned on too - // early. - con.logger.Error( - "Unknown chainID message received (syncer)", - "position", pos, - ) - return false - } - return true - }() { - con.agreementModule.inputChan <- val + continue loop } + con.agreementModule.inputChan <- val case <-con.ctx.Done(): - return + break loop } } }() @@ -505,6 +492,11 @@ func (con *Consensus) startCRSMonitor() { } con.logger.Debug("CRS is ready", "round", round) lastNotifiedRound = round + func() { + con.lock.Lock() + defer con.lock.Unlock() + con.latestCRSRound = round + }() for func() bool { con.lock.RLock() defer con.lock.RUnlock() diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/ticker.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/ticker.go index ffd5ab45d..636fb8c49 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/ticker.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/ticker.go @@ -18,6 +18,9 @@ package core import ( + "context" + "fmt" + "sync" "time" "github.com/dexon-foundation/dexon-consensus/core/utils" @@ -36,32 +39,65 @@ const ( // defaultTicker is a wrapper to implement ticker interface based on // time.Ticker. type defaultTicker struct { - ticker *time.Ticker - duration time.Duration + ticker *time.Ticker + tickerChan chan time.Time + duration time.Duration + ctx context.Context + ctxCancel context.CancelFunc + waitGroup sync.WaitGroup } // newDefaultTicker constructs an defaultTicker instance by giving an interval. func newDefaultTicker(lambda time.Duration) *defaultTicker { - return &defaultTicker{ - ticker: time.NewTicker(lambda), - duration: lambda, - } + ticker := &defaultTicker{duration: lambda} + ticker.init() + return ticker } // Tick implements Tick method of ticker interface. func (t *defaultTicker) Tick() <-chan time.Time { - return t.ticker.C + return t.tickerChan } // Stop implements Stop method of ticker interface. func (t *defaultTicker) Stop() { t.ticker.Stop() + t.ctxCancel() + t.waitGroup.Wait() + t.ctx = nil + t.ctxCancel = nil + close(t.tickerChan) + t.tickerChan = nil } // Restart implements Stop method of ticker interface. func (t *defaultTicker) Restart() { - t.ticker.Stop() + t.Stop() + t.init() +} + +func (t *defaultTicker) init() { t.ticker = time.NewTicker(t.duration) + t.tickerChan = make(chan time.Time) + t.ctx, t.ctxCancel = context.WithCancel(context.Background()) + t.waitGroup.Add(1) + go t.monitor() +} + +func (t *defaultTicker) monitor() { + defer t.waitGroup.Done() +loop: + for { + select { + case <-t.ctx.Done(): + break loop + case v := <-t.ticker.C: + select { + case t.tickerChan <- v: + default: + } + } + } } // newTicker is a helper to setup a ticker by giving an Governance. If @@ -82,8 +118,8 @@ func newTicker(gov Governance, round uint64, tickerType TickerType) (t Ticker) { duration = utils.GetConfigWithPanic(gov, round, nil).LambdaBA case TickerDKG: duration = utils.GetConfigWithPanic(gov, round, nil).LambdaDKG - case TickerCRS: - duration = utils.GetConfigWithPanic(gov, round, nil).RoundInterval / 2 + default: + panic(fmt.Errorf("unknown ticker type: %d", tickerType)) } t = newDefaultTicker(duration) } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go index a2b697ce0..2b23e96e3 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go @@ -23,7 +23,6 @@ import ( "bytes" "fmt" "io" - "sort" "time" "github.com/dexon-foundation/dexon/rlp" @@ -125,17 +124,16 @@ type Witness struct { // Block represents a single event broadcasted on the network. type Block struct { - ProposerID NodeID `json:"proposer_id"` - ParentHash common.Hash `json:"parent_hash"` - Hash common.Hash `json:"hash"` - Position Position `json:"position"` - Timestamp time.Time `json:"timestamp"` - Acks common.SortedHashes `json:"acks"` - Payload []byte `json:"payload"` - PayloadHash common.Hash `json:"payload_hash"` - Witness Witness `json:"witness"` - Finalization FinalizationResult `json:"finalization"` - Signature crypto.Signature `json:"signature"` + ProposerID NodeID `json:"proposer_id"` + ParentHash common.Hash `json:"parent_hash"` + Hash common.Hash `json:"hash"` + Position Position `json:"position"` + Timestamp time.Time `json:"timestamp"` + Payload []byte `json:"payload"` + PayloadHash common.Hash `json:"payload_hash"` + Witness Witness `json:"witness"` + Finalization FinalizationResult `json:"finalization"` + Signature crypto.Signature `json:"signature"` CRSSignature crypto.Signature `json:"crs_signature"` } @@ -146,7 +144,6 @@ type rlpBlock struct { Hash common.Hash Position Position Timestamp *rlpTimestamp - Acks common.SortedHashes Payload []byte PayloadHash common.Hash Witness *Witness @@ -164,7 +161,6 @@ func (b *Block) EncodeRLP(w io.Writer) error { Hash: b.Hash, Position: b.Position, Timestamp: &rlpTimestamp{b.Timestamp}, - Acks: b.Acks, Payload: b.Payload, PayloadHash: b.PayloadHash, Witness: &b.Witness, @@ -185,7 +181,6 @@ func (b *Block) DecodeRLP(s *rlp.Stream) error { Hash: dec.Hash, Position: dec.Position, Timestamp: dec.Timestamp.Time, - Acks: dec.Acks, Payload: dec.Payload, PayloadHash: dec.PayloadHash, Witness: *dec.Witness, @@ -208,7 +203,6 @@ func (b *Block) Clone() (bcopy *Block) { bcopy.ParentHash = b.ParentHash bcopy.Hash = b.Hash bcopy.Position.Round = b.Position.Round - bcopy.Position.ChainID = b.Position.ChainID bcopy.Position.Height = b.Position.Height bcopy.Signature = b.Signature.Clone() bcopy.CRSSignature = b.CRSSignature.Clone() @@ -217,8 +211,6 @@ func (b *Block) Clone() (bcopy *Block) { bcopy.Witness.Data = make([]byte, len(b.Witness.Data)) copy(bcopy.Witness.Data, b.Witness.Data) bcopy.Timestamp = b.Timestamp - bcopy.Acks = make(common.SortedHashes, len(b.Acks)) - copy(bcopy.Acks, b.Acks) bcopy.Payload = make([]byte, len(b.Payload)) copy(bcopy.Payload, b.Payload) bcopy.PayloadHash = b.PayloadHash @@ -240,14 +232,6 @@ func (b *Block) IsEmpty() bool { return b.ProposerID.Hash == common.Hash{} } -// IsAcking checks if a block acking another by it's hash. -func (b *Block) IsAcking(hash common.Hash) bool { - idx := sort.Search(len(b.Acks), func(i int) bool { - return bytes.Compare(b.Acks[i][:], hash[:]) >= 0 - }) - return !(idx == len(b.Acks) || b.Acks[idx] != hash) -} - // ByHash is the helper type for sorting slice of blocks by hash. type ByHash []*Block diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/config.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/config.go index c9d31f8c4..eda09f06e 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/config.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/config.go @@ -19,52 +19,38 @@ package types import ( "encoding/binary" - "math" "time" ) // Config stands for Current Configuration Parameters. type Config struct { - // Network related. - NumChains uint32 - // Lambda related. LambdaBA time.Duration LambdaDKG time.Duration - // Total ordering related. - K int - PhiRatio float32 - // Set related. NotarySetSize uint32 DKGSetSize uint32 // Time related. - RoundInterval time.Duration + RoundLength uint64 MinBlockInterval time.Duration } // Clone return a copied configuration. func (c *Config) Clone() *Config { return &Config{ - NumChains: c.NumChains, LambdaBA: c.LambdaBA, LambdaDKG: c.LambdaDKG, - K: c.K, - PhiRatio: c.PhiRatio, NotarySetSize: c.NotarySetSize, DKGSetSize: c.DKGSetSize, - RoundInterval: c.RoundInterval, + RoundLength: c.RoundLength, MinBlockInterval: c.MinBlockInterval, } } // Bytes returns []byte representation of Config. func (c *Config) Bytes() []byte { - binaryNumChains := make([]byte, 4) - binary.LittleEndian.PutUint32(binaryNumChains, c.NumChains) - binaryLambdaBA := make([]byte, 8) binary.LittleEndian.PutUint64( binaryLambdaBA, uint64(c.LambdaBA.Nanoseconds())) @@ -72,32 +58,23 @@ func (c *Config) Bytes() []byte { binary.LittleEndian.PutUint64( binaryLambdaDKG, uint64(c.LambdaDKG.Nanoseconds())) - binaryK := make([]byte, 4) - binary.LittleEndian.PutUint32(binaryK, uint32(c.K)) - binaryPhiRatio := make([]byte, 4) - binary.LittleEndian.PutUint32(binaryPhiRatio, math.Float32bits(c.PhiRatio)) - binaryNotarySetSize := make([]byte, 4) binary.LittleEndian.PutUint32(binaryNotarySetSize, c.NotarySetSize) binaryDKGSetSize := make([]byte, 4) binary.LittleEndian.PutUint32(binaryDKGSetSize, c.DKGSetSize) - binaryRoundInterval := make([]byte, 8) - binary.LittleEndian.PutUint64(binaryRoundInterval, - uint64(c.RoundInterval.Nanoseconds())) + binaryRoundLength := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryRoundLength, c.RoundLength) binaryMinBlockInterval := make([]byte, 8) binary.LittleEndian.PutUint64(binaryMinBlockInterval, uint64(c.MinBlockInterval.Nanoseconds())) enc := make([]byte, 0, 40) - enc = append(enc, binaryNumChains...) enc = append(enc, binaryLambdaBA...) enc = append(enc, binaryLambdaDKG...) - enc = append(enc, binaryK...) - enc = append(enc, binaryPhiRatio...) enc = append(enc, binaryNotarySetSize...) enc = append(enc, binaryDKGSetSize...) - enc = append(enc, binaryRoundInterval...) + enc = append(enc, binaryRoundLength...) enc = append(enc, binaryMinBlockInterval...) return enc } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/position.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/position.go index 902a55fec..81d23c266 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/position.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/position.go @@ -23,33 +23,22 @@ import ( // Position describes the position in the block lattice of an entity. type Position struct { - ChainID uint32 `json:"chain_id"` - Round uint64 `json:"round"` - Height uint64 `json:"height"` + Round uint64 `json:"round"` + Height uint64 `json:"height"` } func (pos Position) String() string { - return fmt.Sprintf("Position{Round:%d Chain:%d Height:%d}", - pos.Round, pos.ChainID, pos.Height) + return fmt.Sprintf("Position{Round:%d Height:%d}", pos.Round, pos.Height) } -// Equal checks if two positions are equal, it panics when their chainIDs -// are different. +// Equal checks if two positions are equal. func (pos Position) Equal(other Position) bool { - if pos.ChainID != other.ChainID { - panic(fmt.Errorf("unexpected chainID %d, should be %d", - other.ChainID, pos.ChainID)) - } return pos.Round == other.Round && pos.Height == other.Height } // Newer checks if one block is newer than another one on the same chain. // If two blocks on different chain compared by this function, it would panic. func (pos Position) Newer(other Position) bool { - if pos.ChainID != other.ChainID { - panic(fmt.Errorf("unexpected chainID %d, should be %d", - other.ChainID, pos.ChainID)) - } return pos.Round > other.Round || (pos.Round == other.Round && pos.Height > other.Height) } @@ -57,10 +46,6 @@ func (pos Position) Newer(other Position) bool { // Older checks if one block is older than another one on the same chain. // If two blocks on different chain compared by this function, it would panic. func (pos Position) Older(other Position) bool { - if pos.ChainID != other.ChainID { - panic(fmt.Errorf("unexpected chainID %d, should be %d", - other.ChainID, pos.ChainID)) - } return pos.Round < other.Round || (pos.Round == other.Round && pos.Height < other.Height) } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/vote.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/vote.go index 6481eb46d..c4a625edd 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/vote.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/vote.go @@ -66,7 +66,7 @@ type Vote struct { } func (v *Vote) String() string { - return fmt.Sprintf("Vote{BP:%s %s Period:%d Type:%d Hash:%s}", + return fmt.Sprintf("Vote{VP:%s %s Period:%d Type:%d Hash:%s}", v.ProposerID.String()[:6], v.Position, v.Period, v.Type, v.BlockHash.String()[:6]) } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go index 14780e73b..46aa77a6b 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go @@ -21,7 +21,6 @@ import ( "context" "errors" "fmt" - "math/rand" "os" "sort" "time" @@ -130,11 +129,6 @@ func removeFromSortedUint32Slice(xs []uint32, x uint32) []uint32 { return append(xs[:indexToRemove], xs[indexToRemove+1:]...) } -// pickBiasedTime returns a biased time based on a given range. -func pickBiasedTime(base time.Time, biasedRange time.Duration) time.Time { - return base.Add(time.Duration(rand.Intn(int(biasedRange)))) -} - // HashConfigurationBlock returns the hash value of configuration block. func HashConfigurationBlock( notarySet map[types.NodeID]struct{}, @@ -165,8 +159,7 @@ func HashConfigurationBlock( // instance. func VerifyAgreementResult( res *types.AgreementResult, cache *utils.NodeSetCache) error { - notarySet, err := cache.GetNotarySet( - res.Position.Round, res.Position.ChainID) + notarySet, err := cache.GetNotarySet(res.Position.Round) if err != nil { return err } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/crypto.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/crypto.go index 43bbde13d..f5343ca38 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/crypto.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/crypto.go @@ -37,12 +37,6 @@ func hashWitness(witness *types.Witness) (common.Hash, error) { // HashBlock generates hash of a types.Block. func HashBlock(block *types.Block) (common.Hash, error) { hashPosition := hashPosition(block.Position) - // Handling Block.Acks. - binaryAcks := make([][]byte, len(block.Acks)) - for idx, ack := range block.Acks { - binaryAcks[idx] = ack[:] - } - hashAcks := crypto.Keccak256Hash(binaryAcks...) binaryTimestamp, err := block.Timestamp.UTC().MarshalBinary() if err != nil { return common.Hash{}, err @@ -56,7 +50,6 @@ func HashBlock(block *types.Block) (common.Hash, error) { block.ProposerID.Hash[:], block.ParentHash[:], hashPosition[:], - hashAcks[:], binaryTimestamp[:], block.PayloadHash[:], binaryWitness[:]) @@ -140,9 +133,6 @@ func VerifyCRSSignature(block *types.Block, crs common.Hash) ( } func hashPosition(position types.Position) common.Hash { - binaryChainID := make([]byte, 4) - binary.LittleEndian.PutUint32(binaryChainID, position.ChainID) - binaryRound := make([]byte, 8) binary.LittleEndian.PutUint64(binaryRound, position.Round) @@ -150,7 +140,6 @@ func hashPosition(position types.Position) common.Hash { binary.LittleEndian.PutUint64(binaryHeight, position.Height) return crypto.Keccak256Hash( - binaryChainID, binaryRound, binaryHeight, ) diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/nodeset-cache.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/nodeset-cache.go index 83541283b..6249665ac 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/nodeset-cache.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/nodeset-cache.go @@ -19,7 +19,6 @@ package utils import ( "errors" - "fmt" "sync" "github.com/dexon-foundation/dexon-consensus/common" @@ -34,8 +33,6 @@ var ( ErrCRSNotReady = errors.New("crs is not ready") // ErrConfigurationNotReady means we go nil configuration. ErrConfigurationNotReady = errors.New("configuration is not ready") - // ErrInvalidChainID means the chain ID is unexpected. - ErrInvalidChainID = errors.New("invalid chain id") ) type sets struct { @@ -125,12 +122,8 @@ func (cache *NodeSetCache) GetNodeSet(round uint64) (*types.NodeSet, error) { } // GetNotarySet returns of notary set of this round. -// TODO(mission): remove chainID parameter. func (cache *NodeSetCache) GetNotarySet( - round uint64, chainID uint32) (map[types.NodeID]struct{}, error) { - if chainID != 0 { - panic(fmt.Errorf("non-zero chainID found: %d", chainID)) - } + round uint64) (map[types.NodeID]struct{}, error) { IDs, err := cache.getOrUpdate(round) if err != nil { return nil, err @@ -196,12 +189,9 @@ func (cache *NodeSetCache) getOrUpdate(round uint64) (nIDs *sets, err error) { // // This cache would maintain 10 rounds before the updated round and purge // rounds not in this range. -func (cache *NodeSetCache) update( - round uint64) (nIDs *sets, err error) { - +func (cache *NodeSetCache) update(round uint64) (nIDs *sets, err error) { cache.lock.Lock() defer cache.lock.Unlock() - // Get information for the requested round. keySet := cache.nsIntf.NodeSet(round) if keySet == nil { @@ -232,14 +222,15 @@ func (cache *NodeSetCache) update( err = ErrConfigurationNotReady return } - nodesPerChain := cfg.RoundInterval / cfg.MinBlockInterval nIDs = &sets{ - crs: crs, - nodeSet: nodeSet, - notarySet: make(map[types.NodeID]struct{}), - dkgSet: nodeSet.GetSubSet( - int(cfg.DKGSetSize), types.NewDKGSetTarget(crs)), - leaderNode: make(map[uint64]types.NodeID, nodesPerChain), + crs: crs, + nodeSet: nodeSet, + notarySet: make(map[types.NodeID]struct{}), + leaderNode: make(map[uint64]types.NodeID, cfg.RoundLength), + } + if round >= dkgDelayRound { + nIDs.dkgSet = nodeSet.GetSubSet( + int(cfg.DKGSetSize), types.NewDKGSetTarget(crs)) } nIDs.notarySet = nodeSet.GetSubSet( int(cfg.NotarySetSize), types.NewNotarySetTarget(crs)) @@ -261,12 +252,9 @@ func (cache *NodeSetCache) update( return } -func (cache *NodeSetCache) get( - round uint64) (nIDs *sets, exists bool) { - +func (cache *NodeSetCache) get(round uint64) (nIDs *sets, exists bool) { cache.lock.RLock() defer cache.lock.RUnlock() - nIDs, exists = cache.rounds[round] return } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/utils.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/utils.go index 8486d2854..203f57fc2 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/utils.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/utils.go @@ -26,6 +26,13 @@ import ( typesDKG "github.com/dexon-foundation/dexon-consensus/core/types/dkg" ) +var dkgDelayRound uint64 + +// SetDKGDelayRound sets the variable. +func SetDKGDelayRound(delay uint64) { + dkgDelayRound = delay +} + type configAccessor interface { Configuration(round uint64) *types.Config } diff --git a/vendor/vendor.json b/vendor/vendor.json index f424fa691..0955ef4dd 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -139,18 +139,18 @@ "versionExact": "dev" }, { - "checksumSHA1": "pnv6DaNi8uUdtYFqNdLjgpeCp6A=", + "checksumSHA1": "8EuKVkP1v/w5fRuuvUaXX5k/F+I=", "path": "github.com/dexon-foundation/dexon-consensus/common", - "revision": "2cf18fd299ea0fc270b213343314cab652cac271", - "revisionTime": "2019-02-18T10:44:35Z", + "revision": "d4b4c8a05e94f66c85e7b4238ae5947b26f13c40", + "revisionTime": "2019-03-04T10:30:03Z", "version": "single-chain", "versionExact": "single-chain" }, { - "checksumSHA1": "VI5+nQ9e4RiSE4JBOc92UU65eVY=", + "checksumSHA1": "RD3L08SnpZty2qH5mNERxYxB7gg=", "path": "github.com/dexon-foundation/dexon-consensus/core", - "revision": "2cf18fd299ea0fc270b213343314cab652cac271", - "revisionTime": "2019-02-18T10:44:35Z", + "revision": "d4b4c8a05e94f66c85e7b4238ae5947b26f13c40", + "revisionTime": "2019-03-04T10:30:03Z", "version": "single-chain", "versionExact": "single-chain" }, @@ -165,64 +165,64 @@ { "checksumSHA1": "tQSbYCu5P00lUhKsx3IbBZCuSLY=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto", - "revision": "2cf18fd299ea0fc270b213343314cab652cac271", - "revisionTime": "2019-02-18T10:44:35Z", + "revision": "d4b4c8a05e94f66c85e7b4238ae5947b26f13c40", + "revisionTime": "2019-03-04T10:30:03Z", "version": "single-chain", "versionExact": "single-chain" }, { "checksumSHA1": "Nlv7pi1DIBftY+r6CFP8LBIQA3U=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg", - "revision": "2cf18fd299ea0fc270b213343314cab652cac271", - "revisionTime": "2019-02-18T10:44:35Z", + "revision": "d4b4c8a05e94f66c85e7b4238ae5947b26f13c40", + "revisionTime": "2019-03-04T10:30:03Z", "version": "single-chain", "versionExact": "single-chain" }, { "checksumSHA1": "BhLKK8RveoLaeXc9UyUKMwQqchU=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto/ecdsa", - "revision": "2cf18fd299ea0fc270b213343314cab652cac271", - "revisionTime": "2019-02-18T10:44:35Z", + "revision": "d4b4c8a05e94f66c85e7b4238ae5947b26f13c40", + "revisionTime": "2019-03-04T10:30:03Z", "version": "single-chain", "versionExact": "single-chain" }, { "checksumSHA1": "zpuCdMT8MGsy4pLgHKpg/Wd4izU=", "path": "github.com/dexon-foundation/dexon-consensus/core/db", - "revision": "2cf18fd299ea0fc270b213343314cab652cac271", - "revisionTime": "2019-02-18T10:44:35Z", + "revision": "d4b4c8a05e94f66c85e7b4238ae5947b26f13c40", + "revisionTime": "2019-03-04T10:30:03Z", "version": "single-chain", "versionExact": "single-chain" }, { - "checksumSHA1": "KYpliqwnJejH8V/GqygKSiQETbo=", + "checksumSHA1": "T9TNx0oUpaRdlbCuy7AvkK1eQ18=", "path": "github.com/dexon-foundation/dexon-consensus/core/syncer", - "revision": "2cf18fd299ea0fc270b213343314cab652cac271", - "revisionTime": "2019-02-18T10:44:35Z", + "revision": "d4b4c8a05e94f66c85e7b4238ae5947b26f13c40", + "revisionTime": "2019-03-04T10:30:03Z", "version": "single-chain", "versionExact": "single-chain" }, { - "checksumSHA1": "g9eEP7SxpQf10C3wCsNN/Hn9XK0=", + "checksumSHA1": "id8imcgp3SqYhIx0k3Chd0VZrUQ=", "path": "github.com/dexon-foundation/dexon-consensus/core/types", - "revision": "2cf18fd299ea0fc270b213343314cab652cac271", - "revisionTime": "2019-02-18T10:44:35Z", + "revision": "d4b4c8a05e94f66c85e7b4238ae5947b26f13c40", + "revisionTime": "2019-03-04T10:30:03Z", "version": "single-chain", "versionExact": "single-chain" }, { "checksumSHA1": "s28gYj+iji8oT7N7Su6HIFHMuwI=", "path": "github.com/dexon-foundation/dexon-consensus/core/types/dkg", - "revision": "2cf18fd299ea0fc270b213343314cab652cac271", - "revisionTime": "2019-02-18T10:44:35Z", + "revision": "d4b4c8a05e94f66c85e7b4238ae5947b26f13c40", + "revisionTime": "2019-03-04T10:30:03Z", "version": "single-chain", "versionExact": "single-chain" }, { - "checksumSHA1": "1z0CIfS1QRV9xoA9wrTyVUMmXjc=", + "checksumSHA1": "C8Q8sfOSs+FPw/5sPwAR04QFc3U=", "path": "github.com/dexon-foundation/dexon-consensus/core/utils", - "revision": "2cf18fd299ea0fc270b213343314cab652cac271", - "revisionTime": "2019-02-18T10:44:35Z", + "revision": "d4b4c8a05e94f66c85e7b4238ae5947b26f13c40", + "revisionTime": "2019-03-04T10:30:03Z", "version": "single-chain", "versionExact": "single-chain" }, -- cgit v1.2.3