github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/netsync/chainmgr/tx_keeper_test.go (about)

     1  package chainmgr
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"reflect"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/davecgh/go-spew/spew"
    11  
    12  	"github.com/bytom/bytom/consensus"
    13  	dbm "github.com/bytom/bytom/database/leveldb"
    14  	"github.com/bytom/bytom/protocol"
    15  	core "github.com/bytom/bytom/protocol"
    16  	"github.com/bytom/bytom/protocol/bc"
    17  	"github.com/bytom/bytom/protocol/bc/types"
    18  	"github.com/bytom/bytom/test/mock"
    19  	"github.com/bytom/bytom/testcontrol"
    20  )
    21  
    22  const txsNumber = 2000
    23  
    24  type mempool struct {
    25  }
    26  
    27  func (m *mempool) GetTransactions() []*core.TxDesc {
    28  	txs := []*core.TxDesc{}
    29  	for i := 0; i < txsNumber; i++ {
    30  		txInput := types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, uint64(i), 1, []byte{0x51}, [][]byte{})
    31  		txInput.CommitmentSuffix = []byte{0, 1, 2}
    32  		txInput.WitnessSuffix = []byte{0, 1, 2}
    33  
    34  		tx := &types.Tx{
    35  
    36  			TxData: types.TxData{
    37  				//SerializedSize: uint64(i * 10),
    38  				Inputs: []*types.TxInput{
    39  					txInput,
    40  				},
    41  				Outputs: []*types.TxOutput{
    42  					types.NewOriginalTxOutput(*consensus.BTMAssetID, uint64(i), []byte{0x6a}, [][]byte{}),
    43  				},
    44  				SerializedSize: 1000,
    45  			},
    46  			Tx: &bc.Tx{
    47  				ID: bc.Hash{V0: uint64(i), V1: uint64(i), V2: uint64(i), V3: uint64(i)},
    48  			},
    49  		}
    50  		txs = append(txs, &core.TxDesc{Tx: tx})
    51  	}
    52  	return txs
    53  }
    54  
    55  func (m *mempool) IsDust(tx *types.Tx) bool {
    56  	return false
    57  }
    58  
    59  func TestSyncMempool(t *testing.T) {
    60  	if testcontrol.IgnoreTestTemporary {
    61  		return
    62  	}
    63  
    64  	tmpDir, err := ioutil.TempDir(".", "")
    65  	if err != nil {
    66  		t.Fatalf("failed to create temporary data folder: %v", err)
    67  	}
    68  	defer os.RemoveAll(tmpDir)
    69  	testDBA := dbm.NewDB("testdba", "leveldb", tmpDir)
    70  	testDBB := dbm.NewDB("testdbb", "leveldb", tmpDir)
    71  
    72  	blocks := mockBlocks(nil, 5)
    73  	a := mockSync(blocks, &mock.Mempool{}, testDBA)
    74  	b := mockSync(blocks, &mock.Mempool{}, testDBB)
    75  	a.mempool = &mempool{}
    76  	netWork := NewNetWork()
    77  	netWork.Register(a, "192.168.0.1", "test node A", consensus.SFFullNode)
    78  	netWork.Register(b, "192.168.0.2", "test node B", consensus.SFFullNode)
    79  	if B2A, A2B, err := netWork.HandsShake(a, b); err != nil {
    80  		t.Errorf("fail on peer hands shake %v", err)
    81  	} else {
    82  		go B2A.postMan()
    83  		go A2B.postMan()
    84  	}
    85  
    86  	go a.syncMempoolLoop()
    87  	a.syncMempool("test node B")
    88  	wantTxs := a.mempool.GetTransactions()
    89  
    90  	timeout := time.NewTimer(2 * time.Second)
    91  	defer timeout.Stop()
    92  	ticker := time.NewTicker(500 * time.Millisecond)
    93  	defer ticker.Stop()
    94  
    95  	gotTxs := []*protocol.TxDesc{}
    96  	for {
    97  		select {
    98  		case <-ticker.C:
    99  			gotTxs = b.mempool.GetTransactions()
   100  			if len(gotTxs) >= txsNumber {
   101  				goto out
   102  			}
   103  		case <-timeout.C:
   104  			t.Fatalf("mempool sync timeout")
   105  		}
   106  	}
   107  
   108  out:
   109  	if len(gotTxs) != txsNumber {
   110  		t.Fatalf("mempool sync txs num err. got:%d want:%d", len(gotTxs), txsNumber)
   111  	}
   112  
   113  	for i, gotTx := range gotTxs {
   114  		index := gotTx.Tx.Inputs[0].Amount()
   115  		if !reflect.DeepEqual(gotTx.Tx.Inputs[0].Amount(), wantTxs[index].Tx.Inputs[0].Amount()) {
   116  			t.Fatalf("mempool tx err. index:%d\n,gotTx:%s\n,wantTx:%s", i, spew.Sdump(gotTx.Tx.Inputs), spew.Sdump(wantTxs[0].Tx.Inputs))
   117  		}
   118  
   119  		if !reflect.DeepEqual(gotTx.Tx.Outputs[0].AssetAmount, wantTxs[index].Tx.Outputs[0].AssetAmount) {
   120  			t.Fatalf("mempool tx err. index:%d\n,gotTx:%s\n,wantTx:%s", i, spew.Sdump(gotTx.Tx.Outputs), spew.Sdump(wantTxs[0].Tx.Outputs))
   121  		}
   122  	}
   123  }
   124  
   125  func TestBroadcastTxsLoop(t *testing.T) {
   126  	if testcontrol.IgnoreTestTemporary {
   127  		return
   128  	}
   129  
   130  	tmpDir, err := ioutil.TempDir(".", "")
   131  	if err != nil {
   132  		t.Fatalf("failed to create temporary data folder: %v", err)
   133  	}
   134  	defer os.RemoveAll(tmpDir)
   135  	testDBA := dbm.NewDB("testdba", "leveldb", tmpDir)
   136  	testDBB := dbm.NewDB("testdbb", "leveldb", tmpDir)
   137  
   138  	blocks := mockBlocks(nil, 5)
   139  	a := mockSync(blocks, &mock.Mempool{}, testDBA)
   140  	b := mockSync(blocks, &mock.Mempool{}, testDBB)
   141  	a.mempool = &mempool{}
   142  	netWork := NewNetWork()
   143  	netWork.Register(a, "192.168.0.1", "test node A", consensus.SFFullNode)
   144  	netWork.Register(b, "192.168.0.2", "test node B", consensus.SFFullNode)
   145  	if B2A, A2B, err := netWork.HandsShake(a, b); err != nil {
   146  		t.Errorf("fail on peer hands shake %v", err)
   147  	} else {
   148  		go B2A.postMan()
   149  		go A2B.postMan()
   150  	}
   151  	a.txMsgSub, err = a.eventDispatcher.Subscribe(core.TxMsgEvent{})
   152  	if err != nil {
   153  		t.Fatal("txMsgSub subscribe err", err)
   154  	}
   155  	go a.broadcastTxsLoop()
   156  	wantTxs := a.mempool.GetTransactions()
   157  	txsNum := 50
   158  	for i, txD := range wantTxs {
   159  		if i >= txsNum {
   160  			break
   161  		}
   162  		a.eventDispatcher.Post(core.TxMsgEvent{TxMsg: &core.TxPoolMsg{TxDesc: txD, MsgType: core.MsgNewTx}})
   163  	}
   164  	timeout := time.NewTimer(2 * time.Second)
   165  	defer timeout.Stop()
   166  	ticker := time.NewTicker(500 * time.Millisecond)
   167  	defer ticker.Stop()
   168  
   169  	gotTxs := []*protocol.TxDesc{}
   170  	for {
   171  		select {
   172  		case <-ticker.C:
   173  			gotTxs = b.mempool.GetTransactions()
   174  			if len(gotTxs) >= txsNum {
   175  				goto out
   176  			}
   177  		case <-timeout.C:
   178  			t.Fatalf("mempool sync timeout")
   179  		}
   180  	}
   181  
   182  out:
   183  	if len(gotTxs) != txsNum {
   184  		t.Fatalf("mempool sync txs num err. got:%d want:%d", len(gotTxs), txsNumber)
   185  	}
   186  
   187  	for i, gotTx := range gotTxs {
   188  		index := gotTx.Tx.Inputs[0].Amount()
   189  		if !reflect.DeepEqual(gotTx.Tx.Inputs[0].Amount(), wantTxs[index].Tx.Inputs[0].Amount()) {
   190  			t.Fatalf("mempool tx err. index:%d\n,gotTx:%s\n,wantTx:%s", i, spew.Sdump(gotTx.Tx.Inputs), spew.Sdump(wantTxs[0].Tx.Inputs))
   191  		}
   192  
   193  		if !reflect.DeepEqual(gotTx.Tx.Outputs[0].AssetAmount, wantTxs[index].Tx.Outputs[0].AssetAmount) {
   194  			t.Fatalf("mempool tx err. index:%d\n,gotTx:%s\n,wantTx:%s", i, spew.Sdump(gotTx.Tx.Outputs), spew.Sdump(wantTxs[0].Tx.Outputs))
   195  		}
   196  	}
   197  }