/
parachain_head_proof.go
148 lines (126 loc) · 4.25 KB
/
parachain_head_proof.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
package cmd
import (
"errors"
"fmt"
log "github.com/sirupsen/logrus"
"github.com/snowfork/go-substrate-rpc-client/v4/types"
"github.com/snowfork/snowbridge/relayer/chain/relaychain"
"github.com/snowfork/snowbridge/relayer/relays/parachain"
"github.com/spf13/cobra"
)
func parachainHeadProofCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "parachain-head-proof",
Short: "Prove a block using beefy.",
Args: cobra.ExactArgs(0),
RunE: ParachainHeadProofFn,
}
cmd.Flags().StringP("url", "u", "", "Polkadot URL")
cmd.MarkFlagRequired("url")
cmd.Flags().BytesHex(
"beefy-block-hash",
[]byte{},
"Latest block finalized by BEEFY",
)
cmd.MarkFlagRequired("beefy-block-hash")
cmd.Flags().Uint64(
"relaychain-block",
0,
"The relaychain block in which the parachain header was was accepted.",
)
cmd.MarkFlagRequired("relaychain-block")
cmd.Flags().Uint32(
"parachain-id",
0,
"The parachain id for the block you are trying to prove.",
)
cmd.MarkFlagRequired("parachain-id")
cmd.Flags().Uint64(
"parachain-block",
0,
"The parachain block you are trying to prove. i.e. The block containing the message.",
)
cmd.MarkFlagRequired("parachain-block")
return cmd
}
func ParachainHeadProofFn(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
url, _ := cmd.Flags().GetString("url")
conn := relaychain.NewConnection(url)
err := conn.Connect(ctx)
if err != nil {
log.WithError(err).Error("Cannot connect.")
return err
}
beefyBlockHashHex, _ := cmd.Flags().GetBytesHex("beefy-block-hash")
if len(beefyBlockHashHex) != 32 {
log.Error("Incorrect length of beefy block hash.")
return errors.New("incorrect block hash length")
}
var beefyBlockHash types.Hash
copy(beefyBlockHash[:], beefyBlockHashHex[0:32])
relayChainBlock, _ := cmd.Flags().GetUint64("relaychain-block")
mmrProof, err := conn.GenerateProofForBlock(relayChainBlock, beefyBlockHash)
if err != nil {
log.WithError(err).Error("Cannot connect.")
return err
}
log.WithFields(log.Fields{
"relayChainBlock": relayChainBlock,
"beefyBlockHash": beefyBlockHash,
"mmrProof": mmrProof,
}).Info("conn.GenerateProofForBlock")
paraID, _ := cmd.Flags().GetUint32("parachain-id")
parachainBlock, _ := cmd.Flags().GetUint64("parachain-block")
relayChainBlockHash, err := conn.API().RPC.Chain.GetBlockHash(relayChainBlock)
if err != nil {
log.WithError(err).Error("Cannot fetch parachain block hash.")
return err
}
paraHeadsAsSlice, err := conn.FetchParachainHeads(relayChainBlockHash)
if err != nil {
log.WithError(err).Error("Cannot fetch parachain headers")
return err
}
var parachainHeader types.Header
ok, err := conn.FetchParachainHead(relayChainBlockHash, paraID, ¶chainHeader)
if err != nil {
log.WithError(err).Error("Cannot fetch our parachain header")
return err
}
if !ok {
log.WithError(err).Error("parachain is not registered")
return fmt.Errorf("parachain is not registered")
}
log.WithFields(log.Fields{
"paraHeadsAsSlice": paraHeadsAsSlice,
"parachainHeader": parachainHeader,
"paraId": paraID,
"relayChainBlockHash": relayChainBlockHash.Hex(),
}).Info("parachain.CreateParachainMerkleProof")
merkleProofData, err := parachain.CreateParachainMerkleProof(paraHeadsAsSlice, paraID)
if err != nil {
log.WithError(err).Error("Cannot create merkle proof.")
return err
}
log.WithFields(log.Fields{
"paraHeadsAsSlice": paraHeadsAsSlice,
"paraId": paraID,
"merkleProofData": merkleProofData,
}).Info("parachain.CreateParachainMerkleProof")
log.WithFields(log.Fields{
"parachainId": paraID,
"relaychainBlockHash": relayChainBlockHash.Hex(),
"relaychainBlockNumber": relayChainBlock,
"parachainBlockNumber": parachainBlock,
"paraHeads": paraHeadsAsSlice,
"parachainHeader": parachainHeader,
}).Info("Generated proof input for parachain block.")
log.WithFields(log.Fields{
"mmrProofParachainHeads": mmrProof.Leaf.ParachainHeads.Hex(),
"mmrProofParentNumberAndHash": mmrProof.Leaf.ParentNumberAndHash,
"computedProofParachainHeads": merkleProofData.Root.Hex(),
"computedProofParentNumberAndHash": types.ParentNumberAndHash{ParentNumber: types.U32(relayChainBlock), Hash: relayChainBlockHash},
}).Info("Complete.")
return nil
}