Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tss): remove key id check to reduce heartbeat gas costs #2173

Merged
merged 5 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.

2 changes: 1 addition & 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
milapsheth marked this conversation as resolved.
Show resolved Hide resolved
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
Loading