Fix eth_estimateGas and simulated txs (#142)
This commit is contained in:
parent
3ad2bb1de1
commit
42227a1b8c
@ -374,7 +374,10 @@ type account struct {
|
||||
// DoCall performs a simulated call operation through the evm
|
||||
func (e *PublicEthAPI) doCall(args CallArgs, blockNr rpc.BlockNumber, globalGasCap *big.Int) (sdk.Result, error) {
|
||||
// Set height for historical queries
|
||||
ctx := e.cliCtx.WithHeight(blockNr.Int64())
|
||||
ctx := e.cliCtx
|
||||
if blockNr.Int64() != 0 {
|
||||
ctx = e.cliCtx.WithHeight(blockNr.Int64())
|
||||
}
|
||||
|
||||
// Set sender address or use a default if none specified
|
||||
var addr common.Address
|
||||
@ -452,13 +455,14 @@ func (e *PublicEthAPI) doCall(args CallArgs, blockNr rpc.BlockNumber, globalGasC
|
||||
}
|
||||
|
||||
// EstimateGas estimates gas usage for the given smart contract call.
|
||||
func (e *PublicEthAPI) EstimateGas(args CallArgs, blockNr rpc.BlockNumber) (hexutil.Uint64, error) {
|
||||
result, err := e.doCall(args, blockNr, big.NewInt(emint.DefaultRPCGasLimit))
|
||||
func (e *PublicEthAPI) EstimateGas(args CallArgs) (hexutil.Uint64, error) {
|
||||
result, err := e.doCall(args, 0, big.NewInt(emint.DefaultRPCGasLimit))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return hexutil.Uint64(result.GasUsed), nil
|
||||
// TODO: change 1000 buffer for more accurate buffer (must be at least 1 to not run OOG)
|
||||
return hexutil.Uint64(result.GasUsed + 1000), nil
|
||||
}
|
||||
|
||||
// GetBlockByHash returns the block identified by hash.
|
||||
@ -916,7 +920,7 @@ func (e *PublicEthAPI) GenerateFromArgs(args params.SendTxArgs) (msg *types.Ethe
|
||||
Value: args.Value,
|
||||
Data: args.Data,
|
||||
}
|
||||
g, _ := e.EstimateGas(callArgs, rpc.BlockNumber(e.cliCtx.Height))
|
||||
g, _ := e.EstimateGas(callArgs)
|
||||
gasLimit = uint64(g)
|
||||
} else {
|
||||
gasLimit = (uint64)(*args.Gas)
|
||||
|
@ -44,13 +44,19 @@ func (st StateTransition) TransitionCSDB(ctx sdk.Context) (*big.Int, sdk.Result)
|
||||
// This gas limit the the transaction gas limit with intrinsic gas subtracted
|
||||
gasLimit := st.GasLimit - ctx.GasMeter().GasConsumed()
|
||||
|
||||
var snapshot int
|
||||
csdb := st.Csdb
|
||||
if st.Simulate {
|
||||
// gasLimit is set here because stdTxs incur gaskv charges in the ante handler, but for eth_call
|
||||
// the cost needs to be the same as an Ethereum transaction sent through the web3 API
|
||||
consumedGas := ctx.GasMeter().GasConsumed()
|
||||
gasLimit = st.GasLimit - cost
|
||||
if consumedGas < cost {
|
||||
// If Cosmos standard tx ante handler cost is less than EVM intrinsic cost
|
||||
// gas must be consumed to match to accurately simulate an Ethereum transaction
|
||||
ctx.GasMeter().ConsumeGas(cost-consumedGas, "Intrinsic gas match")
|
||||
}
|
||||
|
||||
snapshot = st.Csdb.Snapshot()
|
||||
csdb = st.Csdb.Copy()
|
||||
}
|
||||
|
||||
// Create context for evm
|
||||
@ -70,7 +76,7 @@ func (st StateTransition) TransitionCSDB(ctx sdk.Context) (*big.Int, sdk.Result)
|
||||
evmGasMeter := sdk.NewInfiniteGasMeter()
|
||||
|
||||
vmenv := vm.NewEVM(
|
||||
context, st.Csdb.WithContext(ctx.WithGasMeter(evmGasMeter)),
|
||||
context, csdb.WithContext(ctx.WithGasMeter(evmGasMeter)),
|
||||
GenerateChainConfig(st.ChainID), vm.Config{},
|
||||
)
|
||||
|
||||
@ -86,15 +92,15 @@ func (st StateTransition) TransitionCSDB(ctx sdk.Context) (*big.Int, sdk.Result)
|
||||
ret, addr, leftOverGas, vmerr = vmenv.Create(senderRef, st.Payload, gasLimit, st.Amount)
|
||||
} else {
|
||||
// Increment the nonce for the next transaction
|
||||
st.Csdb.SetNonce(st.Sender, st.Csdb.GetNonce(st.Sender)+1)
|
||||
csdb.SetNonce(st.Sender, csdb.GetNonce(st.Sender)+1)
|
||||
ret, leftOverGas, vmerr = vmenv.Call(senderRef, *st.Recipient, st.Payload, gasLimit, st.Amount)
|
||||
}
|
||||
|
||||
// Generate bloom filter to be saved in tx receipt data
|
||||
bloomInt := big.NewInt(0)
|
||||
var bloomFilter ethtypes.Bloom
|
||||
if st.THash != nil {
|
||||
logs := st.Csdb.GetLogs(*st.THash)
|
||||
if st.THash != nil && !st.Simulate {
|
||||
logs := csdb.GetLogs(*st.THash)
|
||||
bloomInt = ethtypes.LogsBloom(logs)
|
||||
bloomFilter = ethtypes.BytesToBloom(bloomInt.Bytes())
|
||||
}
|
||||
@ -114,13 +120,11 @@ func (st StateTransition) TransitionCSDB(ctx sdk.Context) (*big.Int, sdk.Result)
|
||||
return nil, res
|
||||
}
|
||||
|
||||
if st.Simulate {
|
||||
st.Csdb.RevertToSnapshot(snapshot)
|
||||
}
|
||||
|
||||
// TODO: Refund unused gas here, if intended in future
|
||||
|
||||
st.Csdb.Finalise(true) // Change to depend on config
|
||||
if !st.Simulate {
|
||||
// Finalise state if not a simulated transaction
|
||||
st.Csdb.Finalise(true) // Change to depend on config
|
||||
}
|
||||
|
||||
// Consume gas from evm execution
|
||||
// Out of gas check does not need to be done here since it is done within the EVM execution
|
||||
|
@ -571,7 +571,7 @@ func (csdb *CommitStateDB) CreateAccount(addr ethcmn.Address) {
|
||||
// Copy creates a deep, independent copy of the state.
|
||||
//
|
||||
// NOTE: Snapshots of the copied state cannot be applied to the copy.
|
||||
func (csdb *CommitStateDB) Copy() ethvm.StateDB {
|
||||
func (csdb *CommitStateDB) Copy() *CommitStateDB {
|
||||
csdb.lock.Lock()
|
||||
defer csdb.lock.Unlock()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user