github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/pow/ezp/pow.go (about)

     1  // Copyright 2014 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 ezp
    18  
    19  import (
    20  	"encoding/binary"
    21  	"math/big"
    22  	"math/rand"
    23  	"time"
    24  
    25  	"github.com/ethereum/go-ethereum/common"
    26  	"github.com/ethereum/go-ethereum/crypto/sha3"
    27  	"github.com/ethereum/go-ethereum/logger"
    28  	"github.com/ethereum/go-ethereum/pow"
    29  )
    30  
    31  var powlogger = logger.NewLogger("POW")
    32  
    33  type EasyPow struct {
    34  	hash     *big.Int
    35  	HashRate int64
    36  	turbo    bool
    37  }
    38  
    39  func New() *EasyPow {
    40  	return &EasyPow{turbo: false}
    41  }
    42  
    43  func (pow *EasyPow) GetHashrate() int64 {
    44  	return pow.HashRate
    45  }
    46  
    47  func (pow *EasyPow) Turbo(on bool) {
    48  	pow.turbo = on
    49  }
    50  
    51  func (pow *EasyPow) Search(block pow.Block, stop <-chan struct{}) (uint64, []byte) {
    52  	r := rand.New(rand.NewSource(time.Now().UnixNano()))
    53  	hash := block.HashNoNonce()
    54  	diff := block.Difficulty()
    55  	//i := int64(0)
    56  	// TODO fix offset
    57  	i := rand.Int63()
    58  	starti := i
    59  	start := time.Now().UnixNano()
    60  
    61  	defer func() { pow.HashRate = 0 }()
    62  
    63  	// Make sure stop is empty
    64  empty:
    65  	for {
    66  		select {
    67  		case <-stop:
    68  		default:
    69  			break empty
    70  		}
    71  	}
    72  
    73  	for {
    74  		select {
    75  		case <-stop:
    76  			return 0, nil
    77  		default:
    78  			i++
    79  
    80  			elapsed := time.Now().UnixNano() - start
    81  			hashes := ((float64(1e9) / float64(elapsed)) * float64(i-starti)) / 1000
    82  			pow.HashRate = int64(hashes)
    83  
    84  			sha := uint64(r.Int63())
    85  			if verify(hash, diff, sha) {
    86  				return sha, nil
    87  			}
    88  		}
    89  
    90  		if !pow.turbo {
    91  			time.Sleep(20 * time.Microsecond)
    92  		}
    93  	}
    94  
    95  	return 0, nil
    96  }
    97  
    98  func (pow *EasyPow) Verify(block pow.Block) bool {
    99  	return Verify(block)
   100  }
   101  
   102  func verify(hash common.Hash, diff *big.Int, nonce uint64) bool {
   103  	sha := sha3.NewKeccak256()
   104  	n := make([]byte, 8)
   105  	binary.PutUvarint(n, nonce)
   106  	sha.Write(n)
   107  	sha.Write(hash[:])
   108  	verification := new(big.Int).Div(common.BigPow(2, 256), diff)
   109  	res := common.BigD(sha.Sum(nil))
   110  	return res.Cmp(verification) <= 0
   111  }
   112  
   113  func Verify(block pow.Block) bool {
   114  	return verify(block.HashNoNonce(), block.Difficulty(), block.Nonce())
   115  }