package statesync import ( "errors" "fmt" amino "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/types" ) const ( // snapshotMsgSize is the maximum size of a snapshotResponseMessage snapshotMsgSize = int(4e6) // chunkMsgSize is the maximum size of a chunkResponseMessage chunkMsgSize = int(16e6) // maxMsgSize is the maximum size of any message maxMsgSize = chunkMsgSize ) var cdc = amino.NewCodec() func init() { cdc.RegisterInterface((*Message)(nil), nil) cdc.RegisterConcrete(&snapshotsRequestMessage{}, "tendermint/SnapshotsRequestMessage", nil) cdc.RegisterConcrete(&snapshotsResponseMessage{}, "tendermint/SnapshotsResponseMessage", nil) cdc.RegisterConcrete(&chunkRequestMessage{}, "tendermint/ChunkRequestMessage", nil) cdc.RegisterConcrete(&chunkResponseMessage{}, "tendermint/ChunkResponseMessage", nil) types.RegisterBlockAmino(cdc) } // decodeMsg decodes a message. func decodeMsg(bz []byte) (Message, error) { if len(bz) > maxMsgSize { return nil, fmt.Errorf("msg exceeds max size (%d > %d)", len(bz), maxMsgSize) } var msg Message err := cdc.UnmarshalBinaryBare(bz, &msg) if err != nil { return nil, err } return msg, nil } // Message is a message sent and received by the reactor. type Message interface { ValidateBasic() error } // snapshotsRequestMessage requests recent snapshots from a peer. type snapshotsRequestMessage struct{} // ValidateBasic implements Message. func (m *snapshotsRequestMessage) ValidateBasic() error { if m == nil { return errors.New("nil message") } return nil } // SnapshotResponseMessage contains information about a single snapshot. type snapshotsResponseMessage struct { Height uint64 Format uint32 Chunks uint32 Hash []byte Metadata []byte } // ValidateBasic implements Message. func (m *snapshotsResponseMessage) ValidateBasic() error { if m == nil { return errors.New("nil message") } if m.Height == 0 { return errors.New("height cannot be 0") } if len(m.Hash) == 0 { return errors.New("snapshot has no hash") } if m.Chunks == 0 { return errors.New("snapshot has no chunks") } return nil } // chunkRequestMessage requests a single chunk from a peer. type chunkRequestMessage struct { Height uint64 Format uint32 Index uint32 } // ValidateBasic implements Message. func (m *chunkRequestMessage) ValidateBasic() error { if m == nil { return errors.New("nil message") } if m.Height == 0 { return errors.New("height cannot be 0") } return nil } // chunkResponseMessage contains a single chunk from a peer. type chunkResponseMessage struct { Height uint64 Format uint32 Index uint32 Chunk []byte Missing bool } // ValidateBasic implements Message. func (m *chunkResponseMessage) ValidateBasic() error { if m == nil { return errors.New("nil message") } if m.Height == 0 { return errors.New("height cannot be 0") } if m.Missing && len(m.Chunk) > 0 { return errors.New("missing chunk cannot have contents") } if !m.Missing && m.Chunk == nil { return errors.New("chunk cannot be nil") } return nil }