github.com/theQRL/go-zond@v0.1.1/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 "fmt" 24 "math/big" 25 "sort" 26 "strconv" 27 "strings" 28 "sync" 29 30 "github.com/theQRL/go-zond" 31 "github.com/theQRL/go-zond/common" 32 "github.com/theQRL/go-zond/common/hexutil" 33 "github.com/theQRL/go-zond/common/math" 34 "github.com/theQRL/go-zond/consensus/misc/eip1559" 35 "github.com/theQRL/go-zond/core/state" 36 "github.com/theQRL/go-zond/core/types" 37 "github.com/theQRL/go-zond/internal/ethapi" 38 "github.com/theQRL/go-zond/rlp" 39 "github.com/theQRL/go-zond/rpc" 40 "github.com/theQRL/go-zond/zond/filters" 41 ) 42 43 var ( 44 errBlockInvariant = errors.New("block objects must be instantiated with at least one of num or hash") 45 ) 46 47 type Long int64 48 49 // ImplementsGraphQLType returns true if Long implements the provided GraphQL type. 50 func (b Long) ImplementsGraphQLType(name string) bool { return name == "Long" } 51 52 // UnmarshalGraphQL unmarshals the provided GraphQL query data. 53 func (b *Long) UnmarshalGraphQL(input interface{}) error { 54 var err error 55 switch input := input.(type) { 56 case string: 57 // uncomment to support hex values 58 if strings.HasPrefix(input, "0x") { 59 // apply leniency and support hex representations of longs. 60 value, err := hexutil.DecodeUint64(input) 61 *b = Long(value) 62 return err 63 } else { 64 value, err := strconv.ParseInt(input, 10, 64) 65 *b = Long(value) 66 return err 67 } 68 case int32: 69 *b = Long(input) 70 case int64: 71 *b = Long(input) 72 case float64: 73 *b = Long(input) 74 default: 75 err = fmt.Errorf("unexpected type %T for Long", input) 76 } 77 return err 78 } 79 80 // Account represents an Ethereum account at a particular block. 81 type Account struct { 82 r *Resolver 83 address common.Address 84 blockNrOrHash rpc.BlockNumberOrHash 85 } 86 87 // getState fetches the StateDB object for an account. 88 func (a *Account) getState(ctx context.Context) (*state.StateDB, error) { 89 state, _, err := a.r.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash) 90 return state, err 91 } 92 93 func (a *Account) Address(ctx context.Context) (common.Address, error) { 94 return a.address, nil 95 } 96 97 func (a *Account) Balance(ctx context.Context) (hexutil.Big, error) { 98 state, err := a.getState(ctx) 99 if err != nil { 100 return hexutil.Big{}, err 101 } 102 balance := state.GetBalance(a.address) 103 if balance == nil { 104 return hexutil.Big{}, fmt.Errorf("failed to load balance %x", a.address) 105 } 106 return hexutil.Big(*balance), nil 107 } 108 109 func (a *Account) TransactionCount(ctx context.Context) (hexutil.Uint64, error) { 110 // Ask transaction pool for the nonce which includes pending transactions 111 if blockNr, ok := a.blockNrOrHash.Number(); ok && blockNr == rpc.PendingBlockNumber { 112 nonce, err := a.r.backend.GetPoolNonce(ctx, a.address) 113 if err != nil { 114 return 0, err 115 } 116 return hexutil.Uint64(nonce), nil 117 } 118 state, err := a.getState(ctx) 119 if err != nil { 120 return 0, err 121 } 122 return hexutil.Uint64(state.GetNonce(a.address)), nil 123 } 124 125 func (a *Account) Code(ctx context.Context) (hexutil.Bytes, error) { 126 state, err := a.getState(ctx) 127 if err != nil { 128 return hexutil.Bytes{}, err 129 } 130 return state.GetCode(a.address), nil 131 } 132 133 func (a *Account) Storage(ctx context.Context, args struct{ Slot common.Hash }) (common.Hash, error) { 134 state, err := a.getState(ctx) 135 if err != nil { 136 return common.Hash{}, err 137 } 138 return state.GetState(a.address, args.Slot), nil 139 } 140 141 // Log represents an individual log message. All arguments are mandatory. 142 type Log struct { 143 r *Resolver 144 transaction *Transaction 145 log *types.Log 146 } 147 148 func (l *Log) Transaction(ctx context.Context) *Transaction { 149 return l.transaction 150 } 151 152 func (l *Log) Account(ctx context.Context, args BlockNumberArgs) *Account { 153 return &Account{ 154 r: l.r, 155 address: l.log.Address, 156 blockNrOrHash: args.NumberOrLatest(), 157 } 158 } 159 160 func (l *Log) Index(ctx context.Context) hexutil.Uint64 { 161 return hexutil.Uint64(l.log.Index) 162 } 163 164 func (l *Log) Topics(ctx context.Context) []common.Hash { 165 return l.log.Topics 166 } 167 168 func (l *Log) Data(ctx context.Context) hexutil.Bytes { 169 return l.log.Data 170 } 171 172 // AccessTuple represents EIP-2930 173 type AccessTuple struct { 174 address common.Address 175 storageKeys []common.Hash 176 } 177 178 func (at *AccessTuple) Address(ctx context.Context) common.Address { 179 return at.address 180 } 181 182 func (at *AccessTuple) StorageKeys(ctx context.Context) []common.Hash { 183 return at.storageKeys 184 } 185 186 // Withdrawal represents a withdrawal of value from the beacon chain 187 // by a validator. For details see EIP-4895. 188 type Withdrawal struct { 189 index uint64 190 validator uint64 191 address common.Address 192 amount uint64 193 } 194 195 func (w *Withdrawal) Index(ctx context.Context) hexutil.Uint64 { 196 return hexutil.Uint64(w.index) 197 } 198 199 func (w *Withdrawal) Validator(ctx context.Context) hexutil.Uint64 { 200 return hexutil.Uint64(w.validator) 201 } 202 203 func (w *Withdrawal) Address(ctx context.Context) common.Address { 204 return w.address 205 } 206 207 func (w *Withdrawal) Amount(ctx context.Context) hexutil.Uint64 { 208 return hexutil.Uint64(w.amount) 209 } 210 211 // Transaction represents an Ethereum transaction. 212 // backend and hash are mandatory; all others will be fetched when required. 213 type Transaction struct { 214 r *Resolver 215 hash common.Hash // Must be present after initialization 216 mu sync.Mutex 217 // mu protects following resources 218 tx *types.Transaction 219 block *Block 220 index uint64 221 } 222 223 // resolve returns the internal transaction object, fetching it if needed. 224 // It also returns the block the tx belongs to, unless it is a pending tx. 225 func (t *Transaction) resolve(ctx context.Context) (*types.Transaction, *Block) { 226 t.mu.Lock() 227 defer t.mu.Unlock() 228 if t.tx != nil { 229 return t.tx, t.block 230 } 231 // Try to return an already finalized transaction 232 tx, blockHash, _, index, err := t.r.backend.GetTransaction(ctx, t.hash) 233 if err == nil && tx != nil { 234 t.tx = tx 235 blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false) 236 t.block = &Block{ 237 r: t.r, 238 numberOrHash: &blockNrOrHash, 239 hash: blockHash, 240 } 241 t.index = index 242 return t.tx, t.block 243 } 244 // No finalized transaction, try to retrieve it from the pool 245 t.tx = t.r.backend.GetPoolTransaction(t.hash) 246 return t.tx, nil 247 } 248 249 func (t *Transaction) Hash(ctx context.Context) common.Hash { 250 return t.hash 251 } 252 253 func (t *Transaction) InputData(ctx context.Context) hexutil.Bytes { 254 tx, _ := t.resolve(ctx) 255 if tx == nil { 256 return hexutil.Bytes{} 257 } 258 return tx.Data() 259 } 260 261 func (t *Transaction) Gas(ctx context.Context) hexutil.Uint64 { 262 tx, _ := t.resolve(ctx) 263 if tx == nil { 264 return 0 265 } 266 return hexutil.Uint64(tx.Gas()) 267 } 268 269 func (t *Transaction) GasPrice(ctx context.Context) hexutil.Big { 270 tx, block := t.resolve(ctx) 271 if tx == nil { 272 return hexutil.Big{} 273 } 274 switch tx.Type() { 275 case types.DynamicFeeTxType: 276 if block != nil { 277 if baseFee, _ := block.BaseFeePerGas(ctx); baseFee != nil { 278 // price = min(gasTipCap + baseFee, gasFeeCap) 279 return (hexutil.Big)(*math.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee.ToInt()), tx.GasFeeCap())) 280 } 281 } 282 return hexutil.Big(*tx.GasPrice()) 283 default: 284 return hexutil.Big(*tx.GasPrice()) 285 } 286 } 287 288 func (t *Transaction) EffectiveGasPrice(ctx context.Context) (*hexutil.Big, error) { 289 tx, block := t.resolve(ctx) 290 if tx == nil { 291 return nil, nil 292 } 293 // Pending tx 294 if block == nil { 295 return nil, nil 296 } 297 header, err := block.resolveHeader(ctx) 298 if err != nil || header == nil { 299 return nil, err 300 } 301 if header.BaseFee == nil { 302 return (*hexutil.Big)(tx.GasPrice()), nil 303 } 304 return (*hexutil.Big)(math.BigMin(new(big.Int).Add(tx.GasTipCap(), header.BaseFee), tx.GasFeeCap())), nil 305 } 306 307 func (t *Transaction) MaxFeePerGas(ctx context.Context) *hexutil.Big { 308 tx, _ := t.resolve(ctx) 309 if tx == nil { 310 return nil 311 } 312 switch tx.Type() { 313 case types.DynamicFeeTxType, types.BlobTxType: 314 return (*hexutil.Big)(tx.GasFeeCap()) 315 default: 316 return nil 317 } 318 } 319 320 func (t *Transaction) MaxPriorityFeePerGas(ctx context.Context) *hexutil.Big { 321 tx, _ := t.resolve(ctx) 322 if tx == nil { 323 return nil 324 } 325 switch tx.Type() { 326 case types.DynamicFeeTxType, types.BlobTxType: 327 return (*hexutil.Big)(tx.GasTipCap()) 328 default: 329 return nil 330 } 331 } 332 333 func (t *Transaction) MaxFeePerBlobGas(ctx context.Context) *hexutil.Big { 334 tx, _ := t.resolve(ctx) 335 if tx == nil { 336 return nil 337 } 338 return (*hexutil.Big)(tx.BlobGasFeeCap()) 339 } 340 341 func (t *Transaction) BlobVersionedHashes(ctx context.Context) *[]common.Hash { 342 tx, _ := t.resolve(ctx) 343 if tx == nil { 344 return nil 345 } 346 if tx.Type() != types.BlobTxType { 347 return nil 348 } 349 blobHashes := tx.BlobHashes() 350 return &blobHashes 351 } 352 353 func (t *Transaction) EffectiveTip(ctx context.Context) (*hexutil.Big, error) { 354 tx, block := t.resolve(ctx) 355 if tx == nil { 356 return nil, nil 357 } 358 // Pending tx 359 if block == nil { 360 return nil, nil 361 } 362 header, err := block.resolveHeader(ctx) 363 if err != nil || header == nil { 364 return nil, err 365 } 366 if header.BaseFee == nil { 367 return (*hexutil.Big)(tx.GasPrice()), nil 368 } 369 370 tip, err := tx.EffectiveGasTip(header.BaseFee) 371 if err != nil { 372 return nil, err 373 } 374 return (*hexutil.Big)(tip), nil 375 } 376 377 func (t *Transaction) Value(ctx context.Context) (hexutil.Big, error) { 378 tx, _ := t.resolve(ctx) 379 if tx == nil { 380 return hexutil.Big{}, nil 381 } 382 if tx.Value() == nil { 383 return hexutil.Big{}, fmt.Errorf("invalid transaction value %x", t.hash) 384 } 385 return hexutil.Big(*tx.Value()), nil 386 } 387 388 func (t *Transaction) Nonce(ctx context.Context) hexutil.Uint64 { 389 tx, _ := t.resolve(ctx) 390 if tx == nil { 391 return 0 392 } 393 return hexutil.Uint64(tx.Nonce()) 394 } 395 396 func (t *Transaction) To(ctx context.Context, args BlockNumberArgs) *Account { 397 tx, _ := t.resolve(ctx) 398 if tx == nil { 399 return nil 400 } 401 to := tx.To() 402 if to == nil { 403 return nil 404 } 405 return &Account{ 406 r: t.r, 407 address: *to, 408 blockNrOrHash: args.NumberOrLatest(), 409 } 410 } 411 412 func (t *Transaction) From(ctx context.Context, args BlockNumberArgs) *Account { 413 tx, _ := t.resolve(ctx) 414 if tx == nil { 415 return nil 416 } 417 signer := types.LatestSigner(t.r.backend.ChainConfig()) 418 from, _ := types.Sender(signer, tx) 419 return &Account{ 420 r: t.r, 421 address: from, 422 blockNrOrHash: args.NumberOrLatest(), 423 } 424 } 425 426 func (t *Transaction) Block(ctx context.Context) *Block { 427 _, block := t.resolve(ctx) 428 return block 429 } 430 431 func (t *Transaction) Index(ctx context.Context) *hexutil.Uint64 { 432 _, block := t.resolve(ctx) 433 // Pending tx 434 if block == nil { 435 return nil 436 } 437 index := hexutil.Uint64(t.index) 438 return &index 439 } 440 441 // getReceipt returns the receipt associated with this transaction, if any. 442 func (t *Transaction) getReceipt(ctx context.Context) (*types.Receipt, error) { 443 _, block := t.resolve(ctx) 444 // Pending tx 445 if block == nil { 446 return nil, nil 447 } 448 receipts, err := block.resolveReceipts(ctx) 449 if err != nil { 450 return nil, err 451 } 452 return receipts[t.index], nil 453 } 454 455 func (t *Transaction) Status(ctx context.Context) (*hexutil.Uint64, error) { 456 receipt, err := t.getReceipt(ctx) 457 if err != nil || receipt == nil { 458 return nil, err 459 } 460 if len(receipt.PostState) != 0 { 461 return nil, nil 462 } 463 ret := hexutil.Uint64(receipt.Status) 464 return &ret, nil 465 } 466 467 func (t *Transaction) GasUsed(ctx context.Context) (*hexutil.Uint64, error) { 468 receipt, err := t.getReceipt(ctx) 469 if err != nil || receipt == nil { 470 return nil, err 471 } 472 ret := hexutil.Uint64(receipt.GasUsed) 473 return &ret, nil 474 } 475 476 func (t *Transaction) CumulativeGasUsed(ctx context.Context) (*hexutil.Uint64, error) { 477 receipt, err := t.getReceipt(ctx) 478 if err != nil || receipt == nil { 479 return nil, err 480 } 481 ret := hexutil.Uint64(receipt.CumulativeGasUsed) 482 return &ret, nil 483 } 484 485 func (t *Transaction) BlobGasUsed(ctx context.Context) (*hexutil.Uint64, error) { 486 tx, _ := t.resolve(ctx) 487 if tx == nil { 488 return nil, nil 489 } 490 if tx.Type() != types.BlobTxType { 491 return nil, nil 492 } 493 494 receipt, err := t.getReceipt(ctx) 495 if err != nil || receipt == nil { 496 return nil, err 497 } 498 ret := hexutil.Uint64(receipt.BlobGasUsed) 499 return &ret, nil 500 } 501 502 func (t *Transaction) BlobGasPrice(ctx context.Context) (*hexutil.Big, error) { 503 tx, _ := t.resolve(ctx) 504 if tx == nil { 505 return nil, nil 506 } 507 if tx.Type() != types.BlobTxType { 508 return nil, nil 509 } 510 511 receipt, err := t.getReceipt(ctx) 512 if err != nil || receipt == nil { 513 return nil, err 514 } 515 ret := (*hexutil.Big)(receipt.BlobGasPrice) 516 return ret, nil 517 } 518 519 func (t *Transaction) CreatedContract(ctx context.Context, args BlockNumberArgs) (*Account, error) { 520 receipt, err := t.getReceipt(ctx) 521 if err != nil || receipt == nil || receipt.ContractAddress == (common.Address{}) { 522 return nil, err 523 } 524 return &Account{ 525 r: t.r, 526 address: receipt.ContractAddress, 527 blockNrOrHash: args.NumberOrLatest(), 528 }, nil 529 } 530 531 func (t *Transaction) Logs(ctx context.Context) (*[]*Log, error) { 532 _, block := t.resolve(ctx) 533 // Pending tx 534 if block == nil { 535 return nil, nil 536 } 537 h, err := block.Hash(ctx) 538 if err != nil { 539 return nil, err 540 } 541 return t.getLogs(ctx, h) 542 } 543 544 // getLogs returns log objects for the given tx. 545 // Assumes block hash is resolved. 546 func (t *Transaction) getLogs(ctx context.Context, hash common.Hash) (*[]*Log, error) { 547 var ( 548 filter = t.r.filterSystem.NewBlockFilter(hash, nil, nil) 549 logs, err = filter.Logs(ctx) 550 ) 551 if err != nil { 552 return nil, err 553 } 554 var ret []*Log 555 // Select tx logs from all block logs 556 ix := sort.Search(len(logs), func(i int) bool { return uint64(logs[i].TxIndex) >= t.index }) 557 for ix < len(logs) && uint64(logs[ix].TxIndex) == t.index { 558 ret = append(ret, &Log{ 559 r: t.r, 560 transaction: t, 561 log: logs[ix], 562 }) 563 ix++ 564 } 565 return &ret, nil 566 } 567 568 func (t *Transaction) Type(ctx context.Context) *hexutil.Uint64 { 569 tx, _ := t.resolve(ctx) 570 txType := hexutil.Uint64(tx.Type()) 571 return &txType 572 } 573 574 func (t *Transaction) AccessList(ctx context.Context) *[]*AccessTuple { 575 tx, _ := t.resolve(ctx) 576 if tx == nil { 577 return nil 578 } 579 accessList := tx.AccessList() 580 ret := make([]*AccessTuple, 0, len(accessList)) 581 for _, al := range accessList { 582 ret = append(ret, &AccessTuple{ 583 address: al.Address, 584 storageKeys: al.StorageKeys, 585 }) 586 } 587 return &ret 588 } 589 func (t *Transaction) PublicKey(ctx context.Context) (hexutil.Bytes, error) { 590 tx, _ := t.resolve(ctx) 591 if tx == nil { 592 return hexutil.Bytes{}, nil 593 } 594 return tx.RawPublicKeyValue(), nil 595 } 596 597 func (t *Transaction) Signature(ctx context.Context) (hexutil.Bytes, error) { 598 tx, err := t.resolve(ctx) 599 if err != nil || tx == nil { 600 return hexutil.Bytes{}, nil 601 } 602 return tx.RawSignatureValue(), nil 603 } 604 func (t *Transaction) Raw(ctx context.Context) (hexutil.Bytes, error) { 605 tx, _ := t.resolve(ctx) 606 if tx == nil { 607 return hexutil.Bytes{}, nil 608 } 609 return tx.MarshalBinary() 610 } 611 612 func (t *Transaction) RawReceipt(ctx context.Context) (hexutil.Bytes, error) { 613 receipt, err := t.getReceipt(ctx) 614 if err != nil || receipt == nil { 615 return hexutil.Bytes{}, err 616 } 617 return receipt.MarshalBinary() 618 } 619 620 type BlockType int 621 622 // Block represents an Ethereum block. 623 // backend, and numberOrHash are mandatory. All other fields are lazily fetched 624 // when required. 625 type Block struct { 626 r *Resolver 627 numberOrHash *rpc.BlockNumberOrHash // Field resolvers assume numberOrHash is always present 628 mu sync.Mutex 629 // mu protects following resources 630 hash common.Hash // Must be resolved during initialization 631 header *types.Header 632 block *types.Block 633 receipts []*types.Receipt 634 } 635 636 // resolve returns the internal Block object representing this block, fetching 637 // it if necessary. 638 func (b *Block) resolve(ctx context.Context) (*types.Block, error) { 639 b.mu.Lock() 640 defer b.mu.Unlock() 641 if b.block != nil { 642 return b.block, nil 643 } 644 if b.numberOrHash == nil { 645 latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) 646 b.numberOrHash = &latest 647 } 648 var err error 649 b.block, err = b.r.backend.BlockByNumberOrHash(ctx, *b.numberOrHash) 650 if b.block != nil { 651 b.hash = b.block.Hash() 652 if b.header == nil { 653 b.header = b.block.Header() 654 } 655 } 656 return b.block, err 657 } 658 659 // resolveHeader returns the internal Header object for this block, fetching it 660 // if necessary. Call this function instead of `resolve` unless you need the 661 // additional data (transactions and uncles). 662 func (b *Block) resolveHeader(ctx context.Context) (*types.Header, error) { 663 b.mu.Lock() 664 defer b.mu.Unlock() 665 if b.header != nil { 666 return b.header, nil 667 } 668 if b.numberOrHash == nil && b.hash == (common.Hash{}) { 669 return nil, errBlockInvariant 670 } 671 var err error 672 b.header, err = b.r.backend.HeaderByNumberOrHash(ctx, *b.numberOrHash) 673 if err != nil { 674 return nil, err 675 } 676 if b.hash == (common.Hash{}) { 677 b.hash = b.header.Hash() 678 } 679 return b.header, nil 680 } 681 682 // resolveReceipts returns the list of receipts for this block, fetching them 683 // if necessary. 684 func (b *Block) resolveReceipts(ctx context.Context) ([]*types.Receipt, error) { 685 b.mu.Lock() 686 defer b.mu.Unlock() 687 if b.receipts != nil { 688 return b.receipts, nil 689 } 690 receipts, err := b.r.backend.GetReceipts(ctx, b.hash) 691 if err != nil { 692 return nil, err 693 } 694 b.receipts = receipts 695 return receipts, nil 696 } 697 698 func (b *Block) Number(ctx context.Context) (hexutil.Uint64, error) { 699 header, err := b.resolveHeader(ctx) 700 if err != nil { 701 return 0, err 702 } 703 704 return hexutil.Uint64(header.Number.Uint64()), nil 705 } 706 707 func (b *Block) Hash(ctx context.Context) (common.Hash, error) { 708 b.mu.Lock() 709 defer b.mu.Unlock() 710 return b.hash, nil 711 } 712 713 func (b *Block) GasLimit(ctx context.Context) (hexutil.Uint64, error) { 714 header, err := b.resolveHeader(ctx) 715 if err != nil { 716 return 0, err 717 } 718 return hexutil.Uint64(header.GasLimit), nil 719 } 720 721 func (b *Block) GasUsed(ctx context.Context) (hexutil.Uint64, error) { 722 header, err := b.resolveHeader(ctx) 723 if err != nil { 724 return 0, err 725 } 726 return hexutil.Uint64(header.GasUsed), nil 727 } 728 729 func (b *Block) BaseFeePerGas(ctx context.Context) (*hexutil.Big, error) { 730 header, err := b.resolveHeader(ctx) 731 if err != nil { 732 return nil, err 733 } 734 if header.BaseFee == nil { 735 return nil, nil 736 } 737 return (*hexutil.Big)(header.BaseFee), nil 738 } 739 740 func (b *Block) NextBaseFeePerGas(ctx context.Context) (*hexutil.Big, error) { 741 header, err := b.resolveHeader(ctx) 742 if err != nil { 743 return nil, err 744 } 745 chaincfg := b.r.backend.ChainConfig() 746 if header.BaseFee == nil { 747 // Make sure next block doesn't enable EIP-1559 748 if !chaincfg.IsLondon(new(big.Int).Add(header.Number, common.Big1)) { 749 return nil, nil 750 } 751 } 752 nextBaseFee := eip1559.CalcBaseFee(chaincfg, header) 753 return (*hexutil.Big)(nextBaseFee), nil 754 } 755 756 func (b *Block) Parent(ctx context.Context) (*Block, error) { 757 if _, err := b.resolveHeader(ctx); err != nil { 758 return nil, err 759 } 760 if b.header == nil || b.header.Number.Uint64() < 1 { 761 return nil, nil 762 } 763 var ( 764 num = rpc.BlockNumber(b.header.Number.Uint64() - 1) 765 hash = b.header.ParentHash 766 numOrHash = rpc.BlockNumberOrHash{ 767 BlockNumber: &num, 768 BlockHash: &hash, 769 } 770 ) 771 return &Block{ 772 r: b.r, 773 numberOrHash: &numOrHash, 774 hash: hash, 775 }, nil 776 } 777 778 func (b *Block) Difficulty(ctx context.Context) (hexutil.Big, error) { 779 header, err := b.resolveHeader(ctx) 780 if err != nil { 781 return hexutil.Big{}, err 782 } 783 return hexutil.Big(*header.Difficulty), nil 784 } 785 786 func (b *Block) Timestamp(ctx context.Context) (hexutil.Uint64, error) { 787 header, err := b.resolveHeader(ctx) 788 if err != nil { 789 return 0, err 790 } 791 return hexutil.Uint64(header.Time), nil 792 } 793 794 func (b *Block) Nonce(ctx context.Context) (hexutil.Bytes, error) { 795 header, err := b.resolveHeader(ctx) 796 if err != nil { 797 return hexutil.Bytes{}, err 798 } 799 return header.Nonce[:], nil 800 } 801 802 func (b *Block) MixHash(ctx context.Context) (common.Hash, error) { 803 header, err := b.resolveHeader(ctx) 804 if err != nil { 805 return common.Hash{}, err 806 } 807 return header.MixDigest, nil 808 } 809 810 func (b *Block) TransactionsRoot(ctx context.Context) (common.Hash, error) { 811 header, err := b.resolveHeader(ctx) 812 if err != nil { 813 return common.Hash{}, err 814 } 815 return header.TxHash, nil 816 } 817 818 func (b *Block) StateRoot(ctx context.Context) (common.Hash, error) { 819 header, err := b.resolveHeader(ctx) 820 if err != nil { 821 return common.Hash{}, err 822 } 823 return header.Root, nil 824 } 825 826 func (b *Block) ReceiptsRoot(ctx context.Context) (common.Hash, error) { 827 header, err := b.resolveHeader(ctx) 828 if err != nil { 829 return common.Hash{}, err 830 } 831 return header.ReceiptHash, nil 832 } 833 834 func (b *Block) OmmerHash(ctx context.Context) (common.Hash, error) { 835 header, err := b.resolveHeader(ctx) 836 if err != nil { 837 return common.Hash{}, err 838 } 839 return header.UncleHash, nil 840 } 841 842 func (b *Block) OmmerCount(ctx context.Context) (*hexutil.Uint64, error) { 843 block, err := b.resolve(ctx) 844 if err != nil || block == nil { 845 return nil, err 846 } 847 count := hexutil.Uint64(len(block.Uncles())) 848 return &count, err 849 } 850 851 func (b *Block) Ommers(ctx context.Context) (*[]*Block, error) { 852 block, err := b.resolve(ctx) 853 if err != nil || block == nil { 854 return nil, err 855 } 856 ret := make([]*Block, 0, len(block.Uncles())) 857 for _, uncle := range block.Uncles() { 858 blockNumberOrHash := rpc.BlockNumberOrHashWithHash(uncle.Hash(), false) 859 ret = append(ret, &Block{ 860 r: b.r, 861 numberOrHash: &blockNumberOrHash, 862 header: uncle, 863 hash: uncle.Hash(), 864 }) 865 } 866 return &ret, nil 867 } 868 869 func (b *Block) ExtraData(ctx context.Context) (hexutil.Bytes, error) { 870 header, err := b.resolveHeader(ctx) 871 if err != nil { 872 return hexutil.Bytes{}, err 873 } 874 return header.Extra, nil 875 } 876 877 func (b *Block) LogsBloom(ctx context.Context) (hexutil.Bytes, error) { 878 header, err := b.resolveHeader(ctx) 879 if err != nil { 880 return hexutil.Bytes{}, err 881 } 882 return header.Bloom.Bytes(), nil 883 } 884 885 func (b *Block) TotalDifficulty(ctx context.Context) (hexutil.Big, error) { 886 hash, err := b.Hash(ctx) 887 if err != nil { 888 return hexutil.Big{}, err 889 } 890 td := b.r.backend.GetTd(ctx, hash) 891 if td == nil { 892 return hexutil.Big{}, fmt.Errorf("total difficulty not found %x", hash) 893 } 894 return hexutil.Big(*td), nil 895 } 896 897 func (b *Block) RawHeader(ctx context.Context) (hexutil.Bytes, error) { 898 header, err := b.resolveHeader(ctx) 899 if err != nil { 900 return hexutil.Bytes{}, err 901 } 902 return rlp.EncodeToBytes(header) 903 } 904 905 func (b *Block) Raw(ctx context.Context) (hexutil.Bytes, error) { 906 block, err := b.resolve(ctx) 907 if err != nil { 908 return hexutil.Bytes{}, err 909 } 910 return rlp.EncodeToBytes(block) 911 } 912 913 // BlockNumberArgs encapsulates arguments to accessors that specify a block number. 914 type BlockNumberArgs struct { 915 // TODO: Ideally we could use input unions to allow the query to specify the 916 // block parameter by hash, block number, or tag but input unions aren't part of the 917 // standard GraphQL schema SDL yet, see: https://github.com/graphql/graphql-spec/issues/488 918 Block *Long 919 } 920 921 // NumberOr returns the provided block number argument, or the "current" block number or hash if none 922 // was provided. 923 func (a BlockNumberArgs) NumberOr(current rpc.BlockNumberOrHash) rpc.BlockNumberOrHash { 924 if a.Block != nil { 925 blockNr := rpc.BlockNumber(*a.Block) 926 return rpc.BlockNumberOrHashWithNumber(blockNr) 927 } 928 return current 929 } 930 931 // NumberOrLatest returns the provided block number argument, or the "latest" block number if none 932 // was provided. 933 func (a BlockNumberArgs) NumberOrLatest() rpc.BlockNumberOrHash { 934 return a.NumberOr(rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)) 935 } 936 937 func (b *Block) Miner(ctx context.Context, args BlockNumberArgs) (*Account, error) { 938 header, err := b.resolveHeader(ctx) 939 if err != nil { 940 return nil, err 941 } 942 return &Account{ 943 r: b.r, 944 address: header.Coinbase, 945 blockNrOrHash: args.NumberOrLatest(), 946 }, nil 947 } 948 949 func (b *Block) TransactionCount(ctx context.Context) (*hexutil.Uint64, error) { 950 block, err := b.resolve(ctx) 951 if err != nil || block == nil { 952 return nil, err 953 } 954 count := hexutil.Uint64(len(block.Transactions())) 955 return &count, err 956 } 957 958 func (b *Block) Transactions(ctx context.Context) (*[]*Transaction, error) { 959 block, err := b.resolve(ctx) 960 if err != nil || block == nil { 961 return nil, err 962 } 963 ret := make([]*Transaction, 0, len(block.Transactions())) 964 for i, tx := range block.Transactions() { 965 ret = append(ret, &Transaction{ 966 r: b.r, 967 hash: tx.Hash(), 968 tx: tx, 969 block: b, 970 index: uint64(i), 971 }) 972 } 973 return &ret, nil 974 } 975 976 func (b *Block) TransactionAt(ctx context.Context, args struct{ Index Long }) (*Transaction, error) { 977 block, err := b.resolve(ctx) 978 if err != nil || block == nil { 979 return nil, err 980 } 981 txs := block.Transactions() 982 if args.Index < 0 || int(args.Index) >= len(txs) { 983 return nil, nil 984 } 985 tx := txs[args.Index] 986 return &Transaction{ 987 r: b.r, 988 hash: tx.Hash(), 989 tx: tx, 990 block: b, 991 index: uint64(args.Index), 992 }, nil 993 } 994 995 func (b *Block) OmmerAt(ctx context.Context, args struct{ Index Long }) (*Block, error) { 996 block, err := b.resolve(ctx) 997 if err != nil || block == nil { 998 return nil, err 999 } 1000 uncles := block.Uncles() 1001 if args.Index < 0 || int(args.Index) >= len(uncles) { 1002 return nil, nil 1003 } 1004 uncle := uncles[args.Index] 1005 blockNumberOrHash := rpc.BlockNumberOrHashWithHash(uncle.Hash(), false) 1006 return &Block{ 1007 r: b.r, 1008 numberOrHash: &blockNumberOrHash, 1009 header: uncle, 1010 hash: uncle.Hash(), 1011 }, nil 1012 } 1013 1014 func (b *Block) WithdrawalsRoot(ctx context.Context) (*common.Hash, error) { 1015 header, err := b.resolveHeader(ctx) 1016 if err != nil { 1017 return nil, err 1018 } 1019 // Pre-shanghai blocks 1020 if header.WithdrawalsHash == nil { 1021 return nil, nil 1022 } 1023 return header.WithdrawalsHash, nil 1024 } 1025 1026 func (b *Block) Withdrawals(ctx context.Context) (*[]*Withdrawal, error) { 1027 block, err := b.resolve(ctx) 1028 if err != nil || block == nil { 1029 return nil, err 1030 } 1031 // Pre-shanghai blocks 1032 if block.Header().WithdrawalsHash == nil { 1033 return nil, nil 1034 } 1035 ret := make([]*Withdrawal, 0, len(block.Withdrawals())) 1036 for _, w := range block.Withdrawals() { 1037 ret = append(ret, &Withdrawal{ 1038 index: w.Index, 1039 validator: w.Validator, 1040 address: w.Address, 1041 amount: w.Amount, 1042 }) 1043 } 1044 return &ret, nil 1045 } 1046 1047 func (b *Block) BlobGasUsed(ctx context.Context) (*hexutil.Uint64, error) { 1048 header, err := b.resolveHeader(ctx) 1049 if err != nil { 1050 return nil, err 1051 } 1052 if header.BlobGasUsed == nil { 1053 return nil, nil 1054 } 1055 ret := hexutil.Uint64(*header.BlobGasUsed) 1056 return &ret, nil 1057 } 1058 1059 func (b *Block) ExcessBlobGas(ctx context.Context) (*hexutil.Uint64, error) { 1060 header, err := b.resolveHeader(ctx) 1061 if err != nil { 1062 return nil, err 1063 } 1064 if header.ExcessBlobGas == nil { 1065 return nil, nil 1066 } 1067 ret := hexutil.Uint64(*header.ExcessBlobGas) 1068 return &ret, nil 1069 } 1070 1071 // BlockFilterCriteria encapsulates criteria passed to a `logs` accessor inside 1072 // a block. 1073 type BlockFilterCriteria struct { 1074 Addresses *[]common.Address // restricts matches to events created by specific contracts 1075 1076 // The Topic list restricts matches to particular event topics. Each event has a list 1077 // of topics. Topics matches a prefix of that list. An empty element slice matches any 1078 // topic. Non-empty elements represent an alternative that matches any of the 1079 // contained topics. 1080 // 1081 // Examples: 1082 // {} or nil matches any topic list 1083 // {{A}} matches topic A in first position 1084 // {{}, {B}} matches any topic in first position, B in second position 1085 // {{A}, {B}} matches topic A in first position, B in second position 1086 // {{A, B}}, {C, D}} matches topic (A OR B) in first position, (C OR D) in second position 1087 Topics *[][]common.Hash 1088 } 1089 1090 // runFilter accepts a filter and executes it, returning all its results as 1091 // `Log` objects. 1092 func runFilter(ctx context.Context, r *Resolver, filter *filters.Filter) ([]*Log, error) { 1093 logs, err := filter.Logs(ctx) 1094 if err != nil || logs == nil { 1095 return nil, err 1096 } 1097 ret := make([]*Log, 0, len(logs)) 1098 for _, log := range logs { 1099 ret = append(ret, &Log{ 1100 r: r, 1101 transaction: &Transaction{r: r, hash: log.TxHash}, 1102 log: log, 1103 }) 1104 } 1105 return ret, nil 1106 } 1107 1108 func (b *Block) Logs(ctx context.Context, args struct{ Filter BlockFilterCriteria }) ([]*Log, error) { 1109 var addresses []common.Address 1110 if args.Filter.Addresses != nil { 1111 addresses = *args.Filter.Addresses 1112 } 1113 var topics [][]common.Hash 1114 if args.Filter.Topics != nil { 1115 topics = *args.Filter.Topics 1116 } 1117 // Construct the range filter 1118 hash, err := b.Hash(ctx) 1119 if err != nil { 1120 return nil, err 1121 } 1122 filter := b.r.filterSystem.NewBlockFilter(hash, addresses, topics) 1123 1124 // Run the filter and return all the logs 1125 return runFilter(ctx, b.r, filter) 1126 } 1127 1128 func (b *Block) Account(ctx context.Context, args struct { 1129 Address common.Address 1130 }) (*Account, error) { 1131 return &Account{ 1132 r: b.r, 1133 address: args.Address, 1134 blockNrOrHash: *b.numberOrHash, 1135 }, nil 1136 } 1137 1138 // CallData encapsulates arguments to `call` or `estimateGas`. 1139 // All arguments are optional. 1140 type CallData struct { 1141 From *common.Address // The Ethereum address the call is from. 1142 To *common.Address // The Ethereum address the call is to. 1143 Gas *Long // The amount of gas provided for the call. 1144 GasPrice *hexutil.Big // The price of each unit of gas, in wei. 1145 MaxFeePerGas *hexutil.Big // The max price of each unit of gas, in wei (1559). 1146 MaxPriorityFeePerGas *hexutil.Big // The max tip of each unit of gas, in wei (1559). 1147 Value *hexutil.Big // The value sent along with the call. 1148 Data *hexutil.Bytes // Any data sent with the call. 1149 } 1150 1151 // CallResult encapsulates the result of an invocation of the `call` accessor. 1152 type CallResult struct { 1153 data hexutil.Bytes // The return data from the call 1154 gasUsed hexutil.Uint64 // The amount of gas used 1155 status hexutil.Uint64 // The return status of the call - 0 for failure or 1 for success. 1156 } 1157 1158 func (c *CallResult) Data() hexutil.Bytes { 1159 return c.data 1160 } 1161 1162 func (c *CallResult) GasUsed() hexutil.Uint64 { 1163 return c.gasUsed 1164 } 1165 1166 func (c *CallResult) Status() hexutil.Uint64 { 1167 return c.status 1168 } 1169 1170 func (b *Block) Call(ctx context.Context, args struct { 1171 Data ethapi.TransactionArgs 1172 }) (*CallResult, error) { 1173 result, err := ethapi.DoCall(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, nil, b.r.backend.RPCEVMTimeout(), b.r.backend.RPCGasCap()) 1174 if err != nil { 1175 return nil, err 1176 } 1177 status := hexutil.Uint64(1) 1178 if result.Failed() { 1179 status = 0 1180 } 1181 1182 return &CallResult{ 1183 data: result.ReturnData, 1184 gasUsed: hexutil.Uint64(result.UsedGas), 1185 status: status, 1186 }, nil 1187 } 1188 1189 func (b *Block) EstimateGas(ctx context.Context, args struct { 1190 Data ethapi.TransactionArgs 1191 }) (hexutil.Uint64, error) { 1192 return ethapi.DoEstimateGas(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, b.r.backend.RPCGasCap()) 1193 } 1194 1195 type Pending struct { 1196 r *Resolver 1197 } 1198 1199 func (p *Pending) TransactionCount(ctx context.Context) (hexutil.Uint64, error) { 1200 txs, err := p.r.backend.GetPoolTransactions() 1201 return hexutil.Uint64(len(txs)), err 1202 } 1203 1204 func (p *Pending) Transactions(ctx context.Context) (*[]*Transaction, error) { 1205 txs, err := p.r.backend.GetPoolTransactions() 1206 if err != nil { 1207 return nil, err 1208 } 1209 ret := make([]*Transaction, 0, len(txs)) 1210 for i, tx := range txs { 1211 ret = append(ret, &Transaction{ 1212 r: p.r, 1213 hash: tx.Hash(), 1214 tx: tx, 1215 index: uint64(i), 1216 }) 1217 } 1218 return &ret, nil 1219 } 1220 1221 func (p *Pending) Account(ctx context.Context, args struct { 1222 Address common.Address 1223 }) *Account { 1224 pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) 1225 return &Account{ 1226 r: p.r, 1227 address: args.Address, 1228 blockNrOrHash: pendingBlockNr, 1229 } 1230 } 1231 1232 func (p *Pending) Call(ctx context.Context, args struct { 1233 Data ethapi.TransactionArgs 1234 }) (*CallResult, error) { 1235 pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) 1236 result, err := ethapi.DoCall(ctx, p.r.backend, args.Data, pendingBlockNr, nil, nil, p.r.backend.RPCEVMTimeout(), p.r.backend.RPCGasCap()) 1237 if err != nil { 1238 return nil, err 1239 } 1240 status := hexutil.Uint64(1) 1241 if result.Failed() { 1242 status = 0 1243 } 1244 1245 return &CallResult{ 1246 data: result.ReturnData, 1247 gasUsed: hexutil.Uint64(result.UsedGas), 1248 status: status, 1249 }, nil 1250 } 1251 1252 func (p *Pending) EstimateGas(ctx context.Context, args struct { 1253 Data ethapi.TransactionArgs 1254 }) (hexutil.Uint64, error) { 1255 latestBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) 1256 return ethapi.DoEstimateGas(ctx, p.r.backend, args.Data, latestBlockNr, nil, p.r.backend.RPCGasCap()) 1257 } 1258 1259 // Resolver is the top-level object in the GraphQL hierarchy. 1260 type Resolver struct { 1261 backend ethapi.Backend 1262 filterSystem *filters.FilterSystem 1263 } 1264 1265 func (r *Resolver) Block(ctx context.Context, args struct { 1266 Number *Long 1267 Hash *common.Hash 1268 }) (*Block, error) { 1269 if args.Number != nil && args.Hash != nil { 1270 return nil, errors.New("only one of number or hash must be specified") 1271 } 1272 var numberOrHash rpc.BlockNumberOrHash 1273 if args.Number != nil { 1274 if *args.Number < 0 { 1275 return nil, nil 1276 } 1277 number := rpc.BlockNumber(*args.Number) 1278 numberOrHash = rpc.BlockNumberOrHashWithNumber(number) 1279 } else if args.Hash != nil { 1280 numberOrHash = rpc.BlockNumberOrHashWithHash(*args.Hash, false) 1281 } else { 1282 numberOrHash = rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) 1283 } 1284 block := &Block{ 1285 r: r, 1286 numberOrHash: &numberOrHash, 1287 } 1288 // Resolve the header, return nil if it doesn't exist. 1289 // Note we don't resolve block directly here since it will require an 1290 // additional network request for light client. 1291 h, err := block.resolveHeader(ctx) 1292 if err != nil { 1293 return nil, err 1294 } else if h == nil { 1295 return nil, nil 1296 } 1297 return block, nil 1298 } 1299 1300 func (r *Resolver) Blocks(ctx context.Context, args struct { 1301 From *Long 1302 To *Long 1303 }) ([]*Block, error) { 1304 from := rpc.BlockNumber(*args.From) 1305 1306 var to rpc.BlockNumber 1307 if args.To != nil { 1308 to = rpc.BlockNumber(*args.To) 1309 } else { 1310 to = rpc.BlockNumber(r.backend.CurrentBlock().Number.Int64()) 1311 } 1312 if to < from { 1313 return []*Block{}, nil 1314 } 1315 var ret []*Block 1316 for i := from; i <= to; i++ { 1317 numberOrHash := rpc.BlockNumberOrHashWithNumber(i) 1318 block := &Block{ 1319 r: r, 1320 numberOrHash: &numberOrHash, 1321 } 1322 // Resolve the header to check for existence. 1323 // Note we don't resolve block directly here since it will require an 1324 // additional network request for light client. 1325 h, err := block.resolveHeader(ctx) 1326 if err != nil { 1327 return nil, err 1328 } else if h == nil { 1329 // Blocks after must be non-existent too, break. 1330 break 1331 } 1332 ret = append(ret, block) 1333 if err := ctx.Err(); err != nil { 1334 return nil, err 1335 } 1336 } 1337 return ret, nil 1338 } 1339 1340 func (r *Resolver) Pending(ctx context.Context) *Pending { 1341 return &Pending{r} 1342 } 1343 1344 func (r *Resolver) Transaction(ctx context.Context, args struct{ Hash common.Hash }) *Transaction { 1345 tx := &Transaction{ 1346 r: r, 1347 hash: args.Hash, 1348 } 1349 // Resolve the transaction; if it doesn't exist, return nil. 1350 t, _ := tx.resolve(ctx) 1351 if t == nil { 1352 return nil 1353 } 1354 return tx 1355 } 1356 1357 func (r *Resolver) SendRawTransaction(ctx context.Context, args struct{ Data hexutil.Bytes }) (common.Hash, error) { 1358 tx := new(types.Transaction) 1359 if err := tx.UnmarshalBinary(args.Data); err != nil { 1360 return common.Hash{}, err 1361 } 1362 hash, err := ethapi.SubmitTransaction(ctx, r.backend, tx) 1363 return hash, err 1364 } 1365 1366 // FilterCriteria encapsulates the arguments to `logs` on the root resolver object. 1367 type FilterCriteria struct { 1368 FromBlock *Long // beginning of the queried range, nil means genesis block 1369 ToBlock *Long // end of the range, nil means latest block 1370 Addresses *[]common.Address // restricts matches to events created by specific contracts 1371 1372 // The Topic list restricts matches to particular event topics. Each event has a list 1373 // of topics. Topics matches a prefix of that list. An empty element slice matches any 1374 // topic. Non-empty elements represent an alternative that matches any of the 1375 // contained topics. 1376 // 1377 // Examples: 1378 // {} or nil matches any topic list 1379 // {{A}} matches topic A in first position 1380 // {{}, {B}} matches any topic in first position, B in second position 1381 // {{A}, {B}} matches topic A in first position, B in second position 1382 // {{A, B}}, {C, D}} matches topic (A OR B) in first position, (C OR D) in second position 1383 Topics *[][]common.Hash 1384 } 1385 1386 func (r *Resolver) Logs(ctx context.Context, args struct{ Filter FilterCriteria }) ([]*Log, error) { 1387 // Convert the RPC block numbers into internal representations 1388 begin := rpc.LatestBlockNumber.Int64() 1389 if args.Filter.FromBlock != nil { 1390 begin = int64(*args.Filter.FromBlock) 1391 } 1392 end := rpc.LatestBlockNumber.Int64() 1393 if args.Filter.ToBlock != nil { 1394 end = int64(*args.Filter.ToBlock) 1395 } 1396 var addresses []common.Address 1397 if args.Filter.Addresses != nil { 1398 addresses = *args.Filter.Addresses 1399 } 1400 var topics [][]common.Hash 1401 if args.Filter.Topics != nil { 1402 topics = *args.Filter.Topics 1403 } 1404 // Construct the range filter 1405 filter := r.filterSystem.NewRangeFilter(begin, end, addresses, topics) 1406 return runFilter(ctx, r, filter) 1407 } 1408 1409 func (r *Resolver) GasPrice(ctx context.Context) (hexutil.Big, error) { 1410 tipcap, err := r.backend.SuggestGasTipCap(ctx) 1411 if err != nil { 1412 return hexutil.Big{}, err 1413 } 1414 if head := r.backend.CurrentHeader(); head.BaseFee != nil { 1415 tipcap.Add(tipcap, head.BaseFee) 1416 } 1417 return (hexutil.Big)(*tipcap), nil 1418 } 1419 1420 func (r *Resolver) MaxPriorityFeePerGas(ctx context.Context) (hexutil.Big, error) { 1421 tipcap, err := r.backend.SuggestGasTipCap(ctx) 1422 if err != nil { 1423 return hexutil.Big{}, err 1424 } 1425 return (hexutil.Big)(*tipcap), nil 1426 } 1427 1428 func (r *Resolver) ChainID(ctx context.Context) (hexutil.Big, error) { 1429 return hexutil.Big(*r.backend.ChainConfig().ChainID), nil 1430 } 1431 1432 // SyncState represents the synchronisation status returned from the `syncing` accessor. 1433 type SyncState struct { 1434 progress zond.SyncProgress 1435 } 1436 1437 func (s *SyncState) StartingBlock() hexutil.Uint64 { 1438 return hexutil.Uint64(s.progress.StartingBlock) 1439 } 1440 func (s *SyncState) CurrentBlock() hexutil.Uint64 { 1441 return hexutil.Uint64(s.progress.CurrentBlock) 1442 } 1443 func (s *SyncState) HighestBlock() hexutil.Uint64 { 1444 return hexutil.Uint64(s.progress.HighestBlock) 1445 } 1446 func (s *SyncState) SyncedAccounts() hexutil.Uint64 { 1447 return hexutil.Uint64(s.progress.SyncedAccounts) 1448 } 1449 func (s *SyncState) SyncedAccountBytes() hexutil.Uint64 { 1450 return hexutil.Uint64(s.progress.SyncedAccountBytes) 1451 } 1452 func (s *SyncState) SyncedBytecodes() hexutil.Uint64 { 1453 return hexutil.Uint64(s.progress.SyncedBytecodes) 1454 } 1455 func (s *SyncState) SyncedBytecodeBytes() hexutil.Uint64 { 1456 return hexutil.Uint64(s.progress.SyncedBytecodeBytes) 1457 } 1458 func (s *SyncState) SyncedStorage() hexutil.Uint64 { 1459 return hexutil.Uint64(s.progress.SyncedStorage) 1460 } 1461 func (s *SyncState) SyncedStorageBytes() hexutil.Uint64 { 1462 return hexutil.Uint64(s.progress.SyncedStorageBytes) 1463 } 1464 func (s *SyncState) HealedTrienodes() hexutil.Uint64 { 1465 return hexutil.Uint64(s.progress.HealedTrienodes) 1466 } 1467 func (s *SyncState) HealedTrienodeBytes() hexutil.Uint64 { 1468 return hexutil.Uint64(s.progress.HealedTrienodeBytes) 1469 } 1470 func (s *SyncState) HealedBytecodes() hexutil.Uint64 { 1471 return hexutil.Uint64(s.progress.HealedBytecodes) 1472 } 1473 func (s *SyncState) HealedBytecodeBytes() hexutil.Uint64 { 1474 return hexutil.Uint64(s.progress.HealedBytecodeBytes) 1475 } 1476 func (s *SyncState) HealingTrienodes() hexutil.Uint64 { 1477 return hexutil.Uint64(s.progress.HealingTrienodes) 1478 } 1479 func (s *SyncState) HealingBytecode() hexutil.Uint64 { 1480 return hexutil.Uint64(s.progress.HealingBytecode) 1481 } 1482 1483 // Syncing returns false in case the node is currently not syncing with the network. It can be up-to-date or has not 1484 // yet received the latest block headers from its pears. In case it is synchronizing: 1485 // - startingBlock: block number this node started to synchronize from 1486 // - currentBlock: block number this node is currently importing 1487 // - highestBlock: block number of the highest block header this node has received from peers 1488 // - syncedAccounts: number of accounts downloaded 1489 // - syncedAccountBytes: number of account trie bytes persisted to disk 1490 // - syncedBytecodes: number of bytecodes downloaded 1491 // - syncedBytecodeBytes: number of bytecode bytes downloaded 1492 // - syncedStorage: number of storage slots downloaded 1493 // - syncedStorageBytes: number of storage trie bytes persisted to disk 1494 // - healedTrienodes: number of state trie nodes downloaded 1495 // - healedTrienodeBytes: number of state trie bytes persisted to disk 1496 // - healedBytecodes: number of bytecodes downloaded 1497 // - healedBytecodeBytes: number of bytecodes persisted to disk 1498 // - healingTrienodes: number of state trie nodes pending 1499 // - healingBytecode: number of bytecodes pending 1500 func (r *Resolver) Syncing() (*SyncState, error) { 1501 progress := r.backend.SyncProgress() 1502 1503 // Return not syncing if the synchronisation already completed 1504 if progress.CurrentBlock >= progress.HighestBlock { 1505 return nil, nil 1506 } 1507 // Otherwise gather the block sync stats 1508 return &SyncState{progress}, nil 1509 }