github.com/ava-labs/subnet-evm@v0.6.4/internal/ethapi/api_extra.go (about)

     1  // (c) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package ethapi
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"math/big"
    10  
    11  	"github.com/ava-labs/subnet-evm/commontype"
    12  	"github.com/ava-labs/subnet-evm/core"
    13  	"github.com/ava-labs/subnet-evm/core/types"
    14  	"github.com/ava-labs/subnet-evm/params"
    15  	"github.com/ava-labs/subnet-evm/rpc"
    16  	"github.com/ethereum/go-ethereum/common"
    17  	"github.com/ethereum/go-ethereum/common/hexutil"
    18  	"github.com/ethereum/go-ethereum/rlp"
    19  )
    20  
    21  func (s *BlockChainAPI) GetChainConfig(ctx context.Context) *params.ChainConfigWithUpgradesJSON {
    22  	return s.b.ChainConfig().ToWithUpgradesJSON()
    23  }
    24  
    25  type DetailedExecutionResult struct {
    26  	UsedGas    uint64        `json:"gas"`        // Total used gas but include the refunded gas
    27  	ErrCode    int           `json:"errCode"`    // EVM error code
    28  	Err        string        `json:"err"`        // Any error encountered during the execution(listed in core/vm/errors.go)
    29  	ReturnData hexutil.Bytes `json:"returnData"` // Data from evm(function result or data supplied with revert opcode)
    30  }
    31  
    32  // CallDetailed performs the same call as Call, but returns the full context
    33  func (s *BlockChainAPI) CallDetailed(ctx context.Context, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride) (*DetailedExecutionResult, error) {
    34  	result, err := DoCall(ctx, s.b, args, blockNrOrHash, overrides, nil, s.b.RPCEVMTimeout(), s.b.RPCGasCap())
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  
    39  	reply := &DetailedExecutionResult{
    40  		UsedGas:    result.UsedGas,
    41  		ReturnData: result.ReturnData,
    42  	}
    43  	if result.Err != nil {
    44  		if err, ok := result.Err.(rpc.Error); ok {
    45  			reply.ErrCode = err.ErrorCode()
    46  		}
    47  		reply.Err = result.Err.Error()
    48  	}
    49  	// If the result contains a revert reason, try to unpack and return it.
    50  	if len(result.Revert()) > 0 {
    51  		err := newRevertError(result.Revert())
    52  		reply.ErrCode = err.ErrorCode()
    53  		reply.Err = err.Error()
    54  	}
    55  	return reply, nil
    56  }
    57  
    58  // Note: this API is moved directly from ./eth/api.go to ensure that it is available under an API that is enabled by
    59  // default without duplicating the code and serving the same API in the original location as well without creating a
    60  // cyclic import.
    61  //
    62  // BadBlockArgs represents the entries in the list returned when bad blocks are queried.
    63  type BadBlockArgs struct {
    64  	Hash   common.Hash            `json:"hash"`
    65  	Block  map[string]interface{} `json:"block"`
    66  	RLP    string                 `json:"rlp"`
    67  	Reason *core.BadBlockReason   `json:"reason"`
    68  }
    69  
    70  // GetBadBlocks returns a list of the last 'bad blocks' that the client has seen on the network
    71  // and returns them as a JSON list of block hashes.
    72  func (s *BlockChainAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs, error) {
    73  	var (
    74  		badBlocks, reasons = s.b.BadBlocks()
    75  		results            = make([]*BadBlockArgs, 0, len(badBlocks))
    76  	)
    77  	for i, block := range badBlocks {
    78  		var (
    79  			blockRlp  string
    80  			blockJSON map[string]interface{}
    81  		)
    82  		if rlpBytes, err := rlp.EncodeToBytes(block); err != nil {
    83  			blockRlp = err.Error() // Hacky, but hey, it works
    84  		} else {
    85  			blockRlp = fmt.Sprintf("%#x", rlpBytes)
    86  		}
    87  		blockJSON = RPCMarshalBlock(block, true, true, s.b.ChainConfig())
    88  		results = append(results, &BadBlockArgs{
    89  			Hash:   block.Hash(),
    90  			RLP:    blockRlp,
    91  			Block:  blockJSON,
    92  			Reason: reasons[i],
    93  		})
    94  	}
    95  	return results, nil
    96  }
    97  
    98  type FeeConfigResult struct {
    99  	FeeConfig     commontype.FeeConfig `json:"feeConfig"`
   100  	LastChangedAt *big.Int             `json:"lastChangedAt,omitempty"`
   101  }
   102  
   103  func (s *BlockChainAPI) FeeConfig(ctx context.Context, blockNrOrHash *rpc.BlockNumberOrHash) (*FeeConfigResult, error) {
   104  	var (
   105  		header *types.Header
   106  		err    error
   107  	)
   108  	if blockNrOrHash == nil {
   109  		header = s.b.CurrentHeader()
   110  	} else {
   111  		header, err = s.b.HeaderByNumberOrHash(ctx, *blockNrOrHash)
   112  		if err != nil {
   113  			return nil, err
   114  		}
   115  	}
   116  
   117  	feeConfig, lastChangedAt, err := s.b.GetFeeConfigAt(header)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  	return &FeeConfigResult{FeeConfig: feeConfig, LastChangedAt: lastChangedAt}, nil
   122  }
   123  
   124  // GetActivePrecompilesAt returns the active precompile configs at the given block timestamp.
   125  func (s *BlockChainAPI) GetActivePrecompilesAt(ctx context.Context, blockTimestamp *uint64) params.Precompiles {
   126  	var timestamp uint64
   127  	if blockTimestamp == nil {
   128  		timestamp = s.b.CurrentHeader().Time
   129  	} else {
   130  		timestamp = *blockTimestamp
   131  	}
   132  
   133  	return s.b.ChainConfig().EnabledStatefulPrecompiles(timestamp)
   134  }
   135  
   136  func (s *BlockChainAPI) GetActiveRulesAt(ctx context.Context, blockTimestamp *uint64) params.Rules {
   137  	var timestamp uint64
   138  	if blockTimestamp == nil {
   139  		timestamp = s.b.CurrentHeader().Time
   140  	} else {
   141  		timestamp = *blockTimestamp
   142  	}
   143  	return s.b.ChainConfig().Rules(common.Big0, timestamp)
   144  }