Skip to content

Commit

Permalink
refactor: Transaction fee calculation reworked to accomodate the diff…
Browse files Browse the repository at this point in the history
…erent gas calculation equation for Oracle*Txs
  • Loading branch information
randomshinichi committed Nov 11, 2019
1 parent a7cfbc5 commit 1875246
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 75 deletions.
2 changes: 2 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ const (
// blocks) should be interpreted as an absolute block height, after which
// the TTL expires.
OracleTTLTypeAbsolute = 1
// KeyBlockInterval is the average time between key blocks in minutes
KeyBlockInterval = 3
)

// NodeConfig configuration for the node
Expand Down
46 changes: 13 additions & 33 deletions transactions/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ type TransactionFeeCalculable interface {
Transaction
SetFee(*big.Int)
GetFee() *big.Int
GetGasLimit() *big.Int
CalcGas() (g *big.Int, err error)
}

// calculateSignature calculates the signature of the SignedTx.Tx. Although it does not use
Expand Down Expand Up @@ -270,54 +270,34 @@ func calcRlpLen(o interface{}) (size int64, err error) {
return
}

func baseGasForTxType(tx Transaction) (baseGas *big.Int) {
baseGas = big.NewInt(0)
switch tx.(type) {
case *ContractCreateTx, *GAAttachTx, *GAMetaTx:
return baseGas.Mul(big.NewInt(5), config.Client.BaseGas)
case *ContractCallTx:
return baseGas.Mul(big.NewInt(30), config.Client.BaseGas)
default:
return config.Client.BaseGas
}
}

