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

     1  package environment
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/onflow/cadence/runtime/common"
     7  
     8  	"github.com/koko1123/flow-go-1/fvm/errors"
     9  	"github.com/koko1123/flow-go-1/fvm/state"
    10  	"github.com/koko1123/flow-go-1/model/flow"
    11  	"github.com/koko1123/flow-go-1/module/trace"
    12  )
    13  
    14  // AccountFreezer disables accounts.
    15  //
    16  // Note that scripts cannot freeze accounts, but must expose the API in
    17  // compliance with the environment interface.
    18  type AccountFreezer interface {
    19  	// Note that the script variant will return OperationNotSupportedError.
    20  	SetAccountFrozen(address common.Address, frozen bool) error
    21  
    22  	FrozenAccounts() []common.Address
    23  
    24  	Reset()
    25  }
    26  
    27  type ParseRestrictedAccountFreezer struct {
    28  	txnState *state.TransactionState
    29  	impl     AccountFreezer
    30  }
    31  
    32  func NewParseRestrictedAccountFreezer(
    33  	txnState *state.TransactionState,
    34  	impl AccountFreezer,
    35  ) AccountFreezer {
    36  	return ParseRestrictedAccountFreezer{
    37  		txnState: txnState,
    38  		impl:     impl,
    39  	}
    40  }
    41  
    42  func (freezer ParseRestrictedAccountFreezer) SetAccountFrozen(
    43  	address common.Address,
    44  	frozen bool,
    45  ) error {
    46  	return parseRestrict2Arg(
    47  		freezer.txnState,
    48  		trace.FVMEnvSetAccountFrozen,
    49  		freezer.impl.SetAccountFrozen,
    50  		address,
    51  		frozen)
    52  }
    53  
    54  func (freezer ParseRestrictedAccountFreezer) FrozenAccounts() []common.Address {
    55  	return freezer.impl.FrozenAccounts()
    56  }
    57  
    58  func (freezer ParseRestrictedAccountFreezer) Reset() {
    59  	freezer.impl.Reset()
    60  }
    61  
    62  type NoAccountFreezer struct{}
    63  
    64  func (NoAccountFreezer) FrozenAccounts() []common.Address {
    65  	return nil
    66  }
    67  
    68  func (NoAccountFreezer) SetAccountFrozen(_ common.Address, _ bool) error {
    69  	return errors.NewOperationNotSupportedError("SetAccountFrozen")
    70  }
    71  
    72  func (NoAccountFreezer) Reset() {
    73  }
    74  
    75  type accountFreezer struct {
    76  	serviceAddress flow.Address
    77  
    78  	accounts        Accounts
    79  	transactionInfo TransactionInfo
    80  
    81  	frozenAccounts []common.Address
    82  }
    83  
    84  func NewAccountFreezer(
    85  	serviceAddress flow.Address,
    86  	accounts Accounts,
    87  	transactionInfo TransactionInfo,
    88  ) *accountFreezer {
    89  	freezer := &accountFreezer{
    90  		serviceAddress:  serviceAddress,
    91  		accounts:        accounts,
    92  		transactionInfo: transactionInfo,
    93  	}
    94  	freezer.Reset()
    95  	return freezer
    96  }
    97  
    98  func (freezer *accountFreezer) Reset() {
    99  	freezer.frozenAccounts = nil
   100  }
   101  
   102  func (freezer *accountFreezer) FrozenAccounts() []common.Address {
   103  	return freezer.frozenAccounts
   104  }
   105  
   106  func (freezer *accountFreezer) SetAccountFrozen(
   107  	address common.Address,
   108  	frozen bool,
   109  ) error {
   110  	flowAddress := flow.Address(address)
   111  
   112  	if flowAddress == freezer.serviceAddress {
   113  		return fmt.Errorf(
   114  			"setting account frozen failed: %w",
   115  			errors.NewValueErrorf(
   116  				flowAddress.String(),
   117  				"cannot freeze service account"))
   118  	}
   119  
   120  	if !freezer.transactionInfo.IsServiceAccountAuthorizer() {
   121  		return fmt.Errorf(
   122  			"setting account frozen failed: %w",
   123  			errors.NewOperationAuthorizationErrorf(
   124  				"SetAccountFrozen",
   125  				"accounts can be frozen only by transactions authorized by "+
   126  					"the service account"))
   127  	}
   128  
   129  	err := freezer.accounts.SetAccountFrozen(flowAddress, frozen)
   130  	if err != nil {
   131  		return fmt.Errorf("setting account frozen failed: %w", err)
   132  	}
   133  
   134  	if frozen {
   135  		freezer.frozenAccounts = append(freezer.frozenAccounts, address)
   136  	}
   137  
   138  	return nil
   139  }