| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2015 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-23 18:35:11 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 11:21:41 +01:00
										 |  |  | package miner | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2015-04-20 00:41:50 +02:00
										 |  |  | 	"math/big" | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | 	"sync" | 
					
						
							|  |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2015-04-19 17:42:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 11:09:48 +01:00
										 |  |  | 	"github.com/ethereum/ethash" | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/logger/glog" | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 11:14:42 +01:00
										 |  |  | type RemoteAgent struct { | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | 	mu sync.Mutex | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	quit     chan struct{} | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | 	workCh   chan *Work | 
					
						
							|  |  |  | 	returnCh chan<- *Result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	currentWork *Work | 
					
						
							|  |  |  | 	work        map[common.Hash]*Work | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 11:14:42 +01:00
										 |  |  | func NewRemoteAgent() *RemoteAgent { | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | 	agent := &RemoteAgent{work: make(map[common.Hash]*Work)} | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return agent | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | func (a *RemoteAgent) Work() chan<- *Work { | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | 	return a.workCh | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | func (a *RemoteAgent) SetReturnCh(returnCh chan<- *Result) { | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | 	a.returnCh = returnCh | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 11:14:42 +01:00
										 |  |  | func (a *RemoteAgent) Start() { | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | 	a.quit = make(chan struct{}) | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | 	a.workCh = make(chan *Work, 1) | 
					
						
							|  |  |  | 	go a.maintainLoop() | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 11:14:42 +01:00
										 |  |  | func (a *RemoteAgent) Stop() { | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | 	close(a.quit) | 
					
						
							|  |  |  | 	close(a.workCh) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 11:14:42 +01:00
										 |  |  | func (a *RemoteAgent) GetHashRate() int64 { return 0 } | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 11:14:42 +01:00
										 |  |  | func (a *RemoteAgent) GetWork() [3]string { | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | 	a.mu.Lock() | 
					
						
							|  |  |  | 	defer a.mu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | 	var res [3]string | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | 	if a.currentWork != nil { | 
					
						
							|  |  |  | 		block := a.currentWork.Block | 
					
						
							| 
									
										
										
										
											2015-04-19 21:58:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | 		res[0] = block.HashNoNonce().Hex() | 
					
						
							|  |  |  | 		seedHash, _ := ethash.GetSeedHash(block.NumberU64()) | 
					
						
							| 
									
										
										
										
											2015-05-11 10:11:33 -04:00
										 |  |  | 		res[1] = common.BytesToHash(seedHash).Hex() | 
					
						
							| 
									
										
										
										
											2015-04-20 00:41:50 +02:00
										 |  |  | 		// Calculate the "target" to be returned to the external miner | 
					
						
							|  |  |  | 		n := big.NewInt(1) | 
					
						
							|  |  |  | 		n.Lsh(n, 255) | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | 		n.Div(n, block.Difficulty()) | 
					
						
							| 
									
										
										
										
											2015-04-20 00:41:50 +02:00
										 |  |  | 		n.Lsh(n, 1) | 
					
						
							| 
									
										
										
										
											2015-05-11 10:11:33 -04:00
										 |  |  | 		res[2] = common.BytesToHash(n.Bytes()).Hex() | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		a.work[block.HashNoNonce()] = a.currentWork | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return res | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | // Returns true or false, but does not indicate if the PoW was correct | 
					
						
							|  |  |  | func (a *RemoteAgent) SubmitWork(nonce uint64, mixDigest, hash common.Hash) bool { | 
					
						
							|  |  |  | 	a.mu.Lock() | 
					
						
							|  |  |  | 	defer a.mu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Make sure the work submitted is present | 
					
						
							|  |  |  | 	if a.work[hash] != nil { | 
					
						
							|  |  |  | 		block := a.work[hash].Block.WithMiningResult(nonce, mixDigest) | 
					
						
							|  |  |  | 		a.returnCh <- &Result{a.work[hash], block} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		delete(a.work, hash) | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return true | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		glog.V(logger.Info).Infof("Work was submitted for %x but no pending work found\n", hash) | 
					
						
							| 
									
										
										
										
											2015-03-23 09:35:42 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-07-11 20:45:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (a *RemoteAgent) maintainLoop() { | 
					
						
							|  |  |  | 	ticker := time.Tick(5 * time.Second) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case <-a.quit: | 
					
						
							|  |  |  | 			break out | 
					
						
							|  |  |  | 		case work := <-a.workCh: | 
					
						
							|  |  |  | 			a.mu.Lock() | 
					
						
							|  |  |  | 			a.currentWork = work | 
					
						
							|  |  |  | 			a.mu.Unlock() | 
					
						
							|  |  |  | 		case <-ticker: | 
					
						
							|  |  |  | 			// cleanup | 
					
						
							|  |  |  | 			a.mu.Lock() | 
					
						
							|  |  |  | 			for hash, work := range a.work { | 
					
						
							|  |  |  | 				if time.Since(work.createdAt) > 7*(12*time.Second) { | 
					
						
							|  |  |  | 					delete(a.work, hash) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			a.mu.Unlock() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |