aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJimmy Hu <jimmy.hu@dexon.org>2018-08-28 11:21:48 +0800
committerGitHub <noreply@github.com>2018-08-28 11:21:48 +0800
commit9c8f9a447bfd768a7b29db904bd604410ec66a09 (patch)
tree76495e11738e24e4ff3f27d647509f29012eea6f
parente122cb236312e0ca3ef6e0207a20890ec1e7bfaf (diff)
downloaddexon-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.go5
-rw-r--r--core/crypto.go48
-rw-r--r--core/types/block.go4
-rw-r--r--core/types/vote.go62
-rw-r--r--crypto/utils.go5
-rw-r--r--simulation/network.go1
-rw-r--r--simulation/tcp-network.go14
-rw-r--r--simulation/validator.go4
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)
+ }
}
}
}