aboutsummaryrefslogblamecommitdiffstats
path: root/dagger.go
blob: 8509232a2340cf0f88aa1f8a82d3f386a6d139c5 (plain) (tree)
1
2
3
4
5
6
7
8



            


                            
        






                    











                                                           








                         
                                                         


                                                                    
                 



                          


                                
 


                                         
 




                                                
     

   
                        

 









                                                    

























                                                      
                      



                                                 
                        



            




                                







                                              
                          

                            
 




                                         
 




                                      
 
                               
 
package main

import (
  "math/big"
  "math/rand"
  "time"
  "github.com/obscuren/sha3"
  "hash"
)

type Dagger struct {
  hash *big.Int
  xn *big.Int
}

var Found bool
func (dag *Dagger) Find(obj *big.Int, resChan chan int64) {
  r := rand.New(rand.NewSource(time.Now().UnixNano()))

  for i := 0; i < 1000; i++ {
    rnd := r.Int63()

    if dag.Eval(big.NewInt(rnd)).Cmp(obj) < 0 {
      // Post back result on the channel
      resChan <- rnd
      // Notify other threads we've found a valid nonce
      Found = true
    }

    // Break out if found
    if Found { break }
  }

  resChan <- 0
}

func (dag *Dagger) Search(hash, diff *big.Int) *big.Int {
  // TODO fix multi threading. Somehow it results in the wrong nonce
  amountOfRoutines := 1

  dag.hash = hash

  obj := BigPow(2, 256)
  obj = obj.Div(obj, diff)

  Found =  false
  resChan := make(chan int64, 3)
  var res int64

  for k := 0; k < amountOfRoutines; k++ {
    go dag.Find(obj, resChan)
  }

  // Wait for each go routine to finish
  for k := 0; k < amountOfRoutines; k++ {
    // Get the result from the channel. 0 = quit
    if r := <- resChan; r != 0 {
      res = r
    }
  }

  return big.NewInt(res)
}

func DaggerVerify(hash, diff, nonce *big.Int) bool {
  dagger := &Dagger{}
  dagger.hash = hash

  obj := BigPow(2, 256)
  obj = obj.Div(obj, diff)

  return dagger.Eval(nonce).Cmp(obj) < 0
}

func (dag *Dagger) Node(L uint64, i uint64) *big.Int {
  if L == i {
    return dag.hash
  }

  var m *big.Int
  if L == 9 {
    m = big.NewInt(16)
  } else {
    m = big.NewInt(3)
  }

  sha := sha3.NewKeccak224()
  sha.Reset()
  d := sha3.NewKeccak224()
  b := new(big.Int)
  ret := new(big.Int)

  for k := 0; k < int(m.Uint64()); k++ {
    d.Reset()
    d.Write(dag.hash.Bytes())
    d.Write(dag.xn.Bytes())
    d.Write(big.NewInt(int64(L)).Bytes())
    d.Write(big.NewInt(int64(i)).Bytes())
    d.Write(big.NewInt(int64(k)).Bytes())

    b.SetBytes(Sum(d))
    pk := b.Uint64() & ((1 << ((L - 1) * 3)) - 1)
    sha.Write(dag.Node(L - 1, pk).Bytes())
  }

  ret.SetBytes(Sum(sha))

  return ret
}

func Sum(sha hash.Hash) []byte {
  in := make([]byte, 32)
  return sha.Sum(in)
}

func (dag *Dagger) Eval(N *big.Int) *big.Int {
  pow := BigPow(2, 26)
  dag.xn = N.Div(N, pow)

  sha := sha3.NewKeccak224()
  sha.Reset()
  ret := new(big.Int)

  for k := 0; k < 4; k++ {
    d := sha3.NewKeccak224()
    b := new(big.Int)

    d.Reset()
    d.Write(dag.hash.Bytes())
    d.Write(dag.xn.Bytes())
    d.Write(N.Bytes())
    d.Write(big.NewInt(int64(k)).Bytes())

    b.SetBytes(Sum(d))
    pk := (b.Uint64() & 0x1ffffff)

    sha.Write(dag.Node(9, pk).Bytes())
  }

  return ret.SetBytes(Sum(sha))
}