// Copyright (c) 2016-2024 The Hush developers // Copyright (c) 2024-2026 The DragonX developers // Distributed under the GPLv3 software license, see the accompanying // file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html #ifndef ASYNCRPCOPERATION_AUTOSHIELDCOINBASE_H #define ASYNCRPCOPERATION_AUTOSHIELDCOINBASE_H #include "amount.h" #include "asyncrpcoperation.h" #include "univalue.h" #include "zcash/Address.hpp" #include "zcash/zip32.h" // Default fee for automatic coinbase-shielding transactions static const CAmount DEFAULT_AUTOSHIELD_FEE = 10000; // Sentinel for "not a derived account" (i.e. the configured -autoshieldaddress). static const uint32_t AUTOSHIELD_ACCOUNT_NONE = UINT32_MAX; enum class AutoShieldDestStatus { Resolved, // destOut/destStrOut are set NotFound, // no in-gap account held yet; the operation will derive one InvalidOverride, // -autoshieldaddress is set but is not a Sapling address NoSeed, // no HD seed available (e.g. locked wallet) }; // Resolve the auto-shield destination WITHOUT mutating the wallet: the configured // -autoshieldaddress if set, else the lowest in-gap seed-derived account the wallet // already holds. It deliberately does NOT generate a key, so init can call it purely // to answer "where will this send?" -- deriving a fresh account as a side effect of // populating a status field would be wrong. The operation's own resolveDestination // falls through to generation when this returns NotFound. // Caller must hold cs_wallet. AutoShieldDestStatus ResolveAutoShieldDestinationReadOnly( libzcash::SaplingPaymentAddress& destOut, std::string& destStrOut, uint32_t& accountOut); // A periodic, wallet-local operation that drains matured *transparent* coinbase // UTXOs into a wallet-owned Sapling z-address in size-bounded batches. It is the // automatic sibling of the manual z_shieldcoinbase RPC and mirrors the dispatch // model of AsyncRPCOperation_sweep (self-gathers on the async worker thread, // commits via CWallet::CommitAutomatedTx). It never mints a transparent output, // so it respects the ac_private=1 transparent-output ban, and it deliberately // does NOT toggle mining (unlike z_shieldcoinbase) so it can run every interval // on a mining node without thrashing the miner. class AsyncRPCOperation_autoshieldcoinbase : public AsyncRPCOperation { public: AsyncRPCOperation_autoshieldcoinbase(int targetHeight); virtual ~AsyncRPCOperation_autoshieldcoinbase(); // We don't want to be copied or moved around AsyncRPCOperation_autoshieldcoinbase(AsyncRPCOperation_autoshieldcoinbase const&) = delete; AsyncRPCOperation_autoshieldcoinbase(AsyncRPCOperation_autoshieldcoinbase&&) = delete; AsyncRPCOperation_autoshieldcoinbase& operator=(AsyncRPCOperation_autoshieldcoinbase const&) = delete; AsyncRPCOperation_autoshieldcoinbase& operator=(AsyncRPCOperation_autoshieldcoinbase&&) = delete; virtual void main(); virtual void cancel(); virtual UniValue getStatus() const; private: int targetHeight_; int numTxCreated_ = 0; CAmount amountShielded_ = 0; std::vector shieldTxIds_; bool main_impl(); // Resolve a spendable, wallet-owned Sapling destination: the configured // -autoshieldaddress if set, else the first spendable z-addr the wallet // holds, else a freshly generated one (requires an unlocked wallet). // Returns false if none is available (e.g. locked wallet with no z-addr). bool resolveDestination(libzcash::SaplingPaymentAddress& destOut, std::string& destStrOut); void setResult(); }; #endif /* ASYNCRPCOPERATION_AUTOSHIELDCOINBASE_H */