github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/consensus/scrypt/scrypt.go (about) 1 // Copyright (c) 2019 Simplechain 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Lesser General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Lesser General Public License for more details. 12 // 13 // You should have received a copy of the GNU Lesser General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 // Package scrypt implements the scrypt proof-of-work consensus engine. 17 package scrypt 18 19 import ( 20 "math/big" 21 "math/rand" 22 "sync" 23 "time" 24 25 "github.com/bigzoro/my_simplechain/common" 26 "github.com/bigzoro/my_simplechain/consensus" 27 "github.com/bigzoro/my_simplechain/core/types" 28 "github.com/bigzoro/my_simplechain/metrics" 29 "github.com/bigzoro/my_simplechain/rpc" 30 ) 31 32 var ( 33 // two256 is a big integer representing 2^256 34 two256 = new(big.Int).Exp(big.NewInt(2), big.NewInt(256), big.NewInt(0)) 35 // SimpleChain scrypt mode, default scrypt mode=0x0 36 ScryptMode = uint(0x30) 37 ) 38 39 // Mode defines the type and amount of PoW verification an scrypt engine makes. 40 type Mode uint 41 42 const ( 43 ModeNormal Mode = iota 44 ModeShared 45 ModeTest 46 ModeFake 47 ModeFullFake 48 ) 49 50 // Config are the configuration parameters of the scrypt. 51 type Config struct { 52 PowMode Mode 53 } 54 55 // sealTask wraps a seal block with relative result channel for remote sealer thread. 56 type sealTask struct { 57 block *types.Block 58 results chan<- *types.Block 59 } 60 61 // mineResult wraps the pow solution parameters for the specified block. 62 type mineResult struct { 63 nonce types.BlockNonce 64 mixDigest common.Hash 65 hash common.Hash 66 67 errc chan error 68 } 69 70 // hashrate wraps the hash rate submitted by the remote sealer. 71 type hashrate struct { 72 id common.Hash 73 ping time.Time 74 rate uint64 75 76 done chan struct{} 77 } 78 79 // sealWork wraps a seal work package for remote sealer. 80 type sealWork struct { 81 errc chan error 82 res chan [3]string 83 } 84 85 // PowScrypt is a consensus engine based on proof-of-work implementing the scrypt 86 // algorithm. 87 type PowScrypt struct { 88 config Config 89 90 // Mining related fields 91 rand *rand.Rand // Properly seeded random source for nonces 92 threads int // Number of threads to mine on if mining 93 update chan struct{} // Notification channel to update mining parameters 94 hashrate metrics.Meter // Meter tracking the average hashrate 95 96 // Remote sealer related fields 97 workCh chan *sealTask // Notification channel to push new work and relative result channel to remote sealer 98 fetchWorkCh chan *sealWork // Channel used for remote sealer to fetch mining work 99 submitWorkCh chan *mineResult // Channel used for remote sealer to submit their mining result 100 fetchRateCh chan chan uint64 // Channel used to gather submitted hash rate for local or remote sealer. 101 submitRateCh chan *hashrate // Channel used for remote sealer to submit their mining hashrate 102 103 // The fields below are hooks for testing 104 fakeFail uint64 // Block number which fails PoW check even in fake mode 105 fakeDelay time.Duration // Time delay to sleep for before returning from verify 106 107 lock sync.Mutex // Ensures thread safety for the in-memory caches and mining fields 108 closeOnce sync.Once // Ensures exit channel will not be closed twice. 109 exitCh chan chan error // Notification channel to exiting backend threads 110 } 111 112 // New creates a full sized scrypt PoW scheme and starts a background thread for 113 // remote mining, also optionally notifying a batch of remote services of new work 114 // packages. 115 func NewScrypt(config Config, notify []string, noverify bool) *PowScrypt { 116 pow := &PowScrypt{ 117 config: config, 118 update: make(chan struct{}), 119 hashrate: metrics.NewMeterForced(), 120 121 workCh: make(chan *sealTask), 122 fetchWorkCh: make(chan *sealWork), 123 submitWorkCh: make(chan *mineResult), 124 fetchRateCh: make(chan chan uint64), 125 submitRateCh: make(chan *hashrate), 126 exitCh: make(chan chan error), 127 } 128 129 go pow.remote(notify, noverify) 130 return pow 131 } 132 133 // NewTester creates a small sized scrypt PoW scheme useful only for testing 134 // purposes. 135 func NewTester(notify []string, noverify bool) *PowScrypt { 136 pow := &PowScrypt{ 137 config: Config{PowMode: ModeTest}, 138 update: make(chan struct{}), 139 hashrate: metrics.NewMeterForced(), 140 141 workCh: make(chan *sealTask), 142 fetchWorkCh: make(chan *sealWork), 143 submitWorkCh: make(chan *mineResult), 144 fetchRateCh: make(chan chan uint64), 145 submitRateCh: make(chan *hashrate), 146 exitCh: make(chan chan error), 147 } 148 go pow.remote(notify, noverify) 149 return pow 150 } 151 152 // NewFaker creates a scrypt consensus engine with a fake PoW scheme that accepts 153 // all blocks' seal as valid, though they still have to conform to the SimpleChain 154 // consensus rules. 155 func NewFaker() *PowScrypt { 156 return &PowScrypt{ 157 config: Config{ 158 PowMode: ModeFake, 159 }, 160 } 161 } 162 163 // NewFakeFailer creates a scrypt consensus engine with a fake PoW scheme that 164 // accepts all blocks as valid apart from the single one specified, though they 165 // still have to conform to the SimpleChain consensus rules. 166 func NewFakeFailer(fail uint64) *PowScrypt { 167 return &PowScrypt{ 168 config: Config{ 169 PowMode: ModeFake, 170 }, 171 fakeFail: fail, 172 } 173 } 174 175 // NewFakeDelayer creates a scrypt consensus engine with a fake PoW scheme that 176 // accepts all blocks as valid, but delays verifications by some time, though 177 // they still have to conform to the SimplChain consensus rules. 178 func NewFakeDelayer(delay time.Duration) *PowScrypt { 179 return &PowScrypt{ 180 config: Config{ 181 PowMode: ModeFake, 182 }, 183 fakeDelay: delay, 184 } 185 } 186 187 // NewFullFaker creates an scrypt consensus engine with a full fake scheme that 188 // accepts all blocks as valid, without checking any consensus rules whatsoever. 189 func NewFullFaker() *PowScrypt { 190 return &PowScrypt{ 191 config: Config{ 192 PowMode: ModeFullFake, 193 }, 194 } 195 } 196 197 // Close closes the exit channel to notify all backend threads exiting. 198 func (powScrypt *PowScrypt) Close() error { 199 var err error 200 powScrypt.closeOnce.Do(func() { 201 // Short circuit if the exit channel is not allocated. 202 if powScrypt.exitCh == nil { 203 return 204 } 205 errc := make(chan error) 206 powScrypt.exitCh <- errc 207 err = <-errc 208 close(powScrypt.exitCh) 209 //walker 210 //if powScrypt.remote ==nil{ 211 // return 212 //} 213 //close(powScrypt.remote.requestExit) 214 //<-powScrypt.remote.exitCh 215 }) 216 return err 217 } 218 219 // Threads returns the number of mining threads currently enabled. This doesn't 220 // necessarily mean that mining is running! 221 func (powScrypt *PowScrypt) Threads() int { 222 powScrypt.lock.Lock() 223 defer powScrypt.lock.Unlock() 224 225 return powScrypt.threads 226 } 227 228 // SetThreads updates the number of mining threads currently enabled. Calling 229 // this method does not start mining, only sets the thread count. If zero is 230 // specified, the miner will use all cores of the machine. Setting a thread 231 // count below zero is allowed and will cause the miner to idle, without any 232 // work being done. 233 func (powScrypt *PowScrypt) SetThreads(threads int) { 234 powScrypt.lock.Lock() 235 defer powScrypt.lock.Unlock() 236 237 // Update the threads and ping any running seal to pull in any changes 238 powScrypt.threads = threads 239 select { 240 case powScrypt.update <- struct{}{}: 241 default: 242 } 243 } 244 245 // Hashrate implements PoW, returning the measured rate of the search invocations 246 // per second over the last minute. 247 // Note the returned hashrate includes local hashrate, but also includes the total 248 // hashrate of all remote miner. 249 func (powScrypt *PowScrypt) Hashrate() float64 { 250 // Short circuit if we are run the scrypt in normal/test mode. 251 if powScrypt.config.PowMode != ModeNormal && powScrypt.config.PowMode != ModeTest { 252 return powScrypt.hashrate.Rate1() 253 } 254 var res = make(chan uint64, 1) 255 256 select { 257 case powScrypt.fetchRateCh <- res: 258 case <-powScrypt.exitCh: 259 // Return local hashrate only if scrypt is stopped. 260 return powScrypt.hashrate.Rate1() 261 } 262 263 // Gather total submitted hash rate of remote sealers. 264 return powScrypt.hashrate.Rate1() + float64(<-res) 265 } 266 267 // APIs implements consensus.Engine, returning the user facing RPC APIs. 268 func (powScrypt *PowScrypt) APIs(chain consensus.ChainReader) []rpc.API { 269 // In order to ensure backward compatibility, we exposes scrypt RPC APIs 270 // to both eth and scrypt namespaces. 271 return []rpc.API{ 272 { 273 Namespace: "eth", 274 Version: "1.0", 275 Service: &API{powScrypt}, 276 Public: true, 277 }, 278 { 279 Namespace: "scrypt", 280 Version: "1.0", 281 Service: &API{powScrypt}, 282 Public: true, 283 }, 284 } 285 }