Compare commits

..

2 Commits

Author SHA1 Message Date
Ori Newman
af93d5fdfe Add failed broadcast transactions on send error` 2024-09-18 08:15:08 +03:00
Ori Newman
89c932dec1 Add checkTransactionFeeRate 2024-09-18 08:04:10 +03:00
9 changed files with 63 additions and 11 deletions

View File

@@ -8,6 +8,7 @@ import (
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/client"
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/server"
"github.com/pkg/errors"
)
@@ -37,7 +38,7 @@ func broadcast(conf *broadcastConfig) error {
transactionsHex = strings.TrimSpace(string(transactionHexBytes))
}
transactions, err := decodeTransactionsFromHex(transactionsHex)
transactions, err := server.DecodeTransactionsFromHex(transactionsHex)
if err != nil {
return err
}

View File

@@ -8,6 +8,7 @@ import (
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/client"
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/server"
"github.com/pkg/errors"
)
@@ -37,7 +38,7 @@ func broadcastReplacement(conf *broadcastConfig) error {
transactionsHex = strings.TrimSpace(string(transactionHexBytes))
}
transactions, err := decodeTransactionsFromHex(transactionsHex)
transactions, err := server.DecodeTransactionsFromHex(transactionsHex)
if err != nil {
return err
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/client"
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/server"
)
func bumpFeeUnsigned(conf *bumpFeeUnsignedConfig) error {
@@ -51,7 +52,7 @@ func bumpFeeUnsigned(conf *bumpFeeUnsignedConfig) error {
}
fmt.Fprintln(os.Stderr, "Created unsigned transaction")
fmt.Println(encodeTransactionsToHex(response.Transactions))
fmt.Println(server.EncodeTransactionsToHex(response.Transactions))
return nil
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/client"
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/server"
"github.com/kaspanet/kaspad/cmd/kaspawallet/utils"
)
@@ -59,7 +60,7 @@ func createUnsignedTransaction(conf *createUnsignedTransactionConfig) error {
}
fmt.Fprintln(os.Stderr, "Created unsigned transaction")
fmt.Println(encodeTransactionsToHex(response.UnsignedTransactions))
fmt.Println(server.EncodeTransactionsToHex(response.UnsignedTransactions))
return nil
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
"github.com/pkg/errors"
)
func (s *server) Send(_ context.Context, request *pb.SendRequest) (*pb.SendResponse, error) {
@@ -24,7 +25,7 @@ func (s *server) Send(_ context.Context, request *pb.SendRequest) (*pb.SendRespo
txIDs, err := s.broadcast(signedTransactions, false)
if err != nil {
return nil, err
return nil, errors.Wrapf(err, "error broadcasting transactions %s", EncodeTransactionsToHex(signedTransactions))
}
return &pb.SendResponse{TxIDs: txIDs, SignedTransactions: signedTransactions}, nil

View File

@@ -23,6 +23,7 @@ import (
// paying to the original transaction's payee.
func (s *server) maybeAutoCompoundTransaction(transaction *serialization.PartiallySignedTransaction, toAddress util.Address,
changeAddress util.Address, changeWalletAddress *walletAddress, feeRate float64, maxFee uint64) ([][]byte, error) {
splitTransactions, err := s.maybeSplitAndMergeTransaction(transaction, toAddress, changeAddress, changeWalletAddress, feeRate, maxFee)
if err != nil {
return nil, err
@@ -104,9 +105,49 @@ func (s *server) mergeTransaction(
s.keysFile.MinimumSignatures, payments, utxos)
}
func (s *server) transactionFeeRate(psTx *serialization.PartiallySignedTransaction) (float64, error) {
totalOuts := 0
for _, output := range psTx.Tx.Outputs {
totalOuts += int(output.Value)
}
totalIns := 0
for _, input := range psTx.PartiallySignedInputs {
totalIns += int(input.PrevOutput.Value)
}
if totalIns < totalOuts {
return 0, errors.Errorf("Transaction don't have enough funds to pay for the outputs")
}
fee := totalIns - totalOuts
mass, err := s.estimateComputeMassAfterSignatures(psTx)
if err != nil {
return 0, err
}
return float64(fee) / float64(mass), nil
}
func (s *server) checkTransactionFeeRate(psTx *serialization.PartiallySignedTransaction, maxFee uint64) error {
feeRate, err := s.transactionFeeRate(psTx)
if err != nil {
return err
}
if feeRate < 1 {
return errors.Errorf("setting --max-fee to %d results in a fee rate of %f, which is below the minimum allowed fee rate of 1 sompi/gram", maxFee, feeRate)
}
return nil
}
func (s *server) maybeSplitAndMergeTransaction(transaction *serialization.PartiallySignedTransaction, toAddress util.Address,
changeAddress util.Address, changeWalletAddress *walletAddress, feeRate float64, maxFee uint64) ([]*serialization.PartiallySignedTransaction, error) {
err := s.checkTransactionFeeRate(transaction, maxFee)
if err != nil {
return nil, err
}
transactionMass, err := s.estimateComputeMassAfterSignatures(transaction)
if err != nil {
return nil, err
@@ -130,6 +171,11 @@ func (s *server) maybeSplitAndMergeTransaction(transaction *serialization.Partia
if err != nil {
return nil, err
}
err = s.checkTransactionFeeRate(splitTransactions[i], maxFee)
if err != nil {
return nil, err
}
}
if len(splitTransactions) > 1 {

View File

@@ -1,4 +1,4 @@
package main
package server
import (
"encoding/hex"
@@ -9,7 +9,7 @@ import (
// We use a separator that is not in the hex alphabet, but which will not split selection with a double click
const hexTransactionsSeparator = "_"
func encodeTransactionsToHex(transactions [][]byte) string {
func EncodeTransactionsToHex(transactions [][]byte) string {
transactionsInHex := make([]string, len(transactions))
for i, transaction := range transactions {
transactionsInHex[i] = hex.EncodeToString(transaction)
@@ -17,7 +17,7 @@ func encodeTransactionsToHex(transactions [][]byte) string {
return strings.Join(transactionsInHex, hexTransactionsSeparator)
}
func decodeTransactionsFromHex(transactionsHex string) ([][]byte, error) {
func DecodeTransactionsFromHex(transactionsHex string) ([][]byte, error) {
splitTransactionsHexes := strings.Split(transactionsHex, hexTransactionsSeparator)
transactions := make([][]byte, len(splitTransactionsHexes))

View File

@@ -38,7 +38,7 @@ func parse(conf *parseConfig) error {
transactionHex = strings.TrimSpace(string(transactionHexBytes))
}
transactions, err := decodeTransactionsFromHex(transactionHex)
transactions, err := server.DecodeTransactionsFromHex(transactionHex)
if err != nil {
return err
}

View File

@@ -6,6 +6,7 @@ import (
"os"
"strings"
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/server"
"github.com/kaspanet/kaspad/cmd/kaspawallet/keys"
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
"github.com/pkg/errors"
@@ -40,7 +41,7 @@ func sign(conf *signConfig) error {
}
transactionsHex = strings.TrimSpace(string(transactionHexBytes))
}
partiallySignedTransactions, err := decodeTransactionsFromHex(transactionsHex)
partiallySignedTransactions, err := server.DecodeTransactionsFromHex(transactionsHex)
if err != nil {
return err
}
@@ -72,6 +73,6 @@ func sign(conf *signConfig) error {
fmt.Fprintln(os.Stderr, "Successfully signed transaction")
}
fmt.Println(encodeTransactionsToHex(updatedPartiallySignedTransactions))
fmt.Println(server.EncodeTransactionsToHex(updatedPartiallySignedTransactions))
return nil
}