Skip to content

Commit cd98b4e

Browse files
committed
happy path test
addresses review comment #457 (comment)
1 parent ad87ee7 commit cd98b4e

2 files changed

Lines changed: 244 additions & 6 deletions

File tree

‎peers/app_request_network.go‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,12 @@ type ConnectedCanonicalValidators struct {
212212
ConnectedWeight uint64
213213
TotalValidatorWeight uint64
214214
ValidatorSet []*warp.Validator
215-
nodeValidatorIndexMap map[ids.NodeID]int
215+
NodeValidatorIndexMap map[ids.NodeID]int
216216
}
217217

218218
// Returns the Warp Validator and its index in the canonical Validator ordering for a given nodeID
219219
func (c *ConnectedCanonicalValidators) GetValidator(nodeID ids.NodeID) (*warp.Validator, int) {
220-
return c.ValidatorSet[c.nodeValidatorIndexMap[nodeID]], c.nodeValidatorIndexMap[nodeID]
220+
return c.ValidatorSet[c.NodeValidatorIndexMap[nodeID]], c.NodeValidatorIndexMap[nodeID]
221221
}
222222

223223
// 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
258258
ConnectedWeight: connectedWeight,
259259
TotalValidatorWeight: totalValidatorWeight,
260260
ValidatorSet: validatorSet,
261-
nodeValidatorIndexMap: nodeValidatorIndexMap,
261+
NodeValidatorIndexMap: nodeValidatorIndexMap,
262262
}, nil
263263
}
264264

‎signature-aggregator/aggregator/aggregator_test.go‎

Lines changed: 241 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,36 @@
11
package aggregator
22

33
import (
4+
"os"
45
"testing"
56

67
"github.com/ava-labs/avalanchego/ids"
78
"github.com/ava-labs/avalanchego/message"
9+
"github.com/ava-labs/avalanchego/subnets"
10+
"github.com/ava-labs/avalanchego/utils"
811
"github.com/ava-labs/avalanchego/utils/constants"
12+
"github.com/ava-labs/avalanchego/utils/crypto/bls"
913
"github.com/ava-labs/avalanchego/utils/logging"
14+
"github.com/ava-labs/avalanchego/utils/set"
1015
"github.com/ava-labs/avalanchego/vms/platformvm/warp"
1116
"github.com/ava-labs/awm-relayer/peers"
1217
"github.com/ava-labs/awm-relayer/peers/mocks"
1318
"github.com/ava-labs/awm-relayer/signature-aggregator/metrics"
19+
evmMsg "github.com/ava-labs/subnet-evm/plugin/evm/message"
1420
"github.com/prometheus/client_golang/prometheus"
1521
"github.com/stretchr/testify/require"
1622
"go.uber.org/mock/gomock"
23+
"go.uber.org/zap"
24+
"go.uber.org/zap/zapcore"
1725
)
1826

19-
var sigAggMetrics *metrics.SignatureAggregatorMetrics
20-
var messageCreator message.Creator
27+
const validatorCount = 2
28+
29+
var (
30+
sigAggMetrics *metrics.SignatureAggregatorMetrics
31+
messageCreator message.Creator
32+
validatorSecretKeys []*bls.SecretKey
33+
)
2134

