github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/jsonrpc/types/codec.go (about)

     1  package types
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"strings"
     8  
     9  	"github.com/0xPolygon/supernets2-node/encoding"
    10  	"github.com/0xPolygon/supernets2-node/hex"
    11  	"github.com/jackc/pgx/v4"
    12  )
    13  
    14  const (
    15  	// PendingBlockNumber represents the pending block number
    16  	PendingBlockNumber = BlockNumber(-3)
    17  	// LatestBlockNumber represents the latest block number
    18  	LatestBlockNumber = BlockNumber(-2)
    19  	// EarliestBlockNumber represents the earliest block number
    20  	EarliestBlockNumber = BlockNumber(-1)
    21  	// SafeBlockNumber represents the last virtualized block number
    22  	SafeBlockNumber = BlockNumber(-4)
    23  	// FinalizedBlockNumber represents the last verified block number
    24  	FinalizedBlockNumber = BlockNumber(-5)
    25  
    26  	// LatestBatchNumber represents the latest batch number
    27  	LatestBatchNumber = BatchNumber(-2)
    28  	// EarliestBatchNumber represents the earliest batch number
    29  	EarliestBatchNumber = BatchNumber(-1)
    30  
    31  	// Earliest contains the string to represent the earliest block known.
    32  	Earliest = "earliest"
    33  	// Latest contains the string to represent the latest block known.
    34  	Latest = "latest"
    35  	// Pending contains the string to represent the pending block known.
    36  	Pending = "pending"
    37  	// Safe contains the string to represent the last virtualized block known.
    38  	Safe = "safe"
    39  	// Finalized contains the string to represent the last verified block known.
    40  	Finalized = "finalized"
    41  
    42  	// EIP-1898: https://eips.ethereum.org/EIPS/eip-1898 //
    43  
    44  	// BlockNumberKey is the key for the block number for EIP-1898
    45  	BlockNumberKey = "blockNumber"
    46  	// BlockHashKey is the key for the block hash for EIP-1898
    47  	BlockHashKey = "blockHash"
    48  	// RequireCanonicalKey is the key for the require canonical for EIP-1898
    49  	RequireCanonicalKey = "requireCanonical"
    50  )
    51  
    52  // Request is a jsonrpc request
    53  type Request struct {
    54  	JSONRPC string          `json:"jsonrpc"`
    55  	ID      interface{}     `json:"id"`
    56  	Method  string          `json:"method"`
    57  	Params  json.RawMessage `json:"params,omitempty"`
    58  }
    59  
    60  // Response is a jsonrpc  success response
    61  type Response struct {
    62  	JSONRPC string
    63  	ID      interface{}
    64  	Result  json.RawMessage
    65  	Error   *ErrorObject
    66  }
    67  
    68  // ErrorObject is a jsonrpc error
    69  type ErrorObject struct {
    70  	Code    int       `json:"code"`
    71  	Message string    `json:"message"`
    72  	Data    *ArgBytes `json:"data,omitempty"`
    73  }
    74  
    75  // NewResponse returns Success/Error response object
    76  func NewResponse(req Request, reply []byte, err Error) Response {
    77  	var result json.RawMessage
    78  	if reply != nil {
    79  		result = reply
    80  	}
    81  
    82  	var errorObj *ErrorObject
    83  	if err != nil {
    84  		errorObj = &ErrorObject{
    85  			Code:    err.ErrorCode(),
    86  			Message: err.Error(),
    87  		}
    88  		if err.ErrorData() != nil {
    89  			errorObj.Data = ArgBytesPtr(*err.ErrorData())
    90  		}
    91  	}
    92  
    93  	return Response{
    94  		JSONRPC: req.JSONRPC,
    95  		ID:      req.ID,
    96  		Result:  result,
    97  		Error:   errorObj,
    98  	}
    99  }
   100  
   101  // MarshalJSON customizes the JSON representation of the response.
   102  func (r Response) MarshalJSON() ([]byte, error) {
   103  	if r.Error != nil {
   104  		return json.Marshal(struct {
   105  			JSONRPC string       `json:"jsonrpc"`
   106  			ID      interface{}  `json:"id"`
   107  			Error   *ErrorObject `json:"error"`
   108  		}{
   109  			JSONRPC: r.JSONRPC,
   110  			ID:      r.ID,
   111  			Error:   r.Error,
   112  		})
   113  	}
   114  
   115  	return json.Marshal(struct {
   116  		JSONRPC string          `json:"jsonrpc"`
   117  		ID      interface{}     `json:"id"`
   118  		Result  json.RawMessage `json:"result"`
   119  	}{
   120  		JSONRPC: r.JSONRPC,
   121  		ID:      r.ID,
   122  		Result:  r.Result,
   123  	})
   124  }
   125  
   126  // Bytes return the serialized response
   127  func (s Response) Bytes() ([]byte, error) {
   128  	return json.Marshal(s)
   129  }
   130  
   131  // SubscriptionResponse used to push response for filters
   132  // that have an active web socket connection
   133  type SubscriptionResponse struct {
   134  	JSONRPC string                     `json:"jsonrpc"`
   135  	Method  string                     `json:"method"`
   136  	Params  SubscriptionResponseParams `json:"params"`
   137  }
   138  
   139  // SubscriptionResponseParams parameters for subscription responses
   140  type SubscriptionResponseParams struct {
   141  	Subscription string          `json:"subscription"`
   142  	Result       json.RawMessage `json:"result"`
   143  }
   144  
   145  // Bytes return the serialized response
   146  func (s SubscriptionResponse) Bytes() ([]byte, error) {
   147  	return json.Marshal(s)
   148  }
   149  
   150  // BlockNumber is the number of a ethereum block
   151  type BlockNumber int64
   152  
   153  // UnmarshalJSON automatically decodes the user input for the block number, when a JSON RPC method is called
   154  func (b *BlockNumber) UnmarshalJSON(buffer []byte) error {
   155  	num, err := StringToBlockNumber(string(buffer))
   156  	if err != nil {
   157  		return err
   158  	}
   159  	*b = num
   160  	return nil
   161  }
   162  
   163  // GetNumericBlockNumber returns a numeric block number based on the BlockNumber instance
   164  func (b *BlockNumber) GetNumericBlockNumber(ctx context.Context, s StateInterface, dbTx pgx.Tx) (uint64, Error) {
   165  	bValue := LatestBlockNumber
   166  	if b != nil {
   167  		bValue = *b
   168  	}
   169  
   170  	switch bValue {
   171  	case LatestBlockNumber, PendingBlockNumber:
   172  		lastBlockNumber, err := s.GetLastL2BlockNumber(ctx, dbTx)
   173  		if err != nil {
   174  			return 0, NewRPCError(DefaultErrorCode, "failed to get the last block number from state")
   175  		}
   176  
   177  		return lastBlockNumber, nil
   178  
   179  	case EarliestBlockNumber:
   180  		return 0, nil
   181  
   182  	case SafeBlockNumber:
   183  		lastBlockNumber, err := s.GetLastVirtualizedL2BlockNumber(ctx, dbTx)
   184  		if err != nil {
   185  			return 0, NewRPCError(DefaultErrorCode, "failed to get the last virtualized block number from state")
   186  		}
   187  
   188  		return lastBlockNumber, nil
   189  
   190  	case FinalizedBlockNumber:
   191  		lastBlockNumber, err := s.GetLastConsolidatedL2BlockNumber(ctx, dbTx)
   192  		if err != nil {
   193  			return 0, NewRPCError(DefaultErrorCode, "failed to get the last verified block number from state")
   194  		}
   195  
   196  		return lastBlockNumber, nil
   197  
   198  	default:
   199  		if bValue < 0 {
   200  			return 0, NewRPCError(InvalidParamsErrorCode, "invalid block number: %v", bValue)
   201  		}
   202  		return uint64(bValue), nil
   203  	}
   204  }
   205  
   206  // StringOrHex returns the block number as a string or hex
   207  // n == -3 = pending
   208  // n == -2 = latest
   209  // n == -1 = earliest
   210  // n >=  0 = hex(n)
   211  func (b *BlockNumber) StringOrHex() string {
   212  	switch *b {
   213  	case EarliestBlockNumber:
   214  		return Earliest
   215  	case PendingBlockNumber:
   216  		return Pending
   217  	case LatestBlockNumber:
   218  		return Latest
   219  	case SafeBlockNumber:
   220  		return Safe
   221  	case FinalizedBlockNumber:
   222  		return Finalized
   223  	default:
   224  		return hex.EncodeUint64(uint64(*b))
   225  	}
   226  }
   227  
   228  // StringToBlockNumber converts a string like "latest" or "0x1" to a BlockNumber instance
   229  func StringToBlockNumber(str string) (BlockNumber, error) {
   230  	str = strings.Trim(str, "\"")
   231  	switch str {
   232  	case Earliest:
   233  		return EarliestBlockNumber, nil
   234  	case Pending:
   235  		return PendingBlockNumber, nil
   236  	case Latest, "":
   237  		return LatestBlockNumber, nil
   238  	case Safe:
   239  		return SafeBlockNumber, nil
   240  	case Finalized:
   241  		return FinalizedBlockNumber, nil
   242  	}
   243  
   244  	n, err := encoding.DecodeUint64orHex(&str)
   245  	if err != nil {
   246  		return 0, err
   247  	}
   248  	return BlockNumber(n), nil
   249  }
   250  
   251  // BlockNumberOrHash allows a string value to be parsed
   252  // into a block number or a hash, it's used by methods
   253  // like eth_call that allows the block to be specified
   254  // either by the block number or the block hash
   255  type BlockNumberOrHash struct {
   256  	number           *BlockNumber
   257  	hash             *ArgHash
   258  	requireCanonical bool
   259  }
   260  
   261  // IsHash checks if the hash has value
   262  func (b *BlockNumberOrHash) IsHash() bool {
   263  	return b.hash != nil
   264  }
   265  
   266  // IsNumber checks if the number has value
   267  func (b *BlockNumberOrHash) IsNumber() bool {
   268  	return b.number != nil
   269  }
   270  
   271  // SetHash sets the hash and nullify the number
   272  func (b *BlockNumberOrHash) SetHash(hash ArgHash, requireCanonical bool) {
   273  	t := hash
   274  	b.number = nil
   275  	b.hash = &t
   276  	b.requireCanonical = requireCanonical
   277  }
   278  
   279  // SetNumber sets the number and nullify the hash
   280  func (b *BlockNumberOrHash) SetNumber(number BlockNumber) {
   281  	t := number
   282  	b.number = &t
   283  	b.hash = nil
   284  	b.requireCanonical = false
   285  }
   286  
   287  // Hash returns the hash
   288  func (b *BlockNumberOrHash) Hash() *ArgHash {
   289  	return b.hash
   290  }
   291  
   292  // Number returns the number
   293  func (b *BlockNumberOrHash) Number() *BlockNumber {
   294  	return b.number
   295  }
   296  
   297  // UnmarshalJSON automatically decodes the user input for the block number, when a JSON RPC method is called
   298  func (b *BlockNumberOrHash) UnmarshalJSON(buffer []byte) error {
   299  	var number BlockNumber
   300  	err := json.Unmarshal(buffer, &number)
   301  	if err == nil {
   302  		b.SetNumber(number)
   303  		return nil
   304  	}
   305  
   306  	var hash ArgHash
   307  	err = json.Unmarshal(buffer, &hash)
   308  	if err == nil {
   309  		b.SetHash(hash, false)
   310  		return nil
   311  	}
   312  
   313  	var m map[string]interface{}
   314  	err = json.Unmarshal(buffer, &m)
   315  	if err == nil {
   316  		if v, ok := m[BlockNumberKey]; ok {
   317  			input, _ := json.Marshal(v.(string))
   318  			err := json.Unmarshal(input, &number)
   319  			if err == nil {
   320  				b.SetNumber(number)
   321  				return nil
   322  			}
   323  		} else if v, ok := m[BlockHashKey]; ok {
   324  			input, _ := json.Marshal(v.(string))
   325  			err := json.Unmarshal(input, &hash)
   326  			if err == nil {
   327  				requireCanonical, ok := m[RequireCanonicalKey]
   328  				if ok {
   329  					switch v := requireCanonical.(type) {
   330  					case bool:
   331  						b.SetHash(hash, v)
   332  					default:
   333  						return fmt.Errorf("invalid requiredCanonical")
   334  					}
   335  				} else {
   336  					b.SetHash(hash, false)
   337  				}
   338  				return nil
   339  			}
   340  		} else {
   341  			return fmt.Errorf("invalid block or hash")
   342  		}
   343  	}
   344  
   345  	return err
   346  }
   347  
   348  // Index of a item
   349  type Index int64
   350  
   351  // UnmarshalJSON automatically decodes the user input for the block number, when a JSON RPC method is called
   352  func (i *Index) UnmarshalJSON(buffer []byte) error {
   353  	str := strings.Trim(string(buffer), "\"")
   354  	n, err := encoding.DecodeUint64orHex(&str)
   355  	if err != nil {
   356  		return err
   357  	}
   358  	*i = Index(n)
   359  	return nil
   360  }
   361  
   362  // BatchNumber is the number of a ethereum block
   363  type BatchNumber int64
   364  
   365  // UnmarshalJSON automatically decodes the user input for the block number, when a JSON RPC method is called
   366  func (b *BatchNumber) UnmarshalJSON(buffer []byte) error {
   367  	num, err := stringToBatchNumber(string(buffer))
   368  	if err != nil {
   369  		return err
   370  	}
   371  	*b = num
   372  	return nil
   373  }
   374  
   375  // GetNumericBatchNumber returns a numeric batch number based on the BatchNumber instance
   376  func (b *BatchNumber) GetNumericBatchNumber(ctx context.Context, s StateInterface, dbTx pgx.Tx) (uint64, Error) {
   377  	bValue := LatestBatchNumber
   378  	if b != nil {
   379  		bValue = *b
   380  	}
   381  
   382  	switch bValue {
   383  	case LatestBatchNumber:
   384  		lastBatchNumber, err := s.GetLastBatchNumber(ctx, dbTx)
   385  		if err != nil {
   386  			return 0, NewRPCError(DefaultErrorCode, "failed to get the last batch number from state")
   387  		}
   388  
   389  		return lastBatchNumber, nil
   390  
   391  	case EarliestBatchNumber:
   392  		return 0, nil
   393  
   394  	default:
   395  		if bValue < 0 {
   396  			return 0, NewRPCError(InvalidParamsErrorCode, "invalid batch number: %v", bValue)
   397  		}
   398  		return uint64(bValue), nil
   399  	}
   400  }
   401  
   402  func stringToBatchNumber(str string) (BatchNumber, error) {
   403  	str = strings.Trim(str, "\"")
   404  	switch str {
   405  	case Earliest:
   406  		return EarliestBatchNumber, nil
   407  	case Latest, "":
   408  		return LatestBatchNumber, nil
   409  	}
   410  
   411  	n, err := encoding.DecodeUint64orHex(&str)
   412  	if err != nil {
   413  		return 0, err
   414  	}
   415  	return BatchNumber(n), nil
   416  }