mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-16 13:01:19 +02:00
Merge pull request #1186 from achow101/createfunded-explicit-value
Add include_explicit to walletcreatefundedpsbt
This commit is contained in:
commit
58b5fa0dbf
6 changed files with 48 additions and 7 deletions
|
|
@ -136,8 +136,21 @@ static bool CreateBlindValueProof(std::vector<unsigned char>& rangeproof, const
|
||||||
return res == 1;
|
return res == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CreateBlindValueProof(std::vector<unsigned char>& rangeproof, const uint256& value_blinder, const CAmount amount, const CConfidentialValue& conf_value, const CConfidentialAsset& conf_asset)
|
||||||
|
{
|
||||||
|
secp256k1_pedersen_commitment value_commit;
|
||||||
|
int ret = secp256k1_pedersen_commitment_parse(secp256k1_blind_context, &value_commit, conf_value.vchCommitment.data());
|
||||||
|
assert(ret == 1);
|
||||||
|
|
||||||
|
secp256k1_generator asset_gen;
|
||||||
|
ret = secp256k1_generator_parse(secp256k1_blind_context, &asset_gen, conf_asset.vchCommitment.data());
|
||||||
|
assert(ret == 1);
|
||||||
|
|
||||||
|
return CreateBlindValueProof(rangeproof, value_blinder, amount, value_commit, asset_gen);
|
||||||
|
}
|
||||||
|
|
||||||
// Create an explicit value rangeproof which proves that the commitment commits to an explicit value
|
// Create an explicit value rangeproof which proves that the commitment commits to an explicit value
|
||||||
static bool CreateBlindAssetProof(std::vector<unsigned char>& assetproof, const CAsset& asset, const CConfidentialAsset& asset_commit, const uint256& asset_blinder)
|
bool CreateBlindAssetProof(std::vector<unsigned char>& assetproof, const CAsset& asset, const CConfidentialAsset& asset_commit, const uint256& asset_blinder)
|
||||||
{
|
{
|
||||||
const unsigned char zero32[32] = {0};
|
const unsigned char zero32[32] = {0};
|
||||||
secp256k1_surjectionproof proof;
|
secp256k1_surjectionproof proof;
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@ void CreateValueCommitment(CConfidentialValue& conf_value, secp256k1_pedersen_co
|
||||||
BlindingStatus BlindPSBT(PartiallySignedTransaction& psbt, 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);
|
BlindingStatus BlindPSBT(PartiallySignedTransaction& psbt, 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);
|
||||||
|
|
||||||
|
|
||||||
|
bool CreateBlindValueProof(std::vector<unsigned char>& rangeproof, const uint256& value_blinder, const CAmount amount, const CConfidentialValue& conf_value, const CConfidentialAsset& conf_asset);
|
||||||
|
bool CreateBlindAssetProof(std::vector<unsigned char>& assetproof, const CAsset& asset, const CConfidentialAsset& asset_commit, const uint256& asset_blinder);
|
||||||
bool VerifyBlindValueProof(CAmount value, const CConfidentialValue& conf_value, const std::vector<unsigned char>& proof, const CConfidentialAsset& conf_asset);
|
bool VerifyBlindValueProof(CAmount value, const CConfidentialValue& conf_value, const std::vector<unsigned char>& proof, const CConfidentialAsset& conf_asset);
|
||||||
bool VerifyBlindAssetProof(const uint256& asset, const std::vector<unsigned char>& proof, const CConfidentialAsset& conf_asset);
|
bool VerifyBlindAssetProof(const uint256& asset, const std::vector<unsigned char>& proof, const CConfidentialAsset& conf_asset);
|
||||||
BlindProofResult VerifyBlindProofs(const PSBTOutput& o);
|
BlindProofResult VerifyBlindProofs(const PSBTOutput& o);
|
||||||
|
|
|
||||||
|
|
@ -3337,6 +3337,7 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out,
|
||||||
{"replaceable", UniValueType(UniValue::VBOOL)},
|
{"replaceable", UniValueType(UniValue::VBOOL)},
|
||||||
{"conf_target", UniValueType(UniValue::VNUM)},
|
{"conf_target", UniValueType(UniValue::VNUM)},
|
||||||
{"estimate_mode", UniValueType(UniValue::VSTR)},
|
{"estimate_mode", UniValueType(UniValue::VSTR)},
|
||||||
|
{"include_explicit", UniValueType(UniValue::VBOOL)},
|
||||||
},
|
},
|
||||||
true, true);
|
true, true);
|
||||||
|
|
||||||
|
|
@ -4909,6 +4910,7 @@ static RPCHelpMan walletcreatefundedpsbt()
|
||||||
{"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},
|
{"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},
|
||||||
{"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
|
{"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
|
||||||
" \"" + FeeModes("\"\n\"") + "\""},
|
" \"" + FeeModes("\"\n\"") + "\""},
|
||||||
|
{"include_explicit", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include explicit values and assets and their proofs for blinded inputs"},
|
||||||
},
|
},
|
||||||
"options"},
|
"options"},
|
||||||
{"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include BIP 32 derivation paths for public keys if we know them"},
|
{"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include BIP 32 derivation paths for public keys if we know them"},
|
||||||
|
|
@ -5089,10 +5091,13 @@ static RPCHelpMan walletcreatefundedpsbt()
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Missing output for reissuance tokens");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Missing output for reissuance tokens");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine whether to include explicit values
|
||||||
|
bool include_explicit = request.params[3].exists("include_explicit") && request.params[3]["include_explicit"].get_bool();
|
||||||
|
|
||||||
// Fill transaction with out data but don't sign
|
// Fill transaction with out data but don't sign
|
||||||
bool bip32derivs = request.params[4].isNull() ? true : request.params[4].get_bool();
|
bool bip32derivs = request.params[4].isNull() ? true : request.params[4].get_bool();
|
||||||
bool complete = true;
|
bool complete = true;
|
||||||
const TransactionError err{wallet.FillPSBT(psbtx, complete, 1, false, bip32derivs, true)};
|
const TransactionError err{wallet.FillPSBT(psbtx, complete, 1, false, bip32derivs, true, nullptr, include_explicit)};
|
||||||
if (err != TransactionError::OK) {
|
if (err != TransactionError::OK) {
|
||||||
throw JSONRPCTransactionError(err);
|
throw JSONRPCTransactionError(err);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <wallet/wallet.h>
|
#include <wallet/wallet.h>
|
||||||
|
|
||||||
|
#include <blindpsbt.h>
|
||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
#include <consensus/consensus.h>
|
#include <consensus/consensus.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
|
|
@ -1817,7 +1818,7 @@ bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ELEMENTS: split FillPSBT into FillPSBData and SignPSBT
|
// ELEMENTS: split FillPSBT into FillPSBData and SignPSBT
|
||||||
TransactionError CWallet::FillPSBTData(PartiallySignedTransaction& psbtx, bool bip32derivs) const
|
TransactionError CWallet::FillPSBTData(PartiallySignedTransaction& psbtx, bool bip32derivs, bool include_explicit) const
|
||||||
{
|
{
|
||||||
const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
|
const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
|
|
@ -1841,6 +1842,17 @@ TransactionError CWallet::FillPSBTData(PartiallySignedTransaction& psbtx, bool b
|
||||||
if (*input.prev_out < wtx.tx->witness.vtxoutwit.size() && !wtx.tx->witness.vtxoutwit[*input.prev_out].vchRangeproof.empty()) {
|
if (*input.prev_out < wtx.tx->witness.vtxoutwit.size() && !wtx.tx->witness.vtxoutwit[*input.prev_out].vchRangeproof.empty()) {
|
||||||
input.m_utxo_rangeproof = wtx.tx->witness.vtxoutwit[*input.prev_out].vchRangeproof;
|
input.m_utxo_rangeproof = wtx.tx->witness.vtxoutwit[*input.prev_out].vchRangeproof;
|
||||||
}
|
}
|
||||||
|
const CTxOut& utxo = wtx.tx->vout[*input.prev_out];
|
||||||
|
if (include_explicit && utxo.nAsset.IsCommitment()) {
|
||||||
|
const CAsset asset = wtx.GetOutputAsset(*input.prev_out);
|
||||||
|
input.m_explicit_asset = asset.id;
|
||||||
|
CreateBlindAssetProof(input.m_asset_proof, asset, utxo.nAsset, wtx.GetOutputAssetBlindingFactor(*input.prev_out));
|
||||||
|
|
||||||
|
if (utxo.nValue.IsCommitment()) {
|
||||||
|
input.m_explicit_value = wtx.GetOutputValueOut(*input.prev_out);
|
||||||
|
CreateBlindValueProof(input.m_value_proof, wtx.GetOutputAmountBlindingFactor(*input.prev_out), *input.m_explicit_value, utxo.nValue, utxo.nAsset);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2109,11 +2121,11 @@ TransactionError CWallet::SignPSBT(PartiallySignedTransaction& psbtx, bool& comp
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function remains for backwards compatibility. It will not succeed in Elements unless everything involved is non-blinded.
|
// This function remains for backwards compatibility. It will not succeed in Elements unless everything involved is non-blinded.
|
||||||
TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs, bool imbalance_ok, size_t* n_signed) const
|
TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs, bool imbalance_ok, size_t* n_signed, bool include_explicit) const
|
||||||
{
|
{
|
||||||
complete = false;
|
complete = false;
|
||||||
TransactionError te;
|
TransactionError te;
|
||||||
te = FillPSBTData(psbtx, bip32derivs);
|
te = FillPSBTData(psbtx, bip32derivs, include_explicit);
|
||||||
if (te != TransactionError::OK) {
|
if (te != TransactionError::OK) {
|
||||||
return te;
|
return te;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -608,10 +608,11 @@ public:
|
||||||
bool sign = true,
|
bool sign = true,
|
||||||
bool bip32derivs = true,
|
bool bip32derivs = true,
|
||||||
bool imbalance_ok = false,
|
bool imbalance_ok = false,
|
||||||
size_t* n_signed = nullptr) const;
|
size_t* n_signed = nullptr,
|
||||||
|
bool include_explicit = false) const;
|
||||||
|
|
||||||
// ELEMENTS
|
// ELEMENTS
|
||||||
TransactionError FillPSBTData(PartiallySignedTransaction& psbtx, bool bip32derivs = false) const;
|
TransactionError FillPSBTData(PartiallySignedTransaction& psbtx, bool bip32derivs = false, bool include_explicit = 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;
|
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;
|
BlindingStatus WalletBlindPSBT(PartiallySignedTransaction& psbtx) const;
|
||||||
// end ELEMENTS
|
// end ELEMENTS
|
||||||
|
|
|
||||||
|
|
@ -679,6 +679,14 @@ class PSBTTest(BitcoinTestFramework):
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
|
# Check include_explicit option
|
||||||
|
psbt = self.nodes[2].walletcreatefundedpsbt([{"txid": txid_conf_2, "vout": 1}], [{self.get_address(True, 0): 24.998, "blinder_index": 0}, {"fee": 0.001}], 0, {"include_explicit": True})["psbt"]
|
||||||
|
decoded = self.nodes[1].decodepsbt(psbt)
|
||||||
|
assert "explicit_value" in decoded["inputs"][0]
|
||||||
|
assert "value_proof" in decoded["inputs"][0]
|
||||||
|
assert "explicit_asset" in decoded["inputs"][0]
|
||||||
|
assert "asset_proof" in decoded["inputs"][0]
|
||||||
|
|
||||||
# Try to send conf->conf
|
# Try to send conf->conf
|
||||||
conf_addr_4 = self.get_address(True, 0)
|
conf_addr_4 = self.get_address(True, 0)
|
||||||
psbt = self.nodes[2].createpsbt([{"txid": txid_conf_2, "vout": 1}], [{conf_addr_4: 24.998, "blinder_index": 0}, {"fee": 0.001}])
|
psbt = self.nodes[2].createpsbt([{"txid": txid_conf_2, "vout": 1}], [{conf_addr_4: 24.998, "blinder_index": 0}, {"fee": 0.001}])
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue