github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/module/state_synchronization/indexer/util.go (about)

     1  package indexer
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/onflow/cadence"
     7  	"github.com/onflow/cadence/encoding/ccf"
     8  	"github.com/onflow/cadence/runtime/common"
     9  	"github.com/onflow/cadence/runtime/stdlib"
    10  
    11  	"github.com/onflow/flow-go/fvm/storage/derived"
    12  	"github.com/onflow/flow-go/fvm/storage/snapshot"
    13  	"github.com/onflow/flow-go/model/flow"
    14  )
    15  
    16  var (
    17  	accountContractUpdated = flow.EventType(stdlib.AccountContractUpdatedEventType.ID())
    18  )
    19  
    20  // hasAuthorizedTransaction checks if the provided account was an authorizer in any of the transactions
    21  // within the provided collections.
    22  func hasAuthorizedTransaction(collections []*flow.Collection, address flow.Address) bool {
    23  	for _, collection := range collections {
    24  		for _, tx := range collection.Transactions {
    25  			for _, authorizer := range tx.Authorizers {
    26  				if authorizer == address {
    27  					return true
    28  				}
    29  			}
    30  		}
    31  	}
    32  
    33  	return false
    34  }
    35  
    36  // findContractUpdates returns a map of common.AddressLocation for all contracts updated within the
    37  // provided events.
    38  // No errors are expected during normal operation and indicate an invalid protocol event was encountered
    39  func findContractUpdates(events []flow.Event) (map[common.Location]struct{}, error) {
    40  	invalidatedPrograms := make(map[common.Location]struct{})
    41  	for _, event := range events {
    42  		if event.Type == accountContractUpdated {
    43  			location, err := parseAccountContractUpdated(&event)
    44  			if err != nil {
    45  				return nil, fmt.Errorf("could not parse account contract updated event: %w", err)
    46  			}
    47  			invalidatedPrograms[location] = struct{}{}
    48  		}
    49  	}
    50  	return invalidatedPrograms, nil
    51  }
    52  
    53  // parseAccountContractUpdated parses an account contract updated event and returns the address location.
    54  // No errors are expected during normal operation and indicate an invalid protocol event was encountered
    55  func parseAccountContractUpdated(event *flow.Event) (common.AddressLocation, error) {
    56  	payload, err := ccf.Decode(nil, event.Payload)
    57  	if err != nil {
    58  		return common.AddressLocation{}, fmt.Errorf("could not unmarshal event payload: %w", err)
    59  	}
    60  
    61  	cdcEvent, ok := payload.(cadence.Event)
    62  	if !ok {
    63  		return common.AddressLocation{}, fmt.Errorf("invalid event payload type: %T", payload)
    64  	}
    65  
    66  	fields := cadence.FieldsMappedByName(cdcEvent)
    67  
    68  	addressField := fields[stdlib.AccountEventAddressParameter.Identifier]
    69  	address, ok := addressField.(cadence.Address)
    70  	if !ok {
    71  		return common.AddressLocation{}, fmt.Errorf("invalid Cadence type for address field: %T", addressField)
    72  	}
    73  
    74  	contractNameField := fields[stdlib.AccountEventContractParameter.Identifier]
    75  	contractName, ok := contractNameField.(cadence.String)
    76  	if !ok {
    77  		return common.AddressLocation{}, fmt.Errorf(
    78  			"invalid Cadence type for contract name field: %T",
    79  			contractNameField,
    80  		)
    81  	}
    82  
    83  	return common.NewAddressLocation(
    84  		nil,
    85  		common.Address(address),
    86  		string(contractName),
    87  	), nil
    88  }
    89  
    90  var _ derived.TransactionInvalidator = (*accessInvalidator)(nil)
    91  
    92  // accessInvalidator is a derived.TransactionInvalidator that invalidates programs and meter param overrides.
    93  type accessInvalidator struct {
    94  	programs            *programInvalidator
    95  	meterParamOverrides *meterParamOverridesInvalidator
    96  }
    97  
    98  func (inv *accessInvalidator) ProgramInvalidator() derived.ProgramInvalidator {
    99  	return inv.programs
   100  }
   101  
   102  func (inv *accessInvalidator) MeterParamOverridesInvalidator() derived.MeterParamOverridesInvalidator {
   103  	return inv.meterParamOverrides
   104  }
   105  
   106  var _ derived.ProgramInvalidator = (*programInvalidator)(nil)
   107  
   108  // programInvalidator is a derived.ProgramInvalidator that invalidates all programs or a specific set of programs.
   109  // this is used to invalidate all programs who's code was updated in a specific block.
   110  type programInvalidator struct {
   111  	invalidateAll bool
   112  	invalidated   map[common.Location]struct{}
   113  }
   114  
   115  func (inv *programInvalidator) ShouldInvalidateEntries() bool {
   116  	return inv.invalidateAll
   117  }
   118  
   119  func (inv *programInvalidator) ShouldInvalidateEntry(location common.AddressLocation, _ *derived.Program, _ *snapshot.ExecutionSnapshot) bool {
   120  	_, ok := inv.invalidated[location]
   121  	return inv.invalidateAll || ok
   122  }
   123  
   124  var _ derived.MeterParamOverridesInvalidator = (*meterParamOverridesInvalidator)(nil)
   125  
   126  // meterParamOverridesInvalidator is a derived.MeterParamOverridesInvalidator that invalidates meter param overrides.
   127  type meterParamOverridesInvalidator struct {
   128  	invalidateAll bool
   129  }
   130  
   131  func (inv *meterParamOverridesInvalidator) ShouldInvalidateEntries() bool {
   132  	return inv.invalidateAll
   133  }
   134  
   135  func (inv *meterParamOverridesInvalidator) ShouldInvalidateEntry(_ struct{}, _ derived.MeterParamOverrides, _ *snapshot.ExecutionSnapshot) bool {
   136  	return inv.invalidateAll
   137  }