-
Notifications
You must be signed in to change notification settings - Fork 103
/
evidence.go
154 lines (138 loc) · 3.74 KB
/
evidence.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package crypto
import (
"fmt"
"time"
ibctmtypes "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint"
"github.com/cometbft/cometbft/crypto/tmhash"
"github.com/cometbft/cometbft/libs/bytes"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
tmtypes "github.com/cometbft/cometbft/types"
)
// utility function duplicated from CometBFT
// see https://github.com/cometbft/cometbft/blob/main/evidence/verify_test.go#L554
func MakeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) tmtypes.BlockID {
var (
h = make([]byte, tmhash.Size)
psH = make([]byte, tmhash.Size)
)
copy(h, hash)
copy(psH, partSetHash)
return tmtypes.BlockID{
Hash: h,
PartSetHeader: tmtypes.PartSetHeader{
Total: partSetSize,
Hash: psH,
},
}
}
func MakeAndSignVote(
blockID tmtypes.BlockID,
blockHeight int64,
blockTime time.Time,
valSet *tmtypes.ValidatorSet,
signer tmtypes.PrivValidator,
chainID string,
) *tmtypes.Vote {
pubKey, err := signer.GetPubKey()
if err != nil {
panic(fmt.Errorf("can't get pubkey: %w", err))
}
addr := pubKey.Address()
idx, _ := valSet.GetByAddress(addr)
vote, err := tmtypes.MakeVote(
signer,
chainID,
idx, // val index
blockHeight, // height
0, // round
tmproto.PrecommitType, // type (does not work if set to sth else)
blockID,
blockTime,
)
if err != nil {
panic(err)
}
v := vote.ToProto()
err = signer.SignVote(chainID, v)
if err != nil {
panic(err)
}
vote.Signature = v.Signature
return vote
}
// MakeAndSignVoteWithForgedValAddress makes and signs a vote using two different keys:
// one to derive the validator address in the vote and a second to sign it.
func MakeAndSignVoteWithForgedValAddress(
blockID tmtypes.BlockID,
blockHeight int64,
blockTime time.Time,
valSet *tmtypes.ValidatorSet,
signer tmtypes.PrivValidator,
valAddressSigner tmtypes.PrivValidator,
chainID string,
) *tmtypes.Vote {
pubKey, err := signer.GetPubKey()
if err != nil {
panic(fmt.Errorf("can't get pubkey: %w", err))
}
addr := pubKey.Address()
idx, _ := valSet.GetByAddress(addr)
// create the vote using a different key than the signing key
vote, err := tmtypes.MakeVote(
valAddressSigner,
chainID,
idx,
blockHeight,
0,
tmproto.PrecommitType,
blockID,
blockTime,
)
if err != nil {
panic(err)
}
// sign vote using the given private key
v := vote.ToProto()
err = signer.SignVote(chainID, v)
if err != nil {
panic(err)
}
vote.Signature = v.Signature
return vote
}
// CorruptCommitSigsInHeader corrupts the header by changing the value
// of the commit signature for given validator address.
// Note that this method is solely used for testing purposes
func CorruptCommitSigsInHeader(header *ibctmtypes.Header, valAddress bytes.HexBytes) {
commit, err := tmtypes.CommitFromProto(header.Commit)
if err != nil {
panic(err)
}
for idx, sig := range commit.Signatures {
if sig.ValidatorAddress.String() == valAddress.String() {
sig.Signature = []byte("randomsig")
commit.Signatures[idx] = sig
}
}
// update the commit in client the header
header.SignedHeader.Commit = commit.ToProto()
}
// CorruptValidatorPubkeyInHeader corrupts the header by changing the validator pubkey
// of the given validator address in the validator set.
// Note that this method is solely used for testing purposes
func CorruptValidatorPubkeyInHeader(header *ibctmtypes.Header, valAddress bytes.HexBytes) {
valset, err := tmtypes.ValidatorSetFromProto(header.ValidatorSet)
if err != nil {
panic(err)
}
for _, v := range valset.Validators {
if v.Address.String() == valAddress.String() {
v.PubKey = tmtypes.NewMockPV().PrivKey.PubKey()
}
}
vs, err := valset.ToProto()
if err != nil {
panic(err)
}
header.ValidatorSet = vs
}