From 3f94d09c1f07538c3fc72c72609037c47c04c4b5 Mon Sep 17 00:00:00 2001 From: zsfelfoldi Date: Tue, 26 May 2015 14:17:43 +0200 Subject: fixed saving receipts --- eth/backend.go | 52 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 16 deletions(-) (limited to 'eth') diff --git a/eth/backend.go b/eth/backend.go index d2ec0cc62..c24b4e877 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -93,6 +93,13 @@ type Config struct { AccountManager *accounts.Manager SolcPath string + GpoMinGasPrice *big.Int + GpoMaxGasPrice *big.Int + GpoFullBlockRatio int + GpobaseStepDown int + GpobaseStepUp int + GpobaseCorrectionFactor int + // NewDB is used to create databases. // If nil, the default is to create leveldb databases on disk. NewDB func(path string) (common.Database, error) @@ -197,6 +204,13 @@ type Ethereum struct { SolcPath string solc *compiler.Solidity + GpoMinGasPrice *big.Int + GpoMaxGasPrice *big.Int + GpoFullBlockRatio int + GpobaseStepDown int + GpobaseStepUp int + GpobaseCorrectionFactor int + net *p2p.Server eventMux *event.TypeMux miner *miner.Miner @@ -266,22 +280,28 @@ func New(config *Config) (*Ethereum, error) { glog.V(logger.Info).Infof("Blockchain DB Version: %d", config.BlockChainVersion) eth := &Ethereum{ - shutdownChan: make(chan bool), - databasesClosed: make(chan bool), - blockDb: blockDb, - stateDb: stateDb, - extraDb: extraDb, - eventMux: &event.TypeMux{}, - accountManager: config.AccountManager, - DataDir: config.DataDir, - etherbase: common.HexToAddress(config.Etherbase), - clientVersion: config.Name, // TODO should separate from Name - ethVersionId: config.ProtocolVersion, - netVersionId: config.NetworkId, - NatSpec: config.NatSpec, - MinerThreads: config.MinerThreads, - SolcPath: config.SolcPath, - AutoDAG: config.AutoDAG, + shutdownChan: make(chan bool), + databasesClosed: make(chan bool), + blockDb: blockDb, + stateDb: stateDb, + extraDb: extraDb, + eventMux: &event.TypeMux{}, + accountManager: config.AccountManager, + DataDir: config.DataDir, + etherbase: common.HexToAddress(config.Etherbase), + clientVersion: config.Name, // TODO should separate from Name + ethVersionId: config.ProtocolVersion, + netVersionId: config.NetworkId, + NatSpec: config.NatSpec, + MinerThreads: config.MinerThreads, + SolcPath: config.SolcPath, + AutoDAG: config.AutoDAG, + GpoMinGasPrice: config.GpoMinGasPrice, + GpoMaxGasPrice: config.GpoMaxGasPrice, + GpoFullBlockRatio: config.GpoFullBlockRatio, + GpobaseStepDown: config.GpobaseStepDown, + GpobaseStepUp: config.GpobaseStepUp, + GpobaseCorrectionFactor: config.GpobaseCorrectionFactor, } eth.pow = ethash.New() -- cgit v1.2.3 From 0930e190a7eec8f956e22ada638e5b97f7ba9cda Mon Sep 17 00:00:00 2001 From: zsfelfoldi Date: Tue, 26 May 2015 14:28:32 +0200 Subject: added missing source --- eth/gasprice.go | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 eth/gasprice.go (limited to 'eth') diff --git a/eth/gasprice.go b/eth/gasprice.go new file mode 100644 index 000000000..f5b241e2c --- /dev/null +++ b/eth/gasprice.go @@ -0,0 +1,174 @@ +package eth + +import ( + "math/big" + "math/rand" + "sync" + + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/logger/glog" +) + +const gpoProcessPastBlocks = 100 + +type blockPriceInfo struct { + baseGasPrice *big.Int +} + +type GasPriceOracle struct { + eth *Ethereum + chain *core.ChainManager + pool *core.TxPool + events event.Subscription + blocks map[uint64]*blockPriceInfo + firstProcessed, lastProcessed uint64 + lastBaseMutex sync.Mutex + lastBase *big.Int +} + +func NewGasPriceOracle(eth *Ethereum) (self *GasPriceOracle) { + self = &GasPriceOracle{} + self.blocks = make(map[uint64]*blockPriceInfo) + self.eth = eth + self.chain = eth.chainManager + self.pool = eth.txPool + self.events = eth.EventMux().Subscribe( + core.ChainEvent{}, + core.ChainSplitEvent{}, + core.TxPreEvent{}, + core.TxPostEvent{}, + ) + self.processPastBlocks() + go self.listenLoop() + return +} + +func (self *GasPriceOracle) processPastBlocks() { + last := self.chain.CurrentBlock().NumberU64() + first := uint64(0) + if last > gpoProcessPastBlocks { + first = last - gpoProcessPastBlocks + } + self.firstProcessed = first + for i := first; i <= last; i++ { + self.processBlock(self.chain.GetBlockByNumber(i)) + } + +} + +func (self *GasPriceOracle) listenLoop() { + for { + ev, isopen := <-self.events.Chan() + if !isopen { + break + } + switch ev := ev.(type) { + case core.ChainEvent: + self.processBlock(ev.Block) + case core.ChainSplitEvent: + self.processBlock(ev.Block) + case core.TxPreEvent: + case core.TxPostEvent: + } + } + self.events.Unsubscribe() +} + +func (self *GasPriceOracle) processBlock(block *types.Block) { + i := block.NumberU64() + if i > self.lastProcessed { + self.lastProcessed = i + } + + lastBase := self.eth.GpoMinGasPrice + bpl := self.blocks[i-1] + if bpl != nil { + lastBase = bpl.baseGasPrice + } + if lastBase == nil { + return + } + + var corr int + lp := self.lowestPrice(block) + if lp == nil { + return + } + + if lastBase.Cmp(lp) < 0 { + corr = self.eth.GpobaseStepUp + } else { + corr = -self.eth.GpobaseStepDown + } + + crand := int64(corr * (900 + rand.Intn(201))) + newBase := new(big.Int).Mul(lastBase, big.NewInt(1000000+crand)) + newBase.Div(newBase, big.NewInt(1000000)) + + bpi := self.blocks[i] + if bpi == nil { + bpi = &blockPriceInfo{} + self.blocks[i] = bpi + } + bpi.baseGasPrice = newBase + self.lastBaseMutex.Lock() + self.lastBase = newBase + self.lastBaseMutex.Unlock() + + glog.V(logger.Detail).Infof("Processed block #%v, base price is %v\n", block.NumberU64(), newBase.Int64()) +} + +// returns the lowers possible price with which a tx was or could have been included +func (self *GasPriceOracle) lowestPrice(block *types.Block) *big.Int { + gasUsed := new(big.Int) + recepits, err := self.eth.BlockProcessor().GetBlockReceipts(block.Hash()) + if err != nil { + return self.eth.GpoMinGasPrice + } + + if len(recepits) > 0 { + gasUsed = recepits[len(recepits)-1].CumulativeGasUsed + } + + if new(big.Int).Mul(gasUsed, big.NewInt(100)).Cmp(new(big.Int).Mul(block.Header().GasLimit, + big.NewInt(int64(self.eth.GpoFullBlockRatio)))) < 0 { + // block is not full, could have posted a tx with MinGasPrice + return self.eth.GpoMinGasPrice + } + + if len(block.Transactions()) < 1 { + return self.eth.GpoMinGasPrice + } + + // block is full, find smallest gasPrice + minPrice := block.Transactions()[0].GasPrice() + for i := 1; i < len(block.Transactions()); i++ { + price := block.Transactions()[i].GasPrice() + if price.Cmp(minPrice) < 0 { + minPrice = price + } + } + return minPrice +} + +func (self *GasPriceOracle) SuggestPrice() *big.Int { + self.lastBaseMutex.Lock() + base := self.lastBase + self.lastBaseMutex.Unlock() + + baseCorr := new(big.Int).Mul(base, big.NewInt(int64(100+self.eth.GpobaseCorrectionFactor))) + baseCorr.Div(baseCorr, big.NewInt(100)) + + if baseCorr.Cmp(self.eth.GpoMinGasPrice) < 0 { + return self.eth.GpoMinGasPrice + } + + if baseCorr.Cmp(self.eth.GpoMaxGasPrice) > 0 { + return self.eth.GpoMaxGasPrice + } + + return baseCorr +} -- cgit v1.2.3 From 2e8016c80d450a7d1126b481f1262b7cd9dec24d Mon Sep 17 00:00:00 2001 From: zsfelfoldi Date: Tue, 26 May 2015 14:39:13 +0200 Subject: fixed initial base price bug --- eth/gasprice.go | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'eth') diff --git a/eth/gasprice.go b/eth/gasprice.go index f5b241e2c..6f46559a2 100644 --- a/eth/gasprice.go +++ b/eth/gasprice.go @@ -159,6 +159,10 @@ func (self *GasPriceOracle) SuggestPrice() *big.Int { base := self.lastBase self.lastBaseMutex.Unlock() + if base == nil { + base = self.eth.GpoMinGasPrice + } + baseCorr := new(big.Int).Mul(base, big.NewInt(int64(100+self.eth.GpobaseCorrectionFactor))) baseCorr.Div(baseCorr, big.NewInt(100)) -- cgit v1.2.3 From 6e212bdc6d1319c84c305c446bbf1ba9ddfdc66d Mon Sep 17 00:00:00 2001 From: zsfelfoldi Date: Tue, 26 May 2015 15:15:54 +0200 Subject: fallback for uninitialized GPO config values --- eth/gasprice.go | 3 +++ 1 file changed, 3 insertions(+) (limited to 'eth') diff --git a/eth/gasprice.go b/eth/gasprice.go index 6f46559a2..12e76fc2c 100644 --- a/eth/gasprice.go +++ b/eth/gasprice.go @@ -162,6 +162,9 @@ func (self *GasPriceOracle) SuggestPrice() *big.Int { if base == nil { base = self.eth.GpoMinGasPrice } + if base == nil { + return big.NewInt(10000000000000) // apparently MinGasPrice is not initialized during some tests + } baseCorr := new(big.Int).Mul(base, big.NewInt(int64(100+self.eth.GpobaseCorrectionFactor))) baseCorr.Div(baseCorr, big.NewInt(100)) -- cgit v1.2.3 From a977cecbe49e9cf049785a437581a767b079570c Mon Sep 17 00:00:00 2001 From: zsfelfoldi Date: Wed, 27 May 2015 12:39:59 +0200 Subject: fixed gas price corr. factor --- eth/gasprice.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'eth') diff --git a/eth/gasprice.go b/eth/gasprice.go index 12e76fc2c..cd5293691 100644 --- a/eth/gasprice.go +++ b/eth/gasprice.go @@ -166,7 +166,7 @@ func (self *GasPriceOracle) SuggestPrice() *big.Int { return big.NewInt(10000000000000) // apparently MinGasPrice is not initialized during some tests } - baseCorr := new(big.Int).Mul(base, big.NewInt(int64(100+self.eth.GpobaseCorrectionFactor))) + baseCorr := new(big.Int).Mul(base, big.NewInt(int64(self.eth.GpobaseCorrectionFactor))) baseCorr.Div(baseCorr, big.NewInt(100)) if baseCorr.Cmp(self.eth.GpoMinGasPrice) < 0 { -- cgit v1.2.3