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

     1  package state
     2  
     3  import (
     4  	"context"
     5  	"math/big"
     6  	"sync"
     7  
     8  	"github.com/0xPolygon/supernets2-node/event"
     9  	"github.com/0xPolygon/supernets2-node/merkletree"
    10  	"github.com/0xPolygon/supernets2-node/state/metrics"
    11  	"github.com/0xPolygon/supernets2-node/state/runtime/executor/pb"
    12  	"github.com/ethereum/go-ethereum/common"
    13  	"github.com/ethereum/go-ethereum/core/types"
    14  	"github.com/jackc/pgx/v4"
    15  )
    16  
    17  var (
    18  	// ZeroHash is the hash 0x0000000000000000000000000000000000000000000000000000000000000000
    19  	ZeroHash = common.Hash{}
    20  	// ZeroAddress is the address 0x0000000000000000000000000000000000000000
    21  	ZeroAddress = common.Address{}
    22  )
    23  
    24  // State is an implementation of the state
    25  type State struct {
    26  	cfg Config
    27  	*PostgresStorage
    28  	executorClient pb.ExecutorServiceClient
    29  	tree           *merkletree.StateTree
    30  	eventLog       *event.EventLog
    31  
    32  	lastL2BlockSeen         types.Block
    33  	newL2BlockEvents        chan NewL2BlockEvent
    34  	newL2BlockEventHandlers []NewL2BlockEventHandler
    35  }
    36  
    37  // NewState creates a new State
    38  func NewState(cfg Config, storage *PostgresStorage, executorClient pb.ExecutorServiceClient, stateTree *merkletree.StateTree, eventLog *event.EventLog) *State {
    39  	var once sync.Once
    40  	once.Do(func() {
    41  		metrics.Register()
    42  	})
    43  
    44  	state := &State{
    45  		cfg:                     cfg,
    46  		PostgresStorage:         storage,
    47  		executorClient:          executorClient,
    48  		tree:                    stateTree,
    49  		eventLog:                eventLog,
    50  		newL2BlockEvents:        make(chan NewL2BlockEvent),
    51  		newL2BlockEventHandlers: []NewL2BlockEventHandler{},
    52  	}
    53  
    54  	return state
    55  }
    56  
    57  // BeginStateTransaction starts a state transaction
    58  func (s *State) BeginStateTransaction(ctx context.Context) (pgx.Tx, error) {
    59  	tx, err := s.Begin(ctx)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	return tx, nil
    64  }
    65  
    66  // GetBalance from a given address
    67  func (s *State) GetBalance(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) {
    68  	if s.tree == nil {
    69  		return nil, ErrStateTreeNil
    70  	}
    71  	return s.tree.GetBalance(ctx, address, root.Bytes())
    72  }
    73  
    74  // GetCode from a given address
    75  func (s *State) GetCode(ctx context.Context, address common.Address, root common.Hash) ([]byte, error) {
    76  	if s.tree == nil {
    77  		return nil, ErrStateTreeNil
    78  	}
    79  	return s.tree.GetCode(ctx, address, root.Bytes())
    80  }
    81  
    82  // GetNonce returns the nonce of the given account at the given block number
    83  func (s *State) GetNonce(ctx context.Context, address common.Address, root common.Hash) (uint64, error) {
    84  	if s.tree == nil {
    85  		return 0, ErrStateTreeNil
    86  	}
    87  	nonce, err := s.tree.GetNonce(ctx, address, root.Bytes())
    88  	if err != nil {
    89  		return 0, err
    90  	}
    91  	return nonce.Uint64(), nil
    92  }
    93  
    94  // GetStorageAt from a given address
    95  func (s *State) GetStorageAt(ctx context.Context, address common.Address, position *big.Int, root common.Hash) (*big.Int, error) {
    96  	if s.tree == nil {
    97  		return nil, ErrStateTreeNil
    98  	}
    99  	return s.tree.GetStorageAt(ctx, address, position, root.Bytes())
   100  }
   101  
   102  // GetLastStateRoot returns the latest state root
   103  func (s *State) GetLastStateRoot(ctx context.Context, dbTx pgx.Tx) (common.Hash, error) {
   104  	lastBlockHeader, err := s.GetLastL2BlockHeader(ctx, dbTx)
   105  	if err != nil {
   106  		return common.Hash{}, err
   107  	}
   108  	return lastBlockHeader.Root, nil
   109  }
   110  
   111  // GetBalanceByStateRoot gets balance from the MT Service using the provided state root
   112  func (s *State) GetBalanceByStateRoot(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) {
   113  	if s.tree == nil {
   114  		return nil, ErrStateTreeNil
   115  	}
   116  	balance, err := s.tree.GetBalance(ctx, address, root.Bytes())
   117  	if err != nil && balance == nil {
   118  		balance = big.NewInt(0)
   119  	}
   120  	return balance, err
   121  }
   122  
   123  // GetNonceByStateRoot gets nonce from the MT Service using the provided state root
   124  func (s *State) GetNonceByStateRoot(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) {
   125  	if s.tree == nil {
   126  		return nil, ErrStateTreeNil
   127  	}
   128  	return s.tree.GetNonce(ctx, address, root.Bytes())
   129  }
   130  
   131  // GetTree returns State inner tree
   132  func (s *State) GetTree() *merkletree.StateTree {
   133  	return s.tree
   134  }
   135  
   136  // FlushMerkleTree persists updates in the Merkle tree
   137  func (s *State) FlushMerkleTree(ctx context.Context) error {
   138  	if s.tree == nil {
   139  		return ErrStateTreeNil
   140  	}
   141  	return s.tree.Flush(ctx)
   142  }