github.com/dominant-strategies/go-quai@v0.28.2/internal/quaiapi/quai_api.go (about)

     1  // Copyright 2015 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 quaiapi
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"errors"
    23  	"math/big"
    24  	"time"
    25  
    26  	"github.com/dominant-strategies/go-quai/common"
    27  	"github.com/dominant-strategies/go-quai/common/hexutil"
    28  	"github.com/dominant-strategies/go-quai/core"
    29  	"github.com/dominant-strategies/go-quai/core/types"
    30  	"github.com/dominant-strategies/go-quai/crypto"
    31  	"github.com/dominant-strategies/go-quai/log"
    32  	"github.com/dominant-strategies/go-quai/rpc"
    33  	"github.com/dominant-strategies/go-quai/trie"
    34  )
    35  
    36  // PublicQuaiAPI provides an API to access Quai related information.
    37  // It offers only methods that operate on public data that is freely available to anyone.
    38  type PublicQuaiAPI struct {
    39  	b Backend
    40  }
    41  
    42  // NewPublicQuaiAPI creates a new Quai protocol API.
    43  func NewPublicQuaiAPI(b Backend) *PublicQuaiAPI {
    44  	return &PublicQuaiAPI{b}
    45  }
    46  
    47  // GasPrice returns a suggestion for a gas price for legacy transactions.
    48  func (s *PublicQuaiAPI) GasPrice(ctx context.Context) (*hexutil.Big, error) {
    49  	tipcap, err := s.b.SuggestGasTipCap(ctx)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  	if head := s.b.CurrentHeader(); head.BaseFee() != nil {
    54  		tipcap.Add(tipcap, head.BaseFee())
    55  	}
    56  	return (*hexutil.Big)(tipcap), err
    57  }
    58  
    59  // MaxPriorityFeePerGas returns a suggestion for a gas tip cap for dynamic fee transactions.
    60  func (s *PublicQuaiAPI) MaxPriorityFeePerGas(ctx context.Context) (*hexutil.Big, error) {
    61  	tipcap, err := s.b.SuggestGasTipCap(ctx)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  	return (*hexutil.Big)(tipcap), err
    66  }
    67  
    68  func (s *PublicQuaiAPI) FeeHistory(ctx context.Context, blockCount rpc.DecimalOrHex, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*feeHistoryResult, error) {
    69  	oldest, reward, baseFee, gasUsed, err := s.b.FeeHistory(ctx, int(blockCount), lastBlock, rewardPercentiles)
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  	results := &feeHistoryResult{
    74  		OldestBlock:  (*hexutil.Big)(oldest),
    75  		GasUsedRatio: gasUsed,
    76  	}
    77  	if reward != nil {
    78  		results.Reward = make([][]*hexutil.Big, len(reward))
    79  		for i, w := range reward {
    80  			results.Reward[i] = make([]*hexutil.Big, len(w))
    81  			for j, v := range w {
    82  				results.Reward[i][j] = (*hexutil.Big)(v)
    83  			}
    84  		}
    85  	}
    86  	if baseFee != nil {
    87  		results.BaseFee = make([]*hexutil.Big, len(baseFee))
    88  		for i, v := range baseFee {
    89  			results.BaseFee[i] = (*hexutil.Big)(v)
    90  		}
    91  	}
    92  	return results, nil
    93  }
    94  
    95  // Syncing returns false in case the node is currently not syncing with the network. It can be up to date or has not
    96  // yet received the latest block headers from its pears. In case it is synchronizing:
    97  // - startingBlock: block number this node started to synchronise from
    98  // - currentBlock:  block number this node is currently importing
    99  // - highestBlock:  block number of the highest block header this node has received from peers
   100  // - pulledStates:  number of state entries processed until now
   101  // - knownStates:   number of known state entries that still need to be pulled
   102  func (s *PublicQuaiAPI) Syncing() (interface{}, error) {
   103  	progress := s.b.SyncProgress()
   104  
   105  	// Return not syncing if the synchronisation already completed
   106  	if progress.CurrentBlock >= progress.HighestBlock {
   107  		return false, nil
   108  	}
   109  	// Otherwise gather the block sync stats
   110  	return map[string]interface{}{
   111  		"startingBlock": hexutil.Uint64(progress.StartingBlock),
   112  		"currentBlock":  hexutil.Uint64(progress.CurrentBlock),
   113  		"highestBlock":  hexutil.Uint64(progress.HighestBlock),
   114  		"pulledStates":  hexutil.Uint64(progress.PulledStates),
   115  		"knownStates":   hexutil.Uint64(progress.KnownStates),
   116  	}, nil
   117  }
   118  
   119  // PublicBlockChainQuaiAPI provides an API to access the Quai blockchain.
   120  // It offers only methods that operate on public data that is freely available to anyone.
   121  type PublicBlockChainQuaiAPI struct {
   122  	b Backend
   123  }
   124  
   125  // NewPublicBlockChainQuaiAPI creates a new Quai blockchain API.
   126  func NewPublicBlockChainQuaiAPI(b Backend) *PublicBlockChainQuaiAPI {
   127  	return &PublicBlockChainQuaiAPI{b}
   128  }
   129  
   130  // ChainId is the replay-protection chain id for the current Quai chain config.
   131  func (api *PublicBlockChainQuaiAPI) ChainId() (*hexutil.Big, error) {
   132  	return (*hexutil.Big)(api.b.ChainConfig().ChainID), nil
   133  }
   134  
   135  // NodeLocation is the access call to the location of the node.
   136  func (api *PublicBlockChainQuaiAPI) NodeLocation() []hexutil.Uint64 {
   137  	return common.NodeLocation.RPCMarshal()
   138  }
   139  
   140  // BlockNumber returns the block number of the chain head.
   141  func (s *PublicBlockChainQuaiAPI) BlockNumber() hexutil.Uint64 {
   142  	header, _ := s.b.HeaderByNumber(context.Background(), rpc.LatestBlockNumber) // latest header should always be available
   143  	return hexutil.Uint64(header.NumberU64())
   144  
   145  }
   146  
   147  // GetBalance returns the amount of wei for the given address in the state of the
   148  // given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
   149  // block numbers are also allowed.
   150  func (s *PublicBlockChainQuaiAPI) GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Big, error) {
   151  	nodeCtx := common.NodeLocation.Context()
   152  	if nodeCtx != common.ZONE_CTX {
   153  		return nil, errors.New("getBalance call can only be made in zone chain")
   154  	}
   155  	if !s.b.ProcessingState() {
   156  		return nil, errors.New("getBalance call can only be made on chain processing the state")
   157  	}
   158  	state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
   159  	if state == nil || err != nil {
   160  		return nil, err
   161  	}
   162  	internal, err := address.InternalAddress()
   163  	if err != nil {
   164  		return nil, err
   165  	}
   166  	return (*hexutil.Big)(state.GetBalance(internal)), state.Error()
   167  }
   168  
   169  // GetProof returns the Merkle-proof for a given account and optionally some storage keys.
   170  func (s *PublicBlockChainQuaiAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) {
   171  	nodeCtx := common.NodeLocation.Context()
   172  	if nodeCtx != common.ZONE_CTX {
   173  		return nil, errors.New("getProof call can only be made in zone chain")
   174  	}
   175  	if !s.b.ProcessingState() {
   176  		return nil, errors.New("getProof call can only be made on chain processing the state")
   177  	}
   178  	state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
   179  	if state == nil || err != nil {
   180  		return nil, err
   181  	}
   182  	internal, err := address.InternalAddress()
   183  	if err != nil {
   184  		return nil, err
   185  	}
   186  
   187  	storageTrie := state.StorageTrie(internal)
   188  	storageHash := types.EmptyRootHash
   189  	codeHash := state.GetCodeHash(internal)
   190  	storageProof := make([]StorageResult, len(storageKeys))
   191  
   192  	// if we have a storageTrie, (which means the account exists), we can update the storagehash
   193  	if storageTrie != nil {
   194  		storageHash = storageTrie.Hash()
   195  	} else {
   196  		// no storageTrie means the account does not exist, so the codeHash is the hash of an empty bytearray.
   197  		codeHash = crypto.Keccak256Hash(nil)
   198  	}
   199  
   200  	// create the proof for the storageKeys
   201  	for i, key := range storageKeys {
   202  		if storageTrie != nil {
   203  			proof, storageError := state.GetStorageProof(internal, common.HexToHash(key))
   204  			if storageError != nil {
   205  				return nil, storageError
   206  			}
   207  			storageProof[i] = StorageResult{key, (*hexutil.Big)(state.GetState(internal, common.HexToHash(key)).Big()), toHexSlice(proof)}
   208  		} else {
   209  			storageProof[i] = StorageResult{key, &hexutil.Big{}, []string{}}
   210  		}
   211  	}
   212  
   213  	// create the accountProof
   214  	accountProof, proofErr := state.GetProof(internal)
   215  	if proofErr != nil {
   216  		return nil, proofErr
   217  	}
   218  
   219  	return &AccountResult{
   220  		Address:      address,
   221  		AccountProof: toHexSlice(accountProof),
   222  		Balance:      (*hexutil.Big)(state.GetBalance(internal)),
   223  		CodeHash:     codeHash,
   224  		Nonce:        hexutil.Uint64(state.GetNonce(internal)),
   225  		StorageHash:  storageHash,
   226  		StorageProof: storageProof,
   227  	}, state.Error()
   228  }
   229  
   230  // GetHeaderByNumber returns the requested canonical block header.
   231  // * When blockNr is -1 the chain head is returned.
   232  // * When blockNr is -2 the pending chain head is returned.
   233  func (s *PublicBlockChainQuaiAPI) GetHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (map[string]interface{}, error) {
   234  	header, err := s.b.HeaderByNumber(ctx, number)
   235  	if header != nil && err == nil {
   236  		response := header.RPCMarshalHeader()
   237  		if number == rpc.PendingBlockNumber {
   238  			// Pending header need to nil out a few fields
   239  			for _, field := range []string{"hash", "nonce", "miner"} {
   240  				response[field] = nil
   241  			}
   242  		}
   243  		return response, err
   244  	}
   245  	return nil, err
   246  }
   247  
   248  // GetHeaderByHash returns the requested header by hash.
   249  func (s *PublicBlockChainQuaiAPI) GetHeaderHashByNumber(ctx context.Context, number rpc.BlockNumber) common.Hash {
   250  	header, err := s.b.HeaderByNumber(ctx, number)
   251  	if err != nil {
   252  		return common.Hash{}
   253  	}
   254  	return header.Hash()
   255  }
   256  
   257  // GetHeaderByHash returns the requested header by hash.
   258  func (s *PublicBlockChainQuaiAPI) GetHeaderByHash(ctx context.Context, hash common.Hash) map[string]interface{} {
   259  	header, _ := s.b.HeaderByHash(ctx, hash)
   260  	if header != nil {
   261  		return header.RPCMarshalHeader()
   262  	}
   263  	return nil
   264  }
   265  
   266  // GetBlockByNumber returns the requested canonical block.
   267  //   - When blockNr is -1 the chain head is returned.
   268  //   - When blockNr is -2 the pending chain head is returned.
   269  //   - When fullTx is true all transactions in the block are returned, otherwise
   270  //     only the transaction hash is returned.
   271  func (s *PublicBlockChainQuaiAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
   272  	block, err := s.b.BlockByNumber(ctx, number)
   273  	if block != nil && err == nil {
   274  		response, err := s.rpcMarshalBlock(ctx, block, true, fullTx)
   275  		if err == nil && number == rpc.PendingBlockNumber {
   276  			// Pending blocks need to nil out a few fields
   277  			for _, field := range []string{"hash", "nonce", "miner"} {
   278  				response[field] = nil
   279  			}
   280  		}
   281  		return response, err
   282  	}
   283  	return nil, err
   284  }
   285  
   286  // GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full
   287  // detail, otherwise only the transaction hash is returned.
   288  func (s *PublicBlockChainQuaiAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) {
   289  	block, err := s.b.BlockByHash(ctx, hash)
   290  	if block != nil {
   291  		return s.rpcMarshalBlock(ctx, block, true, fullTx)
   292  	}
   293  	return nil, err
   294  }
   295  
   296  // GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index. When fullTx is true
   297  // all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
   298  func (s *PublicBlockChainQuaiAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) {
   299  	block, err := s.b.BlockByNumber(ctx, blockNr)
   300  	if block != nil {
   301  		uncles := block.Uncles()
   302  		if index >= hexutil.Uint(len(uncles)) {
   303  			log.Debug("Requested uncle not found", "number", blockNr, "hash", block.Hash(), "index", index)
   304  			return nil, nil
   305  		}
   306  		block = types.NewBlockWithHeader(uncles[index])
   307  		return s.rpcMarshalBlock(ctx, block, false, false)
   308  	}
   309  	return nil, err
   310  }
   311  
   312  // GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index. When fullTx is true
   313  // all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
   314  func (s *PublicBlockChainQuaiAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (map[string]interface{}, error) {
   315  	block, err := s.b.BlockByHash(ctx, blockHash)
   316  	if block != nil {
   317  		uncles := block.Uncles()
   318  		if index >= hexutil.Uint(len(uncles)) {
   319  			log.Debug("Requested uncle not found", "number", block.Number(), "hash", blockHash, "index", index)
   320  			return nil, nil
   321  		}
   322  		block = types.NewBlockWithHeader(uncles[index])
   323  		return s.rpcMarshalBlock(ctx, block, false, false)
   324  	}
   325  	pendBlock, _ := s.b.PendingBlockAndReceipts()
   326  	if pendBlock != nil && pendBlock.Hash() == blockHash {
   327  		uncles := pendBlock.Uncles()
   328  		if index >= hexutil.Uint(len(uncles)) {
   329  			log.Debug("Requested uncle not found in pending block", "number", block.Number(), "hash", blockHash, "index", index)
   330  			return nil, nil
   331  		}
   332  		block = types.NewBlockWithHeader(uncles[index])
   333  		return s.rpcMarshalBlock(ctx, block, false, false)
   334  	}
   335  	return nil, err
   336  }
   337  
   338  // GetUncleCountByBlockNumber returns number of uncles in the block for the given block number
   339  func (s *PublicBlockChainQuaiAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint {
   340  	if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
   341  		n := hexutil.Uint(len(block.Uncles()))
   342  		return &n
   343  	}
   344  	return nil
   345  }
   346  
   347  // GetUncleCountByBlockHash returns number of uncles in the block for the given block hash
   348  func (s *PublicBlockChainQuaiAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint {
   349  	if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
   350  		n := hexutil.Uint(len(block.Uncles()))
   351  		return &n
   352  	}
   353  	return nil
   354  }
   355  
   356  // GetCode returns the code stored at the given address in the state for the given block number.
   357  func (s *PublicBlockChainQuaiAPI) GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
   358  	nodeCtx := common.NodeLocation.Context()
   359  	if nodeCtx != common.ZONE_CTX {
   360  		return nil, errors.New("getCode can only called in a zone chain")
   361  	}
   362  	if !s.b.ProcessingState() {
   363  		return nil, errors.New("getCode call can only be made on chain processing the state")
   364  	}
   365  	state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
   366  	if state == nil || err != nil {
   367  		return nil, err
   368  	}
   369  	internal, err := address.InternalAddress()
   370  	if err != nil {
   371  		return nil, err
   372  	}
   373  	code := state.GetCode(internal)
   374  	return code, state.Error()
   375  }
   376  
   377  // GetStorageAt returns the storage from the state at the given address, key and
   378  // block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
   379  // numbers are also allowed.
   380  func (s *PublicBlockChainQuaiAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
   381  	nodeCtx := common.NodeLocation.Context()
   382  	if nodeCtx != common.ZONE_CTX {
   383  		return nil, errors.New("getStorageAt can only called in a zone chain")
   384  	}
   385  	if !s.b.ProcessingState() {
   386  		return nil, errors.New("getStorageAt call can only be made on chain processing the state")
   387  	}
   388  	state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
   389  	if state == nil || err != nil {
   390  		return nil, err
   391  	}
   392  	internal, err := address.InternalAddress()
   393  	if err != nil {
   394  		return nil, err
   395  	}
   396  	res := state.GetState(internal, common.HexToHash(key))
   397  	return res[:], state.Error()
   398  }
   399  
   400  // Call executes the given transaction on the state for the given block number.
   401  //
   402  // Additionally, the caller can specify a batch of contract for fields overriding.
   403  //
   404  // Note, this function doesn't make and changes in the state/blockchain and is
   405  // useful to execute and retrieve values.
   406  func (s *PublicBlockChainQuaiAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Bytes, error) {
   407  	result, err := DoCall(ctx, s.b, args, blockNrOrHash, overrides, 5*time.Second, s.b.RPCGasCap())
   408  	if err != nil {
   409  		return nil, err
   410  	}
   411  	// If the result contains a revert reason, try to unpack and return it.
   412  	if len(result.Revert()) > 0 {
   413  		return nil, newRevertError(result)
   414  	}
   415  	return result.Return(), result.Err
   416  }
   417  
   418  // EstimateGas returns an estimate of the amount of gas needed to execute the
   419  // given transaction against the current pending block.
   420  func (s *PublicBlockChainQuaiAPI) EstimateGas(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (hexutil.Uint64, error) {
   421  	nodeCtx := common.NodeLocation.Context()
   422  	if nodeCtx != common.ZONE_CTX {
   423  		return 0, errors.New("estimateGas can only called in a zone chain")
   424  	}
   425  	if !s.b.ProcessingState() {
   426  		return 0, errors.New("estimateGas call can only be made on chain processing the state")
   427  	}
   428  	bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
   429  	if blockNrOrHash != nil {
   430  		bNrOrHash = *blockNrOrHash
   431  	}
   432  	return DoEstimateGas(ctx, s.b, args, bNrOrHash, s.b.RPCGasCap())
   433  }
   434  
   435  // RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
   436  // returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
   437  // transaction hashes.
   438  func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
   439  	fields := block.Header().RPCMarshalHeader()
   440  	fields["size"] = hexutil.Uint64(block.Size())
   441  
   442  	if inclTx {
   443  		formatTx := func(tx *types.Transaction) (interface{}, error) {
   444  			return tx.Hash(), nil
   445  		}
   446  		formatEtx := formatTx
   447  		if fullTx {
   448  			formatTx = func(tx *types.Transaction) (interface{}, error) {
   449  				return newRPCTransactionFromBlockHash(block, tx.Hash(), false), nil
   450  			}
   451  			formatEtx = func(tx *types.Transaction) (interface{}, error) {
   452  				return newRPCTransactionFromBlockHash(block, tx.Hash(), true), nil
   453  			}
   454  		}
   455  		txs := block.Transactions()
   456  		transactions := make([]interface{}, len(txs))
   457  		var err error
   458  		for i, tx := range txs {
   459  			if transactions[i], err = formatTx(tx); err != nil {
   460  				return nil, err
   461  			}
   462  		}
   463  		fields["transactions"] = transactions
   464  		etxs := block.ExtTransactions()
   465  		extTransactions := make([]interface{}, len(etxs))
   466  		for i, etx := range etxs {
   467  			if extTransactions[i], err = formatEtx(etx); err != nil {
   468  				return nil, err
   469  			}
   470  		}
   471  		fields["extTransactions"] = extTransactions
   472  	}
   473  
   474  	fields["uncles"] = block.Uncles()
   475  	fields["subManifest"] = block.SubManifest()
   476  
   477  	return fields, nil
   478  }
   479  
   480  // rpcMarshalReOrgData converts the reOrgData obtained to the right header format
   481  func RPCMarshalReOrgData(header *types.Header, newHeaders []*types.Header, oldHeaders []*types.Header) (map[string]interface{}, error) {
   482  	fields := map[string]interface{}{"header": header.RPCMarshalHeader()}
   483  
   484  	fieldNewHeaders := make([]interface{}, len(newHeaders))
   485  	for i, newHeader := range newHeaders {
   486  		fieldNewHeaders[i] = newHeader.RPCMarshalHeader()
   487  	}
   488  
   489  	fieldOldHeaders := make([]interface{}, len(oldHeaders))
   490  	for i, oldHeader := range oldHeaders {
   491  		fieldOldHeaders[i] = oldHeader.RPCMarshalHeader()
   492  	}
   493  
   494  	fields["newHeaders"] = fieldNewHeaders
   495  	fields["oldHeaders"] = fieldOldHeaders
   496  	return fields, nil
   497  }
   498  
   499  // RPCMarshalHash convert the hash into a the correct interface.
   500  func RPCMarshalHash(hash common.Hash) (map[string]interface{}, error) {
   501  	fields := map[string]interface{}{"Hash": hash}
   502  	return fields, nil
   503  }
   504  
   505  // rpcMarshalHeader uses the generalized output filler, then adds the total difficulty field, which requires
   506  // a `PublicBlockchainQuaiAPI`.
   507  func (s *PublicBlockChainQuaiAPI) rpcMarshalHeader(ctx context.Context, header *types.Header) map[string]interface{} {
   508  	fields := header.RPCMarshalHeader()
   509  	fields["totalEntropy"] = (*hexutil.Big)(s.b.TotalLogS(header))
   510  	return fields
   511  }
   512  
   513  // rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field, which requires
   514  // a `PublicBlockchainAPI`.
   515  func (s *PublicBlockChainQuaiAPI) rpcMarshalBlock(ctx context.Context, b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
   516  	fields, err := RPCMarshalBlock(b, inclTx, fullTx)
   517  	if err != nil {
   518  		return nil, err
   519  	}
   520  	_, order, err := s.b.CalcOrder(b.Header())
   521  	if err != nil {
   522  		return nil, err
   523  	}
   524  	fields["order"] = order
   525  	fields["totalEntropy"] = (*hexutil.Big)(s.b.TotalLogS(b.Header()))
   526  	return fields, err
   527  }
   528  
   529  // CreateAccessList creates an AccessList for the given transaction.
   530  // Reexec and BlockNrOrHash can be specified to create the accessList on top of a certain state.
   531  func (s *PublicBlockChainQuaiAPI) CreateAccessList(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (*accessListResult, error) {
   532  	nodeCtx := common.NodeLocation.Context()
   533  	if nodeCtx != common.ZONE_CTX {
   534  		return nil, errors.New("createAccessList can only be called in zone chain")
   535  	}
   536  	if !s.b.ProcessingState() {
   537  		return nil, errors.New("createAccessList call can only be made on chain processing the state")
   538  	}
   539  	bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
   540  	if blockNrOrHash != nil {
   541  		bNrOrHash = *blockNrOrHash
   542  	}
   543  	acl, gasUsed, vmerr, err := AccessList(ctx, s.b, bNrOrHash, args)
   544  	if err != nil {
   545  		return nil, err
   546  	}
   547  	result := &accessListResult{Accesslist: &acl, GasUsed: hexutil.Uint64(gasUsed)}
   548  	if vmerr != nil {
   549  		result.Error = vmerr.Error()
   550  	}
   551  	return result, nil
   552  }
   553  
   554  func (s *PublicBlockChainQuaiAPI) fillSubordinateManifest(b *types.Block) (*types.Block, error) {
   555  	nodeCtx := common.NodeLocation.Context()
   556  	if b.ManifestHash(nodeCtx+1) == types.EmptyRootHash {
   557  		return nil, errors.New("cannot fill empty subordinate manifest")
   558  	} else if subManifestHash := types.DeriveSha(b.SubManifest(), trie.NewStackTrie(nil)); subManifestHash == b.ManifestHash(nodeCtx+1) {
   559  		// If the manifest hashes match, nothing to do
   560  		return b, nil
   561  	} else {
   562  		subParentHash := b.ParentHash(nodeCtx + 1)
   563  		var subManifest types.BlockManifest
   564  		if subParent, err := s.b.BlockByHash(context.Background(), subParentHash); err == nil && subParent != nil {
   565  			// If we have the the subordinate parent in our chain, that means that block
   566  			// was also coincident. In this case, the subordinate manifest resets, and
   567  			// only consists of the subordinate parent hash.
   568  			subManifest = types.BlockManifest{subParentHash}
   569  		} else {
   570  			// Otherwise we need to reconstruct the sub manifest, by getting the
   571  			// parent's sub manifest and appending the parent hash.
   572  			subManifest, err = s.b.GetSubManifest(b.Location(), subParentHash)
   573  			if err != nil {
   574  				return nil, err
   575  			}
   576  		}
   577  		if len(subManifest) == 0 {
   578  			return nil, errors.New("reconstructed sub manifest is empty")
   579  		}
   580  		if subManifest == nil || b.ManifestHash(nodeCtx+1) != types.DeriveSha(subManifest, trie.NewStackTrie(nil)) {
   581  			return nil, errors.New("reconstructed sub manifest does not match manifest hash")
   582  		}
   583  		return types.NewBlockWithHeader(b.Header()).WithBody(b.Transactions(), b.Uncles(), b.ExtTransactions(), subManifest), nil
   584  	}
   585  }
   586  
   587  // ReceiveMinedHeader will run checks on the block and add to canonical chain if valid.
   588  func (s *PublicBlockChainQuaiAPI) ReceiveMinedHeader(ctx context.Context, raw json.RawMessage) error {
   589  	nodeCtx := common.NodeLocation.Context()
   590  	// Decode header and transactions.
   591  	var header *types.Header
   592  	if err := json.Unmarshal(raw, &header); err != nil {
   593  		return err
   594  	}
   595  	block, err := s.b.ConstructLocalMinedBlock(header)
   596  	if err != nil && err.Error() == core.ErrBadSubManifest.Error() && nodeCtx < common.ZONE_CTX {
   597  		log.Info("filling sub manifest")
   598  		// If we just mined this block, and we have a subordinate chain, its possible
   599  		// the subordinate manifest in our block body is incorrect. If so, ask our sub
   600  		// for the correct manifest and reconstruct the block.
   601  		var err error
   602  		block, err = s.fillSubordinateManifest(block)
   603  		if err != nil {
   604  			return err
   605  		}
   606  	} else if err != nil {
   607  		return err
   608  	}
   609  	s.b.WriteBlock(block)
   610  	// Broadcast the block and announce chain insertion event
   611  	if block.Header() != nil {
   612  		s.b.EventMux().Post(core.NewMinedBlockEvent{Block: block})
   613  	}
   614  	log.Info("Retrieved mined block", "number", header.Number(), "location", header.Location())
   615  
   616  	return nil
   617  }
   618  
   619  type tdBlock struct {
   620  	Header           *types.Header       `json:"header"`
   621  	Manifest         types.BlockManifest `json:"manifest"`
   622  	DomPendingHeader *types.Header       `json:"domPendingHeader"`
   623  	DomTerminus      common.Hash         `json:"domTerminus"`
   624  	DomOrigin        bool                `json:"domOrigin"`
   625  	NewInboundEtxs   types.Transactions  `json:"newInboundEtxs"`
   626  }
   627  
   628  func (s *PublicBlockChainQuaiAPI) Append(ctx context.Context, raw json.RawMessage) (map[string]interface{}, error) {
   629  	// Decode header and transactions.
   630  	var body tdBlock
   631  
   632  	if err := json.Unmarshal(raw, &body); err != nil {
   633  		return nil, err
   634  	}
   635  
   636  	pendingEtxs, subReorg, setHead, err := s.b.Append(body.Header, body.Manifest, body.DomPendingHeader, body.DomTerminus, body.DomOrigin, body.NewInboundEtxs)
   637  	if err != nil {
   638  		return nil, err
   639  	}
   640  	// Marshal the output for decoding
   641  	fields := map[string]interface{}{
   642  		"pendingEtxs": pendingEtxs,
   643  		"subReorg":    subReorg,
   644  		"setHead":     setHead,
   645  	}
   646  
   647  	return fields, nil
   648  
   649  }
   650  
   651  type DownloadBlocksInManifestArgs struct {
   652  	Hash     common.Hash         `json:"hash"`
   653  	Manifest types.BlockManifest `json:"manifest"`
   654  	Entropy  *big.Int            `json:"entropy"`
   655  }
   656  
   657  func (s *PublicBlockChainQuaiAPI) DownloadBlocksInManifest(ctx context.Context, raw json.RawMessage) {
   658  	var manifest DownloadBlocksInManifestArgs
   659  	if err := json.Unmarshal(raw, &manifest); err != nil {
   660  		return
   661  	}
   662  	s.b.DownloadBlocksInManifest(manifest.Hash, manifest.Manifest, manifest.Entropy)
   663  }
   664  
   665  type SubRelay struct {
   666  	Header     *types.Header `json:"header"`
   667  	Termini    types.Termini `json:"termini"`
   668  	NewEntropy *big.Int
   669  	Location   common.Location
   670  	SubReorg   bool
   671  	Order      int
   672  }
   673  
   674  func (s *PublicBlockChainQuaiAPI) SubRelayPendingHeader(ctx context.Context, raw json.RawMessage) {
   675  	var subRelay SubRelay
   676  	if err := json.Unmarshal(raw, &subRelay); err != nil {
   677  		return
   678  	}
   679  	pendingHeader := types.NewPendingHeader(subRelay.Header, subRelay.Termini)
   680  	s.b.SubRelayPendingHeader(pendingHeader, subRelay.NewEntropy, subRelay.Location, subRelay.SubReorg, subRelay.Order)
   681  }
   682  
   683  type DomUpdate struct {
   684  	OldTerminus common.Hash
   685  	Header      *types.Header `json:"header"`
   686  	Termini     types.Termini `json:"termini"`
   687  	Location    common.Location
   688  }
   689  
   690  func (s *PublicBlockChainQuaiAPI) UpdateDom(ctx context.Context, raw json.RawMessage) {
   691  	var domUpdate DomUpdate
   692  	if err := json.Unmarshal(raw, &domUpdate); err != nil {
   693  		log.Error("Error unmarshaling domUpdate in api", "err", err)
   694  		return
   695  	}
   696  
   697  	pendingHeader := types.NewPendingHeader(domUpdate.Header, domUpdate.Termini)
   698  	s.b.UpdateDom(domUpdate.OldTerminus, pendingHeader, domUpdate.Location)
   699  }
   700  
   701  type RequestDomToAppendOrFetchArgs struct {
   702  	Hash    common.Hash
   703  	Entropy *big.Int
   704  	Order   int
   705  }
   706  
   707  func (s *PublicBlockChainQuaiAPI) RequestDomToAppendOrFetch(ctx context.Context, raw json.RawMessage) {
   708  	var requestDom RequestDomToAppendOrFetchArgs
   709  	if err := json.Unmarshal(raw, &requestDom); err != nil {
   710  		return
   711  	}
   712  	s.b.RequestDomToAppendOrFetch(requestDom.Hash, requestDom.Entropy, requestDom.Order)
   713  }
   714  func (s *PublicBlockChainQuaiAPI) NewGenesisPendingHeader(ctx context.Context, raw json.RawMessage) {
   715  	var pendingHeader *types.Header
   716  	if err := json.Unmarshal(raw, &pendingHeader); err != nil {
   717  		return
   718  	}
   719  	s.b.NewGenesisPendingHeader(pendingHeader)
   720  }
   721  
   722  func (s *PublicBlockChainQuaiAPI) GetPendingHeader(ctx context.Context) (map[string]interface{}, error) {
   723  	nodeCtx := common.NodeLocation.Context()
   724  	if nodeCtx != common.ZONE_CTX {
   725  		return nil, errors.New("getPendingHeader can only be called in zone chain")
   726  	}
   727  	if !s.b.ProcessingState() {
   728  		return nil, errors.New("getPendingHeader call can only be made on chain processing the state")
   729  	}
   730  	pendingHeader, err := s.b.GetPendingHeader()
   731  	if err != nil {
   732  		return nil, err
   733  	} else if pendingHeader == nil {
   734  		return nil, errors.New("no pending header found")
   735  	}
   736  	// Marshal the response.
   737  	marshaledPh := pendingHeader.RPCMarshalHeader()
   738  	return marshaledPh, nil
   739  }
   740  
   741  func (s *PublicBlockChainQuaiAPI) GetManifest(ctx context.Context, raw json.RawMessage) (types.BlockManifest, error) {
   742  	var blockHash common.Hash
   743  	if err := json.Unmarshal(raw, &blockHash); err != nil {
   744  		return nil, err
   745  	}
   746  	manifest, err := s.b.GetManifest(blockHash)
   747  	if err != nil {
   748  		return nil, err
   749  	}
   750  	return manifest, nil
   751  }
   752  
   753  type SendPendingEtxsToDomArgs struct {
   754  	Header         types.Header         `json:"header"`
   755  	NewPendingEtxs []types.Transactions `json:"newPendingEtxs"`
   756  }
   757  
   758  func (s *PublicBlockChainQuaiAPI) SendPendingEtxsToDom(ctx context.Context, raw json.RawMessage) error {
   759  	var pEtxs types.PendingEtxs
   760  	if err := json.Unmarshal(raw, &pEtxs); err != nil {
   761  		return err
   762  	}
   763  	return s.b.AddPendingEtxs(pEtxs)
   764  }
   765  
   766  type SendPendingEtxsRollupToDomArgs struct {
   767  	Header   *types.Header       `json:"header"`
   768  	Manifest types.BlockManifest `json:"manifest"`
   769  }
   770  
   771  func (s *PublicBlockChainQuaiAPI) SendPendingEtxsRollupToDom(ctx context.Context, raw json.RawMessage) error {
   772  	var pEtxsRollup SendPendingEtxsRollupToDomArgs
   773  	if err := json.Unmarshal(raw, &pEtxsRollup); err != nil {
   774  		return err
   775  	}
   776  	return s.b.AddPendingEtxsRollup(types.PendingEtxsRollup{Header: pEtxsRollup.Header, Manifest: pEtxsRollup.Manifest})
   777  }
   778  
   779  type GenerateRecoveryPendingHeaderArgs struct {
   780  	PendingHeader    *types.Header `json:"pendingHeader"`
   781  	CheckpointHashes types.Termini `json:"checkpointHashes"`
   782  }
   783  
   784  func (s *PublicBlockChainQuaiAPI) GenerateRecoveryPendingHeader(ctx context.Context, raw json.RawMessage) error {
   785  	var pHandcheckPointHashes GenerateRecoveryPendingHeaderArgs
   786  	if err := json.Unmarshal(raw, &pHandcheckPointHashes); err != nil {
   787  		return err
   788  	}
   789  	return s.b.GenerateRecoveryPendingHeader(pHandcheckPointHashes.PendingHeader, pHandcheckPointHashes.CheckpointHashes)
   790  }
   791  
   792  type GetPendingEtxsRollupFuncArgs struct {
   793  	Hash     common.Hash
   794  	Location common.Location
   795  }
   796  
   797  func (s *PublicBlockChainQuaiAPI) GetPendingEtxsRollupFromSub(ctx context.Context, raw json.RawMessage) (map[string]interface{}, error) {
   798  	var getPEtxsRollup GetPendingEtxsFuncArgs
   799  	if err := json.Unmarshal(raw, &getPEtxsRollup); err != nil {
   800  		return nil, err
   801  	}
   802  	pEtxsRollup, err := s.b.GetPendingEtxsRollupFromSub(getPEtxsRollup.Hash, getPEtxsRollup.Location)
   803  	if err != nil {
   804  		return nil, err
   805  	}
   806  	fields := make(map[string]interface{})
   807  	fields["header"] = pEtxsRollup.Header.RPCMarshalHeader()
   808  	fields["manifest"] = pEtxsRollup.Manifest
   809  
   810  	return fields, nil
   811  }
   812  
   813  type GetPendingEtxsFuncArgs struct {
   814  	Hash     common.Hash
   815  	Location common.Location
   816  }
   817  
   818  func (s *PublicBlockChainQuaiAPI) GetPendingEtxsFromSub(ctx context.Context, raw json.RawMessage) (map[string]interface{}, error) {
   819  	var getPEtxs GetPendingEtxsFuncArgs
   820  	if err := json.Unmarshal(raw, &getPEtxs); err != nil {
   821  		return nil, err
   822  	}
   823  	pEtxs, err := s.b.GetPendingEtxsFromSub(getPEtxs.Hash, getPEtxs.Location)
   824  	if err != nil {
   825  		return nil, err
   826  	}
   827  	fields := make(map[string]interface{})
   828  	fields["header"] = pEtxs.Header.RPCMarshalHeader()
   829  	fields["etxs"] = pEtxs.Etxs
   830  
   831  	return fields, nil
   832  }
   833  
   834  func (s *PublicBlockChainQuaiAPI) SetSyncTarget(ctx context.Context, raw json.RawMessage) error {
   835  	var header *types.Header
   836  	if err := json.Unmarshal(raw, &header); err != nil {
   837  		return err
   838  	}
   839  	s.b.SetSyncTarget(header)
   840  	return nil
   841  }