github.com/annchain/OG@v0.0.9/consensus/bft/message.go (about)

     1  // Copyright © 2019 Annchain Authors <EMAIL ADDRESS>
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  package bft
    15  
    16  import (
    17  	"crypto/sha256"
    18  	"fmt"
    19  	"github.com/annchain/OG/arefactor/og/types"
    20  	"github.com/annchain/OG/common/byteutil"
    21  	"github.com/annchain/OG/common/hexutil"
    22  	"github.com/tinylib/msgp/msgp"
    23  )
    24  
    25  //go:generate msgp
    26  
    27  type Signable interface {
    28  	SignatureTargets() []byte
    29  }
    30  
    31  // OgMessage is the message that can be convert to BinaryMessage
    32  type BftMessage interface {
    33  	Signable
    34  	GetType() BftMessageType
    35  	ProvideHeight() uint64
    36  	String() string
    37  }
    38  
    39  // HeightRound is the current progress of the consensus.
    40  // Height is the block height, round is the sub-progress if no consensus can be easily reached
    41  //msgp:tuple HeightRound
    42  type HeightRound struct {
    43  	Height uint64
    44  	Round  int
    45  }
    46  
    47  func (h *HeightRound) String() string {
    48  	return fmt.Sprintf("[%d-%d]", h.Height, h.Round)
    49  }
    50  
    51  // IsAfter judges whether self is a higher HeightRound
    52  func (h *HeightRound) IsAfter(o HeightRound) bool {
    53  	return h.Height > o.Height ||
    54  		(h.Height == o.Height && h.Round > o.Round)
    55  }
    56  
    57  // IsAfterOrEqual judges whether self is a higher or equal HeightRound
    58  func (h *HeightRound) IsAfterOrEqual(o HeightRound) bool {
    59  	return h.Height > o.Height ||
    60  		(h.Height == o.Height && h.Round >= o.Round)
    61  }
    62  
    63  // IsAfterOrEqual judges whether self is a lower HeightRound
    64  func (h *HeightRound) IsBefore(o HeightRound) bool {
    65  	return h.Height < o.Height ||
    66  		(h.Height == o.Height && h.Round < o.Round)
    67  }
    68  
    69  type BftMessageType uint16
    70  
    71  func (m BftMessageType) String() string {
    72  	switch m {
    73  	case BftMessageTypeProposal:
    74  		return "BFTProposal"
    75  	case BftMessageTypePreVote:
    76  		return "BFTPreVote"
    77  	case BftMessageTypePreCommit:
    78  		return "BFTPreCommit"
    79  	default:
    80  		return "BFTUnknown"
    81  	}
    82  }
    83  
    84  const (
    85  	BftMessageTypeProposal BftMessageType = iota + 100
    86  	BftMessageTypePreVote
    87  	BftMessageTypePreCommit
    88  )
    89  
    90  //msgp:tuple BftBasicInfo
    91  type BftBasicInfo struct {
    92  	SourceId       uint16
    93  	HeightRound    HeightRound
    94  	PublicKeyBytes hexutil.Bytes
    95  }
    96  
    97  func (b *BftBasicInfo) ProvideHeight() uint64 {
    98  	return b.HeightRound.Height
    99  }
   100  
   101  //msgp:tuple BftMessageProposal
   102  type BftMessageProposal struct {
   103  	BftBasicInfo
   104  	Value      Proposal //TODO
   105  	ValidRound int
   106  }
   107  
   108  func (m *BftMessageProposal) GetType() BftMessageType {
   109  	return BftMessageTypeProposal
   110  }
   111  
   112  func (m *BftMessageProposal) PublicKey() []byte {
   113  	return m.PublicKeyBytes
   114  }
   115  
   116  //msgp:tuple BftMessagePreVote
   117  type BftMessagePreVote struct {
   118  	BftBasicInfo
   119  	Idv *types.Hash // ID of the proposal, usually be the hash of the proposal
   120  }
   121  
   122  func (z *BftMessagePreVote) GetType() BftMessageType {
   123  	return BftMessageTypePreVote
   124  }
   125  
   126  func (z *BftMessagePreVote) PublicKey() []byte {
   127  	return z.PublicKeyBytes
   128  }
   129  
   130  //msgp:tuple BftMessagePreCommit
   131  type BftMessagePreCommit struct {
   132  	BftBasicInfo
   133  	Idv          *types.Hash // ID of the proposal, usually be the hash of the proposal
   134  	BlsSignature hexutil.Bytes
   135  }
   136  
   137  func (z *BftMessagePreCommit) PublicKey() []byte {
   138  	return z.PublicKeyBytes
   139  }
   140  
   141  func (z *BftMessagePreCommit) GetType() BftMessageType {
   142  	return BftMessageTypePreCommit
   143  }
   144  
   145  func (m BftBasicInfo) String() string {
   146  	return fmt.Sprintf("SourceId:%d, hr:%d", m.SourceId, m.HeightRound)
   147  }
   148  
   149  func (m BftMessageProposal) String() string {
   150  	return fmt.Sprintf("bm %s, value %s", m.BftBasicInfo, m.Value)
   151  }
   152  
   153  func (m BftMessagePreVote) String() string {
   154  	return fmt.Sprintf("bm %s, idv %s", m.BftBasicInfo, m.Idv)
   155  }
   156  
   157  func (m BftMessagePreCommit) String() string {
   158  	return fmt.Sprintf("bm %s, idv %s", m.BftBasicInfo, m.Idv)
   159  }
   160  
   161  func (m *BftMessagePreVote) SignatureTargets() []byte {
   162  	w := byteutil.NewBinaryWriter()
   163  	if m.Idv != nil {
   164  		w.Write(m.Idv.Bytes)
   165  	}
   166  	w.Write(m.HeightRound.Height, uint64(m.HeightRound.Round), m.SourceId)
   167  	return w.Bytes()
   168  }
   169  
   170  func (m *BftMessagePreCommit) SignatureTargets() []byte {
   171  	w := byteutil.NewBinaryWriter()
   172  	w.Write(m.BlsSignature)
   173  	return w.Bytes()
   174  }
   175  
   176  func (m *BftMessagePreCommit) BlsSignatureTargets() []byte {
   177  	w := byteutil.NewBinaryWriter()
   178  	if m.Idv != nil {
   179  		w.Write(m.Idv.Bytes)
   180  	}
   181  	w.Write(m.HeightRound.Height, uint64(m.HeightRound.Round), m.SourceId)
   182  	return w.Bytes()
   183  }
   184  
   185  func (m *BftMessageProposal) SignatureTargets() []byte {
   186  	w := byteutil.NewBinaryWriter()
   187  	if idv := m.Value.GetId(); idv != nil {
   188  		w.Write(idv.Bytes)
   189  	}
   190  	//w.Write(m.HeightRound.Height, uint64(m.HeightRound.Round), m.SourceId, uint64(m.ValidRound))
   191  	w.Write(m.HeightRound.Height, uint64(m.HeightRound.Round), m.SourceId)
   192  	return w.Bytes()
   193  }
   194  
   195  type MsgpEnabled interface {
   196  	msgp.MarshalSizer
   197  	msgp.Unmarshaler
   198  	msgp.Decodable
   199  	msgp.Encodable
   200  }
   201  type Proposal interface {
   202  	MsgpEnabled
   203  	Equal(Proposal) bool
   204  	GetId() *types.Hash
   205  	String() string
   206  	Copy() Proposal
   207  }
   208  
   209  //StringProposal is for test
   210  //msgp:tuple StringProposal
   211  type StringProposal struct {
   212  	Content string
   213  }
   214  
   215  func (s StringProposal) Equal(o Proposal) bool {
   216  	v, ok := o.(*StringProposal)
   217  	if !ok || v == nil {
   218  		return false
   219  	}
   220  	return s.Content == v.Content
   221  }
   222  
   223  func (s StringProposal) Copy() Proposal {
   224  	var r StringProposal
   225  	r.Content = s.Content
   226  	return &r
   227  }
   228  
   229  func (s StringProposal) GetId() *types.Hash {
   230  	h := sha256.New()
   231  	h.Write([]byte(s.Content))
   232  	sum := h.Sum(nil)
   233  	hash := types.Hash{}
   234  	hash.MustSetBytes(sum, types.PaddingNone)
   235  	return &hash
   236  }
   237  
   238  func (s StringProposal) String() string {
   239  	return s.Content
   240  }
   241  
   242  type ConsensusDecision Proposal