dagger.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. package core
  2. import (
  3. "hash"
  4. "math/big"
  5. "math/rand"
  6. "time"
  7. "github.com/ethereum/go-ethereum/core/types"
  8. "github.com/ethereum/go-ethereum/crypto"
  9. "github.com/ethereum/go-ethereum/ethutil"
  10. "github.com/ethereum/go-ethereum/logger"
  11. "github.com/obscuren/sha3"
  12. )
  13. var powlogger = logger.NewLogger("POW")
  14. type PoW interface {
  15. Search(block *types.Block, stop <-chan struct{}) []byte
  16. Verify(hash []byte, diff *big.Int, nonce []byte) bool
  17. GetHashrate() int64
  18. Turbo(bool)
  19. }
  20. type EasyPow struct {
  21. hash *big.Int
  22. HashRate int64
  23. turbo bool
  24. }
  25. func (pow *EasyPow) GetHashrate() int64 {
  26. return pow.HashRate
  27. }
  28. func (pow *EasyPow) Turbo(on bool) {
  29. pow.turbo = on
  30. }
  31. func (pow *EasyPow) Search(block *types.Block, stop <-chan struct{}) []byte {
  32. r := rand.New(rand.NewSource(time.Now().UnixNano()))
  33. hash := block.HashNoNonce()
  34. diff := block.Difficulty
  35. i := int64(0)
  36. start := time.Now().UnixNano()
  37. t := time.Now()
  38. for {
  39. select {
  40. case <-stop:
  41. powlogger.Infoln("Breaking from mining")
  42. pow.HashRate = 0
  43. return nil
  44. default:
  45. i++
  46. if time.Since(t) > (1 * time.Second) {
  47. elapsed := time.Now().UnixNano() - start
  48. hashes := ((float64(1e9) / float64(elapsed)) * float64(i)) / 1000
  49. pow.HashRate = int64(hashes)
  50. powlogger.Infoln("Hashing @", pow.HashRate, "khash")
  51. t = time.Now()
  52. }
  53. sha := crypto.Sha3(big.NewInt(r.Int63()).Bytes())
  54. if pow.Verify(hash, diff, sha) {
  55. return sha
  56. }
  57. }
  58. if !pow.turbo {
  59. time.Sleep(20 * time.Microsecond)
  60. }
  61. }
  62. return nil
  63. }
  64. func (pow *EasyPow) Verify(hash []byte, diff *big.Int, nonce []byte) bool {
  65. sha := sha3.NewKeccak256()
  66. d := append(hash, nonce...)
  67. sha.Write(d)
  68. verification := new(big.Int).Div(ethutil.BigPow(2, 256), diff)
  69. res := ethutil.U256(ethutil.BigD(sha.Sum(nil)))
  70. /*
  71. fmt.Printf("hash w/o nonce %x\n", hash)
  72. fmt.Printf("2**256 / %v = %v\n", diff, verification)
  73. fmt.Printf("%v <= %v\n", res, verification)
  74. fmt.Printf("vlen: %d rlen: %d\n", len(verification.Bytes()), len(res.Bytes()))
  75. */
  76. return res.Cmp(verification) <= 0
  77. }
  78. func (pow *EasyPow) SetHash(hash *big.Int) {
  79. }
  80. type Dagger struct {
  81. hash *big.Int
  82. xn *big.Int
  83. }
  84. var Found bool
  85. func (dag *Dagger) Find(obj *big.Int, resChan chan int64) {
  86. r := rand.New(rand.NewSource(time.Now().UnixNano()))
  87. for i := 0; i < 1000; i++ {
  88. rnd := r.Int63()
  89. res := dag.Eval(big.NewInt(rnd))
  90. powlogger.Infof("rnd %v\nres %v\nobj %v\n", rnd, res, obj)
  91. if res.Cmp(obj) < 0 {
  92. // Post back result on the channel
  93. resChan <- rnd
  94. // Notify other threads we've found a valid nonce
  95. Found = true
  96. }
  97. // Break out if found
  98. if Found {
  99. break
  100. }
  101. }
  102. resChan <- 0
  103. }
  104. func (dag *Dagger) Search(hash, diff *big.Int) *big.Int {
  105. // TODO fix multi threading. Somehow it results in the wrong nonce
  106. amountOfRoutines := 1
  107. dag.hash = hash
  108. obj := ethutil.BigPow(2, 256)
  109. obj = obj.Div(obj, diff)
  110. Found = false
  111. resChan := make(chan int64, 3)
  112. var res int64
  113. for k := 0; k < amountOfRoutines; k++ {
  114. go dag.Find(obj, resChan)
  115. // Wait for each go routine to finish
  116. }
  117. for k := 0; k < amountOfRoutines; k++ {
  118. // Get the result from the channel. 0 = quit
  119. if r := <-resChan; r != 0 {
  120. res = r
  121. }
  122. }
  123. return big.NewInt(res)
  124. }
  125. func (dag *Dagger) Verify(hash, diff, nonce *big.Int) bool {
  126. dag.hash = hash
  127. obj := ethutil.BigPow(2, 256)
  128. obj = obj.Div(obj, diff)
  129. return dag.Eval(nonce).Cmp(obj) < 0
  130. }
  131. func DaggerVerify(hash, diff, nonce *big.Int) bool {
  132. dagger := &Dagger{}
  133. dagger.hash = hash
  134. obj := ethutil.BigPow(2, 256)
  135. obj = obj.Div(obj, diff)
  136. return dagger.Eval(nonce).Cmp(obj) < 0
  137. }
  138. func (dag *Dagger) Node(L uint64, i uint64) *big.Int {
  139. if L == i {
  140. return dag.hash
  141. }
  142. var m *big.Int
  143. if L == 9 {
  144. m = big.NewInt(16)
  145. } else {
  146. m = big.NewInt(3)
  147. }
  148. sha := sha3.NewKeccak256()
  149. sha.Reset()
  150. d := sha3.NewKeccak256()
  151. b := new(big.Int)
  152. ret := new(big.Int)
  153. for k := 0; k < int(m.Uint64()); k++ {
  154. d.Reset()
  155. d.Write(dag.hash.Bytes())
  156. d.Write(dag.xn.Bytes())
  157. d.Write(big.NewInt(int64(L)).Bytes())
  158. d.Write(big.NewInt(int64(i)).Bytes())
  159. d.Write(big.NewInt(int64(k)).Bytes())
  160. b.SetBytes(Sum(d))
  161. pk := b.Uint64() & ((1 << ((L - 1) * 3)) - 1)
  162. sha.Write(dag.Node(L-1, pk).Bytes())
  163. }
  164. ret.SetBytes(Sum(sha))
  165. return ret
  166. }
  167. func Sum(sha hash.Hash) []byte {
  168. //in := make([]byte, 32)
  169. return sha.Sum(nil)
  170. }
  171. func (dag *Dagger) Eval(N *big.Int) *big.Int {
  172. pow := ethutil.BigPow(2, 26)
  173. dag.xn = pow.Div(N, pow)
  174. sha := sha3.NewKeccak256()
  175. sha.Reset()
  176. ret := new(big.Int)
  177. for k := 0; k < 4; k++ {
  178. d := sha3.NewKeccak256()
  179. b := new(big.Int)
  180. d.Reset()
  181. d.Write(dag.hash.Bytes())
  182. d.Write(dag.xn.Bytes())
  183. d.Write(N.Bytes())
  184. d.Write(big.NewInt(int64(k)).Bytes())
  185. b.SetBytes(Sum(d))
  186. pk := (b.Uint64() & 0x1ffffff)
  187. sha.Write(dag.Node(9, pk).Bytes())
  188. }
  189. return ret.SetBytes(Sum(sha))
  190. }