-
Notifications
You must be signed in to change notification settings - Fork 199
/
transactionCostEstimator.go
105 lines (89 loc) · 2.94 KB
/
transactionCostEstimator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package transaction
import (
"github.com/ElrondNetwork/elrond-go/core"
"github.com/ElrondNetwork/elrond-go/core/check"
"github.com/ElrondNetwork/elrond-go/data/transaction"
"github.com/ElrondNetwork/elrond-go/node/external"
"github.com/ElrondNetwork/elrond-go/process"
)
type transactionCostEstimator struct {
txTypeHandler process.TxTypeHandler
feeHandler process.FeeHandler
query external.SCQueryService
storePerByteCost uint64
compilePerByteCost uint64
}
// NewTransactionCostEstimator will create a new transaction cost estimator
func NewTransactionCostEstimator(
txTypeHandler process.TxTypeHandler,
feeHandler process.FeeHandler,
query external.SCQueryService,
gasSchedule map[string]map[string]uint64,
) (*transactionCostEstimator, error) {
if check.IfNil(txTypeHandler) {
return nil, process.ErrNilTxTypeHandler
}
if check.IfNil(feeHandler) {
return nil, process.ErrNilEconomicsFeeHandler
}
if check.IfNil(query) {
return nil, external.ErrNilSCQueryService
}
compileCost, storeCost := getOperationCost(gasSchedule)
return &transactionCostEstimator{
txTypeHandler: txTypeHandler,
feeHandler: feeHandler,
query: query,
storePerByteCost: compileCost,
compilePerByteCost: storeCost,
}, nil
}
func getOperationCost(gasSchedule map[string]map[string]uint64) (uint64, uint64) {
baseOpMap, ok := gasSchedule[core.BaseOperationCost]
if !ok {
return 0, 0
}
storeCost, ok := baseOpMap["StorePerByte"]
if !ok {
return 0, 0
}
compilerCost, ok := baseOpMap["CompilePerByte"]
if !ok {
return 0, 0
}
return storeCost, compilerCost
}
// ComputeTransactionGasLimit will calculate how many gas units a transaction will consume
func (tce *transactionCostEstimator) ComputeTransactionGasLimit(tx *transaction.Transaction) (uint64, error) {
txType := tce.txTypeHandler.ComputeTransactionType(tx)
tx.GasPrice = 1
switch txType {
case process.MoveBalance:
return tce.feeHandler.ComputeGasLimit(tx), nil
case process.SCDeployment:
return tce.computeScDeployGasLimit(tx)
case process.SCInvoking:
return tce.computeScCallGasLimit(tx)
case process.BuiltInFunctionCall:
return tce.computeScCallGasLimit(tx)
default:
return 0, process.ErrWrongTransaction
}
}
func (tce *transactionCostEstimator) computeScDeployGasLimit(tx *transaction.Transaction) (uint64, error) {
scDeployCost := uint64(len(tx.Data)) * (tce.storePerByteCost + tce.compilePerByteCost)
baseCost := tce.feeHandler.ComputeGasLimit(tx)
return baseCost + scDeployCost, nil
}
func (tce *transactionCostEstimator) computeScCallGasLimit(tx *transaction.Transaction) (uint64, error) {
scCallGasLimit, err := tce.query.ComputeScCallGasLimit(tx)
if err != nil {
return 0, err
}
baseCost := tce.feeHandler.ComputeGasLimit(tx)
return baseCost + scCallGasLimit, nil
}
// IsInterfaceNil returns true if there is no value under the interface
func (tce *transactionCostEstimator) IsInterfaceNil() bool {
return tce == nil
}