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