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