/
canonical.go
86 lines (74 loc) · 2.79 KB
/
canonical.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package types
import (
"time"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
cmttime "github.com/cometbft/cometbft/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
//-----------------------------------
// Canonicalize the structs
func CanonicalizeBlockID(bid cmtproto.BlockID) *cmtproto.CanonicalBlockID {
rbid, err := BlockIDFromProto(&bid)
if err != nil {
panic(err)
}
var cbid *cmtproto.CanonicalBlockID
if rbid == nil || rbid.IsZero() {
cbid = nil
} else {
cbid = &cmtproto.CanonicalBlockID{
Hash: bid.Hash,
PartSetHeader: CanonicalizePartSetHeader(bid.PartSetHeader),
}
}
return cbid
}
// CanonicalizeVote transforms the given PartSetHeader to a CanonicalPartSetHeader.
func CanonicalizePartSetHeader(psh cmtproto.PartSetHeader) cmtproto.CanonicalPartSetHeader {
return cmtproto.CanonicalPartSetHeader(psh)
}
// CanonicalizeVote transforms the given Proposal to a CanonicalProposal.
func CanonicalizeProposal(chainID string, proposal *cmtproto.Proposal) cmtproto.CanonicalProposal {
return cmtproto.CanonicalProposal{
Type: cmtproto.ProposalType,
Height: proposal.Height, // encoded as sfixed64
Round: int64(proposal.Round), // encoded as sfixed64
POLRound: int64(proposal.PolRound),
BlockID: CanonicalizeBlockID(proposal.BlockID),
Timestamp: proposal.Timestamp,
ChainID: chainID,
}
}
// CanonicalizeVote transforms the given Vote to a CanonicalVote, which does
// not contain ValidatorIndex and ValidatorAddress fields, or any fields
// relating to vote extensions.
func CanonicalizeVote(chainID string, vote *cmtproto.Vote) cmtproto.CanonicalVote {
return cmtproto.CanonicalVote{
Type: vote.Type,
Height: vote.Height, // encoded as sfixed64
Round: int64(vote.Round), // encoded as sfixed64
BlockID: CanonicalizeBlockID(vote.BlockID),
Timestamp: vote.Timestamp,
ChainID: chainID,
}
}
// CanonicalizeVoteExtension extracts the vote extension from the given vote
// and constructs a CanonicalizeVoteExtension struct, whose representation in
// bytes is what is signed in order to produce the vote extension's signature.
func CanonicalizeVoteExtension(chainID string, vote *cmtproto.Vote) cmtproto.CanonicalVoteExtension {
return cmtproto.CanonicalVoteExtension{
Extension: vote.Extension,
Height: vote.Height,
Round: int64(vote.Round),
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 cmttime.Canonical(t).Format(TimeFormat)
}