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