Skip to content

Commit

Permalink
fix(txpool): set fix fee of 0.1 PAC for transactions (#1320)
Browse files Browse the repository at this point in the history
  • Loading branch information
b00f committed Jun 4, 2024
1 parent d1efe2f commit b589372
Show file tree
Hide file tree
Showing 34 changed files with 186 additions and 289 deletions.
3 changes: 2 additions & 1 deletion cmd/gtk/dialog_transaction_unbond.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ func broadcastTransactionUnbond(wlt *wallet.Wallet) {
You are going to sign and broadcast this transaction:
<tt>
Validator: %s
Fee: %s
Memo: %s
</tt>
<b>THIS ACTION IS NOT REVERSIBLE. Do you want to continue?</b>`, validator, trx.Memo())
<b>THIS ACTION IS NOT REVERSIBLE. Do you want to continue?</b>`, validator, trx.Fee(), trx.Memo())

signAndBroadcastTransaction(dlg, msg, wlt, trx)

Expand Down
2 changes: 1 addition & 1 deletion cmd/gtk/dialog_transaction_withdraw.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ You are going to sign and broadcast this transaction:
From: %s
To: %s
Amount: %s
Memo: %s
Fee: %s
Memo: %s
</tt>
<b>THIS ACTION IS NOT REVERSIBLE. Do you want to continue?</b>`,
sender, receiver, amt, trx.Fee(), trx.Memo())
Expand Down
5 changes: 0 additions & 5 deletions config/example_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,6 @@
# Default is `1000`.
max_size = 1000

# `min_value` indicates the minimum value of a transaction in PAC to enter into the pool.
# This prevents spamming transactions.
# Default is `0.1`.
min_value = 0.1

# `logger` contains configuration options for the logger.
[logger]
# `colorful` indicates whether log can be colorful or not.
Expand Down
50 changes: 4 additions & 46 deletions execution/execution.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
package execution

import (
"math"

"github.com/pactus-project/pactus/execution/executor"
"github.com/pactus-project/pactus/sandbox"
"github.com/pactus-project/pactus/types/amount"
"github.com/pactus-project/pactus/types/param"
"github.com/pactus-project/pactus/types/tx"
"github.com/pactus-project/pactus/types/tx/payload"
"github.com/pactus-project/pactus/util"
)

type Executor interface {
Expand Down Expand Up @@ -59,7 +54,7 @@ func (exe *Execution) Execute(trx *tx.Tx, sb sandbox.Sandbox) error {
return err
}

if err := exe.checkFee(trx, sb); err != nil {
if err := exe.checkFee(trx); err != nil {
return err
}

Expand Down Expand Up @@ -110,52 +105,15 @@ func (exe *Execution) checkLockTime(trx *tx.Tx, sb sandbox.Sandbox) error {
return nil
}

func (*Execution) checkFee(trx *tx.Tx, sb sandbox.Sandbox) error {
var fee amount.Amount
if trx.IsSubsidyTx() {
fee = 0
} else {
fee = CalculateFee(trx.Payload().Value(), trx.Payload().Type(), sb.Params())
}

if fee == 0 {
func (*Execution) checkFee(trx *tx.Tx) error {
if trx.IsFreeTx() {
if trx.Fee() != 0 {
return InvalidFeeError{
Fee: trx.Fee(),
Expected: fee,
}
}
} else {
// Check if the absolute difference between the calculated fee and the transaction fee
// is greater than 1 PAC, indicating an invalid fee.
if math.Abs(float64(fee-trx.Fee())) > 1 {
return InvalidFeeError{
Fee: trx.Fee(),
Expected: fee,
Expected: 0,
}
}
}

return nil
}

func CalculateFee(amt amount.Amount, payloadType payload.Type, params *param.Params) amount.Amount {
switch payloadType {
case payload.TypeUnbond,
payload.TypeSortition:

return 0

case payload.TypeTransfer,
payload.TypeBond,
payload.TypeWithdraw:
fee := amt.MulF64(params.FeeFraction)
fee = util.Max(fee, params.MinimumFee)
fee = util.Min(fee, params.MaximumFee)

return fee

default:
return 0
}
}
87 changes: 2 additions & 85 deletions execution/execution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import (

"github.com/pactus-project/pactus/crypto"
"github.com/pactus-project/pactus/sandbox"
"github.com/pactus-project/pactus/types/amount"
"github.com/pactus-project/pactus/types/tx"
"github.com/pactus-project/pactus/types/tx/payload"
"github.com/pactus-project/pactus/util/errors"
"github.com/pactus-project/pactus/util/testsuite"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -130,43 +128,17 @@ func TestExecution(t *testing.T) {
lockTime := sb.CurrentHeight()

t.Run("Invalid transaction, Should returns error", func(t *testing.T) {
trx := tx.NewTransferTx(lockTime, ts.RandAccAddress(), ts.RandAccAddress(), 1000, 1000, "invalid-tx")
trx := tx.NewTransferTx(lockTime, ts.RandAccAddress(), ts.RandAccAddress(), 1000, 0.1e9, "invalid-tx")
err := exe.Execute(trx, sb)
assert.Equal(t, errors.Code(err), errors.ErrInvalidAddress)
})

t.Run("Invalid fee, Should returns error", func(t *testing.T) {
trx := tx.NewTransferTx(lockTime, rndAccAddr, ts.RandAccAddress(), 1000, 1, "invalid fee")
ts.HelperSignTransaction(rndPrvKey, trx)

expectedErr := InvalidFeeError{Fee: 1, Expected: sb.TestParams.MinimumFee}
assert.ErrorIs(t, exe.Execute(trx, sb), expectedErr)
assert.ErrorIs(t, exe.checkFee(trx, sb), expectedErr)
})

t.Run("Invalid fee, Should returns error", func(t *testing.T) {
trx := tx.NewTransferTx(lockTime, rndAccAddr, ts.RandAccAddress(), 1000, 1002, "invalid fee")
ts.HelperSignTransaction(rndPrvKey, trx)

expectedErr := InvalidFeeError{Fee: 1002, Expected: sb.TestParams.MinimumFee}
assert.ErrorIs(t, exe.Execute(trx, sb), expectedErr)
assert.ErrorIs(t, exe.checkFee(trx, sb), expectedErr)
})

t.Run("Invalid fee (subsidy tx), Should returns error", func(t *testing.T) {
trx := tx.NewTransferTx(lockTime, crypto.TreasuryAddress, ts.RandAccAddress(), 1000, 1, "invalid fee")

expectedErr := InvalidFeeError{Fee: 1, Expected: 0}
assert.ErrorIs(t, exe.Execute(trx, sb), expectedErr)
assert.ErrorIs(t, exe.checkFee(trx, sb), expectedErr)
})

t.Run("Invalid fee (transfer tx), Should returns error", func(t *testing.T) {
trx := tx.NewTransferTx(lockTime, rndAccAddr, ts.RandAccAddress(), 1000, 0, "invalid fee")

expectedErr := InvalidFeeError{Fee: 0, Expected: sb.TestParams.MinimumFee}
assert.ErrorIs(t, exe.Execute(trx, sb), expectedErr)
assert.ErrorIs(t, exe.checkFee(trx, sb), expectedErr)
assert.ErrorIs(t, exe.checkFee(trx), expectedErr)
})

t.Run("Execution failed", func(t *testing.T) {
Expand Down Expand Up @@ -224,58 +196,3 @@ func TestChecker(t *testing.T) {
err = checker.Execute(trx, sb)
assert.NoError(t, err)
}

func TestFee(t *testing.T) {
ts := testsuite.NewTestSuite(t)

exe := NewChecker()
sb := sandbox.MockingSandbox(ts)

tests := []struct {
amount amount.Amount
fee amount.Amount
expectedFee amount.Amount
expectErr bool
}{
{1, 1, sb.TestParams.MinimumFee, true},
{1, 1002, sb.TestParams.MinimumFee, true},
{1, 998, sb.TestParams.MinimumFee, true},

{1, 1001, sb.TestParams.MinimumFee, false},
{1, 1000, sb.TestParams.MinimumFee, false},
{1, 999, sb.TestParams.MinimumFee, false},

{2 * 1e9, 100002, 200000, true},
{2 * 1e9, 99998, 200000, true},

{2 * 1e9, 200001, 200000, false},
{2 * 1e9, 200000, 200000, false},
{2 * 1e9, 199999, 200000, false},

{1 * 1e12, 1000002, sb.TestParams.MaximumFee, true},
{1 * 1e12, 999998, sb.TestParams.MaximumFee, true},

{1 * 1e12, 1000001, sb.TestParams.MaximumFee, false},
{1 * 1e12, 1000000, sb.TestParams.MaximumFee, false},
{1 * 1e12, 999999, sb.TestParams.MaximumFee, false},

{9_999_299_000, 999929, 999930, false}, // Block 66679
}

sender := ts.RandAccAddress()
receiver := ts.RandAccAddress()
for i, test := range tests {
trx := tx.NewTransferTx(sb.CurrentHeight()+1, sender, receiver, test.amount, test.fee,
"testing fee")
err := exe.checkFee(trx, sb)

if test.expectErr {
assert.Error(t, err, "test %v failed. expected error", i)
} else {
assert.NoError(t, err, "test %v failed. unexpected error", i)
}

expectedFee := CalculateFee(test.amount, payload.TypeTransfer, sb.Params())
assert.Equal(t, expectedFee, test.expectedFee, "test %v failed. invalid fee", i)
}
}
31 changes: 21 additions & 10 deletions execution/executor/bond_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ func TestExecuteBondTx(t *testing.T) {
senderBalance := senderAcc.Balance()
pub, _ := td.RandBLSKeyPair()
receiverAddr := pub.ValidatorAddress()
amt, fee := td.randomAmountAndFee(td.sandbox.TestParams.MinimumStake,
td.sandbox.TestParams.MaximumStake-10e9)
amt := td.RandAmountRange(
td.sandbox.TestParams.MinimumStake,
td.sandbox.TestParams.MaximumStake)
fee := td.RandFee()
lockTime := td.sandbox.CurrentHeight()

t.Run("Should fail, invalid sender", func(t *testing.T) {
Expand Down Expand Up @@ -115,8 +117,10 @@ func TestBondInsideCommittee(t *testing.T) {
exe1 := NewBondExecutor(true)
exe2 := NewBondExecutor(false)
senderAddr, _ := td.sandbox.TestStore.RandomTestAcc()
amt, fee := td.randomAmountAndFee(td.sandbox.TestParams.MinimumStake,
td.sandbox.TestParams.MaximumStake-10e9)
amt := td.RandAmountRange(
td.sandbox.TestParams.MinimumStake,
td.sandbox.TestParams.MaximumStake-10e9) // it has 10e9 stake
fee := td.RandFee()
lockTime := td.sandbox.CurrentHeight()

pub := td.sandbox.Committee().Proposer(0).PublicKey()
Expand All @@ -137,8 +141,10 @@ func TestBondJoiningCommittee(t *testing.T) {
exe2 := NewBondExecutor(false)
senderAddr, _ := td.sandbox.TestStore.RandomTestAcc()
pub, _ := td.RandBLSKeyPair()
amt, fee := td.randomAmountAndFee(td.sandbox.TestParams.MinimumStake,
td.sandbox.TestParams.MaximumStake-10e9)
amt := td.RandAmountRange(
td.sandbox.TestParams.MinimumStake,
td.sandbox.TestParams.MaximumStake-10e9) // it has 10e9 stake
fee := td.RandFee()
lockTime := td.sandbox.CurrentHeight()

val := td.sandbox.MakeNewValidator(pub)
Expand All @@ -160,7 +166,7 @@ func TestStakeExceeded(t *testing.T) {

exe := NewBondExecutor(true)
amt := td.sandbox.TestParams.MaximumStake + 1
fee := amt.MulF64(td.sandbox.Params().FeeFraction)
fee := td.RandFee()
senderAddr, senderAcc := td.sandbox.TestStore.RandomTestAcc()
senderAcc.AddToBalance(td.sandbox.TestParams.MaximumStake + 1)
td.sandbox.UpdateAccount(senderAddr, senderAcc)
Expand All @@ -181,8 +187,10 @@ func TestPowerDeltaBond(t *testing.T) {
senderAddr, _ := td.sandbox.TestStore.RandomTestAcc()
pub, _ := td.RandBLSKeyPair()
receiverAddr := pub.ValidatorAddress()
amt, fee := td.randomAmountAndFee(td.sandbox.TestParams.MinimumStake,
td.sandbox.TestParams.MaximumStake-10e9)
amt := td.RandAmountRange(
td.sandbox.TestParams.MinimumStake,
td.sandbox.TestParams.MaximumStake)
fee := td.RandFee()
lockTime := td.sandbox.CurrentHeight()
trx := tx.NewBondTx(lockTime, senderAddr,
receiverAddr, pub, amt, fee, "ok")
Expand All @@ -204,7 +212,7 @@ func TestSmallBond(t *testing.T) {
senderAddr, _ := td.sandbox.TestStore.RandomTestAcc()
receiverVal := td.sandbox.TestStore.RandomTestVal()
receiverAddr := receiverVal.Address()
fee := td.sandbox.Params().MaximumFee
fee := td.RandFee()
lockTime := td.sandbox.CurrentHeight()
trxBond := tx.NewBondTx(lockTime, senderAddr,
receiverAddr, nil, 1000e9-receiverVal.Stake()-2, fee, "ok")
Expand Down Expand Up @@ -243,4 +251,7 @@ func TestSmallBond(t *testing.T) {
err := exe.Execute(trx, td.sandbox)
assert.Error(t, err, "Zero bond amount on full stake should be rejected")
})

val, _ := td.sandbox.TestStore.Validator(receiverVal.Address())
assert.Equal(t, td.sandbox.Params().MaximumStake, val.Stake())
}
3 changes: 2 additions & 1 deletion execution/executor/sortition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ func TestExecuteSortitionTx(t *testing.T) {
pub, _ := td.RandBLSKeyPair()
newVal := td.sandbox.MakeNewValidator(pub)
accAddr, acc := td.sandbox.TestStore.RandomTestAcc()
amt, fee := td.randomAmountAndFee(0, acc.Balance())
amt := td.RandAmountRange(0, acc.Balance())
fee := td.RandFee()
newVal.AddToStake(amt + fee)
acc.SubtractFromBalance(amt + fee)
td.sandbox.UpdateAccount(accAddr, acc)
Expand Down
25 changes: 6 additions & 19 deletions execution/executor/transfer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,29 +46,15 @@ func (td *testData) checkTotalCoin(t *testing.T, fee amount.Amount) {
assert.Equal(t, total+fee, amount.Amount(21_000_000*1e9))
}

func (td *testData) randomAmountAndFee(min, max amount.Amount) (amount.Amount, amount.Amount) {
amt := amount.Amount(td.RandInt64NonZero(int64(max)))
for amt < min {
amt = amount.Amount(td.RandInt64NonZero(int64(max)))
}

fee := amt.MulF64(td.sandbox.Params().FeeFraction)
if amt+fee > max {
// To make sure amt+fee is less than max
return td.randomAmountAndFee(min, max)
}

return amt, fee
}

func TestExecuteTransferTx(t *testing.T) {
td := setup(t)
exe := NewTransferExecutor(true)

senderAddr, senderAcc := td.sandbox.TestStore.RandomTestAcc()
senderBalance := senderAcc.Balance()
receiverAddr := td.RandAccAddress()
amt, fee := td.randomAmountAndFee(0, senderBalance)
amt := td.RandAmountRange(0, senderBalance)
fee := td.RandFee()
lockTime := td.sandbox.CurrentHeight()

t.Run("Should fail, Sender has no account", func(t *testing.T) {
Expand Down Expand Up @@ -106,13 +92,14 @@ func TestTransferToSelf(t *testing.T) {
exe := NewTransferExecutor(true)

senderAddr, senderAcc := td.sandbox.TestStore.RandomTestAcc()
senderBalance := senderAcc.Balance()
amt, fee := td.randomAmountAndFee(0, senderBalance)
amt := td.RandAmountRange(0, senderAcc.Balance())
fee := td.RandFee()
lockTime := td.sandbox.CurrentHeight()

trx := tx.NewTransferTx(lockTime, senderAddr, senderAddr, amt, fee, "ok")
err := exe.Execute(trx, td.sandbox)
assert.NoError(t, err)

assert.Equal(t, td.sandbox.Account(senderAddr).Balance(), senderBalance-fee) // Fee should be deducted
expectedBalance := senderAcc.Balance() - fee // Fee should be deducted
assert.Equal(t, expectedBalance, td.sandbox.Account(senderAddr).Balance())
}
4 changes: 3 additions & 1 deletion execution/executor/unbond_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ func TestExecuteUnbondTx(t *testing.T) {

bonderAddr, bonderAcc := td.sandbox.TestStore.RandomTestAcc()
bonderBalance := bonderAcc.Balance()
stake, _ := td.randomAmountAndFee(td.sandbox.TestParams.MinimumStake, bonderBalance)
stake := td.RandAmountRange(
td.sandbox.TestParams.MinimumStake,
bonderBalance)
bonderAcc.SubtractFromBalance(stake)
td.sandbox.UpdateAccount(bonderAddr, bonderAcc)

Expand Down
3 changes: 2 additions & 1 deletion execution/executor/withdraw_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ func TestExecuteWithdrawTx(t *testing.T) {
pub, _ := td.RandBLSKeyPair()
val := td.sandbox.MakeNewValidator(pub)
accAddr, acc := td.sandbox.TestStore.RandomTestAcc()
amt, fee := td.randomAmountAndFee(0, acc.Balance())
amt := td.RandAmountRange(0, acc.Balance())
fee := td.RandFee()
val.AddToStake(amt + fee)
acc.SubtractFromBalance(amt + fee)
td.sandbox.UpdateAccount(accAddr, acc)
Expand Down
2 changes: 1 addition & 1 deletion genesis/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func TestMarshaling(t *testing.T) {
acc, prv := ts.GenerateTestAccount(0)
acc.AddToBalance(100000)
val, _ := ts.GenerateTestValidator(0)
gen1 := genesis.MakeGenesis(util.Now(),
gen1 := genesis.MakeGenesis(util.RoundNow(10),
map[crypto.Address]*account.Account{prv: acc},
[]*validator.Validator{val}, param.DefaultParams())
gen2 := new(genesis.Genesis)
Expand Down
Loading

0 comments on commit b589372

Please sign in to comment.