diff --git a/RELEASES.md b/RELEASES.md index b76a14a347..dee9ff8cf8 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -6,6 +6,7 @@ - Add metrics for ACP-176 - Removed the `"price-options-max-base-fee"` config flag - Moved extra types returned in `ethclient` package to a new package `plugin/evm/customethclient` which supports the same functionality as `ethclient` but with the new types registered in header and block. +- Removed legacy warp message handlers in favor of ACP-118 SDK handlers. ## [v0.15.0](https://github.com/ava-labs/coreth/releases/tag/v0.15.0) diff --git a/plugin/evm/message/codec.go b/plugin/evm/message/codec.go index a1ce7ff86e..c3f1a6795f 100644 --- a/plugin/evm/message/codec.go +++ b/plugin/evm/message/codec.go @@ -32,14 +32,13 @@ func init() { c.RegisterType(LeafsResponse{}), c.RegisterType(CodeRequest{}), c.RegisterType(CodeResponse{}), + ) - // Warp request types - c.RegisterType(MessageSignatureRequest{}), - c.RegisterType(BlockSignatureRequest{}), - c.RegisterType(SignatureResponse{}), + // Deprecated Warp request/responde types are skipped + // See https://github.com/ava-labs/coreth/pull/999 + c.SkipRegistrations(3) - Codec.RegisterCodec(Version, c), - ) + Codec.RegisterCodec(Version, c) if errs.Errored() { panic(errs.Err) diff --git a/plugin/evm/message/handler.go b/plugin/evm/message/handler.go index ac39bdc761..d25d28a00f 100644 --- a/plugin/evm/message/handler.go +++ b/plugin/evm/message/handler.go @@ -19,8 +19,6 @@ type RequestHandler interface { HandleLeafsRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, leafsRequest LeafsRequest) ([]byte, error) HandleBlockRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, request BlockRequest) ([]byte, error) HandleCodeRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, codeRequest CodeRequest) ([]byte, error) - HandleMessageSignatureRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, signatureRequest MessageSignatureRequest) ([]byte, error) - HandleBlockSignatureRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, signatureRequest BlockSignatureRequest) ([]byte, error) } // ResponseHandler handles response for a sent request @@ -45,11 +43,3 @@ func (NoopRequestHandler) HandleBlockRequest(ctx context.Context, nodeID ids.Nod func (NoopRequestHandler) HandleCodeRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, codeRequest CodeRequest) ([]byte, error) { return nil, nil } - -func (NoopRequestHandler) HandleMessageSignatureRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, signatureRequest MessageSignatureRequest) ([]byte, error) { - return nil, nil -} - -func (NoopRequestHandler) HandleBlockSignatureRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, signatureRequest BlockSignatureRequest) ([]byte, error) { - return nil, nil -} diff --git a/plugin/evm/message/signature_request.go b/plugin/evm/message/signature_request.go deleted file mode 100644 index 384b54ca3c..0000000000 --- a/plugin/evm/message/signature_request.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package message - -import ( - "context" - "fmt" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/crypto/bls" -) - -var ( - _ Request = MessageSignatureRequest{} - _ Request = BlockSignatureRequest{} -) - -// MessageSignatureRequest is used to request a warp message's signature. -type MessageSignatureRequest struct { - MessageID ids.ID `serialize:"true"` -} - -func (s MessageSignatureRequest) String() string { - return fmt.Sprintf("MessageSignatureRequest(MessageID=%s)", s.MessageID.String()) -} - -func (s MessageSignatureRequest) Handle(ctx context.Context, nodeID ids.NodeID, requestID uint32, handler RequestHandler) ([]byte, error) { - return handler.HandleMessageSignatureRequest(ctx, nodeID, requestID, s) -} - -// BlockSignatureRequest is used to request a warp message's signature. -type BlockSignatureRequest struct { - BlockID ids.ID `serialize:"true"` -} - -func (s BlockSignatureRequest) String() string { - return fmt.Sprintf("BlockSignatureRequest(BlockID=%s)", s.BlockID.String()) -} - -func (s BlockSignatureRequest) Handle(ctx context.Context, nodeID ids.NodeID, requestID uint32, handler RequestHandler) ([]byte, error) { - return handler.HandleBlockSignatureRequest(ctx, nodeID, requestID, s) -} - -// SignatureResponse is the response to a BlockSignatureRequest or MessageSignatureRequest. -// The response contains a BLS signature of the requested message, signed by the responding node's BLS private key. -type SignatureResponse struct { - Signature [bls.SignatureLen]byte `serialize:"true"` -} diff --git a/plugin/evm/message/signature_request_test.go b/plugin/evm/message/signature_request_test.go deleted file mode 100644 index dea154e16b..0000000000 --- a/plugin/evm/message/signature_request_test.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package message - -import ( - "encoding/base64" - "encoding/hex" - "testing" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/crypto/bls" - "github.com/stretchr/testify/require" -) - -// TestMarshalMessageSignatureRequest asserts that the structure or serialization logic hasn't changed, primarily to -// ensure compatibility with the network. -func TestMarshalMessageSignatureRequest(t *testing.T) { - signatureRequest := MessageSignatureRequest{ - MessageID: ids.ID{68, 79, 70, 65, 72, 73, 64, 107}, - } - - base64MessageSignatureRequest := "AABET0ZBSElAawAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - signatureRequestBytes, err := Codec.Marshal(Version, signatureRequest) - require.NoError(t, err) - require.Equal(t, base64MessageSignatureRequest, base64.StdEncoding.EncodeToString(signatureRequestBytes)) - - var s MessageSignatureRequest - _, err = Codec.Unmarshal(signatureRequestBytes, &s) - require.NoError(t, err) - require.Equal(t, signatureRequest.MessageID, s.MessageID) -} - -// TestMarshalBlockSignatureRequest asserts that the structure or serialization logic hasn't changed, primarily to -// ensure compatibility with the network. -func TestMarshalBlockSignatureRequest(t *testing.T) { - signatureRequest := BlockSignatureRequest{ - BlockID: ids.ID{68, 79, 70, 65, 72, 73, 64, 107}, - } - - base64BlockSignatureRequest := "AABET0ZBSElAawAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - signatureRequestBytes, err := Codec.Marshal(Version, signatureRequest) - require.NoError(t, err) - require.Equal(t, base64BlockSignatureRequest, base64.StdEncoding.EncodeToString(signatureRequestBytes)) - - var s BlockSignatureRequest - _, err = Codec.Unmarshal(signatureRequestBytes, &s) - require.NoError(t, err) - require.Equal(t, signatureRequest.BlockID, s.BlockID) -} - -// TestMarshalSignatureResponse asserts that the structure or serialization logic hasn't changed, primarily to -// ensure compatibility with the network. -func TestMarshalSignatureResponse(t *testing.T) { - var signature [bls.SignatureLen]byte - sig, err := hex.DecodeString("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef") - require.NoError(t, err, "failed to decode string to hex") - - copy(signature[:], sig) - signatureResponse := SignatureResponse{ - Signature: signature, - } - - base64SignatureResponse := "AAABI0VniavN7wEjRWeJq83vASNFZ4mrze8BI0VniavN7wEjRWeJq83vASNFZ4mrze8BI0VniavN7wEjRWeJq83vASNFZ4mrze8BI0VniavN7wEjRWeJq83vASNFZ4mrze8=" - signatureResponseBytes, err := Codec.Marshal(Version, signatureResponse) - require.NoError(t, err) - require.Equal(t, base64SignatureResponse, base64.StdEncoding.EncodeToString(signatureResponseBytes)) - - var s SignatureResponse - _, err = Codec.Unmarshal(signatureResponseBytes, &s) - require.NoError(t, err) - require.Equal(t, signatureResponse.Signature, s.Signature) -} diff --git a/plugin/evm/network_handler.go b/plugin/evm/network_handler.go index fb5162e17e..7eae1a7483 100644 --- a/plugin/evm/network_handler.go +++ b/plugin/evm/network_handler.go @@ -12,7 +12,6 @@ import ( syncHandlers "github.com/ava-labs/coreth/sync/handlers" "github.com/ava-labs/coreth/sync/handlers/stats" "github.com/ava-labs/coreth/warp" - warpHandlers "github.com/ava-labs/coreth/warp/handlers" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/triedb" @@ -23,10 +22,9 @@ var _ message.RequestHandler = (*networkHandler)(nil) type LeafHandlers map[message.NodeType]syncHandlers.LeafRequestHandler type networkHandler struct { - leafRequestHandlers LeafHandlers - blockRequestHandler *syncHandlers.BlockRequestHandler - codeRequestHandler *syncHandlers.CodeRequestHandler - signatureRequestHandler *warpHandlers.SignatureRequestHandler + leafRequestHandlers LeafHandlers + blockRequestHandler *syncHandlers.BlockRequestHandler + codeRequestHandler *syncHandlers.CodeRequestHandler } type LeafRequestTypeConfig struct { @@ -47,10 +45,9 @@ func newNetworkHandler( syncStats stats.HandlerStats, ) *networkHandler { return &networkHandler{ - leafRequestHandlers: leafRequestHandlers, - blockRequestHandler: syncHandlers.NewBlockRequestHandler(provider, networkCodec, syncStats), - codeRequestHandler: syncHandlers.NewCodeRequestHandler(diskDB, networkCodec, syncStats), - signatureRequestHandler: warpHandlers.NewSignatureRequestHandler(warpBackend, networkCodec), + leafRequestHandlers: leafRequestHandlers, + blockRequestHandler: syncHandlers.NewBlockRequestHandler(provider, networkCodec, syncStats), + codeRequestHandler: syncHandlers.NewCodeRequestHandler(diskDB, networkCodec, syncStats), } } @@ -70,11 +67,3 @@ func (n networkHandler) HandleBlockRequest(ctx context.Context, nodeID ids.NodeI func (n networkHandler) HandleCodeRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, codeRequest message.CodeRequest) ([]byte, error) { return n.codeRequestHandler.OnCodeRequest(ctx, nodeID, requestID, codeRequest) } - -func (n networkHandler) HandleMessageSignatureRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, messageSignatureRequest message.MessageSignatureRequest) ([]byte, error) { - return n.signatureRequestHandler.OnMessageSignatureRequest(ctx, nodeID, requestID, messageSignatureRequest) -} - -func (n networkHandler) HandleBlockSignatureRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, blockSignatureRequest message.BlockSignatureRequest) ([]byte, error) { - return n.signatureRequestHandler.OnBlockSignatureRequest(ctx, nodeID, requestID, blockSignatureRequest) -} diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index 7b1d2ac69a..2ec5e28f79 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -1091,8 +1091,10 @@ func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { } if vm.config.WarpAPIEnabled { - warpAPI := warp.NewAPI(vm.ctx, vm.networkCodec, vm.warpBackend, vm.Network, vm.requirePrimaryNetworkSigners) - if err := handler.RegisterName("warp", warpAPI); err != nil { + warpSDKClient := vm.Network.NewClient(p2p.SignatureRequestHandlerID) + signatureAggregator := acp118.NewSignatureAggregator(vm.ctx.Log, warpSDKClient) + + if err := handler.RegisterName("warp", warp.NewAPI(vm.ctx, vm.warpBackend, signatureAggregator, vm.requirePrimaryNetworkSigners)); err != nil { return nil, err } enabledAPIs = append(enabledAPIs, "warp") diff --git a/plugin/evm/vm_warp_test.go b/plugin/evm/vm_warp_test.go index 15b8f8f00a..572c0bf760 100644 --- a/plugin/evm/vm_warp_test.go +++ b/plugin/evm/vm_warp_test.go @@ -14,6 +14,9 @@ import ( _ "embed" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/network/p2p" + "github.com/ava-labs/avalanchego/network/p2p/acp118" + "github.com/ava-labs/avalanchego/proto/pb/sdk" commonEng "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/enginetest" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" @@ -34,7 +37,6 @@ import ( "github.com/ava-labs/coreth/params/extras" "github.com/ava-labs/coreth/plugin/evm/extension" customheader "github.com/ava-labs/coreth/plugin/evm/header" - "github.com/ava-labs/coreth/plugin/evm/message" "github.com/ava-labs/coreth/plugin/evm/upgrade/ap0" "github.com/ava-labs/coreth/precompile/contract" warpcontract "github.com/ava-labs/coreth/precompile/contracts/warp" @@ -46,6 +48,7 @@ import ( "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" ) var ( @@ -732,7 +735,7 @@ func testReceiveWarpMessage( require.JSONEq(string(txTraceResultBytes), string(blockTxTraceResultBytes)) } -func TestMessageSignatureRequestsToVM(t *testing.T) { +func TestSignatureRequestsToVM(t *testing.T) { fork := upgradetest.Durango tvm := newVM(t, testVMConfig{ fork: &fork, @@ -741,112 +744,107 @@ func TestMessageSignatureRequestsToVM(t *testing.T) { require.NoError(t, tvm.vm.Shutdown(context.Background())) }() - // Generate a new warp unsigned message and add to warp backend - warpMessage, err := avalancheWarp.NewUnsignedMessage(tvm.vm.ctx.NetworkID, tvm.vm.ctx.ChainID, []byte{1, 2, 3}) + // Setup known message + knownPayload, err := payload.NewAddressedCall([]byte{0, 0, 0}, []byte("test")) require.NoError(t, err) - - // Add the known message and get its signature to confirm. - require.NoError(t, tvm.vm.warpBackend.AddMessage(warpMessage)) - signature, err := tvm.vm.warpBackend.GetMessageSignature(context.TODO(), warpMessage) + knownWarpMessage, err := avalancheWarp.NewUnsignedMessage(tvm.vm.ctx.NetworkID, tvm.vm.ctx.ChainID, knownPayload.Bytes()) require.NoError(t, err) - var knownSignature [bls.SignatureLen]byte - copy(knownSignature[:], signature) - - tests := map[string]struct { - messageID ids.ID - expectedResponse [bls.SignatureLen]byte - }{ - "known": { - messageID: warpMessage.ID(), - expectedResponse: knownSignature, - }, - "unknown": { - messageID: ids.GenerateTestID(), - expectedResponse: [bls.SignatureLen]byte{}, - }, - } - - for name, test := range tests { - calledSendAppResponseFn := false - tvm.appSender.SendAppResponseF = func(ctx context.Context, nodeID ids.NodeID, requestID uint32, responseBytes []byte) error { - calledSendAppResponseFn = true - var response message.SignatureResponse - _, err := message.Codec.Unmarshal(responseBytes, &response) - require.NoError(t, err) - require.Equal(t, test.expectedResponse, response.Signature) - - return nil - } - t.Run(name, func(t *testing.T) { - var signatureRequest message.Request = message.MessageSignatureRequest{ - MessageID: test.messageID, - } - - requestBytes, err := message.Codec.Marshal(message.Version, &signatureRequest) - require.NoError(t, err) - // Send the app request and make sure we called SendAppResponseFn - deadline := time.Now().Add(60 * time.Second) - require.NoError(t, tvm.vm.Network.AppRequest(context.Background(), ids.GenerateTestNodeID(), 0, deadline, requestBytes)) - require.True(t, calledSendAppResponseFn) - }) - } -} - -func TestBlockSignatureRequestsToVM(t *testing.T) { - fork := upgradetest.Durango - tvm := newVM(t, testVMConfig{ - fork: &fork, - }) - defer func() { - require.NoError(t, tvm.vm.Shutdown(context.Background())) - }() + // Add the known message and get its signature to confirm + require.NoError(t, tvm.vm.warpBackend.AddMessage(knownWarpMessage)) + knownMessageSignature, err := tvm.vm.warpBackend.GetMessageSignature(context.TODO(), knownWarpMessage) + require.NoError(t, err) + // Setup known block lastAcceptedID, err := tvm.vm.LastAccepted(context.Background()) require.NoError(t, err) - - signature, err := tvm.vm.warpBackend.GetBlockSignature(context.TODO(), lastAcceptedID) + knownBlockSignature, err := tvm.vm.warpBackend.GetBlockSignature(context.TODO(), lastAcceptedID) require.NoError(t, err) - var knownSignature [bls.SignatureLen]byte - copy(knownSignature[:], signature) - - tests := map[string]struct { - blockID ids.ID - expectedResponse [bls.SignatureLen]byte - }{ - "known": { - blockID: lastAcceptedID, - expectedResponse: knownSignature, + + type testCase struct { + name string + message *avalancheWarp.UnsignedMessage + expectedResponse []byte + err *commonEng.AppError + } + + tests := []testCase{ + { + name: "known message", + message: knownWarpMessage, + expectedResponse: knownMessageSignature, }, - "unknown": { - blockID: ids.GenerateTestID(), - expectedResponse: [bls.SignatureLen]byte{}, + { + name: "unknown message", + message: func() *avalancheWarp.UnsignedMessage { + unknownPayload, err := payload.NewAddressedCall([]byte{1, 1, 1}, []byte("unknown")) + require.NoError(t, err) + msg, err := avalancheWarp.NewUnsignedMessage(tvm.vm.ctx.NetworkID, tvm.vm.ctx.ChainID, unknownPayload.Bytes()) + require.NoError(t, err) + return msg + }(), + err: &commonEng.AppError{Code: warp.ParseErrCode}, + }, + { + name: "known block", + message: func() *avalancheWarp.UnsignedMessage { + payload, err := payload.NewHash(lastAcceptedID) + require.NoError(t, err) + msg, err := avalancheWarp.NewUnsignedMessage(tvm.vm.ctx.NetworkID, tvm.vm.ctx.ChainID, payload.Bytes()) + require.NoError(t, err) + return msg + }(), + expectedResponse: knownBlockSignature, + }, + { + name: "unknown block", + message: func() *avalancheWarp.UnsignedMessage { + payload, err := payload.NewHash(ids.GenerateTestID()) + require.NoError(t, err) + msg, err := avalancheWarp.NewUnsignedMessage(tvm.vm.ctx.NetworkID, tvm.vm.ctx.ChainID, payload.Bytes()) + require.NoError(t, err) + return msg + }(), + err: &commonEng.AppError{Code: warp.VerifyErrCode}, }, } - for name, test := range tests { - calledSendAppResponseFn := false - tvm.appSender.SendAppResponseF = func(ctx context.Context, nodeID ids.NodeID, requestID uint32, responseBytes []byte) error { - calledSendAppResponseFn = true - var response message.SignatureResponse - _, err := message.Codec.Unmarshal(responseBytes, &response) - require.NoError(t, err) - require.Equal(t, test.expectedResponse, response.Signature) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + calledSendAppResponseFn := false + calledSendAppErrorFn := false + + tvm.appSender.SendAppResponseF = func(ctx context.Context, nodeID ids.NodeID, requestID uint32, responseBytes []byte) error { + calledSendAppResponseFn = true + var response sdk.SignatureResponse + if err := proto.Unmarshal(responseBytes, &response); err != nil { + return err + } + require.Equal(t, test.expectedResponse, response.Signature) + return nil + } - return nil - } - t.Run(name, func(t *testing.T) { - var signatureRequest message.Request = message.BlockSignatureRequest{ - BlockID: test.blockID, + tvm.appSender.SendAppErrorF = func(ctx context.Context, nodeID ids.NodeID, requestID uint32, errCode int32, errString string) error { + calledSendAppErrorFn = true + require.ErrorIs(t, test.err, test.err) + return nil } - requestBytes, err := message.Codec.Marshal(message.Version, &signatureRequest) + protoMsg := &sdk.SignatureRequest{Message: test.message.Bytes()} + requestBytes, err := proto.Marshal(protoMsg) require.NoError(t, err) + msg := p2p.PrefixMessage(p2p.ProtocolPrefix(acp118.HandlerID), requestBytes) - // Send the app request and make sure we called SendAppResponseFn + // Send the app request and verify the response deadline := time.Now().Add(60 * time.Second) - require.NoError(t, tvm.vm.Network.AppRequest(context.Background(), ids.GenerateTestNodeID(), 0, deadline, requestBytes)) - require.True(t, calledSendAppResponseFn) + appErr := tvm.vm.Network.AppRequest(context.Background(), ids.GenerateTestNodeID(), 1, deadline, msg) + require.Nil(t, appErr) + + if test.err != nil { + require.True(t, calledSendAppErrorFn) + } else { + require.True(t, calledSendAppResponseFn) + } }) } } diff --git a/warp/aggregator/aggregator.go b/tests/warp/aggregator/aggregator.go similarity index 100% rename from warp/aggregator/aggregator.go rename to tests/warp/aggregator/aggregator.go diff --git a/warp/aggregator/aggregator_test.go b/tests/warp/aggregator/aggregator_test.go similarity index 100% rename from warp/aggregator/aggregator_test.go rename to tests/warp/aggregator/aggregator_test.go diff --git a/warp/aggregator/mock_signature_getter.go b/tests/warp/aggregator/mock_signature_getter.go similarity index 100% rename from warp/aggregator/mock_signature_getter.go rename to tests/warp/aggregator/mock_signature_getter.go diff --git a/warp/aggregator/mocks_generate_test.go b/tests/warp/aggregator/mocks_generate_test.go similarity index 100% rename from warp/aggregator/mocks_generate_test.go rename to tests/warp/aggregator/mocks_generate_test.go diff --git a/warp/aggregator/signature_getter.go b/tests/warp/aggregator/signature_getter.go similarity index 73% rename from warp/aggregator/signature_getter.go rename to tests/warp/aggregator/signature_getter.go index cc6a3fe515..8f03814f5e 100644 --- a/warp/aggregator/signature_getter.go +++ b/tests/warp/aggregator/signature_getter.go @@ -10,10 +10,10 @@ import ( "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/proto/pb/sdk" "github.com/ava-labs/avalanchego/utils/crypto/bls" avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" - "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" - "github.com/ava-labs/coreth/plugin/evm/message" + "google.golang.org/protobuf/proto" ) const ( @@ -53,35 +53,17 @@ func NewSignatureGetter(client NetworkClient, networkCodec codec.Manager) *Netwo // Note: this function will continue attempting to fetch the signature from [nodeID] until it receives an invalid value or [ctx] is cancelled. // The caller is responsible to cancel [ctx] if it no longer needs to fetch this signature. func (s *NetworkSignatureGetter) GetSignature(ctx context.Context, nodeID ids.NodeID, unsignedWarpMessage *avalancheWarp.UnsignedMessage) (*bls.Signature, error) { - var signatureReqBytes []byte - parsedPayload, err := payload.Parse(unsignedWarpMessage.Payload) + protoMsg := &sdk.SignatureRequest{Message: unsignedWarpMessage.Bytes()} + protoBytes, err := proto.Marshal(protoMsg) if err != nil { - return nil, fmt.Errorf("failed to parse unsigned message payload: %w", err) - } - switch p := parsedPayload.(type) { - case *payload.AddressedCall: - signatureReq := message.MessageSignatureRequest{ - MessageID: unsignedWarpMessage.ID(), - } - signatureReqBytes, err = message.RequestToBytes(s.networkCodec, signatureReq) - if err != nil { - return nil, fmt.Errorf("failed to marshal signature request: %w", err) - } - case *payload.Hash: - signatureReq := message.BlockSignatureRequest{ - BlockID: p.Hash, - } - signatureReqBytes, err = message.RequestToBytes(s.networkCodec, signatureReq) - if err != nil { - return nil, fmt.Errorf("failed to marshal signature request: %w", err) - } + return nil, fmt.Errorf("failed to marshal signature request: %w", err) } delay := initialRetryFetchSignatureDelay timer := time.NewTimer(delay) defer timer.Stop() for { - signatureRes, err := s.client.SendSyncedAppRequest(ctx, nodeID, signatureReqBytes) + signatureRes, err := s.client.SendSyncedAppRequest(ctx, nodeID, protoBytes) // If the client fails to retrieve a response perform an exponential backoff. // Note: it is up to the caller to ensure that [ctx] is eventually cancelled if err != nil { @@ -104,11 +86,12 @@ func (s *NetworkSignatureGetter) GetSignature(ctx context.Context, nodeID ids.No } continue } - var response message.SignatureResponse - if _, err := s.networkCodec.Unmarshal(signatureRes, &response); err != nil { + var response sdk.SignatureResponse + if err := proto.Unmarshal(signatureRes, &response); err != nil { return nil, fmt.Errorf("failed to unmarshal signature res: %w", err) } - if response.Signature == [bls.SignatureLen]byte{} { + + if len(response.Signature) == 0 { return nil, fmt.Errorf("received empty signature response") } blsSignature, err := bls.SignatureFromBytes(response.Signature[:]) diff --git a/warp/fetcher.go b/tests/warp/fetcher.go similarity index 87% rename from warp/fetcher.go rename to tests/warp/fetcher.go index 18149549ab..467677a238 100644 --- a/warp/fetcher.go +++ b/tests/warp/fetcher.go @@ -11,16 +11,14 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/bls" avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" - "github.com/ava-labs/coreth/warp/aggregator" + warpBackend "github.com/ava-labs/coreth/warp" ) -var _ aggregator.SignatureGetter = (*apiFetcher)(nil) - type apiFetcher struct { - clients map[ids.NodeID]Client + clients map[ids.NodeID]warpBackend.Client } -func NewAPIFetcher(clients map[ids.NodeID]Client) *apiFetcher { +func NewAPIFetcher(clients map[ids.NodeID]warpBackend.Client) *apiFetcher { return &apiFetcher{ clients: clients, } diff --git a/tests/warp/warp_test.go b/tests/warp/warp_test.go index 3c5c19e251..252840263f 100644 --- a/tests/warp/warp_test.go +++ b/tests/warp/warp_test.go @@ -17,8 +17,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/ava-labs/coreth/accounts/abi/bind" - "github.com/ava-labs/coreth/warp/aggregator" "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/crypto" @@ -33,6 +31,7 @@ import ( avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" + "github.com/ava-labs/coreth/accounts/abi/bind" "github.com/ava-labs/coreth/cmd/simulator/key" "github.com/ava-labs/coreth/cmd/simulator/load" "github.com/ava-labs/coreth/cmd/simulator/metrics" @@ -42,6 +41,7 @@ import ( "github.com/ava-labs/coreth/precompile/contracts/warp" "github.com/ava-labs/coreth/predicate" "github.com/ava-labs/coreth/tests/utils" + "github.com/ava-labs/coreth/tests/warp/aggregator" warpBackend "github.com/ava-labs/coreth/warp" ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/core/types" @@ -370,7 +370,7 @@ func (w *warpTest) aggregateSignaturesViaAPI() { } ginkgo.GinkgoLogr.Info("Aggregating signatures from validator set", "numValidators", len(warpValidators), "totalWeight", totalWeight) - apiSignatureGetter := warpBackend.NewAPIFetcher(warpAPIs) + apiSignatureGetter := NewAPIFetcher(warpAPIs) signatureResult, err := aggregator.New(apiSignatureGetter, warpValidators, totalWeight).AggregateSignatures(ctx, w.addressedCallUnsignedMessage, 100) require.NoError(err) require.Equal(signatureResult.SignatureWeight, signatureResult.TotalWeight) diff --git a/warp/backend.go b/warp/backend.go index 76ce1ef64e..55fa8828e7 100644 --- a/warp/backend.go +++ b/warp/backend.go @@ -43,8 +43,6 @@ type Backend interface { GetBlockSignature(ctx context.Context, blockID ids.ID) ([]byte, error) // GetMessage retrieves the [unsignedMessage] from the warp backend database if available - // TODO: After Etna, the backend no longer needs to store the mapping from messageHash - // to unsignedMessage (and this method can be removed). GetMessage(messageHash ids.ID) (*avalancheWarp.UnsignedMessage, error) acp118.Verifier diff --git a/warp/handlers/signature_request.go b/warp/handlers/signature_request.go deleted file mode 100644 index 3655960634..0000000000 --- a/warp/handlers/signature_request.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package handlers - -import ( - "context" - "time" - - "github.com/ava-labs/avalanchego/codec" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/crypto/bls" - "github.com/ava-labs/coreth/plugin/evm/message" - "github.com/ava-labs/coreth/warp" - "github.com/ava-labs/libevm/log" -) - -// SignatureRequestHandler serves warp signature requests. It is a peer.RequestHandler for message.MessageSignatureRequest. -// TODO: After Etna, this handler can be removed and SignatureRequestHandlerP2P is sufficient. -type SignatureRequestHandler struct { - backend warp.Backend - codec codec.Manager - stats *handlerStats -} - -func NewSignatureRequestHandler(backend warp.Backend, codec codec.Manager) *SignatureRequestHandler { - return &SignatureRequestHandler{ - backend: backend, - codec: codec, - stats: newStats(), - } -} - -// OnMessageSignatureRequest handles message.MessageSignatureRequest, and retrieves a warp signature for the requested message ID. -// Never returns an error -// Expects returned errors to be treated as FATAL -// Returns empty response if signature is not found -// Assumes ctx is active -func (s *SignatureRequestHandler) OnMessageSignatureRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, signatureRequest message.MessageSignatureRequest) ([]byte, error) { - startTime := time.Now() - s.stats.IncMessageSignatureRequest() - - // Always report signature request time - defer func() { - s.stats.UpdateMessageSignatureRequestTime(time.Since(startTime)) - }() - - var signature [bls.SignatureLen]byte - unsignedMessage, err := s.backend.GetMessage(signatureRequest.MessageID) - if err != nil { - log.Debug("Unknown warp message requested", "messageID", signatureRequest.MessageID) - s.stats.IncMessageSignatureMiss() - } else { - sig, err := s.backend.GetMessageSignature(ctx, unsignedMessage) - if err != nil { - log.Debug("Unknown warp signature requested", "messageID", signatureRequest.MessageID) - s.stats.IncMessageSignatureMiss() - } else { - s.stats.IncMessageSignatureHit() - copy(signature[:], sig) - } - } - - response := message.SignatureResponse{Signature: signature} - responseBytes, err := s.codec.Marshal(message.Version, &response) - if err != nil { - log.Error("could not marshal SignatureResponse, dropping request", "nodeID", nodeID, "requestID", requestID, "err", err) - return nil, nil - } - - return responseBytes, nil -} - -func (s *SignatureRequestHandler) OnBlockSignatureRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, request message.BlockSignatureRequest) ([]byte, error) { - startTime := time.Now() - s.stats.IncBlockSignatureRequest() - - // Always report signature request time - defer func() { - s.stats.UpdateBlockSignatureRequestTime(time.Since(startTime)) - }() - - var signature [bls.SignatureLen]byte - sig, err := s.backend.GetBlockSignature(ctx, request.BlockID) - if err != nil { - log.Debug("Unknown warp signature requested", "blockID", request.BlockID) - s.stats.IncBlockSignatureMiss() - } else { - s.stats.IncBlockSignatureHit() - copy(signature[:], sig) - } - - response := message.SignatureResponse{Signature: signature} - responseBytes, err := s.codec.Marshal(message.Version, &response) - if err != nil { - log.Error("could not marshal SignatureResponse, dropping request", "nodeID", nodeID, "requestID", requestID, "err", err) - return nil, nil - } - - return responseBytes, nil -} - -type NoopSignatureRequestHandler struct{} - -func (s *NoopSignatureRequestHandler) OnMessageSignatureRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, signatureRequest message.MessageSignatureRequest) ([]byte, error) { - return nil, nil -} - -func (s *NoopSignatureRequestHandler) OnBlockSignatureRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, signatureRequest message.BlockSignatureRequest) ([]byte, error) { - return nil, nil -} diff --git a/warp/handlers/signature_request_test.go b/warp/handlers/signature_request_test.go deleted file mode 100644 index afae530f9d..0000000000 --- a/warp/handlers/signature_request_test.go +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package handlers - -import ( - "context" - "testing" - - "github.com/ava-labs/avalanchego/cache/lru" - "github.com/ava-labs/avalanchego/database/memdb" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow/snowtest" - "github.com/ava-labs/avalanchego/utils/crypto/bls" - avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" - "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" - "github.com/ava-labs/coreth/metrics/metricstest" - "github.com/ava-labs/coreth/plugin/evm/message" - "github.com/ava-labs/coreth/warp" - "github.com/ava-labs/coreth/warp/warptest" - - "github.com/stretchr/testify/require" -) - -func TestMessageSignatureHandler(t *testing.T) { - metricstest.WithMetrics(t) - - database := memdb.New() - snowCtx := snowtest.Context(t, snowtest.CChainID) - - addressedPayload, err := payload.NewAddressedCall([]byte{1, 2, 3}, []byte{1, 2, 3}) - require.NoError(t, err) - offchainMessage, err := avalancheWarp.NewUnsignedMessage(snowCtx.NetworkID, snowCtx.ChainID, addressedPayload.Bytes()) - require.NoError(t, err) - - messageSignatureCache := lru.NewCache[ids.ID, []byte](100) - backend, err := warp.NewBackend(snowCtx.NetworkID, snowCtx.ChainID, snowCtx.WarpSigner, warptest.EmptyBlockClient, database, messageSignatureCache, [][]byte{offchainMessage.Bytes()}) - require.NoError(t, err) - - msg, err := avalancheWarp.NewUnsignedMessage(snowCtx.NetworkID, snowCtx.ChainID, []byte("test")) - require.NoError(t, err) - messageID := msg.ID() - require.NoError(t, backend.AddMessage(msg)) - signature, err := backend.GetMessageSignature(context.TODO(), msg) - require.NoError(t, err) - offchainSignature, err := backend.GetMessageSignature(context.TODO(), offchainMessage) - require.NoError(t, err) - - unknownMessageID := ids.GenerateTestID() - - emptySignature := [bls.SignatureLen]byte{} - - tests := map[string]struct { - setup func() (request message.MessageSignatureRequest, expectedResponse []byte) - verifyStats func(t *testing.T, stats *handlerStats) - }{ - "known message": { - setup: func() (request message.MessageSignatureRequest, expectedResponse []byte) { - return message.MessageSignatureRequest{ - MessageID: messageID, - }, signature[:] - }, - verifyStats: func(t *testing.T, stats *handlerStats) { - require.EqualValues(t, 1, stats.messageSignatureRequest.Snapshot().Count()) - require.EqualValues(t, 1, stats.messageSignatureHit.Snapshot().Count()) - require.EqualValues(t, 0, stats.messageSignatureMiss.Snapshot().Count()) - require.EqualValues(t, 0, stats.blockSignatureRequest.Snapshot().Count()) - require.EqualValues(t, 0, stats.blockSignatureHit.Snapshot().Count()) - require.EqualValues(t, 0, stats.blockSignatureMiss.Snapshot().Count()) - }, - }, - "offchain message": { - setup: func() (request message.MessageSignatureRequest, expectedResponse []byte) { - return message.MessageSignatureRequest{ - MessageID: offchainMessage.ID(), - }, offchainSignature[:] - }, - verifyStats: func(t *testing.T, stats *handlerStats) { - require.EqualValues(t, 1, stats.messageSignatureRequest.Snapshot().Count()) - require.EqualValues(t, 1, stats.messageSignatureHit.Snapshot().Count()) - require.EqualValues(t, 0, stats.messageSignatureMiss.Snapshot().Count()) - require.EqualValues(t, 0, stats.blockSignatureRequest.Snapshot().Count()) - require.EqualValues(t, 0, stats.blockSignatureHit.Snapshot().Count()) - require.EqualValues(t, 0, stats.blockSignatureMiss.Snapshot().Count()) - }, - }, - "unknown message": { - setup: func() (request message.MessageSignatureRequest, expectedResponse []byte) { - return message.MessageSignatureRequest{ - MessageID: unknownMessageID, - }, emptySignature[:] - }, - verifyStats: func(t *testing.T, stats *handlerStats) { - require.EqualValues(t, 1, stats.messageSignatureRequest.Snapshot().Count()) - require.EqualValues(t, 0, stats.messageSignatureHit.Snapshot().Count()) - require.EqualValues(t, 1, stats.messageSignatureMiss.Snapshot().Count()) - require.EqualValues(t, 0, stats.blockSignatureRequest.Snapshot().Count()) - require.EqualValues(t, 0, stats.blockSignatureHit.Snapshot().Count()) - require.EqualValues(t, 0, stats.blockSignatureMiss.Snapshot().Count()) - }, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - handler := NewSignatureRequestHandler(backend, message.Codec) - - request, expectedResponse := test.setup() - responseBytes, err := handler.OnMessageSignatureRequest(context.Background(), ids.GenerateTestNodeID(), 1, request) - require.NoError(t, err) - - test.verifyStats(t, handler.stats) - - // If the expected response is empty, assert that the handler returns an empty response and return early. - if len(expectedResponse) == 0 { - require.Len(t, responseBytes, 0, "expected response to be empty") - return - } - var response message.SignatureResponse - _, err = message.Codec.Unmarshal(responseBytes, &response) - require.NoError(t, err, "error unmarshalling SignatureResponse") - - require.Equal(t, expectedResponse, response.Signature[:]) - }) - } -} - -func TestBlockSignatureHandler(t *testing.T) { - metricstest.WithMetrics(t) - - database := memdb.New() - snowCtx := snowtest.Context(t, snowtest.CChainID) - - blkID := ids.GenerateTestID() - blockClient := warptest.MakeBlockClient(blkID) - messageSignatureCache := lru.NewCache[ids.ID, []byte](100) - backend, err := warp.NewBackend( - snowCtx.NetworkID, - snowCtx.ChainID, - snowCtx.WarpSigner, - blockClient, - database, - messageSignatureCache, - nil, - ) - require.NoError(t, err) - - signature, err := backend.GetBlockSignature(context.TODO(), blkID) - require.NoError(t, err) - unknownMessageID := ids.GenerateTestID() - - emptySignature := [bls.SignatureLen]byte{} - - tests := map[string]struct { - setup func() (request message.BlockSignatureRequest, expectedResponse []byte) - verifyStats func(t *testing.T, stats *handlerStats) - }{ - "known block": { - setup: func() (request message.BlockSignatureRequest, expectedResponse []byte) { - return message.BlockSignatureRequest{ - BlockID: blkID, - }, signature[:] - }, - verifyStats: func(t *testing.T, stats *handlerStats) { - require.EqualValues(t, 0, stats.messageSignatureRequest.Snapshot().Count()) - require.EqualValues(t, 0, stats.messageSignatureHit.Snapshot().Count()) - require.EqualValues(t, 0, stats.messageSignatureMiss.Snapshot().Count()) - require.EqualValues(t, 1, stats.blockSignatureRequest.Snapshot().Count()) - require.EqualValues(t, 1, stats.blockSignatureHit.Snapshot().Count()) - require.EqualValues(t, 0, stats.blockSignatureMiss.Snapshot().Count()) - }, - }, - "unknown block": { - setup: func() (request message.BlockSignatureRequest, expectedResponse []byte) { - return message.BlockSignatureRequest{ - BlockID: unknownMessageID, - }, emptySignature[:] - }, - verifyStats: func(t *testing.T, stats *handlerStats) { - require.EqualValues(t, 0, stats.messageSignatureRequest.Snapshot().Count()) - require.EqualValues(t, 0, stats.messageSignatureHit.Snapshot().Count()) - require.EqualValues(t, 0, stats.messageSignatureMiss.Snapshot().Count()) - require.EqualValues(t, 1, stats.blockSignatureRequest.Snapshot().Count()) - require.EqualValues(t, 0, stats.blockSignatureHit.Snapshot().Count()) - require.EqualValues(t, 1, stats.blockSignatureMiss.Snapshot().Count()) - }, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - handler := NewSignatureRequestHandler(backend, message.Codec) - - request, expectedResponse := test.setup() - responseBytes, err := handler.OnBlockSignatureRequest(context.Background(), ids.GenerateTestNodeID(), 1, request) - require.NoError(t, err) - - test.verifyStats(t, handler.stats) - - // If the expected response is empty, assert that the handler returns an empty response and return early. - if len(expectedResponse) == 0 { - require.Len(t, responseBytes, 0, "expected response to be empty") - return - } - var response message.SignatureResponse - _, err = message.Codec.Unmarshal(responseBytes, &response) - require.NoError(t, err, "error unmarshalling SignatureResponse") - - require.Equal(t, expectedResponse, response.Signature[:]) - }) - } -} diff --git a/warp/handlers/stats.go b/warp/handlers/stats.go deleted file mode 100644 index f5b9a0e0d5..0000000000 --- a/warp/handlers/stats.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package handlers - -import ( - "time" - - "github.com/ava-labs/libevm/metrics" -) - -type handlerStats struct { - // MessageSignatureRequestHandler metrics - messageSignatureRequest metrics.Counter - messageSignatureHit metrics.Counter - messageSignatureMiss metrics.Counter - messageSignatureRequestDuration metrics.Gauge - // BlockSignatureRequestHandler metrics - blockSignatureRequest metrics.Counter - blockSignatureHit metrics.Counter - blockSignatureMiss metrics.Counter - blockSignatureRequestDuration metrics.Gauge -} - -func newStats() *handlerStats { - return &handlerStats{ - messageSignatureRequest: metrics.NewRegisteredCounter("message_signature_request_count", nil), - messageSignatureHit: metrics.NewRegisteredCounter("message_signature_request_hit", nil), - messageSignatureMiss: metrics.NewRegisteredCounter("message_signature_request_miss", nil), - messageSignatureRequestDuration: metrics.NewRegisteredGauge("message_signature_request_duration", nil), - blockSignatureRequest: metrics.NewRegisteredCounter("block_signature_request_count", nil), - blockSignatureHit: metrics.NewRegisteredCounter("block_signature_request_hit", nil), - blockSignatureMiss: metrics.NewRegisteredCounter("block_signature_request_miss", nil), - blockSignatureRequestDuration: metrics.NewRegisteredGauge("block_signature_request_duration", nil), - } -} - -func (h *handlerStats) IncMessageSignatureRequest() { h.messageSignatureRequest.Inc(1) } -func (h *handlerStats) IncMessageSignatureHit() { h.messageSignatureHit.Inc(1) } -func (h *handlerStats) IncMessageSignatureMiss() { h.messageSignatureMiss.Inc(1) } -func (h *handlerStats) UpdateMessageSignatureRequestTime(duration time.Duration) { - h.messageSignatureRequestDuration.Inc(int64(duration)) -} -func (h *handlerStats) IncBlockSignatureRequest() { h.blockSignatureRequest.Inc(1) } -func (h *handlerStats) IncBlockSignatureHit() { h.blockSignatureHit.Inc(1) } -func (h *handlerStats) IncBlockSignatureMiss() { h.blockSignatureMiss.Inc(1) } -func (h *handlerStats) UpdateBlockSignatureRequestTime(duration time.Duration) { - h.blockSignatureRequestDuration.Inc(int64(duration)) -} diff --git a/warp/service.go b/warp/service.go index da13e40876..d477b61d70 100644 --- a/warp/service.go +++ b/warp/service.go @@ -8,13 +8,12 @@ import ( "errors" "fmt" - "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/network/p2p/acp118" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" - "github.com/ava-labs/coreth/network" - "github.com/ava-labs/coreth/warp/aggregator" + warpprecompile "github.com/ava-labs/coreth/precompile/contracts/warp" warpValidators "github.com/ava-labs/coreth/warp/validators" "github.com/ava-labs/libevm/common/hexutil" "github.com/ava-labs/libevm/log" @@ -26,16 +25,15 @@ var errNoValidators = errors.New("cannot aggregate signatures from subnet with n type API struct { chainContext *snow.Context backend Backend - signatureGetter aggregator.SignatureGetter + signatureAggregator *acp118.SignatureAggregator requirePrimaryNetworkSigners func() bool } -func NewAPI(chainCtx *snow.Context, networkCodec codec.Manager, backend Backend, client network.SyncedNetworkClient, requirePrimaryNetworkSigners func() bool) *API { - signatureGetter := aggregator.NewSignatureGetter(client, networkCodec) +func NewAPI(chainCtx *snow.Context, backend Backend, signatureAggregator *acp118.SignatureAggregator, requirePrimaryNetworkSigners func() bool) *API { return &API{ backend: backend, chainContext: chainCtx, - signatureGetter: signatureGetter, + signatureAggregator: signatureAggregator, requirePrimaryNetworkSigners: requirePrimaryNetworkSigners, } } @@ -124,14 +122,23 @@ func (a *API) aggregateSignatures(ctx context.Context, unsignedMessage *warp.Uns "numValidators", len(validatorSet.Validators), "totalWeight", validatorSet.TotalWeight, ) - - agg := aggregator.New(a.signatureGetter, validatorSet.Validators, validatorSet.TotalWeight) - signatureResult, err := agg.AggregateSignatures(ctx, unsignedMessage, quorumNum) + warpMessage := &warp.Message{ + UnsignedMessage: *unsignedMessage, + Signature: &warp.BitSetSignature{}, + } + signedMessage, _, _, err := a.signatureAggregator.AggregateSignatures( + ctx, + warpMessage, + nil, + validatorSet.Validators, + quorumNum, + warpprecompile.WarpQuorumDenominator, + ) if err != nil { return nil, err } // TODO: return the signature and total weight as well to the caller for more complete details // Need to decide on the best UI for this and write up documentation with the potential // gotchas that could impact signed messages becoming invalid. - return hexutil.Bytes(signatureResult.Message.Bytes()), nil + return hexutil.Bytes(signedMessage.Bytes()), nil }