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 }