github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/eth/helper_test.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:38</date>
    10  //</624342636186046464>
    11  
    12  
    13  //此文件包含一些共享测试功能,多个共享测试功能
    14  //正在测试的不同文件和模块。
    15  
    16  package eth
    17  
    18  import (
    19  	"crypto/ecdsa"
    20  	"crypto/rand"
    21  	"math/big"
    22  	"sort"
    23  	"sync"
    24  	"testing"
    25  
    26  	"github.com/ethereum/go-ethereum/common"
    27  	"github.com/ethereum/go-ethereum/consensus/ethash"
    28  	"github.com/ethereum/go-ethereum/core"
    29  	"github.com/ethereum/go-ethereum/core/types"
    30  	"github.com/ethereum/go-ethereum/core/vm"
    31  	"github.com/ethereum/go-ethereum/crypto"
    32  	"github.com/ethereum/go-ethereum/eth/downloader"
    33  	"github.com/ethereum/go-ethereum/ethdb"
    34  	"github.com/ethereum/go-ethereum/event"
    35  	"github.com/ethereum/go-ethereum/p2p"
    36  	"github.com/ethereum/go-ethereum/p2p/discover"
    37  	"github.com/ethereum/go-ethereum/params"
    38  )
    39  
    40  var (
    41  	testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    42  	testBank       = crypto.PubkeyToAddress(testBankKey.PublicKey)
    43  )
    44  
    45  //NewTestProtocolManager为测试目的创建了一个新的协议管理器,
    46  //已知已知的块数和潜在的通知
    47  //不同事件的频道。
    48  func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, *ethdb.MemDatabase, error) {
    49  	var (
    50  		evmux  = new(event.TypeMux)
    51  		engine = ethash.NewFaker()
    52  		db     = ethdb.NewMemDatabase()
    53  		gspec  = &core.Genesis{
    54  			Config: params.TestChainConfig,
    55  			Alloc:  core.GenesisAlloc{testBank: {Balance: big.NewInt(1000000)}},
    56  		}
    57  		genesis       = gspec.MustCommit(db)
    58  		blockchain, _ = core.NewBlockChain(db, nil, gspec.Config, engine, vm.Config{})
    59  	)
    60  	chain, _ := core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, blocks, generator)
    61  	if _, err := blockchain.InsertChain(chain); err != nil {
    62  		panic(err)
    63  	}
    64  
    65  	pm, err := NewProtocolManager(gspec.Config, mode, DefaultConfig.NetworkId, evmux, &testTxPool{added: newtx}, engine, blockchain, db)
    66  	if err != nil {
    67  		return nil, nil, err
    68  	}
    69  	pm.Start(1000)
    70  	return pm, db, nil
    71  }
    72  
    73  //newTestProtocolManager必须为测试目的创建新的协议管理器,
    74  //已知已知的块数和潜在的通知
    75  //不同事件的频道。如果出现错误,构造函数强制-
    76  //测试失败。
    77  func newTestProtocolManagerMust(t *testing.T, mode downloader.SyncMode, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, *ethdb.MemDatabase) {
    78  	pm, db, err := newTestProtocolManager(mode, blocks, generator, newtx)
    79  	if err != nil {
    80  		t.Fatalf("Failed to create protocol manager: %v", err)
    81  	}
    82  	return pm, db
    83  }
    84  
    85  //testxtpool是一个用于测试的假助手事务池
    86  type testTxPool struct {
    87  	txFeed event.Feed
    88  pool   []*types.Transaction        //收集所有交易
    89  added  chan<- []*types.Transaction //新事务的通知通道
    90  
    91  lock sync.RWMutex //保护事务池
    92  }
    93  
    94  //AddRemotes向池追加一批事务,并通知
    95  //如果添加通道为非零,则侦听器
    96  func (p *testTxPool) AddRemotes(txs []*types.Transaction) []error {
    97  	p.lock.Lock()
    98  	defer p.lock.Unlock()
    99  
   100  	p.pool = append(p.pool, txs...)
   101  	if p.added != nil {
   102  		p.added <- txs
   103  	}
   104  	return make([]error, len(txs))
   105  }
   106  
   107  //挂起返回池已知的所有事务
   108  func (p *testTxPool) Pending() (map[common.Address]types.Transactions, error) {
   109  	p.lock.RLock()
   110  	defer p.lock.RUnlock()
   111  
   112  	batches := make(map[common.Address]types.Transactions)
   113  	for _, tx := range p.pool {
   114  		from, _ := types.Sender(types.HomesteadSigner{}, tx)
   115  		batches[from] = append(batches[from], tx)
   116  	}
   117  	for _, batch := range batches {
   118  		sort.Sort(types.TxByNonce(batch))
   119  	}
   120  	return batches, nil
   121  }
   122  
   123  func (p *testTxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
   124  	return p.txFeed.Subscribe(ch)
   125  }
   126  
   127  //NewTestTransaction创建新的虚拟事务。
   128  func newTestTransaction(from *ecdsa.PrivateKey, nonce uint64, datasize int) *types.Transaction {
   129  	tx := types.NewTransaction(nonce, common.Address{}, big.NewInt(0), 100000, big.NewInt(0), make([]byte, datasize))
   130  	tx, _ = types.SignTx(tx, types.HomesteadSigner{}, from)
   131  	return tx
   132  }
   133  
   134  //testpeer是允许测试直接网络调用的模拟对等机。
   135  type testPeer struct {
   136  net p2p.MsgReadWriter //模拟远程消息传递的网络层读写器
   137  app *p2p.MsgPipeRW    //应用层读写器模拟本地端
   138  	*peer
   139  }
   140  
   141  //newtestpeer创建在给定的协议管理器上注册的新对等。
   142  func newTestPeer(name string, version int, pm *ProtocolManager, shake bool) (*testPeer, <-chan error) {
   143  //创建消息管道以通过
   144  	app, net := p2p.MsgPipe()
   145  
   146  //生成随机ID并创建对等机
   147  	var id discover.NodeID
   148  	rand.Read(id[:])
   149  
   150  	peer := pm.newPeer(version, p2p.NewPeer(id, name, nil), net)
   151  
   152  //在新线程上启动对等机
   153  	errc := make(chan error, 1)
   154  	go func() {
   155  		select {
   156  		case pm.newPeerCh <- peer:
   157  			errc <- pm.handle(peer)
   158  		case <-pm.quitSync:
   159  			errc <- p2p.DiscQuitting
   160  		}
   161  	}()
   162  	tp := &testPeer{app: app, net: net, peer: peer}
   163  //执行任何隐式请求的握手并返回
   164  	if shake {
   165  		var (
   166  			genesis = pm.blockchain.Genesis()
   167  			head    = pm.blockchain.CurrentHeader()
   168  			td      = pm.blockchain.GetTd(head.Hash(), head.Number.Uint64())
   169  		)
   170  		tp.handshake(nil, td, head.Hash(), genesis.Hash())
   171  	}
   172  	return tp, errc
   173  }
   174  
   175  //握手模拟一个简单的握手,它期望
   176  //我们在本地模拟的远程端。
   177  func (p *testPeer) handshake(t *testing.T, td *big.Int, head common.Hash, genesis common.Hash) {
   178  	msg := &statusData{
   179  		ProtocolVersion: uint32(p.version),
   180  		NetworkId:       DefaultConfig.NetworkId,
   181  		TD:              td,
   182  		CurrentBlock:    head,
   183  		GenesisBlock:    genesis,
   184  	}
   185  	if err := p2p.ExpectMsg(p.app, StatusMsg, msg); err != nil {
   186  		t.Fatalf("status recv: %v", err)
   187  	}
   188  	if err := p2p.Send(p.app, StatusMsg, msg); err != nil {
   189  		t.Fatalf("status send: %v", err)
   190  	}
   191  }
   192  
   193  //CLOSE终止对等端的本地端,通知远程协议
   194  //终止经理。
   195  func (p *testPeer) close() {
   196  	p.app.Close()
   197  }
   198