fix(wallet): opreturn_burn return change + widen txfee to CAmount
#10 (HIGH) opreturn_burn selected UTXOs for nAmount+txfee but pushed only the burn vout and returned - so the entire selected-input surplus was silently paid as miner fee (e.g. a 500-coin UTXO burning 10 lost ~490). Push a change output for (inputs - nAmount - txfee). Also widen the int32_t txfee (which truncated large CAmount fees) to CAmount and MoneyRange-validate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6380,7 +6380,7 @@ void RegisterWalletRPCCommands(CRPCTable &tableRPC)
|
|||||||
|
|
||||||
UniValue opreturn_burn(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
UniValue opreturn_burn(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> vHexStr; CScript opret; int32_t txfee = 10000;CPubKey myPubkey;
|
std::vector<uint8_t> vHexStr; CScript opret; CAmount txfee = 10000;CPubKey myPubkey;
|
||||||
if (fHelp || (params.size() < 2) || (params.size() > 4) )
|
if (fHelp || (params.size() < 2) || (params.size() > 4) )
|
||||||
{
|
{
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
@@ -6413,6 +6413,9 @@ UniValue opreturn_burn(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|||||||
if ( params.size() > 2 )
|
if ( params.size() > 2 )
|
||||||
txfee = AmountFromValue(params[2]);
|
txfee = AmountFromValue(params[2]);
|
||||||
|
|
||||||
|
if ( !MoneyRange(nAmount) || !MoneyRange(txfee) || !MoneyRange(nAmount + txfee) )
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "burn_amount + txfee out of range.");
|
||||||
|
|
||||||
if (!EnsureWalletIsAvailable(fHelp))
|
if (!EnsureWalletIsAvailable(fHelp))
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, "wallet is locked or unavailable.");
|
throw JSONRPCError(RPC_TYPE_ERROR, "wallet is locked or unavailable.");
|
||||||
EnsureWalletIsUnlocked();
|
EnsureWalletIsUnlocked();
|
||||||
@@ -6425,12 +6428,17 @@ UniValue opreturn_burn(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|||||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||||
|
|
||||||
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, nAmount+txfee, 60);
|
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, nAmount+txfee, 60);
|
||||||
if (normalInputs < nAmount)
|
if (normalInputs < nAmount+txfee)
|
||||||
throw runtime_error("insufficient funds\n");
|
throw runtime_error("insufficient funds\n");
|
||||||
|
|
||||||
opret << OP_RETURN << E_MARSHAL(ss << vHexStr);
|
opret << OP_RETURN << E_MARSHAL(ss << vHexStr);
|
||||||
|
|
||||||
mtx.vout.push_back(CTxOut(nAmount,opret));
|
mtx.vout.push_back(CTxOut(nAmount,opret));
|
||||||
|
// Return the unspent surplus (selected inputs - burn amount - txfee) as change to a
|
||||||
|
// wallet-owned address; without this the entire surplus is silently paid as miner fee.
|
||||||
|
CAmount change = normalInputs - nAmount - txfee;
|
||||||
|
if ( change > 0 )
|
||||||
|
mtx.vout.push_back(CTxOut(change, GetScriptForDestination(myPubkey.GetID())));
|
||||||
ret.push_back(Pair("hex", EncodeHexTx(mtx)));
|
ret.push_back(Pair("hex", EncodeHexTx(mtx)));
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user