diff --git a/config.go b/config.go index 7119df13c..947ae3484 100644 --- a/config.go +++ b/config.go @@ -174,7 +174,7 @@ type config struct { mixedAccount string mixedBranch uint32 TicketSplitAccount string `long:"ticketsplitaccount" description:"Account to derive fresh addresses from for mixed ticket splits; uses mixedaccount if unset"` - ChangeAccount string `long:"changeaccount" description:"Account used to derive unmixed CoinJoin outputs in CoinShuffle++ protocol"` + ChangeAccount string `long:"changeaccount" description:"Account to send change when ticket autobuying or mixing; required when mixing"` MixChange bool `long:"mixchange" description:"Use CoinShuffle++ to mix change account outputs into mix account"` MixSplitLimit int `long:"mixsplitlimit" description:"Maximum concurrent mixes for any change amount"` diff --git a/dcrwallet.go b/dcrwallet.go index 2bb680448..c47463f18 100644 --- a/dcrwallet.go +++ b/dcrwallet.go @@ -301,7 +301,7 @@ func run(ctx context.Context) error { purchaseAccount uint32 // enableticketbuyer votingAccount uint32 // enableticketbuyer mixedAccount uint32 // (enableticketbuyer && mixing) || mixchange - changeAccount uint32 // (enableticketbuyer && mixing) || mixchange + changeAccount uint32 // enableticketbuyer || mixchange ticketSplitAccount uint32 // enableticketbuyer && mixing ) if cfg.EnableTicketBuyer { @@ -317,6 +317,11 @@ func run(ctx context.Context) error { } else { votingAccount = purchaseAccount } + if cfg.ChangeAccount != "" { + changeAccount = lookup("changeaccount", cfg.ChangeAccount) + } else { + changeAccount = purchaseAccount + } } if (cfg.EnableTicketBuyer && cfg.MixingEnabled) || cfg.MixChange { mixedAccount = lookup("mixedaccount", cfg.mixedAccount) diff --git a/go.mod b/go.mod index 2e5aac261..784398a93 100644 --- a/go.mod +++ b/go.mod @@ -16,16 +16,16 @@ require ( github.com/decred/dcrd/crypto/rand v1.0.1 github.com/decred/dcrd/crypto/ripemd160 v1.0.2 github.com/decred/dcrd/dcrec v1.0.1 - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 github.com/decred/dcrd/dcrjson/v4 v4.2.0 github.com/decred/dcrd/dcrutil/v4 v4.0.3 github.com/decred/dcrd/gcs/v4 v4.1.1 github.com/decred/dcrd/hdkeychain/v3 v3.1.3 - github.com/decred/dcrd/mixing v0.6.1 + github.com/decred/dcrd/mixing v0.7.0 github.com/decred/dcrd/rpc/jsonrpc/types/v4 v4.4.0 github.com/decred/dcrd/rpcclient/v8 v8.1.0 github.com/decred/dcrd/txscript/v4 v4.1.2 - github.com/decred/dcrd/wire v1.7.2 + github.com/decred/dcrd/wire v1.7.5 github.com/decred/go-socks v1.1.0 github.com/decred/slog v1.2.0 github.com/decred/vspd/client/v4 v4.0.2 diff --git a/go.sum b/go.sum index cd0d4bee4..62c820d34 100644 --- a/go.sum +++ b/go.sum @@ -40,8 +40,8 @@ github.com/decred/dcrd/dcrec v1.0.1 h1:gDzlndw0zYxM5BlaV17d7ZJV6vhRe9njPBFeg4Db2 github.com/decred/dcrd/dcrec v1.0.1/go.mod h1:CO+EJd8eHFb8WHa84C7ZBkXsNUIywaTHb+UAuI5uo6o= github.com/decred/dcrd/dcrec/edwards/v2 v2.0.4 h1:xmmdtnGxF/Od2doiP56zBv5a3LgJ3PA6mlx3Luf622I= github.com/decred/dcrd/dcrec/edwards/v2 v2.0.4/go.mod h1:07Ke2V+uJkG72M1Eiek8CF6NUB3XPlZ38cIit57R0UU= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 h1:5RVFMOWjMyRy8cARdy79nAmgYw3hK/4HUq48LQ6Wwqo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= github.com/decred/dcrd/dcrjson/v4 v4.2.0 h1:VZOitxS5/J1Gr8V/rUcVnvbtTvijxrVy7i2A3nu9wto= github.com/decred/dcrd/dcrjson/v4 v4.2.0/go.mod h1:1YuURV3cVmko3lmBlkKc6Y2iHwHJJXATdiLULBS9D+Q= github.com/decred/dcrd/dcrutil/v4 v4.0.3 h1:uUgSBB4ZFHeKQFrdUgKv3PvVJ3YpBpFeXMgXZsa0790= @@ -50,16 +50,16 @@ github.com/decred/dcrd/gcs/v4 v4.1.1 h1:3ELoII8uwIxXFGq6ETB29AjW7Lmr3McQOYsSD3dv github.com/decred/dcrd/gcs/v4 v4.1.1/go.mod h1:5q1EnYp1CzJw057/XfRB6UGkos24fpu2r2ZLuwE7YdE= github.com/decred/dcrd/hdkeychain/v3 v3.1.3 h1:Kn2wfj5cOR6pQO/WrYOMT1KK12IgWFEeQwnk1o81WsU= github.com/decred/dcrd/hdkeychain/v3 v3.1.3/go.mod h1:mDAuGaH6InRD+hKVeVJsjLD/ih1mD3aCKURNHS8Tq2s= -github.com/decred/dcrd/mixing v0.6.1 h1:nysHraShVbgKIrqpa04364YTchmVtqgaphTNWqs7nHc= -github.com/decred/dcrd/mixing v0.6.1/go.mod h1:M+Ao9h49usdSEsC0N6kMafijwgYh7E57RTKh8cCw02o= +github.com/decred/dcrd/mixing v0.7.0 h1:rKs5/6E8szo561kKp54iXdcC7GlQBIE9IP3utgKxjAM= +github.com/decred/dcrd/mixing v0.7.0/go.mod h1:UE7+nPvXA6C7GdIFXJmz0ksmxykwn88zzbQFwAopahE= github.com/decred/dcrd/rpc/jsonrpc/types/v4 v4.4.0 h1:BBVaYemabsFsaqNVlCmacoZlSsLDqwHYIs8ty6fg59Q= github.com/decred/dcrd/rpc/jsonrpc/types/v4 v4.4.0/go.mod h1:w4C6hZ7ywpc8/YNkiPAknCaqKofF68cRhUiTglEIc7s= github.com/decred/dcrd/rpcclient/v8 v8.1.0 h1:FLZ1j4ub7+O9oCIcKf+frYCrZW++G3FSzk2/f4U80hI= github.com/decred/dcrd/rpcclient/v8 v8.1.0/go.mod h1:iTHqLrHnS2VLJPHQk7guy0BP3jKvMew9STDqWWhFNA4= github.com/decred/dcrd/txscript/v4 v4.1.2 h1:1EP7ZmBDl2LBeAMTEygxY8rVNN3+lkGqrsb4u64x+II= github.com/decred/dcrd/txscript/v4 v4.1.2/go.mod h1:r5/8qfCnl6TFrE369gggUayVIryM1oC7BLoRfa27Ckw= -github.com/decred/dcrd/wire v1.7.2 h1:04vpHHE3t78rDztjZx82JV2EEOMDUtUUB1347H32kho= -github.com/decred/dcrd/wire v1.7.2/go.mod h1:eP9XRsMloy+phlntkTAaAm611JgLv8NqY1YJoRxkNKU= +github.com/decred/dcrd/wire v1.7.5 h1:fRaaB5CrwYWGI3YVv50XHm54lsU1TB40WnnIJ4W6aGM= +github.com/decred/dcrd/wire v1.7.5/go.mod h1:NZK8QD5W2ObX6p+Q0TUzYNpQtk4Ov3pBIvc6ZUK88FU= github.com/decred/go-socks v1.1.0 h1:dnENcc0KIqQo3HSXdgboXAHgqsCIutkqq6ntQjYtm2U= github.com/decred/go-socks v1.1.0/go.mod h1:sDhHqkZH0X4JjSa02oYOGhcGHYp12FsY1jQ/meV8md0= github.com/decred/slog v1.2.0 h1:soHAxV52B54Di3WtKLfPum9OFfWqwtf/ygf9njdfnPM= diff --git a/internal/rpc/jsonrpc/methods.go b/internal/rpc/jsonrpc/methods.go index cd837ecfc..ad6fdebc8 100644 --- a/internal/rpc/jsonrpc/methods.go +++ b/internal/rpc/jsonrpc/methods.go @@ -4599,7 +4599,7 @@ func (s *Server) sendRawTransaction(ctx context.Context, icmd any) (any, error) return nil, err } - msgtx := wire.NewMsgTx() + msgtx := new(wire.MsgTx) err = msgtx.Deserialize(hex.NewDecoder(strings.NewReader(cmd.HexTx))) if err != nil { return nil, rpcError(dcrjson.ErrRPCDeserialization, err) @@ -4812,7 +4812,7 @@ func (s *Server) signRawTransaction(ctx context.Context, icmd any) (any, error) return nil, errUnloadedWallet } - tx := wire.NewMsgTx() + tx := new(wire.MsgTx) err := tx.Deserialize(hex.NewDecoder(strings.NewReader(cmd.RawTx))) if err != nil { return nil, rpcError(dcrjson.ErrRPCDeserialization, err) @@ -5062,7 +5062,7 @@ func (s *Server) signRawTransactions(ctx context.Context, icmd any) (any, error) for i, result := range results { if result.Complete { // Slow/mem hungry because of the deserializing. - msgTx := wire.NewMsgTx() + msgTx := new(wire.MsgTx) err := msgTx.Deserialize(hex.NewDecoder(strings.NewReader(result.Hex))) if err != nil { return nil, rpcError(dcrjson.ErrRPCDeserialization, err) diff --git a/internal/rpc/jsonrpc/server.go b/internal/rpc/jsonrpc/server.go index 8e7cd37f6..5b96dcd76 100644 --- a/internal/rpc/jsonrpc/server.go +++ b/internal/rpc/jsonrpc/server.go @@ -24,7 +24,6 @@ import ( "decred.org/dcrwallet/v5/rpc/jsonrpc/types" "github.com/decred/dcrd/chaincfg/v3" "github.com/decred/dcrd/dcrjson/v4" - dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v4" "github.com/gorilla/websocket" ) @@ -319,13 +318,13 @@ func idPointer(id any) (p *any) { func (s *Server) invalidAuth(req *dcrjson.Request) bool { cmd, err := dcrjson.ParseParams(types.Method(req.Method), req.Params) if err != nil { - return false + return true } - authCmd, ok := cmd.(*dcrdtypes.AuthenticateCmd) + authCmd, ok := cmd.(*types.AuthenticateCmd) if !ok { - return false + return true } - // Authenticate commands are invalid when no basic auth is used + // Authenticate commands are invalid when no basic auth is used. if s.authsha == nil { return true } diff --git a/p2p/peering.go b/p2p/peering.go index e41bdf4ac..67016f748 100644 --- a/p2p/peering.go +++ b/p2p/peering.go @@ -144,7 +144,6 @@ type RemotePeer struct { // messages with remote peers on the network. type LocalPeer struct { mask atomic.Uint64 - peerIDCounter atomic.Uint64 requireHeight atomic.Int32 dial DialFunc @@ -160,8 +159,9 @@ type LocalPeer struct { chainParams *chaincfg.Params disableRelayTx bool - rpByID map[uint64]*RemotePeer - rpMu sync.Mutex + rpByID map[uint64]*RemotePeer + rpIDCounter uint64 + rpMu sync.Mutex } // NewLocalPeer creates a LocalPeer that is externally reachable to remote peers @@ -257,9 +257,6 @@ func (lp *LocalPeer) ConnectOutbound(ctx context.Context, addr string, reqSvcs w log.Debugf("Attempting connection to peer %v", addr) - // Generate a unique ID for this peer and add the initial connection state. - id := lp.peerIDCounter.Add(1) - tcpAddr, err := net.ResolveTCPAddr("tcp", addr) if err != nil { return nil, err @@ -269,7 +266,7 @@ func (lp *LocalPeer) ConnectOutbound(ctx context.Context, addr string, reqSvcs w na := addrmgr.NewNetAddressFromIPPort(tcpAddr.IP, uint16(tcpAddr.Port), wire.SFNodeNetwork) na.Timestamp = time.Now() - rp, err := lp.connectOutbound(ctx, id, addr, na) + rp, err := lp.connectOutbound(ctx, addr, na) if err != nil { op := errors.Opf(opf, addr) return nil, errors.E(op, err) @@ -544,11 +541,11 @@ func (rp *RemotePeer) sendWaitingInventory(ctx context.Context) error { return nil } -func handshake(ctx context.Context, lp *LocalPeer, id uint64, na *addrmgr.NetAddress, c net.Conn) (*RemotePeer, error) { +func handshake(ctx context.Context, lp *LocalPeer, na *addrmgr.NetAddress, c net.Conn) (*RemotePeer, error) { const op errors.Op = "p2p.handshake" rp := &RemotePeer{ - id: id, + id: 0, // Set after handshake completes lp: lp, ua: "", services: 0, @@ -618,9 +615,7 @@ func handshake(ctx context.Context, lp *LocalPeer, id uint64, na *addrmgr.NetAdd return rp, nil } -func (lp *LocalPeer) connectOutbound(ctx context.Context, id uint64, addr string, - na *addrmgr.NetAddress) (*RemotePeer, error) { - +func (lp *LocalPeer) connectOutbound(ctx context.Context, addr string, na *addrmgr.NetAddress) (*RemotePeer, error) { // Mark the connection attempt. lp.amgr.Attempt(na) @@ -636,7 +631,7 @@ func (lp *LocalPeer) connectOutbound(ctx context.Context, id uint64, addr string // Handshake with a timeout of 5s. handshakeCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - rp, err := handshake(handshakeCtx, lp, id, na, c) + rp, err := handshake(handshakeCtx, lp, na, c) cancel() if err != nil { return nil, err @@ -644,7 +639,16 @@ func (lp *LocalPeer) connectOutbound(ctx context.Context, id uint64, addr string // Associate connected rp with local peer. lp.rpMu.Lock() - lp.rpByID[rp.id] = rp + for { + // Generate a unique ID for this peer and add the initial connection state. + lp.rpIDCounter++ + id := lp.rpIDCounter + if _, ok := lp.rpByID[id]; !ok && id != 0 { + rp.id = id + lp.rpByID[id] = rp + break + } + } lp.rpMu.Unlock() // The real services of the net address are now known. diff --git a/rpc/jsonrpc/types/methods.go b/rpc/jsonrpc/types/methods.go index 356138ae2..9ea4370a1 100644 --- a/rpc/jsonrpc/types/methods.go +++ b/rpc/jsonrpc/types/methods.go @@ -1,5 +1,5 @@ // Copyright (c) 2014 The btcsuite developers -// Copyright (c) 2015-2025 The Decred developers +// Copyright (c) 2015-2026 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -147,19 +147,6 @@ func NewCreateNewAccountCmd(account string) *CreateNewAccountCmd { } } -// CreateVotingAccountCmd is a type for handling custom marshaling and -// unmarshalling of createvotingaccount JSON-RPC command. -type CreateVotingAccountCmd struct { - Name string - PubKey string - ChildIndex *uint32 `jsonrpcdefault:"0"` -} - -// NewCreateVotingAccountCmd creates a new CreateVotingAccountCmd. -func NewCreateVotingAccountCmd(name, pubKey string, childIndex *uint32) *CreateVotingAccountCmd { - return &CreateVotingAccountCmd{name, pubKey, childIndex} -} - // DumpPrivKeyCmd defines the dumpprivkey JSON-RPC command. type DumpPrivKeyCmd struct { Address string @@ -1211,7 +1198,6 @@ func init() { {"createmultisig", (*CreateMultisigCmd)(nil)}, {"createnewaccount", (*CreateNewAccountCmd)(nil)}, {"createsignature", (*CreateSignatureCmd)(nil)}, - {"createvotingaccount", (*CreateVotingAccountCmd)(nil)}, {"disapprovepercent", (*DisapprovePercentCmd)(nil)}, {"discoverusage", (*DiscoverUsageCmd)(nil)}, {"dumpprivkey", (*DumpPrivKeyCmd)(nil)}, diff --git a/spv/sync.go b/spv/sync.go index 265dc4e32..a0bf8e510 100644 --- a/spv/sync.go +++ b/spv/sync.go @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2025 The Decred developers +// Copyright (c) 2018-2026 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -1237,7 +1237,6 @@ func (s *Syncer) handleMixInvs(ctx context.Context, rp *p2p.RemotePeer, hashes [ } if len(requestUnknownPRs) > 0 { - requestUnknownPRs := make(map[chainhash.Hash]struct{}) unknownPRs := make([]*chainhash.Hash, 0, len(requestUnknownPRs)) for hash := range requestUnknownPRs { unknownPRs = append(unknownPRs, &hash) diff --git a/version/version.go b/version/version.go index c49f94282..f9e2ea7f0 100644 --- a/version/version.go +++ b/version/version.go @@ -20,7 +20,7 @@ const semverAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrst const ( Major = 2 Minor = 1 - Patch = 3 + Patch = 4 ) // Integer is an integer encoding of the major.minor.patch version. diff --git a/wallet/mixing.go b/wallet/mixing.go index 7e26c07af..d8b2433cc 100644 --- a/wallet/mixing.go +++ b/wallet/mixing.go @@ -103,7 +103,7 @@ func (w *mixingWallet) SubmitMixMessage(ctx context.Context, msg mixing.Message) } }() - _, err = w.mixpool.AcceptMessage(msg) + _, err = w.mixpool.AcceptMessage(msg, mixpool.ZeroSource) if err != nil { return err } @@ -554,7 +554,7 @@ func PossibleCoinJoin(tx *wire.MsgTx) (isMix bool, mixDenom int64, mixCount uint // AcceptMixMessage adds a mixing message received from the network backend to // the wallet's mixpool. func (w *Wallet) AcceptMixMessage(msg mixing.Message) error { - _, err := w.mixpool.AcceptMessage(msg) + _, err := w.mixpool.AcceptMessage(msg, mixpool.ZeroSource) if err != nil { return err } diff --git a/wallet/wallet.go b/wallet/wallet.go index e3ab21d6c..f16f892d6 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2025 The Decred developers +// Copyright (c) 2015-2026 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -246,6 +246,8 @@ func (w *Wallet) VotingEnabled() bool { // IsTSpendCached returns whether the given hash is already cached. func (w *Wallet) IsTSpendCached(hash *chainhash.Hash) bool { + w.stakeSettingsLock.Lock() + defer w.stakeSettingsLock.Unlock() if _, ok := w.tspends[*hash]; ok { return true }