github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/eth/helper_test.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2015 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  //此文件包含一些共享测试功能,多个共享测试功能
    26  //正在测试的不同文件和模块。
    27  
    28  package eth
    29  
    30  import (
    31  	"crypto/ecdsa"
    32  	"crypto/rand"
    33  	"math/big"
    34  	"sort"
    35  	"sync"
    36  	"testing"
    37  
    38  	"github.com/ethereum/go-ethereum/common"
    39  	"github.com/ethereum/go-ethereum/consensus/ethash"
    40  	"github.com/ethereum/go-ethereum/core"
    41  	"github.com/ethereum/go-ethereum/core/types"
    42  	"github.com/ethereum/go-ethereum/core/vm"
    43  	"github.com/ethereum/go-ethereum/crypto"
    44  	"github.com/ethereum/go-ethereum/eth/downloader"
    45  	"github.com/ethereum/go-ethereum/ethdb"
    46  	"github.com/ethereum/go-ethereum/event"
    47  	"github.com/ethereum/go-ethereum/p2p"
    48  	"github.com/ethereum/go-ethereum/p2p/discover"
    49  	"github.com/ethereum/go-ethereum/params"
    50  )
    51  
    52  var (
    53  	testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    54  	testBank       = crypto.PubkeyToAddress(testBankKey.PublicKey)
    55  )
    56  
    57  //NewTestProtocolManager为测试目的创建了一个新的协议管理器,
    58  //已知已知的块数和潜在的通知
    59  //不同事件的频道。
    60  func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, *ethdb.MemDatabase, error) {
    61  	var (
    62  		evmux  = new(event.TypeMux)
    63  		engine = ethash.NewFaker()
    64  		db     = ethdb.NewMemDatabase()
    65  		gspec  = &core.Genesis{
    66  			Config: params.TestChainConfig,
    67  			Alloc:  core.GenesisAlloc{testBank: {Balance: big.NewInt(1000000)}},
    68  		}
    69  		genesis       = gspec.MustCommit(db)
    70  		blockchain, _ = core.NewBlockChain(db, nil, gspec.Config, engine, vm.Config{})
    71  	)
    72  	chain, _ := core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, blocks, generator)
    73  	if _, err := blockchain.InsertChain(chain); err != nil {
    74  		panic(err)
    75  	}
    76  
    77  	pm, err := NewProtocolManager(gspec.Config, mode, DefaultConfig.NetworkId, evmux, &testTxPool{added: newtx}, engine, blockchain, db)
    78  	if err != nil {
    79  		return nil, nil, err
    80  	}
    81  	pm.Start(1000)
    82  	return pm, db, nil
    83  }
    84  
    85  //newTestProtocolManager必须为测试目的创建新的协议管理器,
    86  //已知已知的块数和潜在的通知
    87  //不同事件的频道。如果出现错误,构造函数强制-
    88  //测试失败。
    89  func newTestProtocolManagerMust(t *testing.T, mode downloader.SyncMode, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, *ethdb.MemDatabase) {
    90  	pm, db, err := newTestProtocolManager(mode, blocks, generator, newtx)
    91  	if err != nil {
    92  		t.Fatalf("Failed to create protocol manager: %v", err)
    93  	}
    94  	return pm, db
    95  }
    96  
    97  //testxtpool是一个用于测试的假助手事务池
    98  type testTxPool struct {
    99  	txFeed event.Feed
   100  pool   []*types.Transaction        //收集所有交易
   101  added  chan<- []*types.Transaction //新事务的通知通道
   102  
   103  lock sync.RWMutex //保护事务池
   104  }
   105  
   106  //AddRemotes向池追加一批事务,并通知
   107  //如果添加通道为非零,则侦听器
   108  func (p *testTxPool) AddRemotes(txs []*types.Transaction) []error {
   109  	p.lock.Lock()
   110  	defer p.lock.Unlock()
   111  
   112  	p.pool = append(p.pool, txs...)
   113  	if p.added != nil {
   114  		p.added <- txs
   115  	}
   116  	return make([]error, len(txs))
   117  }
   118  
   119  //挂起返回池已知的所有事务
   120  func (p *testTxPool) Pending() (map[common.Address]types.Transactions, error) {
   121  	p.lock.RLock()
   122  	defer p.lock.RUnlock()
   123  
   124  	batches := make(map[common.Address]types.Transactions)
   125  	for _, tx := range p.pool {
   126  		from, _ := types.Sender(types.HomesteadSigner{}, tx)
   127  		batches[from] = append(batches[from], tx)
   128  	}
   129  	for _, batch := range batches {
   130  		sort.Sort(types.TxByNonce(batch))
   131  	}
   132  	return batches, nil
   133  }
   134  
   135  func (p *testTxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
   136  	return p.txFeed.Subscribe(ch)
   137  }
   138  
   139  //NewTestTransaction创建新的虚拟事务。
   140  func newTestTransaction(from *ecdsa.PrivateKey, nonce uint64, datasize int) *types.Transaction {
   141  	tx := types.NewTransaction(nonce, common.Address{}, big.NewInt(0), 100000, big.NewInt(0), make([]byte, datasize))
   142  	tx, _ = types.SignTx(tx, types.HomesteadSigner{}, from)
   143  	return tx
   144  }
   145  
   146  //testpeer是允许测试直接网络调用的模拟对等机。
   147  type testPeer struct {
   148  net p2p.MsgReadWriter //模拟远程消息传递的网络层读写器
   149  app *p2p.MsgPipeRW    //应用层读写器模拟本地端
   150  	*peer
   151  }
   152  
   153  //newtestpeer创建在给定的协议管理器上注册的新对等。
   154  func newTestPeer(name string, version int, pm *ProtocolManager, shake bool) (*testPeer, <-chan error) {
   155  //创建消息管道以通过
   156  	app, net := p2p.MsgPipe()
   157  
   158  //生成随机ID并创建对等机
   159  	var id discover.NodeID
   160  	rand.Read(id[:])
   161  
   162  	peer := pm.newPeer(version, p2p.NewPeer(id, name, nil), net)
   163  
   164  //在新线程上启动对等机
   165  	errc := make(chan error, 1)
   166  	go func() {
   167  		select {
   168  		case pm.newPeerCh <- peer:
   169  			errc <- pm.handle(peer)
   170  		case <-pm.quitSync:
   171  			errc <- p2p.DiscQuitting
   172  		}
   173  	}()
   174  	tp := &testPeer{app: app, net: net, peer: peer}
   175  //执行任何隐式请求的握手并返回
   176  	if shake {
   177  		var (
   178  			genesis = pm.blockchain.Genesis()
   179  			head    = pm.blockchain.CurrentHeader()
   180  			td      = pm.blockchain.GetTd(head.Hash(), head.Number.Uint64())
   181  		)
   182  		tp.handshake(nil, td, head.Hash(), genesis.Hash())
   183  	}
   184  	return tp, errc
   185  }
   186  
   187  //握手模拟一个简单的握手,它期望
   188  //我们在本地模拟的远程端。
   189  func (p *testPeer) handshake(t *testing.T, td *big.Int, head common.Hash, genesis common.Hash) {
   190  	msg := &statusData{
   191  		ProtocolVersion: uint32(p.version),
   192  		NetworkId:       DefaultConfig.NetworkId,
   193  		TD:              td,
   194  		CurrentBlock:    head,
   195  		GenesisBlock:    genesis,
   196  	}
   197  	if err := p2p.ExpectMsg(p.app, StatusMsg, msg); err != nil {
   198  		t.Fatalf("status recv: %v", err)
   199  	}
   200  	if err := p2p.Send(p.app, StatusMsg, msg); err != nil {
   201  		t.Fatalf("status send: %v", err)
   202  	}
   203  }
   204  
   205  //CLOSE终止对等端的本地端,通知远程协议
   206  //终止经理。
   207  func (p *testPeer) close() {
   208  	p.app.Close()
   209  }