github.com/ava-labs/avalanchego@v1.11.11/vms/platformvm/network/network_test.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package network
     5  
     6  import (
     7  	"context"
     8  	"errors"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/prometheus/client_golang/prometheus"
    13  	"github.com/stretchr/testify/require"
    14  	"go.uber.org/mock/gomock"
    15  
    16  	"github.com/ava-labs/avalanchego/ids"
    17  	"github.com/ava-labs/avalanchego/snow/engine/common"
    18  	"github.com/ava-labs/avalanchego/snow/engine/common/commonmock"
    19  	"github.com/ava-labs/avalanchego/snow/snowtest"
    20  	"github.com/ava-labs/avalanchego/vms/platformvm/txs"
    21  	"github.com/ava-labs/avalanchego/vms/platformvm/txs/mempool/mempoolmock"
    22  	"github.com/ava-labs/avalanchego/vms/txs/mempool"
    23  
    24  	pmempool "github.com/ava-labs/avalanchego/vms/platformvm/txs/mempool"
    25  )
    26  
    27  var (
    28  	errTest = errors.New("test error")
    29  
    30  	testConfig = Config{
    31  		MaxValidatorSetStaleness:                    time.Second,
    32  		TargetGossipSize:                            1,
    33  		PushGossipNumValidators:                     1,
    34  		PushGossipNumPeers:                          0,
    35  		PushRegossipNumValidators:                   1,
    36  		PushRegossipNumPeers:                        0,
    37  		PushGossipDiscardedCacheSize:                1,
    38  		PushGossipMaxRegossipFrequency:              time.Second,
    39  		PushGossipFrequency:                         time.Second,
    40  		PullGossipPollSize:                          1,
    41  		PullGossipFrequency:                         time.Second,
    42  		PullGossipThrottlingPeriod:                  time.Second,
    43  		PullGossipThrottlingLimit:                   1,
    44  		ExpectedBloomFilterElements:                 10,
    45  		ExpectedBloomFilterFalsePositiveProbability: .1,
    46  		MaxBloomFilterFalsePositiveProbability:      .5,
    47  	}
    48  )
    49  
    50  var _ TxVerifier = (*testTxVerifier)(nil)
    51  
    52  type testTxVerifier struct {
    53  	err error
    54  }
    55  
    56  func (t testTxVerifier) VerifyTx(*txs.Tx) error {
    57  	return t.err
    58  }
    59  
    60  func TestNetworkIssueTxFromRPC(t *testing.T) {
    61  	tx := &txs.Tx{}
    62  
    63  	type test struct {
    64  		name                      string
    65  		mempoolFunc               func(*gomock.Controller) pmempool.Mempool
    66  		txVerifier                testTxVerifier
    67  		partialSyncPrimaryNetwork bool
    68  		appSenderFunc             func(*gomock.Controller) common.AppSender
    69  		expectedErr               error
    70  	}
    71  
    72  	tests := []test{
    73  		{
    74  			name: "mempool has transaction",
    75  			mempoolFunc: func(ctrl *gomock.Controller) pmempool.Mempool {
    76  				mempool := mempoolmock.NewMempool(ctrl)
    77  				mempool.EXPECT().Get(gomock.Any()).Return(tx, true)
    78  				return mempool
    79  			},
    80  			appSenderFunc: func(ctrl *gomock.Controller) common.AppSender {
    81  				return commonmock.NewSender(ctrl)
    82  			},
    83  			expectedErr: mempool.ErrDuplicateTx,
    84  		},
    85  		{
    86  			name: "transaction marked as dropped in mempool",
    87  			mempoolFunc: func(ctrl *gomock.Controller) pmempool.Mempool {
    88  				mempool := mempoolmock.NewMempool(ctrl)
    89  				mempool.EXPECT().Get(gomock.Any()).Return(nil, false)
    90  				mempool.EXPECT().GetDropReason(gomock.Any()).Return(errTest)
    91  				return mempool
    92  			},
    93  			appSenderFunc: func(ctrl *gomock.Controller) common.AppSender {
    94  				// Shouldn't gossip the tx
    95  				return commonmock.NewSender(ctrl)
    96  			},
    97  			expectedErr: errTest,
    98  		},
    99  		{
   100  			name: "transaction invalid",
   101  			mempoolFunc: func(ctrl *gomock.Controller) pmempool.Mempool {
   102  				mempool := mempoolmock.NewMempool(ctrl)
   103  				mempool.EXPECT().Get(gomock.Any()).Return(nil, false)
   104  				mempool.EXPECT().GetDropReason(gomock.Any()).Return(nil)
   105  				mempool.EXPECT().MarkDropped(gomock.Any(), gomock.Any())
   106  				return mempool
   107  			},
   108  			txVerifier: testTxVerifier{err: errTest},
   109  			appSenderFunc: func(ctrl *gomock.Controller) common.AppSender {
   110  				// Shouldn't gossip the tx
   111  				return commonmock.NewSender(ctrl)
   112  			},
   113  			expectedErr: errTest,
   114  		},
   115  		{
   116  			name: "can't add transaction to mempool",
   117  			mempoolFunc: func(ctrl *gomock.Controller) pmempool.Mempool {
   118  				mempool := mempoolmock.NewMempool(ctrl)
   119  				mempool.EXPECT().Get(gomock.Any()).Return(nil, false)
   120  				mempool.EXPECT().GetDropReason(gomock.Any()).Return(nil)
   121  				mempool.EXPECT().Add(gomock.Any()).Return(errTest)
   122  				mempool.EXPECT().MarkDropped(gomock.Any(), gomock.Any())
   123  				return mempool
   124  			},
   125  			appSenderFunc: func(ctrl *gomock.Controller) common.AppSender {
   126  				// Shouldn't gossip the tx
   127  				return commonmock.NewSender(ctrl)
   128  			},
   129  			expectedErr: errTest,
   130  		},
   131  		{
   132  			name: "mempool is disabled if primary network is not being fully synced",
   133  			mempoolFunc: func(ctrl *gomock.Controller) pmempool.Mempool {
   134  				return mempoolmock.NewMempool(ctrl)
   135  			},
   136  			partialSyncPrimaryNetwork: true,
   137  			appSenderFunc: func(ctrl *gomock.Controller) common.AppSender {
   138  				return commonmock.NewSender(ctrl)
   139  			},
   140  			expectedErr: errMempoolDisabledWithPartialSync,
   141  		},
   142  		{
   143  			name: "happy path",
   144  			mempoolFunc: func(ctrl *gomock.Controller) pmempool.Mempool {
   145  				mempool := mempoolmock.NewMempool(ctrl)
   146  				mempool.EXPECT().Get(gomock.Any()).Return(nil, false)
   147  				mempool.EXPECT().GetDropReason(gomock.Any()).Return(nil)
   148  				mempool.EXPECT().Add(gomock.Any()).Return(nil)
   149  				mempool.EXPECT().Len().Return(0)
   150  				mempool.EXPECT().RequestBuildBlock(false)
   151  				mempool.EXPECT().Get(gomock.Any()).Return(nil, true).Times(2)
   152  				return mempool
   153  			},
   154  			appSenderFunc: func(ctrl *gomock.Controller) common.AppSender {
   155  				appSender := commonmock.NewSender(ctrl)
   156  				appSender.EXPECT().SendAppGossip(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   157  				return appSender
   158  			},
   159  			expectedErr: nil,
   160  		},
   161  	}
   162  
   163  	for _, tt := range tests {
   164  		t.Run(tt.name, func(t *testing.T) {
   165  			require := require.New(t)
   166  			ctrl := gomock.NewController(t)
   167  
   168  			snowCtx := snowtest.Context(t, ids.Empty)
   169  			n, err := New(
   170  				snowCtx.Log,
   171  				snowCtx.NodeID,
   172  				snowCtx.SubnetID,
   173  				snowCtx.ValidatorState,
   174  				tt.txVerifier,
   175  				tt.mempoolFunc(ctrl),
   176  				tt.partialSyncPrimaryNetwork,
   177  				tt.appSenderFunc(ctrl),
   178  				prometheus.NewRegistry(),
   179  				testConfig,
   180  			)
   181  			require.NoError(err)
   182  
   183  			err = n.IssueTxFromRPC(tx)
   184  			require.ErrorIs(err, tt.expectedErr)
   185  
   186  			require.NoError(n.txPushGossiper.Gossip(context.Background()))
   187  		})
   188  	}
   189  }