Skip to content

Commit

Permalink
feat(tss): remove key id check to reduce heartbeat gas costs (#2173) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
cgorenflo authored Aug 21, 2024
1 parent 8134137 commit 92e7003
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 164 deletions.
4 changes: 2 additions & 2 deletions client/docs/static/openapi/index.html

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions client/docs/static/openapi/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16808,6 +16808,7 @@ paths:
type: array
items:
type: string
title: "Deprecated: this field will be removed in the next release"
required: true
tags:
- MsgService
Expand Down Expand Up @@ -52868,6 +52869,7 @@ components:
type: array
items:
type: string
title: "Deprecated: this field will be removed in the next release"
axelar.tss.v1beta1.HeartBeatResponse:
type: object
axelar.tss.v1beta1.Params:
Expand Down
2 changes: 2 additions & 0 deletions client/docs/static/swagger/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18454,6 +18454,7 @@ paths:
type: array
items:
type: string
title: 'Deprecated: this field will be removed in the next release'
tags:
- MsgService
/axelar/tss/v1beta1/params:
Expand Down Expand Up @@ -57298,6 +57299,7 @@ definitions:
type: array
items:
type: string
title: 'Deprecated: this field will be removed in the next release'
axelar.tss.v1beta1.HeartBeatResponse:
type: object
axelar.tss.v1beta1.Params:
Expand Down
2 changes: 1 addition & 1 deletion client/docs/statik/statik.go

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion docs/proto/proto-docs.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions proto/axelar/tss/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,12 @@ message HeartBeatRequest {
bytes sender = 1 [ (gogoproto.casttype) =
"github.com/cosmos/cosmos-sdk/types.AccAddress" ];

// Deprecated: this field will be removed in the next release
repeated string key_ids = 2 [
(gogoproto.customname) = "KeyIDs",
(gogoproto.casttype) =
"github.com/axelarnetwork/axelar-core/x/tss/exported.KeyID"
];
"github.com/axelarnetwork/axelar-core/x/tss/exported.KeyID",
deprecated = true ]; // key_ids was deprecated in v1.0
}

message HeartBeatResponse {}
Expand Down
2 changes: 1 addition & 1 deletion third_party/proto/google/api/annotations.proto
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2015 Google LLC
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down
50 changes: 21 additions & 29 deletions third_party/proto/google/api/http.proto
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023 Google LLC
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -41,7 +41,7 @@ message Http {
bool fully_decode_reserved_expansion = 2;
}

