forked from cerc-io/plugeth
Optimisations and fixed a couple of DDOS issues in the miner
This commit is contained in:
parent
c14071df9d
commit
fa4cbad315
22
cmd/mist/assets/examples/bomb.html
Normal file
22
cmd/mist/assets/examples/bomb.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="../ext/bignumber.min.js"></script>
|
||||||
|
<script src="../ext/ethereum.js/dist/ethereum.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var web3 = require('web3');
|
||||||
|
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545'));
|
||||||
|
var eth = web3.eth;
|
||||||
|
|
||||||
|
function bomb() {
|
||||||
|
for (var i = 0; i < 200; i++) {
|
||||||
|
eth.transact({})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<button onclick="bomb();">BOOM!</button>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -387,14 +387,11 @@ func (gui *Gui) update() {
|
|||||||
generalUpdateTicker := time.NewTicker(500 * time.Millisecond)
|
generalUpdateTicker := time.NewTicker(500 * time.Millisecond)
|
||||||
statsUpdateTicker := time.NewTicker(5 * time.Second)
|
statsUpdateTicker := time.NewTicker(5 * time.Second)
|
||||||
|
|
||||||
state := gui.eth.ChainManager().TransState()
|
|
||||||
|
|
||||||
gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetAccount(gui.address()).Balance())))
|
|
||||||
|
|
||||||
lastBlockLabel := gui.getObjectByName("lastBlockLabel")
|
lastBlockLabel := gui.getObjectByName("lastBlockLabel")
|
||||||
miningLabel := gui.getObjectByName("miningLabel")
|
miningLabel := gui.getObjectByName("miningLabel")
|
||||||
|
|
||||||
events := gui.eth.EventMux().Subscribe(
|
events := gui.eth.EventMux().Subscribe(
|
||||||
|
core.ChainEvent{},
|
||||||
core.TxPreEvent{},
|
core.TxPreEvent{},
|
||||||
core.TxPostEvent{},
|
core.TxPostEvent{},
|
||||||
)
|
)
|
||||||
@ -407,6 +404,8 @@ func (gui *Gui) update() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch ev := ev.(type) {
|
switch ev := ev.(type) {
|
||||||
|
case core.ChainEvent:
|
||||||
|
gui.processBlock(ev.Block, false)
|
||||||
case core.TxPreEvent:
|
case core.TxPreEvent:
|
||||||
gui.insertTransaction("pre", ev.Tx)
|
gui.insertTransaction("pre", ev.Tx)
|
||||||
|
|
||||||
@ -422,19 +421,6 @@ func (gui *Gui) update() {
|
|||||||
lastBlockLabel.Set("text", statusText)
|
lastBlockLabel.Set("text", statusText)
|
||||||
miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.Miner().HashRate(), 10)+"/Khash")
|
miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.Miner().HashRate(), 10)+"/Khash")
|
||||||
|
|
||||||
/*
|
|
||||||
blockLength := gui.eth.BlockPool().BlocksProcessed
|
|
||||||
chainLength := gui.eth.BlockPool().ChainLength
|
|
||||||
|
|
||||||
var (
|
|
||||||
pct float64 = 1.0 / float64(chainLength) * float64(blockLength)
|
|
||||||
dlWidget = gui.win.Root().ObjectByName("downloadIndicator")
|
|
||||||
dlLabel = gui.win.Root().ObjectByName("downloadLabel")
|
|
||||||
)
|
|
||||||
dlWidget.Set("value", pct)
|
|
||||||
dlLabel.Set("text", fmt.Sprintf("%d / %d", blockLength, chainLength))
|
|
||||||
*/
|
|
||||||
|
|
||||||
case <-statsUpdateTicker.C:
|
case <-statsUpdateTicker.C:
|
||||||
gui.setStatsPane()
|
gui.setStatsPane()
|
||||||
}
|
}
|
||||||
|
@ -73,24 +73,27 @@ 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) {
|
func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, statedb *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
|
// If we are mining this block and validating we want to set the logs back to 0
|
||||||
state.EmptyLogs()
|
statedb.EmptyLogs()
|
||||||
|
|
||||||
txGas := new(big.Int).Set(tx.Gas())
|
txGas := new(big.Int).Set(tx.Gas())
|
||||||
|
|
||||||
cb := state.GetStateObject(coinbase.Address())
|
cb := statedb.GetStateObject(coinbase.Address())
|
||||||
st := NewStateTransition(NewEnv(state, self.bc, tx, block), tx, cb)
|
st := NewStateTransition(NewEnv(statedb, self.bc, tx, block), tx, cb)
|
||||||
_, err := st.TransitionState()
|
_, err := st.TransitionState()
|
||||||
|
if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err)) {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
txGas.Sub(txGas, st.gas)
|
txGas.Sub(txGas, st.gas)
|
||||||
|
|
||||||
// Update the state with pending changes
|
// Update the state with pending changes
|
||||||
state.Update(txGas)
|
statedb.Update(txGas)
|
||||||
|
|
||||||
cumulative := new(big.Int).Set(usedGas.Add(usedGas, txGas))
|
cumulative := new(big.Int).Set(usedGas.Add(usedGas, txGas))
|
||||||
receipt := types.NewReceipt(state.Root(), cumulative)
|
receipt := types.NewReceipt(statedb.Root(), cumulative)
|
||||||
receipt.SetLogs(state.Logs())
|
receipt.SetLogs(statedb.Logs())
|
||||||
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
||||||
chainlogger.Debugln(receipt)
|
chainlogger.Debugln(receipt)
|
||||||
|
|
||||||
@ -99,12 +102,12 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, state
|
|||||||
go self.eventMux.Post(TxPostEvent{tx})
|
go self.eventMux.Post(TxPostEvent{tx})
|
||||||
}
|
}
|
||||||
|
|
||||||
go self.eventMux.Post(state.Logs())
|
go self.eventMux.Post(statedb.Logs())
|
||||||
|
|
||||||
return receipt, txGas, err
|
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, statedb *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
|
||||||
handled, unhandled types.Transactions
|
handled, unhandled types.Transactions
|
||||||
@ -115,12 +118,12 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
|
|||||||
)
|
)
|
||||||
|
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
receipt, txGas, err := self.ApplyTransaction(coinbase, state, block, tx, totalUsedGas, transientProcess)
|
receipt, txGas, err := self.ApplyTransaction(coinbase, statedb, block, tx, totalUsedGas, transientProcess)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch {
|
switch {
|
||||||
case IsNonceErr(err):
|
case IsNonceErr(err):
|
||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, err
|
||||||
case IsGasLimitErr(err):
|
case state.IsGasLimitErr(err):
|
||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, err
|
||||||
default:
|
default:
|
||||||
statelogger.Infoln(err)
|
statelogger.Infoln(err)
|
||||||
|
@ -134,14 +134,11 @@ func (self *ChainManager) State() *state.StateDB {
|
|||||||
func (self *ChainManager) TransState() *state.StateDB {
|
func (self *ChainManager) TransState() *state.StateDB {
|
||||||
self.tsmu.RLock()
|
self.tsmu.RLock()
|
||||||
defer self.tsmu.RUnlock()
|
defer self.tsmu.RUnlock()
|
||||||
//tmp := self.transState
|
|
||||||
|
|
||||||
return self.transState
|
return self.transState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ChainManager) setTransState(statedb *state.StateDB) {
|
func (self *ChainManager) setTransState(statedb *state.StateDB) {
|
||||||
self.tsmu.Lock()
|
|
||||||
defer self.tsmu.Unlock()
|
|
||||||
self.transState = statedb
|
self.transState = statedb
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,6 +358,9 @@ func (bc *ChainManager) Stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *ChainManager) InsertChain(chain types.Blocks) error {
|
func (self *ChainManager) InsertChain(chain types.Blocks) error {
|
||||||
|
self.tsmu.Lock()
|
||||||
|
defer self.tsmu.Unlock()
|
||||||
|
|
||||||
for _, block := range chain {
|
for _, block := range chain {
|
||||||
td, err := self.processor.Process(block)
|
td, err := self.processor.Process(block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -376,6 +376,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
|
|||||||
}
|
}
|
||||||
block.Td = td
|
block.Td = td
|
||||||
|
|
||||||
|
var chain, split bool
|
||||||
self.mu.Lock()
|
self.mu.Lock()
|
||||||
{
|
{
|
||||||
self.write(block)
|
self.write(block)
|
||||||
@ -383,16 +384,26 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
|
|||||||
if td.Cmp(self.td) > 0 {
|
if td.Cmp(self.td) > 0 {
|
||||||
if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, ethutil.Big1)) < 0 {
|
if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, ethutil.Big1)) < 0 {
|
||||||
chainlogger.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, block.Hash()[:4], td, cblock.Header().Number, cblock.Hash()[:4], self.td)
|
chainlogger.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, block.Hash()[:4], td, cblock.Header().Number, cblock.Hash()[:4], self.td)
|
||||||
|
split = true
|
||||||
}
|
}
|
||||||
|
|
||||||
self.setTotalDifficulty(td)
|
self.setTotalDifficulty(td)
|
||||||
self.insert(block)
|
self.insert(block)
|
||||||
self.setTransState(state.New(cblock.Root(), self.db))
|
|
||||||
|
|
||||||
self.eventMux.Post(ChainEvent{block, td})
|
chain = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.mu.Unlock()
|
self.mu.Unlock()
|
||||||
|
|
||||||
|
if chain {
|
||||||
|
//self.setTransState(state.New(block.Root(), self.db))
|
||||||
|
self.eventMux.Post(ChainEvent{block, td})
|
||||||
|
}
|
||||||
|
|
||||||
|
if split {
|
||||||
|
self.setTransState(state.New(block.Root(), self.db))
|
||||||
|
self.eventMux.Post(ChainSplitEvent{block})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -402,3 +413,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
|
|||||||
func (self *ChainManager) GetAccount(addr []byte) *state.StateObject {
|
func (self *ChainManager) GetAccount(addr []byte) *state.StateObject {
|
||||||
return self.State().GetAccount(addr)
|
return self.State().GetAccount(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *ChainManager) TransMut() *sync.RWMutex {
|
||||||
|
return &self.tsmu
|
||||||
|
}
|
||||||
|
@ -68,23 +68,6 @@ func IsValidationErr(err error) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
type GasLimitErr struct {
|
|
||||||
Message string
|
|
||||||
Is, Max *big.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsGasLimitErr(err error) bool {
|
|
||||||
_, ok := err.(*GasLimitErr)
|
|
||||||
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
func (err *GasLimitErr) Error() string {
|
|
||||||
return err.Message
|
|
||||||
}
|
|
||||||
func GasLimitError(is, max *big.Int) *GasLimitErr {
|
|
||||||
return &GasLimitErr{Message: fmt.Sprintf("GasLimit error. Max %s, transaction would take it to %s", max, is), Is: is, Max: max}
|
|
||||||
}
|
|
||||||
|
|
||||||
type NonceErr struct {
|
type NonceErr struct {
|
||||||
Message string
|
Message string
|
||||||
Is, Exp uint64
|
Is, Exp uint64
|
||||||
|
@ -13,3 +13,6 @@ type NewBlockEvent struct{ Block *types.Block }
|
|||||||
|
|
||||||
// NewMinedBlockEvent is posted when a block has been imported.
|
// NewMinedBlockEvent is posted when a block has been imported.
|
||||||
type NewMinedBlockEvent struct{ Block *types.Block }
|
type NewMinedBlockEvent struct{ Block *types.Block }
|
||||||
|
|
||||||
|
// ChainSplit is posted when a new head is detected
|
||||||
|
type ChainSplitEvent struct{ Block *types.Block }
|
||||||
|
@ -166,7 +166,8 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) {
|
|||||||
defer self.RefundGas()
|
defer self.RefundGas()
|
||||||
|
|
||||||
// Increment the nonce for the next transaction
|
// Increment the nonce for the next transaction
|
||||||
sender.Nonce += 1
|
self.state.SetNonce(sender.Address(), sender.Nonce+1)
|
||||||
|
//sender.Nonce += 1
|
||||||
|
|
||||||
// Transaction gas
|
// Transaction gas
|
||||||
if err = self.UseGas(vm.GasTx); err != nil {
|
if err = self.UseGas(vm.GasTx); err != nil {
|
||||||
|
@ -3,6 +3,7 @@ package core
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
@ -35,6 +36,7 @@ type TxProcessor interface {
|
|||||||
// guarantee a non blocking pool we use a queue channel which can be
|
// guarantee a non blocking pool we use a queue channel which can be
|
||||||
// independently read without needing access to the actual pool.
|
// independently read without needing access to the actual pool.
|
||||||
type TxPool struct {
|
type TxPool struct {
|
||||||
|
mu sync.RWMutex
|
||||||
// Queueing channel for reading and writing incoming
|
// Queueing channel for reading and writing incoming
|
||||||
// transactions to
|
// transactions to
|
||||||
queueChan chan *types.Transaction
|
queueChan chan *types.Transaction
|
||||||
@ -97,7 +99,7 @@ func (self *TxPool) addTx(tx *types.Transaction) {
|
|||||||
self.txs[string(tx.Hash())] = tx
|
self.txs[string(tx.Hash())] = tx
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TxPool) Add(tx *types.Transaction) error {
|
func (self *TxPool) add(tx *types.Transaction) error {
|
||||||
if self.txs[string(tx.Hash())] != nil {
|
if self.txs[string(tx.Hash())] != nil {
|
||||||
return fmt.Errorf("Known transaction (%x)", tx.Hash()[0:4])
|
return fmt.Errorf("Known transaction (%x)", tx.Hash()[0:4])
|
||||||
}
|
}
|
||||||
@ -128,17 +130,28 @@ func (self *TxPool) Size() int {
|
|||||||
return len(self.txs)
|
return len(self.txs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *TxPool) Add(tx *types.Transaction) error {
|
||||||
|
self.mu.Lock()
|
||||||
|
defer self.mu.Unlock()
|
||||||
|
return self.add(tx)
|
||||||
|
}
|
||||||
func (self *TxPool) AddTransactions(txs []*types.Transaction) {
|
func (self *TxPool) AddTransactions(txs []*types.Transaction) {
|
||||||
|
self.mu.Lock()
|
||||||
|
defer self.mu.Unlock()
|
||||||
|
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
if err := self.Add(tx); err != nil {
|
if err := self.add(tx); err != nil {
|
||||||
txplogger.Infoln(err)
|
txplogger.Debugln(err)
|
||||||
} else {
|
} else {
|
||||||
txplogger.Infof("tx %x\n", tx.Hash()[0:4])
|
txplogger.Debugf("tx %x\n", tx.Hash()[0:4])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TxPool) GetTransactions() (txs types.Transactions) {
|
func (self *TxPool) GetTransactions() (txs types.Transactions) {
|
||||||
|
self.mu.RLock()
|
||||||
|
defer self.mu.RUnlock()
|
||||||
|
|
||||||
txs = make(types.Transactions, self.Size())
|
txs = make(types.Transactions, self.Size())
|
||||||
i := 0
|
i := 0
|
||||||
for _, tx := range self.txs {
|
for _, tx := range self.txs {
|
||||||
@ -150,30 +163,32 @@ func (self *TxPool) GetTransactions() (txs types.Transactions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pool *TxPool) RemoveInvalid(query StateQuery) {
|
func (pool *TxPool) RemoveInvalid(query StateQuery) {
|
||||||
|
pool.mu.Lock()
|
||||||
|
|
||||||
var removedTxs types.Transactions
|
var removedTxs types.Transactions
|
||||||
for _, tx := range pool.txs {
|
for _, tx := range pool.txs {
|
||||||
sender := query.GetAccount(tx.From())
|
sender := query.GetAccount(tx.From())
|
||||||
err := pool.ValidateTransaction(tx)
|
err := pool.ValidateTransaction(tx)
|
||||||
fmt.Println(err, sender.Nonce, tx.Nonce())
|
|
||||||
if err != nil || sender.Nonce >= tx.Nonce() {
|
if err != nil || sender.Nonce >= tx.Nonce() {
|
||||||
removedTxs = append(removedTxs, tx)
|
removedTxs = append(removedTxs, tx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pool.mu.Unlock()
|
||||||
|
|
||||||
pool.RemoveSet(removedTxs)
|
pool.RemoveSet(removedTxs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TxPool) RemoveSet(txs types.Transactions) {
|
func (self *TxPool) RemoveSet(txs types.Transactions) {
|
||||||
|
self.mu.Lock()
|
||||||
|
defer self.mu.Unlock()
|
||||||
|
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
delete(self.txs, string(tx.Hash()))
|
delete(self.txs, string(tx.Hash()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pool *TxPool) Flush() []*types.Transaction {
|
func (pool *TxPool) Flush() {
|
||||||
txList := pool.GetTransactions()
|
|
||||||
pool.txs = make(map[string]*types.Transaction)
|
pool.txs = make(map[string]*types.Transaction)
|
||||||
|
|
||||||
return txList
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pool *TxPool) Start() {
|
func (pool *TxPool) Start() {
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func IsWindows() bool {
|
func IsWindows() bool {
|
||||||
@ -86,3 +87,9 @@ var (
|
|||||||
Big256 = big.NewInt(0xff)
|
Big256 = big.NewInt(0xff)
|
||||||
Big257 = big.NewInt(257)
|
Big257 = big.NewInt(257)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func Bench(pre string, cb func()) {
|
||||||
|
start := time.Now()
|
||||||
|
cb()
|
||||||
|
fmt.Println(pre, ": took:", time.Since(start))
|
||||||
|
}
|
||||||
|
@ -109,14 +109,18 @@ func (self *worker) register(agent Agent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *worker) update() {
|
func (self *worker) update() {
|
||||||
events := self.mux.Subscribe(core.ChainEvent{}, core.TxPreEvent{})
|
events := self.mux.Subscribe(core.ChainEvent{}, core.NewMinedBlockEvent{})
|
||||||
|
|
||||||
out:
|
out:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case event := <-events.Chan():
|
case event := <-events.Chan():
|
||||||
switch event.(type) {
|
switch ev := event.(type) {
|
||||||
case core.ChainEvent, core.TxPreEvent:
|
case core.ChainEvent:
|
||||||
|
if self.current.block != ev.Block {
|
||||||
|
self.commitNewWork()
|
||||||
|
}
|
||||||
|
case core.NewMinedBlockEvent:
|
||||||
self.commitNewWork()
|
self.commitNewWork()
|
||||||
}
|
}
|
||||||
case <-self.quit:
|
case <-self.quit:
|
||||||
@ -172,17 +176,19 @@ func (self *worker) commitNewWork() {
|
|||||||
transactions := self.eth.TxPool().GetTransactions()
|
transactions := self.eth.TxPool().GetTransactions()
|
||||||
sort.Sort(types.TxByNonce{transactions})
|
sort.Sort(types.TxByNonce{transactions})
|
||||||
|
|
||||||
|
minerlogger.Infof("committing new work with %d txs\n", len(transactions))
|
||||||
// Keep track of transactions which return errors so they can be removed
|
// Keep track of transactions which return errors so they can be removed
|
||||||
var remove types.Transactions
|
var remove types.Transactions
|
||||||
|
gasLimit:
|
||||||
for _, tx := range transactions {
|
for _, tx := range transactions {
|
||||||
err := self.commitTransaction(tx)
|
err := self.commitTransaction(tx)
|
||||||
switch {
|
switch {
|
||||||
case core.IsNonceErr(err):
|
case core.IsNonceErr(err):
|
||||||
// Remove invalid transactions
|
// Remove invalid transactions
|
||||||
remove = append(remove, tx)
|
remove = append(remove, tx)
|
||||||
case core.IsGasLimitErr(err):
|
case state.IsGasLimitErr(err):
|
||||||
// Break on gas limit
|
// Break on gas limit
|
||||||
break
|
break gasLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -227,11 +233,9 @@ func (self *worker) commitUncle(uncle *types.Header) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *worker) commitTransaction(tx *types.Transaction) error {
|
func (self *worker) commitTransaction(tx *types.Transaction) error {
|
||||||
snapshot := self.current.state.Copy()
|
//fmt.Printf("proc %x %v\n", tx.Hash()[:3], tx.Nonce())
|
||||||
receipt, _, err := self.proc.ApplyTransaction(self.current.coinbase, self.current.state, self.current.block, tx, self.current.totalUsedGas, true)
|
receipt, _, err := self.proc.ApplyTransaction(self.current.coinbase, self.current.state, self.current.block, tx, self.current.totalUsedGas, true)
|
||||||
if err != nil && (core.IsNonceErr(err) || core.IsGasLimitErr(err)) {
|
if err != nil && (core.IsNonceErr(err) || state.IsGasLimitErr(err)) {
|
||||||
self.current.state.Set(snapshot)
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ type EasyPow struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New() *EasyPow {
|
func New() *EasyPow {
|
||||||
return &EasyPow{turbo: false}
|
return &EasyPow{turbo: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pow *EasyPow) GetHashrate() int64 {
|
func (pow *EasyPow) GetHashrate() int64 {
|
||||||
|
@ -180,6 +180,7 @@ func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) error {
|
|||||||
result, _ := p.xeth.Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
|
result, _ := p.xeth.Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
|
||||||
*reply = result
|
*reply = result
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ type StateObject struct {
|
|||||||
// When an object is marked for deletion it will be delete from the trie
|
// When an object is marked for deletion it will be delete from the trie
|
||||||
// during the "update" phase of the state transition
|
// during the "update" phase of the state transition
|
||||||
remove bool
|
remove bool
|
||||||
|
dirty bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateObject) Reset() {
|
func (self *StateObject) Reset() {
|
||||||
@ -211,6 +212,8 @@ func (self *StateObject) BuyGas(gas, price *big.Int) error {
|
|||||||
return GasLimitError(self.gasPool, gas)
|
return GasLimitError(self.gasPool, gas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.gasPool.Sub(self.gasPool, gas)
|
||||||
|
|
||||||
rGas := new(big.Int).Set(gas)
|
rGas := new(big.Int).Set(gas)
|
||||||
rGas.Mul(rGas, price)
|
rGas.Mul(rGas, price)
|
||||||
|
|
||||||
@ -241,6 +244,7 @@ func (self *StateObject) Copy() *StateObject {
|
|||||||
stateObject.storage = self.storage.Copy()
|
stateObject.storage = self.storage.Copy()
|
||||||
stateObject.gasPool.Set(self.gasPool)
|
stateObject.gasPool.Set(self.gasPool)
|
||||||
stateObject.remove = self.remove
|
stateObject.remove = self.remove
|
||||||
|
stateObject.dirty = self.dirty
|
||||||
|
|
||||||
return stateObject
|
return stateObject
|
||||||
}
|
}
|
||||||
|
@ -78,13 +78,6 @@ func (self *StateDB) GetNonce(addr []byte) uint64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateDB) SetNonce(addr []byte, nonce uint64) {
|
|
||||||
stateObject := self.GetStateObject(addr)
|
|
||||||
if stateObject != nil {
|
|
||||||
stateObject.Nonce = nonce
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *StateDB) GetCode(addr []byte) []byte {
|
func (self *StateDB) GetCode(addr []byte) []byte {
|
||||||
stateObject := self.GetStateObject(addr)
|
stateObject := self.GetStateObject(addr)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
@ -94,14 +87,6 @@ func (self *StateDB) GetCode(addr []byte) []byte {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateDB) SetCode(addr, code []byte) {
|
|
||||||
stateObject := self.GetStateObject(addr)
|
|
||||||
if stateObject != nil {
|
|
||||||
stateObject.SetCode(code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO vars
|
|
||||||
func (self *StateDB) GetState(a, b []byte) []byte {
|
func (self *StateDB) GetState(a, b []byte) []byte {
|
||||||
stateObject := self.GetStateObject(a)
|
stateObject := self.GetStateObject(a)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
@ -111,10 +96,27 @@ func (self *StateDB) GetState(a, b []byte) []byte {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *StateDB) SetNonce(addr []byte, nonce uint64) {
|
||||||
|
stateObject := self.GetStateObject(addr)
|
||||||
|
if stateObject != nil {
|
||||||
|
stateObject.Nonce = nonce
|
||||||
|
stateObject.dirty = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *StateDB) SetCode(addr, code []byte) {
|
||||||
|
stateObject := self.GetStateObject(addr)
|
||||||
|
if stateObject != nil {
|
||||||
|
stateObject.SetCode(code)
|
||||||
|
stateObject.dirty = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (self *StateDB) SetState(addr, key []byte, value interface{}) {
|
func (self *StateDB) SetState(addr, key []byte, value interface{}) {
|
||||||
stateObject := self.GetStateObject(addr)
|
stateObject := self.GetStateObject(addr)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
stateObject.SetState(key, ethutil.NewValue(value))
|
stateObject.SetState(key, ethutil.NewValue(value))
|
||||||
|
stateObject.dirty = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,6 +124,7 @@ func (self *StateDB) Delete(addr []byte) bool {
|
|||||||
stateObject := self.GetStateObject(addr)
|
stateObject := self.GetStateObject(addr)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
stateObject.MarkForDeletion()
|
stateObject.MarkForDeletion()
|
||||||
|
stateObject.dirty = true
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -282,16 +285,18 @@ func (self *StateDB) Refunds() map[string]*big.Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateDB) Update(gasUsed *big.Int) {
|
func (self *StateDB) Update(gasUsed *big.Int) {
|
||||||
|
|
||||||
self.refund = make(map[string]*big.Int)
|
self.refund = make(map[string]*big.Int)
|
||||||
|
|
||||||
for _, stateObject := range self.stateObjects {
|
for _, stateObject := range self.stateObjects {
|
||||||
if stateObject.remove {
|
if stateObject.dirty {
|
||||||
self.DeleteStateObject(stateObject)
|
if stateObject.remove {
|
||||||
} else {
|
self.DeleteStateObject(stateObject)
|
||||||
stateObject.Sync()
|
} else {
|
||||||
|
stateObject.Sync()
|
||||||
|
|
||||||
self.UpdateStateObject(stateObject)
|
self.UpdateStateObject(stateObject)
|
||||||
|
}
|
||||||
|
stateObject.dirty = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
29
xeth/xeth.go
29
xeth/xeth.go
@ -7,6 +7,7 @@ package xeth
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
@ -241,7 +242,6 @@ func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (st
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
|
func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
to []byte
|
to []byte
|
||||||
value = ethutil.NewValue(valueStr)
|
value = ethutil.NewValue(valueStr)
|
||||||
@ -265,29 +265,32 @@ func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string)
|
|||||||
tx = types.NewTransactionMessage(to, value.BigInt(), gas.BigInt(), price.BigInt(), data)
|
tx = types.NewTransactionMessage(to, value.BigInt(), gas.BigInt(), price.BigInt(), data)
|
||||||
}
|
}
|
||||||
|
|
||||||
state := self.chainManager.TransState()
|
var err error
|
||||||
|
state := self.eth.ChainManager().TransState()
|
||||||
|
if balance := state.GetBalance(key.Address()); balance.Cmp(tx.Value()) < 0 {
|
||||||
|
return "", fmt.Errorf("insufficient balance. balance=%v tx=%v", balance, tx.Value())
|
||||||
|
}
|
||||||
nonce := state.GetNonce(key.Address())
|
nonce := state.GetNonce(key.Address())
|
||||||
|
|
||||||
tx.SetNonce(nonce)
|
tx.SetNonce(nonce)
|
||||||
tx.Sign(key.PrivateKey)
|
tx.Sign(key.PrivateKey)
|
||||||
|
|
||||||
// Do some pre processing for our "pre" events and hooks
|
//fmt.Printf("create tx: %x %v\n", tx.Hash()[:4], tx.Nonce())
|
||||||
block := self.chainManager.NewBlock(key.Address())
|
|
||||||
coinbase := state.GetOrNewStateObject(key.Address())
|
|
||||||
coinbase.SetGasPool(block.GasLimit())
|
|
||||||
self.blockProcessor.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true)
|
|
||||||
|
|
||||||
err := self.eth.TxPool().Add(tx)
|
/*
|
||||||
|
// Do some pre processing for our "pre" events and hooks
|
||||||
|
block := self.chainManager.NewBlock(key.Address())
|
||||||
|
coinbase := state.GetOrNewStateObject(key.Address())
|
||||||
|
coinbase.SetGasPool(block.GasLimit())
|
||||||
|
self.blockProcessor.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true)
|
||||||
|
*/
|
||||||
|
|
||||||
|
err = self.eth.TxPool().Add(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
state.SetNonce(key.Address(), nonce+1)
|
state.SetNonce(key.Address(), nonce+1)
|
||||||
|
|
||||||
if contractCreation {
|
|
||||||
addr := core.AddressFromMessage(tx)
|
|
||||||
pipelogger.Infof("Contract addr %x\n", addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if types.IsContractAddr(to) {
|
if types.IsContractAddr(to) {
|
||||||
return toHex(core.AddressFromMessage(tx)), nil
|
return toHex(core.AddressFromMessage(tx)), nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user