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