github.com/codingfuture/orig-energi3@v0.8.4/consensus/ethash/ethash_test.go (about) 1 // Copyright 2018 The Energi Core Authors 2 // Copyright 2017 The go-ethereum Authors 3 // This file is part of the Energi Core library. 4 // 5 // The Energi Core library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The Energi Core library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the Energi Core library. If not, see <http://www.gnu.org/licenses/>. 17 18 package ethash 19 20 import ( 21 "io/ioutil" 22 "math/big" 23 "math/rand" 24 "os" 25 "sync" 26 "testing" 27 "time" 28 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/common/hexutil" 31 "github.com/ethereum/go-ethereum/consensus" 32 "github.com/ethereum/go-ethereum/core/types" 33 ) 34 35 // Tests that ethash works correctly in test mode. 36 func TestTestMode(t *testing.T) { 37 header := &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(100)} 38 39 ethash := NewTester(nil, false) 40 defer ethash.Close() 41 42 results := make(chan *consensus.SealResult) 43 err := ethash.Seal(nil, types.NewBlockWithHeader(header), results, nil) 44 if err != nil { 45 t.Fatalf("failed to seal block: %v", err) 46 } 47 select { 48 case data := <-results: 49 block := data.Block 50 header.Nonce = types.EncodeNonce(block.Nonce()) 51 header.MixDigest = block.MixDigest() 52 if err := ethash.VerifySeal(nil, header); err != nil { 53 t.Fatalf("unexpected verification error: %v", err) 54 } 55 case <-time.NewTimer(time.Second).C: 56 t.Error("sealing result timeout") 57 } 58 } 59 60 // This test checks that cache lru logic doesn't crash under load. 61 // It reproduces https://github.com/ethereum/go-ethereum/issues/14943 62 func TestCacheFileEvict(t *testing.T) { 63 tmpdir, err := ioutil.TempDir("", "ethash-test") 64 if err != nil { 65 t.Fatal(err) 66 } 67 defer os.RemoveAll(tmpdir) 68 e := New(Config{CachesInMem: 3, CachesOnDisk: 10, CacheDir: tmpdir, PowMode: ModeTest}, nil, false) 69 defer e.Close() 70 71 workers := 8 72 epochs := 100 73 var wg sync.WaitGroup 74 wg.Add(workers) 75 for i := 0; i < workers; i++ { 76 go verifyTest(&wg, e, i, epochs) 77 } 78 wg.Wait() 79 } 80 81 func verifyTest(wg *sync.WaitGroup, e *Ethash, workerIndex, epochs int) { 82 defer wg.Done() 83 84 const wiggle = 4 * epochLength 85 r := rand.New(rand.NewSource(int64(workerIndex))) 86 for epoch := 0; epoch < epochs; epoch++ { 87 block := int64(epoch)*epochLength - wiggle/2 + r.Int63n(wiggle) 88 if block < 0 { 89 block = 0 90 } 91 header := &types.Header{Number: big.NewInt(block), Difficulty: big.NewInt(100)} 92 e.VerifySeal(nil, header) 93 } 94 } 95 96 func TestRemoteSealer(t *testing.T) { 97 ethash := NewTester(nil, false) 98 defer ethash.Close() 99 100 api := &API{ethash} 101 if _, err := api.GetWork(); err != errNoMiningWork { 102 t.Error("expect to return an error indicate there is no mining work") 103 } 104 header := &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(100)} 105 block := types.NewBlockWithHeader(header) 106 sealhash := ethash.SealHash(header) 107 108 // Push new work. 109 results := make(chan *consensus.SealResult) 110 ethash.Seal(nil, block, results, nil) 111 112 var ( 113 work [4]string 114 err error 115 ) 116 if work, err = api.GetWork(); err != nil || work[0] != sealhash.Hex() { 117 t.Error("expect to return a mining work has same hash") 118 } 119 120 if res := api.SubmitWork(types.BlockNonce{}, sealhash, common.Hash{}); res { 121 t.Error("expect to return false when submit a fake solution") 122 } 123 // Push new block with same block number to replace the original one. 124 header = &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(1000)} 125 block = types.NewBlockWithHeader(header) 126 sealhash = ethash.SealHash(header) 127 ethash.Seal(nil, block, results, nil) 128 129 if work, err = api.GetWork(); err != nil || work[0] != sealhash.Hex() { 130 t.Error("expect to return the latest pushed work") 131 } 132 } 133 134 func TestHashRate(t *testing.T) { 135 var ( 136 hashrate = []hexutil.Uint64{100, 200, 300} 137 expect uint64 138 ids = []common.Hash{common.HexToHash("a"), common.HexToHash("b"), common.HexToHash("c")} 139 ) 140 ethash := NewTester(nil, false) 141 defer ethash.Close() 142 143 if tot := ethash.Hashrate(); tot != 0 { 144 t.Error("expect the result should be zero") 145 } 146 147 api := &API{ethash} 148 for i := 0; i < len(hashrate); i += 1 { 149 if res := api.SubmitHashRate(hashrate[i], ids[i]); !res { 150 t.Error("remote miner submit hashrate failed") 151 } 152 expect += uint64(hashrate[i]) 153 } 154 if tot := ethash.Hashrate(); tot != float64(expect) { 155 t.Error("expect total hashrate should be same") 156 } 157 } 158 159 func TestClosedRemoteSealer(t *testing.T) { 160 ethash := NewTester(nil, false) 161 time.Sleep(1 * time.Second) // ensure exit channel is listening 162 ethash.Close() 163 164 api := &API{ethash} 165 if _, err := api.GetWork(); err != errEthashStopped { 166 t.Error("expect to return an error to indicate ethash is stopped") 167 } 168 169 if res := api.SubmitHashRate(hexutil.Uint64(100), common.HexToHash("a")); res { 170 t.Error("expect to return false when submit hashrate to a stopped ethash") 171 } 172 }