github.com/MetalBlockchain/metalgo@v1.11.9/vms/platformvm/block/executor/manager.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package executor
     5  
     6  import (
     7  	"errors"
     8  
     9  	"github.com/MetalBlockchain/metalgo/ids"
    10  	"github.com/MetalBlockchain/metalgo/snow/consensus/snowman"
    11  	"github.com/MetalBlockchain/metalgo/utils/set"
    12  	"github.com/MetalBlockchain/metalgo/vms/platformvm/block"
    13  	"github.com/MetalBlockchain/metalgo/vms/platformvm/metrics"
    14  	"github.com/MetalBlockchain/metalgo/vms/platformvm/state"
    15  	"github.com/MetalBlockchain/metalgo/vms/platformvm/txs"
    16  	"github.com/MetalBlockchain/metalgo/vms/platformvm/txs/executor"
    17  	"github.com/MetalBlockchain/metalgo/vms/platformvm/txs/mempool"
    18  	"github.com/MetalBlockchain/metalgo/vms/platformvm/validators"
    19  )
    20  
    21  var (
    22  	_ Manager = (*manager)(nil)
    23  
    24  	ErrChainNotSynced = errors.New("chain not synced")
    25  )
    26  
    27  type Manager interface {
    28  	state.Versions
    29  
    30  	// Returns the ID of the most recently accepted block.
    31  	LastAccepted() ids.ID
    32  
    33  	SetPreference(blkID ids.ID) (updated bool)
    34  	Preferred() ids.ID
    35  
    36  	GetBlock(blkID ids.ID) (snowman.Block, error)
    37  	GetStatelessBlock(blkID ids.ID) (block.Block, error)
    38  	NewBlock(block.Block) snowman.Block
    39  
    40  	// VerifyTx verifies that the transaction can be issued based on the currently
    41  	// preferred state. This should *not* be used to verify transactions in a block.
    42  	VerifyTx(tx *txs.Tx) error
    43  
    44  	// VerifyUniqueInputs verifies that the inputs are not duplicated in the
    45  	// provided blk or any of its ancestors pinned in memory.
    46  	VerifyUniqueInputs(blkID ids.ID, inputs set.Set[ids.ID]) error
    47  }
    48  
    49  func NewManager(
    50  	mempool mempool.Mempool,
    51  	metrics metrics.Metrics,
    52  	s state.State,
    53  	txExecutorBackend *executor.Backend,
    54  	validatorManager validators.Manager,
    55  ) Manager {
    56  	lastAccepted := s.GetLastAccepted()
    57  	backend := &backend{
    58  		Mempool:      mempool,
    59  		lastAccepted: lastAccepted,
    60  		state:        s,
    61  		ctx:          txExecutorBackend.Ctx,
    62  		blkIDToState: map[ids.ID]*blockState{},
    63  	}
    64  
    65  	return &manager{
    66  		backend: backend,
    67  		verifier: &verifier{
    68  			backend:           backend,
    69  			txExecutorBackend: txExecutorBackend,
    70  		},
    71  		acceptor: &acceptor{
    72  			backend:      backend,
    73  			metrics:      metrics,
    74  			validators:   validatorManager,
    75  			bootstrapped: txExecutorBackend.Bootstrapped,
    76  		},
    77  		rejector: &rejector{
    78  			backend:         backend,
    79  			addTxsToMempool: !txExecutorBackend.Config.PartialSyncPrimaryNetwork,
    80  		},
    81  		preferred:         lastAccepted,
    82  		txExecutorBackend: txExecutorBackend,
    83  	}
    84  }
    85  
    86  type manager struct {
    87  	*backend
    88  	verifier block.Visitor
    89  	acceptor block.Visitor
    90  	rejector block.Visitor
    91  
    92  	preferred         ids.ID
    93  	txExecutorBackend *executor.Backend
    94  }
    95  
    96  func (m *manager) GetBlock(blkID ids.ID) (snowman.Block, error) {
    97  	blk, err := m.backend.GetBlock(blkID)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	return m.NewBlock(blk), nil
   102  }
   103  
   104  func (m *manager) GetStatelessBlock(blkID ids.ID) (block.Block, error) {
   105  	return m.backend.GetBlock(blkID)
   106  }
   107  
   108  func (m *manager) NewBlock(blk block.Block) snowman.Block {
   109  	return &Block{
   110  		manager: m,
   111  		Block:   blk,
   112  	}
   113  }
   114  
   115  func (m *manager) SetPreference(blkID ids.ID) bool {
   116  	updated := m.preferred != blkID
   117  	m.preferred = blkID
   118  	return updated
   119  }
   120  
   121  func (m *manager) Preferred() ids.ID {
   122  	return m.preferred
   123  }
   124  
   125  func (m *manager) VerifyTx(tx *txs.Tx) error {
   126  	if !m.txExecutorBackend.Bootstrapped.Get() {
   127  		return ErrChainNotSynced
   128  	}
   129  
   130  	stateDiff, err := state.NewDiff(m.preferred, m)
   131  	if err != nil {
   132  		return err
   133  	}
   134  
   135  	nextBlkTime, _, err := state.NextBlockTime(stateDiff, m.txExecutorBackend.Clk)
   136  	if err != nil {
   137  		return err
   138  	}
   139  
   140  	_, err = executor.AdvanceTimeTo(m.txExecutorBackend, stateDiff, nextBlkTime)
   141  	if err != nil {
   142  		return err
   143  	}
   144  
   145  	return tx.Unsigned.Visit(&executor.StandardTxExecutor{
   146  		Backend: m.txExecutorBackend,
   147  		State:   stateDiff,
   148  		Tx:      tx,
   149  	})
   150  }
   151  
   152  func (m *manager) VerifyUniqueInputs(blkID ids.ID, inputs set.Set[ids.ID]) error {
   153  	return m.backend.verifyUniqueInputs(blkID, inputs)
   154  }