Merge pull request #990 from zsfelfoldi/gasprice
eth: add GasPriceOracle
This commit is contained in:
commit
f2a2164184
@ -256,6 +256,12 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
|
|||||||
utils.PProfEanbledFlag,
|
utils.PProfEanbledFlag,
|
||||||
utils.PProfPortFlag,
|
utils.PProfPortFlag,
|
||||||
utils.SolcPathFlag,
|
utils.SolcPathFlag,
|
||||||
|
utils.GpoMinGasPriceFlag,
|
||||||
|
utils.GpoMaxGasPriceFlag,
|
||||||
|
utils.GpoFullBlockRatioFlag,
|
||||||
|
utils.GpobaseStepDownFlag,
|
||||||
|
utils.GpobaseStepUpFlag,
|
||||||
|
utils.GpobaseCorrectionFactorFlag,
|
||||||
}
|
}
|
||||||
app.Before = func(ctx *cli.Context) error {
|
app.Before = func(ctx *cli.Context) error {
|
||||||
utils.SetupLogger(ctx)
|
utils.SetupLogger(ctx)
|
||||||
|
@ -23,10 +23,10 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
"github.com/ethereum/go-ethereum/p2p/nat"
|
"github.com/ethereum/go-ethereum/p2p/nat"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/xeth"
|
|
||||||
"github.com/ethereum/go-ethereum/rpc/api"
|
"github.com/ethereum/go-ethereum/rpc/api"
|
||||||
"github.com/ethereum/go-ethereum/rpc/comms"
|
|
||||||
"github.com/ethereum/go-ethereum/rpc/codec"
|
"github.com/ethereum/go-ethereum/rpc/codec"
|
||||||
|
"github.com/ethereum/go-ethereum/rpc/comms"
|
||||||
|
"github.com/ethereum/go-ethereum/xeth"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -132,7 +132,7 @@ var (
|
|||||||
GasPriceFlag = cli.StringFlag{
|
GasPriceFlag = cli.StringFlag{
|
||||||
Name: "gasprice",
|
Name: "gasprice",
|
||||||
Usage: "Sets the minimal gasprice when mining transactions",
|
Usage: "Sets the minimal gasprice when mining transactions",
|
||||||
Value: new(big.Int).Mul(big.NewInt(10), common.Szabo).String(),
|
Value: new(big.Int).Mul(big.NewInt(1), common.Szabo).String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
UnlockedAccountFlag = cli.StringFlag{
|
UnlockedAccountFlag = cli.StringFlag{
|
||||||
@ -276,6 +276,36 @@ var (
|
|||||||
Usage: "solidity compiler to be used",
|
Usage: "solidity compiler to be used",
|
||||||
Value: "solc",
|
Value: "solc",
|
||||||
}
|
}
|
||||||
|
GpoMinGasPriceFlag = cli.StringFlag{
|
||||||
|
Name: "gpomin",
|
||||||
|
Usage: "Minimum suggested gas price",
|
||||||
|
Value: new(big.Int).Mul(big.NewInt(1), common.Szabo).String(),
|
||||||
|
}
|
||||||
|
GpoMaxGasPriceFlag = cli.StringFlag{
|
||||||
|
Name: "gpomax",
|
||||||
|
Usage: "Maximum suggested gas price",
|
||||||
|
Value: new(big.Int).Mul(big.NewInt(100), common.Szabo).String(),
|
||||||
|
}
|
||||||
|
GpoFullBlockRatioFlag = cli.IntFlag{
|
||||||
|
Name: "gpofull",
|
||||||
|
Usage: "Full block threshold for gas price calculation (%)",
|
||||||
|
Value: 80,
|
||||||
|
}
|
||||||
|
GpobaseStepDownFlag = cli.IntFlag{
|
||||||
|
Name: "gpobasedown",
|
||||||
|
Usage: "Suggested gas price base step down ratio (1/1000)",
|
||||||
|
Value: 10,
|
||||||
|
}
|
||||||
|
GpobaseStepUpFlag = cli.IntFlag{
|
||||||
|
Name: "gpobaseup",
|
||||||
|
Usage: "Suggested gas price base step up ratio (1/1000)",
|
||||||
|
Value: 100,
|
||||||
|
}
|
||||||
|
GpobaseCorrectionFactorFlag = cli.IntFlag{
|
||||||
|
Name: "gpobasecf",
|
||||||
|
Usage: "Suggested gas price base correction factor (%)",
|
||||||
|
Value: 110,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// MakeNAT creates a port mapper from set command line flags.
|
// MakeNAT creates a port mapper from set command line flags.
|
||||||
@ -338,6 +368,12 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
|
|||||||
Dial: true,
|
Dial: true,
|
||||||
BootNodes: ctx.GlobalString(BootnodesFlag.Name),
|
BootNodes: ctx.GlobalString(BootnodesFlag.Name),
|
||||||
GasPrice: common.String2Big(ctx.GlobalString(GasPriceFlag.Name)),
|
GasPrice: common.String2Big(ctx.GlobalString(GasPriceFlag.Name)),
|
||||||
|
GpoMinGasPrice: common.String2Big(ctx.GlobalString(GpoMinGasPriceFlag.Name)),
|
||||||
|
GpoMaxGasPrice: common.String2Big(ctx.GlobalString(GpoMaxGasPriceFlag.Name)),
|
||||||
|
GpoFullBlockRatio: ctx.GlobalInt(GpoFullBlockRatioFlag.Name),
|
||||||
|
GpobaseStepDown: ctx.GlobalInt(GpobaseStepDownFlag.Name),
|
||||||
|
GpobaseStepUp: ctx.GlobalInt(GpobaseStepUpFlag.Name),
|
||||||
|
GpobaseCorrectionFactor: ctx.GlobalInt(GpobaseCorrectionFactorFlag.Name),
|
||||||
SolcPath: ctx.GlobalString(SolcPathFlag.Name),
|
SolcPath: ctx.GlobalString(SolcPathFlag.Name),
|
||||||
AutoDAG: ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name),
|
AutoDAG: ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name),
|
||||||
}
|
}
|
||||||
|
@ -260,6 +260,12 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
|
|||||||
putTx(sm.extraDb, tx, block, uint64(i))
|
putTx(sm.extraDb, tx, block, uint64(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
receiptsRlp := receipts.RlpEncode()
|
||||||
|
/*if len(receipts) > 0 {
|
||||||
|
glog.V(logger.Info).Infof("Saving %v receipts, rlp len is %v\n", len(receipts), len(receiptsRlp))
|
||||||
|
}*/
|
||||||
|
sm.extraDb.Put(append(receiptsPre, block.Hash().Bytes()...), receiptsRlp)
|
||||||
|
|
||||||
return state.Logs(), nil
|
return state.Logs(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,6 +410,8 @@ func getBlockReceipts(db common.Database, bhash common.Hash) (receipts types.Rec
|
|||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = rlp.DecodeBytes(rdata, &receipts)
|
err = rlp.DecodeBytes(rdata, &receipts)
|
||||||
|
} else {
|
||||||
|
glog.V(logger.Detail).Infof("getBlockReceipts error %v\n", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,13 @@ type Config struct {
|
|||||||
AccountManager *accounts.Manager
|
AccountManager *accounts.Manager
|
||||||
SolcPath string
|
SolcPath string
|
||||||
|
|
||||||
|
GpoMinGasPrice *big.Int
|
||||||
|
GpoMaxGasPrice *big.Int
|
||||||
|
GpoFullBlockRatio int
|
||||||
|
GpobaseStepDown int
|
||||||
|
GpobaseStepUp int
|
||||||
|
GpobaseCorrectionFactor int
|
||||||
|
|
||||||
// NewDB is used to create databases.
|
// NewDB is used to create databases.
|
||||||
// If nil, the default is to create leveldb databases on disk.
|
// If nil, the default is to create leveldb databases on disk.
|
||||||
NewDB func(path string) (common.Database, error)
|
NewDB func(path string) (common.Database, error)
|
||||||
@ -196,6 +203,13 @@ type Ethereum struct {
|
|||||||
SolcPath string
|
SolcPath string
|
||||||
solc *compiler.Solidity
|
solc *compiler.Solidity
|
||||||
|
|
||||||
|
GpoMinGasPrice *big.Int
|
||||||
|
GpoMaxGasPrice *big.Int
|
||||||
|
GpoFullBlockRatio int
|
||||||
|
GpobaseStepDown int
|
||||||
|
GpobaseStepUp int
|
||||||
|
GpobaseCorrectionFactor int
|
||||||
|
|
||||||
net *p2p.Server
|
net *p2p.Server
|
||||||
eventMux *event.TypeMux
|
eventMux *event.TypeMux
|
||||||
miner *miner.Miner
|
miner *miner.Miner
|
||||||
@ -281,6 +295,12 @@ func New(config *Config) (*Ethereum, error) {
|
|||||||
MinerThreads: config.MinerThreads,
|
MinerThreads: config.MinerThreads,
|
||||||
SolcPath: config.SolcPath,
|
SolcPath: config.SolcPath,
|
||||||
AutoDAG: config.AutoDAG,
|
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()
|
eth.pow = ethash.New()
|
||||||
|
181
eth/gasprice.go
Normal file
181
eth/gasprice.go
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
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()
|
||||||
|
|
||||||
|
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(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
|
||||||
|
}
|
@ -59,7 +59,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
|
|||||||
case "eth_mining":
|
case "eth_mining":
|
||||||
*reply = api.xeth().IsMining()
|
*reply = api.xeth().IsMining()
|
||||||
case "eth_gasPrice":
|
case "eth_gasPrice":
|
||||||
v := xeth.DefaultGasPrice()
|
v := api.xeth().DefaultGasPrice()
|
||||||
*reply = newHexNum(v.Bytes())
|
*reply = newHexNum(v.Bytes())
|
||||||
case "eth_accounts":
|
case "eth_accounts":
|
||||||
*reply = api.xeth().Accounts()
|
*reply = api.xeth().Accounts()
|
||||||
|
@ -139,7 +139,7 @@ func (self *ethApi) IsMining(req *shared.Request) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *ethApi) GasPrice(req *shared.Request) (interface{}, error) {
|
func (self *ethApi) GasPrice(req *shared.Request) (interface{}, error) {
|
||||||
return newHexNum(xeth.DefaultGasPrice().Bytes()), nil
|
return newHexNum(self.xeth.DefaultGasPrice().Bytes()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ethApi) GetStorage(req *shared.Request) (interface{}, error) {
|
func (self *ethApi) GetStorage(req *shared.Request) (interface{}, error) {
|
||||||
|
27
xeth/xeth.go
27
xeth/xeth.go
@ -40,7 +40,13 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func DefaultGas() *big.Int { return new(big.Int).Set(defaultGas) }
|
func DefaultGas() *big.Int { return new(big.Int).Set(defaultGas) }
|
||||||
func DefaultGasPrice() *big.Int { return new(big.Int).Set(defaultGasPrice) }
|
|
||||||
|
func (self *XEth) DefaultGasPrice() *big.Int {
|
||||||
|
if self.gpo == nil {
|
||||||
|
self.gpo = eth.NewGasPriceOracle(self.backend)
|
||||||
|
}
|
||||||
|
return self.gpo.SuggestPrice()
|
||||||
|
}
|
||||||
|
|
||||||
type XEth struct {
|
type XEth struct {
|
||||||
backend *eth.Ethereum
|
backend *eth.Ethereum
|
||||||
@ -68,6 +74,8 @@ type XEth struct {
|
|||||||
// register map[string][]*interface{} // TODO improve return type
|
// register map[string][]*interface{} // TODO improve return type
|
||||||
|
|
||||||
agent *miner.RemoteAgent
|
agent *miner.RemoteAgent
|
||||||
|
|
||||||
|
gpo *eth.GasPriceOracle
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTest(eth *eth.Ethereum, frontend Frontend) *XEth {
|
func NewTest(eth *eth.Ethereum, frontend Frontend) *XEth {
|
||||||
@ -80,22 +88,22 @@ func NewTest(eth *eth.Ethereum, frontend Frontend) *XEth {
|
|||||||
// New creates an XEth that uses the given frontend.
|
// New creates an XEth that uses the given frontend.
|
||||||
// If a nil Frontend is provided, a default frontend which
|
// If a nil Frontend is provided, a default frontend which
|
||||||
// confirms all transactions will be used.
|
// confirms all transactions will be used.
|
||||||
func New(eth *eth.Ethereum, frontend Frontend) *XEth {
|
func New(ethereum *eth.Ethereum, frontend Frontend) *XEth {
|
||||||
xeth := &XEth{
|
xeth := &XEth{
|
||||||
backend: eth,
|
backend: ethereum,
|
||||||
frontend: frontend,
|
frontend: frontend,
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
filterManager: filter.NewFilterManager(eth.EventMux()),
|
filterManager: filter.NewFilterManager(ethereum.EventMux()),
|
||||||
logQueue: make(map[int]*logQueue),
|
logQueue: make(map[int]*logQueue),
|
||||||
blockQueue: make(map[int]*hashQueue),
|
blockQueue: make(map[int]*hashQueue),
|
||||||
transactionQueue: make(map[int]*hashQueue),
|
transactionQueue: make(map[int]*hashQueue),
|
||||||
messages: make(map[int]*whisperFilter),
|
messages: make(map[int]*whisperFilter),
|
||||||
agent: miner.NewRemoteAgent(),
|
agent: miner.NewRemoteAgent(),
|
||||||
}
|
}
|
||||||
if eth.Whisper() != nil {
|
if ethereum.Whisper() != nil {
|
||||||
xeth.whisper = NewWhisper(eth.Whisper())
|
xeth.whisper = NewWhisper(ethereum.Whisper())
|
||||||
}
|
}
|
||||||
eth.Miner().Register(xeth.agent)
|
ethereum.Miner().Register(xeth.agent)
|
||||||
if frontend == nil {
|
if frontend == nil {
|
||||||
xeth.frontend = dummyFrontend{}
|
xeth.frontend = dummyFrontend{}
|
||||||
}
|
}
|
||||||
@ -227,6 +235,7 @@ func (self *XEth) WithState(statedb *state.StateDB) *XEth {
|
|||||||
xeth := &XEth{
|
xeth := &XEth{
|
||||||
backend: self.backend,
|
backend: self.backend,
|
||||||
frontend: self.frontend,
|
frontend: self.frontend,
|
||||||
|
gpo: self.gpo,
|
||||||
}
|
}
|
||||||
|
|
||||||
xeth.state = NewState(xeth, statedb)
|
xeth.state = NewState(xeth, statedb)
|
||||||
@ -829,7 +838,7 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st
|
|||||||
}
|
}
|
||||||
|
|
||||||
if msg.gasPrice.Cmp(big.NewInt(0)) == 0 {
|
if msg.gasPrice.Cmp(big.NewInt(0)) == 0 {
|
||||||
msg.gasPrice = DefaultGasPrice()
|
msg.gasPrice = self.DefaultGasPrice()
|
||||||
}
|
}
|
||||||
|
|
||||||
block := self.CurrentBlock()
|
block := self.CurrentBlock()
|
||||||
@ -898,7 +907,7 @@ func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceS
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(gasPriceStr) == 0 {
|
if len(gasPriceStr) == 0 {
|
||||||
price = DefaultGasPrice()
|
price = self.DefaultGasPrice()
|
||||||
} else {
|
} else {
|
||||||
price = common.Big(gasPriceStr)
|
price = common.Big(gasPriceStr)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user