diff --git a/api/service/transactionApiService_test.go b/api/service/transactionApiService_test.go index 00598cf86..53e6f65ae 100644 --- a/api/service/transactionApiService_test.go +++ b/api/service/transactionApiService_test.go @@ -5,17 +5,17 @@ package service import ( "database/sql" "errors" - "github.com/zoobc/zoobc-core/common/crypto" - "github.com/zoobc/zoobc-core/common/feedbacksystem" - "github.com/zoobc/zoobc-core/common/storage" "reflect" "testing" "github.com/DATA-DOG/go-sqlmock" "github.com/sirupsen/logrus" "github.com/zoobc/zoobc-core/common/chaintype" + "github.com/zoobc/zoobc-core/common/crypto" + "github.com/zoobc/zoobc-core/common/feedbacksystem" "github.com/zoobc/zoobc-core/common/model" "github.com/zoobc/zoobc-core/common/query" + "github.com/zoobc/zoobc-core/common/storage" "github.com/zoobc/zoobc-core/common/transaction" "github.com/zoobc/zoobc-core/core/service" "github.com/zoobc/zoobc-core/observer" @@ -95,15 +95,15 @@ func (*mockTypeSwitcherSuccess) GetTransactionType(tx *model.Transaction) (trans return &mockTxTypeSuccess{}, nil } -func (*mockTxTypeValidateFail) Validate(bool) error { +func (*mockTxTypeValidateFail) Validate(bool, bool) error { return errors.New("mockError:validateFail") } -func (*mockTxTypeApplyUnconfirmedFail) Validate(bool) error { +func (*mockTxTypeApplyUnconfirmedFail) Validate(bool, bool) error { return nil } -func (*mockTxTypeSuccess) Validate(bool) error { +func (*mockTxTypeSuccess) Validate(bool, bool) error { return nil } diff --git a/common/transaction/accountBalanceHelper.go b/common/transaction/accountBalanceHelper.go index 44fd43bd9..3b6f53ae9 100644 --- a/common/transaction/accountBalanceHelper.go +++ b/common/transaction/accountBalanceHelper.go @@ -18,6 +18,7 @@ type ( blockTimestamp uint64) error GetBalanceByAccountAddress(accountBalance *model.AccountBalance, address []byte, dbTx bool) error HasEnoughSpendableBalance(dbTX bool, address []byte, compareBalance int64) (enough bool, err error) + HasEnoughBalance(dbTX bool, address []byte, compareBalance int64) (enough bool, err error) } // AccountBalanceHelper fields for AccountBalanceHelperInterface for transaction helper AccountBalanceHelper struct { @@ -141,3 +142,19 @@ func (abh *AccountBalanceHelper) HasEnoughSpendableBalance(dbTX bool, address [] abh.accountBalance = accountBalance return accountBalance.GetSpendableBalance() >= compareBalance, nil } + +// check if account has enough balance +func (abh *AccountBalanceHelper) HasEnoughBalance(dbTX bool, address []byte, compareBalance int64) (enough bool, err error) { + if bytes.Equal(abh.accountBalance.GetAccountAddress(), address) { + return abh.accountBalance.GetBalance() >= compareBalance, nil + } + var ( + accountBalance model.AccountBalance + ) + err = abh.GetBalanceByAccountAddress(&accountBalance, address, dbTX) + if err != nil { + return false, err + } + abh.accountBalance = accountBalance + return accountBalance.GetBalance() >= compareBalance, nil +} diff --git a/common/transaction/approvalEscrowTransaction.go b/common/transaction/approvalEscrowTransaction.go index 94f55e8ec..e748acb84 100644 --- a/common/transaction/approvalEscrowTransaction.go +++ b/common/transaction/approvalEscrowTransaction.go @@ -36,7 +36,7 @@ type ( EscrowApplyConfirmed(blockTimestamp int64) error EscrowApplyUnconfirmed() error EscrowUndoApplyUnconfirmed() error - EscrowValidate(dbTx bool) error + EscrowValidate(dbTx, checkOnSpendableBalance bool) error // EscrowApproval handle approval an escrow transaction, execute tasks that was skipped on EscrowApplyConfirmed. EscrowApproval( blockTimestamp int64, @@ -125,7 +125,7 @@ func (tx *ApprovalEscrowTransaction) ParseBodyBytes( Validate is func that for validating to Transaction type. Check transaction fields, spendable balance and more */ -func (tx *ApprovalEscrowTransaction) Validate(dbTx bool) error { +func (tx *ApprovalEscrowTransaction) Validate(dbTx, checkOnSpendableBalance bool) error { var ( err error enough bool @@ -135,8 +135,12 @@ func (tx *ApprovalEscrowTransaction) Validate(dbTx bool) error { return err } // check existing account & balance - - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee) + } if err != nil { if err != sql.ErrNoRows { return err @@ -295,7 +299,7 @@ func (tx *ApprovalEscrowTransaction) Escrowable() (EscrowTypeAction, bool) { } // EscrowValidate special validation for escrow's transaction -func (tx *ApprovalEscrowTransaction) EscrowValidate(dbTx bool) error { +func (tx *ApprovalEscrowTransaction) EscrowValidate(dbTx, checkOnSpendableBalance bool) error { return nil } diff --git a/common/transaction/approvalEscrowTransaction_test.go b/common/transaction/approvalEscrowTransaction_test.go index 2a5ea5120..a6eeb26e0 100644 --- a/common/transaction/approvalEscrowTransaction_test.go +++ b/common/transaction/approvalEscrowTransaction_test.go @@ -238,7 +238,8 @@ func TestApprovalEscrowTransaction_Validate(t *testing.T) { AccountBalanceHelper AccountBalanceHelperInterface } type args struct { - dbTx bool + dbTx bool + checkOnSpendableBalance bool } tests := []struct { name string @@ -260,7 +261,7 @@ func TestApprovalEscrowTransaction_Validate(t *testing.T) { QueryExecutor: &mockQueryExecutorValidateNotFound{}, EscrowQuery: query.NewEscrowTransactionQuery(), }, - args: args{dbTx: false}, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -278,7 +279,7 @@ func TestApprovalEscrowTransaction_Validate(t *testing.T) { EscrowQuery: query.NewEscrowTransactionQuery(), TransactionQuery: nil, }, - args: args{dbTx: false}, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -296,7 +297,7 @@ func TestApprovalEscrowTransaction_Validate(t *testing.T) { EscrowQuery: query.NewEscrowTransactionQuery(), AccountBalanceHelper: &mockAccountApprovalEscrowTransactionAccountBalanceHelperAccountBalanceNotFound{}, }, - args: args{dbTx: false}, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -314,7 +315,7 @@ func TestApprovalEscrowTransaction_Validate(t *testing.T) { EscrowQuery: query.NewEscrowTransactionQuery(), AccountBalanceHelper: &mockAccountBalanceApprovalEscrowTransactionAccountBalanceHelperWantSuccess{}, }, - args: args{dbTx: false}, + args: args{dbTx: false, checkOnSpendableBalance: true}, }, } for _, tt := range tests { @@ -332,7 +333,7 @@ func TestApprovalEscrowTransaction_Validate(t *testing.T) { TypeActionSwitcher: tt.fields.TypeActionSwitcher, AccountBalanceHelper: tt.fields.AccountBalanceHelper, } - if err := tx.Validate(tt.args.dbTx); (err != nil) != tt.wantErr { + if err := tx.Validate(tt.args.dbTx, tt.args.checkOnSpendableBalance); (err != nil) != tt.wantErr { t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/common/transaction/empty.go b/common/transaction/empty.go index fe4783d1e..2da5514e4 100644 --- a/common/transaction/empty.go +++ b/common/transaction/empty.go @@ -31,7 +31,7 @@ func (tx *TXEmpty) ApplyUnconfirmed() error { func (tx *TXEmpty) UndoApplyUnconfirmed() error { return nil } -func (tx *TXEmpty) Validate(bool) error { +func (tx *TXEmpty) Validate(bool, bool) error { return nil } diff --git a/common/transaction/feeVoteCommit.go b/common/transaction/feeVoteCommit.go index 640d20193..2843fdd74 100644 --- a/common/transaction/feeVoteCommit.go +++ b/common/transaction/feeVoteCommit.go @@ -94,7 +94,7 @@ func (tx *FeeVoteCommitTransaction) UndoApplyUnconfirmed() error { /* Validate to validating Transaction FeeVoteCommitTransaction type */ -func (tx *FeeVoteCommitTransaction) Validate(dbTx bool) error { +func (tx *FeeVoteCommitTransaction) Validate(dbTx, checkOnSpendableBalance bool) error { var ( row *sql.Row err error @@ -143,7 +143,12 @@ func (tx *FeeVoteCommitTransaction) Validate(dbTx bool) error { } // check existing & balance account sender - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee) + } if err != nil { if err != sql.ErrNoRows { return err @@ -321,20 +326,24 @@ func (tx *FeeVoteCommitTransaction) EscrowUndoApplyUnconfirmed() error { return tx.AccountBalanceHelper.AddAccountSpendableBalance(tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) } -func (tx *FeeVoteCommitTransaction) EscrowValidate(dbTx bool) (err error) { +func (tx *FeeVoteCommitTransaction) EscrowValidate(dbTx, checkOnSpendableBalance bool) (err error) { if tx.Escrow.GetApproverAddress() == nil || bytes.Equal(tx.Escrow.GetApproverAddress(), []byte{}) { return blocker.NewBlocker(blocker.ValidationErr, "ApproverAddressRequired") } if tx.Escrow.GetTimeout() > uint64(constant.MinRollbackBlocks) { return blocker.NewBlocker(blocker.ValidationErr, "TimeoutLimitExceeded") } - err = tx.Validate(dbTx) + err = tx.Validate(dbTx, checkOnSpendableBalance) if err != nil { return err } - + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance var enough bool - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } if err != nil { if err != sql.ErrNoRows { return err diff --git a/common/transaction/feeVoteCommit_test.go b/common/transaction/feeVoteCommit_test.go index e2c8a00f1..e48e08036 100644 --- a/common/transaction/feeVoteCommit_test.go +++ b/common/transaction/feeVoteCommit_test.go @@ -574,7 +574,8 @@ func TestFeeVoteCommitTransaction_Validate(t *testing.T) { QueryExecutor query.ExecutorInterface } type args struct { - dbTx bool + dbTx bool + checkOnSpendableBalance bool } tests := []struct { name string @@ -601,7 +602,8 @@ func TestFeeVoteCommitTransaction_Validate(t *testing.T) { QueryExecutor: &mockQueryExecutorFeeVoteCommitValidateSuccess{}, }, args: args{ - dbTx: false, + dbTx: false, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -614,7 +616,8 @@ func TestFeeVoteCommitTransaction_Validate(t *testing.T) { FeeScaleService: &mockFeeScaleServiceValidateFail{}, }, args: args{ - dbTx: false, + dbTx: false, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -627,7 +630,8 @@ func TestFeeVoteCommitTransaction_Validate(t *testing.T) { FeeScaleService: &mockFeeScaleServiceValidateSuccess{}, }, args: args{ - dbTx: false, + dbTx: false, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -641,7 +645,8 @@ func TestFeeVoteCommitTransaction_Validate(t *testing.T) { QueryExecutor: &mockQueryExecutorFeeVoteCommitValidateSuccess{}, }, args: args{ - dbTx: false, + dbTx: false, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -655,7 +660,8 @@ func TestFeeVoteCommitTransaction_Validate(t *testing.T) { BlockQuery: &mockBlockQueryGetBlockHeightFeeVoteCommitValidateDuplicated{}, }, args: args{ - dbTx: false, + dbTx: false, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -670,7 +676,8 @@ func TestFeeVoteCommitTransaction_Validate(t *testing.T) { NodeRegistrationQuery: &mockNodeRegistrationQueryFeeVoteCommitValidateFail{}, }, args: args{ - dbTx: false, + dbTx: false, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -685,7 +692,8 @@ func TestFeeVoteCommitTransaction_Validate(t *testing.T) { NodeRegistrationQuery: &mockNodeRegistrationQueryFeeVoteCommitValidateFailErrNoRow{}, }, args: args{ - dbTx: false, + dbTx: false, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -700,7 +708,8 @@ func TestFeeVoteCommitTransaction_Validate(t *testing.T) { NodeRegistrationQuery: &mockNodeRegistrationQueryFeeVoteCommitValidateFailErrNoRow{}, }, args: args{ - dbTx: false, + dbTx: false, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -716,7 +725,8 @@ func TestFeeVoteCommitTransaction_Validate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperFeeVoteCommitValidateFail{}, }, args: args{ - dbTx: false, + dbTx: false, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -733,7 +743,8 @@ func TestFeeVoteCommitTransaction_Validate(t *testing.T) { FeeScaleService: &mockFeeScaleServiceValidateSuccess{}, }, args: args{ - dbTx: false, + dbTx: false, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -750,7 +761,8 @@ func TestFeeVoteCommitTransaction_Validate(t *testing.T) { FeeScaleService: &mockFeeScaleServiceValidateSuccess{}, }, args: args{ - dbTx: false, + dbTx: false, + checkOnSpendableBalance: true, }, wantErr: false, }, @@ -770,7 +782,7 @@ func TestFeeVoteCommitTransaction_Validate(t *testing.T) { AccountBalanceHelper: tt.fields.AccountBalanceHelper, QueryExecutor: tt.fields.QueryExecutor, } - if err := tx.Validate(tt.args.dbTx); (err != nil) != tt.wantErr { + if err := tx.Validate(tt.args.dbTx, tt.args.checkOnSpendableBalance); (err != nil) != tt.wantErr { t.Errorf("FeeVoteCommitTransaction.Validate() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/common/transaction/feeVoteReveal.go b/common/transaction/feeVoteReveal.go index 58e02ecd1..61280e18d 100644 --- a/common/transaction/feeVoteReveal.go +++ b/common/transaction/feeVoteReveal.go @@ -41,7 +41,7 @@ type ( ) // Validate for validating the transaction concerned -func (tx *FeeVoteRevealTransaction) Validate(dbTx bool) error { +func (tx *FeeVoteRevealTransaction) Validate(dbTx, checkOnSpendableBalance bool) error { var ( feeVotePhase model.FeeVotePhase recentBlock model.Block @@ -143,8 +143,12 @@ func (tx *FeeVoteRevealTransaction) Validate(dbTx bool) error { return err } // check existing & balance account sender - - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee) + } if err != nil { if err != sql.ErrNoRows { return err @@ -394,7 +398,7 @@ func (tx *FeeVoteRevealTransaction) EscrowUndoApplyUnconfirmed() error { return tx.AccountBalanceHelper.AddAccountSpendableBalance(tx.SenderAddress, tx.Fee) } -func (tx *FeeVoteRevealTransaction) EscrowValidate(dbTx bool) (err error) { +func (tx *FeeVoteRevealTransaction) EscrowValidate(dbTx, checkOnSpendableBalance bool) (err error) { if tx.Escrow.GetApproverAddress() == nil || bytes.Equal(tx.Escrow.GetApproverAddress(), []byte{}) { return blocker.NewBlocker(blocker.ValidationErr, "ApproverAddressRequired") } @@ -402,13 +406,18 @@ func (tx *FeeVoteRevealTransaction) EscrowValidate(dbTx bool) (err error) { return blocker.NewBlocker(blocker.ValidationErr, "TimeoutLimitExceeded") } - err = tx.Validate(dbTx) + err = tx.Validate(dbTx, checkOnSpendableBalance) if err != nil { return err } + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance var enough bool - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } if err != nil { if err != sql.ErrNoRows { return err diff --git a/common/transaction/feeVoteReveal_test.go b/common/transaction/feeVoteReveal_test.go index 5f63880db..7623425a1 100644 --- a/common/transaction/feeVoteReveal_test.go +++ b/common/transaction/feeVoteReveal_test.go @@ -4,12 +4,13 @@ import ( "crypto/sha256" "database/sql" "errors" - "github.com/zoobc/zoobc-core/common/crypto" "reflect" "regexp" "strings" "testing" + "github.com/zoobc/zoobc-core/common/crypto" + "github.com/DATA-DOG/go-sqlmock" "github.com/zoobc/zoobc-core/common/chaintype" "github.com/zoobc/zoobc-core/common/fee" @@ -209,7 +210,8 @@ func TestFeeVoteRevealTransaction_Validate(t *testing.T) { QueryExecutor query.ExecutorInterface } type args struct { - dbTx bool + dbTx bool + checkOnSpendableBalance bool } tests := []struct { name string @@ -224,6 +226,7 @@ func TestFeeVoteRevealTransaction_Validate(t *testing.T) { Timestamp: 12345678, FeeScaleService: &mockFeeScaleFeeVoteRevealTXValidateInvalidPhasePeriod{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -244,6 +247,7 @@ func TestFeeVoteRevealTransaction_Validate(t *testing.T) { FeeVoteCommitVoteQuery: &mockCommitmentVoteQueryFeeVoteRevealTXValidateFound{}, QueryExecutor: &mockQueryExecutorFeeVoteRevealTXValidateSuccess{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -265,6 +269,7 @@ func TestFeeVoteRevealTransaction_Validate(t *testing.T) { QueryExecutor: &mockQueryExecutorFeeVoteRevealTXValidateSuccess{}, FeeVoteCommitVoteQuery: &mockCommitmentVoteQueryFeeVoteRevealTXValidateFound{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -286,6 +291,7 @@ func TestFeeVoteRevealTransaction_Validate(t *testing.T) { QueryExecutor: &mockQueryExecutorFeeVoteRevealTXValidateSuccess{}, FeeVoteCommitVoteQuery: &mockCommitmentVoteQueryFeeVoteRevealTXValidateNotFound{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -308,6 +314,7 @@ func TestFeeVoteRevealTransaction_Validate(t *testing.T) { FeeVoteCommitVoteQuery: &mockCommitmentVoteQueryFeeVoteRevealTXValidateFound{}, NodeRegistrationQuery: &mockNodeRegistrationQueryFeeVoteRevealTXValidateNotFound{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -331,6 +338,7 @@ func TestFeeVoteRevealTransaction_Validate(t *testing.T) { FeeVoteRevealVoteQuery: &mockVoteRevealQueryFeeVoteRevealTXValidateFound{}, NodeRegistrationQuery: &mockNodeRegistrationQueryFeeVoteRevealTXValidateFound{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -355,6 +363,7 @@ func TestFeeVoteRevealTransaction_Validate(t *testing.T) { NodeRegistrationQuery: &mockNodeRegistrationQueryFeeVoteRevealTXValidateFound{}, AccountBalanceHelper: &mockAccountBalanceHelperValidateSuccess{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: false, }, } @@ -376,7 +385,7 @@ func TestFeeVoteRevealTransaction_Validate(t *testing.T) { AccountBalanceHelper: tt.fields.AccountBalanceHelper, QueryExecutor: tt.fields.QueryExecutor, } - if err := tx.Validate(tt.args.dbTx); (err != nil) != tt.wantErr { + if err := tx.Validate(tt.args.dbTx, tt.args.checkOnSpendableBalance); (err != nil) != tt.wantErr { t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/common/transaction/liquidPayment.go b/common/transaction/liquidPayment.go index 26c1d99da..118e3490b 100644 --- a/common/transaction/liquidPayment.go +++ b/common/transaction/liquidPayment.go @@ -90,7 +90,7 @@ func (tx *LiquidPaymentTransaction) UndoApplyUnconfirmed() (err error) { return nil } -func (tx *LiquidPaymentTransaction) Validate(dbTx bool) error { +func (tx *LiquidPaymentTransaction) Validate(dbTx, checkOnSpendableBalance bool) error { var ( err error enough bool @@ -107,7 +107,12 @@ func (tx *LiquidPaymentTransaction) Validate(dbTx bool) error { } // check existing & balance account sender - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Body.GetAmount()+tx.Fee) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Body.GetAmount()+tx.Fee) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Body.GetAmount()+tx.Fee) + } if err != nil { if err != sql.ErrNoRows { return err @@ -296,7 +301,7 @@ func (tx *LiquidPaymentTransaction) EscrowUndoApplyUnconfirmed() (err error) { return nil } -func (tx *LiquidPaymentTransaction) EscrowValidate(dbTx bool) (err error) { +func (tx *LiquidPaymentTransaction) EscrowValidate(dbTx, checkOnSpendableBalance bool) (err error) { var enough bool if tx.Escrow.GetApproverAddress() == nil || bytes.Equal(tx.Escrow.GetApproverAddress(), []byte{}) { return blocker.NewBlocker(blocker.ValidationErr, "ApproverAddressRequired") @@ -304,15 +309,25 @@ func (tx *LiquidPaymentTransaction) EscrowValidate(dbTx bool) (err error) { if tx.Escrow.GetTimeout() > uint64(constant.MinRollbackBlocks) { return blocker.NewBlocker(blocker.ValidationErr, "TimeoutLimitExceeded") } - err = tx.Validate(dbTx) + err = tx.Validate(dbTx, checkOnSpendableBalance) if err != nil { return err } - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance( - dbTx, - tx.SenderAddress, - tx.Body.GetAmount()+tx.Fee+tx.Escrow.GetCommission(), - ) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance( + dbTx, + tx.SenderAddress, + tx.Body.GetAmount()+tx.Fee+tx.Escrow.GetCommission(), + ) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance( + dbTx, + tx.SenderAddress, + tx.Body.GetAmount()+tx.Fee+tx.Escrow.GetCommission(), + ) + } + if err != nil { if err != sql.ErrNoRows { return err diff --git a/common/transaction/liquidPaymentStop.go b/common/transaction/liquidPaymentStop.go index bdc8b87b5..6c1504022 100644 --- a/common/transaction/liquidPaymentStop.go +++ b/common/transaction/liquidPaymentStop.go @@ -123,7 +123,7 @@ func (tx *LiquidPaymentStopTransaction) UndoApplyUnconfirmed() error { return nil } -func (tx *LiquidPaymentStopTransaction) Validate(dbTx bool) error { +func (tx *LiquidPaymentStopTransaction) Validate(dbTx, checkOnSpendableBalance bool) error { var ( row *sql.Row err error @@ -163,7 +163,13 @@ func (tx *LiquidPaymentStopTransaction) Validate(dbTx bool) error { } // check existing & balance account sender - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee) + } + if err != nil { if err != sql.ErrNoRows { return err @@ -283,7 +289,7 @@ func (tx *LiquidPaymentStopTransaction) EscrowUndoApplyUnconfirmed() error { return nil } -func (tx *LiquidPaymentStopTransaction) EscrowValidate(dbTx bool) (err error) { +func (tx *LiquidPaymentStopTransaction) EscrowValidate(dbTx, checkOnSpendableBalance bool) (err error) { var enough bool if tx.Escrow.GetApproverAddress() == nil || bytes.Equal(tx.Escrow.GetApproverAddress(), []byte{}) { @@ -293,11 +299,17 @@ func (tx *LiquidPaymentStopTransaction) EscrowValidate(dbTx bool) (err error) { return blocker.NewBlocker(blocker.ValidationErr, "TimeoutLimitExceeded") } - err = tx.Validate(dbTx) + err = tx.Validate(dbTx, checkOnSpendableBalance) if err != nil { return err } - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } + if err != nil { if err != sql.ErrNoRows { return err diff --git a/common/transaction/liquidPaymentStop_test.go b/common/transaction/liquidPaymentStop_test.go index 9835defe0..523705263 100644 --- a/common/transaction/liquidPaymentStop_test.go +++ b/common/transaction/liquidPaymentStop_test.go @@ -584,7 +584,8 @@ func TestLiquidPaymentStop_Validate(t *testing.T) { TypeActionSwitcher TypeActionSwitcher } type args struct { - dbTx bool + dbTx bool + checkOnSpendableBalance bool } tests := []struct { name string @@ -611,6 +612,7 @@ func TestLiquidPaymentStop_Validate(t *testing.T) { ), NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -632,6 +634,7 @@ func TestLiquidPaymentStop_Validate(t *testing.T) { ), NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -653,6 +656,7 @@ func TestLiquidPaymentStop_Validate(t *testing.T) { ), NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -674,6 +678,7 @@ func TestLiquidPaymentStop_Validate(t *testing.T) { ), NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -698,6 +703,7 @@ func TestLiquidPaymentStop_Validate(t *testing.T) { ), NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -722,6 +728,7 @@ func TestLiquidPaymentStop_Validate(t *testing.T) { ), NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -742,6 +749,7 @@ func TestLiquidPaymentStop_Validate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperLiquidPaymentStopValidateSuccess{}, NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: false, }, { @@ -762,6 +770,7 @@ func TestLiquidPaymentStop_Validate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperLiquidPaymentStopValidateSuccess{}, NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: false, }, { @@ -782,6 +791,7 @@ func TestLiquidPaymentStop_Validate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperLiquidPaymentStopValidateSuccess{}, NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: false, }, } @@ -801,7 +811,7 @@ func TestLiquidPaymentStop_Validate(t *testing.T) { NormalFee: tt.fields.NormalFee, TypeActionSwitcher: tt.fields.TypeActionSwitcher, } - if err := tx.Validate(tt.args.dbTx); (err != nil) != tt.wantErr { + if err := tx.Validate(tt.args.dbTx, tt.args.checkOnSpendableBalance); (err != nil) != tt.wantErr { t.Errorf("LiquidPaymentStop.Validate() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/common/transaction/liquidPayment_test.go b/common/transaction/liquidPayment_test.go index 2ac741074..3263ae656 100644 --- a/common/transaction/liquidPayment_test.go +++ b/common/transaction/liquidPayment_test.go @@ -349,7 +349,8 @@ func TestLiquidPayment_Validate(t *testing.T) { NormalFee fee.FeeModelInterface } type args struct { - dbTx bool + dbTx bool + checkOnSpendableBalance bool } tests := []struct { name string @@ -378,6 +379,7 @@ func TestLiquidPayment_Validate(t *testing.T) { ), NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -401,6 +403,7 @@ func TestLiquidPayment_Validate(t *testing.T) { ), NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -424,6 +427,7 @@ func TestLiquidPayment_Validate(t *testing.T) { ), NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -447,6 +451,7 @@ func TestLiquidPayment_Validate(t *testing.T) { ), NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -470,6 +475,7 @@ func TestLiquidPayment_Validate(t *testing.T) { ), NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -493,6 +499,7 @@ func TestLiquidPayment_Validate(t *testing.T) { ), NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -514,6 +521,7 @@ func TestLiquidPayment_Validate(t *testing.T) { }, query.NewAccountLedgerQuery()), NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -535,6 +543,7 @@ func TestLiquidPayment_Validate(t *testing.T) { }, query.NewAccountLedgerQuery()), NormalFee: fee.NewBlockLifeTimeFeeModel(1, 2), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: false, }, } @@ -552,7 +561,7 @@ func TestLiquidPayment_Validate(t *testing.T) { AccountBalanceHelper: tt.fields.AccountBalanceHelper, NormalFee: tt.fields.NormalFee, } - if err := tx.Validate(tt.args.dbTx); (err != nil) != tt.wantErr { + if err := tx.Validate(tt.args.dbTx, tt.args.checkOnSpendableBalance); (err != nil) != tt.wantErr { t.Errorf("LiquidPayment.Validate() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/common/transaction/multiSignature.go b/common/transaction/multiSignature.go index 6a1647e96..bfedcc65f 100644 --- a/common/transaction/multiSignature.go +++ b/common/transaction/multiSignature.go @@ -511,12 +511,11 @@ func (tx *MultiSignatureTransaction) UndoApplyUnconfirmed() error { } // Validate dbTx specify whether validation should read from transaction state or db state -func (tx *MultiSignatureTransaction) Validate(dbTx bool) error { +func (tx *MultiSignatureTransaction) Validate(dbTx, checkOnSpendableBalance bool) error { var ( body = tx.Body multisigInfoAddresses = make(map[string]bool) err error - accountBalance model.AccountBalance ) if body.MultiSignatureInfo == nil && body.SignatureInfo == nil && body.UnsignedTransactionBytes == nil { return blocker.NewBlocker( @@ -526,12 +525,17 @@ func (tx *MultiSignatureTransaction) Validate(dbTx bool) error { } // check existing & balance account sender - err = tx.AccountBalanceHelper.GetBalanceByAccountAddress(&accountBalance, tx.SenderAddress, dbTx) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + var enough bool + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee) + } if err != nil { return err } - - if accountBalance.SpendableBalance < tx.Fee { + if !enough { return blocker.NewBlocker( blocker.ValidationErr, "UserBalanceNotEnough", @@ -557,6 +561,7 @@ func (tx *MultiSignatureTransaction) Validate(dbTx bool) error { body.UnsignedTransactionBytes, tx.Height, dbTx, + checkOnSpendableBalance, ) if err != nil { return err @@ -585,6 +590,7 @@ func (tx *MultiSignatureTransaction) Validate(dbTx bool) error { body.UnsignedTransactionBytes, tx.Height, dbTx, + checkOnSpendableBalance, ) if err != nil { return err @@ -838,7 +844,7 @@ func (tx *MultiSignatureTransaction) EscrowUndoApplyUnconfirmed() error { return tx.AccountBalanceHelper.AddAccountSpendableBalance(tx.SenderAddress, tx.Fee) } -func (tx *MultiSignatureTransaction) EscrowValidate(dbTx bool) error { +func (tx *MultiSignatureTransaction) EscrowValidate(dbTx, checkOnSpendableBalance bool) error { var ( err error @@ -853,12 +859,16 @@ func (tx *MultiSignatureTransaction) EscrowValidate(dbTx bool) error { if tx.Escrow.GetTimeout() > uint64(constant.MinRollbackBlocks) { return blocker.NewBlocker(blocker.ValidationErr, "TimeoutRequired") } - err = tx.Validate(dbTx) + err = tx.Validate(dbTx, checkOnSpendableBalance) if err != nil { return err } - - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } if err != nil { if err != sql.ErrNoRows { return err diff --git a/common/transaction/multiSignature_test.go b/common/transaction/multiSignature_test.go index da335056d..e1f6aa412 100644 --- a/common/transaction/multiSignature_test.go +++ b/common/transaction/multiSignature_test.go @@ -3,11 +3,11 @@ package transaction import ( "database/sql" "errors" - "github.com/zoobc/zoobc-core/common/crypto" "reflect" "testing" "github.com/DATA-DOG/go-sqlmock" + "github.com/zoobc/zoobc-core/common/crypto" "github.com/zoobc/zoobc-core/common/fee" "github.com/zoobc/zoobc-core/common/model" "github.com/zoobc/zoobc-core/common/query" @@ -1254,7 +1254,7 @@ func (*mockMultisignatureValidateMultisigUtilValidatePendingTxFail) ValidatePend multisigInfo *model.MultiSignatureInfo, senderAddress, unsignedTxBytes []byte, blockHeight uint32, - dbTx bool, + dbTx, checkOnSpendableBalance bool, ) error { return errors.New("mockedError") } @@ -1267,7 +1267,7 @@ func (*mockMultisignatureValidateMultisigUtilValidatePendingTxSuccessValidateSig multisigInfo *model.MultiSignatureInfo, senderAddress, unsignedTxBytes []byte, blockHeight uint32, - dbTx bool, + dbTx, checkOnSpendableBalance bool, ) error { *multisigInfo = model.MultiSignatureInfo{ Addresses: make([][]byte, 2), @@ -1289,7 +1289,7 @@ func (*mockMultisignatureValidateMultisigUtilValidateMultisigInfoSuccessPendingT multisigInfo *model.MultiSignatureInfo, senderAddress, unsignedTxBytes []byte, blockHeight uint32, - dbTx bool, + dbTx, checkOnSpendableBalance bool, ) error { return errors.New("mockedError") } @@ -1311,6 +1311,11 @@ func (*mockAccountBalanceHelperMultisignatureValidateSuccess) GetBalanceByAccoun accountBalance.SpendableBalance = mockFeeMultisignatureValidate + 1 return nil } +func (*mockAccountBalanceHelperMultisignatureValidateSuccess) HasEnoughSpendableBalance( + dbTX bool, address []byte, compareBalance int64, +) (enough bool, err error) { + return true, nil +} func TestMultiSignatureTransaction_Validate(t *testing.T) { type fields struct { @@ -1332,7 +1337,8 @@ func TestMultiSignatureTransaction_Validate(t *testing.T) { TransactionHelper TransactionHelperInterface } type args struct { - dbTx bool + dbTx bool + checkOnSpendableBalance bool } tests := []struct { name string @@ -1350,7 +1356,8 @@ func TestMultiSignatureTransaction_Validate(t *testing.T) { }, }, args: args{ - dbTx: true, + dbTx: true, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -1367,7 +1374,8 @@ func TestMultiSignatureTransaction_Validate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperMultisignatureValidateSuccess{}, }, args: args{ - dbTx: true, + dbTx: true, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -1384,7 +1392,8 @@ func TestMultiSignatureTransaction_Validate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperMultisignatureValidateSuccess{}, }, args: args{ - dbTx: true, + dbTx: true, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -1402,7 +1411,8 @@ func TestMultiSignatureTransaction_Validate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperMultisignatureValidateSuccess{}, }, args: args{ - dbTx: true, + dbTx: true, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -1419,7 +1429,8 @@ func TestMultiSignatureTransaction_Validate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperMultisignatureValidateSuccess{}, }, args: args{ - dbTx: true, + dbTx: true, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -1437,7 +1448,8 @@ func TestMultiSignatureTransaction_Validate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperMultisignatureValidateSuccess{}, }, args: args{ - dbTx: true, + dbTx: true, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -1455,7 +1467,8 @@ func TestMultiSignatureTransaction_Validate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperMultisignatureValidateSuccess{}, }, args: args{ - dbTx: true, + dbTx: true, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -1473,7 +1486,8 @@ func TestMultiSignatureTransaction_Validate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperMultisignatureValidateSuccess{}, }, args: args{ - dbTx: true, + dbTx: true, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -1492,7 +1506,8 @@ func TestMultiSignatureTransaction_Validate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperMultisignatureValidateSuccess{}, }, args: args{ - dbTx: true, + dbTx: true, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -1511,7 +1526,8 @@ func TestMultiSignatureTransaction_Validate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperMultisignatureValidateSuccess{}, }, args: args{ - dbTx: true, + dbTx: true, + checkOnSpendableBalance: true, }, wantErr: true, }, @@ -1531,7 +1547,8 @@ func TestMultiSignatureTransaction_Validate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperMultisignatureValidateSuccess{}, }, args: args{ - dbTx: true, + dbTx: true, + checkOnSpendableBalance: true, }, wantErr: false, }, @@ -1556,7 +1573,7 @@ func TestMultiSignatureTransaction_Validate(t *testing.T) { AccountBalanceHelper: tt.fields.AccountBalanceHelper, TransactionHelper: tt.fields.TransactionHelper, } - if err := tx.Validate(tt.args.dbTx); (err != nil) != tt.wantErr { + if err := tx.Validate(tt.args.dbTx, tt.args.checkOnSpendableBalance); (err != nil) != tt.wantErr { t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/common/transaction/nodeRegistration.go b/common/transaction/nodeRegistration.go index aff90d0c1..ac3a84128 100644 --- a/common/transaction/nodeRegistration.go +++ b/common/transaction/nodeRegistration.go @@ -203,7 +203,7 @@ func (tx *NodeRegistration) UndoApplyUnconfirmed() error { } // Validate validate node registration transaction and tx body -func (tx *NodeRegistration) Validate(dbTx bool) error { +func (tx *NodeRegistration) Validate(dbTx, checkOnSpendableBalance bool) error { var ( nodeRegByNodePub, nodeRegByAccAddress model.NodeRegistration row *sql.Row @@ -228,7 +228,13 @@ func (tx *NodeRegistration) Validate(dbTx bool) error { } // check balance - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Body.GetLockedBalance()+tx.Fee) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Body.GetLockedBalance()+tx.Fee) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Body.GetLockedBalance()+tx.Fee) + } + if err != nil { if err != sql.ErrNoRows { return err @@ -401,7 +407,7 @@ func (tx *NodeRegistration) Escrowable() (EscrowTypeAction, bool) { } // EscrowValidate special validation for escrow's transaction -func (tx *NodeRegistration) EscrowValidate(dbTx bool) error { +func (tx *NodeRegistration) EscrowValidate(dbTx, checkOnSpendableBalance bool) error { var ( err error enough bool @@ -413,13 +419,18 @@ func (tx *NodeRegistration) EscrowValidate(dbTx bool) error { if tx.Escrow.GetTimeout() > uint64(constant.MinRollbackBlocks) { return blocker.NewBlocker(blocker.ValidationErr, "TimeoutRequired") } - err = tx.Validate(dbTx) + err = tx.Validate(dbTx, checkOnSpendableBalance) if err != nil { return err } // check balance - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Body.GetLockedBalance()+tx.Fee+tx.Escrow.GetCommission()) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Body.GetLockedBalance()+tx.Fee+tx.Escrow.GetCommission()) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Body.GetLockedBalance()+tx.Fee+tx.Escrow.GetCommission()) + } if err != nil { if err != sql.ErrNoRows { return err diff --git a/common/transaction/nodeRegistrationClaim.go b/common/transaction/nodeRegistrationClaim.go index 10ffa79de..7a8e28333 100644 --- a/common/transaction/nodeRegistrationClaim.go +++ b/common/transaction/nodeRegistrationClaim.go @@ -160,7 +160,7 @@ func (tx *ClaimNodeRegistration) UndoApplyUnconfirmed() error { } // Validate validate node registration transaction and tx body -func (tx *ClaimNodeRegistration) Validate(dbTx bool) error { +func (tx *ClaimNodeRegistration) Validate(dbTx, checkOnSpendableBalance bool) error { var ( nodeRegistration model.NodeRegistration row *sql.Row @@ -195,8 +195,12 @@ func (tx *ClaimNodeRegistration) Validate(dbTx bool) error { if nodeRegistration.GetRegistrationStatus() == uint32(model.NodeRegistrationState_NodeDeleted) { return blocker.NewBlocker(blocker.ValidationErr, "NodeAlreadyClaimedOrDeleted") } - - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee) + } if err != nil { return err } @@ -296,7 +300,7 @@ func (tx *ClaimNodeRegistration) Escrowable() (EscrowTypeAction, bool) { } // EscrowValidate validate node registration transaction and tx body -func (tx *ClaimNodeRegistration) EscrowValidate(dbTX bool) error { +func (tx *ClaimNodeRegistration) EscrowValidate(dbTX, checkOnSpendableBalance bool) error { var ( err error enough bool @@ -309,12 +313,18 @@ func (tx *ClaimNodeRegistration) EscrowValidate(dbTX bool) error { return blocker.NewBlocker(blocker.ValidationErr, "TimeoutLimitExceeded") } - err = tx.Validate(dbTX) + err = tx.Validate(dbTX, checkOnSpendableBalance) if err != nil { return err } - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTX, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTX, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTX, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } + if err != nil { return err } diff --git a/common/transaction/nodeRegistrationClaim_test.go b/common/transaction/nodeRegistrationClaim_test.go index bf0c83a86..10606e77e 100644 --- a/common/transaction/nodeRegistrationClaim_test.go +++ b/common/transaction/nodeRegistrationClaim_test.go @@ -193,7 +193,10 @@ func TestClaimNodeRegistration_Validate(t *testing.T) { Poown: poown, NodePublicKey: []byte{1, 1, 1, 1}, } - + type args struct { + dbTx bool + checkOnSpendableBalance bool + } type fields struct { Body *model.ClaimNodeRegistrationTransactionBody Fee int64 @@ -208,6 +211,7 @@ func TestClaimNodeRegistration_Validate(t *testing.T) { tests := []struct { name string fields fields + args args wantErr bool errText string }{ @@ -216,6 +220,7 @@ func TestClaimNodeRegistration_Validate(t *testing.T) { fields: fields{ Body: txBodyWithoutPoown, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, errText: "ValidationErr: PoownRequired", }, @@ -225,6 +230,7 @@ func TestClaimNodeRegistration_Validate(t *testing.T) { Body: txBodyWithPoown, AuthPoown: &mockAuthPoown{success: false}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, errText: "MockedError", }, @@ -236,6 +242,7 @@ func TestClaimNodeRegistration_Validate(t *testing.T) { NodeRegistrationQuery: query.NewNodeRegistrationQuery(), QueryExecutor: &mockExecutorValidateFailClaimNRNodeNotRegistered{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, errText: blocker.NewBlocker(blocker.ValidationErr, "NodePublicKeyNotRegistered").Error(), }, @@ -247,6 +254,7 @@ func TestClaimNodeRegistration_Validate(t *testing.T) { NodeRegistrationQuery: query.NewNodeRegistrationQuery(), QueryExecutor: &mockExecutorValidateFailClaimNRNodeAlreadyDeleted{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, errText: blocker.NewBlocker(blocker.ValidationErr, "NodeAlreadyClaimedOrDeleted").Error(), }, @@ -260,6 +268,7 @@ func TestClaimNodeRegistration_Validate(t *testing.T) { QueryExecutor: &mockExecutorValidateSuccessClaimNR{}, AccountBalanceHelper: &mockAccountBalanceHelperClaimNRValidateFail{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, errText: "ValidationErr: BalanceNotEnough", }, @@ -273,6 +282,7 @@ func TestClaimNodeRegistration_Validate(t *testing.T) { QueryExecutor: &mockExecutorValidateSuccessClaimNR{}, AccountBalanceHelper: &mockAccountBalanceHelperClaimNRValidateNotEnoughSpendable{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, errText: blocker.NewBlocker(blocker.ValidationErr, "BalanceNotEnough").Error(), }, @@ -301,7 +311,7 @@ func TestClaimNodeRegistration_Validate(t *testing.T) { AuthPoown: tt.fields.AuthPoown, AccountBalanceHelper: tt.fields.AccountBalanceHelper, } - err := tx.Validate(false) + err := tx.Validate(tt.args.dbTx, tt.args.checkOnSpendableBalance) if err != nil { if !tt.wantErr { t.Errorf("NodeAuthValidation.ValidateProofOfOwnership() error = %v, wantErr %v", err, tt.wantErr) diff --git a/common/transaction/nodeRegistrationUpdate.go b/common/transaction/nodeRegistrationUpdate.go index 53c8233eb..81714e147 100644 --- a/common/transaction/nodeRegistrationUpdate.go +++ b/common/transaction/nodeRegistrationUpdate.go @@ -220,7 +220,7 @@ func (tx *UpdateNodeRegistration) UndoApplyUnconfirmed() error { } // Validate validate node registration transaction and tx body -func (tx *UpdateNodeRegistration) Validate(dbTx bool) error { +func (tx *UpdateNodeRegistration) Validate(dbTx, checkOnSpendableBalance bool) error { var ( err error enough bool @@ -284,7 +284,13 @@ func (tx *UpdateNodeRegistration) Validate(dbTx bool) error { } // check aalance - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+effectiveBalanceToLock) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+effectiveBalanceToLock) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee+effectiveBalanceToLock) + } + if err != nil { if err != sql.ErrNoRows { return err @@ -408,7 +414,7 @@ func (tx *UpdateNodeRegistration) Escrowable() (EscrowTypeAction, bool) { } // EscrowValidate validate node registration transaction and tx body -func (tx *UpdateNodeRegistration) EscrowValidate(dbTx bool) error { +func (tx *UpdateNodeRegistration) EscrowValidate(dbTx, checkOnSpendableBalance bool) error { var ( effectiveBalanceToLock int64 err error @@ -423,7 +429,7 @@ func (tx *UpdateNodeRegistration) EscrowValidate(dbTx bool) error { return blocker.NewBlocker(blocker.ValidationErr, "TimeoutLimitExceeded") } - err = tx.Validate(dbTx) + err = tx.Validate(dbTx, checkOnSpendableBalance) if err != nil { return err } @@ -438,8 +444,12 @@ func (tx *UpdateNodeRegistration) EscrowValidate(dbTx bool) error { return blocker.NewBlocker(blocker.ValidationErr, "SenderAccountNotNodeOwner") } effectiveBalanceToLock = tx.Body.GetLockedBalance() - prevNodeReg.GetLockedBalance() - - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()+effectiveBalanceToLock) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()+effectiveBalanceToLock) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()+effectiveBalanceToLock) + } if err != nil { if err != sql.ErrNoRows { return err diff --git a/common/transaction/nodeRegistrationUpdate_test.go b/common/transaction/nodeRegistrationUpdate_test.go index 74097bad0..8ca28d43b 100644 --- a/common/transaction/nodeRegistrationUpdate_test.go +++ b/common/transaction/nodeRegistrationUpdate_test.go @@ -376,6 +376,10 @@ func TestUpdateNodeRegistration_Validate(t *testing.T) { Poown: poown, LockedBalance: int64(100000), } + type args struct { + dbTx bool + checkOnSpendableBalance bool + } type fields struct { Body *model.UpdateNodeRegistrationTransactionBody Fee int64 @@ -390,6 +394,7 @@ func TestUpdateNodeRegistration_Validate(t *testing.T) { tests := []struct { name string fields fields + args args wantErr bool }{ { @@ -397,6 +402,7 @@ func TestUpdateNodeRegistration_Validate(t *testing.T) { fields: fields{ Body: txBodyWithoutPoown, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -405,6 +411,7 @@ func TestUpdateNodeRegistration_Validate(t *testing.T) { Body: txBodyInvalidPoown, AuthPoown: &mockAuthPoown{success: false}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -417,6 +424,7 @@ func TestUpdateNodeRegistration_Validate(t *testing.T) { BlockQuery: query.NewBlockQuery(&chaintype.MainChain{}), AuthPoown: &mockAuthPoown{success: true}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -429,6 +437,7 @@ func TestUpdateNodeRegistration_Validate(t *testing.T) { BlockQuery: query.NewBlockQuery(&chaintype.MainChain{}), AuthPoown: &mockAuthPoown{success: true}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -441,6 +450,7 @@ func TestUpdateNodeRegistration_Validate(t *testing.T) { BlockQuery: query.NewBlockQuery(&chaintype.MainChain{}), AuthPoown: &mockAuthPoown{success: true}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -453,6 +463,7 @@ func TestUpdateNodeRegistration_Validate(t *testing.T) { BlockQuery: query.NewBlockQuery(&chaintype.MainChain{}), AuthPoown: &mockAuthPoown{success: true}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -466,6 +477,7 @@ func TestUpdateNodeRegistration_Validate(t *testing.T) { AuthPoown: &mockAuthPoown{success: true}, AccountBalanceHelper: &mockAccountBalanceHelperUpdateNRValidateSuccess{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: false, }, { @@ -478,6 +490,7 @@ func TestUpdateNodeRegistration_Validate(t *testing.T) { BlockQuery: query.NewBlockQuery(&chaintype.MainChain{}), AuthPoown: &mockAuthPoown{success: true}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -491,6 +504,7 @@ func TestUpdateNodeRegistration_Validate(t *testing.T) { AuthPoown: &mockAuthPoown{success: true}, AccountBalanceHelper: &mockAccountBalanceHelperUpdateNRValidateFail{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -504,6 +518,7 @@ func TestUpdateNodeRegistration_Validate(t *testing.T) { AuthPoown: &mockAuthPoown{success: true}, AccountBalanceHelper: &mockAccountBalanceHelperUpdateNRValidateSuccess{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: false, }, } @@ -520,7 +535,7 @@ func TestUpdateNodeRegistration_Validate(t *testing.T) { AuthPoown: tt.fields.AuthPoown, AccountBalanceHelper: tt.fields.AccountBalanceHelper, } - if err := tx.Validate(false); (err != nil) != tt.wantErr { + if err := tx.Validate(tt.args.dbTx, tt.args.checkOnSpendableBalance); (err != nil) != tt.wantErr { t.Errorf("UpdateNodeRegistration.Validate() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/common/transaction/nodeRegistration_test.go b/common/transaction/nodeRegistration_test.go index a2a68f06b..80fe214f7 100644 --- a/common/transaction/nodeRegistration_test.go +++ b/common/transaction/nodeRegistration_test.go @@ -1068,6 +1068,10 @@ func TestNodeRegistration_Validate(t *testing.T) { NodePublicKey: nodePubKey1, } bodyWithoutPoown := &model.NodeRegistrationTransactionBody{} + type args struct { + dbTx bool + checkOnSpendableBalance bool + } type fields struct { Body *model.NodeRegistrationTransactionBody Fee int64 @@ -1082,6 +1086,7 @@ func TestNodeRegistration_Validate(t *testing.T) { tests := []struct { name string fields fields + args args wantErr bool }{ { @@ -1093,6 +1098,7 @@ func TestNodeRegistration_Validate(t *testing.T) { BlockQuery: query.NewBlockQuery(&chaintype.MainChain{}), AuthPoown: &mockAuthPoown{success: false}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: false, }, { @@ -1104,6 +1110,7 @@ func TestNodeRegistration_Validate(t *testing.T) { BlockQuery: query.NewBlockQuery(&chaintype.MainChain{}), AuthPoown: &mockAuthPoown{success: false}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -1115,6 +1122,7 @@ func TestNodeRegistration_Validate(t *testing.T) { BlockQuery: query.NewBlockQuery(&chaintype.MainChain{}), AuthPoown: &mockAuthPoown{success: false}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -1127,6 +1135,7 @@ func TestNodeRegistration_Validate(t *testing.T) { BlockQuery: query.NewBlockQuery(&chaintype.MainChain{}), AuthPoown: &mockAuthPoown{success: false}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -1140,6 +1149,7 @@ func TestNodeRegistration_Validate(t *testing.T) { AuthPoown: &mockAuthPoown{success: true}, AccountBalanceHelper: &mockAccountBalanceHelperNRFail{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -1158,6 +1168,7 @@ func TestNodeRegistration_Validate(t *testing.T) { AuthPoown: &mockAuthPoown{success: true}, AccountBalanceHelper: &mockAccountBalanceHelperNRFail{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -1173,6 +1184,7 @@ func TestNodeRegistration_Validate(t *testing.T) { AuthPoown: &mockAuthPoown{success: true}, AccountBalanceHelper: &mockAccountBalanceHelperNRSuccess{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -1188,6 +1200,7 @@ func TestNodeRegistration_Validate(t *testing.T) { AuthPoown: &mockAuthPoown{success: true}, AccountBalanceHelper: &mockAccountBalanceHelperNRSuccess{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -1203,6 +1216,7 @@ func TestNodeRegistration_Validate(t *testing.T) { AuthPoown: &mockAuthPoown{success: true}, AccountBalanceHelper: &mockAccountBalanceHelperNRSuccess{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: false, }, { @@ -1218,6 +1232,7 @@ func TestNodeRegistration_Validate(t *testing.T) { AuthPoown: &mockAuthPoown{success: true}, AccountBalanceHelper: &mockAccountBalanceHelperNRSuccess{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -1233,6 +1248,7 @@ func TestNodeRegistration_Validate(t *testing.T) { AuthPoown: &mockAuthPoown{success: true}, AccountBalanceHelper: &mockAccountBalanceHelperNRSuccess{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: false, }, } @@ -1249,7 +1265,7 @@ func TestNodeRegistration_Validate(t *testing.T) { AuthPoown: tt.fields.AuthPoown, AccountBalanceHelper: tt.fields.AccountBalanceHelper, } - if err := tx.Validate(false); (err != nil) != tt.wantErr { + if err := tx.Validate(tt.args.dbTx, tt.args.checkOnSpendableBalance); (err != nil) != tt.wantErr { t.Errorf("NodeRegistration.Validate() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/common/transaction/removeAccountDataset.go b/common/transaction/removeAccountDataset.go index 71b60dd2e..af39bc36c 100644 --- a/common/transaction/removeAccountDataset.go +++ b/common/transaction/removeAccountDataset.go @@ -110,7 +110,7 @@ That specs: - Check existing Account Dataset - Check Spendable Balance sender */ -func (tx *RemoveAccountDataset) Validate(dbTx bool) error { +func (tx *RemoveAccountDataset) Validate(dbTx, checkOnSpendableBalance bool) error { var ( accountDataset model.AccountDataset err error @@ -149,8 +149,12 @@ func (tx *RemoveAccountDataset) Validate(dbTx bool) error { if !accountDataset.GetIsActive() { return blocker.NewBlocker(blocker.ValidationErr, "AccountDatasetAlreadyRemoved") } - - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee) + } if err != nil { if err != sql.ErrNoRows { return err @@ -273,7 +277,7 @@ That specs: - Check existing Account Dataset - Check Spendable Balance sender */ -func (tx *RemoveAccountDataset) EscrowValidate(dbTx bool) error { +func (tx *RemoveAccountDataset) EscrowValidate(dbTx, checkOnSpendableBalance bool) error { var ( err error enough bool @@ -286,12 +290,17 @@ func (tx *RemoveAccountDataset) EscrowValidate(dbTx bool) error { return blocker.NewBlocker(blocker.ValidationErr, "TimeoutLimitExceeded") } - err = tx.Validate(dbTx) + err = tx.Validate(dbTx, checkOnSpendableBalance) if err != nil { return err } + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) if err != nil { if err != sql.ErrNoRows { return err diff --git a/common/transaction/removeAccountDataset_test.go b/common/transaction/removeAccountDataset_test.go index bbdf7bb64..cd93a896f 100644 --- a/common/transaction/removeAccountDataset_test.go +++ b/common/transaction/removeAccountDataset_test.go @@ -383,6 +383,10 @@ func (*executorRemoveAccountDatasetValidateFail) ExecuteSelectRow(qStr string, _ func TestRemoveAccountDataset_Validate(t *testing.T) { mockRemoveAccountDatasetTransactionBody, _ := GetFixturesForRemoveAccountDataset() + type args struct { + dbTx bool + checkOnSpendableBalance bool + } type fields struct { Body *model.RemoveAccountDatasetTransactionBody @@ -397,6 +401,7 @@ func TestRemoveAccountDataset_Validate(t *testing.T) { tests := []struct { name string fields fields + args args wantErr bool }{ { @@ -410,6 +415,7 @@ func TestRemoveAccountDataset_Validate(t *testing.T) { QueryExecutor: &executorRemoveAccountDatasetValidateSuccess{}, AccountBalanceHelper: &mockAccountBalanceHelperSuccess{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: false, }, { @@ -423,6 +429,7 @@ func TestRemoveAccountDataset_Validate(t *testing.T) { QueryExecutor: &executorRemoveAccountDatasetValidateSuccess{}, AccountBalanceHelper: &mockAccountBalanceHelperFail{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -435,6 +442,7 @@ func TestRemoveAccountDataset_Validate(t *testing.T) { AccountDatasetQuery: query.NewAccountDatasetsQuery(), QueryExecutor: &executorRemoveAccountDatasetValidateFail{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, } @@ -450,7 +458,7 @@ func TestRemoveAccountDataset_Validate(t *testing.T) { QueryExecutor: tt.fields.QueryExecutor, AccountBalanceHelper: tt.fields.AccountBalanceHelper, } - if err := tx.Validate(false); (err != nil) != tt.wantErr { + if err := tx.Validate(tt.args.dbTx, tt.args.checkOnSpendableBalance); (err != nil) != tt.wantErr { t.Errorf("RemoveAccountDataset.Validate() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/common/transaction/removeNodeRegistration.go b/common/transaction/removeNodeRegistration.go index 35b488e56..9a55c1fb6 100644 --- a/common/transaction/removeNodeRegistration.go +++ b/common/transaction/removeNodeRegistration.go @@ -170,7 +170,7 @@ func (tx *RemoveNodeRegistration) UndoApplyUnconfirmed() error { } // Validate validate node registration transaction and tx body -func (tx *RemoveNodeRegistration) Validate(dbTx bool) error { +func (tx *RemoveNodeRegistration) Validate(dbTx, checkOnSpendableBalance bool) error { var ( nodeReg model.NodeRegistration err error @@ -199,7 +199,12 @@ func (tx *RemoveNodeRegistration) Validate(dbTx bool) error { return blocker.NewBlocker(blocker.AuthErr, "NodeAlreadyDeleted") } // check existing & balance account sender - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee) + } if err != nil { if err != sql.ErrNoRows { return err @@ -279,7 +284,7 @@ func (tx *RemoveNodeRegistration) Escrowable() (EscrowTypeAction, bool) { } // EscrowValidate validate node registration transaction and tx body -func (tx *RemoveNodeRegistration) EscrowValidate(dbTx bool) error { +func (tx *RemoveNodeRegistration) EscrowValidate(dbTx, checkOnSpendableBalance bool) error { var ( err error enough bool @@ -291,12 +296,16 @@ func (tx *RemoveNodeRegistration) EscrowValidate(dbTx bool) error { return blocker.NewBlocker(blocker.ValidationErr, "TimeoutLimitExceeded") } - err = tx.Validate(dbTx) + err = tx.Validate(dbTx, checkOnSpendableBalance) if err != nil { return err } - - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + // checkOnSpendableBalance will check to the spendable balance of the sender otherwise will check the actual balance + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } if err != nil { if err != sql.ErrNoRows { return err diff --git a/common/transaction/removeNodeRegistration_test.go b/common/transaction/removeNodeRegistration_test.go index 6c133d1af..cbefb17fa 100644 --- a/common/transaction/removeNodeRegistration_test.go +++ b/common/transaction/removeNodeRegistration_test.go @@ -377,9 +377,14 @@ func TestRemoveNodeRegistration_Validate(t *testing.T) { QueryExecutor query.ExecutorInterface AccountBalanceHelper AccountBalanceHelperInterface } + type args struct { + dbTx bool + checkOnSpendableBalance bool + } tests := []struct { name string fields fields + args args wantErr bool }{ { @@ -393,6 +398,7 @@ func TestRemoveNodeRegistration_Validate(t *testing.T) { NodeRegistrationQuery: query.NewNodeRegistrationQuery(), AccountBalanceHelper: &mockAccountBalanceHelperSuccess{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: false, }, { @@ -405,6 +411,7 @@ func TestRemoveNodeRegistration_Validate(t *testing.T) { QueryExecutor: &mockExecutorValidateRemoveNodeRegistrationFailGetRNode{}, NodeRegistrationQuery: query.NewNodeRegistrationQuery(), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -417,6 +424,7 @@ func TestRemoveNodeRegistration_Validate(t *testing.T) { QueryExecutor: &mockExecutorValidateRemoveNodeRegistrationSuccess{}, NodeRegistrationQuery: query.NewNodeRegistrationQuery(), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -429,6 +437,7 @@ func TestRemoveNodeRegistration_Validate(t *testing.T) { QueryExecutor: &mockExecutorValidateRemoveNodeRegistrationFailNodeAlreadyDeleted{}, NodeRegistrationQuery: query.NewNodeRegistrationQuery(), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -442,6 +451,7 @@ func TestRemoveNodeRegistration_Validate(t *testing.T) { NodeRegistrationQuery: query.NewNodeRegistrationQuery(), AccountBalanceHelper: &mockAccountBalanceHelperFail{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -455,6 +465,7 @@ func TestRemoveNodeRegistration_Validate(t *testing.T) { NodeRegistrationQuery: query.NewNodeRegistrationQuery(), AccountBalanceHelper: &mockAccountBalanceHelperFail{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, } @@ -469,7 +480,7 @@ func TestRemoveNodeRegistration_Validate(t *testing.T) { QueryExecutor: tt.fields.QueryExecutor, AccountBalanceHelper: tt.fields.AccountBalanceHelper, } - if err := tx.Validate(false); (err != nil) != tt.wantErr { + if err := tx.Validate(tt.args.dbTx, tt.args.checkOnSpendableBalance); (err != nil) != tt.wantErr { t.Errorf("RemoveNodeRegistration.Validate() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/common/transaction/sendMoney.go b/common/transaction/sendMoney.go index 64a3fc661..9bedcddc8 100644 --- a/common/transaction/sendMoney.go +++ b/common/transaction/sendMoney.go @@ -111,7 +111,7 @@ That specs: - If Genesis, sender and recipient allowed not exists, - If Not Genesis, sender and recipient must be exists, `sender.spendable_balance` must bigger than amount */ -func (tx *SendMoney) Validate(dbTx bool) error { +func (tx *SendMoney) Validate(dbTx, checkOnSpendableBalance bool) error { var ( err error ) @@ -128,10 +128,14 @@ func (tx *SendMoney) Validate(dbTx bool) error { if tx.SenderAddress == nil { return errors.New("transaction must have a valid sender account id") } - - enough, e := tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Body.GetAmount()+tx.Fee) - if e != nil { - if e != sql.ErrNoRows { + var enough bool + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Body.GetAmount()+tx.Fee) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Body.GetAmount()+tx.Fee) + } + if err != nil { + if err != sql.ErrNoRows { return err } return blocker.NewBlocker(blocker.ValidationErr, "AccountBalanceNotFound") @@ -223,7 +227,7 @@ func (tx *SendMoney) Escrowable() (EscrowTypeAction, bool) { } // EscrowValidate special validation for escrow's transaction -func (tx *SendMoney) EscrowValidate(dbTx bool) error { +func (tx *SendMoney) EscrowValidate(dbTx, checkOnSpendableBalance bool) error { var ( err error enough bool @@ -239,11 +243,16 @@ func (tx *SendMoney) EscrowValidate(dbTx bool) error { return blocker.NewBlocker(blocker.ValidationErr, "TimeoutLimitExceeded") } - err = tx.Validate(dbTx) + err = tx.Validate(dbTx, checkOnSpendableBalance) if err != nil { return err } - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Body.GetAmount()+tx.Fee+tx.Escrow.GetCommission()) + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Body.GetAmount()+tx.Fee+tx.Escrow.GetCommission()) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Body.GetAmount()+tx.Fee+tx.Escrow.GetCommission()) + } + if err != nil { if err != sql.ErrNoRows { return err diff --git a/common/transaction/sendMoney_test.go b/common/transaction/sendMoney_test.go index c7239d3e5..1d1085c48 100644 --- a/common/transaction/sendMoney_test.go +++ b/common/transaction/sendMoney_test.go @@ -150,6 +150,10 @@ func (*mockAccountBalanceValidateSendMoneySuccess) Scan(accountBalance *model.Ac } func TestSendMoney_Validate(t *testing.T) { + type args struct { + dbTx bool + checkOnSpendableBalance bool + } type fields struct { Body *model.SendMoneyTransactionBody SenderAddress []byte @@ -163,6 +167,7 @@ func TestSendMoney_Validate(t *testing.T) { tests := []struct { name string fields fields + args args wantErr bool }{ { @@ -173,6 +178,7 @@ func TestSendMoney_Validate(t *testing.T) { }, AccountBalanceHelper: &mockAccountBalanceHelperFail{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -184,6 +190,7 @@ func TestSendMoney_Validate(t *testing.T) { RecipientAddress: nil, RecipientAccountType: 0, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -199,6 +206,7 @@ func TestSendMoney_Validate(t *testing.T) { RecipientAccountType: 0, RecipientAddress: recipientAddress1, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -214,6 +222,7 @@ func TestSendMoney_Validate(t *testing.T) { RecipientAccountType: 0, RecipientAddress: recipientAddress1, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -230,6 +239,7 @@ func TestSendMoney_Validate(t *testing.T) { QueryExecutor: &mockQueryExecutorValidateSendMoneyHasEscrow{}, AccountBalanceHelper: &mockAccountBalanceHelperSuccess{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: false, }, } @@ -243,7 +253,7 @@ func TestSendMoney_Validate(t *testing.T) { QueryExecutor: tt.fields.QueryExecutor, AccountBalanceHelper: tt.fields.AccountBalanceHelper, } - if err := tx.Validate(false); (err != nil) != tt.wantErr { + if err := tx.Validate(tt.args.dbTx, tt.args.checkOnSpendableBalance); (err != nil) != tt.wantErr { t.Errorf("SendMoney.Validate() error = %v, wantErr %v", err, tt.wantErr) } if err := mock.ExpectationsWereMet(); err != nil { @@ -873,7 +883,8 @@ func TestSendMoney_EscrowValidate(t *testing.T) { } type args struct { - dbTx bool + dbTx bool + checkOnSpendableBalance bool } tests := []struct { name string @@ -889,6 +900,7 @@ func TestSendMoney_EscrowValidate(t *testing.T) { }, AccountBalanceHelper: &mockAccountBalanceHelperFail{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -901,6 +913,7 @@ func TestSendMoney_EscrowValidate(t *testing.T) { Commission: 1, }, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -914,6 +927,7 @@ func TestSendMoney_EscrowValidate(t *testing.T) { ApproverAddress: senderAddress2, }, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -930,6 +944,7 @@ func TestSendMoney_EscrowValidate(t *testing.T) { QueryExecutor: &mockExecutorEscrowValidateInvalidBlockHeight{}, BlockQuery: &mockBlockQueryInvalidBlockHeight{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -947,6 +962,7 @@ func TestSendMoney_EscrowValidate(t *testing.T) { QueryExecutor: &mockExecutorEscrowValidateValid{}, BlockQuery: &mockBlockQueryValidBlockHeight{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -969,6 +985,7 @@ func TestSendMoney_EscrowValidate(t *testing.T) { AccountBalanceHelper: &mockAccountBalanceHelperSuccess{}, AccountDatasetQuery: query.NewAccountDatasetsQuery(), }, + args: args{dbTx: false, checkOnSpendableBalance: true}, }, } for _, tt := range tests { @@ -986,7 +1003,7 @@ func TestSendMoney_EscrowValidate(t *testing.T) { BlockQuery: tt.fields.BlockQuery, AccountBalanceHelper: tt.fields.AccountBalanceHelper, } - if err := tx.EscrowValidate(tt.args.dbTx); (err != nil) != tt.wantErr { + if err := tx.EscrowValidate(tt.args.dbTx, tt.args.checkOnSpendableBalance); (err != nil) != tt.wantErr { t.Errorf("EscrowValidate() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/common/transaction/setupAccountDataset.go b/common/transaction/setupAccountDataset.go index db386c9a7..db8764d1e 100644 --- a/common/transaction/setupAccountDataset.go +++ b/common/transaction/setupAccountDataset.go @@ -108,7 +108,7 @@ That specs: - Checking the expiration time - Checking Spendable Balance sender */ -func (tx *SetupAccountDataset) Validate(dbTx bool) error { +func (tx *SetupAccountDataset) Validate(dbTx, checkOnSpendableBalance bool) error { var ( accountDataset model.AccountDataset row *sql.Row @@ -148,10 +148,16 @@ func (tx *SetupAccountDataset) Validate(dbTx bool) error { } // check account balance sender - enough, e := tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) - if e != nil { - if e != sql.ErrNoRows { - return blocker.NewBlocker(blocker.ValidationErr, e.Error()) + var enough bool + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee) + } + + if err != nil { + if err != sql.ErrNoRows { + return blocker.NewBlocker(blocker.ValidationErr, err.Error()) } return blocker.NewBlocker(blocker.ValidationErr, "AccountBalanceNotFound") } @@ -268,7 +274,7 @@ func (tx *SetupAccountDataset) Escrowable() (EscrowTypeAction, bool) { /* EscrowValidate is func that for validating to Transaction SetupAccountDataset type. */ -func (tx *SetupAccountDataset) EscrowValidate(dbTx bool) error { +func (tx *SetupAccountDataset) EscrowValidate(dbTx, checkOnSpendableBalance bool) error { var ( err error enough bool @@ -281,12 +287,16 @@ func (tx *SetupAccountDataset) EscrowValidate(dbTx bool) error { return blocker.NewBlocker(blocker.ValidationErr, "TimeoutLimitExceeded") } - err = tx.Validate(dbTx) + err = tx.Validate(dbTx, checkOnSpendableBalance) if err != nil { return err } // Need to check also spendable balance has enough again: plus commission - enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + if checkOnSpendableBalance { + enough, err = tx.AccountBalanceHelper.HasEnoughSpendableBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } else { + enough, err = tx.AccountBalanceHelper.HasEnoughBalance(dbTx, tx.SenderAddress, tx.Fee+tx.Escrow.GetCommission()) + } if err != nil { if err != sql.ErrNoRows { return blocker.NewBlocker(blocker.ValidationErr, err.Error()) diff --git a/common/transaction/setupAccountDataset_test.go b/common/transaction/setupAccountDataset_test.go index 13cc1cfdb..edc57d66c 100644 --- a/common/transaction/setupAccountDataset_test.go +++ b/common/transaction/setupAccountDataset_test.go @@ -390,9 +390,14 @@ func TestSetupAccountDataset_Validate(t *testing.T) { QueryExecutor query.ExecutorInterface AccountBalanceHelper AccountBalanceHelperInterface } + type args struct { + dbTx bool + checkOnSpendableBalance bool + } tests := []struct { name string fields fields + args args wantErr bool }{ { @@ -404,6 +409,7 @@ func TestSetupAccountDataset_Validate(t *testing.T) { QueryExecutor: &executorSetupAccountDatasetValidateSuccess{}, AccountBalanceHelper: &mockAccountBalanceHelperFail{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -419,6 +425,7 @@ func TestSetupAccountDataset_Validate(t *testing.T) { AccountDatasetQuery: query.NewAccountDatasetsQuery(), QueryExecutor: &executorSetupAccountDatasetValidateAlreadyExists{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, wantErr: true, }, { @@ -435,6 +442,7 @@ func TestSetupAccountDataset_Validate(t *testing.T) { QueryExecutor: &executorSetupAccountDatasetValidateSuccess{}, AccountBalanceHelper: &mockAccountBalanceHelperSuccess{}, }, + args: args{dbTx: false, checkOnSpendableBalance: true}, }, } for _, tt := range tests { @@ -449,7 +457,7 @@ func TestSetupAccountDataset_Validate(t *testing.T) { QueryExecutor: tt.fields.QueryExecutor, AccountBalanceHelper: tt.fields.AccountBalanceHelper, } - if err := tx.Validate(false); (err != nil) != tt.wantErr { + if err := tx.Validate(tt.args.dbTx, tt.args.checkOnSpendableBalance); (err != nil) != tt.wantErr { t.Errorf("SetupAccountDataset.Validate() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/common/transaction/transaction.go b/common/transaction/transaction.go index e4475c1d3..bc10fd9ee 100644 --- a/common/transaction/transaction.go +++ b/common/transaction/transaction.go @@ -22,7 +22,7 @@ type ( ApplyUnconfirmed() error UndoApplyUnconfirmed() error // Validate dbTx specify whether validation should read from transaction state or db state - Validate(dbTx bool) error + Validate(dbTx, checkOnSpendableBalance bool) error GetMinimumFee() (int64, error) GetAmount() int64 GetSize() (uint32, error) diff --git a/common/transaction/transactionGeneral.go b/common/transaction/transactionGeneral.go index e5c7eecc2..47d3fa3d5 100644 --- a/common/transaction/transactionGeneral.go +++ b/common/transaction/transactionGeneral.go @@ -55,7 +55,8 @@ type ( multisigInfo *model.MultiSignatureInfo, senderAddress, unsignedTxBytes []byte, blockHeight uint32, - dbTx bool, + dbTx, + checkOnSpendableBalance bool, ) error ValidateMultisignatureInfo(info *model.MultiSignatureInfo) error ValidateSignatureInfo( @@ -494,7 +495,8 @@ func (mtu *MultisigTransactionUtil) ValidatePendingTransactionBytes( multisigInfo *model.MultiSignatureInfo, senderAddress, unsignedTxBytes []byte, blockHeight uint32, - dbTx bool, + dbTx, + checkOnSpendableBalance bool, ) error { var ( pendingTx model.PendingTransaction @@ -540,7 +542,7 @@ func (mtu *MultisigTransactionUtil) ValidatePendingTransactionBytes( ) } - err = innerTa.Validate(dbTx) + err = innerTa.Validate(dbTx, checkOnSpendableBalance) if err != nil { return blocker.NewBlocker( blocker.ValidationErr, diff --git a/core/service/blockMainService.go b/core/service/blockMainService.go index 1882d1ff5..0fa8ae887 100644 --- a/core/service/blockMainService.go +++ b/core/service/blockMainService.go @@ -469,7 +469,7 @@ func (bs *BlockService) PushBlock(previousBlock, block *model.Block, broadcast, } if block.Height > 0 { - err = bs.TransactionCoreService.ValidateTransaction(txType, true) + err = bs.TransactionCoreService.ValidateTransaction(txType, true, false) if err != nil { bs.queryAndCacheRollbackProcess("") return err diff --git a/core/service/blockMainService_test.go b/core/service/blockMainService_test.go index 36704712b..f6f71c9fe 100644 --- a/core/service/blockMainService_test.go +++ b/core/service/blockMainService_test.go @@ -286,7 +286,7 @@ var ( func (*mockTypeAction) ApplyConfirmed(int64) error { return nil } -func (*mockTypeAction) Validate(bool) error { +func (*mockTypeAction) Validate(bool, bool) error { return nil } func (*mockTypeAction) GetAmount() int64 { diff --git a/core/service/blockSpineService_test.go b/core/service/blockSpineService_test.go index 7009a15a9..2da58af19 100644 --- a/core/service/blockSpineService_test.go +++ b/core/service/blockSpineService_test.go @@ -181,7 +181,7 @@ func (*mockSpineNodeRegistrationServiceFail) GetBlockHeightToBuildScrambleNodes( func (*mockSpineTypeAction) ApplyConfirmed(int64) error { return nil } -func (*mockSpineTypeAction) Validate(bool) error { +func (*mockSpineTypeAction) Validate(bool, bool) error { return nil } func (*mockSpineTypeAction) GetAmount() int64 { diff --git a/core/service/mempoolCoreService.go b/core/service/mempoolCoreService.go index 73622a453..3b673d96d 100644 --- a/core/service/mempoolCoreService.go +++ b/core/service/mempoolCoreService.go @@ -279,7 +279,7 @@ func (mps *MempoolService) ValidateMempoolTransaction(mpTx *model.Transaction) e return blocker.NewBlocker(blocker.ValidationErr, errVal.Error()) } - err = mps.TransactionCoreService.ValidateTransaction(txType, false) + err = mps.TransactionCoreService.ValidateTransaction(txType, false, true) if err != nil { return blocker.NewBlocker(blocker.ValidationErr, err.Error()) } diff --git a/core/service/transactionCoreService.go b/core/service/transactionCoreService.go index c33fc9902..4e8734f50 100644 --- a/core/service/transactionCoreService.go +++ b/core/service/transactionCoreService.go @@ -16,7 +16,7 @@ type ( TransactionCoreServiceInterface interface { GetTransactionsByIds(transactionIds []int64) ([]*model.Transaction, error) GetTransactionsByBlockID(blockID int64) ([]*model.Transaction, error) - ValidateTransaction(txAction transaction.TypeAction, useTX bool) error + ValidateTransaction(txAction transaction.TypeAction, useTX, checkOnSpendableBalance bool) error ApplyUnconfirmedTransaction(txAction transaction.TypeAction) error UndoApplyUnconfirmedTransaction(txAction transaction.TypeAction) error ApplyConfirmedTransaction(txAction transaction.TypeAction, blockTimestamp int64) error @@ -307,13 +307,13 @@ func (tg *TransactionCoreService) CompletePassedLiquidPayment(block *model.Block return nil } -func (tg *TransactionCoreService) ValidateTransaction(txAction transaction.TypeAction, useTX bool) error { +func (tg *TransactionCoreService) ValidateTransaction(txAction transaction.TypeAction, useTX, checkOnSpendableBalance bool) error { escrowAction, ok := txAction.Escrowable() switch ok { case true: - return escrowAction.EscrowValidate(useTX) + return escrowAction.EscrowValidate(useTX, checkOnSpendableBalance) default: - return txAction.Validate(useTX) + return txAction.Validate(useTX, checkOnSpendableBalance) } } diff --git a/core/service/transactionCoreService_test.go b/core/service/transactionCoreService_test.go index 9c99421b8..511d2f7b5 100644 --- a/core/service/transactionCoreService_test.go +++ b/core/service/transactionCoreService_test.go @@ -716,7 +716,7 @@ type mockValidateTransactionEscrowValidate struct { transaction.EscrowTypeAction } -func (*mockValidateTransactionEscrowValidate) EscrowValidate(dbTx bool) error { +func (*mockValidateTransactionEscrowValidate) EscrowValidate(dbTx, checkOnSpendableBalance bool) error { return nil } @@ -736,7 +736,7 @@ func (*mockValidateTransactionEscrowableFalse) Escrowable() (transaction.EscrowT return nil, false } -func (*mockValidateTransactionEscrowableFalse) Validate(dbTx bool) error { +func (*mockValidateTransactionEscrowableFalse) Validate(dbTx, checkOnSpendableBalance bool) error { return nil } @@ -747,8 +747,9 @@ func TestTransactionCoreService_ValidateTransaction(t *testing.T) { QueryExecutor query.ExecutorInterface } type args struct { - txAction transaction.TypeAction - useTX bool + txAction transaction.TypeAction + useTX bool + checkOnSpendableBalance bool } tests := []struct { name string @@ -760,14 +761,16 @@ func TestTransactionCoreService_ValidateTransaction(t *testing.T) { { name: "ValidateTransaction:EscrowableTrue", args: args{ - txAction: &mockValidateTransactionEscrowableTrue{}, + txAction: &mockValidateTransactionEscrowableTrue{}, + checkOnSpendableBalance: true, }, wantErr: false, }, { name: "ValidateTransaction:EscrowableFalse", args: args{ - txAction: &mockValidateTransactionEscrowableFalse{}, + txAction: &mockValidateTransactionEscrowableFalse{}, + checkOnSpendableBalance: true, }, wantErr: false, }, @@ -779,7 +782,7 @@ func TestTransactionCoreService_ValidateTransaction(t *testing.T) { EscrowTransactionQuery: tt.fields.EscrowTransactionQuery, QueryExecutor: tt.fields.QueryExecutor, } - if err := tg.ValidateTransaction(tt.args.txAction, tt.args.useTX); (err != nil) != tt.wantErr { + if err := tg.ValidateTransaction(tt.args.txAction, tt.args.useTX, tt.args.checkOnSpendableBalance); (err != nil) != tt.wantErr { t.Errorf("TransactionCoreService.ValidateTransaction() error = %v, wantErr %v", err, tt.wantErr) } })