github.com/jonasnick/go-ethereum@v0.7.12-0.20150216215225-22176f05d387/pow/dagger/dagger.go (about) 1 package dagger 2 3 import ( 4 "hash" 5 "math/big" 6 "math/rand" 7 "time" 8 9 "github.com/jonasnick/go-ethereum/crypto/sha3" 10 "github.com/jonasnick/go-ethereum/ethutil" 11 "github.com/jonasnick/go-ethereum/logger" 12 ) 13 14 var powlogger = logger.NewLogger("POW") 15 16 type Dagger struct { 17 hash *big.Int 18 xn *big.Int 19 } 20 21 var Found bool 22 23 func (dag *Dagger) Find(obj *big.Int, resChan chan int64) { 24 r := rand.New(rand.NewSource(time.Now().UnixNano())) 25 26 for i := 0; i < 1000; i++ { 27 rnd := r.Int63() 28 29 res := dag.Eval(big.NewInt(rnd)) 30 powlogger.Infof("rnd %v\nres %v\nobj %v\n", rnd, res, obj) 31 if res.Cmp(obj) < 0 { 32 // Post back result on the channel 33 resChan <- rnd 34 // Notify other threads we've found a valid nonce 35 Found = true 36 } 37 38 // Break out if found 39 if Found { 40 break 41 } 42 } 43 44 resChan <- 0 45 } 46 47 func (dag *Dagger) Search(hash, diff *big.Int) *big.Int { 48 // TODO fix multi threading. Somehow it results in the wrong nonce 49 amountOfRoutines := 1 50 51 dag.hash = hash 52 53 obj := ethutil.BigPow(2, 256) 54 obj = obj.Div(obj, diff) 55 56 Found = false 57 resChan := make(chan int64, 3) 58 var res int64 59 60 for k := 0; k < amountOfRoutines; k++ { 61 go dag.Find(obj, resChan) 62 63 // Wait for each go routine to finish 64 } 65 for k := 0; k < amountOfRoutines; k++ { 66 // Get the result from the channel. 0 = quit 67 if r := <-resChan; r != 0 { 68 res = r 69 } 70 } 71 72 return big.NewInt(res) 73 } 74 75 func (dag *Dagger) Verify(hash, diff, nonce *big.Int) bool { 76 dag.hash = hash 77 78 obj := ethutil.BigPow(2, 256) 79 obj = obj.Div(obj, diff) 80 81 return dag.Eval(nonce).Cmp(obj) < 0 82 } 83 84 func DaggerVerify(hash, diff, nonce *big.Int) bool { 85 dagger := &Dagger{} 86 dagger.hash = hash 87 88 obj := ethutil.BigPow(2, 256) 89 obj = obj.Div(obj, diff) 90 91 return dagger.Eval(nonce).Cmp(obj) < 0 92 } 93 94 func (dag *Dagger) Node(L uint64, i uint64) *big.Int { 95 if L == i { 96 return dag.hash 97 } 98 99 var m *big.Int 100 if L == 9 { 101 m = big.NewInt(16) 102 } else { 103 m = big.NewInt(3) 104 } 105 106 sha := sha3.NewKeccak256() 107 sha.Reset() 108 d := sha3.NewKeccak256() 109 b := new(big.Int) 110 ret := new(big.Int) 111 112 for k := 0; k < int(m.Uint64()); k++ { 113 d.Reset() 114 d.Write(dag.hash.Bytes()) 115 d.Write(dag.xn.Bytes()) 116 d.Write(big.NewInt(int64(L)).Bytes()) 117 d.Write(big.NewInt(int64(i)).Bytes()) 118 d.Write(big.NewInt(int64(k)).Bytes()) 119 120 b.SetBytes(Sum(d)) 121 pk := b.Uint64() & ((1 << ((L - 1) * 3)) - 1) 122 sha.Write(dag.Node(L-1, pk).Bytes()) 123 } 124 125 ret.SetBytes(Sum(sha)) 126 127 return ret 128 } 129 130 func Sum(sha hash.Hash) []byte { 131 //in := make([]byte, 32) 132 return sha.Sum(nil) 133 } 134 135 func (dag *Dagger) Eval(N *big.Int) *big.Int { 136 pow := ethutil.BigPow(2, 26) 137 dag.xn = pow.Div(N, pow) 138 139 sha := sha3.NewKeccak256() 140 sha.Reset() 141 ret := new(big.Int) 142 143 for k := 0; k < 4; k++ { 144 d := sha3.NewKeccak256() 145 b := new(big.Int) 146 147 d.Reset() 148 d.Write(dag.hash.Bytes()) 149 d.Write(dag.xn.Bytes()) 150 d.Write(N.Bytes()) 151 d.Write(big.NewInt(int64(k)).Bytes()) 152 153 b.SetBytes(Sum(d)) 154 pk := (b.Uint64() & 0x1ffffff) 155 156 sha.Write(dag.Node(9, pk).Bytes()) 157 } 158 159 return ret.SetBytes(Sum(sha)) 160 }