func calcFee(tx TransactionFeeCalculable) (fee *big.Int, err error) {
gas := big.NewInt(0)
// baseGas + len(tx)*GasPerByte + contractExecutionGas
baseGas := baseGasForTxType(tx)
gas.Add(gas, baseGas)

s, err := calcRlpLen(tx)
// normalGasComponent implements the equation byte_size(Transaction) *
// GasPerByte + gas for contract execution if applicable.
func normalGasComponent(tx Transaction, gasLimit *big.Int) (gas *big.Int, err error) {
l, err := calcRlpLen(tx)
if err != nil {
return
}
txLenGasPerByte := big.NewInt(s)
txLenGasPerByte.Mul(txLenGasPerByte, config.Client.GasPerByte)
gas.Add(gas, txLenGasPerByte)

gas.Add(gas, tx.GetGasLimit())

fee = new(big.Int)
fee = gas.Mul(gas, config.Client.GasPrice)

tx.SetFee(fee)
gas = big.NewInt(l)
gas.Mul(gas, config.Client.GasPerByte)
gas.Add(gas, gasLimit)
return
}

// CalculateFee calculates the required transaction fee, and increases the fee
// further in case the newer fee ends up increasing the transaction size.
func CalculateFee(tx TransactionFeeCalculable) (err error) {
var fee, newFee *big.Int
var fee, gas, newFee *big.Int
for {
fee = tx.GetFee()
newFee, err = calcFee(tx)
gas, err = tx.CalcGas()
if err != nil {
break
}

newFee = gas.Mul(gas, config.Client.GasPrice)
if fee.Cmp(newFee) == 0 {
break
} else {
tx.SetFee(newFee)
}
}
return
Expand Down
70 changes: 55 additions & 15 deletions transactions/tx_aens.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,17 @@ func (tx *NamePreclaimTx) GetFee() *big.Int {
return tx.Fee
}

// GetGasLimit implements TransactionFeeCalculable
func (tx *NamePreclaimTx) GetGasLimit() *big.Int {
return big.NewInt(0)
// CalcGas implements TransactionFeeCalculable
func (tx *NamePreclaimTx) CalcGas() (g *big.Int, err error) {
baseGas := new(big.Int)
baseGas.Add(baseGas, config.Client.BaseGas)
gasComponent, err := normalGasComponent(tx, big.NewInt(0))
if err != nil {
return
}
g = new(big.Int)
g = baseGas.Add(baseGas, gasComponent)
return
}

// NewNamePreclaimTx is a constructor for a NamePreclaimTx struct
Expand Down Expand Up @@ -336,9 +344,17 @@ func (tx *NameClaimTx) GetFee() *big.Int {
return tx.Fee
}

// GetGasLimit implements TransactionFeeCalculable
func (tx *NameClaimTx) GetGasLimit() *big.Int {
return big.NewInt(0)
// CalcGas implements TransactionFeeCalculable
func (tx *NameClaimTx) CalcGas() (g *big.Int, err error) {
baseGas := new(big.Int)
baseGas.Add(baseGas, config.Client.BaseGas)
gasComponent, err := normalGasComponent(tx, big.NewInt(0))
if err != nil {
return
}
g = new(big.Int)
g = baseGas.Add(baseGas, gasComponent)
return
}

// NewNameClaimTx is a constructor for a NameClaimTx struct
Expand Down Expand Up @@ -571,9 +587,17 @@ func (tx *NameUpdateTx) GetFee() *big.Int {
return tx.Fee
}

// GetGasLimit implements TransactionFeeCalculable
func (tx *NameUpdateTx) GetGasLimit() *big.Int {
return big.NewInt(0)
// CalcGas implements TransactionFeeCalculable
func (tx *NameUpdateTx) CalcGas() (g *big.Int, err error) {
baseGas := new(big.Int)
baseGas.Add(baseGas, config.Client.BaseGas)
gasComponent, err := normalGasComponent(tx, big.NewInt(0))
if err != nil {
return
}
g = new(big.Int)
g = baseGas.Add(baseGas, gasComponent)
return
}

// NewNameUpdateTx is a constructor for a NameUpdateTx struct
Expand Down Expand Up @@ -712,9 +736,17 @@ func (tx *NameRevokeTx) GetFee() *big.Int {
return tx.Fee
}

// GetGasLimit implements TransactionFeeCalculable
func (tx *NameRevokeTx) GetGasLimit() *big.Int {
return big.NewInt(0)
// CalcGas implements TransactionFeeCalculable
func (tx *NameRevokeTx) CalcGas() (g *big.Int, err error) {
baseGas := new(big.Int)
baseGas.Add(baseGas, config.Client.BaseGas)
gasComponent, err := normalGasComponent(tx, big.NewInt(0))
if err != nil {
return
}
g = new(big.Int)
g = baseGas.Add(baseGas, gasComponent)
return
}

// NewNameRevokeTx is a constructor for a NameRevokeTx struct
Expand Down Expand Up @@ -859,9 +891,17 @@ func (tx *NameTransferTx) GetFee() *big.Int {
return tx.Fee
}

// GetGasLimit implements TransactionFeeCalculable
func (tx *NameTransferTx) GetGasLimit() *big.Int {
return big.NewInt(0)
// CalcGas implements TransactionFeeCalculable
func (tx *NameTransferTx) CalcGas() (g *big.Int, err error) {
baseGas := new(big.Int)
baseGas.Add(baseGas, config.Client.BaseGas)
gasComponent, err := normalGasComponent(tx, big.NewInt(0))
if err != nil {
return
}
g = new(big.Int)
g = baseGas.Add(baseGas, gasComponent)
return
}

// NewNameTransferTx is a constructor for a NameTransferTx struct
Expand Down
28 changes: 22 additions & 6 deletions transactions/tx_contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,17 @@ func (tx *ContractCreateTx) GetFee() *big.Int {
return tx.Fee
}

// GetGasLimit implements TransactionFeeCalculable
func (tx *ContractCreateTx) GetGasLimit() *big.Int {
return tx.GasLimit
// CalcGas implements TransactionFeeCalculable
func (tx *ContractCreateTx) CalcGas() (g *big.Int, err error) {
baseGas := new(big.Int)
baseGas.Mul(config.Client.BaseGas, big.NewInt(5))
gasComponent, err := normalGasComponent(tx, tx.GasLimit)
if err != nil {
return
}
g = new(big.Int)
g = baseGas.Add(baseGas, gasComponent)
return
}

// NewContractCreateTx is a constructor for a ContractCreateTx struct
Expand Down Expand Up @@ -355,9 +363,17 @@ func (tx *ContractCallTx) GetFee() *big.Int {
return tx.Fee
}

// GetGasLimit implements TransactionFeeCalculable
func (tx *ContractCallTx) GetGasLimit() *big.Int {
return tx.GasLimit
// CalcGas implements TransactionFeeCalculable
func (tx *ContractCallTx) CalcGas() (g *big.Int, err error) {
baseGas := new(big.Int)
baseGas.Mul(config.Client.BaseGas, big.NewInt(30))
gasComponent, err := normalGasComponent(tx, tx.GasLimit)
if err != nil {
return
}
g = new(big.Int)
g = baseGas.Add(baseGas, gasComponent)
return
}

// NewContractCallTx is a constructor for a ContractCallTx struct
Expand Down
29 changes: 23 additions & 6 deletions transactions/tx_ga.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,17 @@ func (tx *GAAttachTx) GetFee() *big.Int {
return tx.Fee
}

// GetGasLimit implements TransactionFeeCalculable
func (tx *GAAttachTx) GetGasLimit() *big.Int {
return tx.GasLimit
// CalcGas implements TransactionFeeCalculable
func (tx *GAAttachTx) CalcGas() (g *big.Int, err error) {
baseGas := new(big.Int)
baseGas.Mul(config.Client.BaseGas, big.NewInt(5))
gasComponent, err := normalGasComponent(tx, tx.GasLimit)
if err != nil {
return
}
g = new(big.Int)
g = baseGas.Add(baseGas, gasComponent)
return
}

// NewGAAttachTx creates a GAAttachTx
Expand Down Expand Up @@ -273,9 +281,18 @@ func (tx *GAMetaTx) GetFee() *big.Int {
return tx.Fee
}

// GetGasLimit implements TransactionFeeCalculable
func (tx *GAMetaTx) GetGasLimit() *big.Int {
return tx.GasLimit
// CalcGas implements TransactionFeeCalculable
// TODO Recursive tx gas calculation not implemented
func (tx *GAMetaTx) CalcGas() (g *big.Int, err error) {
baseGas := new(big.Int)
baseGas.Mul(config.Client.BaseGas, big.NewInt(5))
gasComponent, err := normalGasComponent(tx, tx.GasLimit)
if err != nil {
return
}
g = new(big.Int)
g = baseGas.Add(baseGas, gasComponent)
return
}

// NewGAMetaTx creates a GAMetaTx
Expand Down
78 changes: 66 additions & 12 deletions transactions/tx_oracles.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package transactions

import (
"io"
"math"
"math/big"

"github.com/aeternity/aepp-sdk-go/v6/binary"
Expand All @@ -11,6 +12,11 @@ import (
rlp "github.com/randomshinichi/rlpae"
)

func timeGas(ttl uint64) (timeGasComponent uint64) {
timeGasComponent = uint64(math.Ceil((32000 * float64(ttl)) / math.Floor(60*24*365/config.KeyBlockInterval)))
return
}

// OracleRegisterTx represents a transaction that registers an oracle on the blockchain's state
type OracleRegisterTx struct {
AccountID string
Expand Down Expand Up @@ -154,9 +160,21 @@ func (tx *OracleRegisterTx) GetFee() *big.Int {
return tx.Fee
}

// GetGasLimit implements TransactionFeeCalculable
func (tx *OracleRegisterTx) GetGasLimit() *big.Int {
return big.NewInt(0)
// CalcGas implements TransactionFeeCalculable
func (tx *OracleRegisterTx) CalcGas() (g *big.Int, err error) {
baseGas := new(big.Int)
baseGas.Add(baseGas, config.Client.BaseGas)
gasComponent, err := normalGasComponent(tx, big.NewInt(0))
if err != nil {
return
}
timeGasComponent := new(big.Int)
timeGasComponent.SetUint64(timeGas(tx.OracleTTLValue))

g = new(big.Int)
g.Add(baseGas, gasComponent)
g.Add(g, timeGasComponent)
return
}

// NewOracleRegisterTx is a constructor for a OracleRegisterTx struct
Expand Down Expand Up @@ -277,9 +295,21 @@ func (tx *OracleExtendTx) GetFee() *big.Int {
return tx.Fee
}

// GetGasLimit implements TransactionFeeCalculable
func (tx *OracleExtendTx) GetGasLimit() *big.Int {
return big.NewInt(0)
// CalcGas implements TransactionFeeCalculable
func (tx *OracleExtendTx) CalcGas() (g *big.Int, err error) {
baseGas := new(big.Int)
baseGas.Add(baseGas, config.Client.BaseGas)
gasComponent, err := normalGasComponent(tx, big.NewInt(0))
if err != nil {
return
}
timeGasComponent := new(big.Int)
timeGasComponent.SetUint64(timeGas(tx.OracleTTLValue))

g = new(big.Int)
g.Add(baseGas, gasComponent)
g.Add(g, timeGasComponent)
return
}

// NewOracleExtendTx is a constructor for a OracleExtendTx struct
Expand Down Expand Up @@ -436,9 +466,21 @@ func (tx *OracleQueryTx) GetFee() *big.Int {
return tx.Fee
}

// GetGasLimit implements TransactionFeeCalculable
func (tx *OracleQueryTx) GetGasLimit() *big.Int {
return big.NewInt(0)
// CalcGas implements TransactionFeeCalculable
func (tx *OracleQueryTx) CalcGas() (g *big.Int, err error) {
baseGas := new(big.Int)
baseGas.Add(baseGas, config.Client.BaseGas)
gasComponent, err := normalGasComponent(tx, big.NewInt(0))
if err != nil {
return
}
timeGasComponent := new(big.Int)
timeGasComponent.SetUint64(timeGas(tx.QueryTTLValue))

g = new(big.Int)
g.Add(baseGas, gasComponent)
g.Add(g, timeGasComponent)
return
}

// NewOracleQueryTx is a constructor for a OracleQueryTx struct
Expand Down Expand Up @@ -576,9 +618,21 @@ func (tx *OracleRespondTx) GetFee() *big.Int {
return tx.Fee
}

// GetGasLimit implements TransactionFeeCalculable
func (tx *OracleRespondTx) GetGasLimit() *big.Int {
return big.NewInt(0)
// CalcGas implements TransactionFeeCalculable
func (tx *OracleRespondTx) CalcGas() (g *big.Int, err error) {
baseGas := new(big.Int)
baseGas.Add(baseGas, config.Client.BaseGas)
gasComponent, err := normalGasComponent(tx, big.NewInt(0))
if err != nil {
return
}
timeGasComponent := new(big.Int)
timeGasComponent.SetUint64(timeGas(tx.ResponseTTLValue))

g = new(big.Int)
g.Add(baseGas, gasComponent)
g.Add(g, timeGasComponent)
return
}

// NewOracleRespondTx is a constructor for a OracleRespondTx struct
Expand Down
Loading

0 comments on commit 1875246

Please sign in to comment.