github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/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 "context" 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/core/types" 32 ) 33 34 // Tests that ethash works correctly in test mode. 35 func TestTestMode(t *testing.T) { 36 header := &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(100)} 37 38 ethash := NewTester(nil, false) 39 defer ethash.Close() 40 41 results := make(chan *types.Block) 42 err := ethash.Seal(context.Background(), nil, types.NewBlockWithHeader(header), results, nil) 43 if err != nil { 44 t.Fatalf("failed to seal block: %v", err) 45 } 46 select { 47 case block := <-results: 48 header.Nonce = types.EncodeNonce(block.Nonce()) 49 header.MixDigest = block.MixDigest() 50 if err := ethash.verifySeal(nil, header, false); err != nil { 51 t.Fatalf("unexpected verification error: %v", err) 52 } 53 case <-time.NewTimer(4 * time.Second).C: 54 t.Error("sealing result timeout") 55 } 56 } 57 58 // This test checks that cache lru logic doesn't crash under load. 59 // It reproduces https://github.com/ethereum/go-ethereum/issues/14943 60 func TestCacheFileEvict(t *testing.T) { 61 tmpdir, err := ioutil.TempDir("", "ethash-test") 62 if err != nil { 63 t.Fatal(err) 64 } 65 defer os.RemoveAll(tmpdir) 66 67 config := Config{ 68 CachesInMem: 3, 69 CachesOnDisk: 10, 70 CacheDir: tmpdir, 71 PowMode: ModeTest, 72 } 73 e := New(config, nil, false) 74 defer e.Close() 75 76 workers := 8 77 epochs := 100 78 var wg sync.WaitGroup 79 wg.Add(workers) 80 for i := 0; i < workers; i++ { 81 go verifyTest(&wg, e, i, epochs) 82 } 83 wg.Wait() 84 } 85 86 func verifyTest(wg *sync.WaitGroup, e *Ethash, workerIndex, epochs int) { 87 defer wg.Done() 88 89 const wiggle = 4 * epochLength 90 r := rand.New(rand.NewSource(int64(workerIndex))) 91 for epoch := 0; epoch < epochs; epoch++ { 92 block := int64(epoch)*epochLength - wiggle/2 + r.Int63n(wiggle) 93 if block < 0 { 94 block = 0 95 } 96 header := &types.Header{Number: big.NewInt(block), Difficulty: big.NewInt(100)} 97 e.verifySeal(nil, header, false) 98 } 99 } 100 101 func TestRemoteSealer(t *testing.T) { 102 ethash := NewTester(nil, false) 103 defer ethash.Close() 104 105 api := &API{ethash} 106 if _, err := api.GetWork(); err != errNoMiningWork { 107 t.Error("expect to return an error indicate there is no mining work") 108 } 109 header := &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(100)} 110 block := types.NewBlockWithHeader(header) 111 sealhash := ethash.SealHash(header) 112 113 // Push new work. 114 results := make(chan *types.Block) 115 err := ethash.Seal(context.Background(), nil, block, results, nil) 116 117 if err != nil { 118 t.Error("error in sealing block") 119 } 120 121 var work [4]string 122 if work, err = api.GetWork(); err != nil || work[0] != sealhash.Hex() { 123 t.Error("expect to return a mining work has same hash") 124 } 125 126 if res := api.SubmitWork(types.BlockNonce{}, sealhash, common.Hash{}); res { 127 t.Error("expect to return false when submit a fake solution") 128 } 129 // Push new block with same block number to replace the original one. 130 header = &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(1000)} 131 block = types.NewBlockWithHeader(header) 132 sealhash = ethash.SealHash(header) 133 err = ethash.Seal(context.Background(), nil, block, results, nil) 134 135 if err != nil { 136 t.Error("error in sealing block") 137 } 138 139 if work, err = api.GetWork(); err != nil || work[0] != sealhash.Hex() { 140 t.Error("expect to return the latest pushed work") 141 } 142 } 143 144 func TestHashrate(t *testing.T) { 145 var ( 146 hashrate = []hexutil.Uint64{100, 200, 300} 147 expect uint64 148 ids = []common.Hash{common.HexToHash("a"), common.HexToHash("b"), common.HexToHash("c")} 149 ) 150 ethash := NewTester(nil, false) 151 defer ethash.Close() 152 153 if tot := ethash.Hashrate(); tot != 0 { 154 t.Error("expect the result should be zero") 155 } 156 157 api := &API{ethash} 158 for i := 0; i < len(hashrate); i += 1 { 159 if res := api.SubmitHashrate(hashrate[i], ids[i]); !res { 160 t.Error("remote miner submit hashrate failed") 161 } 162 expect += uint64(hashrate[i]) 163 } 164 if tot := ethash.Hashrate(); tot != float64(expect) { 165 t.Error("expect total hashrate should be same") 166 } 167 } 168 169 func TestClosedRemoteSealer(t *testing.T) { 170 ethash := NewTester(nil, false) 171 time.Sleep(1 * time.Second) // ensure exit channel is listening 172 ethash.Close() 173 174 api := &API{ethash} 175 if _, err := api.GetWork(); err != errEthashStopped { 176 t.Error("expect to return an error to indicate ethash is stopped") 177 } 178 179 if res := api.SubmitHashrate(hexutil.Uint64(100), common.HexToHash("a")); res { 180 t.Error("expect to return false when submit hashrate to a stopped ethash") 181 } 182 }