From 23a4a41e5d3f971eca30f6c6ed5c1ced78a4fc79 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Fri, 30 Aug 2024 00:18:16 +0000 Subject: [PATCH 1/9] happy path test addresses review comment https://github.com/ava-labs/awm-relayer/pull/457#discussion_r1736383025 --- peers/app_request_network.go | 6 +- signature-aggregator/aggregator/aggregator.go | 2 + .../aggregator/aggregator_test.go | 327 +++++++++++++++++- .../aggregator/cache/cache.go | 12 +- 4 files changed, 336 insertions(+), 11 deletions(-) diff --git a/peers/app_request_network.go b/peers/app_request_network.go index f25a8518..df4e20e0 100644 --- a/peers/app_request_network.go +++ b/peers/app_request_network.go @@ -212,12 +212,12 @@ type ConnectedCanonicalValidators struct { ConnectedWeight uint64 TotalValidatorWeight uint64 ValidatorSet []*warp.Validator - nodeValidatorIndexMap map[ids.NodeID]int + NodeValidatorIndexMap map[ids.NodeID]int } // Returns the Warp Validator and its index in the canonical Validator ordering for a given nodeID func (c *ConnectedCanonicalValidators) GetValidator(nodeID ids.NodeID) (*warp.Validator, int) { - return c.ValidatorSet[c.nodeValidatorIndexMap[nodeID]], c.nodeValidatorIndexMap[nodeID] + return c.ValidatorSet[c.NodeValidatorIndexMap[nodeID]], c.NodeValidatorIndexMap[nodeID] } // ConnectToCanonicalValidators connects to the canonical validators of the given subnet and returns the connected @@ -258,7 +258,7 @@ func (n *appRequestNetwork) ConnectToCanonicalValidators(subnetID ids.ID) (*Conn ConnectedWeight: connectedWeight, TotalValidatorWeight: totalValidatorWeight, ValidatorSet: validatorSet, - nodeValidatorIndexMap: nodeValidatorIndexMap, + NodeValidatorIndexMap: nodeValidatorIndexMap, }, nil } diff --git a/signature-aggregator/aggregator/aggregator.go b/signature-aggregator/aggregator/aggregator.go index a48ac728..756630b1 100644 --- a/signature-aggregator/aggregator/aggregator.go +++ b/signature-aggregator/aggregator/aggregator.go @@ -5,6 +5,7 @@ package aggregator import ( "bytes" + "encoding/hex" "errors" "fmt" "math/big" @@ -554,6 +555,7 @@ func (s *SignatureAggregator) isValidSignatureResponse( if !bls.Verify(pubKey, sig, unsignedMessage.Bytes()) { s.logger.Debug( "Failed verification for signature", + zap.String("pubKey", hex.EncodeToString(bls.PublicKeyToUncompressedBytes(pubKey))), ) return blsSignatureBuf{}, false } diff --git a/signature-aggregator/aggregator/aggregator_test.go b/signature-aggregator/aggregator/aggregator_test.go index 13a6952c..ff03646f 100644 --- a/signature-aggregator/aggregator/aggregator_test.go +++ b/signature-aggregator/aggregator/aggregator_test.go @@ -1,23 +1,37 @@ package aggregator import ( + "context" + "encoding/hex" + "fmt" + "os" "testing" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/message" + "github.com/ava-labs/avalanchego/snow/validators" + "github.com/ava-labs/avalanchego/subnets" + "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/awm-relayer/peers" "github.com/ava-labs/awm-relayer/peers/mocks" "github.com/ava-labs/awm-relayer/signature-aggregator/metrics" + evmMsg "github.com/ava-labs/subnet-evm/plugin/evm/message" "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" ) -var sigAggMetrics *metrics.SignatureAggregatorMetrics -var messageCreator message.Creator +var ( + sigAggMetrics *metrics.SignatureAggregatorMetrics + messageCreator message.Creator +) func instantiateAggregator(t *testing.T) ( *SignatureAggregator, @@ -35,23 +49,77 @@ func instantiateAggregator(t *testing.T) ( constants.DefaultNetworkCompressionType, constants.DefaultNetworkMaximumInboundTimeout, ) - require.Equal(t, err, nil) + require.Equal(t, nil, err) } aggregator, err := NewSignatureAggregator( mockNetwork, - logging.NoLog{}, + logging.NewLogger( + "aggregator_test", + logging.NewWrappedCore( + logging.Debug, + os.Stdout, + zapcore.NewConsoleEncoder( + zap.NewProductionEncoderConfig(), + ), + ), + ), 1024, sigAggMetrics, messageCreator, ) - require.Equal(t, err, nil) + require.Equal(t, nil, err) return aggregator, mockNetwork } +func makeConnectedValidators(validatorCount int) (*peers.ConnectedCanonicalValidators, []*bls.SecretKey) { + var validatorSet []*warp.Validator + var validatorSecretKeys []*bls.SecretKey + + nodeValidatorIndexMap := make(map[ids.NodeID]int) + + for i := 0; i < validatorCount; i++ { + secretKey, err := bls.NewSecretKey() + if err != nil { + panic(err) + } + validatorSecretKeys = append(validatorSecretKeys, secretKey) + + pubKey := bls.PublicFromSecretKey(secretKey) + + nodeID, err := ids.ToNodeID(utils.RandomBytes(20)) + if err != nil { + panic(err) + } + nodeValidatorIndexMap[nodeID] = i + + fmt.Printf( + "validator with pubKey %s has nodeID %s\n", + hex.EncodeToString(bls.PublicKeyToUncompressedBytes(pubKey)), + nodeID.String(), + ) + + validatorSet = append(validatorSet, + &warp.Validator{ + PublicKey: pubKey, + PublicKeyBytes: bls.PublicKeyToUncompressedBytes(pubKey), + Weight: 1, + NodeIDs: []ids.NodeID{nodeID}, + }, + ) + } + + return &peers.ConnectedCanonicalValidators{ + ConnectedWeight: uint64(validatorCount), + TotalValidatorWeight: uint64(validatorCount), + ValidatorSet: validatorSet, + NodeValidatorIndexMap: nodeValidatorIndexMap, + }, validatorSecretKeys +} + func TestCreateSignedMessageFailsWithNoValidators(t *testing.T) { aggregator, mockNetwork := instantiateAggregator(t) msg, err := warp.NewUnsignedMessage(0, ids.Empty, []byte{}) - require.Equal(t, err, nil) + require.Equal(t, nil, err) mockNetwork.EXPECT().GetSubnetID(ids.Empty).Return(ids.Empty, nil) mockNetwork.EXPECT().ConnectToCanonicalValidators(ids.Empty).Return( &peers.ConnectedCanonicalValidators{ @@ -68,7 +136,7 @@ func TestCreateSignedMessageFailsWithNoValidators(t *testing.T) { func TestCreateSignedMessageFailsWithoutSufficientConnectedStake(t *testing.T) { aggregator, mockNetwork := instantiateAggregator(t) msg, err := warp.NewUnsignedMessage(0, ids.Empty, []byte{}) - require.Equal(t, err, nil) + require.Equal(t, nil, err) mockNetwork.EXPECT().GetSubnetID(ids.Empty).Return(ids.Empty, nil) mockNetwork.EXPECT().ConnectToCanonicalValidators(ids.Empty).Return( &peers.ConnectedCanonicalValidators{ @@ -85,3 +153,248 @@ func TestCreateSignedMessageFailsWithoutSufficientConnectedStake(t *testing.T) { "failed to connect to a threshold of stake", ) } + +func makeAppRequests( + chainID ids.ID, + requestID uint32, + connectedValidators *peers.ConnectedCanonicalValidators, +) []ids.RequestID { + var appRequests []ids.RequestID + for _, validator := range connectedValidators.ValidatorSet { + for _, nodeID := range validator.NodeIDs { + appRequests = append( + appRequests, + ids.RequestID{ + NodeID: nodeID, + SourceChainID: chainID, + DestinationChainID: chainID, + RequestID: requestID, + Op: byte( + message.AppResponseOp, + ), + }, + ) + } + } + return appRequests +} + +func TestCreateSignedMessageRetriesAndFailsWithoutP2PResponses(t *testing.T) { + aggregator, mockNetwork := instantiateAggregator(t) + + var ( + connectedValidators, _ = makeConnectedValidators(2) + requestID = aggregator.currentRequestID.Load() + 1 + ) + + chainID, err := ids.ToID(utils.RandomBytes(32)) + if err != nil { + panic(err) + } + + msg, err := warp.NewUnsignedMessage(0, chainID, []byte{}) + require.Equal(t, nil, err) + + subnetID, err := ids.ToID(utils.RandomBytes(32)) + require.Equal(t, nil, err) + mockNetwork.EXPECT().GetSubnetID(chainID).Return( + subnetID, + nil, + ) + + mockNetwork.EXPECT().ConnectToCanonicalValidators(subnetID).Return( + connectedValidators, + nil, + ) + + appRequests := makeAppRequests(chainID, requestID, connectedValidators) + for _, appRequest := range appRequests { + mockNetwork.EXPECT().RegisterAppRequest(appRequest).Times( + maxRelayerQueryAttempts, + ) + } + + mockNetwork.EXPECT().RegisterRequestID( + requestID, + len(appRequests), + ).Return( + make(chan message.InboundMessage, len(appRequests)), + ).Times(maxRelayerQueryAttempts) + + var nodeIDs set.Set[ids.NodeID] + for _, appRequest := range appRequests { + nodeIDs.Add(appRequest.NodeID) + } + mockNetwork.EXPECT().Send( + gomock.Any(), + nodeIDs, + subnetID, + subnets.NoOpAllower, + ).Times(maxRelayerQueryAttempts) + + _, err = aggregator.CreateSignedMessage(msg, subnetID, 80) + require.ErrorContains( + t, + err, + "failed to collect a threshold of signatures", + ) +} + +func TestCreateSignedMessageSucceeds(t *testing.T) { + var msg *warp.UnsignedMessage // to be signed + chainID, err := ids.ToID(utils.RandomBytes(32)) + if err != nil { + panic(err) + } + networkID := uint32(0) + msg, err = warp.NewUnsignedMessage( + networkID, + chainID, + utils.RandomBytes(1234), + ) + require.Equal(t, nil, err) + + // the signers: + var connectedValidators, validatorSecretKeys = makeConnectedValidators(5) + + // prime the aggregator: + + aggregator, mockNetwork := instantiateAggregator(t) + + subnetID, err := ids.ToID(utils.RandomBytes(32)) + require.Equal(t, nil, err) + mockNetwork.EXPECT().GetSubnetID(chainID).Return( + subnetID, + nil, + ) + + mockNetwork.EXPECT().ConnectToCanonicalValidators(subnetID).Return( + connectedValidators, + nil, + ) + + // prime the signers' responses: + + var requestID = aggregator.currentRequestID.Load() + 1 + + appRequests := makeAppRequests(chainID, requestID, connectedValidators) + for _, appRequest := range appRequests { + mockNetwork.EXPECT().RegisterAppRequest(appRequest).Times(1) + } + + var nodeIDs set.Set[ids.NodeID] + responseChan := make(chan message.InboundMessage, len(appRequests)) + for _, appRequest := range appRequests { + nodeIDs.Add(appRequest.NodeID) + validatorSecretKey := validatorSecretKeys[connectedValidators.NodeValidatorIndexMap[appRequest.NodeID]] + responseBytes, err := evmMsg.Codec.Marshal( + 0, + &evmMsg.SignatureResponse{ + Signature: [bls.SignatureLen]byte( + bls.SignatureToBytes( + bls.Sign( + validatorSecretKey, + msg.Bytes(), + ), + ), + ), + }, + ) + require.Equal(t, nil, err) + responseChan <- message.InboundAppResponse( + chainID, + requestID, + responseBytes, + appRequest.NodeID, + ) + } + mockNetwork.EXPECT().RegisterRequestID( + requestID, + len(appRequests), + ).Return(responseChan).Times(1) + + mockNetwork.EXPECT().Send( + gomock.Any(), + nodeIDs, + subnetID, + subnets.NoOpAllower, + ).Times(1).Return(nodeIDs) + + // aggregate the signatures: + var quorumPercentage uint64 = 80 + signedMessage, err := aggregator.CreateSignedMessage( + msg, + subnetID, + quorumPercentage, + ) + require.Equal(t, nil, err) + + // verify the aggregated signature: + pChainState := newPChainStateStub( + chainID, + subnetID, + 1, + connectedValidators, + ) + require.Equal( + t, + nil, + signedMessage.Signature.Verify( + context.Background(), + msg, + networkID, + pChainState, + pChainState.currentHeight, + quorumPercentage, + 100, + ), + ) +} + +type pChainStateStub struct { + subnetIDByChainID map[ids.ID]ids.ID + connectedCanonicalValidators *peers.ConnectedCanonicalValidators + currentHeight uint64 +} + +func newPChainStateStub( + chainID, subnetID ids.ID, + currentHeight uint64, + connectedValidators *peers.ConnectedCanonicalValidators, +) *pChainStateStub { + subnetIDByChainID := make(map[ids.ID]ids.ID) + subnetIDByChainID[chainID] = subnetID + return &pChainStateStub{ + subnetIDByChainID: subnetIDByChainID, + connectedCanonicalValidators: connectedValidators, + currentHeight: currentHeight, + } +} + +func (p pChainStateStub) GetSubnetID(ctx context.Context, chainID ids.ID) (ids.ID, error) { + return p.subnetIDByChainID[chainID], nil +} + +func (p pChainStateStub) GetMinimumHeight(context.Context) (uint64, error) { return 0, nil } + +func (p pChainStateStub) GetCurrentHeight(context.Context) (uint64, error) { + return p.currentHeight, nil +} + +func (p pChainStateStub) GetValidatorSet( + ctx context.Context, + height uint64, + subnetID ids.ID, +) (map[ids.NodeID]*validators.GetValidatorOutput, error) { + output := make(map[ids.NodeID]*validators.GetValidatorOutput) + for _, validator := range p.connectedCanonicalValidators.ValidatorSet { + for _, nodeID := range validator.NodeIDs { + output[nodeID] = &validators.GetValidatorOutput{ + NodeID: nodeID, + PublicKey: validator.PublicKey, + Weight: validator.Weight, + } + } + } + return output, nil +} diff --git a/signature-aggregator/aggregator/cache/cache.go b/signature-aggregator/aggregator/cache/cache.go index 475a6fdc..89d30941 100644 --- a/signature-aggregator/aggregator/cache/cache.go +++ b/signature-aggregator/aggregator/cache/cache.go @@ -1,6 +1,7 @@ package cache import ( + "encoding/hex" "math" "github.com/ava-labs/avalanchego/ids" @@ -41,7 +42,16 @@ func (c *Cache) Get(msgID ids.ID) (map[PublicKeyBytes]SignatureBytes, bool) { cachedValue, isCached := c.signatures.Get(msgID) if isCached { - c.logger.Debug("cache hit", zap.Stringer("msgID", msgID)) + var encodedKeys []string + for key := range cachedValue { + encodedKeys = append(encodedKeys, hex.EncodeToString(key[:])) + } + c.logger.Debug( + "cache hit", + zap.Stringer("msgID", msgID), + zap.Int("signatureCount", len(cachedValue)), + zap.Strings("public keys", encodedKeys), + ) return cachedValue, true } else { c.logger.Debug("cache miss", zap.Stringer("msgID", msgID)) From 0c630f0c4fe97af16d2220efab508982ed4e0dfe Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 5 Sep 2024 18:15:47 +0000 Subject: [PATCH 2/9] use `require.NoError` addresses review comment https://github.com/ava-labs/awm-relayer/pull/467#discussion_r1745582028 --- .../aggregator/aggregator_test.go | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/signature-aggregator/aggregator/aggregator_test.go b/signature-aggregator/aggregator/aggregator_test.go index ff03646f..226c0f0f 100644 --- a/signature-aggregator/aggregator/aggregator_test.go +++ b/signature-aggregator/aggregator/aggregator_test.go @@ -49,7 +49,7 @@ func instantiateAggregator(t *testing.T) ( constants.DefaultNetworkCompressionType, constants.DefaultNetworkMaximumInboundTimeout, ) - require.Equal(t, nil, err) + require.NoError(t, err) } aggregator, err := NewSignatureAggregator( mockNetwork, @@ -67,7 +67,7 @@ func instantiateAggregator(t *testing.T) ( sigAggMetrics, messageCreator, ) - require.Equal(t, nil, err) + require.NoError(t, err) return aggregator, mockNetwork } @@ -119,7 +119,7 @@ func makeConnectedValidators(validatorCount int) (*peers.ConnectedCanonicalValid func TestCreateSignedMessageFailsWithNoValidators(t *testing.T) { aggregator, mockNetwork := instantiateAggregator(t) msg, err := warp.NewUnsignedMessage(0, ids.Empty, []byte{}) - require.Equal(t, nil, err) + require.NoError(t, err) mockNetwork.EXPECT().GetSubnetID(ids.Empty).Return(ids.Empty, nil) mockNetwork.EXPECT().ConnectToCanonicalValidators(ids.Empty).Return( &peers.ConnectedCanonicalValidators{ @@ -136,7 +136,7 @@ func TestCreateSignedMessageFailsWithNoValidators(t *testing.T) { func TestCreateSignedMessageFailsWithoutSufficientConnectedStake(t *testing.T) { aggregator, mockNetwork := instantiateAggregator(t) msg, err := warp.NewUnsignedMessage(0, ids.Empty, []byte{}) - require.Equal(t, nil, err) + require.NoError(t, err) mockNetwork.EXPECT().GetSubnetID(ids.Empty).Return(ids.Empty, nil) mockNetwork.EXPECT().ConnectToCanonicalValidators(ids.Empty).Return( &peers.ConnectedCanonicalValidators{ @@ -193,10 +193,10 @@ func TestCreateSignedMessageRetriesAndFailsWithoutP2PResponses(t *testing.T) { } msg, err := warp.NewUnsignedMessage(0, chainID, []byte{}) - require.Equal(t, nil, err) + require.NoError(t, err) subnetID, err := ids.ToID(utils.RandomBytes(32)) - require.Equal(t, nil, err) + require.NoError(t, err) mockNetwork.EXPECT().GetSubnetID(chainID).Return( subnetID, nil, @@ -252,7 +252,7 @@ func TestCreateSignedMessageSucceeds(t *testing.T) { chainID, utils.RandomBytes(1234), ) - require.Equal(t, nil, err) + require.NoError(t, err) // the signers: var connectedValidators, validatorSecretKeys = makeConnectedValidators(5) @@ -262,7 +262,7 @@ func TestCreateSignedMessageSucceeds(t *testing.T) { aggregator, mockNetwork := instantiateAggregator(t) subnetID, err := ids.ToID(utils.RandomBytes(32)) - require.Equal(t, nil, err) + require.NoError(t, err) mockNetwork.EXPECT().GetSubnetID(chainID).Return( subnetID, nil, @@ -300,7 +300,7 @@ func TestCreateSignedMessageSucceeds(t *testing.T) { ), }, ) - require.Equal(t, nil, err) + require.NoError(t, err) responseChan <- message.InboundAppResponse( chainID, requestID, @@ -327,7 +327,7 @@ func TestCreateSignedMessageSucceeds(t *testing.T) { subnetID, quorumPercentage, ) - require.Equal(t, nil, err) + require.NoError(t, err) // verify the aggregated signature: pChainState := newPChainStateStub( From 408b68f79c2978058ba31e94b589de3b8e513c0c Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 5 Sep 2024 18:18:21 +0000 Subject: [PATCH 3/9] use `GenerateTestID` and (`GenerateTestNodeID`) addresses review comment https://github.com/ava-labs/awm-relayer/pull/467#discussion_r1745665181 --- .../aggregator/aggregator_test.go | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/signature-aggregator/aggregator/aggregator_test.go b/signature-aggregator/aggregator/aggregator_test.go index 226c0f0f..cfc9e113 100644 --- a/signature-aggregator/aggregator/aggregator_test.go +++ b/signature-aggregator/aggregator/aggregator_test.go @@ -86,10 +86,7 @@ func makeConnectedValidators(validatorCount int) (*peers.ConnectedCanonicalValid pubKey := bls.PublicFromSecretKey(secretKey) - nodeID, err := ids.ToNodeID(utils.RandomBytes(20)) - if err != nil { - panic(err) - } + nodeID := ids.GenerateTestNodeID() nodeValidatorIndexMap[nodeID] = i fmt.Printf( @@ -187,16 +184,12 @@ func TestCreateSignedMessageRetriesAndFailsWithoutP2PResponses(t *testing.T) { requestID = aggregator.currentRequestID.Load() + 1 ) - chainID, err := ids.ToID(utils.RandomBytes(32)) - if err != nil { - panic(err) - } + chainID := ids.GenerateTestID() msg, err := warp.NewUnsignedMessage(0, chainID, []byte{}) require.NoError(t, err) - subnetID, err := ids.ToID(utils.RandomBytes(32)) - require.NoError(t, err) + subnetID := ids.GenerateTestID() mockNetwork.EXPECT().GetSubnetID(chainID).Return( subnetID, nil, @@ -242,12 +235,9 @@ func TestCreateSignedMessageRetriesAndFailsWithoutP2PResponses(t *testing.T) { func TestCreateSignedMessageSucceeds(t *testing.T) { var msg *warp.UnsignedMessage // to be signed - chainID, err := ids.ToID(utils.RandomBytes(32)) - if err != nil { - panic(err) - } + chainID := ids.GenerateTestID() networkID := uint32(0) - msg, err = warp.NewUnsignedMessage( + msg, err := warp.NewUnsignedMessage( networkID, chainID, utils.RandomBytes(1234), @@ -261,8 +251,7 @@ func TestCreateSignedMessageSucceeds(t *testing.T) { aggregator, mockNetwork := instantiateAggregator(t) - subnetID, err := ids.ToID(utils.RandomBytes(32)) - require.NoError(t, err) + subnetID := ids.GenerateTestID() mockNetwork.EXPECT().GetSubnetID(chainID).Return( subnetID, nil, From fc24e7ac55353c8194a69cb4953106d1ad040d15 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 5 Sep 2024 19:33:19 +0000 Subject: [PATCH 4/9] use `constants.UnitTestID` --- signature-aggregator/aggregator/aggregator_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/signature-aggregator/aggregator/aggregator_test.go b/signature-aggregator/aggregator/aggregator_test.go index cfc9e113..f0091c34 100644 --- a/signature-aggregator/aggregator/aggregator_test.go +++ b/signature-aggregator/aggregator/aggregator_test.go @@ -236,7 +236,7 @@ func TestCreateSignedMessageRetriesAndFailsWithoutP2PResponses(t *testing.T) { func TestCreateSignedMessageSucceeds(t *testing.T) { var msg *warp.UnsignedMessage // to be signed chainID := ids.GenerateTestID() - networkID := uint32(0) + networkID := constants.UnitTestID msg, err := warp.NewUnsignedMessage( networkID, chainID, From 6b839ed2ace709e41aabf78c6a425bfb066a23a1 Mon Sep 17 00:00:00 2001 From: Michael Kaplan Date: Fri, 6 Sep 2024 18:57:44 -0400 Subject: [PATCH 5/9] Order mock validator set --- .../aggregator/aggregator_test.go | 79 +++++++++++-------- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/signature-aggregator/aggregator/aggregator_test.go b/signature-aggregator/aggregator/aggregator_test.go index f0091c34..ae08813a 100644 --- a/signature-aggregator/aggregator/aggregator_test.go +++ b/signature-aggregator/aggregator/aggregator_test.go @@ -1,9 +1,8 @@ package aggregator import ( + "bytes" "context" - "encoding/hex" - "fmt" "os" "testing" @@ -71,38 +70,51 @@ func instantiateAggregator(t *testing.T) ( return aggregator, mockNetwork } -func makeConnectedValidators(validatorCount int) (*peers.ConnectedCanonicalValidators, []*bls.SecretKey) { - var validatorSet []*warp.Validator - var validatorSecretKeys []*bls.SecretKey +// Generate the validator values. +type ValidatorInfo struct { + nodeID ids.NodeID + blsSecretKey *bls.SecretKey + blsPublicKey *bls.PublicKey + blsPublicKeyBytes []byte +} - nodeValidatorIndexMap := make(map[ids.NodeID]int) +func (v ValidatorInfo) Compare(o ValidatorInfo) int { + return bytes.Compare(v.blsPublicKeyBytes, o.blsPublicKeyBytes) +} +func makeConnectedValidators(validatorCount int) (*peers.ConnectedCanonicalValidators, []*bls.SecretKey) { + validatorValues := make([]ValidatorInfo, validatorCount) for i := 0; i < validatorCount; i++ { secretKey, err := bls.NewSecretKey() if err != nil { panic(err) } - validatorSecretKeys = append(validatorSecretKeys, secretKey) - pubKey := bls.PublicFromSecretKey(secretKey) - nodeID := ids.GenerateTestNodeID() - nodeValidatorIndexMap[nodeID] = i + validatorValues[i] = ValidatorInfo{ + nodeID: nodeID, + blsSecretKey: secretKey, + blsPublicKey: pubKey, + blsPublicKeyBytes: bls.PublicKeyToUncompressedBytes(pubKey), + } + } - fmt.Printf( - "validator with pubKey %s has nodeID %s\n", - hex.EncodeToString(bls.PublicKeyToUncompressedBytes(pubKey)), - nodeID.String(), - ) + // Sort the validators by public key to construct the NodeValidatorIndexMap + utils.Sort(validatorValues) - validatorSet = append(validatorSet, - &warp.Validator{ - PublicKey: pubKey, - PublicKeyBytes: bls.PublicKeyToUncompressedBytes(pubKey), - Weight: 1, - NodeIDs: []ids.NodeID{nodeID}, - }, - ) + // Placeholder for results + validatorSet := make([]*warp.Validator, validatorCount) + validatorSecretKeys := make([]*bls.SecretKey, validatorCount) + nodeValidatorIndexMap := make(map[ids.NodeID]int) + for i, validator := range validatorValues { + validatorSecretKeys[i] = validator.blsSecretKey + validatorSet[i] = &warp.Validator{ + PublicKey: validator.blsPublicKey, + PublicKeyBytes: validator.blsPublicKeyBytes, + Weight: 1, + NodeIDs: []ids.NodeID{validator.nodeID}, + } + nodeValidatorIndexMap[validator.nodeID] = i } return &peers.ConnectedCanonicalValidators{ @@ -325,19 +337,16 @@ func TestCreateSignedMessageSucceeds(t *testing.T) { 1, connectedValidators, ) - require.Equal( - t, - nil, - signedMessage.Signature.Verify( - context.Background(), - msg, - networkID, - pChainState, - pChainState.currentHeight, - quorumPercentage, - 100, - ), + verifyErr := signedMessage.Signature.Verify( + context.Background(), + msg, + networkID, + pChainState, + pChainState.currentHeight, + quorumPercentage, + 100, ) + require.NoError(t, verifyErr) } type pChainStateStub struct { From 142df89413c26921b9edf11205991649968c3100 Mon Sep 17 00:00:00 2001 From: Michael Kaplan Date: Fri, 6 Sep 2024 19:01:03 -0400 Subject: [PATCH 6/9] Unexport struct --- signature-aggregator/aggregator/aggregator_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/signature-aggregator/aggregator/aggregator_test.go b/signature-aggregator/aggregator/aggregator_test.go index ae08813a..04aa9810 100644 --- a/signature-aggregator/aggregator/aggregator_test.go +++ b/signature-aggregator/aggregator/aggregator_test.go @@ -71,19 +71,19 @@ func instantiateAggregator(t *testing.T) ( } // Generate the validator values. -type ValidatorInfo struct { +type validatorInfo struct { nodeID ids.NodeID blsSecretKey *bls.SecretKey blsPublicKey *bls.PublicKey blsPublicKeyBytes []byte } -func (v ValidatorInfo) Compare(o ValidatorInfo) int { +func (v validatorInfo) Compare(o validatorInfo) int { return bytes.Compare(v.blsPublicKeyBytes, o.blsPublicKeyBytes) } func makeConnectedValidators(validatorCount int) (*peers.ConnectedCanonicalValidators, []*bls.SecretKey) { - validatorValues := make([]ValidatorInfo, validatorCount) + validatorValues := make([]validatorInfo, validatorCount) for i := 0; i < validatorCount; i++ { secretKey, err := bls.NewSecretKey() if err != nil { @@ -91,7 +91,7 @@ func makeConnectedValidators(validatorCount int) (*peers.ConnectedCanonicalValid } pubKey := bls.PublicFromSecretKey(secretKey) nodeID := ids.GenerateTestNodeID() - validatorValues[i] = ValidatorInfo{ + validatorValues[i] = validatorInfo{ nodeID: nodeID, blsSecretKey: secretKey, blsPublicKey: pubKey, From fd04dc52689ce5930f15684875e2a9e7f3e23ab8 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Tue, 10 Sep 2024 16:16:56 +0000 Subject: [PATCH 7/9] stop logging public keys on signature cache hit addresses review comment https://github.com/ava-labs/awm-relayer/pull/467/files#r1752146075 --- signature-aggregator/aggregator/cache/cache.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/signature-aggregator/aggregator/cache/cache.go b/signature-aggregator/aggregator/cache/cache.go index 89d30941..7363e07e 100644 --- a/signature-aggregator/aggregator/cache/cache.go +++ b/signature-aggregator/aggregator/cache/cache.go @@ -1,7 +1,6 @@ package cache import ( - "encoding/hex" "math" "github.com/ava-labs/avalanchego/ids" @@ -42,15 +41,10 @@ func (c *Cache) Get(msgID ids.ID) (map[PublicKeyBytes]SignatureBytes, bool) { cachedValue, isCached := c.signatures.Get(msgID) if isCached { - var encodedKeys []string - for key := range cachedValue { - encodedKeys = append(encodedKeys, hex.EncodeToString(key[:])) - } c.logger.Debug( "cache hit", zap.Stringer("msgID", msgID), zap.Int("signatureCount", len(cachedValue)), - zap.Strings("public keys", encodedKeys), ) return cachedValue, true } else { From 2a475ea0a59e8085dfe8c6d1cab0919053e6116b Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Tue, 10 Sep 2024 20:57:57 +0000 Subject: [PATCH 8/9] adapt to `ids.RequestID` changes --- signature-aggregator/aggregator/aggregator_test.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/signature-aggregator/aggregator/aggregator_test.go b/signature-aggregator/aggregator/aggregator_test.go index 82734f11..03273145 100644 --- a/signature-aggregator/aggregator/aggregator_test.go +++ b/signature-aggregator/aggregator/aggregator_test.go @@ -178,10 +178,9 @@ func makeAppRequests( appRequests = append( appRequests, ids.RequestID{ - NodeID: nodeID, - SourceChainID: chainID, - DestinationChainID: chainID, - RequestID: requestID, + NodeID: nodeID, + ChainID: chainID, + RequestID: requestID, Op: byte( message.AppResponseOp, ), From b064aa81946953992a32b51eb44813f19a198caf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:35:20 +0000 Subject: [PATCH 9/9] Bump google.golang.org/grpc from 1.66.1 to 1.66.2 Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.66.1 to 1.66.2. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.66.1...v1.66.2) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 60c864d5..8c2db5c3 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/stretchr/testify v1.9.0 go.uber.org/mock v0.4.0 go.uber.org/zap v1.27.0 - google.golang.org/grpc v1.66.1 + google.golang.org/grpc v1.66.2 google.golang.org/protobuf v1.34.2 ) diff --git a/go.sum b/go.sum index 80a606f5..1fe265ad 100644 --- a/go.sum +++ b/go.sum @@ -1027,8 +1027,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.66.1 h1:hO5qAXR19+/Z44hmvIM4dQFMSYX9XcWsByfoxutBpAM= -google.golang.org/grpc v1.66.1/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= +google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=