Skip to content

Commit 7f10895

Browse files
yrongvgeddes
andcommitted
Filter bad beefy keys (#1204)
* Filter out bad keys * Get AuthoritySet from storage * Filter invalid validators * Fix validator root * Improve slice compare * Fix empty address * Log cleanup * More logs * Cleanup * Chore * Upgrade go-substrate-rpc-client * Update go.work * Only syncing mandatory/handover commitments * Revert config * Update go.mod * Update go.mod --------- Co-authored-by: Vincent Geddes <[email protected]>
1 parent 1c2ca56 commit 7f10895

File tree

11 files changed

+131
-38
lines changed

11 files changed

+131
-38
lines changed

go.work

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
go 1.20
1+
go 1.21
2+
3+
toolchain go1.21.10
24

35
use ./relayer

go.work.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ github.com/valyala/fasthttp v1.40.0 h1:CRq/00MfruPGFLTQKY8b+8SfdK60TxNztjRMnH0t1
302302
github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
303303
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
304304
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
305+
github.com/vedhavyas/go-subkey/v2 v2.0.0 h1:LemDIsrVtRSOkp0FA8HxP6ynfKjeOj3BY2U9UNfeDMA=
305306
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
306307
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
307308
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=

relayer/cmd/scan_beefy.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,11 @@ func scanBeefyCmd() *cobra.Command {
2323
}
2424

2525
cmd.Flags().StringP("polkadot-url", "p", "ws://127.0.0.1:9944", "Polkadot URL.")
26-
cmd.MarkFlagRequired("polkadot-url")
2726
cmd.Flags().Uint64P("beefy-block", "b", 0, "Beefy block.")
2827
cmd.MarkFlagRequired("beefy-block")
2928
cmd.Flags().Uint64P("validator-set-id", "v", 0, "Validator set id.")
3029
cmd.MarkFlagRequired("validator-set-id")
31-
cmd.Flags().Uint64P("fast-forward-depth", "f", 100, "Fast forward depth.")
30+
cmd.Flags().Uint64P("fast-forward-depth", "f", 10000, "Fast forward depth.")
3231
return cmd
3332
}
3433

relayer/go.mod

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
module github.com/snowfork/snowbridge/relayer
22

3-
go 1.20
3+
go 1.21
4+
5+
toolchain go1.21.10
46

