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 | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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
									
								
								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 | ||||
| 				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,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, | ||||
| 	} | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user