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

     1  package fvm
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/koko1123/flow-go-1/fvm/state"
     7  
     8  	"github.com/onflow/cadence"
     9  
    10  	"github.com/koko1123/flow-go-1/fvm/environment"
    11  	"github.com/koko1123/flow-go-1/fvm/errors"
    12  )
    13  
    14  type TransactionPayerBalanceChecker struct{}
    15  
    16  func (_ TransactionPayerBalanceChecker) CheckPayerBalanceAndReturnMaxFees(
    17  	proc *TransactionProcedure,
    18  	txnState *state.TransactionState,
    19  	env environment.Environment,
    20  ) (uint64, error) {
    21  	if !env.TransactionFeesEnabled() {
    22  		// if the transaction fees are not enabled,
    23  		// the payer can pay for the transaction,
    24  		// and the max transaction fees are 0.
    25  		// This is also the condition that gets hit during bootstrapping.
    26  		return 0, nil
    27  	}
    28  
    29  	var resultValue cadence.Value
    30  	var err error
    31  	txnState.RunWithAllLimitsDisabled(func() {
    32  		// Don't meter the payer balance check.
    33  		// It has a static cost, and its cost should be part of the inclusion fees, not part of execution fees.
    34  		resultValue, err = env.CheckPayerBalanceAndGetMaxTxFees(
    35  			proc.Transaction.Payer,
    36  			proc.Transaction.InclusionEffort(),
    37  			uint64(txnState.TotalComputationLimit()),
    38  		)
    39  	})
    40  	if err != nil {
    41  		return 0, errors.NewPayerBalanceCheckFailure(proc.Transaction.Payer, err)
    42  	}
    43  
    44  	// parse expected result from the Cadence runtime
    45  	// https://github.com/onflow/flow-core-contracts/blob/7c70c6a1d33c2879b60c78e363fa68fc6fce13b9/contracts/FlowFees.cdc#L75
    46  	result, ok := resultValue.(cadence.Struct)
    47  	if ok && len(result.Fields) == 3 {
    48  		payerCanPay, okBool := result.Fields[0].(cadence.Bool)
    49  		requiredBalance, okBalance := result.Fields[1].(cadence.UFix64)
    50  		maxFees, okFees := result.Fields[2].(cadence.UFix64)
    51  
    52  		if okBool && okBalance && okFees {
    53  			if !payerCanPay {
    54  				return 0, errors.NewInsufficientPayerBalanceError(proc.Transaction.Payer, requiredBalance)
    55  			}
    56  			return uint64(maxFees), nil
    57  		}
    58  	}
    59  
    60  	return 0, errors.NewPayerBalanceCheckFailure(proc.Transaction.Payer, fmt.Errorf("invalid result type"))
    61  }