// # gRPC Transcoding
// gRPC Transcoding
//
// gRPC Transcoding is a feature for mapping between a gRPC method and one or
// more HTTP REST endpoints. It allows developers to build a single API service
Expand Down Expand Up @@ -82,9 +82,8 @@ message Http {
//
// This enables an HTTP REST to gRPC mapping as below:
//
// HTTP | gRPC
// -----|-----
// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")`
// - HTTP: `GET /v1/messages/123456`
// - gRPC: `GetMessage(name: "messages/123456")`
//
// Any fields in the request message which are not bound by the path template
// automatically become HTTP query parameters if there is no HTTP request body.
Expand All @@ -108,11 +107,9 @@ message Http {
//
// This enables a HTTP JSON to RPC mapping as below:
//
// HTTP | gRPC
// -----|-----
// `GET /v1/messages/123456?revision=2&sub.subfield=foo` |
// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield:
// "foo"))`
// - HTTP: `GET /v1/messages/123456?revision=2&sub.subfield=foo`
// - gRPC: `GetMessage(message_id: "123456" revision: 2 sub:
// SubMessage(subfield: "foo"))`
//
// Note that fields which are mapped to URL query parameters must have a
// primitive type or a repeated primitive type or a non-repeated message type.
Expand Down Expand Up @@ -142,10 +139,8 @@ message Http {
// representation of the JSON in the request body is determined by
// protos JSON encoding:
//
// HTTP | gRPC
// -----|-----
// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id:
// "123456" message { text: "Hi!" })`
// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }`
// - gRPC: `UpdateMessage(message_id: "123456" message { text: "Hi!" })`
//
// The special name `*` can be used in the body mapping to define that
// every field not bound by the path template should be mapped to the
Expand All @@ -168,10 +163,8 @@ message Http {
//
// The following HTTP JSON to RPC mapping is enabled:
//
// HTTP | gRPC
// -----|-----
// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id:
// "123456" text: "Hi!")`
// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }`
// - gRPC: `UpdateMessage(message_id: "123456" text: "Hi!")`
//
// Note that when using `*` in the body mapping, it is not possible to
// have HTTP parameters, as all fields not bound by the path end in
Expand Down Expand Up @@ -199,13 +192,13 @@ message Http {
//
// This enables the following two alternative HTTP JSON to RPC mappings:
//
// HTTP | gRPC
// -----|-----
// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")`
// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id:
// "123456")`
// - HTTP: `GET /v1/messages/123456`
// - gRPC: `GetMessage(message_id: "123456")`
//
// ## Rules for HTTP mapping
// - HTTP: `GET /v1/users/me/messages/123456`
// - gRPC: `GetMessage(user_id: "me" message_id: "123456")`
//
// Rules for HTTP mapping
//
// 1. Leaf request fields (recursive expansion nested messages in the request
// message) are classified into three categories:
Expand All @@ -224,7 +217,7 @@ message Http {
// request body, all
// fields are passed via URL path and URL query parameters.
//
// ### Path template syntax
// Path template syntax
//
// Template = "/" Segments [ Verb ] ;
// Segments = Segment { "/" Segment } ;
Expand Down Expand Up @@ -263,7 +256,7 @@ message Http {
// Document](https://developers.google.com/discovery/v1/reference/apis) as
// `{+var}`.
//
// ## Using gRPC API Service Configuration
// Using gRPC API Service Configuration
//
// gRPC API Service Configuration (service config) is a configuration language
// for configuring a gRPC service to become a user-facing product. The
Expand All @@ -278,15 +271,14 @@ message Http {
// specified in the service config will override any matching transcoding
// configuration in the proto.
//
// Example:
// The following example selects a gRPC method and applies an `HttpRule` to it:
//
// http:
// rules:
// # Selects a gRPC method and applies HttpRule to it.
// - selector: example.v1.Messaging.GetMessage
// get: /v1/messages/{message_id}/{sub.subfield}
//
// ## Special notes
// Special notes
//
// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the
// proto to JSON conversion must follow the [proto3
Expand Down
67 changes: 6 additions & 61 deletions vald/tss/tss.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import (
"google.golang.org/grpc"

"github.com/axelarnetwork/axelar-core/sdk-utils/broadcast"
"github.com/axelarnetwork/axelar-core/vald/parse"
"github.com/axelarnetwork/axelar-core/vald/tss/rpc"
"github.com/axelarnetwork/axelar-core/x/tss/exported"
"github.com/axelarnetwork/axelar-core/x/tss/tofnd"
tss "github.com/axelarnetwork/axelar-core/x/tss/types"
tmEvents "github.com/axelarnetwork/tm-events/events"
Expand Down Expand Up @@ -55,12 +53,12 @@ func NewMgr(multiSigClient rpc.MultiSigClient, cliCtx sdkClient.Context, timeout
}

// ProcessHeartBeatEvent broadcasts the heartbeat
func (mgr *Mgr) ProcessHeartBeatEvent(e tmEvents.Event) error {
func (mgr *Mgr) ProcessHeartBeatEvent(_ tmEvents.Event) error {
grpcCtx, cancel := context.WithTimeout(context.Background(), mgr.Timeout)
defer cancel()

// tofnd health check using a dummy ID
// TODO: we should have a specific GRPC to do this diagnostic
// tofnd health check
// this just checks if tofnd is up and running, so a dummy ID is fine
request := &tofnd.KeyPresenceRequest{
KeyUid: "dummyID",
PubKey: []byte{},
Expand All @@ -76,51 +74,15 @@ func (mgr *Mgr) ProcessHeartBeatEvent(e tmEvents.Event) error {
return sdkerrors.Wrap(err, "tofnd not set up correctly")
case tofnd.RESPONSE_PRESENT, tofnd.RESPONSE_ABSENT:
// tofnd is working properly
break
default:
return sdkerrors.Wrap(err, "unknown tofnd response")
}

// check for keys presence according to the IDs included in the event
keyInfos := parseHeartBeatParams(mgr.cdc, e.Attributes)
var present []exported.KeyID

for _, keyInfo := range keyInfos {

grpcCtx, cancel = context.WithTimeout(context.Background(), mgr.Timeout)
defer cancel()

switch keyInfo.KeyType {
case exported.Multisig:
request = &tofnd.KeyPresenceRequest{
KeyUid: fmt.Sprintf("%s_%d", string(keyInfo.KeyID), 0),
PubKey: []byte{},
}

response, err = mgr.multiSigClient.KeyPresence(grpcCtx, request)
default:
return sdkerrors.Wrapf(err, fmt.Sprintf("unrecognize key type %s", keyInfo.KeyType.SimpleString()))
}

if err != nil {
return sdkerrors.Wrapf(err, "failed to invoke KeyPresence grpc")
}

switch response.Response {
case tofnd.RESPONSE_UNSPECIFIED, tofnd.RESPONSE_FAIL:
return sdkerrors.Wrap(err, "tofnd not set up correctly")
case tofnd.RESPONSE_ABSENT:
// key is absent
case tofnd.RESPONSE_PRESENT:
present = append(present, keyInfo.KeyID)
default:
return sdkerrors.Wrap(err, "unknown tofnd response")
}
}

tssMsg := tss.NewHeartBeatRequest(mgr.cliCtx.FromAddress, present)
tssMsg := tss.NewHeartBeatRequest(mgr.cliCtx.FromAddress)

logger := log.With("listener", "tss")
logger.Info(fmt.Sprintf("operator %s sending heartbeat acknowledging keys: %s", mgr.principalAddr, present))
logger.Info(fmt.Sprintf("operator %s sending heartbeat", mgr.principalAddr))
if _, err := mgr.broadcaster.Broadcast(context.TODO(), tssMsg); err != nil {
return sdkerrors.Wrap(err, "handler goroutine: failure to broadcast outgoing heartbeat msg")
}
Expand All @@ -129,20 +91,3 @@ func (mgr *Mgr) ProcessHeartBeatEvent(e tmEvents.Event) error {

return nil
}

func parseHeartBeatParams(cdc *codec.LegacyAmino, attributes map[string]string) []tss.KeyInfo {
parsers := []*parse.AttributeParser{
{Key: tss.AttributeKeyKeyInfos, Map: func(s string) (interface{}, error) {
var keyInfos []tss.KeyInfo
cdc.MustUnmarshalJSON([]byte(s), &keyInfos)
return keyInfos, nil
}},
}

results, err := parse.Parse(attributes, parsers)
if err != nil {
panic(err)
}

return results[0].([]tss.KeyInfo)
}
7 changes: 3 additions & 4 deletions x/tss/types/msg_ack.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

"github.com/axelarnetwork/axelar-core/x/tss/exported"
)

// NewHeartBeatRequest constructor for AckRequest
func NewHeartBeatRequest(sender sdk.AccAddress, keyIDs []exported.KeyID) *HeartBeatRequest {
return &HeartBeatRequest{Sender: sender, KeyIDs: keyIDs}
func NewHeartBeatRequest(sender sdk.AccAddress) *HeartBeatRequest {
// TODO: completely remove keyIDs from the message
return &HeartBeatRequest{Sender: sender, KeyIDs: nil}
}

// Route implements the sdk.Msg interface.
Expand Down
Loading

0 comments on commit 92e7003

Please sign in to comment.