Skip to content

Commit fa4cbad

Browse files
committed
Optimisations and fixed a couple of DDOS issues in the miner
1 parent c14071d commit fa4cbad

File tree

15 files changed

+155
-103
lines changed

15 files changed

+155
-103
lines changed

cmd/mist/assets/examples/bomb.html

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<html>
2+
<head>
3+
<script src="../ext/bignumber.min.js"></script>
4+
<script src="../ext/ethereum.js/dist/ethereum.js"></script>
5+
6+
<script>
7+
var web3 = require('web3');
8+
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545'));
9+
var eth = web3.eth;
10+
11+
function bomb() {
12+
for (var i = 0; i < 200; i++) {
13+
eth.transact({})
14+
}
15+
}
16+
</script>
17+
</head>
18+
19+
<body>
20+
<button onclick="bomb();">BOOM!</button>
21+
</body>
22+
</html>

cmd/mist/gui.go

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -387,14 +387,11 @@ func (gui *Gui) update() {
387387
generalUpdateTicker := time.NewTicker(500 * time.Millisecond)
388388
statsUpdateTicker := time.NewTicker(5 * time.Second)
389389

390-
state := gui.eth.ChainManager().TransState()
391-
392-
gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetAccount(gui.address()).Balance())))
393-
394390
lastBlockLabel := gui.getObjectByName("lastBlockLabel")
395391
miningLabel := gui.getObjectByName("miningLabel")
396392

397393
events := gui.eth.EventMux().Subscribe(
394+
core.ChainEvent{},
398395
core.TxPreEvent{},
399396
core.TxPostEvent{},
400397
)
@@ -407,6 +404,8 @@ func (gui *Gui) update() {
407404
return
408405
}
409406
switch ev := ev.(type) {
407+
case core.ChainEvent:
408+
gui.processBlock(ev.Block, false)
410409
case core.TxPreEvent:
411410
gui.insertTransaction("pre", ev.Tx)
412411

@@ -422,19 +421,6 @@ func (gui *Gui) update() {
422421
lastBlockLabel.Set("text", statusText)
423422
miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.Miner().HashRate(), 10)+"/Khash")
424423

425-
/*
426-
blockLength := gui.eth.BlockPool().BlocksProcessed
427-
chainLength := gui.eth.BlockPool().ChainLength
428-
429-
var (
430-
pct float64 = 1.0 / float64(chainLength) * float64(blockLength)
431-
dlWidget = gui.win.Root().ObjectByName("downloadIndicator")
432-
dlLabel = gui.win.Root().ObjectByName("downloadLabel")
433-
)
434-
dlWidget.Set("value", pct)
435-
dlLabel.Set("text", fmt.Sprintf("%d / %d", blockLength, chainLength))
436-
*/
437-
438424
case <-statsUpdateTicker.C:
439425
gui.setStatsPane()
440426
}

core/block_processor.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,24 +73,27 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block
7373
return receipts, nil
7474
}
7575

76-
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) {
76+
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) {
7777
// If we are mining this block and validating we want to set the logs back to 0
78-
state.EmptyLogs()
78+
statedb.EmptyLogs()
7979

8080
txGas := new(big.Int).Set(tx.Gas())
8181

82-
cb := state.GetStateObject(coinbase.Address())
83-
st := NewStateTransition(NewEnv(state, self.bc, tx, block), tx, cb)
82+
cb := statedb.GetStateObject(coinbase.Address())
83+
st := NewStateTransition(NewEnv(statedb, self.bc, tx, block), tx, cb)
8484
_, err := st.TransitionState()
85+
if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err)) {
86+
return nil, nil, err
87+
}
8588

8689
txGas.Sub(txGas, st.gas)
8790

8891
// Update the state with pending changes
89-
state.Update(txGas)
92+
statedb.Update(txGas)
9093

9194
cumulative := new(big.Int).Set(usedGas.Add(usedGas, txGas))
92-
receipt := types.NewReceipt(state.Root(), cumulative)
93-
receipt.SetLogs(state.Logs())
95+
receipt := types.NewReceipt(statedb.Root(), cumulative)
96+
receipt.SetLogs(statedb.Logs())
9497
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
9598
chainlogger.Debugln(receipt)
9699

@@ -99,12 +102,12 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, state
99102
go self.eventMux.Post(TxPostEvent{tx})
100103
}
101104

