diff options
author | Jimmy Hu <jimmy.hu@dexon.org> | 2018-08-20 14:03:18 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-20 14:03:18 +0800 |
commit | 1e71e263e063adbe7e44d48818f9c74924a2945d (patch) | |
tree | b874d8d4d6cc1d0aa6f106f276f83706361f0878 /core | |
parent | d9ba7986a975615fb10790cfd448c48c89c1a7b3 (diff) | |
download | dexon-consensus-1e71e263e063adbe7e44d48818f9c74924a2945d.tar dexon-consensus-1e71e263e063adbe7e44d48818f9c74924a2945d.tar.gz dexon-consensus-1e71e263e063adbe7e44d48818f9c74924a2945d.tar.bz2 dexon-consensus-1e71e263e063adbe7e44d48818f9c74924a2945d.tar.lz dexon-consensus-1e71e263e063adbe7e44d48818f9c74924a2945d.tar.xz dexon-consensus-1e71e263e063adbe7e44d48818f9c74924a2945d.tar.zst dexon-consensus-1e71e263e063adbe7e44d48818f9c74924a2945d.zip |
core: NotaryAck interfaces. (#67)
Diffstat (limited to 'core')
-rw-r--r-- | core/application.go | 4 | ||||
-rw-r--r-- | core/compaction-chain.go | 40 | ||||
-rw-r--r-- | core/consensus.go | 28 | ||||
-rw-r--r-- | core/crypto.go | 2 | ||||
-rw-r--r-- | core/crypto_test.go | 21 | ||||
-rw-r--r-- | core/nonblocking-application.go | 5 | ||||
-rw-r--r-- | core/nonblocking-application_test.go | 8 | ||||
-rw-r--r-- | core/test/app.go | 5 | ||||
-rw-r--r-- | core/types/block.go | 43 | ||||
-rw-r--r-- | core/types/notary.go | 43 |
10 files changed, 132 insertions, 67 deletions
diff --git a/core/application.go b/core/application.go index 5bd325c..e39e238 100644 --- a/core/application.go +++ b/core/application.go @@ -21,6 +21,7 @@ import ( "time" "github.com/dexon-foundation/dexon-consensus-core/common" + "github.com/dexon-foundation/dexon-consensus-core/core/types" ) // Application describes the application interface that interacts with DEXON @@ -34,4 +35,7 @@ type Application interface { // DeliverBlock is called when a block is add to the compaction chain. DeliverBlock(blockHash common.Hash, timestamp time.Time) + + // NotaryAck is called when a notary ack is created. + NotaryAck(notaryAck types.NotaryAck) } diff --git a/core/compaction-chain.go b/core/compaction-chain.go index f2b4d1b..664b692 100644 --- a/core/compaction-chain.go +++ b/core/compaction-chain.go @@ -20,24 +20,37 @@ package core import ( + "fmt" "sync" - //"github.com/dexon-foundation/dexon-consensus-core/common" "github.com/dexon-foundation/dexon-consensus-core/core/types" "github.com/dexon-foundation/dexon-consensus-core/crypto" ) +// Errors for compaction chain. +var ( + ErrIncorrectNotaryAck = fmt.Errorf( + "compaction chain notary of block is incorrect") +) + type compactionChain struct { - prevBlock *types.Block - lock sync.RWMutex + prevBlock *types.Block + lock sync.RWMutex + latestNotaryAcks map[types.ValidatorID]types.NotaryAck } func newCompactionChain() *compactionChain { return &compactionChain{} } -func (cc *compactionChain) prepareBlock( - block *types.Block, prvKey crypto.PrivateKey) (err error) { +func (cc *compactionChain) sanityCheck(notaryAck types.NotaryAck) bool { + return true +} + +func (cc *compactionChain) processBlock(block *types.Block) (err error) { + cc.lock.Lock() + defer cc.lock.Unlock() + cc.prevBlock = block /* prevBlock := cc.lastBlock() if prevBlock != nil { @@ -51,8 +64,18 @@ func (cc *compactionChain) prepareBlock( */ return } +func (cc *compactionChain) prepareNotaryAck(prvKey crypto.PrivateKey) ( + notaryAck types.NotaryAck, err error) { + notaryAck.NotaryBlockHash = cc.lastBlock().Hash + return +} -func (cc *compactionChain) processBlock(block *types.Block) (err error) { +func (cc *compactionChain) processNotaryAck(notaryAck types.NotaryAck) ( + err error) { + if !cc.sanityCheck(notaryAck) { + err = ErrIncorrectNotaryAck + return + } /* prevBlock := cc.lastBlock() if prevBlock == nil { @@ -69,9 +92,14 @@ func (cc *compactionChain) processBlock(block *types.Block) (err error) { defer cc.lock.Unlock() cc.prevBlock = block */ + cc.latestNotaryAcks[notaryAck.ProposerID] = notaryAck return } +func (cc *compactionChain) notaryAcks() map[types.ValidatorID]types.NotaryAck { + return cc.latestNotaryAcks +} + func (cc *compactionChain) lastBlock() *types.Block { cc.lock.RLock() defer cc.lock.RUnlock() diff --git a/core/consensus.go b/core/consensus.go index 3e8f87d..0b4ea62 100644 --- a/core/consensus.go +++ b/core/consensus.go @@ -48,8 +48,6 @@ var ( "hash of block is incorrect") ErrIncorrectSignature = fmt.Errorf( "signature of block is incorrect") - ErrIncorrectNotaryAck = fmt.Errorf( - "compaction chain notary of block is incorrect") ErrGenesisBlockNotEmpty = fmt.Errorf( "genesis block should be empty") ) @@ -204,6 +202,12 @@ func (con *Consensus) ProcessBlock(blockConv types.BlockConverter) (err error) { } con.app.DeliverBlock(b.Hash, b.Notary.Timestamp) } + var notaryAck types.NotaryAck + notaryAck, err = con.ccModule.prepareNotaryAck(con.prvKey) + if err != nil { + return + } + con.app.NotaryAck(notaryAck) } return } @@ -237,10 +241,6 @@ func (con *Consensus) PrepareBlock(blockConv types.BlockConverter, if err != nil { return } - err = con.ccModule.prepareBlock(b, con.prvKey) - if err != nil { - return - } blockConv.SetBlock(b) return } @@ -275,3 +275,19 @@ func (con *Consensus) PrepareGenesisBlock(blockConv types.BlockConverter, blockConv.SetBlock(b) return } + +// ProcessNotaryAck is the entry point to submit one notary ack. +func (con *Consensus) ProcessNotaryAck(notaryAck types.NotaryAck) (err error) { + err = con.ccModule.processNotaryAck(notaryAck) + return +} + +// NotaryAcks returns the latest NotaryAck received from all other validators. +func (con *Consensus) NotaryAcks() ( + notaryAcks map[types.ValidatorID]types.NotaryAck) { + notaryAcks = make(map[types.ValidatorID]types.NotaryAck) + for k, v := range con.ccModule.notaryAcks() { + notaryAcks[k] = v + } + return +} diff --git a/core/crypto.go b/core/crypto.go index 664607b..0de73af 100644 --- a/core/crypto.go +++ b/core/crypto.go @@ -34,7 +34,7 @@ func hashNotary(block *types.Block) (common.Hash, error) { binaryHeight := make([]byte, 8) binary.LittleEndian.PutUint64(binaryHeight, block.Notary.Height) hash := crypto.Keccak256Hash( - block.NotaryParentHash[:], + block.Notary.ParentHash[:], binaryTime, binaryHeight) return hash, nil diff --git a/core/crypto_test.go b/core/crypto_test.go index 94b500e..3aa1674 100644 --- a/core/crypto_test.go +++ b/core/crypto_test.go @@ -69,19 +69,14 @@ func (s *CryptoTestSuite) prepareBlock(prevBlock *types.Block) *types.Block { s.Require().NotEqual(prevBlock.Hash, common.Hash{}) acks[parentHash] = struct{}{} return &types.Block{ - ParentHash: prevBlock.Hash, - Acks: acks, - Timestamps: timestamps, - NotaryParentHash: parentHash, - Height: prevBlock.Height + 1, - /* - NotaryAck: types.NotaryAck{ - NotaryBlockHash: prevBlock.Hash, - }, - */ + ParentHash: prevBlock.Hash, + Acks: acks, + Timestamps: timestamps, + Height: prevBlock.Height + 1, Notary: types.Notary{ - Timestamp: time.Now(), - Height: prevBlock.Notary.Height + 1, + ParentHash: parentHash, + Timestamp: time.Now(), + Height: prevBlock.Notary.Height + 1, }, } } @@ -104,7 +99,7 @@ func (s *CryptoTestSuite) generateCompactionChain( blocks[idx] = block var err error if idx > 0 { - block.NotaryParentHash, err = hashNotary(blocks[idx-1]) + block.Notary.ParentHash, err = hashNotary(blocks[idx-1]) s.Require().Nil(err) /* block.NotaryAck.NotarySignature, err = diff --git a/core/nonblocking-application.go b/core/nonblocking-application.go index 4c06ab9..a04d7d2 100644 --- a/core/nonblocking-application.go +++ b/core/nonblocking-application.go @@ -23,6 +23,7 @@ import ( "time" "github.com/dexon-foundation/dexon-consensus-core/common" + "github.com/dexon-foundation/dexon-consensus-core/core/types" ) type stronglyAckedEvent struct { @@ -124,3 +125,7 @@ func (app *nonBlockingApplication) DeliverBlock( blockHash common.Hash, timestamp time.Time) { app.addEvent(deliverBlockEvent{blockHash, timestamp}) } + +// NotaryAck is called when a notary ack is created. +func (app *nonBlockingApplication) NotaryAck(notaryAck types.NotaryAck) { +} diff --git a/core/nonblocking-application_test.go b/core/nonblocking-application_test.go index 070eae3..0f7d7f2 100644 --- a/core/nonblocking-application_test.go +++ b/core/nonblocking-application_test.go @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/suite" "github.com/dexon-foundation/dexon-consensus-core/common" + "github.com/dexon-foundation/dexon-consensus-core/core/types" ) type slowApp struct { @@ -31,6 +32,7 @@ type slowApp struct { stronglyAcked map[common.Hash]struct{} totalOrderingDeliver map[common.Hash]struct{} deliverBlock map[common.Hash]struct{} + notaryAck map[common.Hash]struct{} } func newSlowApp(sleep time.Duration) *slowApp { @@ -39,6 +41,7 @@ func newSlowApp(sleep time.Duration) *slowApp { stronglyAcked: make(map[common.Hash]struct{}), totalOrderingDeliver: make(map[common.Hash]struct{}), deliverBlock: make(map[common.Hash]struct{}), + notaryAck: make(map[common.Hash]struct{}), } } @@ -59,6 +62,11 @@ func (app *slowApp) DeliverBlock(blockHash common.Hash, timestamp time.Time) { app.deliverBlock[blockHash] = struct{}{} } +func (app *slowApp) NotaryAck(notaryAck types.NotaryAck) { + time.Sleep(app.sleep) + app.notaryAck[notaryAck.Hash] = struct{}{} +} + type NonBlockingAppTestSuite struct { suite.Suite } diff --git a/core/test/app.go b/core/test/app.go index 5c438a7..4a704a0 100644 --- a/core/test/app.go +++ b/core/test/app.go @@ -23,6 +23,7 @@ import ( "time" "github.com/dexon-foundation/dexon-consensus-core/common" + "github.com/dexon-foundation/dexon-consensus-core/core/types" ) var ( @@ -105,6 +106,10 @@ func (app *App) DeliverBlock(blockHash common.Hash, timestamp time.Time) { app.DeliverSequence = append(app.DeliverSequence, blockHash) } +// NotaryAck implements Application interface. +func (app *App) NotaryAck(notaryAck types.NotaryAck) { +} + // Compare performs these checks against another App instance // and return erros if not passed: // - deliver sequence by comparing block hashes. diff --git a/core/types/block.go b/core/types/block.go index 0386ed7..557974f 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -28,28 +28,6 @@ import ( "github.com/dexon-foundation/dexon-consensus-core/crypto" ) -// NotaryAck represents the acking to the compaction chain. -type NotaryAck struct { - NotaryBlockHash common.Hash `json:"notary_block_hash"` - // NotarySignature is the signature of the hash value of - // Block.NotaryParentHash and Block.Notary. - NotarySignature crypto.Signature `json:"notary_signature"` -} - -// CompactionChainAck represents the acking to the compaction chain. -type CompactionChainAck struct { - AckingBlockHash common.Hash `json:"acking_block_hash"` - // Signature is the signature of the hash value of - // Block.ConsensusInfoParentHash and Block.ConsensusInfo. - ConsensusSignature crypto.Signature `json:"consensus_signature"` -} - -// Notary represents the consensus information on the compaction chain. -type Notary struct { - Timestamp time.Time `json:"timestamp"` - Height uint64 `json:"height"` -} - // Block represents a single event broadcasted on the network. type Block struct { ProposerID ValidatorID `json:"proposer_id"` @@ -58,16 +36,9 @@ type Block struct { Height uint64 `json:"height"` Timestamps map[ValidatorID]time.Time `json:"timestamps"` Acks map[common.Hash]struct{} `json:"acks"` - //NotaryAck NotaryAck `json:"notary_ack"` - Signature crypto.Signature `json:"signature"` + Signature crypto.Signature `json:"signature"` Notary Notary `json:"notary"` - // NotaryParentHash is the hash value of Block.NotaryParentHash - // and Block.Notary, where Block is the previous block on - // the compaction chain. - NotaryParentHash common.Hash `json:"notary_parent_hash"` - - ConsensusInfoParentHash common.Hash `json:"consensus_info_parent_hash"` } // Block implements BlockConverter interface. @@ -106,22 +77,12 @@ func (b *Block) Clone() *Block { Height: b.Height, Timestamps: make(map[ValidatorID]time.Time), Acks: make(map[common.Hash]struct{}), - /* - NotaryAck: NotaryAck{ - NotaryBlockHash: b.NotaryAck.NotaryBlockHash, - }, - */ - Signature: b.Signature, + Signature: b.Signature, Notary: Notary{ Timestamp: b.Notary.Timestamp, Height: b.Notary.Height, }, - NotaryParentHash: b.NotaryParentHash, } - /* - bcopy.NotaryAck.NotarySignature = append( - crypto.Signature(nil), b.NotaryAck.NotarySignature...) - */ for k, v := range b.Timestamps { bcopy.Timestamps[k] = v } diff --git a/core/types/notary.go b/core/types/notary.go new file mode 100644 index 0000000..01237b4 --- /dev/null +++ b/core/types/notary.go @@ -0,0 +1,43 @@ +// Copyright 2018 The dexon-consensus-core Authors +// This file is part of the dexon-consensus-core library. +// +// The dexon-consensus-core library is free software: you can redistribute it +// and/or modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// The dexon-consensus-core library is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +// General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the dexon-consensus-core library. If not, see +// <http://www.gnu.org/licenses/>. + +// TODO(jimmy-dexon): remove comments of NotaryAck before open source. + +package types + +import ( + "time" + + "github.com/dexon-foundation/dexon-consensus-core/common" + "github.com/dexon-foundation/dexon-consensus-core/crypto" +) + +// NotaryAck represents the acking to the compaction chain. +type NotaryAck struct { + ProposerID ValidatorID `json:"proposer_id"` + NotaryBlockHash common.Hash `json:"notary_block_hash"` + Hash common.Hash `json:"hash"` + // NotarySignature is the signature of the hash value of BlockNotary. + Signature crypto.Signature `json:"signature"` +} + +// Notary represents the consensus information on the compaction chain. +type Notary struct { + ParentHash common.Hash `json:"parent_hash"` + Timestamp time.Time `json:"timestamp"` + Height uint64 `json:"height"` +} |