package types import ( "time" cmn "github.com/tendermint/tendermint/libs/common" tmtime "github.com/tendermint/tendermint/types/time" ) // Canonical* wraps the structs in types for amino encoding them for use in SignBytes / the Signable interface. // TimeFormat is used for generating the sigs const TimeFormat = time.RFC3339Nano type CanonicalBlockID struct { Hash cmn.HexBytes PartsHeader CanonicalPartSetHeader } type CanonicalPartSetHeader struct { Hash cmn.HexBytes Total int } type CanonicalProposal struct { Version uint64 `binary:"fixed64"` Height int64 `binary:"fixed64"` Round int64 `binary:"fixed64"` Type SignedMsgType // type alias for byte POLRound int64 `binary:"fixed64"` Timestamp time.Time BlockPartsHeader CanonicalPartSetHeader POLBlockID CanonicalBlockID ChainID string } type CanonicalVote struct { Version uint64 `binary:"fixed64"` Height int64 `binary:"fixed64"` Round int64 `binary:"fixed64"` Type SignedMsgType // type alias for byte Timestamp time.Time BlockID CanonicalBlockID ChainID string } type CanonicalHeartbeat struct { Version uint64 `binary:"fixed64"` Height int64 `binary:"fixed64"` Round int `binary:"fixed64"` Type byte Sequence int `binary:"fixed64"` ValidatorAddress Address ValidatorIndex int ChainID string } //----------------------------------- // Canonicalize the structs func CanonicalizeBlockID(blockID BlockID) CanonicalBlockID { return CanonicalBlockID{ Hash: blockID.Hash, PartsHeader: CanonicalizePartSetHeader(blockID.PartsHeader), } } func CanonicalizePartSetHeader(psh PartSetHeader) CanonicalPartSetHeader { return CanonicalPartSetHeader{ psh.Hash, psh.Total, } } func CanonicalizeProposal(chainID string, proposal *Proposal) CanonicalProposal { return CanonicalProposal{ Version: 0, // TODO Height: proposal.Height, Round: int64(proposal.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int) Type: ProposalType, POLRound: int64(proposal.POLRound), Timestamp: proposal.Timestamp, BlockPartsHeader: CanonicalizePartSetHeader(proposal.BlockPartsHeader), POLBlockID: CanonicalizeBlockID(proposal.POLBlockID), ChainID: chainID, } } func CanonicalizeVote(chainID string, vote *Vote) CanonicalVote { return CanonicalVote{ Version: 0, // TODO Height: vote.Height, Round: int64(vote.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int) Type: vote.Type, Timestamp: vote.Timestamp, BlockID: CanonicalizeBlockID(vote.BlockID), ChainID: chainID, } } func CanonicalizeHeartbeat(chainID string, heartbeat *Heartbeat) CanonicalHeartbeat { return CanonicalHeartbeat{ Version: 0, // TODO Height: heartbeat.Height, Round: heartbeat.Round, Type: byte(HeartbeatType), Sequence: heartbeat.Sequence, ValidatorAddress: heartbeat.ValidatorAddress, ValidatorIndex: heartbeat.ValidatorIndex, ChainID: chainID, } } // CanonicalTime can be used to stringify time in a canonical way. func CanonicalTime(t time.Time) string { // Note that sending time over amino resets it to // local time, we need to force UTC here, so the // signatures match return tmtime.Canonical(t).Format(TimeFormat) }