github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/consensus/ethash/ethash_test.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // Copyright 2019 The go-aigar Authors 3 // This file is part of the go-aigar library. 4 // 5 // The go-aigar 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 go-aigar 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 go-aigar 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/AigarNetwork/aigar/common" 30 "github.com/AigarNetwork/aigar/common/hexutil" 31 "github.com/AigarNetwork/aigar/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(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); err != nil { 51 t.Fatalf("unexpected verification error: %v", err) 52 } 53 case <-time.NewTimer(2 * 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/AigarNetwork/aigar/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 e := New(Config{CachesInMem: 3, CachesOnDisk: 10, CacheDir: tmpdir, PowMode: ModeTest}, nil, false) 67 defer e.Close() 68 69 workers := 8 70 epochs := 100 71 var wg sync.WaitGroup 72 wg.Add(workers) 73 for i := 0; i < workers; i++ { 74 go verifyTest(&wg, e, i, epochs) 75 } 76 wg.Wait() 77 } 78 79 func verifyTest(wg *sync.WaitGroup, e *Ethash, workerIndex, epochs int) { 80 defer wg.Done() 81 82 const wiggle = 4 * epochLength 83 r := rand.New(rand.NewSource(int64(workerIndex))) 84 for epoch := 0; epoch < epochs; epoch++ { 85 block := int64(epoch)*epochLength - wiggle/2 + r.Int63n(wiggle) 86 if block < 0 { 87 block = 0 88 } 89 header := &types.Header{Number: big.NewInt(block), Difficulty: big.NewInt(100)} 90 e.VerifySeal(nil, header) 91 } 92 } 93 94 func TestRemoteSealer(t *testing.T) { 95 ethash := NewTester(nil, false) 96 defer ethash.Close() 97 98 api := &API{ethash} 99 if _, err := api.GetWork(); err != errNoMiningWork { 100 t.Error("expect to return an error indicate there is no mining work") 101 } 102 header := &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(100)} 103 block := types.NewBlockWithHeader(header) 104 sealhash := ethash.SealHash(header) 105 106 // Push new work. 107 results := make(chan *types.Block) 108 ethash.Seal(nil, block, results, nil) 109 110 var ( 111 work [4]string 112 err error 113 ) 114 if work, err = api.GetWork(); err != nil || work[0] != sealhash.Hex() { 115 t.Error("expect to return a mining work has same hash") 116 } 117 118 if res := api.SubmitWork(types.BlockNonce{}, sealhash, common.Hash{}); res { 119 t.Error("expect to return false when submit a fake solution") 120 } 121 // Push new block with same block number to replace the original one. 122 header = &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(1000)} 123 block = types.NewBlockWithHeader(header) 124 sealhash = ethash.SealHash(header) 125 ethash.Seal(nil, block, results, nil) 126 127 if work, err = api.GetWork(); err != nil || work[0] != sealhash.Hex() { 128 t.Error("expect to return the latest pushed work") 129 } 130 } 131 132 func TestHashRate(t *testing.T) { 133 var ( 134 hashrate = []hexutil.Uint64{100, 200, 300} 135 expect uint64 136 ids = []common.Hash{common.HexToHash("a"), common.HexToHash("b"), common.HexToHash("c")} 137 ) 138 ethash := NewTester(nil, false) 139 defer ethash.Close() 140 141 if tot := ethash.Hashrate(); tot != 0 { 142 t.Error("expect the result should be zero") 143 } 144 145 api := &API{ethash} 146 for i := 0; i < len(hashrate); i += 1 { 147 if res := api.SubmitHashRate(hashrate[i], ids[i]); !res { 148 t.Error("remote miner submit hashrate failed") 149 } 150 expect += uint64(hashrate[i]) 151 } 152 if tot := ethash.Hashrate(); tot != float64(expect) { 153 t.Error("expect total hashrate should be same") 154 } 155 } 156 157 func TestClosedRemoteSealer(t *testing.T) { 158 ethash := NewTester(nil, false) 159 time.Sleep(1 * time.Second) // ensure exit channel is listening 160 ethash.Close() 161 162 api := &API{ethash} 163 if _, err := api.GetWork(); err != errEthashStopped { 164 t.Error("expect to return an error to indicate ethash is stopped") 165 } 166 167 if res := api.SubmitHashRate(hexutil.Uint64(100), common.HexToHash("a")); res { 168 t.Error("expect to return false when submit hashrate to a stopped ethash") 169 } 170 }