Skip to content

Commit c72f545

Browse files
authored
Merge pull request ethereum#3144 from ethereum/release/1.4
Release/1.4.18 to master
2 parents 3885907 + ef9265d commit c72f545

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+77642
-230
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.4.17
1+
1.4.18

cmd/ethtest/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func runTestWithReader(test string, r io.Reader) error {
7474
var err error
7575
switch strings.ToLower(test) {
7676
case "bk", "block", "blocktest", "blockchaintest", "blocktests", "blockchaintests":
77-
err = tests.RunBlockTestWithReader(params.MainNetHomesteadBlock, params.MainNetDAOForkBlock, r, skipTests)
77+
err = tests.RunBlockTestWithReader(params.MainNetHomesteadBlock, params.MainNetDAOForkBlock, params.MainNetHomesteadGasRepriceBlock, r, skipTests)
7878
case "st", "state", "statetest", "statetests":
7979
rs := tests.RuleSet{HomesteadBlock: params.MainNetHomesteadBlock, DAOForkBlock: params.MainNetDAOForkBlock, DAOForkSupport: true}
8080
err = tests.RunStateTestWithReader(rs, r, skipTests)

cmd/evm/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/ethereum/go-ethereum/crypto"
3434
"github.com/ethereum/go-ethereum/ethdb"
3535
"github.com/ethereum/go-ethereum/logger/glog"
36+
"github.com/ethereum/go-ethereum/params"
3637
"gopkg.in/urfave/cli.v1"
3738
)
3839

@@ -222,6 +223,9 @@ func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg
222223
type ruleSet struct{}
223224

224225
func (ruleSet) IsHomestead(*big.Int) bool { return true }
226+
func (ruleSet) GasTable(*big.Int) params.GasTable {
227+
return params.GasTableHomesteadGasRepriceFork
228+
}
225229

226230
func (self *VMEnv) RuleSet() vm.RuleSet { return ruleSet{} }
227231
func (self *VMEnv) Vm() vm.Vm { return self.evm }

cmd/geth/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const (
5050
clientIdentifier = "Geth" // Client identifier to advertise over the network
5151
versionMajor = 1 // Major version component of the current release
5252
versionMinor = 4 // Minor version component of the current release
53-
versionPatch = 17 // Patch version component of the current release
53+
versionPatch = 18 // Patch version component of the current release
5454
versionMeta = "stable" // Version metadata to append to the version string
5555

5656
versionOracle = "0xfa7b9770ca4cb04296cac84f37736d4041251cdf" // Ethereum address of the Geth release oracle

cmd/utils/flags.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,13 @@ func MustMakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainC
809809
}
810810
config.DAOForkSupport = true
811811
}
812+
if config.HomesteadGasRepriceBlock == nil {
813+
if ctx.GlobalBool(TestNetFlag.Name) {
814+
config.HomesteadGasRepriceBlock = params.TestNetHomesteadGasRepriceBlock
815+
} else {
816+
config.HomesteadGasRepriceBlock = params.MainNetHomesteadGasRepriceBlock
817+
}
818+
}
812819
// Force override any existing configs if explicitly requested
813820
switch {
814821
case ctx.GlobalBool(SupportDAOFork.Name):

core/blockchain.go

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ func (self *BlockChain) FastSyncCommitHead(hash common.Hash) error {
269269
if block == nil {
270270
return fmt.Errorf("non existent block [%x…]", hash[:4])
271271
}
272-
if _, err := trie.NewSecure(block.Root(), self.chainDb); err != nil {
272+
if _, err := trie.NewSecure(block.Root(), self.chainDb, 0); err != nil {
273273
return err
274274
}
275275
// If all checks out, manually set the head block
@@ -824,19 +824,16 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
824824
// faster than direct delivery and requires much less mutex
825825
// acquiring.
826826
var (
827-
stats struct{ queued, processed, ignored int }
827+
stats = insertStats{startTime: time.Now()}
828828
events = make([]interface{}, 0, len(chain))
829829
coalescedLogs vm.Logs
830-
tstart = time.Now()
831-
832-
nonceChecked = make([]bool, len(chain))
830+
nonceChecked = make([]bool, len(chain))
833831
)
834832

835833
// Start the parallel nonce verifier.
836834
nonceAbort, nonceResults := verifyNoncesFromBlocks(self.pow, chain)
837835
defer close(nonceAbort)
838836

839-
txcount := 0
840837
for i, block := range chain {
841838
if atomic.LoadInt32(&self.procInterrupt) == 1 {
842839
glog.V(logger.Debug).Infoln("Premature abort during block chain processing")
@@ -931,7 +928,6 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
931928
return i, err
932929
}
933930

934-
txcount += len(block.Transactions())
935931
// write the block to the chain and get the status
936932
status, err := self.WriteBlock(block)
937933
if err != nil {
@@ -966,19 +962,54 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
966962
case SplitStatTy:
967963
events = append(events, ChainSplitEvent{block, logs})
968964
}
965+
969966
stats.processed++
967+
if glog.V(logger.Info) {
968+
stats.report(chain, i)
969+
}
970970
}
971971

972-
if (stats.queued > 0 || stats.processed > 0 || stats.ignored > 0) && bool(glog.V(logger.Info)) {
973-
tend := time.Since(tstart)
974-
start, end := chain[0], chain[len(chain)-1]
975-
glog.Infof("imported %d block(s) (%d queued %d ignored) including %d txs in %v. #%v [%x / %x]\n", stats.processed, stats.queued, stats.ignored, txcount, tend, end.Number(), start.Hash().Bytes()[:4], end.Hash().Bytes()[:4])
976-
}
977972
go self.postChainEvents(events, coalescedLogs)
978973

979974
return 0, nil
980975
}
981976

977+
// insertStats tracks and reports on block insertion.
978+
type insertStats struct {
979+
queued, processed, ignored int
980+
lastIndex int
981+
startTime time.Time
982+
}
983+
984+
const (
985+
statsReportLimit = 1024
986+
statsReportTimeLimit = 8 * time.Second
987+
)
988+
989+
// report prints statistics if some number of blocks have been processed
990+
// or more than a few seconds have passed since the last message.
991+
func (st *insertStats) report(chain []*types.Block, index int) {
992+
limit := statsReportLimit
993+
if index == len(chain)-1 {
994+
limit = 0 // Always print a message for the last block.
995+
}
996+
now := time.Now()
997+
duration := now.Sub(st.startTime)
998+
if duration > statsReportTimeLimit || st.queued > limit || st.processed > limit || st.ignored > limit {
999+
start, end := chain[st.lastIndex], chain[index]
1000+
txcount := countTransactions(chain[st.lastIndex : index+1])
1001+
glog.Infof("imported %d block(s) (%d queued %d ignored) including %d txs in %v. #%v [%x / %x]\n", st.processed, st.queued, st.ignored, txcount, duration, end.Number(), start.Hash().Bytes()[:4], end.Hash().Bytes()[:4])
1002+
*st = insertStats{startTime: now, lastIndex: index}
1003+
}
1004+
}
1005+
1006+
func countTransactions(chain []*types.Block) (c int) {
1007+
for _, b := range chain {
1008+
c += len(b.Transactions())
1009+
}
1010+
return c
1011+
}
1012+
9821013
// reorgs takes two blocks, an old chain and a new chain and will reconstruct the blocks and inserts them
9831014
// to be part of the new canonical chain and accumulates potential missing transactions and post an
9841015
// event about them

core/config.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"math/big"
2222

2323
"github.com/ethereum/go-ethereum/core/vm"
24+
"github.com/ethereum/go-ethereum/params"
2425
)
2526

2627
var ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error
@@ -35,6 +36,8 @@ type ChainConfig struct {
3536
DAOForkBlock *big.Int `json:"daoForkBlock"` // TheDAO hard-fork switch block (nil = no fork)
3637
DAOForkSupport bool `json:"daoForkSupport"` // Whether the nodes supports or opposes the DAO hard-fork
3738

39+
HomesteadGasRepriceBlock *big.Int `json:"homesteadGasRepriceBlock"` // Homestead gas reprice switch block (nil = no fork)
40+
3841
VmConfig vm.Config `json:"-"`
3942
}
4043

@@ -45,3 +48,14 @@ func (c *ChainConfig) IsHomestead(num *big.Int) bool {
4548
}
4649
return num.Cmp(c.HomesteadBlock) >= 0
4750
}
51+
52+
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
53+
//
54+
// The returned GasTable's fields shouldn't, under any circumstances, be changed.
55+
func (c *ChainConfig) GasTable(num *big.Int) params.GasTable {
56+
if c.HomesteadGasRepriceBlock == nil || num == nil || num.Cmp(c.HomesteadGasRepriceBlock) < 0 {
57+
return params.GasTableHomestead
58+
}
59+
60+
return params.GasTableHomesteadGasRepriceFork
61+
}

