mirror of https://github.com/status-im/op-geth.git
123 lines
2.5 KiB
Go
123 lines
2.5 KiB
Go
package ar
|
|
|
|
import (
|
|
"math/big"
|
|
|
|
"github.com/ethereum/go-ethereum/ethutil"
|
|
)
|
|
|
|
type Entry struct {
|
|
op OpsFunc
|
|
i, j *big.Int
|
|
}
|
|
|
|
type Tape struct {
|
|
tape []Entry
|
|
block Block
|
|
}
|
|
|
|
func NewTape(block Block) *Tape {
|
|
return &Tape{nil, block}
|
|
}
|
|
|
|
func (self *Tape) gen(w, h int64, gen NumberGenerator) {
|
|
self.tape = nil
|
|
|
|
for v := int64(0); v < h; v++ {
|
|
op := ops[gen.rand64(lenops).Int64()]
|
|
r := gen.rand64(100).Uint64()
|
|
|
|
var j *big.Int
|
|
if r < 20 && v > 20 {
|
|
j = self.tape[len(self.tape)-1].i
|
|
} else {
|
|
j = gen.rand64(w)
|
|
}
|
|
|
|
i := gen.rand64(w)
|
|
self.tape = append(self.tape, Entry{op, i, j})
|
|
}
|
|
}
|
|
|
|
func (self *Tape) runTape(w, h int64, gen NumberGenerator) *big.Int {
|
|
var mem []*big.Int
|
|
for i := int64(0); i < w; i++ {
|
|
mem = append(mem, gen.rand(ethutil.BigPow(2, 64)))
|
|
}
|
|
|
|
set := func(i, j int) Entry {
|
|
entry := self.tape[i*100+j]
|
|
mem[entry.i.Uint64()] = entry.op(entry.i, entry.j)
|
|
|
|
return entry
|
|
}
|
|
|
|
dir := true
|
|
for i := 0; i < int(h)/100; i++ {
|
|
var entry Entry
|
|
if dir {
|
|
for j := 0; j < 100; j++ {
|
|
entry = set(i, j)
|
|
}
|
|
} else {
|
|
for j := 99; i >= 0; j-- {
|
|
entry = set(i, j)
|
|
}
|
|
}
|
|
|
|
t := mem[entry.i.Uint64()]
|
|
if big.NewInt(2).Cmp(new(big.Int).Mod(t, big.NewInt(37))) < 0 {
|
|
dir = !dir
|
|
}
|
|
}
|
|
|
|
return Sha3(mem)
|
|
}
|
|
|
|
func (self *Tape) Verify(header, nonce []byte) bool {
|
|
n := ethutil.BigD(nonce)
|
|
|
|
var w int64 = 10000
|
|
var h int64 = 150000
|
|
gen := Rnd(Sha3([]interface{}{header, new(big.Int).Div(n, big.NewInt(1000))}))
|
|
self.gen(w, h, gen)
|
|
|
|
gen = Rnd(Sha3([]interface{}{header, new(big.Int).Mod(n, big.NewInt(1000))}))
|
|
hash := self.runTape(w, h, gen)
|
|
|
|
it := self.block.Trie().Iterator()
|
|
next := it.Next(string(new(big.Int).Mod(hash, ethutil.BigPow(2, 160)).Bytes()))
|
|
|
|
req := ethutil.BigPow(2, 256)
|
|
req.Div(req, self.block.Diff())
|
|
return Sha3([]interface{}{hash, next}).Cmp(req) < 0
|
|
}
|
|
|
|
func (self *Tape) Run(header []byte) []byte {
|
|
nonce := big.NewInt(0)
|
|
var w int64 = 10000
|
|
var h int64 = 150000
|
|
|
|
req := ethutil.BigPow(2, 256)
|
|
req.Div(req, self.block.Diff())
|
|
|
|
for {
|
|
if new(big.Int).Mod(nonce, b(1000)).Cmp(b(0)) == 0 {
|
|
gen := Rnd(Sha3([]interface{}{header, new(big.Int).Div(nonce, big.NewInt(1000))}))
|
|
self.gen(w, h, gen)
|
|
}
|
|
|
|
gen := Rnd(Sha3([]interface{}{header, new(big.Int).Mod(nonce, big.NewInt(1000))}))
|
|
hash := self.runTape(w, h, gen)
|
|
|
|
it := self.block.Trie().Iterator()
|
|
next := it.Next(string(new(big.Int).Mod(hash, ethutil.BigPow(2, 160)).Bytes()))
|
|
|
|
if Sha3([]interface{}{hash, next}).Cmp(req) < 0 {
|
|
return nonce.Bytes()
|
|
} else {
|
|
nonce.Add(nonce, ethutil.Big1)
|
|
}
|
|
}
|
|
}
|