github.com/hhwill/poc-eth@v0.0.0-20240218063348-3bb107c90dbf/consensus/ethpoc/poc.go (about) 1 package ethpoc 2 3 import ( 4 "sync" 5 "time" 6 7 "github.com/ethereum/go-ethereum/accounts" 8 "github.com/ethereum/go-ethereum/common" 9 "github.com/ethereum/go-ethereum/consensus" 10 "github.com/ethereum/go-ethereum/core" 11 "github.com/ethereum/go-ethereum/core/types" 12 "github.com/ethereum/go-ethereum/rpc" 13 "golang.org/x/net/context" 14 "github.com/ethereum/go-ethereum/params" 15 ) 16 17 type Mode uint 18 19 const ( 20 ModeNormal Mode = iota 21 ModeShared 22 ModeTest 23 ModeFake 24 ModeFullFake 25 ) 26 27 // Config are the configuration parameters of the ethPoc. 28 type Config struct { 29 PocMode Mode 30 } 31 32 // sealTask wraps a seal block with relative result channel for remote sealer thread. 33 type sealTask struct { 34 block *types.Block 35 results chan<- *types.Block 36 } 37 38 // hashrate wraps the hash rate submitted by the remote sealer. 39 type hashrate struct { 40 //id common.Hash 41 ping time.Time 42 rate uint64 43 44 done chan struct{} 45 } 46 47 //type sealTask struct { 48 // ReqProTime uint64 `json:"reqProTime"` 49 // Number *big.Int `json:"number"` 50 // BaseTarget *big.Int `json:"baseTarget"` 51 // GenSign []byte `json:"genSign"` 52 //} 53 54 type mineResult struct { 55 hash common.Hash 56 nonce uint64 57 plotter uint64 58 number uint64 59 60 errc chan [2]string 61 } 62 63 // sealWork wraps a seal work package for remote sealer. 64 type sealWork struct { 65 errc chan error 66 res chan [5]string 67 } 68 69 // EthPoc is a consensus engine based on proof-of-Capacity implementing the ethpoc 70 // algorithm. 71 type EthPoc struct { 72 config Config 73 74 blockChain *core.BlockChain 75 chainConfig *params.ChainConfig 76 77 am *accounts.Manager 78 79 // Remote sealer related fields 80 threads int // Number of threads to mine on if mining 81 workCh chan *sealTask // Notification channel to push new work and relative result channel to remote sealer 82 fetchWorkCh chan *sealWork // Channel used for remote sealer to fetch mining work 83 submitWorkCh chan *mineResult // Channel used for remote sealer to submit their mining result 84 fetchRateCh chan chan uint64 // Channel used to gather submitted hash rate for local or remote sealer. 85 //submitRateCh chan *hashrate // Channel used for remote sealer to submit their mining hashrate 86 87 ctx context.Context 88 cancelFunc context.CancelFunc 89 90 // The fields below are hooks for testing 91 //shared *Ethash // Shared PoW verifier to avoid cache regeneration 92 fakeFail uint64 // Block number which fails PoW check even in fake mode 93 fakeDelay time.Duration // Time delay to sleep for before returning from verify 94 95 update chan struct{} // Notification channel to update mining parameters 96 97 lock sync.Mutex // Ensures thread safety for the in-memory caches and mining fields 98 closeOnce sync.Once // Ensures exit channel will not be closed twice. 99 exitCh chan chan error // Notification channel to exiting backend threads 100 } 101 102 // New creates a full sized ethPoc PoW scheme and starts a background thread for 103 // remote mining, also optionally notifying a batch of remote services of new work 104 // packages. 105 func New(chainConfig *params.ChainConfig, am *accounts.Manager, config Config, notify []string, noverify bool) *EthPoc { 106 ethPoc := &EthPoc{ 107 am: am, 108 chainConfig: chainConfig, 109 config: config, 110 workCh: make(chan *sealTask), 111 fetchWorkCh: make(chan *sealWork), 112 submitWorkCh: make(chan *mineResult), 113 fetchRateCh: make(chan chan uint64), 114 //submitRateCh: make(chan *hashrate), 115 exitCh: make(chan chan error), 116 } 117 118 ethPoc.ctx, ethPoc.cancelFunc = context.WithCancel(context.Background()) 119 120 go ethPoc.remote(notify, noverify) 121 return ethPoc 122 } 123 124 func (ethPoc *EthPoc) SetBlockChain(blockChain *core.BlockChain) { 125 ethPoc.blockChain = blockChain 126 } 127 128 // NewTester creates a small sized ethPoc PoW scheme useful only for testing 129 // purposes. 130 func NewTester(notify []string, noverify bool) *EthPoc { 131 ethPoc := &EthPoc{ 132 config: Config{PocMode: ModeTest}, 133 workCh: make(chan *sealTask), 134 fetchWorkCh: make(chan *sealWork), 135 submitWorkCh: make(chan *mineResult), 136 fetchRateCh: make(chan chan uint64), 137 exitCh: make(chan chan error), 138 } 139 go ethPoc.remote(notify, noverify) 140 return ethPoc 141 } 142 143 // NewFaker creates a ethPoc consensus engine with a fake PoW scheme that accepts 144 // all blocks' seal as valid, though they still have to conform to the Ethereum 145 // consensus rules. 146 func NewFaker() *EthPoc { 147 return &EthPoc{ 148 config: Config{ 149 PocMode: ModeFake, 150 }, 151 } 152 } 153 154 // NewFakeFailer creates a ethPoc consensus engine with a fake PoW scheme that 155 // accepts all blocks as valid apart from the single one specified, though they 156 // still have to conform to the Ethereum consensus rules. 157 func NewFakeFailer(fail uint64) *EthPoc { 158 return &EthPoc{ 159 config: Config{ 160 PocMode: ModeFake, 161 }, 162 fakeFail: fail, 163 } 164 } 165 166 // NewFakeDelayer creates a ethPoc consensus engine with a fake PoW scheme that 167 // accepts all blocks as valid, but delays verifications by some time, though 168 // they still have to conform to the Ethereum consensus rules. 169 func NewFakeDelayer(delay time.Duration) *EthPoc { 170 return &EthPoc{ 171 config: Config{ 172 PocMode: ModeFake, 173 }, 174 fakeDelay: delay, 175 } 176 } 177 178 // NewFullFaker creates an ethPoc consensus engine with a full fake scheme that 179 // accepts all blocks as valid, without checking any consensus rules whatsoever. 180 func NewFullFaker() *EthPoc { 181 return &EthPoc{ 182 config: Config{ 183 PocMode: ModeFullFake, 184 }, 185 } 186 } 187 188 // Close closes the exit channel to notify all backend threads exiting. 189 func (ethPoc *EthPoc) Close() error { 190 var err error 191 ethPoc.closeOnce.Do(func() { 192 // Short circuit if the exit channel is not allocated. 193 if ethPoc.exitCh == nil { 194 return 195 } 196 errc := make(chan error) 197 ethPoc.exitCh <- errc 198 err = <-errc 199 close(ethPoc.exitCh) 200 }) 201 return err 202 } 203 204 func (ethPoc *EthPoc) SetThreads(threads int) { 205 ethPoc.lock.Lock() 206 defer ethPoc.lock.Unlock() 207 208 // Update the threads and ping any running seal to pull in any changes 209 ethPoc.threads = threads 210 select { 211 case ethPoc.update <- struct{}{}: 212 default: 213 } 214 } 215 216 // Hashrate implements PoW, returning the measured rate of the search invocations 217 // per second over the last minute. 218 // Note the returned hashrate includes local hashrate, but also includes the total 219 // hashrate of all remote miner. 220 //func (ethPoc *EthPoc) Hashrate() float64 { 221 // // Short circuit if we are run the ethPoc in normal/test mode. 222 // if ethPoc.config.PocMode != ModeNormal && ethPoc.config.PocMode != ModeTest { 223 // return ethPoc.hashrate.Rate1() 224 // } 225 // var res = make(chan uint64, 1) 226 // 227 // select { 228 // case ethPoc.fetchRateCh <- res: 229 // case <-ethPoc.exitCh: 230 // // Return local hashrate only if ethPoc is stopped. 231 // return ethPoc.hashrate.Rate1() 232 // } 233 // 234 // // Gather total submitted hash rate of remote sealers. 235 // return ethPoc.hashrate.Rate1() + float64(<-res) 236 //} 237 238 // APIs implements consensus.Engine, returning the user facing RPC APIs. 239 func (ethPoc *EthPoc) APIs(chain consensus.ChainReader) []rpc.API { 240 // In order to ensure backward compatibility, we exposes ethPoc RPC APIs 241 // to both eth and ethPoc namespaces. 242 return []rpc.API{ 243 { 244 Namespace: "eth", 245 Version: "1.0", 246 Service: &API{ethPoc}, 247 Public: true, 248 }, 249 { 250 Namespace: "ethPoc", 251 Version: "1.0", 252 Service: &API{ethPoc}, 253 Public: true, 254 }, 255 } 256 } 257 258 // SeedHash is the seed to use for generating a verification cache and the mining 259 // dataset. 260 //func SeedHash(block uint64) []byte { 261 // return seedHash(block) 262 //}