57
require (
68
github.com/cbroglie/mustache v1.4.0
@@ -10,10 +12,11 @@ require (
1012
github.com/mattn/go-sqlite3 v1.14.22
1113
github.com/mitchellh/mapstructure v1.5.0
1214
github.com/sirupsen/logrus v1.9.3
13-
github.com/snowfork/go-substrate-rpc-client/v4 v4.0.1-0.20231109131025-3ece5b994f03
15+
github.com/snowfork/go-substrate-rpc-client/v4 v4.0.1-0.20240523155545-4272098ec025
1416
github.com/spf13/cobra v1.8.0
1517
github.com/spf13/viper v1.18.2
1618
github.com/stretchr/testify v1.8.4
19+
golang.org/x/exp v0.0.0-20240110193028-0dcbfd608b1e
1720
golang.org/x/sync v0.6.0
1821
)
1922

@@ -98,7 +101,6 @@ require (
98101
github.com/yusufpapurcu/wmi v1.2.3 // indirect
99102
go.uber.org/multierr v1.11.0 // indirect
100103
golang.org/x/crypto v0.18.0 // indirect
101-
golang.org/x/exp v0.0.0-20240110193028-0dcbfd608b1e // indirect
102104
golang.org/x/mod v0.14.0 // indirect
103105
golang.org/x/net v0.20.0 // indirect
104106
golang.org/x/sys v0.16.0 // indirect

relayer/go.sum

Lines changed: 31 additions & 2 deletions
Large diffs are not rendered by default.

relayer/relays/beefy/ethereum-writer.go

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,31 @@ func (wr *EthereumWriter) Start(ctx context.Context, eg *errgroup.Group, request
8080
}
8181

8282
func (wr *EthereumWriter) submit(ctx context.Context, task Request) error {
83+
callOpts := bind.CallOpts{
84+
Context: ctx,
85+
}
86+
87+
latestBeefyBlock, err := wr.contract.LatestBeefyBlock(&callOpts)
88+
if err != nil {
89+
return err
90+
}
91+
if uint32(latestBeefyBlock) >= task.SignedCommitment.Commitment.BlockNumber {
92+
return nil
93+
}
94+
95+
currentValidatorSet, err := wr.contract.CurrentValidatorSet(&callOpts)
96+
if err != nil {
97+
return err
98+
}
99+
nextValidatorSet, err := wr.contract.NextValidatorSet(&callOpts)
100+
if err != nil {
101+
return err
102+
}
103+
task.ValidatorsRoot = currentValidatorSet.Root
104+
if task.IsHandover {
105+
task.ValidatorsRoot = nextValidatorSet.Root
106+
}
107+
83108
// Initial submission
84109
tx, initialBitfield, err := wr.doSubmitInitial(ctx, &task)
85110
if err != nil {
@@ -148,9 +173,10 @@ func (wr *EthereumWriter) doSubmitInitial(ctx context.Context, task *Request) (*
148173
chosenValidator := signedValidators[rand.Intn(len(signedValidators))].Int64()
149174

150175
log.WithFields(logrus.Fields{
151-
"validatorCount": validatorCount,
152-
"signedValidators": signedValidators,
153-
"chosenValidator": chosenValidator,
176+
"validatorCount": validatorCount,
177+
"signedValidators": signedValidators,
178+
"signedValidatorCount": len(signedValidators),
179+
"chosenValidator": chosenValidator,
154180
}).Info("Creating initial bitfield")
155181

156182
initialBitfield, err := wr.contract.CreateInitialBitfield(

relayer/relays/beefy/parameters.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"github.com/snowfork/snowbridge/relayer/contracts"
1111
"github.com/snowfork/snowbridge/relayer/crypto/keccak"
1212
"github.com/snowfork/snowbridge/relayer/crypto/merkle"
13+
"github.com/snowfork/snowbridge/relayer/relays/util"
14+
"golang.org/x/exp/slices"
1315
)
1416

1517
type InitialRequestParams struct {
@@ -97,19 +99,26 @@ func cleanSignature(input types.BeefySignature) (uint8, [32]byte, [32]byte) {
9799
}
98100

99101
func (r *Request) generateValidatorAddressProof(validatorIndex int64) ([][32]byte, error) {
100-
leaves := make([][]byte, len(r.Validators))
101-
for i, rawAddress := range r.Validators {
102+
var leaves [][]byte
103+
var err error
104+
var invalidAddress []string
105+
for _, rawAddress := range r.Validators {
102106
address, err := rawAddress.IntoEthereumAddress()
103107
if err != nil {
104-
return nil, fmt.Errorf("convert to ethereum address: %w", err)
108+
invalidAddress = append(invalidAddress, util.BytesToHexString(rawAddress[:]))
109+
leaves = append(leaves, make([]byte, 0))
110+
} else {
111+
leaves = append(leaves, address.Bytes())
105112
}
106-
leaves[i] = address.Bytes()
107113
}
108-
109-
_, _, proof, err := merkle.GenerateMerkleProof(leaves, validatorIndex)
114+
_, root, proof, err := merkle.GenerateMerkleProof(leaves, validatorIndex)
110115
if err != nil {
111116
return nil, err
112117
}
118+
equal := slices.Equal(r.ValidatorsRoot[:], root)
119+
if !equal {
120+
return nil, fmt.Errorf("validator root %#x not match calculated root %#x, invalid address are: %s", r.ValidatorsRoot[:], root, invalidAddress)
121+
}
113122

114123
return proof, nil
115124
}

relayer/relays/beefy/scanner.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ func scanCommitments(ctx context.Context, api *gsrpc.SubstrateAPI, startBlock ui
128128
sendError(fmt.Errorf("fetch block: %w", err))
129129
return
130130
}
131+
log.WithFields(log.Fields{
132+
"blockNumber": result.BlockNumber,
133+
"depth": result.Depth,
134+
}).Info("fetch block")
131135

132136
var commitment *types.SignedCommitment
133137
for j := range block.Justifications {
@@ -206,6 +210,11 @@ func scanSafeCommitments(ctx context.Context, meta *types.Metadata, api *gsrpc.S
206210
sendError(result.Error)
207211
return
208212
}
213+
log.WithFields(log.Fields{
214+
"blockNumber": result.BlockNumber,
215+
"depth": result.Depth,
216+
"commitment": result.SignedCommitment.Commitment,
217+
}).Info("fetch commitment")
209218

210219
blockNumber := result.SignedCommitment.Commitment.BlockNumber
211220
blockHash, err := api.RPC.Chain.GetBlockHash(uint64(blockNumber))

relayer/relays/beefy/task.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
type Request struct {
1010
Validators []substrate.Authority
11+
ValidatorsRoot [32]byte
1112
SignedCommitment types.SignedCommitment
1213
Proof merkle.SimplifiedMMRProof
1314
IsHandover bool

web/packages/test-helpers/src/generateBeefyCheckpoint.ts

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,17 @@ import { ApiPromise, WsProvider } from "@polkadot/api"
22
import { MerkleTree } from "merkletreejs"
33
import createKeccakHash from "keccak"
44
import { publicKeyConvert } from "secp256k1"
5-
import type {
6-
ValidatorSetId,
7-
BeefyId,
8-
} from "@polkadot/types/interfaces/beefy/types"
5+
import type { ValidatorSetId, BeefyId } from "@polkadot/types/interfaces/beefy/types"
96
import fs from "fs"
107
import path from "path"
11-
import { u32, u64 } from "@polkadot/types-codec";
12-
import { H256 } from "@polkadot/types/interfaces";
13-
import { Struct } from "@polkadot/types";
14-
15-
interface NextAuthoritySet extends Struct {
16-
id: u64;
17-
len: u32;
18-
keysetCommitment: H256;
8+
import { u32, u64 } from "@polkadot/types-codec"
9+
import { H256 } from "@polkadot/types/interfaces"
10+
import { Struct } from "@polkadot/types"
11+
12+
interface AuthoritySet extends Struct {
13+
id: u64
14+
len: u32
15+
keysetCommitment: H256
1916
}
2017

2118
async function generateBeefyCheckpoint() {
@@ -50,23 +47,42 @@ async function generateBeefyCheckpoint() {
5047
const validatorSetId = await api.query.beefy.validatorSetId<ValidatorSetId>()
5148
const authorities = await api.query.beefy.authorities<BeefyId[]>()
5249

50+
console.log("validatorSetId:", validatorSetId)
51+
console.log("authority length is:" + authorities.length)
52+
5353
let addrs = []
54+
5455
for (let i = 0; i < authorities.length; i++) {
55-
let publicKey = publicKeyConvert(authorities[i], false).slice(1)
56-
let publicKeyHashed = createKeccakHash("keccak256").update(Buffer.from(publicKey)).digest()
57-
addrs.push(publicKeyHashed.slice(12))
56+
console.log("index is:" + i + ",authority is:" + authorities[i])
57+
try {
58+
let publicKey = publicKeyConvert(authorities[i], false).slice(1)
59+
let publicKeyHashed = createKeccakHash("keccak256")
60+
.update(Buffer.from(publicKey))
61+
.digest()
62+
addrs.push(publicKeyHashed.slice(12))
63+
} catch (err) {
64+
console.log(err)
65+
}
5866
}
5967

60-
const tree = createMerkleTree(addrs)
68+
console.log("valid authority length is:" + addrs.length)
6169

62-
const nextAuthorities = await api.query.mmrLeaf.beefyNextAuthorities<NextAuthoritySet>()
70+
let currentAuthorities, nextAuthorities
71+
72+
if (process.env.NODE_ENV == "production") {
73+
currentAuthorities = await api.query.beefyMmrLeaf.beefyAuthorities<AuthoritySet>()
74+
nextAuthorities = await api.query.beefyMmrLeaf.beefyNextAuthorities<AuthoritySet>()
75+
} else {
76+
currentAuthorities = await api.query.mmrLeaf.beefyAuthorities<AuthoritySet>()
77+
nextAuthorities = await api.query.mmrLeaf.beefyNextAuthorities<AuthoritySet>()
78+
}
6379

6480
const beefyCheckpoint = {
6581
startBlock: beefyStartBlock,
6682
current: {
67-
id: validatorSetId.toNumber(),
68-
root: tree.getHexRoot(),
69-
length: addrs.length,
83+
id: currentAuthorities.id.toNumber(),
84+
root: currentAuthorities.keysetCommitment.toHex(),
85+
length: currentAuthorities.len.toNumber(),
7086
},
7187
next: {
7288
id: nextAuthorities.id.toNumber(),

web/packages/test/config/beefy-relay.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"polkadot": {
44
"endpoint": "ws://127.0.0.1:9944"
55
},
6-
"beefy-activation-block": 0,
76
"fast-forward-depth": 20,
87
"update-period": 0
98
},

0 commit comments

Comments
 (0)