-
Notifications
You must be signed in to change notification settings - Fork 2
/
restore.go
129 lines (112 loc) · 4.44 KB
/
restore.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
package relay
import (
"bytes"
"context"
"fmt"
"log"
"reflect"
clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported"
lcptypes "github.com/datachainlab/lcp-go/light-clients/lcp/types"
"github.com/datachainlab/lcp-go/relay/elc"
"github.com/hyperledger-labs/yui-relayer/core"
)
func (pr *Prover) restoreELCState(ctx context.Context, counterparty core.FinalityAwareChain, height uint64) error {
// ensure the client does not exist in the LCP service
_, err := pr.lcpServiceClient.Client(ctx, &elc.QueryClientRequest{
ClientId: pr.config.ElcClientId,
})
if err == nil {
return fmt.Errorf("client '%v' already exists", pr.config.ElcClientId)
}
cplatestHeight, err := counterparty.LatestHeight()
if err != nil {
return err
}
counterpartyClientRes, err := counterparty.QueryClientState(core.NewQueryContext(context.TODO(), cplatestHeight))
if err != nil {
return err
}
var cs ibcexported.ClientState
if err := pr.codec.UnpackAny(counterpartyClientRes.ClientState, &cs); err != nil {
return err
}
var restoreHeight ibcexported.Height
if height == 0 {
restoreHeight = cs.GetLatestHeight()
} else {
restoreHeight = clienttypes.NewHeight(cs.GetLatestHeight().GetRevisionNumber(), height)
}
log.Printf("try to restore ELC state: height=%v", restoreHeight)
counterpartyConsRes, err := counterparty.QueryClientConsensusState(core.NewQueryContext(context.TODO(), cplatestHeight), restoreHeight)
if err != nil {
return err
}
var cons ibcexported.ConsensusState
if err := pr.codec.UnpackAny(counterpartyConsRes.ConsensusState, &cons); err != nil {
return err
}
clientState := cs.(*lcptypes.ClientState)
consensusState := cons.(*lcptypes.ConsensusState)
// Validate the prover config matches the counterparty's client state
if !bytes.Equal(pr.config.GetMrenclave(), clientState.Mrenclave) {
return fmt.Errorf("mrenclave mismatch: expected %v, but got %v", pr.config.GetMrenclave(), clientState.Mrenclave)
}
if pr.config.KeyExpiration != clientState.KeyExpiration {
return fmt.Errorf("key expiration mismatch: expected %v, but got %v", pr.config.KeyExpiration, clientState.KeyExpiration)
}
if len(pr.config.AllowedQuoteStatuses) != len(clientState.AllowedQuoteStatuses) {
return fmt.Errorf("allowed quote statuses mismatch: expected %v, but got %v", pr.config.AllowedQuoteStatuses, clientState.AllowedQuoteStatuses)
}
if !reflect.DeepEqual(pr.config.AllowedQuoteStatuses, clientState.AllowedQuoteStatuses) {
return fmt.Errorf("allowed advisory ids mismatch: expected %v, but got %v", pr.config.AllowedAdvisoryIds, clientState.AllowedAdvisoryIds)
}
if !reflect.DeepEqual(pr.config.AllowedAdvisoryIds, clientState.AllowedAdvisoryIds) {
return fmt.Errorf("allowed advisory ids mismatch: expected %v, but got %v", pr.config.AllowedAdvisoryIds, clientState.AllowedAdvisoryIds)
}
originClientState, originConsensusState, err := pr.originProver.CreateInitialLightClientState(clientState.LatestHeight)
if err != nil {
return err
}
originAnyClientState, err := clienttypes.PackClientState(originClientState)
if err != nil {
return err
}
originAnyConsensusState, err := clienttypes.PackConsensusState(originConsensusState)
if err != nil {
return err
}
tmpEKI, err := pr.selectNewEnclaveKey(context.TODO())
if err != nil {
return err
}
res, err := pr.lcpServiceClient.CreateClient(context.TODO(), &elc.MsgCreateClient{
ClientState: originAnyClientState,
ConsensusState: originAnyConsensusState,
Signer: tmpEKI.EnclaveKeyAddress,
})
if err != nil {
return err
}
// Ensure the restored state is correct
commitment, err := lcptypes.EthABIDecodeHeaderedMessage(res.Message)
if err != nil {
return err
}
ucm, err := commitment.GetUpdateClientMessage()
if err != nil {
return err
}
if !ucm.PostStateID.EqualBytes(consensusState.StateId) {
return fmt.Errorf("unexpected state id: expected %v, but got %v", ucm.PostStateID, consensusState.StateId)
}
if !ucm.PostHeight.EQ(restoreHeight) {
return fmt.Errorf("unexpected height: expected %v, but got %v", restoreHeight, ucm.PostHeight)
}
// TODO relayer should update res.ClientId in the config
if pr.config.ElcClientId != res.ClientId {
return fmt.Errorf("you must specify '%v' as elc_client_id, but got %v", res.ClientId, pr.config.ElcClientId)
}
log.Printf("successfully restored ELC state: client_id=%v, state_id=%v, height=%v", res.ClientId, ucm.PostStateID, ucm.PostHeight)
return nil
}