core/state/state_object.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,9 @@ func (self *StateObject) markSuicided() {
137137
func (c *StateObject) getTrie(db trie.Database) *trie.SecureTrie {
138138
if c.trie == nil {
139139
var err error
140-
c.trie, err = trie.NewSecure(c.data.Root, db)
140+
c.trie, err = trie.NewSecure(c.data.Root, db, 0)
141141
if err != nil {
142-
c.trie, _ = trie.NewSecure(common.Hash{}, db)
142+
c.trie, _ = trie.NewSecure(common.Hash{}, db, 0)
143143
c.setError(fmt.Errorf("can't create storage trie: %v", err))
144144
}
145145
}

core/state/statedb.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ var StartingNonce uint64
4141
const (
4242
// Number of past tries to keep. The arbitrarily chosen value here
4343
// is max uncle depth + 1.
44-
maxTrieCacheLength = 8
44+
maxPastTries = 8
45+
46+
// Trie cache generation limit.
47+
maxTrieCacheGen = 100
4548

4649
// Number of codehash->size associations to keep.
4750
codeSizeCacheSize = 100000
@@ -86,7 +89,7 @@ type StateDB struct {
8689

8790
// Create a new state from a given trie
8891
func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
89-
tr, err := trie.NewSecure(root, db)
92+
tr, err := trie.NewSecure(root, db, maxTrieCacheGen)
9093
if err != nil {
9194
return nil, err
9295
}
@@ -155,14 +158,14 @@ func (self *StateDB) openTrie(root common.Hash) (*trie.SecureTrie, error) {
155158
return &tr, nil
156159
}
157160
}
158-
return trie.NewSecure(root, self.db)
161+
return trie.NewSecure(root, self.db, maxTrieCacheGen)
159162
}
160163

161164
func (self *StateDB) pushTrie(t *trie.SecureTrie) {
162165
self.lock.Lock()
163166
defer self.lock.Unlock()
164167

165-
if len(self.pastTries) >= maxTrieCacheLength {
168+
if len(self.pastTries) >= maxPastTries {
166169
copy(self.pastTries, self.pastTries[1:])
167170
self.pastTries[len(self.pastTries)-1] = t
168171
} else {

core/tx_pool.go

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/ethereum/go-ethereum/event"
3131
"github.com/ethereum/go-ethereum/logger"
3232
"github.com/ethereum/go-ethereum/logger/glog"
33+
"gopkg.in/karalabe/cookiejar.v2/collections/prque"
3334
)
3435

3536
var (
@@ -46,10 +47,12 @@ var (
4647
)
4748

4849
var (
49-
maxQueuedPerAccount = uint64(64) // Max limit of queued transactions per address
50-
maxQueuedInTotal = uint64(8192) // Max limit of queued transactions from all accounts
51-
maxQueuedLifetime = 3 * time.Hour // Max amount of time transactions from idle accounts are queued
52-
evictionInterval = time.Minute // Time interval to check for evictable transactions
50+
minPendingPerAccount = uint64(16) // Min number of guaranteed transaction slots per address
51+
maxPendingTotal = uint64(4096) // Max limit of pending transactions from all accounts (soft)
52+
maxQueuedPerAccount = uint64(64) // Max limit of queued transactions per address
53+
maxQueuedInTotal = uint64(1024) // Max limit of queued transactions from all accounts
54+
maxQueuedLifetime = 3 * time.Hour // Max amount of time transactions from idle accounts are queued
55+
evictionInterval = time.Minute // Time interval to check for evictable transactions
5356
)
5457

5558
type stateFn func() (*state.StateDB, error)
@@ -481,7 +484,6 @@ func (pool *TxPool) promoteExecutables() {
481484
}
482485
// Iterate over all accounts and promote any executable transactions
483486
queued := uint64(0)
484-
485487
for addr, list := range pool.queue {
486488
// Drop all transactions that are deemed too old (low nonce)
487489
for _, tx := range list.Forward(state.GetNonce(addr)) {
@@ -519,6 +521,59 @@ func (pool *TxPool) promoteExecutables() {
519521
delete(pool.queue, addr)
520522
}
521523
}
524+
// If the pending limit is overflown, start equalizing allowances
525+
pending := uint64(0)
526+
for _, list := range pool.pending {
527+
pending += uint64(list.Len())
528+
}
529+
if pending > maxPendingTotal {
530+
// Assemble a spam order to penalize large transactors first
531+
spammers := prque.New()
532+
for addr, list := range pool.pending {
533+
// Only evict transactions from high rollers
534+
if uint64(list.Len()) > minPendingPerAccount {
535+
// Skip local accounts as pools should maintain backlogs for themselves
536+
for _, tx := range list.txs.items {
537+
if !pool.localTx.contains(tx.Hash()) {
538+
spammers.Push(addr, float32(list.Len()))
539+
}
540+
break // Checking on transaction for locality is enough
541+
}
542+
}
543+
}
544+
// Gradually drop transactions from offenders
545+
offenders := []common.Address{}
546+
for pending > maxPendingTotal && !spammers.Empty() {
547+
// Retrieve the next offender if not local address
548+
offender, _ := spammers.Pop()
549+
offenders = append(offenders, offender.(common.Address))
550+
551+
// Equalize balances until all the same or below threshold
552+
if len(offenders) > 1 {
553+
// Calculate the equalization threshold for all current offenders
554+
threshold := pool.pending[offender.(common.Address)].Len()
555+
556+
// Iteratively reduce all offenders until below limit or threshold reached
557+
for pending > maxPendingTotal && pool.pending[offenders[len(offenders)-2]].Len() > threshold {
558+
for i := 0; i < len(offenders)-1; i++ {
559+
list := pool.pending[offenders[i]]
560+
list.Cap(list.Len() - 1)
561+
pending--
562+
}
563+
}
564+
}
565+
}
566+
// If still above threshold, reduce to limit or min allowance
567+
if pending > maxPendingTotal && len(offenders) > 0 {
568+
for pending > maxPendingTotal && uint64(pool.pending[offenders[len(offenders)-1]].Len()) > minPendingPerAccount {
569+
for _, addr := range offenders {
570+
list := pool.pending[addr]
571+
list.Cap(list.Len() - 1)
572+
pending--
573+
}
574+
}
575+
}
576+
}
522577
// If we've queued more transactions than the hard limit, drop oldest ones
523578
if queued > maxQueuedInTotal {
524579
// Sort all accounts with queued transactions by heartbeat

0 commit comments

Comments
 (0)