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

     1  package environment
     2  
     3  import (
     4  	"github.com/onflow/cadence/runtime/common"
     5  
     6  	"github.com/koko1123/flow-go-1/fvm/derived"
     7  	"github.com/koko1123/flow-go-1/fvm/state"
     8  )
     9  
    10  type ContractUpdateKey struct {
    11  	Address common.Address
    12  	Name    string
    13  }
    14  
    15  type ContractUpdate struct {
    16  	ContractUpdateKey
    17  	Code []byte
    18  }
    19  
    20  type DerivedDataInvalidator struct {
    21  	ContractUpdateKeys []ContractUpdateKey
    22  	FrozenAccounts     []common.Address
    23  
    24  	MeterParamOverridesUpdated bool
    25  }
    26  
    27  var _ derived.TransactionInvalidator = DerivedDataInvalidator{}
    28  
    29  func NewDerivedDataInvalidator(
    30  	contractKeys []ContractUpdateKey,
    31  	env *facadeEnvironment,
    32  ) DerivedDataInvalidator {
    33  	return DerivedDataInvalidator{
    34  		ContractUpdateKeys:         contractKeys,
    35  		FrozenAccounts:             env.FrozenAccounts(),
    36  		MeterParamOverridesUpdated: meterParamOverridesUpdated(env),
    37  	}
    38  }
    39  
    40  func meterParamOverridesUpdated(env *facadeEnvironment) bool {
    41  	updatedRegisterIds, _ := env.txnState.RegisterUpdates()
    42  
    43  	serviceAccount := string(env.chain.ServiceAddress().Bytes())
    44  	storageDomain := common.PathDomainStorage.Identifier()
    45  	for _, registerId := range updatedRegisterIds {
    46  		// The meter param override values are stored in the service account.
    47  		if registerId.Owner != serviceAccount {
    48  			continue
    49  		}
    50  
    51  		// NOTE: This condition is empirically generated by running the
    52  		// MeterParamOverridesComputer to capture touched registers.
    53  		//
    54  		// The paramater settings are stored as regular fields in the service
    55  		// account.  In general, each account's regular fields are stored in
    56  		// ordered map known only to cadence.  Cadence encodes this map into
    57  		// bytes and split the bytes into slab chunks before storing the slabs
    58  		// into the ledger.  Hence any changes to the stabs indicate changes
    59  		// the ordered map.
    60  		//
    61  		// The meter param overrides use storageDomain as input, so any
    62  		// changes to it must also invalidate the values.
    63  		if registerId.Key == storageDomain ||
    64  			state.IsSlabIndex(registerId.Key) {
    65  			return true
    66  		}
    67  	}
    68  
    69  	return false
    70  }
    71  
    72  func (invalidator DerivedDataInvalidator) ProgramInvalidator() derived.ProgramInvalidator {
    73  	return ProgramInvalidator{invalidator}
    74  }
    75  
    76  func (invalidator DerivedDataInvalidator) MeterParamOverridesInvalidator() derived.MeterParamOverridesInvalidator {
    77  	return MeterParamOverridesInvalidator{invalidator}
    78  }
    79  
    80  type ProgramInvalidator struct {
    81  	DerivedDataInvalidator
    82  }
    83  
    84  func (invalidator ProgramInvalidator) ShouldInvalidateEntries() bool {
    85  	return invalidator.MeterParamOverridesUpdated ||
    86  		len(invalidator.ContractUpdateKeys) > 0 ||
    87  		len(invalidator.FrozenAccounts) > 0
    88  }
    89  
    90  func (invalidator ProgramInvalidator) ShouldInvalidateEntry(
    91  	location common.AddressLocation,
    92  	program *derived.Program,
    93  	state *state.State,
    94  ) bool {
    95  	if invalidator.MeterParamOverridesUpdated {
    96  		// if meter parameters changed we need to invalidate all programs
    97  		return true
    98  	}
    99  
   100  	// if an account was (un)frozen we need to invalidate all
   101  	// programs that depend on any contract on that address.
   102  	for _, frozenAccount := range invalidator.FrozenAccounts {
   103  		_, ok := program.Dependencies[frozenAccount]
   104  		if ok {
   105  			return true
   106  		}
   107  	}
   108  
   109  	// invalidate all programs depending on any of the contracts that were updated
   110  	// A program has itself listed as a dependency, so that this simpler.
   111  	for _, key := range invalidator.ContractUpdateKeys {
   112  		_, ok := program.Dependencies[key.Address]
   113  		if ok {
   114  			return true
   115  		}
   116  	}
   117  	return false
   118  }
   119  
   120  type MeterParamOverridesInvalidator struct {
   121  	DerivedDataInvalidator
   122  }
   123  
   124  func (invalidator MeterParamOverridesInvalidator) ShouldInvalidateEntries() bool {
   125  	return invalidator.MeterParamOverridesUpdated
   126  }
   127  
   128  func (invalidator MeterParamOverridesInvalidator) ShouldInvalidateEntry(
   129  	_ struct{},
   130  	_ derived.MeterParamOverrides,
   131  	_ *state.State,
   132  ) bool {
   133  	return invalidator.MeterParamOverridesUpdated
   134  }