From d096b3a674309ca730bffaa50303b4bec1212027 Mon Sep 17 00:00:00 2001 From: Janet Liang Date: Mon, 12 Oct 2020 18:24:45 -0700 Subject: [PATCH] [rpc] Add function to convert CallArgs to EVM message --- rosetta/services/construction_check.go | 3 +- rpc/contract.go | 45 ++------------------------ rpc/transaction.go | 2 +- rpc/types.go | 42 ++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 45 deletions(-) diff --git a/rosetta/services/construction_check.go b/rosetta/services/construction_check.go index e38eb6a36..b27ccb3a5 100644 --- a/rosetta/services/construction_check.go +++ b/rosetta/services/construction_check.go @@ -12,7 +12,6 @@ import ( ethRpc "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" - "github.com/harmony-one/harmony/core/vm" "github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/rosetta/common" "github.com/harmony-one/harmony/rpc" @@ -252,7 +251,7 @@ func (s *ConstructAPI) ConstructionMetadata( callArgs.To = &contractAddress } evmExe, err := rpc.DoEVMCall( - ctx, s.hmy, callArgs, ethRpc.LatestBlockNumber, vm.Config{}, rpc.CallTimeout, s.hmy.RPCGasCap, + ctx, s.hmy, callArgs, ethRpc.LatestBlockNumber, rpc.CallTimeout, ) if err != nil { return nil, common.NewError(common.CatchAllError, map[string]interface{}{ diff --git a/rpc/contract.go b/rpc/contract.go index 43d9fb6df..9c2c56cc3 100644 --- a/rpc/contract.go +++ b/rpc/contract.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "math" - "math/big" "time" "github.com/ethereum/go-ethereum/common" @@ -12,8 +11,6 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/harmony-one/harmony/common/denominations" "github.com/harmony-one/harmony/core" - "github.com/harmony-one/harmony/core/types" - "github.com/harmony-one/harmony/core/vm" "github.com/harmony-one/harmony/hmy" hmyCommon "github.com/harmony-one/harmony/internal/common" "github.com/harmony-one/harmony/internal/utils" @@ -50,7 +47,7 @@ func (s *PublicContractService) Call( blockNum := blockNumber.EthBlockNumber() // Execute call - result, err := DoEVMCall(ctx, s.hmy, args, blockNum, vm.Config{}, CallTimeout, s.hmy.RPCGasCap) + result, err := DoEVMCall(ctx, s.hmy, args, blockNum, CallTimeout) if err != nil { return nil, err } @@ -102,7 +99,7 @@ func (s *PublicContractService) GetStorageAt( // DoEVMCall executes an EVM call func DoEVMCall( ctx context.Context, hmy *hmy.Harmony, args CallArgs, blockNum rpc.BlockNumber, - vmCfg vm.Config, timeout time.Duration, globalGasCap *big.Int, + timeout time.Duration, ) (core.ExecutionResult, error) { defer func(start time.Time) { utils.Logger().Debug(). @@ -116,44 +113,8 @@ func DoEVMCall( return core.ExecutionResult{}, err } - // Set sender address or use a default if none specified - var addr common.Address - if args.From == nil { - // Any address does not affect the logic of this call. - addr = common.HexToAddress(defaultFromAddress) - } else { - addr = *args.From - } - - // Set default gas & gas price if none were set - gas := uint64(math.MaxUint64 / 2) - if args.Gas != nil { - gas = uint64(*args.Gas) - } - if globalGasCap != nil && globalGasCap.Uint64() < gas { - utils.Logger().Warn(). - Uint64("requested", gas). - Uint64("cap", globalGasCap.Uint64()). - Msg("Caller gas above allowance, capping") - gas = globalGasCap.Uint64() - } - gasPrice := new(big.Int).SetUint64(defaultGasPrice) - if args.GasPrice != nil { - gasPrice = args.GasPrice.ToInt() - } - - // Set value & data - value := new(big.Int) - if args.Value != nil { - value = args.Value.ToInt() - } - var data []byte - if args.Data != nil { - data = *args.Data - } - // Create new call message - msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, data, false) + msg := args.ToMessage(hmy.RPCGasCap) // Setup context so it may be cancelled the call has completed // or, in case of unmetered gas, setup a context with a timeout. diff --git a/rpc/transaction.go b/rpc/transaction.go index f95e6589b..1d46e16ed 100644 --- a/rpc/transaction.go +++ b/rpc/transaction.go @@ -725,7 +725,7 @@ func EstimateGas( executable := func(gas uint64) bool { args.Gas = (*hexutil.Uint64)(&gas) - result, err := DoEVMCall(ctx, hmy, args, blockNum, vm.Config{}, 0, big.NewInt(int64(max))) + result, err := DoEVMCall(ctx, hmy, args, blockNum, 0) if err != nil || result.VMErr == vm.ErrCodeStoreOutOfGas || result.VMErr == vm.ErrOutOfGas { return false } diff --git a/rpc/types.go b/rpc/types.go index e353a8267..fd71c1555 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -11,10 +11,12 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" "github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/core/types" + "github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/numeric" "github.com/harmony-one/harmony/shard" ) @@ -29,6 +31,46 @@ type CallArgs struct { Data *hexutil.Bytes `json:"data"` } +// Adapted from go-ethereum/internal/ethapi/api.go +// ToMessage converts CallArgs to the Message type used by the core evm +func (args *CallArgs) ToMessage(globalGasCap *big.Int) types.Message { + // Set sender address or use zero address if none specified. + var addr common.Address + if args.From != nil { + addr = *args.From + } + + // Set default gas & gas price if none were set + gas := uint64(math.MaxUint64 / 2) + if args.Gas != nil { + gas = uint64(*args.Gas) + } + if globalGasCap != nil && globalGasCap.Uint64() < gas { + utils.Logger().Warn(). + Uint64("requested", gas). + Uint64("cap", globalGasCap.Uint64()). + Msg("Caller gas above allowance, capping") + gas = globalGasCap.Uint64() + } + gasPrice := new(big.Int) + if args.GasPrice != nil { + gasPrice = args.GasPrice.ToInt() + } + + value := new(big.Int) + if args.Value != nil { + value = args.Value.ToInt() + } + + var data []byte + if args.Data != nil { + data = []byte(*args.Data) + } + + msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, data, false) + return msg +} + // StakingNetworkInfo returns global staking info. type StakingNetworkInfo struct { TotalSupply numeric.Dec `json:"total-supply"`