github.com/koko1123/flow-go-1@v0.29.6/fvm/derived/derived_block_data.go (about)

     1  package derived
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/onflow/cadence/runtime/common"
     7  	"github.com/onflow/cadence/runtime/interpreter"
     8  
     9  	"github.com/koko1123/flow-go-1/fvm/state"
    10  )
    11  
    12  // ProgramDependencies are the locations of the programs this program depends on.
    13  type ProgramDependencies map[common.Address]struct{}
    14  
    15  // AddDependency adds the address as a dependency.
    16  func (d ProgramDependencies) AddDependency(address common.Address) {
    17  	d[address] = struct{}{}
    18  }
    19  
    20  // Merge merges current dependencies with other dependencies.
    21  func (d ProgramDependencies) Merge(other ProgramDependencies) {
    22  	for address := range other {
    23  		d[address] = struct{}{}
    24  	}
    25  }
    26  
    27  type Program struct {
    28  	*interpreter.Program
    29  
    30  	Dependencies ProgramDependencies
    31  }
    32  
    33  // DerivedBlockData is a simple fork-aware OCC database for "caching" derived
    34  // data for a particular block.
    35  type DerivedBlockData struct {
    36  	programs *DerivedDataTable[common.AddressLocation, *Program]
    37  
    38  	meterParamOverrides *DerivedDataTable[struct{}, MeterParamOverrides]
    39  }
    40  
    41  // DerivedTransactionData is the derived data scratch space for a single
    42  // transaction.
    43  type DerivedTransactionData struct {
    44  	programs *TableTransaction[
    45  		common.AddressLocation,
    46  		*Program,
    47  	]
    48  
    49  	// There's only a single entry in this table.  For simplicity, we'll use
    50  	// struct{} as the entry's key.
    51  	meterParamOverrides *TableTransaction[struct{}, MeterParamOverrides]
    52  }
    53  
    54  func NewEmptyDerivedBlockData() *DerivedBlockData {
    55  	return &DerivedBlockData{
    56  		programs: NewEmptyTable[
    57  			common.AddressLocation,
    58  			*Program,
    59  		](),
    60  		meterParamOverrides: NewEmptyTable[
    61  			struct{},
    62  			MeterParamOverrides,
    63  		](),
    64  	}
    65  }
    66  
    67  // This variant is needed by the chunk verifier, which does not start at the
    68  // beginning of the block.
    69  func NewEmptyDerivedBlockDataWithTransactionOffset(offset uint32) *DerivedBlockData {
    70  	return &DerivedBlockData{
    71  		programs: NewEmptyTableWithOffset[
    72  			common.AddressLocation,
    73  			*Program,
    74  		](offset),
    75  		meterParamOverrides: NewEmptyTableWithOffset[
    76  			struct{},
    77  			MeterParamOverrides,
    78  		](offset),
    79  	}
    80  }
    81  
    82  func (block *DerivedBlockData) NewChildDerivedBlockData() *DerivedBlockData {
    83  	return &DerivedBlockData{
    84  		programs:            block.programs.NewChildTable(),
    85  		meterParamOverrides: block.meterParamOverrides.NewChildTable(),
    86  	}
    87  }
    88  
    89  func (block *DerivedBlockData) NewSnapshotReadDerivedTransactionData(
    90  	snapshotTime LogicalTime,
    91  	executionTime LogicalTime,
    92  ) (
    93  	*DerivedTransactionData,
    94  	error,
    95  ) {
    96  	txnPrograms, err := block.programs.NewSnapshotReadTableTransaction(
    97  		snapshotTime,
    98  		executionTime)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  
   103  	txnMeterParamOverrides, err := block.meterParamOverrides.NewSnapshotReadTableTransaction(
   104  		snapshotTime,
   105  		executionTime)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  
   110  	return &DerivedTransactionData{
   111  		programs:            txnPrograms,
   112  		meterParamOverrides: txnMeterParamOverrides,
   113  	}, nil
   114  }
   115  
   116  func (block *DerivedBlockData) NewDerivedTransactionData(
   117  	snapshotTime LogicalTime,
   118  	executionTime LogicalTime,
   119  ) (
   120  	*DerivedTransactionData,
   121  	error,
   122  ) {
   123  	txnPrograms, err := block.programs.NewTableTransaction(
   124  		snapshotTime,
   125  		executionTime)
   126  	if err != nil {
   127  		return nil, err
   128  	}
   129  
   130  	txnMeterParamOverrides, err := block.meterParamOverrides.NewTableTransaction(
   131  		snapshotTime,
   132  		executionTime)
   133  	if err != nil {
   134  		return nil, err
   135  	}
   136  
   137  	return &DerivedTransactionData{
   138  		programs:            txnPrograms,
   139  		meterParamOverrides: txnMeterParamOverrides,
   140  	}, nil
   141  }
   142  
   143  func (block *DerivedBlockData) NextTxIndexForTestingOnly() uint32 {
   144  	// NOTE: We can use next tx index from any table since they are identical.
   145  	return block.programs.NextTxIndexForTestingOnly()
   146  }
   147  
   148  func (block *DerivedBlockData) GetProgramForTestingOnly(
   149  	addressLocation common.AddressLocation,
   150  ) *invalidatableEntry[*Program] {
   151  	return block.programs.GetForTestingOnly(addressLocation)
   152  }
   153  
   154  func (transaction *DerivedTransactionData) GetProgram(
   155  	addressLocation common.AddressLocation,
   156  ) (
   157  	*Program,
   158  	*state.State,
   159  	bool,
   160  ) {
   161  	return transaction.programs.Get(addressLocation)
   162  }
   163  
   164  func (transaction *DerivedTransactionData) SetProgram(
   165  	addressLocation common.AddressLocation,
   166  	program *Program,
   167  	state *state.State,
   168  ) {
   169  	transaction.programs.Set(addressLocation, program, state)
   170  }
   171  
   172  func (transaction *DerivedTransactionData) AddInvalidator(
   173  	invalidator TransactionInvalidator,
   174  ) {
   175  	if invalidator == nil {
   176  		return
   177  	}
   178  
   179  	transaction.programs.AddInvalidator(invalidator.ProgramInvalidator())
   180  	transaction.meterParamOverrides.AddInvalidator(
   181  		invalidator.MeterParamOverridesInvalidator())
   182  }
   183  
   184  func (transaction *DerivedTransactionData) GetMeterParamOverrides(
   185  	txnState *state.TransactionState,
   186  	getMeterParamOverrides ValueComputer[struct{}, MeterParamOverrides],
   187  ) (
   188  	MeterParamOverrides,
   189  	error,
   190  ) {
   191  	return transaction.meterParamOverrides.GetOrCompute(
   192  		txnState,
   193  		struct{}{},
   194  		getMeterParamOverrides)
   195  }
   196  
   197  func (transaction *DerivedTransactionData) Validate() error {
   198  	err := transaction.programs.Validate()
   199  	if err != nil {
   200  		return fmt.Errorf("programs validate failed: %w", err)
   201  	}
   202  
   203  	err = transaction.meterParamOverrides.Validate()
   204  	if err != nil {
   205  		return fmt.Errorf("meter param overrides validate failed: %w", err)
   206  	}
   207  
   208  	return nil
   209  }
   210  
   211  func (transaction *DerivedTransactionData) Commit() error {
   212  	err := transaction.programs.Commit()
   213  	if err != nil {
   214  		return fmt.Errorf("programs commit failed: %w", err)
   215  	}
   216  
   217  	err = transaction.meterParamOverrides.Commit()
   218  	if err != nil {
   219  		return fmt.Errorf("meter param overrides commit failed: %w", err)
   220  	}
   221  
   222  	return nil
   223  }