aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/byzantine-lab/dexon-consensus/core/types
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/byzantine-lab/dexon-consensus/core/types')
-rw-r--r--vendor/github.com/byzantine-lab/dexon-consensus/core/types/block-randomness.go44
-rw-r--r--vendor/github.com/byzantine-lab/dexon-consensus/core/types/block.go227
-rw-r--r--vendor/github.com/byzantine-lab/dexon-consensus/core/types/config.go75
-rw-r--r--vendor/github.com/byzantine-lab/dexon-consensus/core/types/dkg/dkg.go485
-rw-r--r--vendor/github.com/byzantine-lab/dexon-consensus/core/types/message.go24
-rw-r--r--vendor/github.com/byzantine-lab/dexon-consensus/core/types/node.go61
-rw-r--r--vendor/github.com/byzantine-lab/dexon-consensus/core/types/nodeset.go162
-rw-r--r--vendor/github.com/byzantine-lab/dexon-consensus/core/types/position.go51
-rw-r--r--vendor/github.com/byzantine-lab/dexon-consensus/core/types/vote.go100
9 files changed, 1229 insertions, 0 deletions
diff --git a/vendor/github.com/byzantine-lab/dexon-consensus/core/types/block-randomness.go b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/block-randomness.go
new file mode 100644
index 000000000..b97188705
--- /dev/null
+++ b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/block-randomness.go
@@ -0,0 +1,44 @@
+// Copyright 2018 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus 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 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 library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package types
+
+import (
+ "encoding/hex"
+ "fmt"
+
+ "github.com/byzantine-lab/dexon-consensus/common"
+)
+
+// AgreementResult describes an agremeent result.
+type AgreementResult struct {
+ BlockHash common.Hash `json:"block_hash"`
+ Position Position `json:"position"`
+ Votes []Vote `json:"votes"`
+ IsEmptyBlock bool `json:"is_empty_block"`
+ Randomness []byte `json:"randomness"`
+}
+
+func (r *AgreementResult) String() string {
+ if len(r.Randomness) == 0 {
+ return fmt.Sprintf("agreementResult{Block:%s Pos:%s}",
+ r.BlockHash.String()[:6], r.Position)
+ }
+ return fmt.Sprintf("agreementResult{Block:%s Pos:%s Rand:%s}",
+ r.BlockHash.String()[:6], r.Position,
+ hex.EncodeToString(r.Randomness)[:6])
+}
diff --git a/vendor/github.com/byzantine-lab/dexon-consensus/core/types/block.go b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/block.go
new file mode 100644
index 000000000..bc92211b9
--- /dev/null
+++ b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/block.go
@@ -0,0 +1,227 @@
+// Copyright 2018 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus 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 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 library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+// TODO(jimmy-dexon): remove comments of WitnessAck before open source.
+
+package types
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "time"
+
+ "github.com/byzantine-lab/go-tangerine/rlp"
+
+ "github.com/byzantine-lab/dexon-consensus/common"
+ "github.com/byzantine-lab/dexon-consensus/core/crypto"
+)
+
+// GenesisHeight refers to the initial height the genesis block should be.
+const GenesisHeight uint64 = 1
+
+// BlockVerifyStatus is the return code for core.Application.VerifyBlock
+type BlockVerifyStatus int
+
+// Enums for return value of core.Application.VerifyBlock.
+const (
+ // VerifyOK: Block is verified.
+ VerifyOK BlockVerifyStatus = iota
+ // VerifyRetryLater: Block is unable to be verified at this moment.
+ // Try again later.
+ VerifyRetryLater
+ // VerifyInvalidBlock: Block is an invalid one.
+ VerifyInvalidBlock
+)
+
+type rlpTimestamp struct {
+ time.Time
+}
+
+func (t *rlpTimestamp) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, uint64(t.UTC().UnixNano()))
+}
+
+func (t *rlpTimestamp) DecodeRLP(s *rlp.Stream) error {
+ var nano uint64
+ err := s.Decode(&nano)
+ if err == nil {
+ sec := int64(nano) / 1000000000
+ nsec := int64(nano) % 1000000000
+ t.Time = time.Unix(sec, nsec).UTC()
+ }
+ return err
+}
+
+// Witness represents the consensus information on the compaction chain.
+type Witness struct {
+ Height uint64 `json:"height"`
+ Data []byte `json:"data"`
+}
+
+// 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"`
+ Payload []byte `json:"payload"`
+ PayloadHash common.Hash `json:"payload_hash"`
+ Witness Witness `json:"witness"`
+ Randomness []byte `json:"randomness"`
+ Signature crypto.Signature `json:"signature"`
+
+ CRSSignature crypto.Signature `json:"crs_signature"`
+}
+
+type rlpBlock struct {
+ ProposerID NodeID
+ ParentHash common.Hash
+ Hash common.Hash
+ Position Position
+ Timestamp *rlpTimestamp
+ Payload []byte
+ PayloadHash common.Hash
+ Witness *Witness
+ Randomness []byte
+ Signature crypto.Signature
+
+ CRSSignature crypto.Signature
+}
+
+// EncodeRLP implements rlp.Encoder
+func (b *Block) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, rlpBlock{
+ ProposerID: b.ProposerID,
+ ParentHash: b.ParentHash,
+ Hash: b.Hash,
+ Position: b.Position,
+ Timestamp: &rlpTimestamp{b.Timestamp},
+ Payload: b.Payload,
+ PayloadHash: b.PayloadHash,
+ Witness: &b.Witness,
+ Randomness: b.Randomness,
+ Signature: b.Signature,
+ CRSSignature: b.CRSSignature,
+ })
+}
+
+// DecodeRLP implements rlp.Decoder
+func (b *Block) DecodeRLP(s *rlp.Stream) error {
+ var dec rlpBlock
+ err := s.Decode(&dec)
+ if err == nil {
+ *b = Block{
+ ProposerID: dec.ProposerID,
+ ParentHash: dec.ParentHash,
+ Hash: dec.Hash,
+ Position: dec.Position,
+ Timestamp: dec.Timestamp.Time,
+ Payload: dec.Payload,
+ PayloadHash: dec.PayloadHash,
+ Witness: *dec.Witness,
+ Randomness: dec.Randomness,
+ Signature: dec.Signature,
+ CRSSignature: dec.CRSSignature,
+ }
+ }
+ return err
+}
+
+func (b *Block) String() string {
+ return fmt.Sprintf("Block{Hash:%v %s}", b.Hash.String()[:6], b.Position)
+}
+
+// Clone returns a deep copy of a block.
+func (b *Block) Clone() (bcopy *Block) {
+ bcopy = &Block{}
+ bcopy.ProposerID = b.ProposerID
+ bcopy.ParentHash = b.ParentHash
+ bcopy.Hash = b.Hash
+ bcopy.Position.Round = b.Position.Round
+ bcopy.Position.Height = b.Position.Height
+ bcopy.Signature = b.Signature.Clone()
+ bcopy.CRSSignature = b.CRSSignature.Clone()
+ bcopy.Witness.Height = b.Witness.Height
+ bcopy.Witness.Data = common.CopyBytes(b.Witness.Data)
+ bcopy.Timestamp = b.Timestamp
+ bcopy.Payload = common.CopyBytes(b.Payload)
+ bcopy.PayloadHash = b.PayloadHash
+ bcopy.Randomness = common.CopyBytes(b.Randomness)
+ return
+}
+
+// IsGenesis checks if the block is a genesisBlock
+func (b *Block) IsGenesis() bool {
+ return b.Position.Height == GenesisHeight && b.ParentHash == common.Hash{}
+}
+
+// IsFinalized checks if the block is finalized.
+func (b *Block) IsFinalized() bool {
+ return len(b.Randomness) > 0
+}
+
+// IsEmpty checks if the block is an 'empty block'.
+func (b *Block) IsEmpty() bool {
+ return b.ProposerID.Hash == common.Hash{}
+}
+
+// ByHash is the helper type for sorting slice of blocks by hash.
+type ByHash []*Block
+
+func (b ByHash) Len() int {
+ return len(b)
+}
+
+func (b ByHash) Less(i int, j int) bool {
+ return bytes.Compare([]byte(b[i].Hash[:]), []byte(b[j].Hash[:])) == -1
+}
+
+func (b ByHash) Swap(i int, j int) {
+ b[i], b[j] = b[j], b[i]
+}
+
+// BlocksByPosition is the helper type for sorting slice of blocks by position.
+type BlocksByPosition []*Block
+
+// Len implements Len method in sort.Sort interface.
+func (bs BlocksByPosition) Len() int {
+ return len(bs)
+}
+
+// Less implements Less method in sort.Sort interface.
+func (bs BlocksByPosition) Less(i int, j int) bool {
+ return bs[j].Position.Newer(bs[i].Position)
+}
+
+// Swap implements Swap method in sort.Sort interface.
+func (bs BlocksByPosition) Swap(i int, j int) {
+ bs[i], bs[j] = bs[j], bs[i]
+}
+
+// Push implements Push method in heap interface.
+func (bs *BlocksByPosition) Push(x interface{}) {
+ *bs = append(*bs, x.(*Block))
+}
+
+// Pop implements Pop method in heap interface.
+func (bs *BlocksByPosition) Pop() (ret interface{}) {
+ n := len(*bs)
+ *bs, ret = (*bs)[0:n-1], (*bs)[n-1]
+ return
+}
diff --git a/vendor/github.com/byzantine-lab/dexon-consensus/core/types/config.go b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/config.go
new file mode 100644
index 000000000..dce38369e
--- /dev/null
+++ b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/config.go
@@ -0,0 +1,75 @@
+// Copyright 2018 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus 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 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 library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package types
+
+import (
+ "encoding/binary"
+ "time"
+)
+
+// Config stands for Current Configuration Parameters.
+type Config struct {
+ // Lambda related.
+ LambdaBA time.Duration
+ LambdaDKG time.Duration
+
+ // Set related.
+ NotarySetSize uint32
+
+ // Time related.
+ RoundLength uint64
+ MinBlockInterval time.Duration
+}
+
+// Clone return a copied configuration.
+func (c *Config) Clone() *Config {
+ return &Config{
+ LambdaBA: c.LambdaBA,
+ LambdaDKG: c.LambdaDKG,
+ NotarySetSize: c.NotarySetSize,
+ RoundLength: c.RoundLength,
+ MinBlockInterval: c.MinBlockInterval,
+ }
+}
+
+// Bytes returns []byte representation of Config.
+func (c *Config) Bytes() []byte {
+ binaryLambdaBA := make([]byte, 8)
+ binary.LittleEndian.PutUint64(
+ binaryLambdaBA, uint64(c.LambdaBA.Nanoseconds()))
+ binaryLambdaDKG := make([]byte, 8)
+ binary.LittleEndian.PutUint64(
+ binaryLambdaDKG, uint64(c.LambdaDKG.Nanoseconds()))
+
+ binaryNotarySetSize := make([]byte, 4)
+ binary.LittleEndian.PutUint32(binaryNotarySetSize, c.NotarySetSize)
+
+ 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, binaryLambdaBA...)
+ enc = append(enc, binaryLambdaDKG...)
+ enc = append(enc, binaryNotarySetSize...)
+ enc = append(enc, binaryRoundLength...)
+ enc = append(enc, binaryMinBlockInterval...)
+ return enc
+}
diff --git a/vendor/github.com/byzantine-lab/dexon-consensus/core/types/dkg/dkg.go b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/dkg/dkg.go
new file mode 100644
index 000000000..6c2b777cd
--- /dev/null
+++ b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/dkg/dkg.go
@@ -0,0 +1,485 @@
+// Copyright 2018 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus 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 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 library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package dkg
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+
+ "github.com/byzantine-lab/go-tangerine/rlp"
+
+ "github.com/byzantine-lab/dexon-consensus/common"
+ "github.com/byzantine-lab/dexon-consensus/core/crypto"
+ cryptoDKG "github.com/byzantine-lab/dexon-consensus/core/crypto/dkg"
+ "github.com/byzantine-lab/dexon-consensus/core/types"
+)
+
+// Errors for typesDKG package.
+var (
+ ErrNotReachThreshold = fmt.Errorf("threshold not reach")
+ ErrInvalidThreshold = fmt.Errorf("invalid threshold")
+)
+
+// NewID creates a DKGID from NodeID.
+func NewID(ID types.NodeID) cryptoDKG.ID {
+ return cryptoDKG.NewID(ID.Hash[:])
+}
+
+// PrivateShare describe a secret share in DKG protocol.
+type PrivateShare struct {
+ ProposerID types.NodeID `json:"proposer_id"`
+ ReceiverID types.NodeID `json:"receiver_id"`
+ Round uint64 `json:"round"`
+ Reset uint64 `json:"reset"`
+ PrivateShare cryptoDKG.PrivateKey `json:"private_share"`
+ Signature crypto.Signature `json:"signature"`
+}
+
+// Equal checks equality between two PrivateShare instances.
+func (p *PrivateShare) Equal(other *PrivateShare) bool {
+ return p.ProposerID.Equal(other.ProposerID) &&
+ p.ReceiverID.Equal(other.ReceiverID) &&
+ p.Round == other.Round &&
+ p.Reset == other.Reset &&
+ p.Signature.Type == other.Signature.Type &&
+ bytes.Compare(p.Signature.Signature, other.Signature.Signature) == 0 &&
+ bytes.Compare(
+ p.PrivateShare.Bytes(), other.PrivateShare.Bytes()) == 0
+}
+
+// MasterPublicKey decrtibe a master public key in DKG protocol.
+type MasterPublicKey struct {
+ ProposerID types.NodeID `json:"proposer_id"`
+ Round uint64 `json:"round"`
+ Reset uint64 `json:"reset"`
+ DKGID cryptoDKG.ID `json:"dkg_id"`
+ PublicKeyShares cryptoDKG.PublicKeyShares `json:"public_key_shares"`
+ Signature crypto.Signature `json:"signature"`
+}
+
+func (d *MasterPublicKey) String() string {
+ return fmt.Sprintf("MasterPublicKey{KP:%s Round:%d Reset:%d}",
+ d.ProposerID.String()[:6],
+ d.Round,
+ d.Reset)
+}
+
+// Equal check equality of two DKG master public keys.
+func (d *MasterPublicKey) Equal(other *MasterPublicKey) bool {
+ return d.ProposerID.Equal(other.ProposerID) &&
+ d.Round == other.Round &&
+ d.Reset == other.Reset &&
+ d.DKGID.GetHexString() == other.DKGID.GetHexString() &&
+ d.PublicKeyShares.Equal(&other.PublicKeyShares) &&
+ d.Signature.Type == other.Signature.Type &&
+ bytes.Compare(d.Signature.Signature, other.Signature.Signature) == 0
+}
+
+type rlpMasterPublicKey struct {
+ ProposerID types.NodeID
+ Round uint64
+ Reset uint64
+ DKGID []byte
+ PublicKeyShares *cryptoDKG.PublicKeyShares
+ Signature crypto.Signature
+}
+
+// EncodeRLP implements rlp.Encoder
+func (d *MasterPublicKey) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, rlpMasterPublicKey{
+ ProposerID: d.ProposerID,
+ Round: d.Round,
+ Reset: d.Reset,
+ DKGID: d.DKGID.GetLittleEndian(),
+ PublicKeyShares: &d.PublicKeyShares,
+ Signature: d.Signature,
+ })
+}
+
+// DecodeRLP implements rlp.Decoder
+func (d *MasterPublicKey) DecodeRLP(s *rlp.Stream) error {
+ var dec rlpMasterPublicKey
+ if err := s.Decode(&dec); err != nil {
+ return err
+ }
+
+ id, err := cryptoDKG.BytesID(dec.DKGID)
+ if err != nil {
+ return err
+ }
+
+ *d = MasterPublicKey{
+ ProposerID: dec.ProposerID,
+ Round: dec.Round,
+ Reset: dec.Reset,
+ DKGID: id,
+ PublicKeyShares: *dec.PublicKeyShares.Move(),
+ Signature: dec.Signature,
+ }
+ return err
+}
+
+// NewMasterPublicKey returns a new MasterPublicKey instance.
+func NewMasterPublicKey() *MasterPublicKey {
+ return &MasterPublicKey{
+ PublicKeyShares: *cryptoDKG.NewEmptyPublicKeyShares(),
+ }
+}
+
+// UnmarshalJSON implements json.Unmarshaller.
+func (d *MasterPublicKey) UnmarshalJSON(data []byte) error {
+ type innertMasterPublicKey MasterPublicKey
+ d.PublicKeyShares = *cryptoDKG.NewEmptyPublicKeyShares()
+ return json.Unmarshal(data, (*innertMasterPublicKey)(d))
+}
+
+// Complaint describe a complaint in DKG protocol.
+type Complaint struct {
+ ProposerID types.NodeID `json:"proposer_id"`
+ Round uint64 `json:"round"`
+ Reset uint64 `json:"reset"`
+ PrivateShare PrivateShare `json:"private_share"`
+ Signature crypto.Signature `json:"signature"`
+}
+
+func (c *Complaint) String() string {
+ if c.IsNack() {
+ return fmt.Sprintf("DKGNackComplaint{CP:%s Round:%d Reset %d PSP:%s}",
+ c.ProposerID.String()[:6], c.Round, c.Reset,
+ c.PrivateShare.ProposerID.String()[:6])
+ }
+ return fmt.Sprintf("DKGComplaint{CP:%s Round:%d Reset %d PrivateShare:%v}",
+ c.ProposerID.String()[:6], c.Round, c.Reset, c.PrivateShare)
+}
+
+// Equal checks equality between two Complaint instances.
+func (c *Complaint) Equal(other *Complaint) bool {
+ return c.ProposerID.Equal(other.ProposerID) &&
+ c.Round == other.Round &&
+ c.Reset == other.Reset &&
+ c.PrivateShare.Equal(&other.PrivateShare) &&
+ c.Signature.Type == other.Signature.Type &&
+ bytes.Compare(c.Signature.Signature, other.Signature.Signature) == 0
+}
+
+type rlpComplaint struct {
+ ProposerID types.NodeID
+ Round uint64
+ Reset uint64
+ IsNack bool
+ PrivateShare []byte
+ Signature crypto.Signature
+}
+
+// EncodeRLP implements rlp.Encoder
+func (c *Complaint) EncodeRLP(w io.Writer) error {
+ if c.IsNack() {
+ return rlp.Encode(w, rlpComplaint{
+ ProposerID: c.ProposerID,
+ Round: c.Round,
+ Reset: c.Reset,
+ IsNack: true,
+ PrivateShare: c.PrivateShare.ProposerID.Hash[:],
+ Signature: c.Signature,
+ })
+ }
+ prvShare, err := rlp.EncodeToBytes(&c.PrivateShare)
+ if err != nil {
+ return err
+ }
+ return rlp.Encode(w, rlpComplaint{
+ ProposerID: c.ProposerID,
+ Round: c.Round,
+ Reset: c.Reset,
+ IsNack: false,
+ PrivateShare: prvShare,
+ Signature: c.Signature,
+ })
+}
+
+// DecodeRLP implements rlp.Decoder
+func (c *Complaint) DecodeRLP(s *rlp.Stream) error {
+ var dec rlpComplaint
+ if err := s.Decode(&dec); err != nil {
+ return err
+ }
+
+ var prvShare PrivateShare
+ if dec.IsNack {
+ copy(prvShare.ProposerID.Hash[:], dec.PrivateShare)
+ prvShare.Round = dec.Round
+ prvShare.Reset = dec.Reset
+ } else {
+ if err := rlp.DecodeBytes(dec.PrivateShare, &prvShare); err != nil {
+ return err
+ }
+ }
+
+ *c = Complaint{
+ ProposerID: dec.ProposerID,
+ Round: dec.Round,
+ Reset: dec.Reset,
+ PrivateShare: prvShare,
+ Signature: dec.Signature,
+ }
+ return nil
+}
+
+// IsNack returns true if it's a nack complaint in DKG protocol.
+func (c *Complaint) IsNack() bool {
+ return len(c.PrivateShare.Signature.Signature) == 0
+}
+
+// PartialSignature describe a partial signature in DKG protocol.
+type PartialSignature struct {
+ ProposerID types.NodeID `json:"proposer_id"`
+ Round uint64 `json:"round"`
+ Hash common.Hash `json:"hash"`
+ PartialSignature cryptoDKG.PartialSignature `json:"partial_signature"`
+ Signature crypto.Signature `json:"signature"`
+}
+
+// MPKReady describe a dkg ready message in DKG protocol.
+type MPKReady struct {
+ ProposerID types.NodeID `json:"proposer_id"`
+ Round uint64 `json:"round"`
+ Reset uint64 `json:"reset"`
+ Signature crypto.Signature `json:"signature"`
+}
+
+func (ready *MPKReady) String() string {
+ return fmt.Sprintf("DKGMPKReady{RP:%s Round:%d Reset:%d}",
+ ready.ProposerID.String()[:6],
+ ready.Round,
+ ready.Reset)
+}
+
+// Equal check equality of two MPKReady instances.
+func (ready *MPKReady) Equal(other *MPKReady) bool {
+ return ready.ProposerID.Equal(other.ProposerID) &&
+ ready.Round == other.Round &&
+ ready.Reset == other.Reset &&
+ ready.Signature.Type == other.Signature.Type &&
+ bytes.Compare(ready.Signature.Signature, other.Signature.Signature) == 0
+}
+
+// Finalize describe a dkg finalize message in DKG protocol.
+type Finalize struct {
+ ProposerID types.NodeID `json:"proposer_id"`
+ Round uint64 `json:"round"`
+ Reset uint64 `json:"reset"`
+ Signature crypto.Signature `json:"signature"`
+}
+
+func (final *Finalize) String() string {
+ return fmt.Sprintf("DKGFinal{FP:%s Round:%d Reset:%d}",
+ final.ProposerID.String()[:6],
+ final.Round,
+ final.Reset)
+}
+
+// Equal check equality of two Finalize instances.
+func (final *Finalize) Equal(other *Finalize) bool {
+ return final.ProposerID.Equal(other.ProposerID) &&
+ final.Round == other.Round &&
+ final.Reset == other.Reset &&
+ final.Signature.Type == other.Signature.Type &&
+ bytes.Compare(final.Signature.Signature, other.Signature.Signature) == 0
+}
+
+// Success describe a dkg success message in DKG protocol.
+type Success struct {
+ ProposerID types.NodeID `json:"proposer_id"`
+ Round uint64 `json:"round"`
+ Reset uint64 `json:"reset"`
+ Signature crypto.Signature `json:"signature"`
+}
+
+func (s *Success) String() string {
+ return fmt.Sprintf("DKGSuccess{SP:%s Round:%d Reset:%d}",
+ s.ProposerID.String()[:6],
+ s.Round,
+ s.Reset)
+}
+
+// Equal check equality of two Success instances.
+func (s *Success) Equal(other *Success) bool {
+ return s.ProposerID.Equal(other.ProposerID) &&
+ s.Round == other.Round &&
+ s.Reset == other.Reset &&
+ s.Signature.Type == other.Signature.Type &&
+ bytes.Compare(s.Signature.Signature, other.Signature.Signature) == 0
+}
+
+// GroupPublicKey is the result of DKG protocol.
+type GroupPublicKey struct {
+ Round uint64
+ QualifyIDs cryptoDKG.IDs
+ QualifyNodeIDs map[types.NodeID]struct{}
+ IDMap map[types.NodeID]cryptoDKG.ID
+ GroupPublicKey *cryptoDKG.PublicKey
+ Threshold int
+}
+
+// VerifySignature verifies if the signature is correct.
+func (gpk *GroupPublicKey) VerifySignature(
+ hash common.Hash, sig crypto.Signature) bool {
+ return gpk.GroupPublicKey.VerifySignature(hash, sig)
+}
+
+// CalcQualifyNodes returns the qualified nodes.
+func CalcQualifyNodes(
+ mpks []*MasterPublicKey, complaints []*Complaint, threshold int) (
+ qualifyIDs cryptoDKG.IDs, qualifyNodeIDs map[types.NodeID]struct{}, err error) {
+ if len(mpks) < threshold {
+ err = ErrInvalidThreshold
+ return
+ }
+
+ // Calculate qualify members.
+ disqualifyIDs := map[types.NodeID]struct{}{}
+ complaintsByID := map[types.NodeID]map[types.NodeID]struct{}{}
+ for _, complaint := range complaints {
+ if complaint.IsNack() {
+ if _, exist := complaintsByID[complaint.PrivateShare.ProposerID]; !exist {
+ complaintsByID[complaint.PrivateShare.ProposerID] =
+ make(map[types.NodeID]struct{})
+ }
+ complaintsByID[complaint.PrivateShare.ProposerID][complaint.ProposerID] =
+ struct{}{}
+ } else {
+ disqualifyIDs[complaint.PrivateShare.ProposerID] = struct{}{}
+ }
+ }
+ for nID, complaints := range complaintsByID {
+ if len(complaints) >= threshold {
+ disqualifyIDs[nID] = struct{}{}
+ }
+ }
+ qualifyIDs = make(cryptoDKG.IDs, 0, len(mpks)-len(disqualifyIDs))
+ if cap(qualifyIDs) < threshold {
+ err = ErrNotReachThreshold
+ return
+ }
+ qualifyNodeIDs = make(map[types.NodeID]struct{})
+ for _, mpk := range mpks {
+ if _, exist := disqualifyIDs[mpk.ProposerID]; exist {
+ continue
+ }
+ qualifyIDs = append(qualifyIDs, mpk.DKGID)
+ qualifyNodeIDs[mpk.ProposerID] = struct{}{}
+ }
+ return
+}
+
+// NewGroupPublicKey creats a GroupPublicKey instance.
+func NewGroupPublicKey(
+ round uint64,
+ mpks []*MasterPublicKey, complaints []*Complaint,
+ threshold int) (
+ *GroupPublicKey, error) {
+ qualifyIDs, qualifyNodeIDs, err :=
+ CalcQualifyNodes(mpks, complaints, threshold)
+ if err != nil {
+ return nil, err
+ }
+ mpkMap := make(map[cryptoDKG.ID]*MasterPublicKey, cap(qualifyIDs))
+ idMap := make(map[types.NodeID]cryptoDKG.ID)
+ for _, mpk := range mpks {
+ if _, exist := qualifyNodeIDs[mpk.ProposerID]; !exist {
+ continue
+ }
+ mpkMap[mpk.DKGID] = mpk
+ idMap[mpk.ProposerID] = mpk.DKGID
+ }
+ // Recover Group Public Key.
+ pubShares := make([]*cryptoDKG.PublicKeyShares, 0, len(qualifyIDs))
+ for _, id := range qualifyIDs {
+ pubShares = append(pubShares, &mpkMap[id].PublicKeyShares)
+ }
+ groupPK := cryptoDKG.RecoverGroupPublicKey(pubShares)
+ return &GroupPublicKey{
+ Round: round,
+ QualifyIDs: qualifyIDs,
+ QualifyNodeIDs: qualifyNodeIDs,
+ IDMap: idMap,
+ Threshold: threshold,
+ GroupPublicKey: groupPK,
+ }, nil
+}
+
+// NodePublicKeys is the result of DKG protocol.
+type NodePublicKeys struct {
+ Round uint64
+ QualifyIDs cryptoDKG.IDs
+ QualifyNodeIDs map[types.NodeID]struct{}
+ IDMap map[types.NodeID]cryptoDKG.ID
+ PublicKeys map[types.NodeID]*cryptoDKG.PublicKey
+ Threshold int
+}
+
+// NewNodePublicKeys creats a NodePublicKeys instance.
+func NewNodePublicKeys(
+ round uint64,
+ mpks []*MasterPublicKey, complaints []*Complaint,
+ threshold int) (
+ *NodePublicKeys, error) {
+ qualifyIDs, qualifyNodeIDs, err :=
+ CalcQualifyNodes(mpks, complaints, threshold)
+ if err != nil {
+ return nil, err
+ }
+ mpkMap := make(map[cryptoDKG.ID]*MasterPublicKey, cap(qualifyIDs))
+ idMap := make(map[types.NodeID]cryptoDKG.ID)
+ for _, mpk := range mpks {
+ if _, exist := qualifyNodeIDs[mpk.ProposerID]; !exist {
+ continue
+ }
+ mpkMap[mpk.DKGID] = mpk
+ idMap[mpk.ProposerID] = mpk.DKGID
+ }
+ // Recover qualify members' public key.
+ pubKeys := make(map[types.NodeID]*cryptoDKG.PublicKey, len(qualifyIDs))
+ for _, recvID := range qualifyIDs {
+ pubShares := cryptoDKG.NewEmptyPublicKeyShares()
+ for _, id := range qualifyIDs {
+ pubShare, err := mpkMap[id].PublicKeyShares.Share(recvID)
+ if err != nil {
+ return nil, err
+ }
+ if err := pubShares.AddShare(id, pubShare); err != nil {
+ return nil, err
+ }
+ }
+ pubKey, err := pubShares.RecoverPublicKey(qualifyIDs)
+ if err != nil {
+ return nil, err
+ }
+ pubKeys[mpkMap[recvID].ProposerID] = pubKey
+ }
+ return &NodePublicKeys{
+ Round: round,
+ QualifyIDs: qualifyIDs,
+ QualifyNodeIDs: qualifyNodeIDs,
+ IDMap: idMap,
+ PublicKeys: pubKeys,
+ Threshold: threshold,
+ }, nil
+}
diff --git a/vendor/github.com/byzantine-lab/dexon-consensus/core/types/message.go b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/message.go
new file mode 100644
index 000000000..0335cfaae
--- /dev/null
+++ b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/message.go
@@ -0,0 +1,24 @@
+// Copyright 2019 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus 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 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 library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package types
+
+// Msg for the network ReceiveChan.
+type Msg struct {
+ PeerID interface{}
+ Payload interface{}
+}
diff --git a/vendor/github.com/byzantine-lab/dexon-consensus/core/types/node.go b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/node.go
new file mode 100644
index 000000000..84b38a3b1
--- /dev/null
+++ b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/node.go
@@ -0,0 +1,61 @@
+// Copyright 2018 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus 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 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 library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package types
+
+import (
+ "bytes"
+ "encoding/hex"
+
+ "github.com/byzantine-lab/dexon-consensus/common"
+ "github.com/byzantine-lab/dexon-consensus/core/crypto"
+)
+
+// NodeID is the ID type for nodes.
+type NodeID struct {
+ common.Hash
+}
+
+// NewNodeID returns a NodeID with Hash set to the hash value of
+// public key.
+func NewNodeID(pubKey crypto.PublicKey) NodeID {
+ return NodeID{Hash: crypto.Keccak256Hash(pubKey.Bytes()[1:])}
+}
+
+// Equal checks if the hash representation is the same NodeID.
+func (v NodeID) Equal(v2 NodeID) bool {
+ return v.Hash == v2.Hash
+}
+
+func (v NodeID) String() string {
+ return hex.EncodeToString(v.Hash[:])[:6]
+}
+
+// NodeIDs implements sort.Interface for NodeID.
+type NodeIDs []NodeID
+
+func (v NodeIDs) Len() int {
+ return len(v)
+}
+
+func (v NodeIDs) Less(i int, j int) bool {
+ return bytes.Compare([]byte(v[i].Hash[:]), []byte(v[j].Hash[:])) == -1
+}
+
+func (v NodeIDs) Swap(i int, j int) {
+ v[i], v[j] = v[j], v[i]
+}
diff --git a/vendor/github.com/byzantine-lab/dexon-consensus/core/types/nodeset.go b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/nodeset.go
new file mode 100644
index 000000000..522bcb224
--- /dev/null
+++ b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/nodeset.go
@@ -0,0 +1,162 @@
+// Copyright 2018 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus 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 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 library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package types
+
+import (
+ "container/heap"
+ "encoding/binary"
+ "math/big"
+
+ "github.com/byzantine-lab/dexon-consensus/common"
+ "github.com/byzantine-lab/dexon-consensus/core/crypto"
+)
+
+// NodeSet is the node set structure as defined in DEXON consensus core.
+type NodeSet struct {
+ IDs map[NodeID]struct{}
+}
+
+// SubSetTarget is the sub set target for GetSubSet().
+type SubSetTarget struct {
+ data [][]byte
+}
+
+type subSetTargetType byte
+
+const (
+ targetNotarySet subSetTargetType = iota
+ targetNodeLeader
+)
+
+type nodeRank struct {
+ ID NodeID
+ rank *big.Int
+}
+
+// rankHeap is a MaxHeap structure.
+type rankHeap []*nodeRank
+
+func (h rankHeap) Len() int { return len(h) }
+func (h rankHeap) Less(i, j int) bool { return h[i].rank.Cmp(h[j].rank) > 0 }
+func (h rankHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
+func (h *rankHeap) Push(x interface{}) {
+ *h = append(*h, x.(*nodeRank))
+}
+func (h *rankHeap) Pop() interface{} {
+ old := *h
+ n := len(old)
+ x := old[n-1]
+ *h = old[0 : n-1]
+ return x
+}
+
+// NewNodeSet creates a new NodeSet instance.
+func NewNodeSet() *NodeSet {
+ return &NodeSet{
+ IDs: make(map[NodeID]struct{}),
+ }
+}
+
+// NewNodeSetFromMap creates a new NodeSet from NodeID map.
+func NewNodeSetFromMap(nodes map[NodeID]struct{}) *NodeSet {
+ nIDs := make(map[NodeID]struct{}, len(nodes))
+ for nID := range nodes {
+ nIDs[nID] = struct{}{}
+ }
+ return &NodeSet{
+ IDs: nIDs,
+ }
+}
+
+// NewNotarySetTarget is the target for getting Notary Set.
+func NewNotarySetTarget(crs common.Hash) *SubSetTarget {
+ return newTarget(targetNotarySet, crs[:])
+}
+
+// NewNodeLeaderTarget is the target for getting leader of fast BA.
+func NewNodeLeaderTarget(crs common.Hash, height uint64) *SubSetTarget {
+ binaryHeight := make([]byte, 8)
+ binary.LittleEndian.PutUint64(binaryHeight, height)
+ return newTarget(targetNodeLeader, crs[:], binaryHeight)
+}
+
+// Add a NodeID to the set.
+func (ns *NodeSet) Add(ID NodeID) {
+ ns.IDs[ID] = struct{}{}
+}
+
+// Clone the NodeSet.
+func (ns *NodeSet) Clone() *NodeSet {
+ nsCopy := NewNodeSet()
+ for ID := range ns.IDs {
+ nsCopy.Add(ID)
+ }
+ return nsCopy
+}
+
+// GetSubSet returns the subset of given target.
+func (ns *NodeSet) GetSubSet(
+ size int, target *SubSetTarget) map[NodeID]struct{} {
+ if size == 0 {
+ return make(map[NodeID]struct{})
+ }
+ h := rankHeap{}
+ idx := 0
+ for nID := range ns.IDs {
+ if idx < size {
+ h = append(h, newNodeRank(nID, target))
+ } else if idx == size {
+ heap.Init(&h)
+ }
+ if idx >= size {
+ rank := newNodeRank(nID, target)
+ if rank.rank.Cmp(h[0].rank) < 0 {
+ h[0] = rank
+ heap.Fix(&h, 0)
+ }
+ }
+ idx++
+ }
+
+ nIDs := make(map[NodeID]struct{}, size)
+ for _, rank := range h {
+ nIDs[rank.ID] = struct{}{}
+ }
+
+ return nIDs
+}
+
+func newTarget(targetType subSetTargetType, data ...[]byte) *SubSetTarget {
+ data = append(data, []byte{byte(targetType)})
+ return &SubSetTarget{
+ data: data,
+ }
+}
+
+func newNodeRank(ID NodeID, target *SubSetTarget) *nodeRank {
+ data := make([][]byte, 1, len(target.data)+1)
+ data[0] = make([]byte, len(ID.Hash))
+ copy(data[0], ID.Hash[:])
+ data = append(data, target.data...)
+ h := crypto.Keccak256Hash(data...)
+ num := new(big.Int).SetBytes(h[:])
+ return &nodeRank{
+ ID: ID,
+ rank: num,
+ }
+}
diff --git a/vendor/github.com/byzantine-lab/dexon-consensus/core/types/position.go b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/position.go
new file mode 100644
index 000000000..81d23c266
--- /dev/null
+++ b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/position.go
@@ -0,0 +1,51 @@
+// Copyright 2018 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus 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 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 library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package types
+
+import (
+ "fmt"
+)
+
+// Position describes the position in the block lattice of an entity.
+type Position struct {
+ Round uint64 `json:"round"`
+ Height uint64 `json:"height"`
+}
+
+func (pos Position) String() string {
+ return fmt.Sprintf("Position{Round:%d Height:%d}", pos.Round, pos.Height)
+}
+
+// Equal checks if two positions are equal.
+func (pos Position) Equal(other Position) bool {
+ 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 {
+ return pos.Round > other.Round ||
+ (pos.Round == other.Round && pos.Height > other.Height)
+}
+
+// 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 {
+ return pos.Round < other.Round ||
+ (pos.Round == other.Round && pos.Height < other.Height)
+}
diff --git a/vendor/github.com/byzantine-lab/dexon-consensus/core/types/vote.go b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/vote.go
new file mode 100644
index 000000000..def09293a
--- /dev/null
+++ b/vendor/github.com/byzantine-lab/dexon-consensus/core/types/vote.go
@@ -0,0 +1,100 @@
+// Copyright 2018 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus 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 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 library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package types
+
+import (
+ "fmt"
+
+ "github.com/byzantine-lab/dexon-consensus/common"
+ "github.com/byzantine-lab/dexon-consensus/core/crypto"
+ cryptoDKG "github.com/byzantine-lab/dexon-consensus/core/crypto/dkg"
+)
+
+// VoteType is the type of vote.
+type VoteType byte
+
+// VoteType enum.
+const (
+ VoteInit VoteType = iota
+ VotePreCom
+ VoteCom
+ VoteFast
+ VoteFastCom
+ // Do not add any type below MaxVoteType.
+ MaxVoteType
+)
+
+// NullBlockHash is the blockHash for ⊥ value.
+var NullBlockHash common.Hash
+
+// SkipBlockHash is the blockHash for SKIP value.
+var SkipBlockHash common.Hash
+
+func init() {
+ for idx := range SkipBlockHash {
+ SkipBlockHash[idx] = 0xff
+ }
+}
+
+// VoteHeader is the header for vote, which can be used as map keys.
+type VoteHeader struct {
+ ProposerID NodeID `json:"proposer_id"`
+ Type VoteType `json:"type"`
+ BlockHash common.Hash `json:"block_hash"`
+ Period uint64 `json:"period"`
+ Position Position `json:"position"`
+}
+
+// Vote is the vote structure defined in Crypto Shuffle Algorithm.
+type Vote struct {
+ VoteHeader `json:"header"`
+ PartialSignature cryptoDKG.PartialSignature `json:"partial_signature"`
+ Signature crypto.Signature `json:"signature"`
+}
+
+func (v *Vote) String() string {
+ 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])
+}
+
+// NewVote constructs a Vote instance with header fields.
+func NewVote(t VoteType, hash common.Hash, period uint64) *Vote {
+ return &Vote{
+ VoteHeader: VoteHeader{
+ Type: t,
+ BlockHash: hash,
+ Period: period,
+ }}
+}
+
+// Clone returns a deep copy of a vote.
+func (v *Vote) Clone() *Vote {
+ return &Vote{
+ VoteHeader: VoteHeader{
+ ProposerID: v.ProposerID,
+ Type: v.Type,
+ BlockHash: v.BlockHash,
+ Period: v.Period,
+ Position: v.Position,
+ },
+ PartialSignature: cryptoDKG.PartialSignature(
+ crypto.Signature(v.PartialSignature).Clone()),
+ Signature: v.Signature.Clone(),
+ }
+}