Compare commits

..

1 Commits

Author SHA1 Message Date
Ori Newman
f1cff7960c rc2 2023-12-07 13:48:14 +02:00
11 changed files with 46 additions and 78 deletions

View File

@@ -218,7 +218,7 @@ func RPCTransactionToDomainTransaction(rpcTransaction *RPCTransaction) (*externa
Outputs: outputs,
LockTime: rpcTransaction.LockTime,
SubnetworkID: *subnetworkID,
Gas: rpcTransaction.Gas,
Gas: rpcTransaction.LockTime,
Payload: payload,
}, nil
}
@@ -286,7 +286,7 @@ func DomainTransactionToRPCTransaction(transaction *externalapi.DomainTransactio
Outputs: outputs,
LockTime: transaction.LockTime,
SubnetworkID: subnetworkID,
Gas: transaction.Gas,
Gas: transaction.LockTime,
Payload: payload,
}
}

View File

@@ -1,25 +1,3 @@
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

@@ -106,14 +106,9 @@ func (s *server) selectUTXOs(spendAmount uint64, isSendAll bool, feePerInput uin
return nil, 0, 0, err
}
coinbaseMaturity := s.params.BlockCoinbaseMaturity
if dagInfo.NetworkName == "kaspa-testnet-11" {
coinbaseMaturity = 1000
}
for _, utxo := range s.utxosSortedByAmount {
if (fromAddresses != nil && !slices.Contains(fromAddresses, utxo.address)) ||
!isUTXOSpendable(utxo, dagInfo.VirtualDAAScore, coinbaseMaturity) {
!isUTXOSpendable(utxo, dagInfo.VirtualDAAScore, s.params.BlockCoinbaseMaturity) {
continue
}
@@ -135,11 +130,7 @@ func (s *server) selectUTXOs(spendAmount uint64, isSendAll bool, feePerInput uin
fee := feePerInput * uint64(len(selectedUTXOs))
totalSpend := spendAmount + fee
// 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)) {
if !isSendAll && totalValue >= totalSpend {
break
}
}

View File

@@ -75,29 +75,23 @@ func send(conf *sendConfig) error {
signedTransactions[i] = signedTransaction
}
fmt.Printf("Broadcasting %d transaction(s)\n", len(signedTransactions))
if len(signedTransactions) > 1 {
fmt.Printf("Broadcasting %d transactions\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()
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)
}
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)
}
if conf.Verbose {

View File

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

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 *RuleError
Error error
}
func (invalid InvalidTransaction) String() string {

View File

@@ -3,9 +3,8 @@ package ruleerrors
import (
"errors"
"fmt"
"testing"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"testing"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
)
@@ -50,7 +49,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{}
@@ -61,7 +60,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

@@ -387,7 +387,7 @@ func ExtractAtomicSwapDataPushes(version uint16, scriptPubKey []byte) (*AtomicSw
return nil, err
}
if len(pops) != 19 {
if len(pops) != 20 {
return nil, nil
}
isAtomicSwap := pops[0].opcode.value == OpIf &&
@@ -403,12 +403,13 @@ func ExtractAtomicSwapDataPushes(version uint16, scriptPubKey []byte) (*AtomicSw
pops[10].opcode.value == OpElse &&
canonicalPush(pops[11]) &&
pops[12].opcode.value == OpCheckLockTimeVerify &&
pops[13].opcode.value == OpDup &&
pops[14].opcode.value == OpBlake2b &&
pops[15].opcode.value == OpData32 &&
pops[16].opcode.value == OpEndIf &&
pops[17].opcode.value == OpEqualVerify &&
pops[18].opcode.value == OpCheckSig
pops[13].opcode.value == OpDrop &&
pops[14].opcode.value == OpDup &&
pops[15].opcode.value == OpBlake2b &&
pops[16].opcode.value == OpData32 &&
pops[17].opcode.value == OpEndIf &&
pops[18].opcode.value == OpEqualVerify &&
pops[19].opcode.value == OpCheckSig
if !isAtomicSwap {
return nil, nil
}
@@ -416,9 +417,9 @@ func ExtractAtomicSwapDataPushes(version uint16, scriptPubKey []byte) (*AtomicSw
pushes := new(AtomicSwapDataPushes)
copy(pushes.SecretHash[:], pops[5].data)
copy(pushes.RecipientBlake2b[:], pops[9].data)
copy(pushes.RefundBlake2b[:], pops[15].data)
copy(pushes.RefundBlake2b[:], pops[16].data)
if pops[2].data != nil {
locktime, err := makeScriptNum(pops[2].data, 8)
locktime, err := makeScriptNum(pops[2].data, 5)
if err != nil {
return nil, nil
}
@@ -429,7 +430,7 @@ func ExtractAtomicSwapDataPushes(version uint16, scriptPubKey []byte) (*AtomicSw
return nil, nil
}
if pops[11].data != nil {
locktime, err := makeScriptNum(pops[11].data, 8)
locktime, err := makeScriptNum(pops[11].data, 5)
if err != nil {
return nil, nil
}

View File

@@ -232,8 +232,6 @@ var MainnetParams = Params{
"seeder4.kaspad.net",
// This DNS seeder is run by Tim
"kaspadns.kaspacalc.net",
// This DNS seeder is run by supertypo
"n-mainnet.kaspa.ws",
},
// DAG parameters

View File

@@ -1,12 +1,10 @@
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"
"github.com/pkg/errors"
"sync"
"github.com/kaspanet/kaspad/domain/consensusreference"
@@ -211,7 +209,17 @@ func (mp *mempool) RemoveInvalidTransactions(err *ruleerrors.ErrInvalidTransacti
defer mp.mtx.Unlock()
for _, tx := range err.InvalidTransactions {
removeRedeemers := !errors.As(tx.Error, &ruleerrors.ErrMissingTxOut{})
ruleErr, success := tx.Error.(ruleerrors.RuleError)
if !success {
continue
}
inner := ruleErr.Unwrap()
removeRedeemers := true
if _, ok := inner.(ruleerrors.ErrMissingTxOut); ok {
removeRedeemers = false
}
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 = 16
appPatch uint = 15
)
// appBuild is defined as a variable so it can be overridden during the build