diff --git a/cmd/kaspawallet/config.go b/cmd/kaspawallet/config.go index d701b18c2f..c88bc5f39d 100644 --- a/cmd/kaspawallet/config.go +++ b/cmd/kaspawallet/config.go @@ -103,6 +103,7 @@ type broadcastConfig struct { } type parseConfig struct { + KeysFile string `long:"keys-file" short:"f" description:"Keys file location (default: ~/.kaspawallet/keys.json (*nix), %USERPROFILE%\\AppData\\Local\\Kaspawallet\\key.json (Windows))"` Transaction string `long:"transaction" short:"t" description:"The transaction to parse (encoded in hex)"` TransactionFile string `long:"transaction-file" short:"F" description:"The file containing the transaction to parse (encoded in hex)"` Verbose bool `long:"verbose" short:"v" description:"Verbose: show transaction inputs"` diff --git a/cmd/kaspawallet/daemon/server/split_transaction.go b/cmd/kaspawallet/daemon/server/split_transaction.go index 97d017abe7..8e2d09aa48 100644 --- a/cmd/kaspawallet/daemon/server/split_transaction.go +++ b/cmd/kaspawallet/daemon/server/split_transaction.go @@ -12,6 +12,7 @@ import ( "github.com/kaspanet/kaspad/domain/consensus/utils/utxo" "github.com/kaspanet/kaspad/domain/miningmanager/mempool" "github.com/kaspanet/kaspad/util" + "github.com/kaspanet/kaspad/util/txmass" ) // maybeAutoCompoundTransaction checks if a transaction's mass is higher that what is allowed for a standard @@ -218,9 +219,13 @@ func (s *server) createSplitTransaction(transaction *serialization.PartiallySign } func (s *server) estimateMassAfterSignatures(transaction *serialization.PartiallySignedTransaction) (uint64, error) { + return EstimateMassAfterSignatures(transaction, s.keysFile.ECDSA, s.keysFile.MinimumSignatures, s.txMassCalculator) +} + +func EstimateMassAfterSignatures(transaction *serialization.PartiallySignedTransaction, ecdsa bool, minimumSignatures uint32, txMassCalculator *txmass.Calculator) (uint64, error) { transaction = transaction.Clone() var signatureSize uint64 - if s.keysFile.ECDSA { + if ecdsa { signatureSize = secp256k1.SerializedECDSASignatureSize } else { signatureSize = secp256k1.SerializedSchnorrSignatureSize @@ -228,7 +233,7 @@ func (s *server) estimateMassAfterSignatures(transaction *serialization.Partiall for i, input := range transaction.PartiallySignedInputs { for j, pubKeyPair := range input.PubKeySignaturePairs { - if uint32(j) >= s.keysFile.MinimumSignatures { + if uint32(j) >= minimumSignatures { break } pubKeyPair.Signature = make([]byte, signatureSize+1) // +1 for SigHashType @@ -236,12 +241,12 @@ func (s *server) estimateMassAfterSignatures(transaction *serialization.Partiall transaction.Tx.Inputs[i].SigOpCount = byte(len(input.PubKeySignaturePairs)) } - transactionWithSignatures, err := libkaspawallet.ExtractTransactionDeserialized(transaction, s.keysFile.ECDSA) + transactionWithSignatures, err := libkaspawallet.ExtractTransactionDeserialized(transaction, ecdsa) if err != nil { return 0, err } - return s.txMassCalculator.CalculateTransactionMass(transactionWithSignatures), nil + return txMassCalculator.CalculateTransactionMass(transactionWithSignatures), nil } func (s *server) moreUTXOsForMergeTransaction(alreadySelectedUTXOs []*libkaspawallet.UTXO, requiredAmount uint64, feeRate float64) ( diff --git a/cmd/kaspawallet/parse.go b/cmd/kaspawallet/parse.go index 0e278e90f9..68275a0534 100644 --- a/cmd/kaspawallet/parse.go +++ b/cmd/kaspawallet/parse.go @@ -3,13 +3,17 @@ package main import ( "encoding/hex" "fmt" + "io/ioutil" + "strings" + + "github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/server" + "github.com/kaspanet/kaspad/cmd/kaspawallet/keys" "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/kaspanet/kaspad/util/txmass" "github.com/pkg/errors" - "io/ioutil" - "strings" ) func parse(conf *parseConfig) error { @@ -20,6 +24,11 @@ func parse(conf *parseConfig) error { return errors.Errorf("Both --transaction and --transaction-file cannot be passed at the same time") } + keysFile, err := keys.ReadKeysFile(conf.NetParams(), conf.KeysFile) + if err != nil { + return err + } + transactionHex := conf.Transaction if conf.TransactionFile != "" { transactionHexBytes, err := ioutil.ReadFile(conf.TransactionFile) @@ -33,6 +42,8 @@ func parse(conf *parseConfig) error { if err != nil { return err } + + txMassCalculator := txmass.NewCalculator(conf.NetParams().MassPerTxByte, conf.NetParams().MassPerScriptPubKeyByte, conf.NetParams().MassPerSigOp) for i, transaction := range transactions { partiallySignedTransaction, err := serialization.DeserializePartiallySignedTransaction(transaction) @@ -78,7 +89,15 @@ func parse(conf *parseConfig) error { } fmt.Println() - fmt.Printf("Fee:\t%d Sompi\n\n", allInputSompi-allOutputSompi) + fee := allInputSompi - allOutputSompi + fmt.Printf("Fee:\t%d Sompi\n\n", fee) + mass, err := server.EstimateMassAfterSignatures(partiallySignedTransaction, keysFile.ECDSA, keysFile.MinimumSignatures, txMassCalculator) + if err != nil { + return err + } + + feeRate := float64(fee) / float64(mass) + fmt.Printf("Fee rate: %.2f Sompi/Gram\n", feeRate) } return nil