102-
go self.eventMux.Post(state.Logs())
105+
go self.eventMux.Post(statedb.Logs())
103106

104107
return receipt, txGas, err
105108
}
106109

107-
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) {
110+
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) {
108111
var (
109112
receipts types.Receipts
110113
handled, unhandled types.Transactions
@@ -115,12 +118,12 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
115118
)
116119

117120
for _, tx := range txs {
118-
receipt, txGas, err := self.ApplyTransaction(coinbase, state, block, tx, totalUsedGas, transientProcess)
121+
receipt, txGas, err := self.ApplyTransaction(coinbase, statedb, block, tx, totalUsedGas, transientProcess)
119122
if err != nil {
120123
switch {
121124
case IsNonceErr(err):
122125
return nil, nil, nil, nil, err
123-
case IsGasLimitErr(err):
126+
case state.IsGasLimitErr(err):
124127
return nil, nil, nil, nil, err
125128
default:
126129
statelogger.Infoln(err)

core/chain_manager.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,11 @@ func (self *ChainManager) State() *state.StateDB {
134134
func (self *ChainManager) TransState() *state.StateDB {
135135
self.tsmu.RLock()
136136
defer self.tsmu.RUnlock()
137-
//tmp := self.transState
138137

139138
return self.transState
140139
}
141140

142141
func (self *ChainManager) setTransState(statedb *state.StateDB) {
143-
self.tsmu.Lock()
144-
defer self.tsmu.Unlock()
145142
self.transState = statedb
146143
}
147144

@@ -361,6 +358,9 @@ func (bc *ChainManager) Stop() {
361358
}
362359

363360
func (self *ChainManager) InsertChain(chain types.Blocks) error {
361+
self.tsmu.Lock()
362+
defer self.tsmu.Unlock()
363+
364364
for _, block := range chain {
365365
td, err := self.processor.Process(block)
366366
if err != nil {
@@ -376,23 +376,34 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
376376
}
377377
block.Td = td
378378

379+
var chain, split bool
379380
self.mu.Lock()
380381
{
381382
self.write(block)
382383
cblock := self.currentBlock
383384
if td.Cmp(self.td) > 0 {
384385
if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, ethutil.Big1)) < 0 {
385386
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)
387+
split = true
386388
}
387389

388390
self.setTotalDifficulty(td)
389391
self.insert(block)
390-
self.setTransState(state.New(cblock.Root(), self.db))
391392

392-
self.eventMux.Post(ChainEvent{block, td})
393+
chain = true
393394
}
394395
}
395396
self.mu.Unlock()
397+
398+
if chain {
399+
//self.setTransState(state.New(block.Root(), self.db))
400+
self.eventMux.Post(ChainEvent{block, td})
401+
}
402+
403+
if split {
404+
self.setTransState(state.New(block.Root(), self.db))
405+
self.eventMux.Post(ChainSplitEvent{block})
406+
}
396407
}
397408

398409
return nil
@@ -402,3 +413,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
402413
func (self *ChainManager) GetAccount(addr []byte) *state.StateObject {
403414
return self.State().GetAccount(addr)
404415
}
416+
417+
func (self *ChainManager) TransMut() *sync.RWMutex {
418+
return &self.tsmu
419+
}

core/error.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,23 +68,6 @@ func IsValidationErr(err error) bool {
6868
return ok
6969
}
7070

71-
type GasLimitErr struct {
72-
Message string
73-
Is, Max *big.Int
74-
}
75-
76-
func IsGasLimitErr(err error) bool {
77-
_, ok := err.(*GasLimitErr)
78-
79-
return ok
80-
}
81-
func (err *GasLimitErr) Error() string {
82-
return err.Message
83-
}
84-
func GasLimitError(is, max *big.Int) *GasLimitErr {
85-
return &GasLimitErr{Message: fmt.Sprintf("GasLimit error. Max %s, transaction would take it to %s", max, is), Is: is, Max: max}
86-
}
87-
8871
type NonceErr struct {
8972
Message string
9073
Is, Exp uint64

core/events.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ type NewBlockEvent struct{ Block *types.Block }
1313

1414
// NewMinedBlockEvent is posted when a block has been imported.
1515
type NewMinedBlockEvent struct{ Block *types.Block }
16+
17+
// ChainSplit is posted when a new head is detected
18+
type ChainSplitEvent struct{ Block *types.Block }

core/state_transition.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) {
166166
defer self.RefundGas()
167167

168168
// Increment the nonce for the next transaction
169-
sender.Nonce += 1
169+
self.state.SetNonce(sender.Address(), sender.Nonce+1)
170+
//sender.Nonce += 1
170171

171172
// Transaction gas
172173
if err = self.UseGas(vm.GasTx); err != nil {

core/transaction_pool.go

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package core
33
import (
44
"errors"
55
"fmt"
6+
"sync"
67

78
"github.com/ethereum/go-ethereum/core/types"
89
"github.com/ethereum/go-ethereum/ethutil"
@@ -35,6 +36,7 @@ type TxProcessor interface {
3536
// guarantee a non blocking pool we use a queue channel which can be
3637
// independently read without needing access to the actual pool.
3738
type TxPool struct {
39+
mu sync.RWMutex
3840
// Queueing channel for reading and writing incoming
3941
// transactions to
4042
queueChan chan *types.Transaction
@@ -97,7 +99,7 @@ func (self *TxPool) addTx(tx *types.Transaction) {
9799
self.txs[string(tx.Hash())] = tx
98100
}
99101

100-
func (self *TxPool) Add(tx *types.Transaction) error {
102+
func (self *TxPool) add(tx *types.Transaction) error {
101103
if self.txs[string(tx.Hash())] != nil {
102104
return fmt.Errorf("Known transaction (%x)", tx.Hash()[0:4])
103105
}
@@ -128,17 +130,28 @@ func (self *TxPool) Size() int {
128130
return len(self.txs)
129131
}
130132

133+
func (self *TxPool) Add(tx *types.Transaction) error {
134+
self.mu.Lock()
135+
defer self.mu.Unlock()
136+
return self.add(tx)
137+
}
131138
func (self *TxPool) AddTransactions(txs []*types.Transaction) {
139+
self.mu.Lock()
140+
defer self.mu.Unlock()
141+
132142
for _, tx := range txs {
133-
if err := self.Add(tx); err != nil {
134-
txplogger.Infoln(err)
143+
if err := self.add(tx); err != nil {
144+
txplogger.Debugln(err)
135145
} else {
136-
txplogger.Infof("tx %x\n", tx.Hash()[0:4])
146+
txplogger.Debugf("tx %x\n", tx.Hash()[0:4])
137147
}
138148
}
139149
}
140150

141151
func (self *TxPool) GetTransactions() (txs types.Transactions) {
152+
self.mu.RLock()
153+
defer self.mu.RUnlock()
154+
142155
txs = make(types.Transactions, self.Size())
143156
i := 0
144157
for _, tx := range self.txs {
@@ -150,30 +163,32 @@ func (self *TxPool) GetTransactions() (txs types.Transactions) {
150163
}
151164

152165
func (pool *TxPool) RemoveInvalid(query StateQuery) {
166+
pool.mu.Lock()
167+
153168
var removedTxs types.Transactions
154169
for _, tx := range pool.txs {
155170
sender := query.GetAccount(tx.From())
156171
err := pool.ValidateTransaction(tx)
157-
fmt.Println(err, sender.Nonce, tx.Nonce())
158172
if err != nil || sender.Nonce >= tx.Nonce() {
159173
removedTxs = append(removedTxs, tx)
160174
}
161175
}
176+
pool.mu.Unlock()
162177

163178
pool.RemoveSet(removedTxs)
164179
}
165180

166181
func (self *TxPool) RemoveSet(txs types.Transactions) {
182+
self.mu.Lock()
183+
defer self.mu.Unlock()
184+
167185
for _, tx := range txs {
168186
delete(self.txs, string(tx.Hash()))
169187
}
170188
}
171189

172-
func (pool *TxPool) Flush() []*types.Transaction {
173-
txList := pool.GetTransactions()
190+
func (pool *TxPool) Flush() {
174191
pool.txs = make(map[string]*types.Transaction)
175-
176-
return txList
177192
}
178193

179194
func (pool *TxPool) Start() {

ethutil/common.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"math/big"
66
"runtime"
7+
"time"
78
)
89

910
func IsWindows() bool {
@@ -86,3 +87,9 @@ var (
8687
Big256 = big.NewInt(0xff)
8788
Big257 = big.NewInt(257)
8889
)
90+
91+
func Bench(pre string, cb func()) {
92+
start := time.Now()
93+
cb()
94+
fmt.Println(pre, ": took:", time.Since(start))
95+
}

0 commit comments

Comments
 (0)