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

     1  package types
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"math/big"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"github.com/0xPolygon/supernets2-node/hex"
    12  	"github.com/0xPolygon/supernets2-node/state"
    13  	"github.com/ethereum/go-ethereum/common"
    14  	"github.com/ethereum/go-ethereum/core/types"
    15  	"github.com/jackc/pgx/v4"
    16  )
    17  
    18  // ArgUint64 helps to marshal uint64 values provided in the RPC requests
    19  type ArgUint64 uint64
    20  
    21  // MarshalText marshals into text
    22  func (b ArgUint64) MarshalText() ([]byte, error) {
    23  	buf := make([]byte, 2) //nolint:gomnd
    24  	copy(buf, `0x`)
    25  	buf = strconv.AppendUint(buf, uint64(b), hex.Base)
    26  	return buf, nil
    27  }
    28  
    29  // UnmarshalText unmarshals from text
    30  func (b *ArgUint64) UnmarshalText(input []byte) error {
    31  	str := strings.TrimPrefix(string(input), "0x")
    32  	num, err := strconv.ParseUint(str, hex.Base, hex.BitSize64)
    33  	if err != nil {
    34  		return err
    35  	}
    36  	*b = ArgUint64(num)
    37  	return nil
    38  }
    39  
    40  // Hex returns a hexadecimal representation
    41  func (b ArgUint64) Hex() string {
    42  	bb, _ := b.MarshalText()
    43  	return string(bb)
    44  }
    45  
    46  // ArgUint64Ptr returns the pointer of the provided ArgUint64
    47  func ArgUint64Ptr(a ArgUint64) *ArgUint64 {
    48  	return &a
    49  }
    50  
    51  // ArgBytes helps to marshal byte array values provided in the RPC requests
    52  type ArgBytes []byte
    53  
    54  // MarshalText marshals into text
    55  func (b ArgBytes) MarshalText() ([]byte, error) {
    56  	return encodeToHex(b), nil
    57  }
    58  
    59  // UnmarshalText unmarshals from text
    60  func (b *ArgBytes) UnmarshalText(input []byte) error {
    61  	hh, err := decodeToHex(input)
    62  	if err != nil {
    63  		return nil
    64  	}
    65  	aux := make([]byte, len(hh))
    66  	copy(aux[:], hh[:])
    67  	*b = aux
    68  	return nil
    69  }
    70  
    71  // Hex returns a hexadecimal representation
    72  func (b ArgBytes) Hex() string {
    73  	bb, _ := b.MarshalText()
    74  	return string(bb)
    75  }
    76  
    77  // ArgBytesPtr helps to marshal byte array values provided in the RPC requests
    78  func ArgBytesPtr(b []byte) *ArgBytes {
    79  	bb := ArgBytes(b)
    80  
    81  	return &bb
    82  }
    83  
    84  // ArgBig helps to marshal big number values provided in the RPC requests
    85  type ArgBig big.Int
    86  
    87  // UnmarshalText unmarshals an instance of ArgBig into an array of bytes
    88  func (a *ArgBig) UnmarshalText(input []byte) error {
    89  	buf, err := decodeToHex(input)
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	b := new(big.Int)
    95  	b.SetBytes(buf)
    96  	*a = ArgBig(*b)
    97  
    98  	return nil
    99  }
   100  
   101  // MarshalText marshals an array of bytes into an instance of ArgBig
   102  func (a ArgBig) MarshalText() ([]byte, error) {
   103  	b := (*big.Int)(&a)
   104  
   105  	return []byte("0x" + b.Text(hex.Base)), nil
   106  }
   107  
   108  // Hex returns a hexadecimal representation
   109  func (b ArgBig) Hex() string {
   110  	bb, _ := b.MarshalText()
   111  	return string(bb)
   112  }
   113  
   114  func decodeToHex(b []byte) ([]byte, error) {
   115  	str := string(b)
   116  	str = strings.TrimPrefix(str, "0x")
   117  	if len(str)%2 != 0 {
   118  		str = "0" + str
   119  	}
   120  	return hex.DecodeString(str)
   121  }
   122  
   123  func encodeToHex(b []byte) []byte {
   124  	str := hex.EncodeToString(b)
   125  	if len(str)%2 != 0 {
   126  		str = "0" + str
   127  	}
   128  	return []byte("0x" + str)
   129  }
   130  
   131  // ArgHash represents a common.Hash that accepts strings
   132  // shorter than 64 bytes, like 0x00
   133  type ArgHash common.Hash
   134  
   135  // UnmarshalText unmarshals from text
   136  func (arg *ArgHash) UnmarshalText(input []byte) error {
   137  	if !hex.IsValid(string(input)) {
   138  		return fmt.Errorf("invalid hash, it needs to be a hexadecimal value")
   139  	}
   140  
   141  	str := strings.TrimPrefix(string(input), "0x")
   142  	*arg = ArgHash(common.HexToHash(str))
   143  	return nil
   144  }
   145  
   146  // Hash returns an instance of common.Hash
   147  func (arg *ArgHash) Hash() common.Hash {
   148  	result := common.Hash{}
   149  	if arg != nil {
   150  		result = common.Hash(*arg)
   151  	}
   152  	return result
   153  }
   154  
   155  // ArgAddress represents a common.Address that accepts strings
   156  // shorter than 32 bytes, like 0x00
   157  type ArgAddress common.Address
   158  
   159  // UnmarshalText unmarshals from text
   160  func (b *ArgAddress) UnmarshalText(input []byte) error {
   161  	if !hex.IsValid(string(input)) {
   162  		return fmt.Errorf("invalid address, it needs to be a hexadecimal value")
   163  	}
   164  
   165  	str := strings.TrimPrefix(string(input), "0x")
   166  	*b = ArgAddress(common.HexToAddress(str))
   167  	return nil
   168  }
   169  
   170  // Address returns an instance of common.Address
   171  func (arg *ArgAddress) Address() common.Address {
   172  	result := common.Address{}
   173  	if arg != nil {
   174  		result = common.Address(*arg)
   175  	}
   176  	return result
   177  }
   178  
   179  // TxArgs is the transaction argument for the rpc endpoints
   180  type TxArgs struct {
   181  	From     *common.Address
   182  	To       *common.Address
   183  	Gas      *ArgUint64
   184  	GasPrice *ArgBytes
   185  	Value    *ArgBytes
   186  	Data     *ArgBytes
   187  	Input    *ArgBytes
   188  	Nonce    *ArgUint64
   189  }
   190  
   191  // ToTransaction transforms txnArgs into a Transaction
   192  func (args *TxArgs) ToTransaction(ctx context.Context, st StateInterface, maxCumulativeGasUsed uint64, root common.Hash, defaultSenderAddress common.Address, dbTx pgx.Tx) (common.Address, *types.Transaction, error) {
   193  	sender := defaultSenderAddress
   194  	nonce := uint64(0)
   195  	if args.From != nil && *args.From != state.ZeroAddress {
   196  		sender = *args.From
   197  		n, err := st.GetNonce(ctx, sender, root)
   198  		if err != nil {
   199  			return common.Address{}, nil, err
   200  		}
   201  		nonce = n
   202  	}
   203  
   204  	value := big.NewInt(0)
   205  	if args.Value != nil {
   206  		value.SetBytes(*args.Value)
   207  	}
   208  
   209  	gasPrice := big.NewInt(0)
   210  	if args.GasPrice != nil {
   211  		gasPrice.SetBytes(*args.GasPrice)
   212  	}
   213  
   214  	var data []byte
   215  	if args.Data != nil {
   216  		data = *args.Data
   217  	} else if args.Input != nil {
   218  		data = *args.Input
   219  	} else if args.To == nil {
   220  		return common.Address{}, nil, fmt.Errorf("contract creation without data provided")
   221  	}
   222  
   223  	gas := maxCumulativeGasUsed
   224  	if args.Gas != nil && uint64(*args.Gas) > 0 && uint64(*args.Gas) < maxCumulativeGasUsed {
   225  		gas = uint64(*args.Gas)
   226  	}
   227  
   228  	tx := types.NewTx(&types.LegacyTx{
   229  		Nonce:    nonce,
   230  		To:       args.To,
   231  		Value:    value,
   232  		Gas:      gas,
   233  		GasPrice: gasPrice,
   234  		Data:     data,
   235  	})
   236  
   237  	return sender, tx, nil
   238  }
   239  
   240  // Block structure
   241  type Block struct {
   242  	ParentHash      common.Hash         `json:"parentHash"`
   243  	Sha3Uncles      common.Hash         `json:"sha3Uncles"`
   244  	Miner           common.Address      `json:"miner"`
   245  	StateRoot       common.Hash         `json:"stateRoot"`
   246  	TxRoot          common.Hash         `json:"transactionsRoot"`
   247  	ReceiptsRoot    common.Hash         `json:"receiptsRoot"`
   248  	LogsBloom       types.Bloom         `json:"logsBloom"`
   249  	Difficulty      ArgUint64           `json:"difficulty"`
   250  	TotalDifficulty ArgUint64           `json:"totalDifficulty"`
   251  	Size            ArgUint64           `json:"size"`
   252  	Number          ArgUint64           `json:"number"`
   253  	GasLimit        ArgUint64           `json:"gasLimit"`
   254  	GasUsed         ArgUint64           `json:"gasUsed"`
   255  	Timestamp       ArgUint64           `json:"timestamp"`
   256  	ExtraData       ArgBytes            `json:"extraData"`
   257  	MixHash         common.Hash         `json:"mixHash"`
   258  	Nonce           ArgBytes            `json:"nonce"`
   259  	Hash            common.Hash         `json:"hash"`
   260  	Transactions    []TransactionOrHash `json:"transactions"`
   261  	Uncles          []common.Hash       `json:"uncles"`
   262  }
   263  
   264  // NewBlock creates a Block instance
   265  func NewBlock(b *types.Block, fullTx bool) *Block {
   266  	h := b.Header()
   267  
   268  	n := big.NewInt(0).SetUint64(h.Nonce.Uint64())
   269  	nonce := common.LeftPadBytes(n.Bytes(), 8) //nolint:gomnd
   270  
   271  	var difficulty uint64
   272  	if h.Difficulty != nil {
   273  		difficulty = h.Difficulty.Uint64()
   274  	} else {
   275  		difficulty = uint64(0)
   276  	}
   277  
   278  	res := &Block{
   279  		ParentHash:      h.ParentHash,
   280  		Sha3Uncles:      h.UncleHash,
   281  		Miner:           h.Coinbase,
   282  		StateRoot:       h.Root,
   283  		TxRoot:          h.TxHash,
   284  		ReceiptsRoot:    h.ReceiptHash,
   285  		LogsBloom:       h.Bloom,
   286  		Difficulty:      ArgUint64(difficulty),
   287  		TotalDifficulty: ArgUint64(difficulty),
   288  		Size:            ArgUint64(b.Size()),
   289  		Number:          ArgUint64(b.Number().Uint64()),
   290  		GasLimit:        ArgUint64(h.GasLimit),
   291  		GasUsed:         ArgUint64(h.GasUsed),
   292  		Timestamp:       ArgUint64(h.Time),
   293  		ExtraData:       ArgBytes(h.Extra),
   294  		MixHash:         h.MixDigest,
   295  		Nonce:           nonce,
   296  		Hash:            b.Hash(),
   297  		Transactions:    []TransactionOrHash{},
   298  		Uncles:          []common.Hash{},
   299  	}
   300  
   301  	for idx, txn := range b.Transactions() {
   302  		if fullTx {
   303  			blockHash := b.Hash()
   304  			txIndex := uint64(idx)
   305  			tx := NewTransaction(*txn, b.Number(), &blockHash, &txIndex)
   306  			res.Transactions = append(
   307  				res.Transactions,
   308  				TransactionOrHash{Tx: tx},
   309  			)
   310  		} else {
   311  			h := txn.Hash()
   312  			res.Transactions = append(
   313  				res.Transactions,
   314  				TransactionOrHash{Hash: &h},
   315  			)
   316  		}
   317  	}
   318  
   319  	for _, uncle := range b.Uncles() {
   320  		res.Uncles = append(res.Uncles, uncle.Hash())
   321  	}
   322  
   323  	return res
   324  }
   325  
   326  // Batch structure
   327  type Batch struct {
   328  	Number              ArgUint64           `json:"number"`
   329  	Coinbase            common.Address      `json:"coinbase"`
   330  	StateRoot           common.Hash         `json:"stateRoot"`
   331  	GlobalExitRoot      common.Hash         `json:"globalExitRoot"`
   332  	MainnetExitRoot     common.Hash         `json:"mainnetExitRoot"`
   333  	RollupExitRoot      common.Hash         `json:"rollupExitRoot"`
   334  	LocalExitRoot       common.Hash         `json:"localExitRoot"`
   335  	AccInputHash        common.Hash         `json:"accInputHash"`
   336  	Timestamp           ArgUint64           `json:"timestamp"`
   337  	SendSequencesTxHash *common.Hash        `json:"sendSequencesTxHash"`
   338  	VerifyBatchTxHash   *common.Hash        `json:"verifyBatchTxHash"`
   339  	Transactions        []TransactionOrHash `json:"transactions"`
   340  	BatchL2Data         ArgBytes            `json:"batchL2Data"`
   341  }
   342  
   343  // NewBatch creates a Batch instance
   344  func NewBatch(
   345  	batch *state.Batch,
   346  	virtualBatch *state.VirtualBatch,
   347  	verifiedBatch *state.VerifiedBatch,
   348  	receipts []types.Receipt,
   349  	fullTx bool,
   350  	ger *state.GlobalExitRoot,
   351  ) (*Batch, error) {
   352  	batchL2Data := batch.BatchL2Data
   353  	if batchL2Data == nil {
   354  		batchL2dataFromTxs, err := state.EncodeTransactions(batch.Transactions)
   355  		if err != nil {
   356  			return nil, fmt.Errorf("error encoding txs into raw data: %w", err)
   357  		} else {
   358  			batchL2Data = batchL2dataFromTxs
   359  		}
   360  	}
   361  	res := &Batch{
   362  		Number:          ArgUint64(batch.BatchNumber),
   363  		GlobalExitRoot:  batch.GlobalExitRoot,
   364  		MainnetExitRoot: ger.MainnetExitRoot,
   365  		RollupExitRoot:  ger.RollupExitRoot,
   366  		AccInputHash:    batch.AccInputHash,
   367  		Timestamp:       ArgUint64(batch.Timestamp.Unix()),
   368  		StateRoot:       batch.StateRoot,
   369  		Coinbase:        batch.Coinbase,
   370  		LocalExitRoot:   batch.LocalExitRoot,
   371  		BatchL2Data:     ArgBytes(batchL2Data),
   372  	}
   373  
   374  	if virtualBatch != nil {
   375  		res.SendSequencesTxHash = &virtualBatch.TxHash
   376  	}
   377  
   378  	if verifiedBatch != nil {
   379  		res.VerifyBatchTxHash = &verifiedBatch.TxHash
   380  	}
   381  
   382  	receiptsMap := make(map[common.Hash]types.Receipt, len(receipts))
   383  	for _, receipt := range receipts {
   384  		receiptsMap[receipt.TxHash] = receipt
   385  	}
   386  
   387  	for _, tx := range batch.Transactions {
   388  		if fullTx {
   389  			receipt := receiptsMap[tx.Hash()]
   390  			txIndex := uint64(receipt.TransactionIndex)
   391  			rpcTx := NewTransaction(tx, receipt.BlockNumber, &receipt.BlockHash, &txIndex)
   392  			res.Transactions = append(res.Transactions, TransactionOrHash{Tx: rpcTx})
   393  		} else {
   394  			h := tx.Hash()
   395  			res.Transactions = append(res.Transactions, TransactionOrHash{Hash: &h})
   396  		}
   397  	}
   398  
   399  	return res, nil
   400  }
   401  
   402  // TransactionOrHash for union type of transaction and types.Hash
   403  type TransactionOrHash struct {
   404  	Hash *common.Hash
   405  	Tx   *Transaction
   406  }
   407  
   408  // MarshalJSON marshals into json
   409  func (b TransactionOrHash) MarshalJSON() ([]byte, error) {
   410  	if b.Hash != nil {
   411  		return json.Marshal(b.Hash)
   412  	}
   413  	return json.Marshal(b.Tx)
   414  }
   415  
   416  // UnmarshalJSON unmarshals from json
   417  func (b *TransactionOrHash) UnmarshalJSON(input []byte) error {
   418  	v := string(input)
   419  	if strings.HasPrefix(v, "0x") || strings.HasPrefix(v, "\"0x") {
   420  		var h common.Hash
   421  		err := json.Unmarshal(input, &h)
   422  		if err != nil {
   423  			return err
   424  		}
   425  		*b = TransactionOrHash{Hash: &h}
   426  		return nil
   427  	}
   428  
   429  	var t Transaction
   430  	err := json.Unmarshal(input, &t)
   431  	if err != nil {
   432  		return err
   433  	}
   434  	*b = TransactionOrHash{Tx: &t}
   435  	return nil
   436  }
   437  
   438  // Transaction structure
   439  type Transaction struct {
   440  	Nonce       ArgUint64       `json:"nonce"`
   441  	GasPrice    ArgBig          `json:"gasPrice"`
   442  	Gas         ArgUint64       `json:"gas"`
   443  	To          *common.Address `json:"to"`
   444  	Value       ArgBig          `json:"value"`
   445  	Input       ArgBytes        `json:"input"`
   446  	V           ArgBig          `json:"v"`
   447  	R           ArgBig          `json:"r"`
   448  	S           ArgBig          `json:"s"`
   449  	Hash        common.Hash     `json:"hash"`
   450  	From        common.Address  `json:"from"`
   451  	BlockHash   *common.Hash    `json:"blockHash"`
   452  	BlockNumber *ArgUint64      `json:"blockNumber"`
   453  	TxIndex     *ArgUint64      `json:"transactionIndex"`
   454  	ChainID     ArgBig          `json:"chainId"`
   455  	Type        ArgUint64       `json:"type"`
   456  }
   457  
   458  // CoreTx returns a geth core type Transaction
   459  func (t Transaction) CoreTx() *types.Transaction {
   460  	return types.NewTx(&types.LegacyTx{
   461  		Nonce:    uint64(t.Nonce),
   462  		GasPrice: (*big.Int)(&t.GasPrice),
   463  		Gas:      uint64(t.Gas),
   464  		To:       t.To,
   465  		Value:    (*big.Int)(&t.Value),
   466  		Data:     t.Input,
   467  		V:        (*big.Int)(&t.V),
   468  		R:        (*big.Int)(&t.R),
   469  		S:        (*big.Int)(&t.S),
   470  	})
   471  }
   472  
   473  // NewTransaction creates a transaction instance
   474  func NewTransaction(
   475  	t types.Transaction,
   476  	blockNumber *big.Int,
   477  	blockHash *common.Hash,
   478  	txIndex *uint64,
   479  ) *Transaction {
   480  	v, r, s := t.RawSignatureValues()
   481  
   482  	from, _ := state.GetSender(t)
   483  
   484  	res := &Transaction{
   485  		Nonce:    ArgUint64(t.Nonce()),
   486  		GasPrice: ArgBig(*t.GasPrice()),
   487  		Gas:      ArgUint64(t.Gas()),
   488  		To:       t.To(),
   489  		Value:    ArgBig(*t.Value()),
   490  		Input:    t.Data(),
   491  		V:        ArgBig(*v),
   492  		R:        ArgBig(*r),
   493  		S:        ArgBig(*s),
   494  		Hash:     t.Hash(),
   495  		From:     from,
   496  		ChainID:  ArgBig(*t.ChainId()),
   497  		Type:     ArgUint64(t.Type()),
   498  	}
   499  
   500  	if blockNumber != nil {
   501  		bn := ArgUint64(blockNumber.Uint64())
   502  		res.BlockNumber = &bn
   503  	}
   504  
   505  	res.BlockHash = blockHash
   506  
   507  	if txIndex != nil {
   508  		ti := ArgUint64(*txIndex)
   509  		res.TxIndex = &ti
   510  	}
   511  
   512  	return res
   513  }
   514  
   515  // Receipt structure
   516  type Receipt struct {
   517  	Root              common.Hash     `json:"root"`
   518  	CumulativeGasUsed ArgUint64       `json:"cumulativeGasUsed"`
   519  	LogsBloom         types.Bloom     `json:"logsBloom"`
   520  	Logs              []*types.Log    `json:"logs"`
   521  	Status            ArgUint64       `json:"status"`
   522  	TxHash            common.Hash     `json:"transactionHash"`
   523  	TxIndex           ArgUint64       `json:"transactionIndex"`
   524  	BlockHash         common.Hash     `json:"blockHash"`
   525  	BlockNumber       ArgUint64       `json:"blockNumber"`
   526  	GasUsed           ArgUint64       `json:"gasUsed"`
   527  	FromAddr          common.Address  `json:"from"`
   528  	ToAddr            *common.Address `json:"to"`
   529  	ContractAddress   *common.Address `json:"contractAddress"`
   530  	Type              ArgUint64       `json:"type"`
   531  }
   532  
   533  // NewReceipt creates a new Receipt instance
   534  func NewReceipt(tx types.Transaction, r *types.Receipt) (Receipt, error) {
   535  	to := tx.To()
   536  	logs := r.Logs
   537  	if logs == nil {
   538  		logs = []*types.Log{}
   539  	}
   540  
   541  	var contractAddress *common.Address
   542  	if r.ContractAddress != state.ZeroAddress {
   543  		ca := r.ContractAddress
   544  		contractAddress = &ca
   545  	}
   546  
   547  	blockNumber := ArgUint64(0)
   548  	if r.BlockNumber != nil {
   549  		blockNumber = ArgUint64(r.BlockNumber.Uint64())
   550  	}
   551  
   552  	from, err := state.GetSender(tx)
   553  	if err != nil {
   554  		return Receipt{}, err
   555  	}
   556  
   557  	return Receipt{
   558  		Root:              common.BytesToHash(r.PostState),
   559  		CumulativeGasUsed: ArgUint64(r.CumulativeGasUsed),
   560  		LogsBloom:         r.Bloom,
   561  		Logs:              logs,
   562  		Status:            ArgUint64(r.Status),
   563  		TxHash:            r.TxHash,
   564  		TxIndex:           ArgUint64(r.TransactionIndex),
   565  		BlockHash:         r.BlockHash,
   566  		BlockNumber:       blockNumber,
   567  		GasUsed:           ArgUint64(r.GasUsed),
   568  		ContractAddress:   contractAddress,
   569  		FromAddr:          from,
   570  		ToAddr:            to,
   571  		Type:              ArgUint64(r.Type),
   572  	}, nil
   573  }
   574  
   575  // Log structure
   576  type Log struct {
   577  	Address     common.Address `json:"address"`
   578  	Topics      []common.Hash  `json:"topics"`
   579  	Data        ArgBytes       `json:"data"`
   580  	BlockNumber ArgUint64      `json:"blockNumber"`
   581  	TxHash      common.Hash    `json:"transactionHash"`
   582  	TxIndex     ArgUint64      `json:"transactionIndex"`
   583  	BlockHash   common.Hash    `json:"blockHash"`
   584  	LogIndex    ArgUint64      `json:"logIndex"`
   585  	Removed     bool           `json:"removed"`
   586  }
   587  
   588  // NewLog creates a new instance of Log
   589  func NewLog(l types.Log) Log {
   590  	return Log{
   591  		Address:     l.Address,
   592  		Topics:      l.Topics,
   593  		Data:        l.Data,
   594  		BlockNumber: ArgUint64(l.BlockNumber),
   595  		TxHash:      l.TxHash,
   596  		TxIndex:     ArgUint64(l.TxIndex),
   597  		BlockHash:   l.BlockHash,
   598  		LogIndex:    ArgUint64(l.Index),
   599  		Removed:     l.Removed,
   600  	}
   601  }
   602  
   603  // ToBatchNumArg converts a big.Int into a batch number rpc parameter
   604  func ToBatchNumArg(number *big.Int) string {
   605  	if number == nil {
   606  		return Latest
   607  	}
   608  	pending := big.NewInt(-1)
   609  	if number.Cmp(pending) == 0 {
   610  		return Pending
   611  	}
   612  	return hex.EncodeBig(number)
   613  }