2235
func instantiateAggregator(t *testing.T) (
2336
*SignatureAggregator,
@@ -39,7 +52,16 @@ func instantiateAggregator(t *testing.T) (
3952
}
4053
aggregator, err := NewSignatureAggregator(
4154
mockNetwork,
42-
logging.NoLog{},
55+
logging.NewLogger(
56+
"aggregator_test",
57+
logging.NewWrappedCore(
58+
logging.Debug,
59+
os.Stdout,
60+
zapcore.NewConsoleEncoder(
61+
zap.NewProductionEncoderConfig(),
62+
),
63+
),
64+
),
4365
1024,
4466
sigAggMetrics,
4567
messageCreator,
@@ -48,6 +70,63 @@ func instantiateAggregator(t *testing.T) (
4870
return aggregator, mockNetwork
4971
}
5072

73+
func makeConnectedValidators() *peers.ConnectedCanonicalValidators {
74+
var validatorSet []*warp.Validator
75+
for i := 0; i < validatorCount; i++ {
76+
secretKey, err := bls.NewSecretKey()
77+
if err != nil {
78+
panic(err)
79+
}
80+
validatorSecretKeys = append(validatorSecretKeys, secretKey)
81+
82+
pubKey := bls.PublicFromSecretKey(secretKey)
83+
84+
nodeID, err := ids.ToNodeID(utils.RandomBytes(20))
85+
if err != nil {
86+
panic(err)
87+
}
88+
89+
validatorSet = append(validatorSet,
90+
&warp.Validator{
91+
PublicKey: pubKey,
92+
PublicKeyBytes: bls.PublicKeyToUncompressedBytes(pubKey),
93+
Weight: 1,
94+
NodeIDs: []ids.NodeID{nodeID},
95+
},
96+
)
97+
}
98+
99+
nodeValidatorIndexMap := make(map[ids.NodeID]int)
100+
for i, vdr := range validatorSet {
101+
for _, node := range vdr.NodeIDs {
102+
nodeValidatorIndexMap[node] = i
103+
}
104+
}
105+
106+
107+
return &peers.ConnectedCanonicalValidators{
108+
ConnectedWeight: validatorCount,
109+
TotalValidatorWeight: validatorCount,
110+
ValidatorSet: validatorSet,
111+
NodeValidatorIndexMap: nodeValidatorIndexMap,
112+
}
113+
}
114+
115+
func minimumViableAppRequest(requestID uint32, nodeID ids.NodeID) ids.RequestID {
116+
chainID, err := ids.ToID(utils.RandomBytes(32))
117+
if err != nil {
118+
panic(err)
119+
}
120+
121+
return ids.RequestID{
122+
NodeID: nodeID,
123+
SourceChainID: chainID,
124+
DestinationChainID: chainID,
125+
RequestID: requestID,
126+
Op: byte(message.AppResponseOp),
127+
}
128+
}
129+
51130
func TestCreateSignedMessageFailsWithNoValidators(t *testing.T) {
52131
aggregator, mockNetwork := instantiateAggregator(t)
53132
msg, err := warp.NewUnsignedMessage(0, ids.Empty, []byte{})
@@ -85,3 +164,162 @@ func TestCreateSignedMessageFailsWithoutSufficientConnectedStake(t *testing.T) {
85164
"failed to connect to a threshold of stake",
86165
)
87166
}
167+
168+
func TestCreateSignedMessageRetriesAndFailsWithoutP2PResponses(t *testing.T) {
169+
aggregator, mockNetwork := instantiateAggregator(t)
170+
171+
var (
172+
connectedValidators = makeConnectedValidators()
173+
requestID = aggregator.currentRequestID.Load() + 1
174+
)
175+
176+
chainID, err := ids.ToID(utils.RandomBytes(32))
177+
if err != nil {
178+
panic(err)
179+
}
180+
181+
appRequest1 := ids.RequestID{
182+
NodeID: connectedValidators.ValidatorSet[1].NodeIDs[0],
183+
SourceChainID: chainID,
184+
DestinationChainID: chainID,
185+
RequestID: requestID,
186+
Op: byte(message.AppResponseOp),
187+
}
188+
appRequest2 := ids.RequestID{
189+
NodeID: connectedValidators.ValidatorSet[0].NodeIDs[0],
190+
SourceChainID: chainID,
191+
DestinationChainID: chainID,
192+
RequestID: requestID,
193+
Op: byte(message.AppResponseOp),
194+
}
195+
196+
msg, err := warp.NewUnsignedMessage(
197+
0,
198+
appRequest1.SourceChainID,
199+
[]byte{},
200+
)
201+
require.Equal(t, err, nil)
202+
203+
subnetID, err := ids.ToID(utils.RandomBytes(32))
204+
require.Equal(t, err, nil)
205+
mockNetwork.EXPECT().GetSubnetID(appRequest1.SourceChainID).Return(
206+
subnetID,
207+
nil,
208+
)
209+
210+
mockNetwork.EXPECT().ConnectToCanonicalValidators(subnetID).Return(
211+
connectedValidators,
212+
nil,
213+
)
214+
215+
for i := 0; i < maxRelayerQueryAttempts; i++ {
216+
mockNetwork.EXPECT().RegisterAppRequest(appRequest1).Times(1)
217+
mockNetwork.EXPECT().RegisterAppRequest(appRequest2).Times(1)
218+
}
219+
220+
validatorCount := len(connectedValidators.ValidatorSet)
221+
mockNetwork.EXPECT().RegisterRequestID(
222+
requestID,
223+
validatorCount,
224+
).Return(
225+
make(chan message.InboundMessage, validatorCount),
226+
).MaxTimes(maxRelayerQueryAttempts * validatorCount)
227+
228+
mockNetwork.EXPECT().Send(
229+
gomock.Any(),
230+
set.Of(appRequest1.NodeID, appRequest2.NodeID),
231+
subnetID,
232+
subnets.NoOpAllower,
233+
).MaxTimes(maxRelayerQueryAttempts)
234+
235+
_, err = aggregator.CreateSignedMessage(msg, subnetID, 80)
236+
require.ErrorContains(
237+
t,
238+
err,
239+
"failed to collect a threshold of signatures",
240+
)
241+
}
242+
243+
func TestCreateSignedMessageSucceeds(t *testing.T) {
244+
aggregator, mockNetwork := instantiateAggregator(t)
245+
246+
var (
247+
connectedValidators = makeConnectedValidators()
248+
requestID = aggregator.currentRequestID.Load() + 1
249+
)
250+
251+
chainID, err := ids.ToID(utils.RandomBytes(32))
252+
if err != nil {
253+
panic(err)
254+
}
255+
256+
appRequest1 := ids.RequestID{
257+
NodeID: connectedValidators.ValidatorSet[1].NodeIDs[0],
258+
SourceChainID: chainID,
259+
DestinationChainID: chainID,
260+
RequestID: requestID,
261+
Op: byte(message.AppResponseOp),
262+
}
263+
appRequest2 := ids.RequestID{
264+
NodeID: connectedValidators.ValidatorSet[0].NodeIDs[0],
265+
SourceChainID: chainID,
266+
DestinationChainID: chainID,
267+
RequestID: requestID,
268+
Op: byte(message.AppResponseOp),
269+
}
270+
271+
msg, err := warp.NewUnsignedMessage(0, chainID, utils.RandomBytes(1234))
272+
require.Equal(t, err, nil)
273+
274+
subnetID, err := ids.ToID(utils.RandomBytes(32))
275+
require.Equal(t, err, nil)
276+
mockNetwork.EXPECT().GetSubnetID(chainID).Return(
277+
subnetID,
278+
nil,
279+
)
280+
281+
mockNetwork.EXPECT().ConnectToCanonicalValidators(subnetID).Return(
282+
connectedValidators,
283+
nil,
284+
)
285+
286+
mockNetwork.EXPECT().RegisterAppRequest(appRequest1).Times(1)
287+
mockNetwork.EXPECT().RegisterAppRequest(appRequest2).Times(1)
288+
289+
responseChan := make(chan message.InboundMessage, 2)
290+
for i := 0; i < validatorCount; i++ {
291+
responseBytes, err := evmMsg.Codec.Marshal(
292+
0,
293+
&evmMsg.SignatureResponse {
294+
Signature: [bls.SignatureLen]byte(
295+
bls.SignatureToBytes(
296+
bls.Sign(
297+
validatorSecretKeys[i],
298+
msg.Bytes(),
299+
),
300+
),
301+
),
302+
},
303+
)
304+
require.Equal(t, err, nil)
305+
responseChan <- message.InboundAppResponse(
306+
chainID,
307+
requestID,
308+
responseBytes,
309+
connectedValidators.ValidatorSet[i].NodeIDs[0],
310+
)
311+
}
312+
mockNetwork.EXPECT().RegisterRequestID(requestID, 2).Return(
313+
responseChan,
314+
).Times(1)
315+
316+
mockNetwork.EXPECT().Send(
317+
gomock.Any(),
318+
set.Of(appRequest2.NodeID, appRequest1.NodeID),
319+
subnetID,
320+
subnets.NoOpAllower,
321+
).Times(1).Return(set.Of(appRequest2.NodeID, appRequest1.NodeID))
322+
323+
_, err = aggregator.CreateSignedMessage(msg, subnetID, 80)
324+
require.Equal(t, err, nil)
325+
}

0 commit comments

Comments
 (0)