diff options
Diffstat (limited to 'vendor/github.com/dexon-foundation/dexon-consensus/core/types')
8 files changed, 1027 insertions, 0 deletions
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block-randomness.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block-randomness.go new file mode 100644 index 000000000..1eaa3e398 --- /dev/null +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block-randomness.go @@ -0,0 +1,43 @@ +// 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/dexon-foundation/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"` +} + +func (r *AgreementResult) String() string { + return fmt.Sprintf( + "agreementResult[%s:%s]", r.BlockHash, &r.Position) +} + +// BlockRandomnessResult describes a block randomness result +type BlockRandomnessResult struct { + BlockHash common.Hash `json:"block_hash"` + Position Position `json:"position"` + Randomness []byte `json:"randomness"` +} diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go new file mode 100644 index 000000000..bde07d518 --- /dev/null +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go @@ -0,0 +1,341 @@ +// 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" + "sort" + "sync" + "time" + + "github.com/dexon-foundation/dexon/rlp" + + "github.com/dexon-foundation/dexon-consensus/common" + "github.com/dexon-foundation/dexon-consensus/core/crypto" +) + +// 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 +) + +var ( + // blockPool is the blocks cache to reuse allocated blocks. + blockPool = sync.Pool{ + New: func() interface{} { + return &Block{} + }, + } +) + +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 +} + +// FinalizationResult represents the result of DEXON consensus algorithm. +type FinalizationResult struct { + ParentHash common.Hash `json:"parent_hash"` + Randomness []byte `json:"randomness"` + Timestamp time.Time `json:"timestamp"` + Height uint64 `json:"height"` +} + +type rlpFinalizationResult struct { + ParentHash common.Hash + Randomness []byte + Timestamp *rlpTimestamp + Height uint64 +} + +// EncodeRLP implements rlp.Encoder +func (f *FinalizationResult) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, &rlpFinalizationResult{ + ParentHash: f.ParentHash, + Randomness: f.Randomness, + Timestamp: &rlpTimestamp{f.Timestamp}, + Height: f.Height, + }) +} + +// DecodeRLP implements rlp.Decoder +func (f *FinalizationResult) DecodeRLP(s *rlp.Stream) error { + var dec rlpFinalizationResult + err := s.Decode(&dec) + if err == nil { + *f = FinalizationResult{ + ParentHash: dec.ParentHash, + Randomness: dec.Randomness, + Timestamp: dec.Timestamp.Time, + Height: dec.Height, + } + } + return err +} + +// Witness represents the consensus information on the compaction chain. +type Witness struct { + Height uint64 `json:"height"` + Data []byte `json:"data"` +} + +// RecycleBlock put unused block into cache, which might be reused if +// not garbage collected. +func RecycleBlock(b *Block) { + blockPool.Put(b) +} + +// NewBlock initiate a block. +func NewBlock() (b *Block) { + b = blockPool.Get().(*Block) + b.Acks = b.Acks[:0] + return +} + +// 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"` + Acks common.SortedHashes `json:"acks"` + Payload []byte `json:"payload"` + PayloadHash common.Hash `json:"payload_hash"` + Witness Witness `json:"witness"` + Finalization FinalizationResult `json:"finalization"` + 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 + Acks common.SortedHashes + Payload []byte + PayloadHash common.Hash + Witness *Witness + Finalization *FinalizationResult + 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}, + Acks: b.Acks, + Payload: b.Payload, + PayloadHash: b.PayloadHash, + Witness: &b.Witness, + Finalization: &b.Finalization, + 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, + Acks: dec.Acks, + Payload: dec.Payload, + PayloadHash: dec.PayloadHash, + Witness: *dec.Witness, + Finalization: *dec.Finalization, + Signature: dec.Signature, + CRSSignature: dec.CRSSignature, + } + } + return err +} + +func (b *Block) String() string { + return fmt.Sprintf("Block(%v:%d:%d)", b.Hash.String()[:6], + b.Position.ChainID, b.Position.Height) +} + +// Clone returns a deep copy of a block. +func (b *Block) Clone() (bcopy *Block) { + bcopy = NewBlock() + bcopy.ProposerID = b.ProposerID + bcopy.ParentHash = b.ParentHash + bcopy.Hash = b.Hash + bcopy.Position.Round = b.Position.Round + bcopy.Position.ChainID = b.Position.ChainID + bcopy.Position.Height = b.Position.Height + bcopy.Signature = b.Signature.Clone() + bcopy.CRSSignature = b.CRSSignature.Clone() + bcopy.Finalization.ParentHash = b.Finalization.ParentHash + bcopy.Finalization.Timestamp = b.Finalization.Timestamp + bcopy.Finalization.Height = b.Finalization.Height + bcopy.Witness.Height = b.Witness.Height + bcopy.Witness.Data = make([]byte, len(b.Witness.Data)) + copy(bcopy.Witness.Data, b.Witness.Data) + bcopy.Timestamp = b.Timestamp + bcopy.Acks = make(common.SortedHashes, len(b.Acks)) + copy(bcopy.Acks, b.Acks) + bcopy.Payload = make([]byte, len(b.Payload)) + copy(bcopy.Payload, b.Payload) + bcopy.PayloadHash = b.PayloadHash + bcopy.Finalization.Randomness = make([]byte, len(b.Finalization.Randomness)) + copy(bcopy.Finalization.Randomness, b.Finalization.Randomness) + return +} + +// IsGenesis checks if the block is a genesisBlock +func (b *Block) IsGenesis() bool { + return b.Position.Height == 0 && b.ParentHash == common.Hash{} +} + +// IsFinalized checks if the finalization data is ready. +func (b *Block) IsFinalized() bool { + return b.Finalization.Height != 0 +} + +// IsEmpty checks if the block is an 'empty block'. +func (b *Block) IsEmpty() bool { + return b.ProposerID.Hash == common.Hash{} +} + +// IsAcking checks if a block acking another by it's hash. +func (b *Block) IsAcking(hash common.Hash) bool { + idx := sort.Search(len(b.Acks), func(i int) bool { + return bytes.Compare(b.Acks[i][:], hash[:]) >= 0 + }) + return !(idx == len(b.Acks) || b.Acks[idx] != 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] +} + +// ByPosition is the helper type for sorting slice of blocks by position. +type ByPosition []*Block + +// Len implements Len method in sort.Sort interface. +func (bs ByPosition) Len() int { + return len(bs) +} + +// Less implements Less method in sort.Sort interface. +func (bs ByPosition) Less(i int, j int) bool { + return bs[j].Position.Newer(&bs[i].Position) +} + +// Swap implements Swap method in sort.Sort interface. +func (bs ByPosition) Swap(i int, j int) { + bs[i], bs[j] = bs[j], bs[i] +} + +// Push implements Push method in heap interface. +func (bs *ByPosition) Push(x interface{}) { + *bs = append(*bs, x.(*Block)) +} + +// Pop implements Pop method in heap interface. +func (bs *ByPosition) Pop() (ret interface{}) { + n := len(*bs) + *bs, ret = (*bs)[0:n-1], (*bs)[n-1] + return +} + +// ByFinalizationHeight is the helper type for sorting slice of blocks by +// finalization height. +type ByFinalizationHeight []*Block + +// Len implements Len method in sort.Sort interface. +func (bs ByFinalizationHeight) Len() int { + return len(bs) +} + +// Less implements Less method in sort.Sort interface. +func (bs ByFinalizationHeight) Less(i int, j int) bool { + return bs[i].Finalization.Height < bs[j].Finalization.Height +} + +// Swap implements Swap method in sort.Sort interface. +func (bs ByFinalizationHeight) Swap(i int, j int) { + bs[i], bs[j] = bs[j], bs[i] +} + +// Push implements Push method in heap interface. +func (bs *ByFinalizationHeight) Push(x interface{}) { + *bs = append(*bs, x.(*Block)) +} + +// Pop implements Pop method in heap interface. +func (bs *ByFinalizationHeight) Pop() (ret interface{}) { + n := len(*bs) + *bs, ret = (*bs)[0:n-1], (*bs)[n-1] + return +} diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/config.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/config.go new file mode 100644 index 000000000..975eec9cb --- /dev/null +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/config.go @@ -0,0 +1,109 @@ +// 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" + "math" + "time" +) + +// Config stands for Current Configuration Parameters. +type Config struct { + // Network related. + NumChains uint32 + + // Lambda related. + LambdaBA time.Duration + LambdaDKG time.Duration + + // Total ordering related. + K int + PhiRatio float32 + + // Set related. + NotarySetSize uint32 + DKGSetSize uint32 + + // Time related. + RoundInterval time.Duration + MinBlockInterval time.Duration + MaxBlockInterval time.Duration +} + +// Clone return a copied configuration. +func (c *Config) Clone() *Config { + return &Config{ + NumChains: c.NumChains, + LambdaBA: c.LambdaBA, + LambdaDKG: c.LambdaDKG, + K: c.K, + PhiRatio: c.PhiRatio, + NotarySetSize: c.NotarySetSize, + DKGSetSize: c.DKGSetSize, + RoundInterval: c.RoundInterval, + MinBlockInterval: c.MinBlockInterval, + MaxBlockInterval: c.MaxBlockInterval, + } +} + +// Bytes returns []byte representation of Config. +func (c *Config) Bytes() []byte { + binaryNumChains := make([]byte, 4) + binary.LittleEndian.PutUint32(binaryNumChains, c.NumChains) + + binaryLambdaBA := make([]byte, 8) + binary.LittleEndian.PutUint64( + binaryLambdaBA, uint64(c.LambdaBA.Nanoseconds())) + binaryLambdaDKG := make([]byte, 8) + binary.LittleEndian.PutUint64( + binaryLambdaDKG, uint64(c.LambdaDKG.Nanoseconds())) + + binaryK := make([]byte, 4) + binary.LittleEndian.PutUint32(binaryK, uint32(c.K)) + binaryPhiRatio := make([]byte, 4) + binary.LittleEndian.PutUint32(binaryPhiRatio, math.Float32bits(c.PhiRatio)) + + binaryNotarySetSize := make([]byte, 4) + binary.LittleEndian.PutUint32(binaryNotarySetSize, c.NotarySetSize) + binaryDKGSetSize := make([]byte, 4) + binary.LittleEndian.PutUint32(binaryDKGSetSize, c.DKGSetSize) + + binaryRoundInterval := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryRoundInterval, + uint64(c.RoundInterval.Nanoseconds())) + binaryMinBlockInterval := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryMinBlockInterval, + uint64(c.MinBlockInterval.Nanoseconds())) + binaryMaxBlockInterval := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryMaxBlockInterval, + uint64(c.MaxBlockInterval.Nanoseconds())) + + enc := make([]byte, 0, 40) + enc = append(enc, binaryNumChains...) + enc = append(enc, binaryLambdaBA...) + enc = append(enc, binaryLambdaDKG...) + enc = append(enc, binaryK...) + enc = append(enc, binaryPhiRatio...) + enc = append(enc, binaryNotarySetSize...) + enc = append(enc, binaryDKGSetSize...) + enc = append(enc, binaryRoundInterval...) + enc = append(enc, binaryMinBlockInterval...) + enc = append(enc, binaryMaxBlockInterval...) + return enc +} diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/dkg/dkg.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/dkg/dkg.go new file mode 100644 index 000000000..4053c5a28 --- /dev/null +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/dkg/dkg.go @@ -0,0 +1,194 @@ +// 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/dexon-foundation/dexon/rlp" + + "github.com/dexon-foundation/dexon-consensus/common" + "github.com/dexon-foundation/dexon-consensus/core/crypto" + cryptoDKG "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg" + "github.com/dexon-foundation/dexon-consensus/core/types" +) + +// 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"` + 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.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"` + 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[%s:%d]", + d.ProposerID.String()[:6], + d.Round) +} + +// 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.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 + 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, + 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, + DKGID: id, + PublicKeyShares: *dec.PublicKeyShares, + 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"` + PrivateShare PrivateShare `json:"private_share"` + Signature crypto.Signature `json:"signature"` +} + +func (c *Complaint) String() string { + if c.IsNack() { + return fmt.Sprintf("DKGNackComplaint[%s:%d]%s", + c.ProposerID.String()[:6], c.Round, + c.PrivateShare.ProposerID.String()[:6]) + } + return fmt.Sprintf("Complaint[%s:%d]%v", + c.ProposerID.String()[:6], c.Round, 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.PrivateShare.Equal(&other.PrivateShare) && + c.Signature.Type == other.Signature.Type && + bytes.Compare(c.Signature.Signature, other.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"` +} + +// Finalize describe a dig finalize message in DKG protocol. +type Finalize struct { + ProposerID types.NodeID `json:"proposer_id"` + Round uint64 `json:"round"` + Signature crypto.Signature `json:"signature"` +} + +func (final *Finalize) String() string { + return fmt.Sprintf("DKGFinal[%s:%d]", + final.ProposerID.String()[:6], + final.Round) +} + +// 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.Signature.Type == other.Signature.Type && + bytes.Compare(final.Signature.Signature, other.Signature.Signature) == 0 +} + +// IsNack returns true if it's a nack complaint in DKG protocol. +func (c *Complaint) IsNack() bool { + return len(c.PrivateShare.Signature.Signature) == 0 +} diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/node.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/node.go new file mode 100644 index 000000000..2c90f65c8 --- /dev/null +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/node.go @@ -0,0 +1,56 @@ +// 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" + + "github.com/dexon-foundation/dexon-consensus/common" + "github.com/dexon-foundation/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 +} + +// 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/dexon-foundation/dexon-consensus/core/types/nodeset.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/nodeset.go new file mode 100644 index 000000000..3222b3c2f --- /dev/null +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/nodeset.go @@ -0,0 +1,145 @@ +// 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/dexon-foundation/dexon-consensus/common" + "github.com/dexon-foundation/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 *big.Int + +type subSetTargetType byte + +const ( + targetNotarySet subSetTargetType = iota + targetDKGSet +) + +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{}), + } +} + +// NewNotarySetTarget is the target for getting Notary Set. +func NewNotarySetTarget(crs common.Hash, chainID uint32) SubSetTarget { + binaryChainID := make([]byte, 4) + binary.LittleEndian.PutUint32(binaryChainID, chainID) + + return newTarget(targetNotarySet, crs[:], binaryChainID) +} + +// NewDKGSetTarget is the target for getting DKG Set. +func NewDKGSetTarget(crs common.Hash) SubSetTarget { + return newTarget(targetDKGSet, crs[:]) +} + +// 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{} { + 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)}) + h := crypto.Keccak256Hash(data...) + num := big.NewInt(0) + num.SetBytes(h[:]) + return SubSetTarget(num) +} + +func newNodeRank(ID NodeID, target SubSetTarget) *nodeRank { + num := big.NewInt(0) + num.SetBytes(ID.Hash[:]) + num.Abs(num.Sub((*big.Int)(target), num)) + return &nodeRank{ + ID: ID, + rank: num, + } +} diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/position.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/position.go new file mode 100644 index 000000000..404f3035e --- /dev/null +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/position.go @@ -0,0 +1,74 @@ +// 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 { + ChainID uint32 `json:"chain_id"` + Round uint64 `json:"round"` + Height uint64 `json:"height"` +} + +func (pos *Position) String() string { + return fmt.Sprintf("pos[%d:%d:%d]", pos.Round, pos.ChainID, pos.Height) +} + +// Equal checks if two positions are equal, it panics when their chainIDs +// are different. +func (pos *Position) Equal(other *Position) bool { + if pos.ChainID != other.ChainID { + panic(fmt.Errorf("unexpected chainID %d, should be %d", + other.ChainID, pos.ChainID)) + } + 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 { + if pos.ChainID != other.ChainID { + panic(fmt.Errorf("unexpected chainID %d, should be %d", + other.ChainID, pos.ChainID)) + } + 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 { + if pos.ChainID != other.ChainID { + panic(fmt.Errorf("unexpected chainID %d, should be %d", + other.ChainID, pos.ChainID)) + } + return pos.Round < other.Round || + (pos.Round == other.Round && pos.Height < other.Height) +} + +// Clone a position instance. +func (pos *Position) Clone() *Position { + return &Position{ + ChainID: pos.ChainID, + Round: pos.Round, + Height: pos.Height, + } +} diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/vote.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/vote.go new file mode 100644 index 000000000..32fb8982d --- /dev/null +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/vote.go @@ -0,0 +1,65 @@ +// 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/dexon-foundation/dexon-consensus/common" + "github.com/dexon-foundation/dexon-consensus/core/crypto" +) + +// VoteType is the type of vote. +type VoteType byte + +// VoteType enum. +const ( + VoteInit VoteType = iota + VotePreCom + VoteCom + // Do not add any type below MaxVoteType. + MaxVoteType +) + +// Vote is the vote structure defined in Crypto Shuffle Algorithm. +type Vote struct { + ProposerID NodeID `json:"proposer_id"` + Type VoteType `json:"type"` + BlockHash common.Hash `json:"block_hash"` + Period uint64 `json:"period"` + Position Position `json:"position"` + Signature crypto.Signature `json:"signature"` +} + +func (v *Vote) String() string { + return fmt.Sprintf("Vote[%s:%d:%d](%d:%d):%s", + v.ProposerID.String()[:6], v.Position.ChainID, v.Position.Height, + 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, + Position: v.Position, + Signature: v.Signature.Clone(), + } +} |