diff options
-rw-r--r-- | core/compaction-chain.go | 50 | ||||
-rw-r--r-- | core/compaction-chain_test.go | 100 | ||||
-rw-r--r-- | core/consensus-timestamp.go | 8 | ||||
-rw-r--r-- | core/consensus-timestamp_test.go | 2 | ||||
-rw-r--r-- | core/consensus.go | 47 | ||||
-rw-r--r-- | core/crypto.go | 18 | ||||
-rw-r--r-- | core/crypto_test.go | 74 | ||||
-rw-r--r-- | core/types/block.go | 66 |
8 files changed, 197 insertions, 168 deletions
diff --git a/core/compaction-chain.go b/core/compaction-chain.go index 7890b4f..f2b4d1b 100644 --- a/core/compaction-chain.go +++ b/core/compaction-chain.go @@ -15,12 +15,14 @@ // along with the dexon-consensus-core library. If not, see // <http://www.gnu.org/licenses/>. +// TODO(jimmy-dexon): remove those comments before open source. + package core import ( "sync" - "github.com/dexon-foundation/dexon-consensus-core/common" + //"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" ) @@ -36,33 +38,37 @@ func newCompactionChain() *compactionChain { func (cc *compactionChain) prepareBlock( block *types.Block, prvKey crypto.PrivateKey) (err error) { - prevBlock := cc.lastBlock() - if prevBlock != nil { - block.CompactionChainAck.ConsensusInfoSignature, err = - signConsensusInfo(prevBlock, prvKey) - if err != nil { - return + /* + prevBlock := cc.lastBlock() + if prevBlock != nil { + block.NotaryAck.NotarySignature, err = + signNotary(prevBlock, prvKey) + if err != nil { + return + } + block.NotaryAck.NotaryBlockHash = prevBlock.Hash } - block.CompactionChainAck.AckingBlockHash = prevBlock.Hash - } + */ return } func (cc *compactionChain) processBlock(block *types.Block) (err error) { - prevBlock := cc.lastBlock() - if prevBlock == nil { - block.ConsensusInfo.Height = 0 - block.ConsensusInfoParentHash = common.Hash{} - } else { - block.ConsensusInfo.Height = prevBlock.ConsensusInfo.Height + 1 - block.ConsensusInfoParentHash, err = hashConsensusInfo(prevBlock) - if err != nil { - return + /* + prevBlock := cc.lastBlock() + if prevBlock == nil { + block.Notary.Height = 0 + block.NotaryParentHash = common.Hash{} + } else { + block.Notary.Height = prevBlock.Notary.Height + 1 + block.NotaryParentHash, err = hashNotary(prevBlock) + if err != nil { + return + } } - } - cc.lock.Lock() - defer cc.lock.Unlock() - cc.prevBlock = block + cc.lock.Lock() + defer cc.lock.Unlock() + cc.prevBlock = block + */ return } diff --git a/core/compaction-chain_test.go b/core/compaction-chain_test.go index 402394d..05122a3 100644 --- a/core/compaction-chain_test.go +++ b/core/compaction-chain_test.go @@ -20,9 +20,11 @@ package core import ( "testing" - "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/eth" + /* + "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/eth" + */ "github.com/stretchr/testify/suite" ) @@ -31,58 +33,62 @@ type CompactionChainTestSuite struct { } func (s *CompactionChainTestSuite) TestProcessBlock() { - cc := newCompactionChain() - blocks := make([]*types.Block, 10) - for idx := range blocks { - blocks[idx] = &types.Block{ - Hash: common.NewRandomHash(), + /* + cc := newCompactionChain() + blocks := make([]*types.Block, 10) + for idx := range blocks { + blocks[idx] = &types.Block{ + Hash: common.NewRandomHash(), + } } - } - var prevBlock *types.Block - for _, block := range blocks { - s.Equal(cc.prevBlock, prevBlock) - cc.processBlock(block) - if prevBlock != nil { - s.Equal(block.ConsensusInfo.Height, prevBlock.ConsensusInfo.Height+1) - prevHash, err := hashConsensusInfo(prevBlock) - s.Require().Nil(err) - s.Equal(prevHash, block.ConsensusInfoParentHash) + var prevBlock *types.Block + for _, block := range blocks { + s.Equal(cc.prevBlock, prevBlock) + cc.processBlock(block) + if prevBlock != nil { + s.Equal(block.Notary.Height, prevBlock.Notary.Height+1) + prevHash, err := hashNotary(prevBlock) + s.Require().Nil(err) + s.Equal(prevHash, block.NotaryParentHash) + } + prevBlock = block } - prevBlock = block - } + */ } func (s *CompactionChainTestSuite) TestPrepareBlock() { - cc := newCompactionChain() - blocks := make([]*types.Block, 10) - for idx := range blocks { - blocks[idx] = &types.Block{ - Hash: common.NewRandomHash(), - ConsensusInfo: types.ConsensusInfo{ - Height: uint64(idx), - }, + /* + cc := newCompactionChain() + blocks := make([]*types.Block, 10) + for idx := range blocks { + blocks[idx] = &types.Block{ + Hash: common.NewRandomHash(), + Notary: types.Notary{ + Height: uint64(idx), + }, + } + if idx > 0 { + var err error + blocks[idx].NotaryParentHash, err = hashNotary(blocks[idx-1]) + s.Require().Nil(err) + } } - if idx > 0 { - var err error - blocks[idx].ConsensusInfoParentHash, err = hashConsensusInfo(blocks[idx-1]) + prv, err := eth.NewPrivateKey() s.Require().Nil(err) - } - } - prv, err := eth.NewPrivateKey() - s.Require().Nil(err) - for _, block := range blocks { - cc.prepareBlock(block, prv) - if cc.prevBlock != nil { - s.True(verifyConsensusInfoSignature( - prv.PublicKey(), - cc.prevBlock, - block.CompactionChainAck.ConsensusInfoSignature)) - s.Equal(block.CompactionChainAck.AckingBlockHash, cc.prevBlock.Hash) - } - cc.prevBlock = block - } + for _, block := range blocks { + cc.prepareBlock(block, prv) + if cc.prevBlock != nil { + s.True(verifyNotarySignature( + prv.PublicKey(), + cc.prevBlock, + block.NotaryAck.NotarySignature)) + s.Equal(block.NotaryAck.NotaryBlockHash, cc.prevBlock.Hash) + } + cc.prevBlock = block + } + */ } -func TestCompactionChain(t *testing.T) { +func TestNotary(t *testing.T) { suite.Run(t, new(CompactionChainTestSuite)) } diff --git a/core/consensus-timestamp.go b/core/consensus-timestamp.go index 7694f60..90489ed 100644 --- a/core/consensus-timestamp.go +++ b/core/consensus-timestamp.go @@ -67,7 +67,7 @@ func (ct *consensusTimestamp) processBlocks(blocks []*types.Block) ( return } else if block.Hash == mainChain[idxMainChain].Hash { rightMainChainIdx = idx - blocksWithTimestamp[idx].ConsensusInfo.Timestamp, err = + blocksWithTimestamp[idx].Notary.Timestamp, err = getMedianTime(block) if err != nil { return @@ -75,10 +75,10 @@ func (ct *consensusTimestamp) processBlocks(blocks []*types.Block) ( // Process Non-MainChain blocks. if rightMainChainIdx > leftMainChainIdx { for idx, timestamp := range interpoTime( - blocksWithTimestamp[leftMainChainIdx].ConsensusInfo.Timestamp, - blocksWithTimestamp[rightMainChainIdx].ConsensusInfo.Timestamp, + blocksWithTimestamp[leftMainChainIdx].Notary.Timestamp, + blocksWithTimestamp[rightMainChainIdx].Notary.Timestamp, rightMainChainIdx-leftMainChainIdx-1) { - blocksWithTimestamp[leftMainChainIdx+idx+1].ConsensusInfo.Timestamp = + blocksWithTimestamp[leftMainChainIdx+idx+1].Notary.Timestamp = timestamp } } diff --git a/core/consensus-timestamp_test.go b/core/consensus-timestamp_test.go index aeba00a..6dff111 100644 --- a/core/consensus-timestamp_test.go +++ b/core/consensus-timestamp_test.go @@ -79,7 +79,7 @@ func fillBlocksTimestamps(blocks []*types.Block, validatorNum int, func extractTimestamps(blocks []*types.Block) []time.Time { timestamps := make([]time.Time, len(blocks)) for idx, block := range blocks { - timestamps[idx] = block.ConsensusInfo.Timestamp + timestamps[idx] = block.Notary.Timestamp } return timestamps } diff --git a/core/consensus.go b/core/consensus.go index d5ce923..3e8f87d 100644 --- a/core/consensus.go +++ b/core/consensus.go @@ -48,8 +48,8 @@ var ( "hash of block is incorrect") ErrIncorrectSignature = fmt.Errorf( "signature of block is incorrect") - ErrIncorrectCompactionChainAck = fmt.Errorf( - "compaction chain ack of block is incorrect") + ErrIncorrectNotaryAck = fmt.Errorf( + "compaction chain notary of block is incorrect") ErrGenesisBlockNotEmpty = fmt.Errorf( "genesis block should be empty") ) @@ -120,26 +120,29 @@ func (con *Consensus) sanityCheck(blockConv types.BlockConverter) (err error) { return ErrIncorrectSignature } - // Check the compaction chain info. - if ackingBlockHash := - b.CompactionChainAck.AckingBlockHash; (ackingBlockHash != common.Hash{}) { - ackingBlock, err := con.db.Get(ackingBlockHash) - if err != nil { - return err - } - hash, err := hashConsensusInfo(&ackingBlock) - if err != nil { - return err - } - pubKey, err := con.sigToPub(hash, - b.CompactionChainAck.ConsensusInfoSignature) - if err != nil { - return err - } - if !b.ProposerID.Equal(crypto.Keccak256Hash(pubKey.Bytes())) { - return ErrIncorrectCompactionChainAck + // TODO(jimmy-dexon): remove these comments before open source. + /* + // Check the notary ack. + if notaryBlockHash := + b.NotaryAck.NotaryBlockHash; (notaryBlockHash != common.Hash{}) { + notaryBlock, err := con.db.Get(notaryBlockHash) + if err != nil { + return err + } + hash, err := hashNotary(¬aryBlock) + if err != nil { + return err + } + pubKey, err := con.sigToPub(hash, + b.NotaryAck.NotarySignature) + if err != nil { + return err + } + if !b.ProposerID.Equal(crypto.Keccak256Hash(pubKey.Bytes())) { + return ErrIncorrectNotaryAck + } } - } + */ return nil } @@ -199,7 +202,7 @@ func (con *Consensus) ProcessBlock(blockConv types.BlockConverter) (err error) { if err = con.db.Update(*b); err != nil { return } - con.app.DeliverBlock(b.Hash, b.ConsensusInfo.Timestamp) + con.app.DeliverBlock(b.Hash, b.Notary.Timestamp) } } return diff --git a/core/crypto.go b/core/crypto.go index e193e36..664607b 100644 --- a/core/crypto.go +++ b/core/crypto.go @@ -26,32 +26,32 @@ import ( "github.com/dexon-foundation/dexon-consensus-core/crypto" ) -func hashConsensusInfo(block *types.Block) (common.Hash, error) { - binaryTime, err := block.ConsensusInfo.Timestamp.MarshalBinary() +func hashNotary(block *types.Block) (common.Hash, error) { + binaryTime, err := block.Notary.Timestamp.MarshalBinary() if err != nil { return common.Hash{}, err } binaryHeight := make([]byte, 8) - binary.LittleEndian.PutUint64(binaryHeight, block.ConsensusInfo.Height) + binary.LittleEndian.PutUint64(binaryHeight, block.Notary.Height) hash := crypto.Keccak256Hash( - block.ConsensusInfoParentHash[:], + block.NotaryParentHash[:], binaryTime, binaryHeight) return hash, nil } -func signConsensusInfo(block *types.Block, +func signNotary(block *types.Block, prv crypto.PrivateKey) (crypto.Signature, error) { - hash, err := hashConsensusInfo(block) + hash, err := hashNotary(block) if err != nil { return crypto.Signature{}, err } return prv.Sign(hash) } -func verifyConsensusInfoSignature(pubkey crypto.PublicKey, - ackingBlock *types.Block, sig crypto.Signature) (bool, error) { - hash, err := hashConsensusInfo(ackingBlock) +func verifyNotarySignature(pubkey crypto.PublicKey, + notaryBlock *types.Block, sig crypto.Signature) (bool, error) { + hash, err := hashNotary(notaryBlock) if err != nil { return false, err } diff --git a/core/crypto_test.go b/core/crypto_test.go index f5ec28e..94b500e 100644 --- a/core/crypto_test.go +++ b/core/crypto_test.go @@ -58,28 +58,30 @@ func (s *CryptoTestSuite) prepareBlock(prevBlock *types.Block) *types.Block { return &types.Block{ Acks: acks, Timestamps: timestamps, - ConsensusInfo: types.ConsensusInfo{ + Notary: types.Notary{ Timestamp: time.Now(), Height: 0, }, } } - parentHash, err := hashConsensusInfo(prevBlock) + parentHash, err := hashNotary(prevBlock) s.Require().Nil(err) s.Require().NotEqual(prevBlock.Hash, common.Hash{}) acks[parentHash] = struct{}{} return &types.Block{ - ParentHash: prevBlock.Hash, - Acks: acks, - Timestamps: timestamps, - ConsensusInfoParentHash: parentHash, - Height: prevBlock.Height + 1, - CompactionChainAck: types.CompactionChainAck{ - AckingBlockHash: prevBlock.Hash, - }, - ConsensusInfo: types.ConsensusInfo{ + ParentHash: prevBlock.Hash, + Acks: acks, + Timestamps: timestamps, + NotaryParentHash: parentHash, + Height: prevBlock.Height + 1, + /* + NotaryAck: types.NotaryAck{ + NotaryBlockHash: prevBlock.Hash, + }, + */ + Notary: types.Notary{ Timestamp: time.Now(), - Height: prevBlock.ConsensusInfo.Height + 1, + Height: prevBlock.Notary.Height + 1, }, } } @@ -102,19 +104,21 @@ func (s *CryptoTestSuite) generateCompactionChain( blocks[idx] = block var err error if idx > 0 { - block.ConsensusInfoParentHash, err = hashConsensusInfo(blocks[idx-1]) - s.Require().Nil(err) - block.CompactionChainAck.ConsensusInfoSignature, err = - signConsensusInfo(blocks[idx-1], prv) + block.NotaryParentHash, err = hashNotary(blocks[idx-1]) s.Require().Nil(err) + /* + block.NotaryAck.NotarySignature, err = + signNotary(blocks[idx-1], prv) + s.Require().Nil(err) + */ } } return blocks } -func (s *CryptoTestSuite) TestCompactionChainAckSignature() { +func (s *CryptoTestSuite) TestNotaryAckSignature() { prv, err := eth.NewPrivateKey() - pub := prv.PublicKey() + //pub := prv.PublicKey() s.Require().Nil(err) blocks := s.generateCompactionChain(10, prv) blockMap := make(map[common.Hash]*types.Block) @@ -122,28 +126,32 @@ func (s *CryptoTestSuite) TestCompactionChainAckSignature() { blockMap[block.Hash] = block } for _, block := range blocks { - if block.ConsensusInfo.Height == 0 { + if block.Notary.Height == 0 { continue } - ackingBlock, exist := blockMap[block.CompactionChainAck.AckingBlockHash] - s.Require().True(exist) - s.True(ackingBlock.ConsensusInfo.Height == block.ConsensusInfo.Height-1) - hash, err := hashConsensusInfo(ackingBlock) - s.Require().Nil(err) - s.Equal(hash, block.ConsensusInfoParentHash) - s.True(verifyConsensusInfoSignature( - pub, ackingBlock, block.CompactionChainAck.ConsensusInfoSignature)) + /* + ackingBlock, exist := blockMap[block.NotaryAck.NotaryBlockHash] + s.Require().True(exist) + s.True(ackingBlock.Notary.Height == block.Notary.Height-1) + hash, err := hashNotary(ackingBlock) + s.Require().Nil(err) + s.Equal(hash, block.NotaryParentHash) + s.True(verifyNotarySignature( + pub, ackingBlock, block.NotaryAck.NotarySignature)) + */ } // Modify Block.ConsensusTime and verify signature again. for _, block := range blocks { - block.ConsensusInfo.Timestamp = time.Time{} - if block.ConsensusInfo.Height == 0 { + block.Notary.Timestamp = time.Time{} + if block.Notary.Height == 0 { continue } - ackingBlock, exist := blockMap[block.CompactionChainAck.AckingBlockHash] - s.Require().True(exist) - s.False(verifyConsensusInfoSignature( - pub, ackingBlock, block.CompactionChainAck.ConsensusInfoSignature)) + /* + ackingBlock, exist := blockMap[block.NotaryAck.NotaryBlockHash] + s.Require().True(exist) + s.False(verifyNotarySignature( + pub, ackingBlock, block.NotaryAck.NotarySignature)) + */ } } diff --git a/core/types/block.go b/core/types/block.go index 0fa16d4..9665043 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -15,6 +15,8 @@ // 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 ( @@ -37,36 +39,36 @@ const ( BlockStatusFinal ) -// CompactionChainAck represents the acking to the compaction chain. -type CompactionChainAck struct { - AckingBlockHash common.Hash `json:"acking_block_hash"` - // ConsensusInfoSignature is the signature of the hash value of - // Block.ConsensusInfoParentHash and Block.ConsensusInfo. - ConsensusInfoSignature crypto.Signature `json:"consensus_info_signature"` +// 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"` } -// ConsensusInfo represents the consensus information on the compaction chain. -type ConsensusInfo struct { +// 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"` - ParentHash common.Hash `json:"parent_hash"` - Hash common.Hash `json:"hash"` - Height uint64 `json:"height"` - Timestamps map[ValidatorID]time.Time `json:"timestamps"` - Acks map[common.Hash]struct{} `json:"acks"` - CompactionChainAck CompactionChainAck `json:"compaction_chain_ack"` - Signature crypto.Signature `json:"signature"` - - ConsensusInfo ConsensusInfo `json:"consensus_info"` - // ConsensusInfoParentHash is the hash value of Block.ConsensusInfoParentHash - // and Block.ConsensusInfo, where Block is the previous block on + ProposerID ValidatorID `json:"proposer_id"` + ParentHash common.Hash `json:"parent_hash"` + Hash common.Hash `json:"hash"` + 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"` + + 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. - ConsensusInfoParentHash common.Hash `json:"consensus_info_parent_hash"` + NotaryParentHash common.Hash `json:"notary_parent_hash"` Ackeds map[common.Hash]struct{} `json:"-"` AckedValidators map[ValidatorID]struct{} `json:"-"` @@ -110,18 +112,22 @@ func (b *Block) Clone() *Block { Height: b.Height, Timestamps: make(map[ValidatorID]time.Time), Acks: make(map[common.Hash]struct{}), - CompactionChainAck: CompactionChainAck{ - AckingBlockHash: b.CompactionChainAck.AckingBlockHash, - }, + /* + NotaryAck: NotaryAck{ + NotaryBlockHash: b.NotaryAck.NotaryBlockHash, + }, + */ Signature: b.Signature, - ConsensusInfo: ConsensusInfo{ - Timestamp: b.ConsensusInfo.Timestamp, - Height: b.ConsensusInfo.Height, + Notary: Notary{ + Timestamp: b.Notary.Timestamp, + Height: b.Notary.Height, }, - ConsensusInfoParentHash: b.ConsensusInfoParentHash, + NotaryParentHash: b.NotaryParentHash, } - bcopy.CompactionChainAck.ConsensusInfoSignature = append( - crypto.Signature(nil), b.CompactionChainAck.ConsensusInfoSignature...) + /* + bcopy.NotaryAck.NotarySignature = append( + crypto.Signature(nil), b.NotaryAck.NotarySignature...) + */ for k, v := range b.Timestamps { bcopy.Timestamps[k] = v } |