github.com/516108736/tendermint@v0.36.0/consensus/msgs.go (about) 1 package consensus 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/gogo/protobuf/proto" 8 9 cstypes "github.com/tendermint/tendermint/consensus/types" 10 "github.com/tendermint/tendermint/libs/bits" 11 tmmath "github.com/tendermint/tendermint/libs/math" 12 "github.com/tendermint/tendermint/p2p" 13 tmcons "github.com/tendermint/tendermint/proto/tendermint/consensus" 14 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 15 "github.com/tendermint/tendermint/types" 16 ) 17 18 // MsgToProto takes a consensus message type and returns the proto defined consensus message 19 func MsgToProto(msg Message) (*tmcons.Message, error) { 20 if msg == nil { 21 return nil, errors.New("consensus: message is nil") 22 } 23 var pb tmcons.Message 24 25 switch msg := msg.(type) { 26 case *NewRoundStepMessage: 27 pb = tmcons.Message{ 28 Sum: &tmcons.Message_NewRoundStep{ 29 NewRoundStep: &tmcons.NewRoundStep{ 30 Height: msg.Height, 31 Round: msg.Round, 32 Step: uint32(msg.Step), 33 SecondsSinceStartTime: msg.SecondsSinceStartTime, 34 LastCommitRound: msg.LastCommitRound, 35 }, 36 }, 37 } 38 case *NewValidBlockMessage: 39 pbPartSetHeader := msg.BlockPartSetHeader.ToProto() 40 pbBits := msg.BlockParts.ToProto() 41 pb = tmcons.Message{ 42 Sum: &tmcons.Message_NewValidBlock{ 43 NewValidBlock: &tmcons.NewValidBlock{ 44 Height: msg.Height, 45 Round: msg.Round, 46 BlockPartSetHeader: pbPartSetHeader, 47 BlockParts: pbBits, 48 IsCommit: msg.IsCommit, 49 }, 50 }, 51 } 52 case *ProposalMessage: 53 pbP := msg.Proposal.ToProto() 54 pb = tmcons.Message{ 55 Sum: &tmcons.Message_Proposal{ 56 Proposal: &tmcons.Proposal{ 57 Proposal: *pbP, 58 }, 59 }, 60 } 61 case *ProposalPOLMessage: 62 pbBits := msg.ProposalPOL.ToProto() 63 pb = tmcons.Message{ 64 Sum: &tmcons.Message_ProposalPol{ 65 ProposalPol: &tmcons.ProposalPOL{ 66 Height: msg.Height, 67 ProposalPolRound: msg.ProposalPOLRound, 68 ProposalPol: *pbBits, 69 }, 70 }, 71 } 72 case *BlockPartMessage: 73 parts, err := msg.Part.ToProto() 74 if err != nil { 75 return nil, fmt.Errorf("msg to proto error: %w", err) 76 } 77 pb = tmcons.Message{ 78 Sum: &tmcons.Message_BlockPart{ 79 BlockPart: &tmcons.BlockPart{ 80 Height: msg.Height, 81 Round: msg.Round, 82 Part: *parts, 83 }, 84 }, 85 } 86 case *VoteMessage: 87 vote := msg.Vote.ToProto() 88 pb = tmcons.Message{ 89 Sum: &tmcons.Message_Vote{ 90 Vote: &tmcons.Vote{ 91 Vote: vote, 92 }, 93 }, 94 } 95 case *HasVoteMessage: 96 pb = tmcons.Message{ 97 Sum: &tmcons.Message_HasVote{ 98 HasVote: &tmcons.HasVote{ 99 Height: msg.Height, 100 Round: msg.Round, 101 Type: msg.Type, 102 Index: msg.Index, 103 }, 104 }, 105 } 106 case *VoteSetMaj23Message: 107 bi := msg.BlockID.ToProto() 108 pb = tmcons.Message{ 109 Sum: &tmcons.Message_VoteSetMaj23{ 110 VoteSetMaj23: &tmcons.VoteSetMaj23{ 111 Height: msg.Height, 112 Round: msg.Round, 113 Type: msg.Type, 114 BlockID: bi, 115 }, 116 }, 117 } 118 case *VoteSetBitsMessage: 119 bi := msg.BlockID.ToProto() 120 bits := msg.Votes.ToProto() 121 122 vsb := &tmcons.Message_VoteSetBits{ 123 VoteSetBits: &tmcons.VoteSetBits{ 124 Height: msg.Height, 125 Round: msg.Round, 126 Type: msg.Type, 127 BlockID: bi, 128 }, 129 } 130 131 if bits != nil { 132 vsb.VoteSetBits.Votes = *bits 133 } 134 135 pb = tmcons.Message{ 136 Sum: vsb, 137 } 138 139 default: 140 return nil, fmt.Errorf("consensus: message not recognized: %T", msg) 141 } 142 143 return &pb, nil 144 } 145 146 // MsgFromProto takes a consensus proto message and returns the native go type 147 func MsgFromProto(msg *tmcons.Message) (Message, error) { 148 if msg == nil { 149 return nil, errors.New("consensus: nil message") 150 } 151 var pb Message 152 153 switch msg := msg.Sum.(type) { 154 case *tmcons.Message_NewRoundStep: 155 rs, err := tmmath.SafeConvertUint8(int64(msg.NewRoundStep.Step)) 156 // deny message based on possible overflow 157 if err != nil { 158 return nil, fmt.Errorf("denying message due to possible overflow: %w", err) 159 } 160 pb = &NewRoundStepMessage{ 161 Height: msg.NewRoundStep.Height, 162 Round: msg.NewRoundStep.Round, 163 Step: cstypes.RoundStepType(rs), 164 SecondsSinceStartTime: msg.NewRoundStep.SecondsSinceStartTime, 165 LastCommitRound: msg.NewRoundStep.LastCommitRound, 166 } 167 case *tmcons.Message_NewValidBlock: 168 pbPartSetHeader, err := types.PartSetHeaderFromProto(&msg.NewValidBlock.BlockPartSetHeader) 169 if err != nil { 170 return nil, fmt.Errorf("parts to proto error: %w", err) 171 } 172 173 pbBits := new(bits.BitArray) 174 pbBits.FromProto(msg.NewValidBlock.BlockParts) 175 176 pb = &NewValidBlockMessage{ 177 Height: msg.NewValidBlock.Height, 178 Round: msg.NewValidBlock.Round, 179 BlockPartSetHeader: *pbPartSetHeader, 180 BlockParts: pbBits, 181 IsCommit: msg.NewValidBlock.IsCommit, 182 } 183 case *tmcons.Message_Proposal: 184 pbP, err := types.ProposalFromProto(&msg.Proposal.Proposal) 185 if err != nil { 186 return nil, fmt.Errorf("proposal msg to proto error: %w", err) 187 } 188 189 pb = &ProposalMessage{ 190 Proposal: pbP, 191 } 192 case *tmcons.Message_ProposalPol: 193 pbBits := new(bits.BitArray) 194 pbBits.FromProto(&msg.ProposalPol.ProposalPol) 195 pb = &ProposalPOLMessage{ 196 Height: msg.ProposalPol.Height, 197 ProposalPOLRound: msg.ProposalPol.ProposalPolRound, 198 ProposalPOL: pbBits, 199 } 200 case *tmcons.Message_BlockPart: 201 parts, err := types.PartFromProto(&msg.BlockPart.Part) 202 if err != nil { 203 return nil, fmt.Errorf("blockpart msg to proto error: %w", err) 204 } 205 pb = &BlockPartMessage{ 206 Height: msg.BlockPart.Height, 207 Round: msg.BlockPart.Round, 208 Part: parts, 209 } 210 case *tmcons.Message_Vote: 211 vote, err := types.VoteFromProto(msg.Vote.Vote) 212 if err != nil { 213 return nil, fmt.Errorf("vote msg to proto error: %w", err) 214 } 215 216 pb = &VoteMessage{ 217 Vote: vote, 218 } 219 case *tmcons.Message_HasVote: 220 pb = &HasVoteMessage{ 221 Height: msg.HasVote.Height, 222 Round: msg.HasVote.Round, 223 Type: msg.HasVote.Type, 224 Index: msg.HasVote.Index, 225 } 226 case *tmcons.Message_VoteSetMaj23: 227 bi, err := types.BlockIDFromProto(&msg.VoteSetMaj23.BlockID) 228 if err != nil { 229 return nil, fmt.Errorf("voteSetMaj23 msg to proto error: %w", err) 230 } 231 pb = &VoteSetMaj23Message{ 232 Height: msg.VoteSetMaj23.Height, 233 Round: msg.VoteSetMaj23.Round, 234 Type: msg.VoteSetMaj23.Type, 235 BlockID: *bi, 236 } 237 case *tmcons.Message_VoteSetBits: 238 bi, err := types.BlockIDFromProto(&msg.VoteSetBits.BlockID) 239 if err != nil { 240 return nil, fmt.Errorf("voteSetBits msg to proto error: %w", err) 241 } 242 bits := new(bits.BitArray) 243 bits.FromProto(&msg.VoteSetBits.Votes) 244 245 pb = &VoteSetBitsMessage{ 246 Height: msg.VoteSetBits.Height, 247 Round: msg.VoteSetBits.Round, 248 Type: msg.VoteSetBits.Type, 249 BlockID: *bi, 250 Votes: bits, 251 } 252 default: 253 return nil, fmt.Errorf("consensus: message not recognized: %T", msg) 254 } 255 256 if err := pb.ValidateBasic(); err != nil { 257 return nil, err 258 } 259 260 return pb, nil 261 } 262 263 // MustEncode takes the reactors msg, makes it proto and marshals it 264 // this mimics `MustMarshalBinaryBare` in that is panics on error 265 func MustEncode(msg Message) []byte { 266 pb, err := MsgToProto(msg) 267 if err != nil { 268 panic(err) 269 } 270 enc, err := proto.Marshal(pb) 271 if err != nil { 272 panic(err) 273 } 274 return enc 275 } 276 277 // WALToProto takes a WAL message and return a proto walMessage and error 278 func WALToProto(msg WALMessage) (*tmcons.WALMessage, error) { 279 var pb tmcons.WALMessage 280 281 switch msg := msg.(type) { 282 case types.EventDataRoundState: 283 pb = tmcons.WALMessage{ 284 Sum: &tmcons.WALMessage_EventDataRoundState{ 285 EventDataRoundState: &tmproto.EventDataRoundState{ 286 Height: msg.Height, 287 Round: msg.Round, 288 Step: msg.Step, 289 }, 290 }, 291 } 292 case msgInfo: 293 consMsg, err := MsgToProto(msg.Msg) 294 if err != nil { 295 return nil, err 296 } 297 pb = tmcons.WALMessage{ 298 Sum: &tmcons.WALMessage_MsgInfo{ 299 MsgInfo: &tmcons.MsgInfo{ 300 Msg: *consMsg, 301 PeerID: string(msg.PeerID), 302 }, 303 }, 304 } 305 case timeoutInfo: 306 pb = tmcons.WALMessage{ 307 Sum: &tmcons.WALMessage_TimeoutInfo{ 308 TimeoutInfo: &tmcons.TimeoutInfo{ 309 Duration: msg.Duration, 310 Height: msg.Height, 311 Round: msg.Round, 312 Step: uint32(msg.Step), 313 }, 314 }, 315 } 316 case EndHeightMessage: 317 pb = tmcons.WALMessage{ 318 Sum: &tmcons.WALMessage_EndHeight{ 319 EndHeight: &tmcons.EndHeight{ 320 Height: msg.Height, 321 }, 322 }, 323 } 324 default: 325 return nil, fmt.Errorf("to proto: wal message not recognized: %T", msg) 326 } 327 328 return &pb, nil 329 } 330 331 // WALFromProto takes a proto wal message and return a consensus walMessage and error 332 func WALFromProto(msg *tmcons.WALMessage) (WALMessage, error) { 333 if msg == nil { 334 return nil, errors.New("nil WAL message") 335 } 336 var pb WALMessage 337 338 switch msg := msg.Sum.(type) { 339 case *tmcons.WALMessage_EventDataRoundState: 340 pb = types.EventDataRoundState{ 341 Height: msg.EventDataRoundState.Height, 342 Round: msg.EventDataRoundState.Round, 343 Step: msg.EventDataRoundState.Step, 344 } 345 case *tmcons.WALMessage_MsgInfo: 346 walMsg, err := MsgFromProto(&msg.MsgInfo.Msg) 347 if err != nil { 348 return nil, fmt.Errorf("msgInfo from proto error: %w", err) 349 } 350 pb = msgInfo{ 351 Msg: walMsg, 352 PeerID: p2p.ID(msg.MsgInfo.PeerID), 353 } 354 355 case *tmcons.WALMessage_TimeoutInfo: 356 tis, err := tmmath.SafeConvertUint8(int64(msg.TimeoutInfo.Step)) 357 // deny message based on possible overflow 358 if err != nil { 359 return nil, fmt.Errorf("denying message due to possible overflow: %w", err) 360 } 361 pb = timeoutInfo{ 362 Duration: msg.TimeoutInfo.Duration, 363 Height: msg.TimeoutInfo.Height, 364 Round: msg.TimeoutInfo.Round, 365 Step: cstypes.RoundStepType(tis), 366 } 367 return pb, nil 368 case *tmcons.WALMessage_EndHeight: 369 pb := EndHeightMessage{ 370 Height: msg.EndHeight.Height, 371 } 372 return pb, nil 373 default: 374 return nil, fmt.Errorf("from proto: wal message not recognized: %T", msg) 375 } 376 return pb, nil 377 }