diff --git a/core/block_manager.go b/core/block_manager.go index 4c1cea35a..6f952f9f8 100644 --- a/core/block_manager.go +++ b/core/block_manager.go @@ -14,6 +14,8 @@ import ( "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/pow" + "github.com/ethereum/go-ethereum/pow/ezp" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/wire" ) @@ -55,7 +57,7 @@ type BlockManager struct { // non-persistent key/value memory storage mem map[string]*big.Int // Proof of work used for validating - Pow PoW + Pow pow.PoW // The ethereum manager interface eth EthManager // The managed states @@ -78,7 +80,7 @@ type BlockManager struct { func NewBlockManager(ethereum EthManager) *BlockManager { sm := &BlockManager{ mem: make(map[string]*big.Int), - Pow: &EasyPow{}, + Pow: ezp.New(), eth: ethereum, bc: ethereum.ChainManager(), } @@ -327,7 +329,7 @@ func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error { */ // Verify the nonce of the block. Return an error if it's not valid - if !sm.Pow.Verify(block.HashNoNonce(), block.Difficulty, block.Nonce) { + if !sm.Pow.Verify(block /*block.HashNoNonce(), block.Difficulty, block.Nonce*/) { return ValidationError("Block's nonce is invalid (= %v)", ethutil.Bytes2Hex(block.Nonce)) } diff --git a/core/dagger.go b/core/dagger.go index 8a042b34f..3039d8995 100644 --- a/core/dagger.go +++ b/core/dagger.go @@ -6,8 +6,6 @@ import ( "math/rand" "time" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" "github.com/obscuren/sha3" @@ -15,89 +13,6 @@ import ( var powlogger = logger.NewLogger("POW") -type PoW interface { - Search(block *types.Block, stop <-chan struct{}) []byte - Verify(hash []byte, diff *big.Int, nonce []byte) bool - GetHashrate() int64 - Turbo(bool) -} - -type EasyPow struct { - hash *big.Int - HashRate int64 - turbo bool -} - -func (pow *EasyPow) GetHashrate() int64 { - return pow.HashRate -} - -func (pow *EasyPow) Turbo(on bool) { - pow.turbo = on -} - -func (pow *EasyPow) Search(block *types.Block, stop <-chan struct{}) []byte { - r := rand.New(rand.NewSource(time.Now().UnixNano())) - hash := block.HashNoNonce() - diff := block.Difficulty - i := int64(0) - start := time.Now().UnixNano() - t := time.Now() - - for { - select { - case <-stop: - powlogger.Infoln("Breaking from mining") - pow.HashRate = 0 - return nil - default: - i++ - - if time.Since(t) > (1 * time.Second) { - elapsed := time.Now().UnixNano() - start - hashes := ((float64(1e9) / float64(elapsed)) * float64(i)) / 1000 - pow.HashRate = int64(hashes) - powlogger.Infoln("Hashing @", pow.HashRate, "khash") - - t = time.Now() - } - - sha := crypto.Sha3(big.NewInt(r.Int63()).Bytes()) - if pow.Verify(hash, diff, sha) { - return sha - } - } - - if !pow.turbo { - time.Sleep(20 * time.Microsecond) - } - } - - return nil -} - -func (pow *EasyPow) Verify(hash []byte, diff *big.Int, nonce []byte) bool { - sha := sha3.NewKeccak256() - - d := append(hash, nonce...) - sha.Write(d) - - verification := new(big.Int).Div(ethutil.BigPow(2, 256), diff) - res := ethutil.U256(ethutil.BigD(sha.Sum(nil))) - - /* - fmt.Printf("hash w/o nonce %x\n", hash) - fmt.Printf("2**256 / %v = %v\n", diff, verification) - fmt.Printf("%v <= %v\n", res, verification) - fmt.Printf("vlen: %d rlen: %d\n", len(verification.Bytes()), len(res.Bytes())) - */ - - return res.Cmp(verification) <= 0 -} - -func (pow *EasyPow) SetHash(hash *big.Int) { -} - type Dagger struct { hash *big.Int xn *big.Int diff --git a/core/simple_pow.go b/core/simple_pow.go new file mode 100644 index 000000000..9a8bc9592 --- /dev/null +++ b/core/simple_pow.go @@ -0,0 +1 @@ +package core diff --git a/core/types/block.go b/core/types/block.go index 55ce1fb9b..0108bd586 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -411,3 +411,6 @@ func (self *Block) Size() ethutil.StorageSize { func (self *Block) RlpData() interface{} { return self.Value().Val } + +// Implement pow.Block +func (self *Block) N() []byte { return self.Nonce } diff --git a/miner/miner.go b/miner/miner.go index 4f677cbef..82a92cc20 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -29,6 +29,8 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/pow" + "github.com/ethereum/go-ethereum/pow/ezp" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" @@ -59,7 +61,7 @@ type Miner struct { localTxs map[int]*LocalTx localTxId int - pow core.PoW + pow pow.PoW quitCh chan struct{} powQuitCh chan struct{} @@ -74,7 +76,7 @@ func New(coinbase []byte, eth *eth.Ethereum) *Miner { return &Miner{ eth: eth, powQuitCh: make(chan struct{}), - pow: &core.EasyPow{}, + pow: ezp.New(), mining: false, localTxs: make(map[int]*LocalTx), MinAcceptedGasPrice: big.NewInt(10000000000000), @@ -82,7 +84,7 @@ func New(coinbase []byte, eth *eth.Ethereum) *Miner { } } -func (self *Miner) GetPow() core.PoW { +func (self *Miner) GetPow() pow.PoW { return self.pow } diff --git a/pow/block.go b/pow/block.go new file mode 100644 index 000000000..4759e19fb --- /dev/null +++ b/pow/block.go @@ -0,0 +1,9 @@ +package pow + +import "math/big" + +type Block interface { + Diff() *big.Int + HashNoNonce() []byte + N() []byte +} diff --git a/pow/ezp/pow.go b/pow/ezp/pow.go new file mode 100644 index 000000000..cdf89950f --- /dev/null +++ b/pow/ezp/pow.go @@ -0,0 +1,89 @@ +package ezp + +import ( + "math/big" + "math/rand" + "time" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/pow" + "github.com/obscuren/sha3" +) + +var powlogger = logger.NewLogger("POW") + +type EasyPow struct { + hash *big.Int + HashRate int64 + turbo bool +} + +func New() *EasyPow { + return &EasyPow{} +} + +func (pow *EasyPow) GetHashrate() int64 { + return pow.HashRate +} + +func (pow *EasyPow) Turbo(on bool) { + pow.turbo = on +} + +func (pow *EasyPow) Search(block pow.Block, stop <-chan struct{}) []byte { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + hash := block.HashNoNonce() + diff := block.Diff() + i := int64(0) + start := time.Now().UnixNano() + t := time.Now() + + for { + select { + case <-stop: + powlogger.Infoln("Breaking from mining") + pow.HashRate = 0 + return nil + default: + i++ + + if time.Since(t) > (1 * time.Second) { + elapsed := time.Now().UnixNano() - start + hashes := ((float64(1e9) / float64(elapsed)) * float64(i)) / 1000 + pow.HashRate = int64(hashes) + powlogger.Infoln("Hashing @", pow.HashRate, "khash") + + t = time.Now() + } + + sha := crypto.Sha3(big.NewInt(r.Int63()).Bytes()) + if pow.verify(hash, diff, sha) { + return sha + } + } + + if !pow.turbo { + time.Sleep(20 * time.Microsecond) + } + } + + return nil +} + +func (pow *EasyPow) verify(hash []byte, diff *big.Int, nonce []byte) bool { + sha := sha3.NewKeccak256() + + d := append(hash, nonce...) + sha.Write(d) + + verification := new(big.Int).Div(ethutil.BigPow(2, 256), diff) + res := ethutil.U256(ethutil.BigD(sha.Sum(nil))) + + return res.Cmp(verification) <= 0 +} + +func (pow *EasyPow) Verify(block pow.Block) bool { + return pow.verify(block.HashNoNonce(), block.Diff(), block.N()) +} diff --git a/pow/pow.go b/pow/pow.go new file mode 100644 index 000000000..c94ee40ba --- /dev/null +++ b/pow/pow.go @@ -0,0 +1,8 @@ +package pow + +type PoW interface { + Search(block Block, stop <-chan struct{}) []byte + Verify(block Block) bool + GetHashrate() int64 + Turbo(bool) +}