Compare commits

...

4 Commits

8 changed files with 58 additions and 32 deletions

View File

@@ -1,3 +1,25 @@
Kaspad v0.12.16 - 2023-12-25
===========================
* Adapt wallet UTXO selection to dust patch (#2254)
Kaspad v0.12.15 - 2023-12-16
===========================
* Update ECDSA address test to use a valid public key (#2202)
* Fix off by small amounts in sent amount kaspa (#2220)
* Use removeRedeemers correctly by (#2235)
* Fix windows asset building by increasing go version (#2245)
* Added a mainnet dnsseeder (#2247)
* Fix extract atomic swap data pushes (#2203)
* Adapt kaspawallet to support testnet 11 (#2211)
* Fix type detection in RemoveInvalidTransactions (#2252)
Kaspad v0.12.14 - 2023-09-26
===========================
* Anti-spam measurements against dust attack (#2223)
Kaspad v0.12.13 - 2023-03-06
===========================

View File

@@ -135,7 +135,11 @@ func (s *server) selectUTXOs(spendAmount uint64, isSendAll bool, feePerInput uin
fee := feePerInput * uint64(len(selectedUTXOs))
totalSpend := spendAmount + fee
if !isSendAll && totalValue >= totalSpend {
// Two break cases (if not send all):
// 1. totalValue == totalSpend, so there's no change needed -> number of outputs = 1, so a single input is sufficient
// 2. totalValue > totalSpend, so there will be change and 2 outputs, therefor in order to not struggle with new dust
// rules we try and find at least 2 inputs (even though the next one is not necessary in terms of spend value)
if !isSendAll && (totalValue == totalSpend || (totalValue > totalSpend && len(selectedUTXOs) > 1)) {
break
}
}

View File

@@ -75,23 +75,29 @@ func send(conf *sendConfig) error {
signedTransactions[i] = signedTransaction
}
if len(signedTransactions) > 1 {
fmt.Printf("Broadcasting %d transactions\n", len(signedTransactions))
}
fmt.Printf("Broadcasting %d transaction(s)\n", len(signedTransactions))
// Since we waited for user input when getting the password, which could take unbound amount of time -
// create a new context for broadcast, to reset the timeout.
broadcastCtx, broadcastCancel := context.WithTimeout(context.Background(), daemonTimeout)
defer broadcastCancel()
response, err := daemonClient.Broadcast(broadcastCtx, &pb.BroadcastRequest{Transactions: signedTransactions})
if err != nil {
return err
}
fmt.Println("Transactions were sent successfully")
fmt.Println("Transaction ID(s): ")
for _, txID := range response.TxIDs {
fmt.Printf("\t%s\n", txID)
const chunkSize = 100 // To avoid sending a message bigger than the gRPC max message size, we split it to chunks
for offset := 0; offset < len(signedTransactions); offset += chunkSize {
end := len(signedTransactions)
if offset+chunkSize <= len(signedTransactions) {
end = offset + chunkSize
}
chunk := signedTransactions[offset:end]
response, err := daemonClient.Broadcast(broadcastCtx, &pb.BroadcastRequest{Transactions: chunk})
if err != nil {
return err
}
fmt.Printf("Broadcasted %d transaction(s) (broadcasted %.2f%% of the transactions so far)\n", len(chunk), 100*float64(end)/float64(len(signedTransactions)))
fmt.Println("Broadcasted Transaction ID(s): ")
for _, txID := range response.TxIDs {
fmt.Printf("\t%s\n", txID)
}
}
if conf.Verbose {

View File

@@ -131,11 +131,12 @@ func (bb *blockBuilder) validateTransactions(stagingArea *model.StagingArea,
for _, transaction := range transactions {
err := bb.validateTransaction(stagingArea, transaction)
if err != nil {
if !errors.As(err, &ruleerrors.RuleError{}) {
ruleError := ruleerrors.RuleError{}
if !errors.As(err, &ruleError) {
return err
}
invalidTransactions = append(invalidTransactions,
ruleerrors.InvalidTransaction{Transaction: transaction, Error: err})
ruleerrors.InvalidTransaction{Transaction: transaction, Error: &ruleError})
}
}

View File

@@ -315,7 +315,7 @@ func NewErrMissingParents(missingParentHashes []*externalapi.DomainHash) error {
// InvalidTransaction is a struct containing an invalid transaction, and the error explaining why it's invalid.
type InvalidTransaction struct {
Transaction *externalapi.DomainTransaction
Error error
Error *RuleError
}
func (invalid InvalidTransaction) String() string {

View File

@@ -3,9 +3,10 @@ package ruleerrors
import (
"errors"
"fmt"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"testing"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
)
@@ -49,7 +50,7 @@ func TestNewErrMissingTxOut(t *testing.T) {
func TestNewErrInvalidTransactionsInNewBlock(t *testing.T) {
tx := &externalapi.DomainTransaction{Fee: 1337}
txID := consensushashing.TransactionID(tx)
outer := NewErrInvalidTransactionsInNewBlock([]InvalidTransaction{{tx, ErrNoTxInputs}})
outer := NewErrInvalidTransactionsInNewBlock([]InvalidTransaction{{tx, &ErrNoTxInputs}})
//TODO: Implement Stringer for `DomainTransaction`
expectedOuterErr := fmt.Sprintf("ErrInvalidTransactionsInNewBlock: [(%s: ErrNoTxInputs)]", txID)
inner := &ErrInvalidTransactionsInNewBlock{}
@@ -60,7 +61,7 @@ func TestNewErrInvalidTransactionsInNewBlock(t *testing.T) {
if len(inner.InvalidTransactions) != 1 {
t.Fatalf("TestNewErrInvalidTransactionsInNewBlock: Expected len(inner.MissingOutpoints) 1, found: %d", len(inner.InvalidTransactions))
}
if inner.InvalidTransactions[0].Error != ErrNoTxInputs {
if *inner.InvalidTransactions[0].Error != ErrNoTxInputs {
t.Fatalf("TestNewErrInvalidTransactionsInNewBlock: Expected ErrNoTxInputs. found: %v", inner.InvalidTransactions[0].Error)
}
if inner.InvalidTransactions[0].Transaction.Fee != 1337 {

View File

@@ -1,10 +1,12 @@
package mempool
import (
"sync"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"sync"
"github.com/pkg/errors"
"github.com/kaspanet/kaspad/domain/consensusreference"
@@ -209,17 +211,7 @@ func (mp *mempool) RemoveInvalidTransactions(err *ruleerrors.ErrInvalidTransacti
defer mp.mtx.Unlock()
for _, tx := range err.InvalidTransactions {
ruleErr, success := tx.Error.(ruleerrors.RuleError)
if !success {
continue
}
inner := ruleErr.Unwrap()
removeRedeemers := true
if _, ok := inner.(ruleerrors.ErrMissingTxOut); ok {
removeRedeemers = false
}
removeRedeemers := !errors.As(tx.Error, &ruleerrors.ErrMissingTxOut{})
err := mp.removeTransaction(consensushashing.TransactionID(tx.Transaction), removeRedeemers)
if err != nil {
return err

View File

@@ -11,7 +11,7 @@ const validCharacters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs
const (
appMajor uint = 0
appMinor uint = 12
appPatch uint = 15
appPatch uint = 16
)
// appBuild is defined as a variable so it can be overridden during the build