Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kaspawallet: implement fee calcs, centralize constant and logic #2107

Draft
wants to merge 5 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/kaspawallet/daemon/pb/kaspawalletd.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 1 addition & 4 deletions cmd/kaspawallet/daemon/server/create_unsigned_transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ import (
"time"
)

// TODO: Implement a better fee estimation mechanism
const feePerInput = 10000

func (s *server) CreateUnsignedTransactions(_ context.Context, request *pb.CreateUnsignedTransactionsRequest) (
*pb.CreateUnsignedTransactionsResponse, error) {
s.lock.Lock()
Expand Down Expand Up @@ -52,7 +49,7 @@ func (s *server) createUnsignedTransactions(address string, amount uint64, fromA
fromAddresses = append(fromAddresses, fromAddress)
}

selectedUTXOs, changeSompi, err := s.selectUTXOs(amount, feePerInput, fromAddresses)
selectedUTXOs, changeSompi, err := s.selectUTXOs(amount, libkaspawallet.FeePerInput, fromAddresses)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/kaspawallet/daemon/server/external_spendable_utxos.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (s *server) selectExternalSpendableUTXOs(externalUTXOs *appmessage.GetUTXOs
func isExternalUTXOSpendable(entry *appmessage.UTXOsByAddressesEntry, virtualDAAScore uint64, coinbaseMaturity uint64) bool {
if !entry.UTXOEntry.IsCoinbase {
return true
} else if entry.UTXOEntry.Amount <= feePerInput {
} else if entry.UTXOEntry.Amount <= libkaspawallet.FeePerInput {
return false
}
return entry.UTXOEntry.BlockDAAScore+coinbaseMaturity < virtualDAAScore
Expand Down
6 changes: 3 additions & 3 deletions cmd/kaspawallet/daemon/server/split_transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func (s *server) mergeTransaction(
DerivationPath: s.walletAddressPath(changeWalletAddress),
}
totalValue += output.Value
totalValue -= feePerInput
totalValue -= libkaspawallet.FeePerInput
}

if totalValue < sentValue {
Expand Down Expand Up @@ -200,7 +200,7 @@ func (s *server) createSplitTransaction(transaction *serialization.PartiallySign
})

totalSompi += selectedUTXOs[i-startIndex].UTXOEntry.Amount()
totalSompi -= feePerInput
totalSompi -= libkaspawallet.FeePerInput
}
unsignedTransactionBytes, err := libkaspawallet.CreateUnsignedTransaction(s.keysFile.ExtendedPublicKeys,
s.keysFile.MinimumSignatures,
Expand Down Expand Up @@ -265,7 +265,7 @@ func (s *server) moreUTXOsForMergeTransaction(alreadySelectedUTXOs []*libkaspawa
Outpoint: utxo.Outpoint,
UTXOEntry: utxo.UTXOEntry,
DerivationPath: s.walletAddressPath(utxo.address)})
totalValueAdded += utxo.UTXOEntry.Amount() - feePerInput
totalValueAdded += utxo.UTXOEntry.Amount() - libkaspawallet.FeePerInput
if totalValueAdded >= requiredAmount {
break
}
Expand Down
54 changes: 54 additions & 0 deletions cmd/kaspawallet/libkaspawallet/fees.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package libkaspawallet

import (
"github.com/pkg/errors"

"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
)

// TODO: Implement a better fee construction and estimation mechanism.

//FeePerInput is the current constant per input to pay for transactions.
const FeePerInput uint64 = 10000

//CalculateFees calculates the totalFee for a slice of transactions
func CalculateFees(transactions []*externalapi.DomainTransaction) (uint64, error) {

var totalFee uint64

for _, tx := range transactions {
fee, err := CalculateFee(tx)
if err != nil {
return 0, err
}
totalFee += fee
}

return totalFee, nil
}

//CalculateFee calculates fee for a transaction
func CalculateFee(transaction *externalapi.DomainTransaction) (uint64, error) {

var totalInputAmount uint64
var totalOutputAmount uint64

for _, input := range transaction.Inputs {
totalInputAmount += input.UTXOEntry.Amount()
}
for _, output := range transaction.Outputs {
totalOutputAmount += output.Value
}

return CalculateFeeFromInputAndOutputTotalAmounts(totalInputAmount, totalOutputAmount)
}

//CalculateFeeFromInputAndOutputTotalAmounts calculates tx fee form total input and output amounts
//this func is more performant then CalculateFee if total input and output amounts are knowen.
func CalculateFeeFromInputAndOutputTotalAmounts(totalInputAmount uint64, totalOutputAmount uint64) (uint64, error) {
if totalInputAmount > totalOutputAmount {
return 0, errors.Errorf("The input amount may not exceed the output amount, Cannot Calculate negative fees")
}

return totalInputAmount - totalOutputAmount, nil
}
18 changes: 12 additions & 6 deletions cmd/kaspawallet/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package main
import (
"encoding/hex"
"fmt"
"io/ioutil"
"strings"

"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet/serialization"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
"github.com/pkg/errors"
"io/ioutil"
"strings"
)

func parse(conf *parseConfig) error {
Expand Down Expand Up @@ -42,7 +44,6 @@ func parse(conf *parseConfig) error {

fmt.Printf("Transaction #%d ID: \t%s\n", i+1, consensushashing.TransactionID(partiallySignedTransaction.Tx))
fmt.Println()

allInputSompi := uint64(0)
for index, input := range partiallySignedTransaction.Tx.Inputs {
partiallySignedInput := partiallySignedTransaction.PartiallySignedInputs[index]
Expand All @@ -51,7 +52,6 @@ func parse(conf *parseConfig) error {
fmt.Printf("Input %d: \tOutpoint: %s:%d \tAmount: %.2f Kaspa\n", index, input.PreviousOutpoint.TransactionID,
input.PreviousOutpoint.Index, float64(partiallySignedInput.PrevOutput.Value)/float64(constants.SompiPerKaspa))
}

allInputSompi += partiallySignedInput.PrevOutput.Value
}
if conf.Verbose {
Expand All @@ -73,12 +73,18 @@ func parse(conf *parseConfig) error {

fmt.Printf("Output %d: \tRecipient: %s \tAmount: %.2f Kaspa\n",
index, addressString, float64(output.Value)/float64(constants.SompiPerKaspa))

allOutputSompi += output.Value

}
fmt.Println()

fmt.Printf("Fee:\t%d Sompi\n\n", allInputSompi-allOutputSompi)
fee, err := libkaspawallet.CalculateFeeFromInputAndOutputTotalAmounts(allInputSompi, allOutputSompi)
if err != nil {
return err
}

fmt.Printf("Fee:\t%d Sompi\n\n", fee)

}

return nil
Expand Down
9 changes: 3 additions & 6 deletions cmd/kaspawallet/sweep.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ import (
"github.com/pkg/errors"
)

const feePerInput = 10000

func sweep(conf *sweepConfig) error {

privateKeyBytes, err := hex.DecodeString(conf.PrivateKey)
Expand Down Expand Up @@ -89,7 +87,7 @@ func sweep(conf *sweepConfig) error {
return err
}

splitTransactions, err := createSplitTransactionsWithSchnorrPrivteKey(conf.NetParams(), UTXOs, toAddress, feePerInput)
splitTransactions, err := createSplitTransactionsWithSchnorrPrivteKey(conf.NetParams(), UTXOs, toAddress)
if err != nil {
return err
}
Expand Down Expand Up @@ -141,8 +139,7 @@ func newDummyTransaction() *externalapi.DomainTransaction {
func createSplitTransactionsWithSchnorrPrivteKey(
params *dagconfig.Params,
selectedUTXOs []*libkaspawallet.UTXO,
toAddress util.Address,
feePerInput int) ([]*externalapi.DomainTransaction, error) {
toAddress util.Address) ([]*externalapi.DomainTransaction, error) {

var splitTransactions []*externalapi.DomainTransaction

Expand Down Expand Up @@ -180,7 +177,7 @@ func createSplitTransactionsWithSchnorrPrivteKey(
)

currentTx.Outputs[0] = &externalapi.DomainTransactionOutput{
Value: totalSplitAmount - uint64(len(currentTx.Inputs)*feePerInput),
Value: totalSplitAmount - uint64(len(currentTx.Inputs)*int(libkaspawallet.FeePerInput)),
ScriptPublicKey: scriptPublicKey,
}

Expand Down