Skip to content

Commit 73cea87

Browse files
mariuszzaksrdtrkmattac21
authored
fix(attestations): add domain separation to signature verification (#8799)
* feat(attestations): add domain separation to signature verification * fix(attestations): update e2e tests with domain-separated signing * fix(gmp): update e2e tests with domain-separated signing --------- Co-authored-by: srdtrk <59252793+srdtrk@users.noreply.github.com> Co-authored-by: mattac21 <matt@cosmoslabs.io>
1 parent eb52d21 commit 73cea87

File tree

9 files changed

+101
-37
lines changed

9 files changed

+101
-37
lines changed

e2e/tests/attestations/attestations_test.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package attestations
55
import (
66
"context"
77
"crypto/ecdsa"
8-
"crypto/sha256"
98
"encoding/json"
109
"strconv"
1110
"testing"
@@ -441,7 +440,7 @@ func (s *AttestationsTestSuite) TestMsgTransfer_Timeout_Attestations() {
441440
stateAttestationData, err := stateAttestation.ABIEncode()
442441
s.Require().NoError(err)
443442

444-
signatures := s.signAttestationData(stateAttestationData)
443+
signatures := s.signAttestationData(stateAttestationData, attestations.AttestationTypeState)
445444
updateProof := &attestations.AttestationProof{
446445
AttestationData: stateAttestationData,
447446
Signatures: signatures,
@@ -515,7 +514,7 @@ func (s *AttestationsTestSuite) createPacketAttestationProof(height uint64, path
515514
attestationData, err := packetAttestation.ABIEncode()
516515
s.Require().NoError(err)
517516

518-
signatures := s.signAttestationData(attestationData)
517+
signatures := s.signAttestationData(attestationData, attestations.AttestationTypePacket)
519518
proof := &attestations.AttestationProof{
520519
AttestationData: attestationData,
521520
Signatures: signatures,
@@ -525,8 +524,8 @@ func (s *AttestationsTestSuite) createPacketAttestationProof(height uint64, path
525524
return proofBz
526525
}
527526

528-
func (s *AttestationsTestSuite) signAttestationData(data []byte) [][]byte {
529-
hash := sha256.Sum256(data)
527+
func (s *AttestationsTestSuite) signAttestationData(data []byte, attestationType attestations.AttestationType) [][]byte {
528+
hash := attestations.TaggedSigningInput(data, attestationType)
530529
var signatures [][]byte
531530
for _, key := range s.attestorKeys {
532531
sig, err := crypto.Sign(hash[:], key)
@@ -550,7 +549,7 @@ func (s *AttestationsTestSuite) createNonMembershipProof(height uint64, path []b
550549
attestationData, err := packetAttestation.ABIEncode()
551550
s.Require().NoError(err)
552551

553-
signatures := s.signAttestationData(attestationData)
552+
signatures := s.signAttestationData(attestationData, attestations.AttestationTypePacket)
554553
proof := &attestations.AttestationProof{
555554
AttestationData: attestationData,
556555
Signatures: signatures,

e2e/tests/gmp/base_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package gmp
55
import (
66
"context"
77
"crypto/ecdsa"
8-
"crypto/sha256"
98
"testing"
109
"time"
1110

@@ -248,7 +247,7 @@ func (s *GMPTestSuite) createAttestationProof(path, commitment []byte) []byte {
248247
data, err := attestation.ABIEncode()
249248
s.Require().NoError(err)
250249

251-
hash := sha256.Sum256(data)
250+
hash := attestations.TaggedSigningInput(data, attestations.AttestationTypePacket)
252251
signatures := make([][]byte, len(s.attestorKeys))
253252
for i, key := range s.attestorKeys {
254253
sig, err := crypto.Sign(hash[:], key)

modules/light-clients/attestations/client_state.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func (cs *ClientState) verifyMembership(
101101
return errorsmod.Wrapf(ErrInvalidAttestationProof, "failed to unmarshal proof: %v", err)
102102
}
103103

104-
if err := cs.verifySignatures(&attestationProof); err != nil {
104+
if err := cs.verifySignatures(&attestationProof, AttestationTypePacket); err != nil {
105105
return err
106106
}
107107

@@ -171,7 +171,7 @@ func (cs *ClientState) verifyNonMembership(
171171
return errorsmod.Wrapf(ErrInvalidAttestationProof, "failed to unmarshal proof: %v", err)
172172
}
173173

174-
if err := cs.verifySignatures(&attestationProof); err != nil {
174+
if err := cs.verifySignatures(&attestationProof, AttestationTypePacket); err != nil {
175175
return err
176176
}
177177

modules/light-clients/attestations/client_state_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ func (s *AttestationsTestSuite) TestVerifyMembership() {
162162
newTimestamp := uint64(2 * time.Second.Nanoseconds())
163163
stateAttestation := s.createStateAttestation(newHeight, newTimestamp)
164164
signers := []int{0, 1, 2}
165-
updateProof := s.createAttestationProof(stateAttestation, signers)
165+
updateProof := s.createAttestationProof(stateAttestation, signers, attestations.AttestationTypeState)
166166

167167
err := s.lightClientModule.VerifyClientMessage(ctx, clientID, updateProof)
168168
s.Require().NoError(err)
@@ -177,7 +177,7 @@ func (s *AttestationsTestSuite) TestVerifyMembership() {
177177
// Commitment is stored as raw value (not hashed)
178178
hashedPath := crypto.Keccak256(tc.attestedPath)
179179
packetAttestation := s.createPacketAttestation(newHeight, []attestations.PacketCompact{{Path: hashedPath, Commitment: tc.value}})
180-
membershipProof := s.createAttestationProof(packetAttestation, signers)
180+
membershipProof := s.createAttestationProof(packetAttestation, signers, attestations.AttestationTypePacket)
181181
membershipProofBz := s.marshalProof(membershipProof)
182182

183183
proofHeight := clienttypes.NewHeight(0, newHeight)
@@ -210,7 +210,7 @@ func (s *AttestationsTestSuite) TestVerifyMembershipMalformedProof() {
210210
s.Require().ErrorContains(err, "failed to unmarshal proof")
211211

212212
malformedData := []byte("invalid-packet-attestation-data")
213-
proof := s.createAttestationProof(malformedData, []int{0, 1, 2})
213+
proof := s.createAttestationProof(malformedData, []int{0, 1, 2}, attestations.AttestationTypePacket)
214214
proofBz := s.marshalProof(proof)
215215

216216
err = s.lightClientModule.VerifyMembership(ctx, clientID, proofHeight, 0, 0, proofBz, path, value)
@@ -237,7 +237,7 @@ func (s *AttestationsTestSuite) TestVerifyMembershipVariableLengthPath() {
237237
hashedPath := crypto.Keccak256(shortPath)
238238
packetAttestation := s.createPacketAttestation(newHeight, []attestations.PacketCompact{{Path: hashedPath, Commitment: value32}})
239239
signers := []int{0, 1, 2}
240-
proof := s.createAttestationProof(packetAttestation, signers)
240+
proof := s.createAttestationProof(packetAttestation, signers, attestations.AttestationTypePacket)
241241
proofBz := s.marshalProof(proof)
242242

243243
proofHeight := clienttypes.NewHeight(0, newHeight)
@@ -261,7 +261,7 @@ func (s *AttestationsTestSuite) TestVerifyMembershipInvalidKeyPathLength() {
261261
hashedPath := crypto.Keccak256(bytes.Repeat([]byte{0x01}, 32))
262262
packetAttestation := s.createPacketAttestation(newHeight, []attestations.PacketCompact{{Path: hashedPath, Commitment: value32}})
263263
signers := []int{0, 1, 2}
264-
proof := s.createAttestationProof(packetAttestation, signers)
264+
proof := s.createAttestationProof(packetAttestation, signers, attestations.AttestationTypePacket)
265265
proofBz := s.marshalProof(proof)
266266
proofHeight := clienttypes.NewHeight(0, newHeight)
267267

@@ -291,7 +291,7 @@ func (s *AttestationsTestSuite) TestVerifyNonMembershipInvalidKeyPathLength() {
291291
hashedPath := crypto.Keccak256(bytes.Repeat([]byte{0x01}, 32))
292292
packetAttestation := s.createPacketAttestation(newHeight, []attestations.PacketCompact{{Path: hashedPath, Commitment: make([]byte, 32)}})
293293
signers := []int{0, 1, 2}
294-
proof := s.createAttestationProof(packetAttestation, signers)
294+
proof := s.createAttestationProof(packetAttestation, signers, attestations.AttestationTypePacket)
295295
proofBz := s.marshalProof(proof)
296296
proofHeight := clienttypes.NewHeight(0, newHeight)
297297

@@ -399,7 +399,7 @@ func (s *AttestationsTestSuite) TestVerifyNonMembership() {
399399
newTimestamp := uint64(2 * time.Second.Nanoseconds())
400400
stateAttestation := s.createStateAttestation(newHeight, newTimestamp)
401401
signers := []int{0, 1, 2}
402-
updateProof := s.createAttestationProof(stateAttestation, signers)
402+
updateProof := s.createAttestationProof(stateAttestation, signers, attestations.AttestationTypeState)
403403

404404
err := s.lightClientModule.VerifyClientMessage(ctx, clientID, updateProof)
405405
s.Require().NoError(err)
@@ -417,7 +417,7 @@ func (s *AttestationsTestSuite) TestVerifyNonMembership() {
417417
}
418418
}
419419
packetAttestation := s.createPacketAttestation(newHeight, hashedPackets)
420-
nonMembershipProof := s.createAttestationProof(packetAttestation, signers)
420+
nonMembershipProof := s.createAttestationProof(packetAttestation, signers, attestations.AttestationTypePacket)
421421
nonMembershipProofBz := s.marshalProof(nonMembershipProof)
422422

423423
proofHeight := clienttypes.NewHeight(0, newHeight)

modules/light-clients/attestations/light_client_module_test.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package attestations_test
22

33
import (
44
"crypto/ecdsa"
5-
"crypto/sha256"
65
"testing"
76
"time"
87

@@ -62,8 +61,8 @@ func (s *AttestationsTestSuite) SetupTest() {
6261
s.lightClientModule = attestations.NewLightClientModule(cdc, storeProvider)
6362
}
6463

65-
func (s *AttestationsTestSuite) createAttestationProof(attestationData []byte, signers []int) *attestations.AttestationProof {
66-
hash := sha256.Sum256(attestationData)
64+
func (s *AttestationsTestSuite) createAttestationProof(attestationData []byte, signers []int, attestationType attestations.AttestationType) *attestations.AttestationProof {
65+
hash := attestations.TaggedSigningInput(attestationData, attestationType)
6766
signatures := make([][]byte, 0, len(signers))
6867

6968
for _, idx := range signers {
@@ -157,7 +156,7 @@ func (s *AttestationsTestSuite) freezeClient(ctx sdk.Context, clientID string) {
157156
func (s *AttestationsTestSuite) updateClientState(ctx sdk.Context, clientID string, height, timestamp uint64) {
158157
stateAttestation := s.createStateAttestation(height, timestamp)
159158
signers := []int{0, 1, 2}
160-
proof := s.createAttestationProof(stateAttestation, signers)
159+
proof := s.createAttestationProof(stateAttestation, signers, attestations.AttestationTypeState)
161160
_ = s.lightClientModule.UpdateState(ctx, clientID, proof)
162161
}
163162

@@ -241,7 +240,7 @@ func (s *AttestationsTestSuite) TestCheckForMisbehaviourReturnsFalse() {
241240

242241
stateAttestation := s.createStateAttestation(initialHeight+1, initialTimestamp+uint64(time.Second.Nanoseconds()))
243242
signers := []int{0, 1, 2}
244-
proof := s.createAttestationProof(stateAttestation, signers)
243+
proof := s.createAttestationProof(stateAttestation, signers, attestations.AttestationTypeState)
245244

246245
foundMisbehaviour := s.lightClientModule.CheckForMisbehaviour(ctx, testClientID, proof)
247246
s.Require().False(foundMisbehaviour, "CheckForMisbehaviour should return false")

modules/light-clients/attestations/signature.go

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,38 @@ import (
99
errorsmod "cosmossdk.io/errors"
1010
)
1111

12+
// AttestationType distinguishes attestation types to prevent cross-protocol signature replay.
13+
type AttestationType byte
14+
15+
const (
16+
// AttestationTypeState is used for client update (state) attestations.
17+
AttestationTypeState AttestationType = 0x01
18+
// AttestationTypePacket is used for packet membership/non-membership attestations.
19+
AttestationTypePacket AttestationType = 0x02
20+
)
21+
1222
const (
1323
// SignatureLength is the expected length of an ECDSA signature (r||s||v)
1424
SignatureLength = 65
1525
// recoveryIDIndex is the byte position of the recovery ID (v) in the signature
1626
recoveryIDIndex = 64
27+
// domainSeparatedPreimageLen is the length of the domain-separated signing preimage:
28+
// 1-byte type tag + 32-byte SHA-256 hash.
29+
domainSeparatedPreimageLen = 1 + sha256.Size
1730
)
1831

32+
// TaggedSigningInput computes the domain-separated prehash: `sha256(type_tag || sha256(data))`.
33+
func TaggedSigningInput(data []byte, attestationType AttestationType) [32]byte {
34+
innerHash := sha256.Sum256(data)
35+
var tagged [domainSeparatedPreimageLen]byte
36+
tagged[0] = byte(attestationType)
37+
copy(tagged[1:], innerHash[:])
38+
return sha256.Sum256(tagged[:])
39+
}
40+
1941
// verifySignatures verifies that the attestation proof has valid signatures from unique attestors
20-
// meeting the quorum threshold. Signatures cover sha256(attestationData).
21-
func (cs *ClientState) verifySignatures(proof *AttestationProof) error {
42+
// meeting the quorum threshold. Signatures cover `sha256(type_tag || sha256(attestationData))`.
43+
func (cs *ClientState) verifySignatures(proof *AttestationProof, attestationType AttestationType) error {
2244
if len(proof.Signatures) == 0 {
2345
return errorsmod.Wrap(ErrInvalidSignature, "signatures cannot be empty")
2446
}
@@ -28,7 +50,7 @@ func (cs *ClientState) verifySignatures(proof *AttestationProof) error {
2850
attestorSet[common.HexToAddress(addr)] = true
2951
}
3052

31-
hash := sha256.Sum256(proof.AttestationData)
53+
hash := TaggedSigningInput(proof.AttestationData, attestationType)
3254
seenSigners := make(map[common.Address]bool)
3355

3456
for i, sig := range proof.Signatures {

modules/light-clients/attestations/signature_test.go

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ package attestations_test
22

33
import (
44
"bytes"
5-
"crypto/sha256"
65
"strings"
76
"time"
87

98
"github.com/ethereum/go-ethereum/crypto"
109

10+
clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types"
11+
commitmenttypesv2 "github.com/cosmos/ibc-go/v10/modules/core/23-commitment/types/v2"
1112
"github.com/cosmos/ibc-go/v10/modules/light-clients/attestations"
1213
)
1314

@@ -31,7 +32,7 @@ func (s *AttestationsTestSuite) TestVerifySignatures() {
3132
name: "failure: unknown signer",
3233
setupProof: func(attestationData []byte) *attestations.AttestationProof {
3334
unknownKey, _ := crypto.GenerateKey()
34-
hash := sha256.Sum256(attestationData)
35+
hash := attestations.TaggedSigningInput(attestationData, attestations.AttestationTypeState)
3536
unknownSig, _ := crypto.Sign(hash[:], unknownKey)
3637
return &attestations.AttestationProof{
3738
AttestationData: attestationData,
@@ -43,7 +44,7 @@ func (s *AttestationsTestSuite) TestVerifySignatures() {
4344
{
4445
name: "failure: duplicate signer",
4546
setupProof: func(attestationData []byte) *attestations.AttestationProof {
46-
hash := sha256.Sum256(attestationData)
47+
hash := attestations.TaggedSigningInput(attestationData, attestations.AttestationTypeState)
4748
sig1, _ := crypto.Sign(hash[:], s.attestors[0])
4849
sig2, _ := crypto.Sign(hash[:], s.attestors[0])
4950
return &attestations.AttestationProof{
@@ -114,7 +115,7 @@ func (s *AttestationsTestSuite) TestAddressCaseInsensitiveComparison() {
114115
newTimestamp := uint64(2 * time.Second.Nanoseconds())
115116
attestationData := s.createStateAttestation(newHeight, newTimestamp)
116117

117-
hash := sha256.Sum256(attestationData)
118+
hash := attestations.TaggedSigningInput(attestationData, attestations.AttestationTypeState)
118119
sig, err := crypto.Sign(hash[:], privKey)
119120
s.Require().NoError(err)
120121

@@ -126,3 +127,47 @@ func (s *AttestationsTestSuite) TestAddressCaseInsensitiveComparison() {
126127
err = s.lightClientModule.VerifyClientMessage(ctx, clientID, proof)
127128
s.Require().NoError(err)
128129
}
130+
131+
func (s *AttestationsTestSuite) TestCrossDomainReplay() {
132+
initialHeight := uint64(100)
133+
initialTimestamp := uint64(time.Second.Nanoseconds())
134+
clientID := testClientID
135+
ctx := s.chainA.GetContext()
136+
137+
s.initializeClient(ctx, clientID, initialHeight, initialTimestamp)
138+
139+
newHeight := uint64(200)
140+
newTimestamp := uint64(2 * time.Second.Nanoseconds())
141+
attestationData := s.createStateAttestation(newHeight, newTimestamp)
142+
143+
// Sign as Packet, verify as State — must fail
144+
packetProof := s.createAttestationProof(attestationData, []int{0, 1, 2}, attestations.AttestationTypePacket)
145+
err := s.lightClientModule.VerifyClientMessage(ctx, clientID, packetProof)
146+
s.Require().Error(err)
147+
s.Require().ErrorContains(err, "not in attestor set")
148+
149+
// Sign as State, verify as Packet (via membership) — must fail
150+
hashedPath := crypto.Keccak256(bytes.Repeat([]byte{0x01}, 32))
151+
value := bytes.Repeat([]byte{0xAB}, 32)
152+
packetAttestation := s.createPacketAttestation(initialHeight, []attestations.PacketCompact{{Path: hashedPath, Commitment: value}})
153+
stateSignedProof := s.createAttestationProof(packetAttestation, []int{0, 1, 2}, attestations.AttestationTypeState)
154+
proofBz := s.marshalProof(stateSignedProof)
155+
156+
proofHeight := clienttypes.NewHeight(0, initialHeight)
157+
path := commitmenttypesv2.NewMerklePath(bytes.Repeat([]byte{0x01}, 32))
158+
err = s.lightClientModule.VerifyMembership(ctx, clientID, proofHeight, 0, 0, proofBz, path, value)
159+
s.Require().Error(err)
160+
s.Require().ErrorContains(err, "not in attestor set")
161+
162+
// Sign as State, verify as Packet (via non-membership) — must fail
163+
zeroCommitment := make([]byte, 32)
164+
nonMemPath := bytes.Repeat([]byte{0x02}, 32)
165+
hashedNonMemPath := crypto.Keccak256(nonMemPath)
166+
nonMemPacketAttestation := s.createPacketAttestation(initialHeight, []attestations.PacketCompact{{Path: hashedNonMemPath, Commitment: zeroCommitment}})
167+
stateSignedNonMemProof := s.createAttestationProof(nonMemPacketAttestation, []int{0, 1, 2}, attestations.AttestationTypeState)
168+
nonMemProofBz := s.marshalProof(stateSignedNonMemProof)
169+
170+
err = s.lightClientModule.VerifyNonMembership(ctx, clientID, proofHeight, 0, 0, nonMemProofBz, commitmenttypesv2.NewMerklePath(nonMemPath))
171+
s.Require().Error(err)
172+
s.Require().ErrorContains(err, "not in attestor set")
173+
}

modules/light-clients/attestations/update.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func (cs *ClientState) VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCode
2525
return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "expected type %T, got type %T", (*AttestationProof)(nil), clientMsg)
2626
}
2727

28-
return cs.verifySignatures(attestationProof)
28+
return cs.verifySignatures(attestationProof, AttestationTypeState)
2929
}
3030

3131
// UpdateState updates the consensus state to a new height and timestamp.

modules/light-clients/attestations/update_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func (s *AttestationsTestSuite) TestUpdateState() {
3939
newHeight := uint64(200)
4040
newTimestamp := uint64(2 * time.Second.Nanoseconds())
4141
attestationData := s.createStateAttestation(newHeight, newTimestamp)
42-
proof := s.createAttestationProof(attestationData, tc.signers)
42+
proof := s.createAttestationProof(attestationData, tc.signers, attestations.AttestationTypeState)
4343

4444
err := s.lightClientModule.VerifyClientMessage(ctx, clientID, proof)
4545
if tc.expErr != "" {
@@ -75,7 +75,7 @@ func (s *AttestationsTestSuite) TestUpdateStateIdempotency() {
7575
newTimestamp := uint64(2 * time.Second.Nanoseconds())
7676
attestationData := s.createStateAttestation(newHeight, newTimestamp)
7777
signers := []int{0, 1, 2}
78-
proof := s.createAttestationProof(attestationData, signers)
78+
proof := s.createAttestationProof(attestationData, signers, attestations.AttestationTypeState)
7979

8080
err := s.lightClientModule.VerifyClientMessage(ctx, clientID, proof)
8181
s.Require().NoError(err)
@@ -104,7 +104,7 @@ func (s *AttestationsTestSuite) TestVerifyClientMessageFrozenClient() {
104104
newTimestamp := uint64(2 * time.Second.Nanoseconds())
105105
attestationData := s.createStateAttestation(newHeight, newTimestamp)
106106
signers := []int{0, 1, 2}
107-
proof := s.createAttestationProof(attestationData, signers)
107+
proof := s.createAttestationProof(attestationData, signers, attestations.AttestationTypeState)
108108

109109
err := s.lightClientModule.VerifyClientMessage(ctx, clientID, proof)
110110
s.Require().NoError(err)
@@ -116,7 +116,7 @@ func (s *AttestationsTestSuite) TestVerifyClientMessageFrozenClient() {
116116
s.Require().Equal(exported.Frozen, status)
117117

118118
newProofData := s.createStateAttestation(uint64(300), uint64(4*time.Second.Nanoseconds()))
119-
newProof := s.createAttestationProof(newProofData, signers)
119+
newProof := s.createAttestationProof(newProofData, signers, attestations.AttestationTypeState)
120120

121121
err = s.lightClientModule.VerifyClientMessage(ctx, clientID, newProof)
122122
s.Require().ErrorIs(err, attestations.ErrClientFrozen)
@@ -137,15 +137,15 @@ func (s *AttestationsTestSuite) TestUpdateStateOnMisbehaviourPanics() {
137137
newTimestamp := uint64(2 * time.Second.Nanoseconds())
138138
attestationData := s.createStateAttestation(newHeight, newTimestamp)
139139
signers := []int{0, 1, 2}
140-
proof := s.createAttestationProof(attestationData, signers)
140+
proof := s.createAttestationProof(attestationData, signers, attestations.AttestationTypeState)
141141

142142
err := s.lightClientModule.VerifyClientMessage(ctx, clientID, proof)
143143
s.Require().NoError(err)
144144
_ = s.lightClientModule.UpdateState(ctx, clientID, proof)
145145

146146
conflictingTimestamp := uint64(3 * time.Second.Nanoseconds())
147147
conflictingAttestationData := s.createStateAttestation(newHeight, conflictingTimestamp)
148-
conflictingProof := s.createAttestationProof(conflictingAttestationData, signers)
148+
conflictingProof := s.createAttestationProof(conflictingAttestationData, signers, attestations.AttestationTypeState)
149149

150150
updateStateOnMisbehaviourFunc := func() {
151151
s.lightClientModule.UpdateStateOnMisbehaviour(ctx, clientID, conflictingProof)

0 commit comments

Comments
 (0)