Files
dragonx/src/wallet/asyncrpcoperation_autoshieldcoinbase.h
DanS 2ebbbc777c wallet: add default-on auto-shield-coinbase; drain miner coinbase into a z-addr
On this ac_private=1 chain miners accumulate one transparent coinbase UTXO per
block (the only transparent output the chain permits). It had to be shielded
manually via z_shieldcoinbase, and left unshielded it is the sole persistent
metadata leak on the chain and the source of miner UTXO-fragmentation send
failures.

Add AsyncRPCOperation_autoshieldcoinbase: a periodic, default-on wallet op
driven from CWallet::ChainTip alongside sweep/consolidation, draining matured
coinbase into a wallet-owned Sapling z-address in size-bounded batches.

- Enqueue-only driver (RunAutoShieldCoinbase): takes only cs_wallet in the
  notify context; all gathering runs on the async worker under LOCK2(cs_main,
  cs_wallet).
- Dedicated op (not a reuse of z_shieldcoinbase) so it never toggles mining.
- Default-ON but conditional: silent no-op on -disablewallet, external
  -mineraddress, non-mining, or locked wallets (explicit IsLocked() guard).
- Destination is reuse-then-create; -autoshieldaddress override is
  spend-key-validated at init so funds cannot be stranded.
- Sweep-model bookkeeping: advances nextAutoShield and clears the running flag
  on every terminal state; an op-id guard stops a stale op clobbering scheduler
  state; a self-guard stops cancel/re-enqueue churn.
- Sietch-padded output shape matches manual z_shieldcoinbase txns.

Config: -autoshield (default true), -autoshieldinterval, -autoshieldaddress,
-autoshieldfee (range-validated), -autoshieldminutxos.

Incorporates fixes from an 8-angle code review: CAmount fee type with init-time
range validation, op-id-guarded flag bookkeeping, driver self-guard, and a
tipHeight-consistent NU-activation guard.

Note: the fConsolidationRunning / nextConsolidation consolidation-scheduler
wedge is a pre-existing bug, left for a separate change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-21 02:06:09 -05:00

59 lines
2.5 KiB
C++

// 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;
// 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<std::string> 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 */