diff options
author | Jimmy Hu <jimmy.hu@dexon.org> | 2018-08-28 11:21:48 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-28 11:21:48 +0800 |
commit | 9c8f9a447bfd768a7b29db904bd604410ec66a09 (patch) | |
tree | 76495e11738e24e4ff3f27d647509f29012eea6f | |
parent | e122cb236312e0ca3ef6e0207a20890ec1e7bfaf (diff) | |
download | dexon-consensus-9c8f9a447bfd768a7b29db904bd604410ec66a09.tar dexon-consensus-9c8f9a447bfd768a7b29db904bd604410ec66a09.tar.gz dexon-consensus-9c8f9a447bfd768a7b29db904bd604410ec66a09.tar.bz2 dexon-consensus-9c8f9a447bfd768a7b29db904bd604410ec66a09.tar.lz dexon-consensus-9c8f9a447bfd768a7b29db904bd604410ec66a09.tar.xz dexon-consensus-9c8f9a447bfd768a7b29db904bd604410ec66a09.tar.zst dexon-consensus-9c8f9a447bfd768a7b29db904bd604410ec66a09.zip |
core: Add vote type and add field to block. (#76)
-rw-r--r-- | core/consensus.go | 5 | ||||
-rw-r--r-- | core/crypto.go | 48 | ||||
-rw-r--r-- | core/types/block.go | 4 | ||||
-rw-r--r-- | core/types/vote.go | 62 | ||||
-rw-r--r-- | crypto/utils.go | 5 | ||||
-rw-r--r-- | simulation/network.go | 1 | ||||
-rw-r--r-- | simulation/tcp-network.go | 14 | ||||
-rw-r--r-- | simulation/validator.go | 4 |
8 files changed, 139 insertions, 4 deletions
diff --git a/core/consensus.go b/core/consensus.go index 122f0b0..c15d0e5 100644 --- a/core/consensus.go +++ b/core/consensus.go @@ -102,6 +102,11 @@ func NewConsensus( } } +// ProcessVote is the entry point to submit ont vote to a Consensus instance. +func (con *Consensus) ProcessVote(vote *types.Vote) (err error) { + return +} + // sanityCheck checks if the block is a valid block func (con *Consensus) sanityCheck(blockConv types.BlockConverter) (err error) { b := blockConv.Block() diff --git a/core/crypto.go b/core/crypto.go index 4fc49d7..17426f7 100644 --- a/core/crypto.go +++ b/core/crypto.go @@ -51,8 +51,8 @@ func verifyNotarySignature(pubkey crypto.PublicKey, func hashBlock(blockConv types.BlockConverter) (common.Hash, error) { block := blockConv.Block() - binaryHeight := make([]byte, 8) - binary.LittleEndian.PutUint64(binaryHeight, block.Height) + + hashPosition := hashPosition(block.ShardID, block.ChainID, block.Height) // Handling Block.Acks. acks := make(common.Hashes, 0, len(block.Acks)) for ack := range block.Acks { @@ -85,7 +85,7 @@ func hashBlock(blockConv types.BlockConverter) (common.Hash, error) { hash := crypto.Keccak256Hash( block.ProposerID.Hash[:], block.ParentHash[:], - binaryHeight, + hashPosition[:], hashAcks[:], hashTimestamps[:], payloadHash[:]) @@ -100,3 +100,45 @@ func verifyBlockSignature(pubkey crypto.PublicKey, } return pubkey.VerifySignature(hash, sig), nil } + +func hashVote(vote *types.Vote) common.Hash { + binaryPeriod := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryPeriod, vote.Period) + + hash := crypto.Keccak256Hash( + vote.ProposerID.Hash[:], + vote.BlockHash[:], + binaryPeriod, + []byte{byte(vote.Type)}, + ) + return hash +} + +func verifyVoteSignature(vote *types.Vote, sigToPub SigToPubFn) (bool, error) { + hash := hashVote(vote) + pubKey, err := sigToPub(hash, vote.Signature) + if err != nil { + return false, err + } + if vote.ProposerID != types.NewValidatorID(pubKey) { + return false, nil + } + return true, nil +} + +func hashPosition(shardID, chainID, height uint64) common.Hash { + binaryShardID := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryShardID, shardID) + + binaryChainID := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryChainID, chainID) + + binaryHeight := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryHeight, height) + + return crypto.Keccak256Hash( + binaryShardID, + binaryChainID, + binaryHeight, + ) +} diff --git a/core/types/block.go b/core/types/block.go index 557974f..92b0f8a 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -33,6 +33,8 @@ type Block struct { ProposerID ValidatorID `json:"proposer_id"` ParentHash common.Hash `json:"parent_hash"` Hash common.Hash `json:"hash"` + ShardID uint64 `json:"shard_id"` + ChainID uint64 `json:"chain_id"` Height uint64 `json:"height"` Timestamps map[ValidatorID]time.Time `json:"timestamps"` Acks map[common.Hash]struct{} `json:"acks"` @@ -77,7 +79,7 @@ func (b *Block) Clone() *Block { Height: b.Height, Timestamps: make(map[ValidatorID]time.Time), Acks: make(map[common.Hash]struct{}), - Signature: b.Signature, + Signature: b.Signature.Clone(), Notary: Notary{ Timestamp: b.Notary.Timestamp, Height: b.Notary.Height, diff --git a/core/types/vote.go b/core/types/vote.go new file mode 100644 index 0000000..1247f84 --- /dev/null +++ b/core/types/vote.go @@ -0,0 +1,62 @@ +// 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/>. + +package types + +import ( + "fmt" + + "github.com/dexon-foundation/dexon-consensus-core/common" + "github.com/dexon-foundation/dexon-consensus-core/crypto" +) + +// VoteType is the type of vote. +type VoteType byte + +// VoteType enum. +const ( + VoteAck VoteType = iota + VoteConfirm + VotePass + // Do not add any type below MaxVoteType. + MaxVoteType +) + +// Vote is the vote structure defined in Crypto Shuffle Algorithm. +type Vote struct { + ProposerID ValidatorID + Type VoteType + BlockHash common.Hash + Period uint64 + Signature crypto.Signature +} + +func (v *Vote) String() string { + return fmt.Sprintf("Vote(%d:%d):%s", + v.Period, v.Type, v.BlockHash.String()[:6]) +} + +// Clone returns a deep copy of a vote. +func (v *Vote) Clone() *Vote { + return &Vote{ + ProposerID: v.ProposerID, + Type: v.Type, + BlockHash: v.BlockHash, + Period: v.Period, + Signature: v.Signature.Clone(), + } +} diff --git a/crypto/utils.go b/crypto/utils.go index 5534ece..dfb4987 100644 --- a/crypto/utils.go +++ b/crypto/utils.go @@ -28,3 +28,8 @@ import ( func Keccak256Hash(data ...[]byte) (h common.Hash) { return common.Hash(crypto.Keccak256Hash(data...)) } + +// Clone returns a deep copy of a signature. +func (sig Signature) Clone() Signature { + return append(Signature{}, sig...) +} diff --git a/simulation/network.go b/simulation/network.go index f08b638..687dd90 100644 --- a/simulation/network.go +++ b/simulation/network.go @@ -81,6 +81,7 @@ type Network interface { Join(endpoint Endpoint) chan interface{} BroadcastBlock(block *types.Block) BroadcastNotaryAck(notaryAck *types.NotaryAck) + BroadcastVote(vote *types.Vote) Endpoints() types.ValidatorIDs } diff --git a/simulation/tcp-network.go b/simulation/tcp-network.go index 2da9e3a..bb63bd1 100644 --- a/simulation/tcp-network.go +++ b/simulation/tcp-network.go @@ -257,6 +257,9 @@ func (n *TCPNetwork) Send(destID types.ValidatorID, msg interface{}) { case *types.NotaryAck: message.Type = "notaryAck" message.Payload = v + case *types.Vote: + message.Type = "vote" + message.Payload = v default: fmt.Println("error: invalid message type") return @@ -318,6 +321,17 @@ func (n *TCPNetwork) BroadcastNotaryAck(notaryAck *types.NotaryAck) { } } +// BroadcastVote broadcast vote into the network. +func (n *TCPNetwork) BroadcastVote(vote *types.Vote) { + vote = vote.Clone() + for endpoint := range n.endpoints { + if endpoint == vote.ProposerID { + continue + } + n.Send(endpoint, vote) + } +} + // DeliverBlocks sends blocks to peerServer. func (n *TCPNetwork) DeliverBlocks(blocks BlockList) { messageJSON, err := json.Marshal(blocks) diff --git a/simulation/validator.go b/simulation/validator.go index fb5f6cd..b26603a 100644 --- a/simulation/validator.go +++ b/simulation/validator.go @@ -159,6 +159,10 @@ func (v *Validator) MsgServer( if err := v.consensus.ProcessNotaryAck(val); err != nil { fmt.Println(err) } + case *types.Vote: + if err := v.consensus.ProcessVote(val); err != nil { + fmt.Println(err) + } } } } |