diff --git a/relay/cmd.go b/relay/cmd.go index 05a375e..68ed252 100644 --- a/relay/cmd.go +++ b/relay/cmd.go @@ -39,6 +39,7 @@ func LCPCmd(ctx *config.Context) *cobra.Command { restoreELCCmd(ctx), queryELCCmd(ctx), flags.LineBreak, + availableEnclaveKeysCmd(ctx), updateEnclaveKeyCmd(ctx), activateClientCmd(ctx), removeEnclaveKeyInfoCmd(ctx), @@ -48,6 +49,38 @@ func LCPCmd(ctx *config.Context) *cobra.Command { return cmd } +func availableEnclaveKeysCmd(ctx *config.Context) *cobra.Command { + cmd := &cobra.Command{ + Use: "available-enclave-keys [path]", + Short: "List available enclave keys", + 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 + if viper.GetBool(flagSrc) { + target = c[src] + } else { + target = c[dst] + } + prover := target.Prover.(*Prover) + ekis, err := prover.doAvailableEnclaveKeys(context.TODO()) + if err != nil { + return err + } + bz, err := json.Marshal(ekis) + if err != nil { + return err + } + fmt.Println(string(bz)) + return nil + }, + } + return srcFlag(cmd) +} + func updateEnclaveKeyCmd(ctx *config.Context) *cobra.Command { cmd := &cobra.Command{ Use: "update-enclave-key [path]", diff --git a/relay/lcp.go b/relay/lcp.go index 5f77e97..3c9dcca 100644 --- a/relay/lcp.go +++ b/relay/lcp.go @@ -5,6 +5,7 @@ import ( "context" "encoding/binary" "encoding/hex" + "encoding/json" "errors" "fmt" "time" @@ -462,6 +463,51 @@ func (pr *Prover) computeEIP712CosmosChainSalt() common.Hash { return lcptypes.ComputeCosmosChainSalt(params.ChainId, []byte(params.Prefix)) } +type AvailableEnclaveKeysResult struct { + Keys []*enclave.EnclaveKeyInfo `json:"keys"` +} + +func (res *AvailableEnclaveKeysResult) MarshalJSON() ([]byte, error) { + type enclaveKeyInfo struct { + EnclaveKeyAddress string `json:"enclave_key_address,omitempty"` + AttestationTime uint64 `json:"attestation_time,omitempty"` + Report string `json:"report,omitempty"` + Signature string `json:"signature,omitempty"` + SigningCert string `json:"signing_cert,omitempty"` + Extension string `json:"extension,omitempty"` + } + type availableEnclaveKeysResult struct { + Keys []*enclaveKeyInfo `json:"keys"` + } + var keys []*enclaveKeyInfo + for _, key := range res.Keys { + keys = append(keys, &enclaveKeyInfo{ + EnclaveKeyAddress: common.BytesToAddress(key.EnclaveKeyAddress).Hex(), + AttestationTime: key.AttestationTime, + Report: key.Report, + Signature: bytes2Hex(key.Signature), + SigningCert: bytes2Hex(key.SigningCert), + Extension: bytes2Hex(key.Extension), + }) + } + return json.Marshal(&availableEnclaveKeysResult{Keys: keys}) +} + +func bytes2Hex(b []byte) string { + if len(b) == 0 { + return "" + } + return "0x" + hex.EncodeToString(b) +} + +func (pr *Prover) doAvailableEnclaveKeys(ctx context.Context) (*AvailableEnclaveKeysResult, error) { + res, err := pr.lcpServiceClient.AvailableEnclaveKeys(ctx, &enclave.QueryAvailableEnclaveKeysRequest{Mrenclave: pr.config.GetMrenclave()}) + if err != nil { + return nil, err + } + return &AvailableEnclaveKeysResult{Keys: res.Keys}, nil +} + type CreateELCResult struct { Created bool `json:"created"` Message *lcptypes.UpdateStateProxyMessage `json:"message,omitempty"`