forked from cerc-io/plugeth
WIP miner
This commit is contained in:
parent
4dc283c0fb
commit
b1870631a4
@ -84,6 +84,35 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block
|
|||||||
return receipts, nil
|
return receipts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, state *state.StateDB, block *types.Block, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) {
|
||||||
|
// If we are mining this block and validating we want to set the logs back to 0
|
||||||
|
state.EmptyLogs()
|
||||||
|
|
||||||
|
txGas := new(big.Int).Set(tx.Gas())
|
||||||
|
|
||||||
|
cb := state.GetStateObject(coinbase.Address())
|
||||||
|
st := NewStateTransition(NewEnv(state, self.bc, tx, block), tx, cb)
|
||||||
|
_, err := st.TransitionState()
|
||||||
|
|
||||||
|
txGas.Sub(txGas, st.gas)
|
||||||
|
|
||||||
|
// Update the state with pending changes
|
||||||
|
state.Update(txGas)
|
||||||
|
|
||||||
|
cumulative := new(big.Int).Set(usedGas.Add(usedGas, txGas))
|
||||||
|
receipt := types.NewReceipt(state.Root(), cumulative)
|
||||||
|
receipt.SetLogs(state.Logs())
|
||||||
|
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
||||||
|
chainlogger.Debugln(receipt)
|
||||||
|
|
||||||
|
// Notify all subscribers
|
||||||
|
if !transientProcess {
|
||||||
|
go self.eventMux.Post(TxPostEvent{tx})
|
||||||
|
}
|
||||||
|
|
||||||
|
return receipt, txGas, err
|
||||||
|
}
|
||||||
|
|
||||||
func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, types.Transactions, types.Transactions, types.Transactions, error) {
|
func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, types.Transactions, types.Transactions, types.Transactions, error) {
|
||||||
var (
|
var (
|
||||||
receipts types.Receipts
|
receipts types.Receipts
|
||||||
@ -96,15 +125,10 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
|
|||||||
|
|
||||||
done:
|
done:
|
||||||
for i, tx := range txs {
|
for i, tx := range txs {
|
||||||
// If we are mining this block and validating we want to set the logs back to 0
|
receipt, txGas, err := self.ApplyTransaction(coinbase, state, block, tx, totalUsedGas, transientProcess)
|
||||||
state.EmptyLogs()
|
|
||||||
|
|
||||||
txGas := new(big.Int).Set(tx.Gas())
|
|
||||||
|
|
||||||
cb := state.GetStateObject(coinbase.Address())
|
|
||||||
st := NewStateTransition(NewEnv(state, self.bc, tx, block), tx, cb)
|
|
||||||
_, err = st.TransitionState()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
return nil, nil, nil, nil, err
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case IsNonceErr(err):
|
case IsNonceErr(err):
|
||||||
err = nil // ignore error
|
err = nil // ignore error
|
||||||
@ -119,30 +143,10 @@ done:
|
|||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
txGas.Sub(txGas, st.gas)
|
|
||||||
cumulativeSum.Add(cumulativeSum, new(big.Int).Mul(txGas, tx.GasPrice()))
|
|
||||||
|
|
||||||
// Update the state with pending changes
|
|
||||||
state.Update(txGas)
|
|
||||||
|
|
||||||
cumulative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, txGas))
|
|
||||||
receipt := types.NewReceipt(state.Root(), cumulative)
|
|
||||||
receipt.SetLogs(state.Logs())
|
|
||||||
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
|
||||||
chainlogger.Debugln(receipt)
|
|
||||||
|
|
||||||
// Notify all subscribers
|
|
||||||
if !transientProcess {
|
|
||||||
go self.eventMux.Post(TxPostEvent{tx})
|
|
||||||
}
|
|
||||||
|
|
||||||
receipts = append(receipts, receipt)
|
receipts = append(receipts, receipt)
|
||||||
handled = append(handled, tx)
|
handled = append(handled, tx)
|
||||||
|
|
||||||
if ethutil.Config.Diff && ethutil.Config.DiffType == "all" {
|
cumulativeSum.Add(cumulativeSum, new(big.Int).Mul(txGas, tx.GasPrice()))
|
||||||
state.CreateOutputForDiff()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
block.Reward = cumulativeSum
|
block.Reward = cumulativeSum
|
||||||
@ -285,6 +289,10 @@ func (sm *BlockProcessor) AccumelateRewards(statedb *state.StateDB, block, paren
|
|||||||
return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4]))
|
return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !sm.Pow.Verify(types.NewBlockWithHeader(uncle)) {
|
||||||
|
return ValidationError("Uncle's nonce is invalid (= %v)", ethutil.Bytes2Hex(uncle.Nonce))
|
||||||
|
}
|
||||||
|
|
||||||
r := new(big.Int)
|
r := new(big.Int)
|
||||||
r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16))
|
r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16))
|
||||||
|
|
||||||
@ -299,14 +307,6 @@ func (sm *BlockProcessor) AccumelateRewards(statedb *state.StateDB, block, paren
|
|||||||
// Reward amount of ether to the coinbase address
|
// Reward amount of ether to the coinbase address
|
||||||
account.AddAmount(reward)
|
account.AddAmount(reward)
|
||||||
|
|
||||||
statedb.Manifest().AddMessage(&state.Message{
|
|
||||||
To: block.Header().Coinbase,
|
|
||||||
Input: nil,
|
|
||||||
Origin: nil,
|
|
||||||
Timestamp: int64(block.Header().Time), Coinbase: block.Header().Coinbase, Number: block.Header().Number,
|
|
||||||
Value: new(big.Int).Add(reward, block.Reward),
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
@ -146,6 +145,10 @@ func (self *Block) SetTransactions(transactions Transactions) {
|
|||||||
self.transactions = transactions
|
self.transactions = transactions
|
||||||
self.header.TxHash = DeriveSha(transactions)
|
self.header.TxHash = DeriveSha(transactions)
|
||||||
}
|
}
|
||||||
|
func (self *Block) AddTransaction(transaction *Transaction) {
|
||||||
|
self.transactions = append(self.transactions, transaction)
|
||||||
|
self.SetTransactions(self.transactions)
|
||||||
|
}
|
||||||
|
|
||||||
func (self *Block) Receipts() Receipts {
|
func (self *Block) Receipts() Receipts {
|
||||||
return self.receipts
|
return self.receipts
|
||||||
@ -156,6 +159,10 @@ func (self *Block) SetReceipts(receipts Receipts) {
|
|||||||
self.header.ReceiptHash = DeriveSha(receipts)
|
self.header.ReceiptHash = DeriveSha(receipts)
|
||||||
self.header.Bloom = CreateBloom(receipts)
|
self.header.Bloom = CreateBloom(receipts)
|
||||||
}
|
}
|
||||||
|
func (self *Block) AddReceipt(receipt *Receipt) {
|
||||||
|
self.receipts = append(self.receipts, receipt)
|
||||||
|
self.SetReceipts(self.receipts)
|
||||||
|
}
|
||||||
|
|
||||||
func (self *Block) RlpData() interface{} {
|
func (self *Block) RlpData() interface{} {
|
||||||
return []interface{}{self.header, self.transactions, self.uncles}
|
return []interface{}{self.header, self.transactions, self.uncles}
|
||||||
@ -173,9 +180,6 @@ func (self *Block) Coinbase() []byte { return self.header.Coinbase }
|
|||||||
func (self *Block) Time() int64 { return int64(self.header.Time) }
|
func (self *Block) Time() int64 { return int64(self.header.Time) }
|
||||||
func (self *Block) GasLimit() *big.Int { return self.header.GasLimit }
|
func (self *Block) GasLimit() *big.Int { return self.header.GasLimit }
|
||||||
func (self *Block) GasUsed() *big.Int { return self.header.GasUsed }
|
func (self *Block) GasUsed() *big.Int { return self.header.GasUsed }
|
||||||
|
|
||||||
//func (self *Block) Trie() *ptrie.Trie { return ptrie.New(self.header.Root, ethutil.Config.Db) }
|
|
||||||
//func (self *Block) State() *state.StateDB { return state.New(self.Trie()) }
|
|
||||||
func (self *Block) Root() []byte { return self.header.Root }
|
func (self *Block) Root() []byte { return self.header.Root }
|
||||||
func (self *Block) SetRoot(root []byte) { self.header.Root = root }
|
func (self *Block) SetRoot(root []byte) { self.header.Root = root }
|
||||||
func (self *Block) Size() ethutil.StorageSize { return ethutil.StorageSize(len(ethutil.Encode(self))) }
|
func (self *Block) Size() ethutil.StorageSize { return ethutil.StorageSize(len(ethutil.Encode(self))) }
|
||||||
|
164
miner/worker.go
Normal file
164
miner/worker.go
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
package miner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
"github.com/ethereum/go-ethereum/pow"
|
||||||
|
"github.com/ethereum/go-ethereum/state"
|
||||||
|
"gopkg.in/fatih/set.v0"
|
||||||
|
)
|
||||||
|
|
||||||
|
type environment struct {
|
||||||
|
totalUsedGas *big.Int
|
||||||
|
state *state.StateDB
|
||||||
|
coinbase *state.StateObject
|
||||||
|
block *types.Block
|
||||||
|
ancestors *set.Set
|
||||||
|
uncles *set.Set
|
||||||
|
}
|
||||||
|
|
||||||
|
func env(block *types.Block, eth *eth.Ethereum) *environment {
|
||||||
|
state := state.New(block.Root(), eth.Db())
|
||||||
|
env := &environment{
|
||||||
|
totalUsedGas: new(big.Int),
|
||||||
|
state: state,
|
||||||
|
block: block,
|
||||||
|
ancestors: set.New(),
|
||||||
|
uncles: set.New(),
|
||||||
|
coinbase: state.GetOrNewStateObject(block.Coinbase()),
|
||||||
|
}
|
||||||
|
for _, ancestor := range eth.ChainManager().GetAncestors(block, 7) {
|
||||||
|
env.ancestors.Add(string(ancestor.Hash()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return env
|
||||||
|
}
|
||||||
|
|
||||||
|
type worker struct {
|
||||||
|
agents []chan<- *types.Block
|
||||||
|
mux *event.TypeMux
|
||||||
|
quit chan struct{}
|
||||||
|
pow pow.PoW
|
||||||
|
|
||||||
|
eth *eth.Ethereum
|
||||||
|
chain *core.ChainManager
|
||||||
|
proc *core.BlockProcessor
|
||||||
|
coinbase []byte
|
||||||
|
|
||||||
|
current *environment
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *worker) register(agent chan<- *types.Block) {
|
||||||
|
self.agents = append(self.agents, agent)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *worker) update() {
|
||||||
|
events := self.mux.Subscribe(core.NewBlockEvent{}, core.TxPreEvent{}, &LocalTx{})
|
||||||
|
|
||||||
|
out:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case event := <-events.Chan():
|
||||||
|
switch event := event.(type) {
|
||||||
|
case core.NewBlockEvent:
|
||||||
|
block := event.Block
|
||||||
|
if self.eth.ChainManager().HasBlock(block.Hash()) {
|
||||||
|
} else if true {
|
||||||
|
}
|
||||||
|
case core.TxPreEvent, *LocalTx:
|
||||||
|
}
|
||||||
|
case <-self.quit:
|
||||||
|
break out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *worker) commit() {
|
||||||
|
self.current.state.Update(ethutil.Big0)
|
||||||
|
self.current.block.SetRoot(self.current.state.Root())
|
||||||
|
|
||||||
|
for _, agent := range self.agents {
|
||||||
|
agent <- self.current.block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *worker) commitNewWork() {
|
||||||
|
self.current = env(self.chain.NewBlock(self.coinbase), self.eth)
|
||||||
|
parent := self.chain.GetBlock(self.current.block.ParentHash())
|
||||||
|
self.current.coinbase.SetGasPool(core.CalcGasLimit(parent, self.current.block))
|
||||||
|
|
||||||
|
transactions := self.eth.TxPool().GetTransactions()
|
||||||
|
sort.Sort(types.TxByNonce{transactions})
|
||||||
|
|
||||||
|
// Keep track of transactions which return errors so they can be removed
|
||||||
|
var remove types.Transactions
|
||||||
|
for _, tx := range transactions {
|
||||||
|
err := self.commitTransaction(tx)
|
||||||
|
switch {
|
||||||
|
case core.IsNonceErr(err):
|
||||||
|
remove = append(remove, tx)
|
||||||
|
case core.IsGasLimitErr(err):
|
||||||
|
// ignore
|
||||||
|
default:
|
||||||
|
minerlogger.Infoln(err)
|
||||||
|
remove = append(remove, tx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.eth.TxPool().RemoveSet(remove)
|
||||||
|
|
||||||
|
self.current.coinbase.AddAmount(core.BlockReward)
|
||||||
|
|
||||||
|
self.commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
inclusionReward = new(big.Int).Div(core.BlockReward, big.NewInt(32))
|
||||||
|
_uncleReward = new(big.Int).Mul(core.BlockReward, big.NewInt(15))
|
||||||
|
uncleReward = new(big.Int).Div(_uncleReward, big.NewInt(16))
|
||||||
|
)
|
||||||
|
|
||||||
|
func (self *worker) commitUncle(uncle *types.Header) error {
|
||||||
|
if self.current.uncles.Has(string(uncle.Hash())) {
|
||||||
|
// Error not unique
|
||||||
|
return core.UncleError("Uncle not unique")
|
||||||
|
}
|
||||||
|
self.current.uncles.Add(string(uncle.Hash()))
|
||||||
|
|
||||||
|
if !self.current.ancestors.Has(string(uncle.ParentHash)) {
|
||||||
|
return core.UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4]))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.pow.Verify(types.NewBlockWithHeader(uncle)) {
|
||||||
|
return core.ValidationError("Uncle's nonce is invalid (= %v)", ethutil.Bytes2Hex(uncle.Nonce))
|
||||||
|
}
|
||||||
|
|
||||||
|
uncleAccount := self.current.state.GetAccount(uncle.Coinbase)
|
||||||
|
uncleAccount.AddAmount(uncleReward)
|
||||||
|
|
||||||
|
self.current.coinbase.AddBalance(uncleReward)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *worker) commitTransaction(tx *types.Transaction) error {
|
||||||
|
snapshot := self.current.state.Copy()
|
||||||
|
receipt, txGas, err := self.proc.ApplyTransaction(self.current.coinbase, self.current.state, self.current.block, tx, self.current.totalUsedGas, true)
|
||||||
|
if err != nil {
|
||||||
|
self.current.state.Set(snapshot)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
self.current.totalUsedGas.Add(self.current.totalUsedGas, txGas)
|
||||||
|
self.current.block.AddTransaction(tx)
|
||||||
|
self.current.block.AddReceipt(receipt)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -53,7 +53,7 @@ func (pow *EasyPow) Search(block pow.Block, stop <-chan struct{}) []byte {
|
|||||||
elapsed := time.Now().UnixNano() - start
|
elapsed := time.Now().UnixNano() - start
|
||||||
hashes := ((float64(1e9) / float64(elapsed)) * float64(i)) / 1000
|
hashes := ((float64(1e9) / float64(elapsed)) * float64(i)) / 1000
|
||||||
pow.HashRate = int64(hashes)
|
pow.HashRate = int64(hashes)
|
||||||
powlogger.Infoln("Hashing @", pow.HashRate, "khash")
|
//powlogger.Infoln("Hashing @", pow.HashRate, "khash")
|
||||||
|
|
||||||
t = time.Now()
|
t = time.Now()
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,9 @@ package xeth
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/whisper"
|
"github.com/ethereum/go-ethereum/whisper"
|
||||||
)
|
)
|
||||||
@ -32,7 +30,6 @@ func (self *Whisper) Post(payload string, to, from string, topics []string, prio
|
|||||||
|
|
||||||
pk := crypto.ToECDSAPub(fromHex(from))
|
pk := crypto.ToECDSAPub(fromHex(from))
|
||||||
if key := self.Whisper.GetIdentity(pk); key != nil || len(from) == 0 {
|
if key := self.Whisper.GetIdentity(pk); key != nil || len(from) == 0 {
|
||||||
fmt.Println("POST:", to)
|
|
||||||
msg := whisper.NewMessage(fromHex(payload))
|
msg := whisper.NewMessage(fromHex(payload))
|
||||||
envelope, err := msg.Seal(time.Duration(priority*100000), whisper.Opts{
|
envelope, err := msg.Seal(time.Duration(priority*100000), whisper.Opts{
|
||||||
Ttl: time.Duration(ttl) * time.Second,
|
Ttl: time.Duration(ttl) * time.Second,
|
||||||
@ -109,8 +106,8 @@ type WhisperMessage struct {
|
|||||||
func NewWhisperMessage(msg *whisper.Message) WhisperMessage {
|
func NewWhisperMessage(msg *whisper.Message) WhisperMessage {
|
||||||
return WhisperMessage{
|
return WhisperMessage{
|
||||||
ref: msg,
|
ref: msg,
|
||||||
Payload: "0x" + ethutil.Bytes2Hex(msg.Payload),
|
Payload: toHex(msg.Payload),
|
||||||
From: "0x" + ethutil.Bytes2Hex(crypto.FromECDSAPub(msg.Recover())),
|
From: toHex(crypto.FromECDSAPub(msg.Recover())),
|
||||||
Sent: msg.Sent,
|
Sent: msg.Sent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user