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