mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-17 13:07:54 +02:00
Add walletblindpsbt rpc
This commit is contained in:
parent
e7dd046b03
commit
3f6c8bfda1
3 changed files with 99 additions and 5 deletions
|
|
@ -6,6 +6,7 @@
|
|||
#include <amount.h>
|
||||
#include <asset.h>
|
||||
#include <assetsdir.h>
|
||||
#include <blindpsbt.h>
|
||||
#include <block_proof.h>
|
||||
#include <consensus/validation.h>
|
||||
#include <core_io.h>
|
||||
|
|
@ -4865,6 +4866,55 @@ static RPCHelpMan walletprocesspsbt()
|
|||
};
|
||||
}
|
||||
|
||||
static RPCHelpMan walletblindpsbt()
|
||||
{
|
||||
return RPCHelpMan{"walletblindpsbt",
|
||||
"\nUpdate a PSBT with input information from our wallet and then sign inputs\n"
|
||||
"that we can sign for.\n\n" +
|
||||
HELP_REQUIRING_PASSPHRASE,
|
||||
{
|
||||
{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction base64 string"},
|
||||
},
|
||||
RPCResult{
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::STR, "psbt", "The resulting raw transaction (base64-encoded string)"},
|
||||
}
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("walletblindpsbt", "\"psbt\"")
|
||||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
if (!g_con_elementsmode)
|
||||
throw std::runtime_error("PSBT operations are disabled when not in elementsmode.\n");
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VSTR});
|
||||
|
||||
// Unserialize the transaction
|
||||
PartiallySignedTransaction psbtx;
|
||||
std::string error;
|
||||
if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
|
||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
|
||||
}
|
||||
|
||||
if (pwallet->WalletBlindPSBT(psbtx) != BlindingStatus::OK) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Something went wrong");
|
||||
}
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ssTx << psbtx;
|
||||
result.pushKV("psbt", EncodeBase64(ssTx.str()));
|
||||
|
||||
return result;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static RPCHelpMan walletcreatefundedpsbt()
|
||||
{
|
||||
return RPCHelpMan{"walletcreatefundedpsbt",
|
||||
|
|
@ -7106,6 +7156,7 @@ static const CRPCCommand commands[] =
|
|||
{ "wallet", "issueasset", &issueasset, {"assetamount", "tokenamount", "blind"}},
|
||||
{ "wallet", "reissueasset", &reissueasset, {"asset", "assetamount"}},
|
||||
{ "wallet", "destroyamount", &destroyamount, {"asset", "amount", "comment", "verbose"} },
|
||||
{ "wallet", "walletblindpsbt", &walletblindpsbt, {"psbt"} },
|
||||
{ "hidden", "generatepegoutproof", &generatepegoutproof, {"sumkey", "btcpubkey", "onlinepubkey"} },
|
||||
{ "hidden", "getpegoutkeys", &getpegoutkeys, {"btcprivkey", "offlinepubkey"} },
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1258,16 +1258,21 @@ void CWallet::BlockUntilSyncedToCurrentChain() const {
|
|||
chain().waitForNotificationsIfTipChanged(last_block_hash);
|
||||
}
|
||||
|
||||
|
||||
isminetype CWallet::IsMine(const CTxIn &txin) const
|
||||
isminetype CWallet::IsMine(const CTxIn& txin) const
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
|
||||
return IsMine(txin.prevout);
|
||||
}
|
||||
|
||||
isminetype CWallet::IsMine(const COutPoint &outpoint) const
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(outpoint.hash);
|
||||
if (mi != mapWallet.end())
|
||||
{
|
||||
const CWalletTx& prev = (*mi).second;
|
||||
if (txin.prevout.n < prev.tx->vout.size())
|
||||
return IsMine(prev.tx->vout[txin.prevout.n]);
|
||||
if (outpoint.n < prev.tx->vout.size())
|
||||
return IsMine(prev.tx->vout[outpoint.n]);
|
||||
}
|
||||
return ISMINE_NO;
|
||||
}
|
||||
|
|
@ -2792,6 +2797,41 @@ TransactionError CWallet::FillPSBTData(PartiallySignedTransaction& psbtx, bool b
|
|||
return TransactionError::OK;
|
||||
}
|
||||
|
||||
BlindingStatus CWallet::WalletBlindPSBT(PartiallySignedTransaction& psbtx) const
|
||||
{
|
||||
// Gather our input data
|
||||
LOCK(cs_wallet);
|
||||
std::map<uint32_t, std::tuple<CAmount, CAsset, uint256, uint256>> our_input_data;
|
||||
std::map<uint32_t, std::pair<CKey, CKey>> our_issuances_to_blind;
|
||||
for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
|
||||
PSBTInput& input = psbtx.inputs[i];
|
||||
|
||||
if (input.m_peg_in_value && !input.m_peg_in_claim_script.empty()) {
|
||||
if (!IsMine(CTxOut(Params().GetConsensus().pegged_asset, *input.m_peg_in_value, input.m_peg_in_claim_script))) continue;
|
||||
our_input_data[i] = std::make_tuple(*input.m_peg_in_value, Params().GetConsensus().pegged_asset, uint256(), uint256());
|
||||
} else {
|
||||
if (!IsMine(COutPoint(input.prev_txid, *input.prev_out))) continue;
|
||||
const CWalletTx* wtx = GetWalletTx(input.prev_txid);
|
||||
if (!wtx) continue;
|
||||
CPubKey blinding_pubkey;
|
||||
CAmount amount;
|
||||
uint256 value_blinder;
|
||||
CAsset asset;
|
||||
uint256 asset_blinder;
|
||||
wtx->GetNonIssuanceBlindingData(*input.prev_out, &blinding_pubkey, &amount, &value_blinder, &asset, &asset_blinder);
|
||||
our_input_data[i] = std::make_tuple(amount, asset, asset_blinder, value_blinder);
|
||||
}
|
||||
|
||||
// Blind issuances on our inputs
|
||||
if (input.m_issuance_value || input.m_issuance_inflation_keys_amount) {
|
||||
CScript blinding_script(CScript() << OP_RETURN << std::vector<unsigned char>(input.prev_txid.begin(), input.prev_txid.end()) << *input.prev_out);
|
||||
our_issuances_to_blind[i] = std::make_pair(GetBlindingKey(&blinding_script), GetBlindingKey(&blinding_script));
|
||||
}
|
||||
}
|
||||
|
||||
// Blind the PSBT
|
||||
return BlindPSBT(psbtx, our_input_data, our_issuances_to_blind);
|
||||
}
|
||||
TransactionError CWallet::SignPSBT(PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool imbalance_ok, bool bip32derivs, size_t* n_signed) const
|
||||
{
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <amount.h>
|
||||
#include <asset.h>
|
||||
#include <blindpsbt.h>
|
||||
#include <interfaces/chain.h>
|
||||
#include <interfaces/handler.h>
|
||||
#include <outputtype.h>
|
||||
|
|
@ -1090,6 +1091,7 @@ public:
|
|||
// ELEMENTS
|
||||
TransactionError FillPSBTData(PartiallySignedTransaction& psbtx, bool bip32derivs = false) const;
|
||||
TransactionError SignPSBT(PartiallySignedTransaction& psbtx, bool& complete, int sighash_type = 1, bool sign = true, bool imbalance_ok = false, bool bip32derivs = false, size_t* n_signed = nullptr) const;
|
||||
BlindingStatus WalletBlindPSBT(PartiallySignedTransaction& psbtx) const;
|
||||
// end ELEMENTS
|
||||
|
||||
/**
|
||||
|
|
@ -1172,6 +1174,7 @@ public:
|
|||
isminetype IsMine(const CTxDestination& dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
isminetype IsMine(const CScript& script) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
isminetype IsMine(const CTxIn& txin) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
isminetype IsMine(const COutPoint& txin) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
/**
|
||||
* Returns amount of debit if the input matches the
|
||||
* filter, otherwise returns 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue