github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/les/helper_test.go (about) 1 // This file contains some shares testing functionality, common to multiple 2 // different files and modules being tested. 3 4 package les 5 6 import ( 7 "crypto/rand" 8 "math/big" 9 "sync" 10 "testing" 11 12 "github.com/quickchainproject/quickchain/common" 13 "github.com/quickchainproject/quickchain/consensus/qcthash" 14 "github.com/quickchainproject/quickchain/core" 15 "github.com/quickchainproject/quickchain/core/types" 16 "github.com/quickchainproject/quickchain/core/vm" 17 "github.com/quickchainproject/quickchain/crypto" 18 "github.com/quickchainproject/quickchain/event" 19 "github.com/quickchainproject/quickchain/les/flowcontrol" 20 "github.com/quickchainproject/quickchain/qct" 21 "github.com/quickchainproject/quickchain/qctdb" 22 "github.com/quickchainproject/quickchain/light" 23 "github.com/quickchainproject/quickchain/p2p" 24 "github.com/quickchainproject/quickchain/p2p/discover" 25 "github.com/quickchainproject/quickchain/params" 26 ) 27 28 var ( 29 testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 30 testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) 31 testBankFunds = big.NewInt(1000000000000000000) 32 33 acc1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 34 acc2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 35 acc1Addr = crypto.PubkeyToAddress(acc1Key.PublicKey) 36 acc2Addr = crypto.PubkeyToAddress(acc2Key.PublicKey) 37 38 testContractCode = common.Hex2Bytes("606060405260cc8060106000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806360cd2685146041578063c16431b914606b57603f565b005b6055600480803590602001909190505060a9565b6040518082815260200191505060405180910390f35b60886004808035906020019091908035906020019091905050608a565b005b80600060005083606481101560025790900160005b50819055505b5050565b6000600060005082606481101560025790900160005b5054905060c7565b91905056") 39 testContractAddr common.Address 40 testContractCodeDeployed = testContractCode[16:] 41 testContractDeployed = uint64(2) 42 43 testEventEmitterCode = common.Hex2Bytes("60606040523415600e57600080fd5b7f57050ab73f6b9ebdd9f76b8d4997793f48cf956e965ee070551b9ca0bb71584e60405160405180910390a160358060476000396000f3006060604052600080fd00a165627a7a723058203f727efcad8b5811f8cb1fc2620ce5e8c63570d697aef968172de296ea3994140029") 44 testEventEmitterAddr common.Address 45 46 testBufLimit = uint64(100) 47 ) 48 49 /* 50 contract test { 51 52 uint256[100] data; 53 54 function Put(uint256 addr, uint256 value) { 55 data[addr] = value; 56 } 57 58 function Get(uint256 addr) constant returns (uint256 value) { 59 return data[addr]; 60 } 61 } 62 */ 63 64 func testChainGen(i int, block *core.BlockGen) { 65 signer := types.HomesteadSigner{} 66 67 switch i { 68 case 0: 69 // In block 1, the test bank sends account #1 some ether. 70 tx, _ := types.SignTx(types.NewTransaction(types.Binary, block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey) 71 block.AddTx(tx) 72 case 1: 73 // In block 2, the test bank sends some more ether to account #1. 74 // acc1Addr passes it on to account #2. 75 // acc1Addr creates a test contract. 76 // acc1Addr creates a test event. 77 nonce := block.TxNonce(acc1Addr) 78 79 tx1, _ := types.SignTx(types.NewTransaction(types.Binary, block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey) 80 tx2, _ := types.SignTx(types.NewTransaction(types.Binary, nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key) 81 tx3, _ := types.SignTx(types.NewContractCreation(nonce+1, big.NewInt(0), 200000, big.NewInt(0), testContractCode), signer, acc1Key) 82 testContractAddr = crypto.CreateAddress(acc1Addr, nonce+1) 83 tx4, _ := types.SignTx(types.NewContractCreation(nonce+2, big.NewInt(0), 200000, big.NewInt(0), testEventEmitterCode), signer, acc1Key) 84 testEventEmitterAddr = crypto.CreateAddress(acc1Addr, nonce+2) 85 block.AddTx(tx1) 86 block.AddTx(tx2) 87 block.AddTx(tx3) 88 block.AddTx(tx4) 89 case 2: 90 // Block 3 is empty but was mined by account #2. 91 block.SetCoinbase(acc2Addr) 92 block.SetExtra([]byte("yeehaw")) 93 data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001") 94 tx, _ := types.SignTx(types.NewTransaction(types.Binary, block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data), signer, testBankKey) 95 block.AddTx(tx) 96 case 3: 97 // Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data). 98 b2 := block.PrevBlock(1).Header() 99 b2.Extra = []byte("foo") 100 block.AddUncle(b2) 101 b3 := block.PrevBlock(2).Header() 102 b3.Extra = []byte("foo") 103 block.AddUncle(b3) 104 data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002") 105 tx, _ := types.SignTx(types.NewTransaction(types.Binary, block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data), signer, testBankKey) 106 block.AddTx(tx) 107 } 108 } 109 110 func testRCL() RequestCostList { 111 cl := make(RequestCostList, len(reqList)) 112 for i, code := range reqList { 113 cl[i].MsgCode = code 114 cl[i].BaseCost = 0 115 cl[i].ReqCost = 0 116 } 117 return cl 118 } 119 120 // newTestProtocolManager creates a new protocol manager for testing purposes, 121 // with the given number of blocks already known, and potential notification 122 // channels for different events. 123 func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *core.BlockGen), peers *peerSet, odr *LesOdr, db qctdb.Database) (*ProtocolManager, error) { 124 var ( 125 evmux = new(event.TypeMux) 126 engine = qcthash.NewFaker() 127 gspec = core.Genesis{ 128 Config: params.TestChainConfig, 129 Alloc: core.GenesisAlloc{testBankAddress: {Balance: testBankFunds}}, 130 } 131 genesis = gspec.MustCommit(db) 132 chain BlockChain 133 ) 134 if peers == nil { 135 peers = newPeerSet() 136 } 137 138 if lightSync { 139 chain, _ = light.NewLightChain(odr, gspec.Config, engine) 140 } else { 141 blockchain, _ := core.NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}) 142 143 chtIndexer := light.NewChtIndexer(db, false) 144 chtIndexer.Start(blockchain) 145 146 bbtIndexer := light.NewBloomTrieIndexer(db, false) 147 148 bloomIndexer := let.NewBloomIndexer(db, params.BloomBitsBlocks) 149 bloomIndexer.AddChildIndexer(bbtIndexer) 150 bloomIndexer.Start(blockchain) 151 152 gchain, _ := core.GenerateChain(gspec.Config, genesis, qcthash.NewFaker(), db, blocks, generator) 153 if _, err := blockchain.InsertChain(gchain); err != nil { 154 panic(err) 155 } 156 chain = blockchain 157 } 158 159 var protocolVersions []uint 160 if lightSync { 161 protocolVersions = ClientProtocolVersions 162 } else { 163 protocolVersions = ServerProtocolVersions 164 } 165 pm, err := NewProtocolManager(gspec.Config, lightSync, protocolVersions, NetworkId, evmux, engine, peers, chain, nil, db, odr, nil, make(chan struct{}), new(sync.WaitGroup)) 166 if err != nil { 167 return nil, err 168 } 169 if !lightSync { 170 srv := &LesServer{protocolManager: pm} 171 pm.server = srv 172 173 srv.defParams = &flowcontrol.ServerParams{ 174 BufLimit: testBufLimit, 175 MinRecharge: 1, 176 } 177 178 srv.fcManager = flowcontrol.NewClientManager(50, 10, 1000000000) 179 srv.fcCostStats = newCostStats(nil) 180 } 181 pm.Start(1000) 182 return pm, nil 183 } 184 185 // newTestProtocolManagerMust creates a new protocol manager for testing purposes, 186 // with the given number of blocks already known, and potential notification 187 // channels for different events. In case of an error, the constructor force- 188 // fails the test. 189 func newTestProtocolManagerMust(t *testing.T, lightSync bool, blocks int, generator func(int, *core.BlockGen), peers *peerSet, odr *LesOdr, db qctdb.Database) *ProtocolManager { 190 pm, err := newTestProtocolManager(lightSync, blocks, generator, peers, odr, db) 191 if err != nil { 192 t.Fatalf("Failed to create protocol manager: %v", err) 193 } 194 return pm 195 } 196 197 // testPeer is a simulated peer to allow testing direct network calls. 198 type testPeer struct { 199 net p2p.MsgReadWriter // Network layer reader/writer to simulate remote messaging 200 app *p2p.MsgPipeRW // Application layer reader/writer to simulate the local side 201 *peer 202 } 203 204 // newTestPeer creates a new peer registered at the given protocol manager. 205 func newTestPeer(t *testing.T, name string, version int, pm *ProtocolManager, shake bool) (*testPeer, <-chan error) { 206 // Create a message pipe to communicate through 207 app, net := p2p.MsgPipe() 208 209 // Generate a random id and create the peer 210 var id discover.NodeID 211 rand.Read(id[:]) 212 213 peer := pm.newPeer(version, NetworkId, p2p.NewPeer(id, name, nil), net) 214 215 // Start the peer on a new thread 216 errc := make(chan error, 1) 217 go func() { 218 select { 219 case pm.newPeerCh <- peer: 220 errc <- pm.handle(peer) 221 case <-pm.quitSync: 222 errc <- p2p.DiscQuitting 223 } 224 }() 225 tp := &testPeer{ 226 app: app, 227 net: net, 228 peer: peer, 229 } 230 // Execute any implicitly requested handshakes and return 231 if shake { 232 var ( 233 genesis = pm.blockchain.Genesis() 234 head = pm.blockchain.CurrentHeader() 235 td = pm.blockchain.GetTd(head.Hash(), head.Number.Uint64()) 236 ) 237 tp.handshake(t, td, head.Hash(), head.Number.Uint64(), genesis.Hash()) 238 } 239 return tp, errc 240 } 241 242 func newTestPeerPair(name string, version int, pm, pm2 *ProtocolManager) (*peer, <-chan error, *peer, <-chan error) { 243 // Create a message pipe to communicate through 244 app, net := p2p.MsgPipe() 245 246 // Generate a random id and create the peer 247 var id discover.NodeID 248 rand.Read(id[:]) 249 250 peer := pm.newPeer(version, NetworkId, p2p.NewPeer(id, name, nil), net) 251 peer2 := pm2.newPeer(version, NetworkId, p2p.NewPeer(id, name, nil), app) 252 253 // Start the peer on a new thread 254 errc := make(chan error, 1) 255 errc2 := make(chan error, 1) 256 go func() { 257 select { 258 case pm.newPeerCh <- peer: 259 errc <- pm.handle(peer) 260 case <-pm.quitSync: 261 errc <- p2p.DiscQuitting 262 } 263 }() 264 go func() { 265 select { 266 case pm2.newPeerCh <- peer2: 267 errc2 <- pm2.handle(peer2) 268 case <-pm2.quitSync: 269 errc2 <- p2p.DiscQuitting 270 } 271 }() 272 return peer, errc, peer2, errc2 273 } 274 275 // handshake simulates a trivial handshake that expects the same state from the 276 // remote side as we are simulating locally. 277 func (p *testPeer) handshake(t *testing.T, td *big.Int, head common.Hash, headNum uint64, genesis common.Hash) { 278 var expList keyValueList 279 expList = expList.add("protocolVersion", uint64(p.version)) 280 expList = expList.add("networkId", uint64(NetworkId)) 281 expList = expList.add("headTd", td) 282 expList = expList.add("headHash", head) 283 expList = expList.add("headNum", headNum) 284 expList = expList.add("genesisHash", genesis) 285 sendList := make(keyValueList, len(expList)) 286 copy(sendList, expList) 287 expList = expList.add("serveHeaders", nil) 288 expList = expList.add("serveChainSince", uint64(0)) 289 expList = expList.add("serveStateSince", uint64(0)) 290 expList = expList.add("txRelay", nil) 291 expList = expList.add("flowControl/BL", testBufLimit) 292 expList = expList.add("flowControl/MRR", uint64(1)) 293 expList = expList.add("flowControl/MRC", testRCL()) 294 295 if err := p2p.ExpectMsg(p.app, StatusMsg, expList); err != nil { 296 t.Fatalf("status recv: %v", err) 297 } 298 if err := p2p.Send(p.app, StatusMsg, sendList); err != nil { 299 t.Fatalf("status send: %v", err) 300 } 301 302 p.fcServerParams = &flowcontrol.ServerParams{ 303 BufLimit: testBufLimit, 304 MinRecharge: 1, 305 } 306 } 307 308 // close terminates the local side of the peer, notifying the remote protocol 309 // manager of termination. 310 func (p *testPeer) close() { 311 p.app.Close() 312 }