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 }