good morning!!!!

Skip to content
Snippets Groups Projects
Commit cb845b9b authored by obscuren's avatar obscuren
Browse files

Implemented AR PoW

parent 56843ca0
No related branches found
No related tags found
No related merge requests found
package ar
import (
"math/big"
"github.com/ethereum/eth-go/ethtrie"
)
type Block interface {
Trie() *ethtrie.Trie
Diff() *big.Int
}
package ar
import "math/big"
const lenops int64 = 9
type OpsFunc func(a, b *big.Int) *big.Int
var ops [lenops]OpsFunc
func init() {
ops[0] = Add
ops[1] = Mul
ops[2] = Mod
ops[3] = Xor
ops[4] = And
ops[5] = Or
ops[6] = Sub1
ops[7] = XorSub
ops[8] = Rsh
}
func Add(x, y *big.Int) *big.Int {
return new(big.Int).Add(x, y)
}
func Mul(x, y *big.Int) *big.Int {
return new(big.Int).Mul(x, y)
}
func Mod(x, y *big.Int) *big.Int {
return new(big.Int).Mod(x, y)
}
func Xor(x, y *big.Int) *big.Int {
return new(big.Int).Xor(x, y)
}
func And(x, y *big.Int) *big.Int {
return new(big.Int).And(x, y)
}
func Or(x, y *big.Int) *big.Int {
return new(big.Int).Or(x, y)
}
func Sub1(x, y *big.Int) *big.Int {
a := big.NewInt(-1)
a.Sub(a, x)
return a
}
func XorSub(x, y *big.Int) *big.Int {
t := Sub1(x, nil)
return t.Xor(t, y)
}
func Rsh(x, y *big.Int) *big.Int {
return new(big.Int).Rsh(x, uint(y.Uint64()%64))
}
package ar
import (
"math/big"
"github.com/ethereum/eth-go/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)
}
}
}
package ar
import (
"fmt"
"math/big"
"testing"
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethtrie"
)
type TestBlock struct {
trie *ethtrie.Trie
}
func NewTestBlock() *TestBlock {
db, _ := ethdb.NewMemDatabase()
return &TestBlock{
trie: ethtrie.New(db, ""),
}
}
func (self *TestBlock) Diff() *big.Int {
return b(10)
}
func (self *TestBlock) Trie() *ethtrie.Trie {
return self.trie
}
func (self *TestBlock) Hash() []byte {
a := make([]byte, 32)
a[0] = 10
a[1] = 2
return a
}
func TestPow(t *testing.T) {
entry := make([]byte, 32)
entry[0] = 255
block := NewTestBlock()
pow := NewTape(block)
nonce := pow.Run(block.Hash())
fmt.Println("Found nonce", nonce)
}
package ar
import (
"math/big"
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethutil"
)
var b = big.NewInt
type Node interface {
Big() *big.Int
}
type ByteNode []byte
func (self ByteNode) Big() *big.Int {
return ethutil.BigD(ethutil.Encode([]byte(self)))
}
func Sha3(v interface{}) *big.Int {
if b, ok := v.(*big.Int); ok {
return ethutil.BigD(ethcrypto.Sha3(b.Bytes()))
} else if b, ok := v.([]interface{}); ok {
return ethutil.BigD(ethcrypto.Sha3(ethutil.Encode(b)))
} else if s, ok := v.([]*big.Int); ok {
v := make([]interface{}, len(s))
for i, b := range s {
v[i] = b
}
return ethutil.BigD(ethcrypto.Sha3(ethutil.Encode(v)))
}
return nil
}
type NumberGenerator interface {
rand(r *big.Int) *big.Int
rand64(r int64) *big.Int
}
type rnd struct {
seed *big.Int
}
func Rnd(s *big.Int) rnd {
return rnd{s}
}
func (self rnd) rand(r *big.Int) *big.Int {
o := b(0).Mod(self.seed, r)
self.seed.Div(self.seed, r)
if self.seed.Cmp(ethutil.BigPow(2, 64)) < 0 {
self.seed = Sha3(self.seed)
}
return o
}
func (self rnd) rand64(r int64) *big.Int {
return self.rand(b(r))
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment