mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
Refactor call and estimateGas to use ethapi struct type
This commit is contained in:
parent
8790e18ae7
commit
ba6f531027
4 changed files with 85 additions and 63 deletions
|
|
@ -272,6 +272,21 @@ func (b Uint64) String() string {
|
||||||
return EncodeUint64(uint64(b))
|
return EncodeUint64(uint64(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b Uint64) ImplementsGraphQLType(name string) bool { return name == "Long" }
|
||||||
|
|
||||||
|
func (b *Uint64) UnmarshalGraphQL(input interface{}) error {
|
||||||
|
var err error
|
||||||
|
switch input := input.(type) {
|
||||||
|
case string:
|
||||||
|
return b.UnmarshalText([]byte(input))
|
||||||
|
case int32:
|
||||||
|
*b = Uint64(input)
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("Unexpected type for BigInt: %v", input)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Uint marshals/unmarshals as a JSON string with 0x prefix.
|
// Uint marshals/unmarshals as a JSON string with 0x prefix.
|
||||||
// The zero value marshals as "0x0".
|
// The zero value marshals as "0x0".
|
||||||
type Uint uint
|
type Uint uint
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,19 @@ func (a Address) Value() (driver.Value, error) {
|
||||||
return a[:], nil
|
return a[:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a Address) ImplementsGraphQLType(name string) bool { return name == "Address" }
|
||||||
|
|
||||||
|
func (a *Address) UnmarshalGraphQL(input interface{}) error {
|
||||||
|
var err error
|
||||||
|
switch input := input.(type) {
|
||||||
|
case string:
|
||||||
|
*a = HexToAddress(input)
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("Unexpected type for Hash: %v", input)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// UnprefixedAddress allows marshaling an Address without 0x prefix.
|
// UnprefixedAddress allows marshaling an Address without 0x prefix.
|
||||||
type UnprefixedAddress Address
|
type UnprefixedAddress Address
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -848,13 +848,12 @@ func (r *Resolver) SendRawTransaction(ctx context.Context, args struct{ Data hex
|
||||||
}
|
}
|
||||||
|
|
||||||
type CallData struct {
|
type CallData struct {
|
||||||
From *Address
|
From *Address
|
||||||
To *Address
|
To *Address
|
||||||
Gas *int32
|
Gas *hexutil.Uint64
|
||||||
GasPrice *hexutil.Big
|
GasPrice *hexutil.Big
|
||||||
Value *hexutil.Big
|
Value *hexutil.Big
|
||||||
Data *hexutil.Bytes
|
Data *hexutil.Bytes
|
||||||
BlockNumber *int32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CallResult struct {
|
type CallResult struct {
|
||||||
|
|
@ -875,45 +874,21 @@ func (c *CallResult) Status() int32 {
|
||||||
return c.status
|
return c.status
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertCallData(data CallData) (ethapi.CallArgs, rpc.BlockNumber) {
|
func (r *Resolver) Call(ctx context.Context, args struct {
|
||||||
callArgs := ethapi.CallArgs{}
|
Data ethapi.CallArgs
|
||||||
if data.From != nil {
|
BlockNumber *int32
|
||||||
callArgs.From = data.From.Address
|
}) (*CallResult, error) {
|
||||||
}
|
|
||||||
if data.To != nil {
|
|
||||||
addr := data.To.Address
|
|
||||||
callArgs.To = &addr
|
|
||||||
}
|
|
||||||
if data.Gas != nil {
|
|
||||||
callArgs.Gas = hexutil.Uint64(*data.Gas)
|
|
||||||
}
|
|
||||||
if data.GasPrice != nil {
|
|
||||||
callArgs.GasPrice = *data.GasPrice
|
|
||||||
}
|
|
||||||
if data.Value != nil {
|
|
||||||
callArgs.Value = *data.Value
|
|
||||||
}
|
|
||||||
if data.Data != nil {
|
|
||||||
callArgs.Data = *data.Data
|
|
||||||
}
|
|
||||||
|
|
||||||
blockNumber := rpc.LatestBlockNumber
|
|
||||||
if data.BlockNumber != nil {
|
|
||||||
blockNumber = rpc.BlockNumber(*data.BlockNumber)
|
|
||||||
}
|
|
||||||
|
|
||||||
return callArgs, blockNumber
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resolver) Call(ctx context.Context, args struct{ Data CallData }) (*CallResult, error) {
|
|
||||||
be, err := getBackend(r.node)
|
be, err := getBackend(r.node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
callArgs, blockNumber := convertCallData(args.Data)
|
blockNumber := rpc.LatestBlockNumber
|
||||||
|
if args.BlockNumber != nil {
|
||||||
|
blockNumber = rpc.BlockNumber(*args.BlockNumber)
|
||||||
|
}
|
||||||
|
|
||||||
result, gas, failed, err := ethapi.DoCall(ctx, be, callArgs, blockNumber, vm.Config{}, 5*time.Second)
|
result, gas, failed, err := ethapi.DoCall(ctx, be, args.Data, blockNumber, vm.Config{}, 5*time.Second)
|
||||||
status := int32(1)
|
status := int32(1)
|
||||||
if failed {
|
if failed {
|
||||||
status = 0
|
status = 0
|
||||||
|
|
@ -925,15 +900,21 @@ func (r *Resolver) Call(ctx context.Context, args struct{ Data CallData }) (*Cal
|
||||||
}, err
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resolver) EstimateGas(ctx context.Context, args struct{ Data CallData }) (int32, error) {
|
func (r *Resolver) EstimateGas(ctx context.Context, args struct {
|
||||||
|
Data ethapi.CallArgs
|
||||||
|
BlockNumber *int32
|
||||||
|
}) (int32, error) {
|
||||||
be, err := getBackend(r.node)
|
be, err := getBackend(r.node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
callArgs, blockNumber := convertCallData(args.Data)
|
blockNumber := rpc.LatestBlockNumber
|
||||||
|
if args.BlockNumber != nil {
|
||||||
|
blockNumber = rpc.BlockNumber(*args.BlockNumber)
|
||||||
|
}
|
||||||
|
|
||||||
gas, err := ethapi.DoEstimateGas(ctx, be, callArgs, blockNumber)
|
gas, err := ethapi.DoEstimateGas(ctx, be, args.Data, blockNumber)
|
||||||
return int32(gas), err
|
return int32(gas), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -945,6 +926,7 @@ func NewHandler(n *node.Node) (http.Handler, error) {
|
||||||
scalar Address
|
scalar Address
|
||||||
scalar Bytes
|
scalar Bytes
|
||||||
scalar BigInt
|
scalar BigInt
|
||||||
|
scalar Long
|
||||||
|
|
||||||
schema {
|
schema {
|
||||||
query: Query
|
query: Query
|
||||||
|
|
@ -1015,11 +997,10 @@ func NewHandler(n *node.Node) (http.Handler, error) {
|
||||||
input CallData {
|
input CallData {
|
||||||
from: Address
|
from: Address
|
||||||
to: Address
|
to: Address
|
||||||
gas: Int
|
gas: Long
|
||||||
gasPrice: BigInt
|
gasPrice: BigInt
|
||||||
value: BigInt
|
value: BigInt
|
||||||
data: Bytes
|
data: Bytes
|
||||||
blockNumber: Int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CallResult {
|
type CallResult {
|
||||||
|
|
@ -1033,8 +1014,8 @@ func NewHandler(n *node.Node) (http.Handler, error) {
|
||||||
block(number: Int, hash: Bytes32): Block
|
block(number: Int, hash: Bytes32): Block
|
||||||
blocks(from: Int!, to: Int): [Block!]!
|
blocks(from: Int!, to: Int): [Block!]!
|
||||||
transaction(hash: Bytes32!): Transaction
|
transaction(hash: Bytes32!): Transaction
|
||||||
call(data: CallData!): CallResult
|
call(data: CallData!, blockNumber: Int): CallResult
|
||||||
estimateGas(data: CallData!): Int!
|
estimateGas(data: CallData!, blockNumber: Int): Int!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
|
|
|
||||||
|
|
@ -609,12 +609,12 @@ func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.A
|
||||||
|
|
||||||
// CallArgs represents the arguments for a call.
|
// CallArgs represents the arguments for a call.
|
||||||
type CallArgs struct {
|
type CallArgs struct {
|
||||||
From common.Address `json:"from"`
|
From *common.Address `json:"from"`
|
||||||
To *common.Address `json:"to"`
|
To *common.Address `json:"to"`
|
||||||
Gas hexutil.Uint64 `json:"gas"`
|
Gas *hexutil.Uint64 `json:"gas"`
|
||||||
GasPrice hexutil.Big `json:"gasPrice"`
|
GasPrice *hexutil.Big `json:"gasPrice"`
|
||||||
Value hexutil.Big `json:"value"`
|
Value *hexutil.Big `json:"value"`
|
||||||
Data hexutil.Bytes `json:"data"`
|
Data *hexutil.Bytes `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func DoCall(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config, timeout time.Duration) ([]byte, uint64, bool, error) {
|
func DoCall(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config, timeout time.Duration) ([]byte, uint64, bool, error) {
|
||||||
|
|
@ -625,25 +625,38 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumb
|
||||||
return nil, 0, false, err
|
return nil, 0, false, err
|
||||||
}
|
}
|
||||||
// Set sender address or use a default if none specified
|
// Set sender address or use a default if none specified
|
||||||
addr := args.From
|
var addr common.Address
|
||||||
if addr == (common.Address{}) {
|
if args.From == nil {
|
||||||
if wallets := b.AccountManager().Wallets(); len(wallets) > 0 {
|
if wallets := b.AccountManager().Wallets(); len(wallets) > 0 {
|
||||||
if accounts := wallets[0].Accounts(); len(accounts) > 0 {
|
if accounts := wallets[0].Accounts(); len(accounts) > 0 {
|
||||||
addr = accounts[0].Address
|
addr = accounts[0].Address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
addr = *args.From
|
||||||
}
|
}
|
||||||
// Set default gas & gas price if none were set
|
// Set default gas & gas price if none were set
|
||||||
gas, gasPrice := uint64(args.Gas), args.GasPrice.ToInt()
|
gas := uint64(math.MaxUint64 / 2)
|
||||||
if gas == 0 {
|
if args.Gas != nil {
|
||||||
gas = math.MaxUint64 / 2
|
gas = uint64(*args.Gas)
|
||||||
}
|
}
|
||||||
if gasPrice.Sign() == 0 {
|
gasPrice := new(big.Int).SetUint64(defaultGasPrice)
|
||||||
gasPrice = new(big.Int).SetUint64(defaultGasPrice)
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new call message
|
// Create new call message
|
||||||
msg := types.NewMessage(addr, args.To, 0, args.Value.ToInt(), gas, gasPrice, args.Data, false)
|
msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, data, false)
|
||||||
|
|
||||||
// Setup context so it may be cancelled the call has completed
|
// Setup context so it may be cancelled the call has completed
|
||||||
// or, in case of unmetered gas, setup a context with a timeout.
|
// or, in case of unmetered gas, setup a context with a timeout.
|
||||||
|
|
@ -695,8 +708,8 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.Bl
|
||||||
hi uint64
|
hi uint64
|
||||||
cap uint64
|
cap uint64
|
||||||
)
|
)
|
||||||
if uint64(args.Gas) >= params.TxGas {
|
if args.Gas != nil && uint64(*args.Gas) >= params.TxGas {
|
||||||
hi = uint64(args.Gas)
|
hi = uint64(*args.Gas)
|
||||||
} else {
|
} else {
|
||||||
// Retrieve the block to act as the gas ceiling
|
// Retrieve the block to act as the gas ceiling
|
||||||
block, err := b.BlockByNumber(ctx, blockNr)
|
block, err := b.BlockByNumber(ctx, blockNr)
|
||||||
|
|
@ -709,7 +722,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.Bl
|
||||||
|
|
||||||
// Create a helper to check if a gas allowance results in an executable transaction
|
// Create a helper to check if a gas allowance results in an executable transaction
|
||||||
executable := func(gas uint64) bool {
|
executable := func(gas uint64) bool {
|
||||||
args.Gas = hexutil.Uint64(gas)
|
args.Gas = (*hexutil.Uint64)(&gas)
|
||||||
|
|
||||||
_, _, failed, err := DoCall(ctx, b, args, blockNr, vm.Config{}, 0)
|
_, _, failed, err := DoCall(ctx, b, args, blockNr, vm.Config{}, 0)
|
||||||
if err != nil || failed {
|
if err != nil || failed {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue