2021-04-22 13:36:18 +00:00
|
|
|
package transport
|
2020-01-13 19:17:30 +00:00
|
|
|
|
|
|
|
import (
|
2024-05-31 13:17:44 +00:00
|
|
|
"context"
|
2023-11-17 14:45:19 +00:00
|
|
|
"reflect"
|
2020-01-13 19:17:30 +00:00
|
|
|
"testing"
|
2024-05-31 13:17:44 +00:00
|
|
|
"time"
|
2020-01-13 19:17:30 +00:00
|
|
|
|
|
|
|
"go.uber.org/zap"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
|
|
|
|
|
|
|
"github.com/status-im/status-go/eth-node/crypto"
|
|
|
|
"github.com/status-im/status-go/eth-node/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2023-11-17 14:45:19 +00:00
|
|
|
testHash = types.Hash{0x01}
|
|
|
|
testHashes = []types.Hash{testHash}
|
|
|
|
testIDs = [][]byte{[]byte("id")}
|
2020-01-13 19:17:30 +00:00
|
|
|
)
|
|
|
|
|
2023-11-17 14:45:19 +00:00
|
|
|
type envelopeEventsHandlerMock struct {
|
|
|
|
envelopeSentCalls [][][]byte // slice of EnvelopeSent arguments
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *envelopeEventsHandlerMock) EnvelopeSent(identifiers [][]byte) {
|
|
|
|
h.envelopeSentCalls = append(h.envelopeSentCalls, identifiers)
|
|
|
|
}
|
|
|
|
func (h *envelopeEventsHandlerMock) EnvelopeExpired([][]byte, error) {
|
|
|
|
}
|
|
|
|
func (h *envelopeEventsHandlerMock) MailServerRequestCompleted(types.Hash, types.Hash, []byte, error) {
|
|
|
|
}
|
|
|
|
func (h *envelopeEventsHandlerMock) MailServerRequestExpired(types.Hash) {
|
|
|
|
}
|
|
|
|
|
2020-01-13 19:17:30 +00:00
|
|
|
type EnvelopesMonitorSuite struct {
|
|
|
|
suite.Suite
|
|
|
|
|
2023-11-17 14:45:19 +00:00
|
|
|
monitor *EnvelopesMonitor
|
|
|
|
eventsHandlerMock *envelopeEventsHandlerMock
|
2020-01-13 19:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEnvelopesMonitorSuite(t *testing.T) {
|
|
|
|
suite.Run(t, new(EnvelopesMonitorSuite))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *EnvelopesMonitorSuite) SetupTest() {
|
2023-11-17 14:45:19 +00:00
|
|
|
s.eventsHandlerMock = &envelopeEventsHandlerMock{}
|
2020-01-13 19:17:30 +00:00
|
|
|
s.monitor = NewEnvelopesMonitor(
|
|
|
|
nil,
|
2021-04-22 13:36:18 +00:00
|
|
|
EnvelopesMonitorConfig{
|
2023-11-17 14:45:19 +00:00
|
|
|
EnvelopeEventsHandler: s.eventsHandlerMock,
|
2024-05-31 13:17:44 +00:00
|
|
|
MaxAttempts: 6,
|
2021-11-19 12:17:59 +00:00
|
|
|
AwaitOnlyMailServerConfirmations: false,
|
|
|
|
IsMailserver: func(types.EnodeID) bool { return false },
|
|
|
|
Logger: zap.NewNop(),
|
2020-01-13 19:17:30 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-11-19 12:17:59 +00:00
|
|
|
func (s *EnvelopesMonitorSuite) TestEnvelopePosted() {
|
2023-11-17 14:45:19 +00:00
|
|
|
err := s.monitor.Add(testIDs, testHashes, []*types.NewMessage{{}})
|
|
|
|
s.Require().NoError(err)
|
2020-01-13 19:17:30 +00:00
|
|
|
s.Contains(s.monitor.envelopes, testHash)
|
2023-11-22 18:28:40 +00:00
|
|
|
s.Equal(EnvelopePosted, s.monitor.envelopes[testHash].state)
|
2020-01-13 19:17:30 +00:00
|
|
|
s.monitor.handleEvent(types.EnvelopeEvent{
|
|
|
|
Event: types.EventEnvelopeSent,
|
|
|
|
Hash: testHash,
|
|
|
|
})
|
|
|
|
s.Contains(s.monitor.envelopes, testHash)
|
2023-11-22 18:28:40 +00:00
|
|
|
s.Equal(EnvelopeSent, s.monitor.envelopes[testHash].state)
|
2020-01-13 19:17:30 +00:00
|
|
|
}
|
|
|
|
|
2023-06-13 15:08:22 +00:00
|
|
|
func (s *EnvelopesMonitorSuite) TestEnvelopePostedOutOfOrder() {
|
|
|
|
s.monitor.handleEvent(types.EnvelopeEvent{
|
|
|
|
Event: types.EventEnvelopeSent,
|
|
|
|
Hash: testHash,
|
|
|
|
})
|
|
|
|
|
2023-11-17 14:45:19 +00:00
|
|
|
err := s.monitor.Add(testIDs, testHashes, []*types.NewMessage{{}})
|
|
|
|
s.Require().NoError(err)
|
2023-06-13 15:08:22 +00:00
|
|
|
s.Require().Contains(s.monitor.envelopes, testHash)
|
2023-11-22 18:28:40 +00:00
|
|
|
s.Require().Equal(EnvelopeSent, s.monitor.envelopes[testHash].state)
|
2023-06-13 15:08:22 +00:00
|
|
|
}
|
|
|
|
|
2020-01-13 19:17:30 +00:00
|
|
|
func (s *EnvelopesMonitorSuite) TestConfirmedWithAcknowledge() {
|
|
|
|
testBatch := types.Hash{1}
|
|
|
|
pkey, err := crypto.GenerateKey()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
node := enode.NewV4(&pkey.PublicKey, nil, 0, 0)
|
2023-11-17 14:45:19 +00:00
|
|
|
err = s.monitor.Add(testIDs, testHashes, []*types.NewMessage{{}})
|
|
|
|
s.Require().NoError(err)
|
2020-01-13 19:17:30 +00:00
|
|
|
s.Contains(s.monitor.envelopes, testHash)
|
2023-11-22 18:28:40 +00:00
|
|
|
s.Equal(EnvelopePosted, s.monitor.envelopes[testHash].state)
|
2020-01-13 19:17:30 +00:00
|
|
|
s.monitor.handleEvent(types.EnvelopeEvent{
|
|
|
|
Event: types.EventEnvelopeSent,
|
|
|
|
Hash: testHash,
|
|
|
|
Batch: testBatch,
|
|
|
|
})
|
2023-11-22 18:28:40 +00:00
|
|
|
s.Equal(EnvelopePosted, s.monitor.envelopes[testHash].state)
|
2020-01-13 19:17:30 +00:00
|
|
|
s.monitor.handleEvent(types.EnvelopeEvent{
|
|
|
|
Event: types.EventBatchAcknowledged,
|
|
|
|
Batch: testBatch,
|
|
|
|
Peer: types.EnodeID(node.ID()),
|
|
|
|
})
|
|
|
|
s.Contains(s.monitor.envelopes, testHash)
|
2023-11-22 18:28:40 +00:00
|
|
|
s.Equal(EnvelopeSent, s.monitor.envelopes[testHash].state)
|
2020-01-13 19:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *EnvelopesMonitorSuite) TestRemoved() {
|
2023-11-17 14:45:19 +00:00
|
|
|
err := s.monitor.Add(testIDs, testHashes, []*types.NewMessage{{}})
|
|
|
|
s.Require().NoError(err)
|
2020-01-13 19:17:30 +00:00
|
|
|
s.Contains(s.monitor.envelopes, testHash)
|
|
|
|
s.monitor.handleEvent(types.EnvelopeEvent{
|
|
|
|
Event: types.EventEnvelopeExpired,
|
|
|
|
Hash: testHash,
|
|
|
|
})
|
|
|
|
s.NotContains(s.monitor.envelopes, testHash)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *EnvelopesMonitorSuite) TestIgnoreNotFromMailserver() {
|
|
|
|
// enables filter in the tracker to drop confirmations from non-mailserver peers
|
2021-11-19 12:17:59 +00:00
|
|
|
s.monitor.awaitOnlyMailServerConfirmations = true
|
2023-11-17 14:45:19 +00:00
|
|
|
err := s.monitor.Add(testIDs, testHashes, []*types.NewMessage{{}})
|
|
|
|
s.Require().NoError(err)
|
2020-01-13 19:17:30 +00:00
|
|
|
s.monitor.handleEvent(types.EnvelopeEvent{
|
|
|
|
Event: types.EventEnvelopeSent,
|
|
|
|
Hash: testHash,
|
|
|
|
Peer: types.EnodeID{1}, // could be empty, doesn't impact test behaviour
|
|
|
|
})
|
|
|
|
s.Require().Equal(EnvelopePosted, s.monitor.GetState(testHash))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *EnvelopesMonitorSuite) TestReceived() {
|
|
|
|
s.monitor.isMailserver = func(peer types.EnodeID) bool {
|
|
|
|
return true
|
|
|
|
}
|
2023-11-17 14:45:19 +00:00
|
|
|
err := s.monitor.Add(testIDs, testHashes, []*types.NewMessage{{}})
|
|
|
|
s.Require().NoError(err)
|
2020-01-13 19:17:30 +00:00
|
|
|
s.Contains(s.monitor.envelopes, testHash)
|
|
|
|
s.monitor.handleEvent(types.EnvelopeEvent{
|
|
|
|
Event: types.EventEnvelopeReceived,
|
|
|
|
Hash: testHash,
|
|
|
|
})
|
|
|
|
s.Require().Equal(EnvelopeSent, s.monitor.GetState(testHash))
|
|
|
|
}
|
2023-11-17 14:45:19 +00:00
|
|
|
|
|
|
|
func (s *EnvelopesMonitorSuite) TestMultipleHashes() {
|
|
|
|
messageIDs := [][]byte{[]byte("id1"), []byte("id2")}
|
|
|
|
hashes := []types.Hash{{0x01}, {0x02}, {0x03}}
|
|
|
|
messages := []*types.NewMessage{{}, {}, {}}
|
|
|
|
|
|
|
|
err := s.monitor.Add(messageIDs, hashes, messages)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
for _, hash := range hashes {
|
|
|
|
s.Contains(s.monitor.envelopes, hash)
|
|
|
|
}
|
|
|
|
s.Require().Empty(s.eventsHandlerMock.envelopeSentCalls)
|
|
|
|
s.Require().Equal(EnvelopePosted, s.monitor.envelopes[hashes[0]].state)
|
|
|
|
s.Require().Equal(EnvelopePosted, s.monitor.envelopes[hashes[1]].state)
|
|
|
|
s.Require().Equal(EnvelopePosted, s.monitor.envelopes[hashes[2]].state)
|
|
|
|
|
|
|
|
s.monitor.handleEvent(types.EnvelopeEvent{
|
|
|
|
Event: types.EventEnvelopeSent,
|
|
|
|
Hash: hashes[0],
|
|
|
|
})
|
|
|
|
s.Require().Empty(s.eventsHandlerMock.envelopeSentCalls)
|
|
|
|
s.Require().Equal(EnvelopeSent, s.monitor.envelopes[hashes[0]].state)
|
|
|
|
s.Require().Equal(EnvelopePosted, s.monitor.envelopes[hashes[1]].state)
|
|
|
|
s.Require().Equal(EnvelopePosted, s.monitor.envelopes[hashes[2]].state)
|
|
|
|
|
|
|
|
s.monitor.handleEvent(types.EnvelopeEvent{
|
|
|
|
Event: types.EventEnvelopeSent,
|
|
|
|
Hash: hashes[1],
|
|
|
|
})
|
|
|
|
s.Require().Empty(s.eventsHandlerMock.envelopeSentCalls)
|
|
|
|
s.Require().Equal(EnvelopeSent, s.monitor.envelopes[hashes[0]].state)
|
|
|
|
s.Require().Equal(EnvelopeSent, s.monitor.envelopes[hashes[1]].state)
|
|
|
|
s.Require().Equal(EnvelopePosted, s.monitor.envelopes[hashes[2]].state)
|
|
|
|
|
|
|
|
s.monitor.handleEvent(types.EnvelopeEvent{
|
|
|
|
Event: types.EventEnvelopeSent,
|
|
|
|
Hash: hashes[2],
|
|
|
|
})
|
|
|
|
// Identifiers should be marked as sent only if all corresponding envelopes are sent
|
|
|
|
s.Require().Len(s.eventsHandlerMock.envelopeSentCalls, 1)
|
|
|
|
s.Require().True(reflect.DeepEqual(messageIDs, s.eventsHandlerMock.envelopeSentCalls[0]))
|
|
|
|
s.Require().Equal(EnvelopeSent, s.monitor.envelopes[hashes[0]].state)
|
|
|
|
s.Require().Equal(EnvelopeSent, s.monitor.envelopes[hashes[1]].state)
|
|
|
|
s.Require().Equal(EnvelopeSent, s.monitor.envelopes[hashes[2]].state)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *EnvelopesMonitorSuite) TestMultipleHashes_EnvelopeExpired() {
|
|
|
|
messageIDs := [][]byte{[]byte("id1"), []byte("id2")}
|
|
|
|
hashes := []types.Hash{{0x01}, {0x02}, {0x03}}
|
|
|
|
messages := []*types.NewMessage{{}, {}, {}}
|
|
|
|
|
|
|
|
err := s.monitor.Add(messageIDs, hashes, messages)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2024-05-31 13:17:44 +00:00
|
|
|
// If any envelope fails, then messageIDs are considered as not sent
|
2023-11-17 14:45:19 +00:00
|
|
|
s.monitor.handleEvent(types.EnvelopeEvent{
|
|
|
|
Event: types.EventEnvelopeExpired,
|
|
|
|
Hash: hashes[0],
|
|
|
|
})
|
|
|
|
s.monitor.handleEvent(types.EnvelopeEvent{
|
|
|
|
Event: types.EventEnvelopeSent,
|
|
|
|
Hash: hashes[1],
|
|
|
|
})
|
|
|
|
s.monitor.handleEvent(types.EnvelopeEvent{
|
|
|
|
Event: types.EventEnvelopeSent,
|
|
|
|
Hash: hashes[2],
|
|
|
|
})
|
|
|
|
|
|
|
|
s.Require().Empty(s.eventsHandlerMock.envelopeSentCalls)
|
2024-05-31 13:17:44 +00:00
|
|
|
s.Require().Empty(s.monitor.messageEnvelopeHashes)
|
2023-11-17 14:45:19 +00:00
|
|
|
s.Require().Len(s.monitor.envelopes, 2)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *EnvelopesMonitorSuite) TestMultipleHashes_Failure() {
|
|
|
|
err := s.monitor.Add(testIDs, []types.Hash{{0x01}, {0x02}}, []*types.NewMessage{{}})
|
|
|
|
s.Require().Error(err)
|
|
|
|
}
|
2024-05-31 13:17:44 +00:00
|
|
|
|
|
|
|
func (s *EnvelopesMonitorSuite) TestRetryOnce() {
|
|
|
|
s.monitor.api = &mockWakuAPI{}
|
|
|
|
err := s.monitor.Add(testIDs, testHashes, []*types.NewMessage{{}})
|
|
|
|
s.Require().NoError(err)
|
|
|
|
envelope := s.monitor.envelopes[testHash]
|
|
|
|
envelope.attempts = 2
|
|
|
|
envelope.lastAttemptTime = time.Now().Add(-20 * time.Second)
|
|
|
|
s.monitor.retryQueue = append(s.monitor.retryQueue, envelope)
|
|
|
|
|
|
|
|
s.monitor.retryOnce()
|
|
|
|
|
|
|
|
s.Require().Equal(3, envelope.attempts)
|
|
|
|
s.Require().Len(s.monitor.retryQueue, 0)
|
|
|
|
s.Require().Equal(envelope.envelopeHashID, s.monitor.envelopes[envelope.envelopeHashID].envelopeHashID)
|
|
|
|
}
|
|
|
|
|
|
|
|
type mockWakuAPI struct{}
|
|
|
|
|
|
|
|
func (m *mockWakuAPI) Post(ctx context.Context, msg types.NewMessage) ([]byte, error) {
|
|
|
|
return []byte{0x01}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockWakuAPI) AddPrivateKey(ctx context.Context, privateKey types.HexBytes) (string, error) {
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
func (m *mockWakuAPI) GenerateSymKeyFromPassword(ctx context.Context, passwd string) (string, error) {
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
func (m *mockWakuAPI) DeleteKeyPair(ctx context.Context, key string) (bool, error) {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
func (m *mockWakuAPI) NewMessageFilter(req types.Criteria) (string, error) {
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
func (m *mockWakuAPI) GetFilterMessages(id string) ([]*types.Message, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
func (m *mockWakuAPI) BloomFilter() []byte {
|
|
|
|
return nil
|
|
|
|
}
|