github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/les/odr_test.go (about) 1 package les 2 3 import ( 4 "bytes" 5 "context" 6 "math/big" 7 "testing" 8 "time" 9 10 "github.com/quickchainproject/quickchain/common" 11 "github.com/quickchainproject/quickchain/common/math" 12 "github.com/quickchainproject/quickchain/core" 13 "github.com/quickchainproject/quickchain/core/state" 14 "github.com/quickchainproject/quickchain/core/types" 15 "github.com/quickchainproject/quickchain/core/vm" 16 "github.com/quickchainproject/quickchain/qct" 17 "github.com/quickchainproject/quickchain/qctdb" 18 "github.com/quickchainproject/quickchain/light" 19 "github.com/quickchainproject/quickchain/params" 20 "github.com/quickchainproject/quickchain/rlp" 21 ) 22 23 type odrTestFn func(ctx context.Context, db qctdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte 24 25 func TestOdrGetBlockLes1(t *testing.T) { testOdr(t, 1, 1, odrGetBlock) } 26 27 func TestOdrGetBlockLes2(t *testing.T) { testOdr(t, 2, 1, odrGetBlock) } 28 29 func odrGetBlock(ctx context.Context, db qctdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte { 30 var block *types.Block 31 if bc != nil { 32 block = bc.GetBlockByHash(bhash) 33 } else { 34 block, _ = lc.GetBlockByHash(ctx, bhash) 35 } 36 if block == nil { 37 return nil 38 } 39 rlp, _ := rlp.EncodeToBytes(block) 40 return rlp 41 } 42 43 func TestOdrGetReceiptsLes1(t *testing.T) { testOdr(t, 1, 1, odrGetReceipts) } 44 45 func TestOdrGetReceiptsLes2(t *testing.T) { testOdr(t, 2, 1, odrGetReceipts) } 46 47 func odrGetReceipts(ctx context.Context, db qctdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte { 48 var receipts types.Receipts 49 if bc != nil { 50 receipts = core.GetBlockReceipts(db, bhash, core.GetBlockNumber(db, bhash)) 51 } else { 52 receipts, _ = light.GetBlockReceipts(ctx, lc.Odr(), bhash, core.GetBlockNumber(db, bhash)) 53 } 54 if receipts == nil { 55 return nil 56 } 57 rlp, _ := rlp.EncodeToBytes(receipts) 58 return rlp 59 } 60 61 func TestOdrAccountsLes1(t *testing.T) { testOdr(t, 1, 1, odrAccounts) } 62 63 func TestOdrAccountsLes2(t *testing.T) { testOdr(t, 2, 1, odrAccounts) } 64 65 func odrAccounts(ctx context.Context, db qctdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte { 66 dummyAddr := common.HexToAddress("1234567812345678123456781234567812345678") 67 acc := []common.Address{testBankAddress, acc1Addr, acc2Addr, dummyAddr} 68 69 var ( 70 res []byte 71 st *state.StateDB 72 err error 73 ) 74 for _, addr := range acc { 75 if bc != nil { 76 header := bc.GetHeaderByHash(bhash) 77 st, err = state.New(header.Root, state.NewDatabase(db)) 78 } else { 79 header := lc.GetHeaderByHash(bhash) 80 st = light.NewState(ctx, header, lc.Odr()) 81 } 82 if err == nil { 83 bal := st.GetBalance(addr) 84 rlp, _ := rlp.EncodeToBytes(bal) 85 res = append(res, rlp...) 86 } 87 } 88 return res 89 } 90 91 func TestOdrContractCallLes1(t *testing.T) { testOdr(t, 1, 2, odrContractCall) } 92 93 func TestOdrContractCallLes2(t *testing.T) { testOdr(t, 2, 2, odrContractCall) } 94 95 type callmsg struct { 96 types.Message 97 } 98 99 func (callmsg) CheckNonce() bool { return false } 100 101 func odrContractCall(ctx context.Context, db qctdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte { 102 data := common.Hex2Bytes("60CD26850000000000000000000000000000000000000000000000000000000000000000") 103 104 var res []byte 105 for i := 0; i < 3; i++ { 106 data[35] = byte(i) 107 if bc != nil { 108 header := bc.GetHeaderByHash(bhash) 109 statedb, err := state.New(header.Root, state.NewDatabase(db)) 110 111 if err == nil { 112 from := statedb.GetOrNewStateObject(testBankAddress) 113 from.SetBalance(math.MaxBig256) 114 115 msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false)} 116 117 context := core.NewEVMContext(msg, header, bc, nil) 118 vmenv := vm.NewEVM(context, statedb, config, vm.Config{}) 119 120 //vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{}) 121 gp := new(core.GasPool).AddGas(math.MaxUint64) 122 ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp) 123 res = append(res, ret...) 124 } 125 } else { 126 header := lc.GetHeaderByHash(bhash) 127 state := light.NewState(ctx, header, lc.Odr()) 128 state.SetBalance(testBankAddress, math.MaxBig256) 129 msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false)} 130 context := core.NewEVMContext(msg, header, lc, nil) 131 vmenv := vm.NewEVM(context, state, config, vm.Config{}) 132 gp := new(core.GasPool).AddGas(math.MaxUint64) 133 ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp) 134 if state.Error() == nil { 135 res = append(res, ret...) 136 } 137 } 138 } 139 return res 140 } 141 142 func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) { 143 // Assemble the test environment 144 peers := newPeerSet() 145 dist := newRequestDistributor(peers, make(chan struct{})) 146 rm := newRetrieveManager(peers, dist, nil) 147 db, _ := qctdb.NewMemDatabase() 148 ldb, _ := qctdb.NewMemDatabase() 149 odr := NewLesOdr(ldb, light.NewChtIndexer(db, true), light.NewBloomTrieIndexer(db, true), let.NewBloomIndexer(db, light.BloomTrieFrequency), rm) 150 pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db) 151 lpm := newTestProtocolManagerMust(t, true, 0, nil, peers, odr, ldb) 152 _, err1, lpeer, err2 := newTestPeerPair("peer", protocol, pm, lpm) 153 select { 154 case <-time.After(time.Millisecond * 100): 155 case err := <-err1: 156 t.Fatalf("peer 1 handshake error: %v", err) 157 case err := <-err2: 158 t.Fatalf("peer 1 handshake error: %v", err) 159 } 160 161 lpm.synchronise(lpeer) 162 163 test := func(expFail uint64) { 164 for i := uint64(0); i <= pm.blockchain.CurrentHeader().Number.Uint64(); i++ { 165 bhash := core.GetCanonicalHash(db, i) 166 b1 := fn(light.NoOdr, db, pm.chainConfig, pm.blockchain.(*core.BlockChain), nil, bhash) 167 168 ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) 169 defer cancel() 170 b2 := fn(ctx, ldb, lpm.chainConfig, nil, lpm.blockchain.(*light.LightChain), bhash) 171 172 eq := bytes.Equal(b1, b2) 173 exp := i < expFail 174 if exp && !eq { 175 t.Errorf("odr mismatch") 176 } 177 if !exp && eq { 178 t.Errorf("unexpected odr match") 179 } 180 } 181 } 182 183 // temporarily remove peer to test odr fails 184 // expect retrievals to fail (except genesis block) without a les peer 185 peers.Unregister(lpeer.id) 186 time.Sleep(time.Millisecond * 10) // ensure that all peerSetNotify callbacks are executed 187 test(expFail) 188 // expect all retrievals to pass 189 peers.Register(lpeer) 190 time.Sleep(time.Millisecond * 10) // ensure that all peerSetNotify callbacks are executed 191 lpeer.lock.Lock() 192 lpeer.hasBlock = func(common.Hash, uint64) bool { return true } 193 lpeer.lock.Unlock() 194 test(5) 195 // still expect all retrievals to pass, now data should be cached locally 196 peers.Unregister(lpeer.id) 197 time.Sleep(time.Millisecond * 10) // ensure that all peerSetNotify callbacks are executed 198 test(5) 199 }