From 15a1930619c3c49731c78bcf875bd96614dc37ff Mon Sep 17 00:00:00 2001 From: Jun Kimura Date: Wed, 29 May 2024 18:17:12 +0900 Subject: [PATCH] add `update-elc` command Signed-off-by: Jun Kimura --- relay/cmd.go | 42 ++++++++++++++++++++++++++++++++++++++++-- relay/lcp.go | 45 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 78 insertions(+), 9 deletions(-) diff --git a/relay/cmd.go b/relay/cmd.go index 588fe0f..0e68083 100644 --- a/relay/cmd.go +++ b/relay/cmd.go @@ -10,8 +10,9 @@ import ( ) const ( - flagSrc = "src" - flagHeight = "height" + flagSrc = "src" + flagHeight = "height" + flagELCClientID = "elc_client_id" ) func LCPCmd(ctx *config.Context) *cobra.Command { @@ -22,6 +23,7 @@ func LCPCmd(ctx *config.Context) *cobra.Command { cmd.AddCommand( createELCCmd(ctx), + updateELCCmd(ctx), updateEnclaveKeyCmd(ctx), activateClientCmd(ctx), restoreELCStateCmd(ctx), @@ -114,6 +116,34 @@ func createELCCmd(ctx *config.Context) *cobra.Command { return heightFlag(srcFlag(cmd)) } +func updateELCCmd(ctx *config.Context) *cobra.Command { + cmd := &cobra.Command{ + Use: "update-elc [path]", + Short: "Update ELC client", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, src, dst, err := ctx.Config.ChainsFromPath(args[0]) + if err != nil { + return err + } + var ( + target *core.ProvableChain + counterparty *core.ProvableChain + ) + if viper.GetBool(flagSrc) { + target = c[src] + counterparty = c[dst] + } else { + target = c[dst] + counterparty = c[src] + } + prover := target.Prover.(*Prover) + return prover.doUpdateELC(viper.GetString(flagELCClientID), counterparty) + }, + } + return elcClientIDFlag(srcFlag(cmd)) +} + func restoreELCStateCmd(ctx *config.Context) *cobra.Command { cmd := &cobra.Command{ Use: "restore-elc-state [path]", @@ -186,3 +216,11 @@ func heightFlag(cmd *cobra.Command) *cobra.Command { } return cmd } + +func elcClientIDFlag(cmd *cobra.Command) *cobra.Command { + cmd.Flags().StringP("elc_client_id", "", "", "a client ID of the ELC client") + if err := viper.BindPFlag(flagELCClientID, cmd.Flags().Lookup(flagELCClientID)); err != nil { + panic(err) + } + return cmd +} diff --git a/relay/lcp.go b/relay/lcp.go index 8f58ae3..3f91155 100644 --- a/relay/lcp.go +++ b/relay/lcp.go @@ -261,11 +261,11 @@ func (pr *Prover) validateAdvisoryIDs(ids []string) bool { return targetSet.Difference(allowedSet).Cardinality() == 0 } -func (pr *Prover) syncUpstreamHeader(includeState bool) ([]*elc.MsgUpdateClientResponse, error) { +func (pr *Prover) updateELC(elcClientID string, includeState bool) ([]*elc.MsgUpdateClientResponse, error) { // 1. check if the latest height of the client is less than the given height - res, err := pr.lcpServiceClient.Client(context.TODO(), &elc.QueryClientRequest{ClientId: pr.config.ElcClientId}) + res, err := pr.lcpServiceClient.Client(context.TODO(), &elc.QueryClientRequest{ClientId: elcClientID}) if err != nil { return nil, err } @@ -282,11 +282,11 @@ func (pr *Prover) syncUpstreamHeader(includeState bool) ([]*elc.MsgUpdateClientR return nil, nil } - log.Printf("syncUpstreamHeader try to update the client in ELC: latest=%v got=%v", clientState.GetLatestHeight(), latestHeader.GetHeight()) + log.Printf("try to setup headers: elc_client_id=%v current=%v latest=%v", elcClientID, clientState.GetLatestHeight(), latestHeader.GetHeight()) // 2. query the header from the upstream chain - headers, err := pr.originProver.SetupHeadersForUpdate(NewLCPQuerier(pr.lcpServiceClient, pr.config.ElcClientId), latestHeader) + headers, err := pr.originProver.SetupHeadersForUpdate(NewLCPQuerier(pr.lcpServiceClient, elcClientID), latestHeader) if err != nil { return nil, err } @@ -302,7 +302,7 @@ func (pr *Prover) syncUpstreamHeader(includeState bool) ([]*elc.MsgUpdateClientR return nil, err } res, err := pr.lcpServiceClient.UpdateClient(context.TODO(), &elc.MsgUpdateClient{ - ClientId: pr.config.ElcClientId, + ClientId: elcClientID, Header: anyHeader, IncludeState: includeState, Signer: pr.activeEnclaveKey.EnclaveKeyAddress, @@ -374,10 +374,41 @@ func (pr *Prover) doCreateELC(height uint64) error { if err != nil { return err } - log.Printf("created state: post_height=%v post_state_id=0x%x", m.PostHeight, m.PostStateID) + log.Printf("created state: post_height=%v post_state_id=0x%x timestamp=%v", m.PostHeight, m.PostStateID, m.Timestamp.String()) return err } +// height: 0 means the latest height +func (pr *Prover) doUpdateELC(elcClientID string, counterparty core.FinalityAwareChain) error { + if err := pr.UpdateEKIfNeeded(context.TODO(), counterparty); err != nil { + return err + } + if elcClientID == "" { + elcClientID = pr.config.ElcClientId + } + log.Printf("try to update the ELC client: elc_client_id=%v", elcClientID) + updates, err := pr.updateELC(elcClientID, false) + if err != nil { + return err + } + if len(updates) == 0 { + log.Println("no update is needed") + return nil + } + for _, update := range updates { + commitment, err := lcptypes.EthABIDecodeHeaderedProxyMessage(update.Message) + if err != nil { + return err + } + usm, err := commitment.GetUpdateStateProxyMessage() + if err != nil { + return err + } + log.Printf("updated state: prev_height=%v prev_state_id=0x%x post_height=%v post_state_id=0x%x timestamp=%v", usm.PrevHeight, *usm.PrevStateID, usm.PostHeight, usm.PostStateID, usm.Timestamp.String()) + } + return nil +} + func (pr *Prover) createELC(height exported.Height) (*elc.MsgCreateClientResponse, error) { // NOTE: Query the LCP for available keys, but no need to register it into on-chain here tmpEKI, err := pr.selectNewEnclaveKey(context.TODO()) @@ -410,7 +441,7 @@ func activateClient(pathEnd *core.PathEnd, src, dst *core.ProvableChain) error { } // 1. LCP synchronises with the latest header of the upstream chain - updates, err := srcProver.syncUpstreamHeader(true) + updates, err := srcProver.updateELC(srcProver.config.ElcClientId, true) if err != nil { return err }