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