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