obscuren 10 gadi atpakaļ
vecāks
revīzija
b1870631a4
5 mainītis faili ar 219 papildinājumiem un 54 dzēšanām
  1. 37 37
      core/block_processor.go
  2. 15 11
      core/types/block.go
  3. 164 0
      miner/worker.go
  4. 1 1
      pow/ezp/pow.go
  5. 2 5
      xeth/whisper.go

+ 37 - 37
core/block_processor.go

@@ -84,6 +84,35 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block
 	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) {
 	var (
 		receipts           types.Receipts
@@ -96,15 +125,10 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
 
 done:
 	for i, tx := range txs {
-		// 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()
+		receipt, txGas, err := self.ApplyTransaction(coinbase, state, block, tx, totalUsedGas, transientProcess)
 		if err != nil {
+			return nil, nil, nil, nil, err
+
 			switch {
 			case IsNonceErr(err):
 				err = nil // ignore error
@@ -119,30 +143,10 @@ done:
 				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)
 		handled = append(handled, tx)
 
-		if ethutil.Config.Diff && ethutil.Config.DiffType == "all" {
-			state.CreateOutputForDiff()
-		}
+		cumulativeSum.Add(cumulativeSum, new(big.Int).Mul(txGas, tx.GasPrice()))
 	}
 
 	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]))
 		}
 
+		if !sm.Pow.Verify(types.NewBlockWithHeader(uncle)) {
+			return ValidationError("Uncle's nonce is invalid (= %v)", ethutil.Bytes2Hex(uncle.Nonce))
+		}
+
 		r := new(big.Int)
 		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
 	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
 }
 

+ 15 - 11
core/types/block.go

@@ -6,7 +6,6 @@ import (
 	"math/big"
 	"sort"
 	"time"
-
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/ethutil"
 	"github.com/ethereum/go-ethereum/rlp"
@@ -146,6 +145,10 @@ func (self *Block) SetTransactions(transactions Transactions) {
 	self.transactions = 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 {
 	return self.receipts
@@ -156,6 +159,10 @@ func (self *Block) SetReceipts(receipts Receipts) {
 	self.header.ReceiptHash = DeriveSha(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{} {
 	return []interface{}{self.header, self.transactions, self.uncles}
@@ -166,16 +173,13 @@ func (self *Block) RlpDataForStorage() interface{} {
 }
 
 // Header accessors (add as you need them)
-func (self *Block) Number() *big.Int   { return self.header.Number }
-func (self *Block) NumberU64() uint64  { return self.header.Number.Uint64() }
-func (self *Block) Bloom() []byte      { return self.header.Bloom }
-func (self *Block) Coinbase() []byte   { return self.header.Coinbase }
-func (self *Block) Time() int64        { return int64(self.header.Time) }
-func (self *Block) GasLimit() *big.Int { return self.header.GasLimit }
-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) Number() *big.Int          { return self.header.Number }
+func (self *Block) NumberU64() uint64         { return self.header.Number.Uint64() }
+func (self *Block) Bloom() []byte             { return self.header.Bloom }
+func (self *Block) Coinbase() []byte          { return self.header.Coinbase }
+func (self *Block) Time() int64               { return int64(self.header.Time) }
+func (self *Block) GasLimit() *big.Int        { return self.header.GasLimit }
+func (self *Block) GasUsed() *big.Int         { return self.header.GasUsed }
 func (self *Block) Root() []byte              { return self.header.Root }
 func (self *Block) SetRoot(root []byte)       { self.header.Root = root }
 func (self *Block) Size() ethutil.StorageSize { return ethutil.StorageSize(len(ethutil.Encode(self))) }

+ 164 - 0
miner/worker.go

@@ -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
+}

+ 1 - 1
pow/ezp/pow.go

@@ -53,7 +53,7 @@ func (pow *EasyPow) Search(block pow.Block, stop <-chan struct{}) []byte {
 				elapsed := time.Now().UnixNano() - start
 				hashes := ((float64(1e9) / float64(elapsed)) * float64(i)) / 1000
 				pow.HashRate = int64(hashes)
-				powlogger.Infoln("Hashing @", pow.HashRate, "khash")
+				//powlogger.Infoln("Hashing @", pow.HashRate, "khash")
 
 				t = time.Now()
 			}

+ 2 - 5
xeth/whisper.go

@@ -2,11 +2,9 @@ package xeth
 
 import (
 	"errors"
-	"fmt"
 	"time"
 
 	"github.com/ethereum/go-ethereum/crypto"
-	"github.com/ethereum/go-ethereum/ethutil"
 	"github.com/ethereum/go-ethereum/logger"
 	"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))
 	if key := self.Whisper.GetIdentity(pk); key != nil || len(from) == 0 {
-		fmt.Println("POST:", to)
 		msg := whisper.NewMessage(fromHex(payload))
 		envelope, err := msg.Seal(time.Duration(priority*100000), whisper.Opts{
 			Ttl:    time.Duration(ttl) * time.Second,
@@ -109,8 +106,8 @@ type WhisperMessage struct {
 func NewWhisperMessage(msg *whisper.Message) WhisperMessage {
 	return WhisperMessage{
 		ref:     msg,
-		Payload: "0x" + ethutil.Bytes2Hex(msg.Payload),
-		From:    "0x" + ethutil.Bytes2Hex(crypto.FromECDSAPub(msg.Recover())),
+		Payload: toHex(msg.Payload),
+		From:    toHex(crypto.FromECDSAPub(msg.Recover())),
 		Sent:    msg.Sent,
 	}
 }