github.com/core-coin/go-core/v2@v2.1.9/graphql/graphql.go (about)

     1  // Copyright 2019 by the Authors
     2  // This file is part of the go-core library.
     3  //
     4  // The go-core library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-core library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-core library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package graphql provides a GraphQL interface to Core node data.
    18  package graphql
    19  
    20  import (
    21  	"context"
    22  	"errors"
    23  	"math/big"
    24  	"time"
    25  
    26  	"github.com/core-coin/go-core/v2/internal/xcbapi"
    27  
    28  	core "github.com/core-coin/go-core/v2"
    29  	"github.com/core-coin/go-core/v2/common"
    30  	"github.com/core-coin/go-core/v2/common/hexutil"
    31  	"github.com/core-coin/go-core/v2/core/rawdb"
    32  	"github.com/core-coin/go-core/v2/core/state"
    33  	"github.com/core-coin/go-core/v2/core/types"
    34  	"github.com/core-coin/go-core/v2/core/vm"
    35  	"github.com/core-coin/go-core/v2/rlp"
    36  	"github.com/core-coin/go-core/v2/rpc"
    37  	"github.com/core-coin/go-core/v2/xcb/filters"
    38  )
    39  
    40  var (
    41  	errBlockInvariant = errors.New("block objects must be instantiated with at least one of num or hash")
    42  )
    43  
    44  // Account represents an Core account at a particular block.
    45  type Account struct {
    46  	backend       xcbapi.Backend
    47  	address       common.Address
    48  	blockNrOrHash rpc.BlockNumberOrHash
    49  }
    50  
    51  // getState fetches the StateDB object for an account.
    52  func (a *Account) getState(ctx context.Context) (*state.StateDB, error) {
    53  	state, _, err := a.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash)
    54  	return state, err
    55  }
    56  
    57  func (a *Account) Address(ctx context.Context) (common.Address, error) {
    58  	return a.address, nil
    59  }
    60  
    61  func (a *Account) Balance(ctx context.Context) (hexutil.Big, error) {
    62  	state, err := a.getState(ctx)
    63  	if err != nil {
    64  		return hexutil.Big{}, err
    65  	}
    66  	return hexutil.Big(*state.GetBalance(a.address)), nil
    67  }
    68  
    69  func (a *Account) TransactionCount(ctx context.Context) (hexutil.Uint64, error) {
    70  	state, err := a.getState(ctx)
    71  	if err != nil {
    72  		return 0, err
    73  	}
    74  	return hexutil.Uint64(state.GetNonce(a.address)), nil
    75  }
    76  
    77  func (a *Account) Code(ctx context.Context) (hexutil.Bytes, error) {
    78  	state, err := a.getState(ctx)
    79  	if err != nil {
    80  		return hexutil.Bytes{}, err
    81  	}
    82  	return state.GetCode(a.address), nil
    83  }
    84  
    85  func (a *Account) Storage(ctx context.Context, args struct{ Slot common.Hash }) (common.Hash, error) {
    86  	state, err := a.getState(ctx)
    87  	if err != nil {
    88  		return common.Hash{}, err
    89  	}
    90  	return state.GetState(a.address, args.Slot), nil
    91  }
    92  
    93  // Log represents an individual log message. All arguments are mandatory.
    94  type Log struct {
    95  	backend     xcbapi.Backend
    96  	transaction *Transaction
    97  	log         *types.Log
    98  }
    99  
   100  func (l *Log) Transaction(ctx context.Context) *Transaction {
   101  	return l.transaction
   102  }
   103  
   104  func (l *Log) Account(ctx context.Context, args BlockNumberArgs) *Account {
   105  	return &Account{
   106  		backend:       l.backend,
   107  		address:       l.log.Address,
   108  		blockNrOrHash: args.NumberOrLatest(),
   109  	}
   110  }
   111  
   112  func (l *Log) Index(ctx context.Context) int32 {
   113  	return int32(l.log.Index)
   114  }
   115  
   116  func (l *Log) Topics(ctx context.Context) []common.Hash {
   117  	return l.log.Topics
   118  }
   119  
   120  func (l *Log) Data(ctx context.Context) hexutil.Bytes {
   121  	return l.log.Data
   122  }
   123  
   124  // Transaction represents an Core transaction.
   125  // backend and hash are mandatory; all others will be fetched when required.
   126  type Transaction struct {
   127  	backend xcbapi.Backend
   128  	hash    common.Hash
   129  	tx      *types.Transaction
   130  	block   *Block
   131  	index   uint64
   132  }
   133  
   134  // resolve returns the internal transaction object, fetching it if needed.
   135  func (t *Transaction) resolve(ctx context.Context) (*types.Transaction, error) {
   136  	if t.tx == nil {
   137  		tx, blockHash, _, index := rawdb.ReadTransaction(t.backend.ChainDb(), t.hash)
   138  		if tx != nil {
   139  			t.tx = tx
   140  			blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false)
   141  			t.block = &Block{
   142  				backend:      t.backend,
   143  				numberOrHash: &blockNrOrHash,
   144  			}
   145  			t.index = index
   146  		} else {
   147  			t.tx = t.backend.GetPoolTransaction(t.hash)
   148  		}
   149  	}
   150  	return t.tx, nil
   151  }
   152  
   153  func (t *Transaction) Hash(ctx context.Context) common.Hash {
   154  	return t.hash
   155  }
   156  
   157  func (t *Transaction) InputData(ctx context.Context) (hexutil.Bytes, error) {
   158  	tx, err := t.resolve(ctx)
   159  	if err != nil || tx == nil {
   160  		return hexutil.Bytes{}, err
   161  	}
   162  	return tx.Data(), nil
   163  }
   164  
   165  func (t *Transaction) Energy(ctx context.Context) (hexutil.Uint64, error) {
   166  	tx, err := t.resolve(ctx)
   167  	if err != nil || tx == nil {
   168  		return 0, err
   169  	}
   170  	return hexutil.Uint64(tx.Energy()), nil
   171  }
   172  
   173  func (t *Transaction) EnergyPrice(ctx context.Context) (hexutil.Big, error) {
   174  	tx, err := t.resolve(ctx)
   175  	if err != nil || tx == nil {
   176  		return hexutil.Big{}, err
   177  	}
   178  	return hexutil.Big(*tx.EnergyPrice()), nil
   179  }
   180  
   181  func (t *Transaction) Value(ctx context.Context) (hexutil.Big, error) {
   182  	tx, err := t.resolve(ctx)
   183  	if err != nil || tx == nil {
   184  		return hexutil.Big{}, err
   185  	}
   186  	return hexutil.Big(*tx.Value()), nil
   187  }
   188  
   189  func (t *Transaction) Nonce(ctx context.Context) (hexutil.Uint64, error) {
   190  	tx, err := t.resolve(ctx)
   191  	if err != nil || tx == nil {
   192  		return 0, err
   193  	}
   194  	return hexutil.Uint64(tx.Nonce()), nil
   195  }
   196  
   197  func (t *Transaction) To(ctx context.Context, args BlockNumberArgs) (*Account, error) {
   198  	tx, err := t.resolve(ctx)
   199  	if err != nil || tx == nil {
   200  		return nil, err
   201  	}
   202  	to := tx.To()
   203  	if to == nil {
   204  		return nil, nil
   205  	}
   206  	return &Account{
   207  		backend:       t.backend,
   208  		address:       *to,
   209  		blockNrOrHash: args.NumberOrLatest(),
   210  	}, nil
   211  }
   212  
   213  func (t *Transaction) From(ctx context.Context, args BlockNumberArgs) (*Account, error) {
   214  	tx, err := t.resolve(ctx)
   215  	if err != nil || tx == nil {
   216  		return nil, err
   217  	}
   218  	signer := types.NewNucleusSigner(big.NewInt(int64(tx.NetworkID())))
   219  	from, err := types.Sender(signer, tx)
   220  	if err != nil {
   221  		return nil, err
   222  	}
   223  	return &Account{
   224  		backend:       t.backend,
   225  		address:       from,
   226  		blockNrOrHash: args.NumberOrLatest(),
   227  	}, nil
   228  }
   229  
   230  func (t *Transaction) Block(ctx context.Context) (*Block, error) {
   231  	if _, err := t.resolve(ctx); err != nil {
   232  		return nil, err
   233  	}
   234  	return t.block, nil
   235  }
   236  
   237  func (t *Transaction) Index(ctx context.Context) (*int32, error) {
   238  	if _, err := t.resolve(ctx); err != nil {
   239  		return nil, err
   240  	}
   241  	if t.block == nil {
   242  		return nil, nil
   243  	}
   244  	index := int32(t.index)
   245  	return &index, nil
   246  }
   247  
   248  // getReceipt returns the receipt associated with this transaction, if any.
   249  func (t *Transaction) getReceipt(ctx context.Context) (*types.Receipt, error) {
   250  	if _, err := t.resolve(ctx); err != nil {
   251  		return nil, err
   252  	}
   253  	if t.block == nil {
   254  		return nil, nil
   255  	}
   256  	receipts, err := t.block.resolveReceipts(ctx)
   257  	if err != nil {
   258  		return nil, err
   259  	}
   260  	return receipts[t.index], nil
   261  }
   262  
   263  func (t *Transaction) Status(ctx context.Context) (*hexutil.Uint64, error) {
   264  	receipt, err := t.getReceipt(ctx)
   265  	if err != nil || receipt == nil {
   266  		return nil, err
   267  	}
   268  	ret := hexutil.Uint64(receipt.Status)
   269  	return &ret, nil
   270  }
   271  
   272  func (t *Transaction) EnergyUsed(ctx context.Context) (*hexutil.Uint64, error) {
   273  	receipt, err := t.getReceipt(ctx)
   274  	if err != nil || receipt == nil {
   275  		return nil, err
   276  	}
   277  	ret := hexutil.Uint64(receipt.EnergyUsed)
   278  	return &ret, nil
   279  }
   280  
   281  func (t *Transaction) CumulativeEnergyUsed(ctx context.Context) (*hexutil.Uint64, error) {
   282  	receipt, err := t.getReceipt(ctx)
   283  	if err != nil || receipt == nil {
   284  		return nil, err
   285  	}
   286  	ret := hexutil.Uint64(receipt.CumulativeEnergyUsed)
   287  	return &ret, nil
   288  }
   289  
   290  func (t *Transaction) CreatedContract(ctx context.Context, args BlockNumberArgs) (*Account, error) {
   291  	receipt, err := t.getReceipt(ctx)
   292  	if err != nil || receipt == nil || receipt.ContractAddress == (common.Address{}) {
   293  		return nil, err
   294  	}
   295  	return &Account{
   296  		backend:       t.backend,
   297  		address:       receipt.ContractAddress,
   298  		blockNrOrHash: args.NumberOrLatest(),
   299  	}, nil
   300  }
   301  
   302  func (t *Transaction) Logs(ctx context.Context) (*[]*Log, error) {
   303  	receipt, err := t.getReceipt(ctx)
   304  	if err != nil || receipt == nil {
   305  		return nil, err
   306  	}
   307  	ret := make([]*Log, 0, len(receipt.Logs))
   308  	for _, log := range receipt.Logs {
   309  		ret = append(ret, &Log{
   310  			backend:     t.backend,
   311  			transaction: t,
   312  			log:         log,
   313  		})
   314  	}
   315  	return &ret, nil
   316  }
   317  
   318  type BlockType int
   319  
   320  // Block represents an Core block.
   321  // backend, and numberOrHash are mandatory. All other fields are lazily fetched
   322  // when required.
   323  type Block struct {
   324  	backend      xcbapi.Backend
   325  	numberOrHash *rpc.BlockNumberOrHash
   326  	hash         common.Hash
   327  	header       *types.Header
   328  	block        *types.Block
   329  	receipts     []*types.Receipt
   330  }
   331  
   332  // resolve returns the internal Block object representing this block, fetching
   333  // it if necessary.
   334  func (b *Block) resolve(ctx context.Context) (*types.Block, error) {
   335  	if b.block != nil {
   336  		return b.block, nil
   337  	}
   338  	if b.numberOrHash == nil {
   339  		latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
   340  		b.numberOrHash = &latest
   341  	}
   342  	var err error
   343  	b.block, err = b.backend.BlockByNumberOrHash(ctx, *b.numberOrHash)
   344  	if b.block != nil && b.header == nil {
   345  		b.header = b.block.Header()
   346  		if hash, ok := b.numberOrHash.Hash(); ok {
   347  			b.hash = hash
   348  		}
   349  	}
   350  	return b.block, err
   351  }
   352  
   353  // resolveHeader returns the internal Header object for this block, fetching it
   354  // if necessary. Call this function instead of `resolve` unless you need the
   355  // additional data (transactions and uncles).
   356  func (b *Block) resolveHeader(ctx context.Context) (*types.Header, error) {
   357  	if b.numberOrHash == nil && b.hash == (common.Hash{}) {
   358  		return nil, errBlockInvariant
   359  	}
   360  	var err error
   361  	if b.header == nil {
   362  		if b.hash != (common.Hash{}) {
   363  			b.header, err = b.backend.HeaderByHash(ctx, b.hash)
   364  		} else {
   365  			b.header, err = b.backend.HeaderByNumberOrHash(ctx, *b.numberOrHash)
   366  		}
   367  	}
   368  	return b.header, err
   369  }
   370  
   371  // resolveReceipts returns the list of receipts for this block, fetching them
   372  // if necessary.
   373  func (b *Block) resolveReceipts(ctx context.Context) ([]*types.Receipt, error) {
   374  	if b.receipts == nil {
   375  		hash := b.hash
   376  		if hash == (common.Hash{}) {
   377  			header, err := b.resolveHeader(ctx)
   378  			if err != nil {
   379  				return nil, err
   380  			}
   381  			hash = header.Hash()
   382  		}
   383  		receipts, err := b.backend.GetReceipts(ctx, hash)
   384  		if err != nil {
   385  			return nil, err
   386  		}
   387  		b.receipts = receipts
   388  	}
   389  	return b.receipts, nil
   390  }
   391  
   392  func (b *Block) Number(ctx context.Context) (hexutil.Uint64, error) {
   393  	header, err := b.resolveHeader(ctx)
   394  	if err != nil {
   395  		return 0, err
   396  	}
   397  
   398  	return hexutil.Uint64(header.Number.Uint64()), nil
   399  }
   400  
   401  func (b *Block) Hash(ctx context.Context) (common.Hash, error) {
   402  	if b.hash == (common.Hash{}) {
   403  		header, err := b.resolveHeader(ctx)
   404  		if err != nil {
   405  			return common.Hash{}, err
   406  		}
   407  		b.hash = header.Hash()
   408  	}
   409  	return b.hash, nil
   410  }
   411  
   412  func (b *Block) EnergyLimit(ctx context.Context) (hexutil.Uint64, error) {
   413  	header, err := b.resolveHeader(ctx)
   414  	if err != nil {
   415  		return 0, err
   416  	}
   417  	return hexutil.Uint64(header.EnergyLimit), nil
   418  }
   419  
   420  func (b *Block) EnergyUsed(ctx context.Context) (hexutil.Uint64, error) {
   421  	header, err := b.resolveHeader(ctx)
   422  	if err != nil {
   423  		return 0, err
   424  	}
   425  	return hexutil.Uint64(header.EnergyUsed), nil
   426  }
   427  
   428  func (b *Block) Parent(ctx context.Context) (*Block, error) {
   429  	// If the block header hasn't been fetched, and we'll need it, fetch it.
   430  	if b.numberOrHash == nil && b.header == nil {
   431  		if _, err := b.resolveHeader(ctx); err != nil {
   432  			return nil, err
   433  		}
   434  	}
   435  	if b.header != nil && b.header.Number.Uint64() > 0 {
   436  		num := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(b.header.Number.Uint64() - 1))
   437  		return &Block{
   438  			backend:      b.backend,
   439  			numberOrHash: &num,
   440  			hash:         b.header.ParentHash,
   441  		}, nil
   442  	}
   443  	return nil, nil
   444  }
   445  
   446  func (b *Block) Difficulty(ctx context.Context) (hexutil.Big, error) {
   447  	header, err := b.resolveHeader(ctx)
   448  	if err != nil {
   449  		return hexutil.Big{}, err
   450  	}
   451  	return hexutil.Big(*header.Difficulty), nil
   452  }
   453  
   454  func (b *Block) Timestamp(ctx context.Context) (hexutil.Uint64, error) {
   455  	header, err := b.resolveHeader(ctx)
   456  	if err != nil {
   457  		return 0, err
   458  	}
   459  	return hexutil.Uint64(header.Time), nil
   460  }
   461  
   462  func (b *Block) Nonce(ctx context.Context) (hexutil.Bytes, error) {
   463  	header, err := b.resolveHeader(ctx)
   464  	if err != nil {
   465  		return hexutil.Bytes{}, err
   466  	}
   467  	return header.Nonce[:], nil
   468  }
   469  
   470  func (b *Block) TransactionsRoot(ctx context.Context) (common.Hash, error) {
   471  	header, err := b.resolveHeader(ctx)
   472  	if err != nil {
   473  		return common.Hash{}, err
   474  	}
   475  	return header.TxHash, nil
   476  }
   477  
   478  func (b *Block) StateRoot(ctx context.Context) (common.Hash, error) {
   479  	header, err := b.resolveHeader(ctx)
   480  	if err != nil {
   481  		return common.Hash{}, err
   482  	}
   483  	return header.Root, nil
   484  }
   485  
   486  func (b *Block) ReceiptsRoot(ctx context.Context) (common.Hash, error) {
   487  	header, err := b.resolveHeader(ctx)
   488  	if err != nil {
   489  		return common.Hash{}, err
   490  	}
   491  	return header.ReceiptHash, nil
   492  }
   493  
   494  func (b *Block) OmmerHash(ctx context.Context) (common.Hash, error) {
   495  	header, err := b.resolveHeader(ctx)
   496  	if err != nil {
   497  		return common.Hash{}, err
   498  	}
   499  	return header.UncleHash, nil
   500  }
   501  
   502  func (b *Block) OmmerCount(ctx context.Context) (*int32, error) {
   503  	block, err := b.resolve(ctx)
   504  	if err != nil || block == nil {
   505  		return nil, err
   506  	}
   507  	count := int32(len(block.Uncles()))
   508  	return &count, err
   509  }
   510  
   511  func (b *Block) Ommers(ctx context.Context) (*[]*Block, error) {
   512  	block, err := b.resolve(ctx)
   513  	if err != nil || block == nil {
   514  		return nil, err
   515  	}
   516  	ret := make([]*Block, 0, len(block.Uncles()))
   517  	for _, uncle := range block.Uncles() {
   518  		blockNumberOrHash := rpc.BlockNumberOrHashWithHash(uncle.Hash(), false)
   519  		ret = append(ret, &Block{
   520  			backend:      b.backend,
   521  			numberOrHash: &blockNumberOrHash,
   522  			header:       uncle,
   523  		})
   524  	}
   525  	return &ret, nil
   526  }
   527  
   528  func (b *Block) ExtraData(ctx context.Context) (hexutil.Bytes, error) {
   529  	header, err := b.resolveHeader(ctx)
   530  	if err != nil {
   531  		return hexutil.Bytes{}, err
   532  	}
   533  	return header.Extra, nil
   534  }
   535  
   536  func (b *Block) LogsBloom(ctx context.Context) (hexutil.Bytes, error) {
   537  	header, err := b.resolveHeader(ctx)
   538  	if err != nil {
   539  		return hexutil.Bytes{}, err
   540  	}
   541  	return header.Bloom.Bytes(), nil
   542  }
   543  
   544  func (b *Block) TotalDifficulty(ctx context.Context) (hexutil.Big, error) {
   545  	h := b.hash
   546  	if h == (common.Hash{}) {
   547  		header, err := b.resolveHeader(ctx)
   548  		if err != nil {
   549  			return hexutil.Big{}, err
   550  		}
   551  		h = header.Hash()
   552  	}
   553  	return hexutil.Big(*b.backend.GetTd(ctx, h)), nil
   554  }
   555  
   556  // BlockNumberArgs encapsulates arguments to accessors that specify a block number.
   557  type BlockNumberArgs struct {
   558  	// TODO: Ideally we could use input unions to allow the query to specify the
   559  	// block parameter by hash, block number, or tag but input unions aren't part of the
   560  	// standard GraphQL schema SDL yet, see: https://github.com/graphql/graphql-spec/issues/488
   561  	Block *hexutil.Uint64
   562  }
   563  
   564  // NumberOr returns the provided block number argument, or the "current" block number or hash if none
   565  // was provided.
   566  func (a BlockNumberArgs) NumberOr(current rpc.BlockNumberOrHash) rpc.BlockNumberOrHash {
   567  	if a.Block != nil {
   568  		blockNr := rpc.BlockNumber(*a.Block)
   569  		return rpc.BlockNumberOrHashWithNumber(blockNr)
   570  	}
   571  	return current
   572  }
   573  
   574  // NumberOrLatest returns the provided block number argument, or the "latest" block number if none
   575  // was provided.
   576  func (a BlockNumberArgs) NumberOrLatest() rpc.BlockNumberOrHash {
   577  	return a.NumberOr(rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber))
   578  }
   579  
   580  func (b *Block) Miner(ctx context.Context, args BlockNumberArgs) (*Account, error) {
   581  	header, err := b.resolveHeader(ctx)
   582  	if err != nil {
   583  		return nil, err
   584  	}
   585  	return &Account{
   586  		backend:       b.backend,
   587  		address:       header.Coinbase,
   588  		blockNrOrHash: args.NumberOrLatest(),
   589  	}, nil
   590  }
   591  
   592  func (b *Block) TransactionCount(ctx context.Context) (*int32, error) {
   593  	block, err := b.resolve(ctx)
   594  	if err != nil || block == nil {
   595  		return nil, err
   596  	}
   597  	count := int32(len(block.Transactions()))
   598  	return &count, err
   599  }
   600  
   601  func (b *Block) Transactions(ctx context.Context) (*[]*Transaction, error) {
   602  	block, err := b.resolve(ctx)
   603  	if err != nil || block == nil {
   604  		return nil, err
   605  	}
   606  	ret := make([]*Transaction, 0, len(block.Transactions()))
   607  	for i, tx := range block.Transactions() {
   608  		ret = append(ret, &Transaction{
   609  			backend: b.backend,
   610  			hash:    tx.Hash(),
   611  			tx:      tx,
   612  			block:   b,
   613  			index:   uint64(i),
   614  		})
   615  	}
   616  	return &ret, nil
   617  }
   618  
   619  func (b *Block) TransactionAt(ctx context.Context, args struct{ Index int32 }) (*Transaction, error) {
   620  	block, err := b.resolve(ctx)
   621  	if err != nil || block == nil {
   622  		return nil, err
   623  	}
   624  	txs := block.Transactions()
   625  	if args.Index < 0 || int(args.Index) >= len(txs) {
   626  		return nil, nil
   627  	}
   628  	tx := txs[args.Index]
   629  	return &Transaction{
   630  		backend: b.backend,
   631  		hash:    tx.Hash(),
   632  		tx:      tx,
   633  		block:   b,
   634  		index:   uint64(args.Index),
   635  	}, nil
   636  }
   637  
   638  func (b *Block) OmmerAt(ctx context.Context, args struct{ Index int32 }) (*Block, error) {
   639  	block, err := b.resolve(ctx)
   640  	if err != nil || block == nil {
   641  		return nil, err
   642  	}
   643  	uncles := block.Uncles()
   644  	if args.Index < 0 || int(args.Index) >= len(uncles) {
   645  		return nil, nil
   646  	}
   647  	uncle := uncles[args.Index]
   648  	blockNumberOrHash := rpc.BlockNumberOrHashWithHash(uncle.Hash(), false)
   649  	return &Block{
   650  		backend:      b.backend,
   651  		numberOrHash: &blockNumberOrHash,
   652  		header:       uncle,
   653  	}, nil
   654  }
   655  
   656  // BlockFilterCriteria encapsulates criteria passed to a `logs` accessor inside
   657  // a block.
   658  type BlockFilterCriteria struct {
   659  	Addresses *[]common.Address // restricts matches to events created by specific contracts
   660  
   661  	// The Topic list restricts matches to particular event topics. Each event has a list
   662  	// of topics. Topics matches a prefix of that list. An empty element slice matches any
   663  	// topic. Non-empty elements represent an alternative that matches any of the
   664  	// contained topics.
   665  	//
   666  	// Examples:
   667  	// {} or nil          matches any topic list
   668  	// {{A}}              matches topic A in first position
   669  	// {{}, {B}}          matches any topic in first position, B in second position
   670  	// {{A}, {B}}         matches topic A in first position, B in second position
   671  	// {{A, B}}, {C, D}}  matches topic (A OR B) in first position, (C OR D) in second position
   672  	Topics *[][]common.Hash
   673  }
   674  
   675  // runFilter accepts a filter and executes it, returning all its results as
   676  // `Log` objects.
   677  func runFilter(ctx context.Context, be xcbapi.Backend, filter *filters.Filter) ([]*Log, error) {
   678  	logs, err := filter.Logs(ctx)
   679  	if err != nil || logs == nil {
   680  		return nil, err
   681  	}
   682  	ret := make([]*Log, 0, len(logs))
   683  	for _, log := range logs {
   684  		ret = append(ret, &Log{
   685  			backend:     be,
   686  			transaction: &Transaction{backend: be, hash: log.TxHash},
   687  			log:         log,
   688  		})
   689  	}
   690  	return ret, nil
   691  }
   692  
   693  func (b *Block) Logs(ctx context.Context, args struct{ Filter BlockFilterCriteria }) ([]*Log, error) {
   694  	var addresses []common.Address
   695  	if args.Filter.Addresses != nil {
   696  		addresses = *args.Filter.Addresses
   697  	}
   698  	var topics [][]common.Hash
   699  	if args.Filter.Topics != nil {
   700  		topics = *args.Filter.Topics
   701  	}
   702  	hash := b.hash
   703  	if hash == (common.Hash{}) {
   704  		header, err := b.resolveHeader(ctx)
   705  		if err != nil {
   706  			return nil, err
   707  		}
   708  		hash = header.Hash()
   709  	}
   710  	// Construct the range filter
   711  	filter := filters.NewBlockFilter(b.backend, hash, addresses, topics)
   712  
   713  	// Run the filter and return all the logs
   714  	return runFilter(ctx, b.backend, filter)
   715  }
   716  
   717  func (b *Block) Account(ctx context.Context, args struct {
   718  	Address common.Address
   719  }) (*Account, error) {
   720  	if b.numberOrHash == nil {
   721  		_, err := b.resolveHeader(ctx)
   722  		if err != nil {
   723  			return nil, err
   724  		}
   725  	}
   726  	return &Account{
   727  		backend:       b.backend,
   728  		address:       args.Address,
   729  		blockNrOrHash: *b.numberOrHash,
   730  	}, nil
   731  }
   732  
   733  // CallData encapsulates arguments to `call` or `estimateEnergy`.
   734  // All arguments are optional.
   735  type CallData struct {
   736  	From        *common.Address // The Core address the call is from.
   737  	To          *common.Address // The Core address the call is to.
   738  	Energy      *hexutil.Uint64 // The amount of energy provided for the call.
   739  	EnergyPrice *hexutil.Big    // The price of each unit of energy, in ore.
   740  	Value       *hexutil.Big    // The value sent along with the call.
   741  	Data        *hexutil.Bytes  // Any data sent with the call.
   742  }
   743  
   744  // CallResult encapsulates the result of an invocation of the `call` accessor.
   745  type CallResult struct {
   746  	data       hexutil.Bytes  // The return data from the call
   747  	energyUsed hexutil.Uint64 // The amount of energy used
   748  	status     hexutil.Uint64 // The return status of the call - 0 for failure or 1 for success.
   749  }
   750  
   751  func (c *CallResult) Data() hexutil.Bytes {
   752  	return c.data
   753  }
   754  
   755  func (c *CallResult) EnergyUsed() hexutil.Uint64 {
   756  	return c.energyUsed
   757  }
   758  
   759  func (c *CallResult) Status() hexutil.Uint64 {
   760  	return c.status
   761  }
   762  
   763  func (b *Block) Call(ctx context.Context, args struct {
   764  	Data xcbapi.CallArgs
   765  }) (*CallResult, error) {
   766  	if b.numberOrHash == nil {
   767  		_, err := b.resolve(ctx)
   768  		if err != nil {
   769  			return nil, err
   770  		}
   771  	}
   772  	result, err := xcbapi.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, vm.Config{}, 5*time.Second, b.backend.RPCEnergyCap())
   773  	if err != nil {
   774  		return nil, err
   775  	}
   776  	status := hexutil.Uint64(1)
   777  	if result.Failed() {
   778  		status = 0
   779  	}
   780  
   781  	return &CallResult{
   782  		data:       result.ReturnData,
   783  		energyUsed: hexutil.Uint64(result.UsedEnergy),
   784  		status:     status,
   785  	}, nil
   786  }
   787  
   788  func (b *Block) EstimateEnergy(ctx context.Context, args struct {
   789  	Data xcbapi.CallArgs
   790  }) (hexutil.Uint64, error) {
   791  	if b.numberOrHash == nil {
   792  		_, err := b.resolveHeader(ctx)
   793  		if err != nil {
   794  			return hexutil.Uint64(0), err
   795  		}
   796  	}
   797  	energy, err := xcbapi.DoEstimateEnergy(ctx, b.backend, args.Data, *b.numberOrHash, b.backend.RPCEnergyCap())
   798  	return energy, err
   799  }
   800  
   801  type Pending struct {
   802  	backend xcbapi.Backend
   803  }
   804  
   805  func (p *Pending) TransactionCount(ctx context.Context) (int32, error) {
   806  	txs, err := p.backend.GetPoolTransactions()
   807  	return int32(len(txs)), err
   808  }
   809  
   810  func (p *Pending) Transactions(ctx context.Context) (*[]*Transaction, error) {
   811  	txs, err := p.backend.GetPoolTransactions()
   812  	if err != nil {
   813  		return nil, err
   814  	}
   815  	ret := make([]*Transaction, 0, len(txs))
   816  	for i, tx := range txs {
   817  		ret = append(ret, &Transaction{
   818  			backend: p.backend,
   819  			hash:    tx.Hash(),
   820  			tx:      tx,
   821  			index:   uint64(i),
   822  		})
   823  	}
   824  	return &ret, nil
   825  }
   826  
   827  func (p *Pending) Account(ctx context.Context, args struct {
   828  	Address common.Address
   829  }) *Account {
   830  	pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
   831  	return &Account{
   832  		backend:       p.backend,
   833  		address:       args.Address,
   834  		blockNrOrHash: pendingBlockNr,
   835  	}
   836  }
   837  
   838  func (p *Pending) Call(ctx context.Context, args struct {
   839  	Data xcbapi.CallArgs
   840  }) (*CallResult, error) {
   841  	pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
   842  	result, err := xcbapi.DoCall(ctx, p.backend, args.Data, pendingBlockNr, nil, vm.Config{}, 5*time.Second, p.backend.RPCEnergyCap())
   843  	if err != nil {
   844  		return nil, err
   845  	}
   846  	status := hexutil.Uint64(1)
   847  	if result.Failed() {
   848  		status = 0
   849  	}
   850  
   851  	return &CallResult{
   852  		data:       result.ReturnData,
   853  		energyUsed: hexutil.Uint64(result.UsedEnergy),
   854  		status:     status,
   855  	}, nil
   856  }
   857  
   858  func (p *Pending) EstimateEnergy(ctx context.Context, args struct {
   859  	Data xcbapi.CallArgs
   860  }) (hexutil.Uint64, error) {
   861  	pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
   862  	return xcbapi.DoEstimateEnergy(ctx, p.backend, args.Data, pendingBlockNr, p.backend.RPCEnergyCap())
   863  }
   864  
   865  // Resolver is the top-level object in the GraphQL hierarchy.
   866  type Resolver struct {
   867  	backend xcbapi.Backend
   868  }
   869  
   870  func (r *Resolver) Block(ctx context.Context, args struct {
   871  	Number *hexutil.Uint64
   872  	Hash   *common.Hash
   873  }) (*Block, error) {
   874  	var block *Block
   875  	if args.Number != nil {
   876  		number := rpc.BlockNumber(*args.Number)
   877  		numberOrHash := rpc.BlockNumberOrHashWithNumber(number)
   878  		block = &Block{
   879  			backend:      r.backend,
   880  			numberOrHash: &numberOrHash,
   881  		}
   882  	} else if args.Hash != nil {
   883  		numberOrHash := rpc.BlockNumberOrHashWithHash(*args.Hash, false)
   884  		block = &Block{
   885  			backend:      r.backend,
   886  			numberOrHash: &numberOrHash,
   887  		}
   888  	} else {
   889  		numberOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
   890  		block = &Block{
   891  			backend:      r.backend,
   892  			numberOrHash: &numberOrHash,
   893  		}
   894  	}
   895  	// Resolve the header, return nil if it doesn't exist.
   896  	// Note we don't resolve block directly here since it will require an
   897  	// additional network request for light client.
   898  	h, err := block.resolveHeader(ctx)
   899  	if err != nil {
   900  		return nil, err
   901  	} else if h == nil {
   902  		return nil, nil
   903  	}
   904  	return block, nil
   905  }
   906  
   907  func (r *Resolver) Blocks(ctx context.Context, args struct {
   908  	From hexutil.Uint64
   909  	To   *hexutil.Uint64
   910  }) ([]*Block, error) {
   911  	from := rpc.BlockNumber(args.From)
   912  
   913  	var to rpc.BlockNumber
   914  	if args.To != nil {
   915  		to = rpc.BlockNumber(*args.To)
   916  	} else {
   917  		to = rpc.BlockNumber(r.backend.CurrentBlock().Number().Int64())
   918  	}
   919  	if to < from {
   920  		return []*Block{}, nil
   921  	}
   922  	ret := make([]*Block, 0, to-from+1)
   923  	for i := from; i <= to; i++ {
   924  		numberOrHash := rpc.BlockNumberOrHashWithNumber(i)
   925  		ret = append(ret, &Block{
   926  			backend:      r.backend,
   927  			numberOrHash: &numberOrHash,
   928  		})
   929  	}
   930  	return ret, nil
   931  }
   932  
   933  func (r *Resolver) Pending(ctx context.Context) *Pending {
   934  	return &Pending{r.backend}
   935  }
   936  
   937  func (r *Resolver) Transaction(ctx context.Context, args struct{ Hash common.Hash }) (*Transaction, error) {
   938  	tx := &Transaction{
   939  		backend: r.backend,
   940  		hash:    args.Hash,
   941  	}
   942  	// Resolve the transaction; if it doesn't exist, return nil.
   943  	t, err := tx.resolve(ctx)
   944  	if err != nil {
   945  		return nil, err
   946  	} else if t == nil {
   947  		return nil, nil
   948  	}
   949  	return tx, nil
   950  }
   951  
   952  func (r *Resolver) SendRawTransaction(ctx context.Context, args struct{ Data hexutil.Bytes }) (common.Hash, error) {
   953  	tx := new(types.Transaction)
   954  	if err := rlp.DecodeBytes(args.Data, tx); err != nil {
   955  		return common.Hash{}, err
   956  	}
   957  	hash, err := xcbapi.SubmitTransaction(ctx, r.backend, tx)
   958  	return hash, err
   959  }
   960  
   961  // FilterCriteria encapsulates the arguments to `logs` on the root resolver object.
   962  type FilterCriteria struct {
   963  	FromBlock *hexutil.Uint64   // beginning of the queried range, nil means genesis block
   964  	ToBlock   *hexutil.Uint64   // end of the range, nil means latest block
   965  	Addresses *[]common.Address // restricts matches to events created by specific contracts
   966  
   967  	// The Topic list restricts matches to particular event topics. Each event has a list
   968  	// of topics. Topics matches a prefix of that list. An empty element slice matches any
   969  	// topic. Non-empty elements represent an alternative that matches any of the
   970  	// contained topics.
   971  	//
   972  	// Examples:
   973  	// {} or nil          matches any topic list
   974  	// {{A}}              matches topic A in first position
   975  	// {{}, {B}}          matches any topic in first position, B in second position
   976  	// {{A}, {B}}         matches topic A in first position, B in second position
   977  	// {{A, B}}, {C, D}}  matches topic (A OR B) in first position, (C OR D) in second position
   978  	Topics *[][]common.Hash
   979  }
   980  
   981  func (r *Resolver) Logs(ctx context.Context, args struct{ Filter FilterCriteria }) ([]*Log, error) {
   982  	// Convert the RPC block numbers into internal representations
   983  	begin := rpc.LatestBlockNumber.Int64()
   984  	if args.Filter.FromBlock != nil {
   985  		begin = int64(*args.Filter.FromBlock)
   986  	}
   987  	end := rpc.LatestBlockNumber.Int64()
   988  	if args.Filter.ToBlock != nil {
   989  		end = int64(*args.Filter.ToBlock)
   990  	}
   991  	var addresses []common.Address
   992  	if args.Filter.Addresses != nil {
   993  		addresses = *args.Filter.Addresses
   994  	}
   995  	var topics [][]common.Hash
   996  	if args.Filter.Topics != nil {
   997  		topics = *args.Filter.Topics
   998  	}
   999  	// Construct the range filter
  1000  	filter := filters.NewRangeFilter(filters.Backend(r.backend), begin, end, addresses, topics)
  1001  	return runFilter(ctx, r.backend, filter)
  1002  }
  1003  
  1004  func (r *Resolver) EnergyPrice(ctx context.Context) (hexutil.Big, error) {
  1005  	price, err := r.backend.SuggestPrice(ctx)
  1006  	return hexutil.Big(*price), err
  1007  }
  1008  
  1009  func (r *Resolver) ProtocolVersion(ctx context.Context) (int32, error) {
  1010  	return int32(r.backend.ProtocolVersion()), nil
  1011  }
  1012  
  1013  func (r *Resolver) NetworkID(ctx context.Context) (hexutil.Big, error) {
  1014  	return hexutil.Big(*r.backend.ChainConfig().NetworkID), nil
  1015  }
  1016  
  1017  // SyncState represents the synchronisation status returned from the `syncing` accessor.
  1018  type SyncState struct {
  1019  	progress core.SyncProgress
  1020  }
  1021  
  1022  func (s *SyncState) StartingBlock() hexutil.Uint64 {
  1023  	return hexutil.Uint64(s.progress.StartingBlock)
  1024  }
  1025  
  1026  func (s *SyncState) CurrentBlock() hexutil.Uint64 {
  1027  	return hexutil.Uint64(s.progress.CurrentBlock)
  1028  }
  1029  
  1030  func (s *SyncState) HighestBlock() hexutil.Uint64 {
  1031  	return hexutil.Uint64(s.progress.HighestBlock)
  1032  }
  1033  
  1034  func (s *SyncState) PulledStates() *hexutil.Uint64 {
  1035  	ret := hexutil.Uint64(s.progress.PulledStates)
  1036  	return &ret
  1037  }
  1038  
  1039  func (s *SyncState) KnownStates() *hexutil.Uint64 {
  1040  	ret := hexutil.Uint64(s.progress.KnownStates)
  1041  	return &ret
  1042  }
  1043  
  1044  // Syncing returns false in case the node is currently not syncing with the network. It can be up to date or has not
  1045  // yet received the latest block headers from its pears. In case it is synchronizing:
  1046  // - startingBlock: block number this node started to synchronise from
  1047  // - currentBlock:  block number this node is currently importing
  1048  // - highestBlock:  block number of the highest block header this node has received from peers
  1049  // - pulledStates:  number of state entries processed until now
  1050  // - knownStates:   number of known state entries that still need to be pulled
  1051  func (r *Resolver) Syncing() (*SyncState, error) {
  1052  	progress := r.backend.Downloader().Progress()
  1053  
  1054  	// Return not syncing if the synchronisation already completed
  1055  	if progress.CurrentBlock >= progress.HighestBlock {
  1056  		return nil, nil
  1057  	}
  1058  	// Otherwise gather the block sync stats
  1059  	return &SyncState{progress}, nil
  1060  }