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