mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-17 13:07:54 +02:00
Fixup (raw)blindrawtransaction
This commit is contained in:
parent
a5e9e0e40f
commit
2b22b6dfc6
1 changed files with 42 additions and 19 deletions
|
|
@ -712,14 +712,16 @@ void FillBlinds(CMutableTransaction& tx, bool fUseWallet, std::vector<uint256>&
|
||||||
CScript blindingScript = CScript() << OP_RETURN << std::vector<unsigned char>(tx.vin[nIn].prevout.hash.begin(), tx.vin[nIn].prevout.hash.end()) << tx.vin[nIn].prevout.n;
|
CScript blindingScript = CScript() << OP_RETURN << std::vector<unsigned char>(tx.vin[nIn].prevout.hash.begin(), tx.vin[nIn].prevout.hash.end()) << tx.vin[nIn].prevout.n;
|
||||||
|
|
||||||
for (size_t nPseudo = 0; nPseudo < 2; nPseudo++) {
|
for (size_t nPseudo = 0; nPseudo < 2; nPseudo++) {
|
||||||
CConfidentialValue& confValue = (nPseudo == 0) ? issuance.nAmount : issuance.nInflationKeys;
|
bool issuance_asset = (nPseudo == 0);
|
||||||
|
std::vector<CKey>& issuance_blinding_keys = issuance_asset ? asset_keys : token_keys;
|
||||||
|
CConfidentialValue& confValue = issuance_asset ? issuance.nAmount : issuance.nInflationKeys;
|
||||||
if (confValue.IsCommitment()) {
|
if (confValue.IsCommitment()) {
|
||||||
// Rangeproof must exist
|
// Rangeproof must exist
|
||||||
if (tx.wit.vtxinwit.size() <= nIn) {
|
if (tx.wit.vtxinwit.size() <= nIn) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Transaction issuance is already blinded but has no attached rangeproof."));
|
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Transaction issuance is already blinded but has no attached rangeproof."));
|
||||||
}
|
}
|
||||||
CTxInWitness& txinwit = tx.wit.vtxinwit[nIn];
|
CTxInWitness& txinwit = tx.wit.vtxinwit[nIn];
|
||||||
std::vector<unsigned char>& vchRangeproof = (nPseudo == 0) ? txinwit.vchIssuanceAmountRangeproof : txinwit.vchInflationKeysRangeproof;
|
std::vector<unsigned char>& vchRangeproof = issuance_asset ? txinwit.vchIssuanceAmountRangeproof : txinwit.vchInflationKeysRangeproof;
|
||||||
uint256 blinding_factor;
|
uint256 blinding_factor;
|
||||||
uint256 asset_blinding_factor;
|
uint256 asset_blinding_factor;
|
||||||
CAmount amount;
|
CAmount amount;
|
||||||
|
|
@ -728,29 +730,29 @@ void FillBlinds(CMutableTransaction& tx, bool fUseWallet, std::vector<uint256>&
|
||||||
// Wipe out confidential info from issuance
|
// Wipe out confidential info from issuance
|
||||||
vchRangeproof.clear();
|
vchRangeproof.clear();
|
||||||
confValue = CConfidentialValue(amount);
|
confValue = CConfidentialValue(amount);
|
||||||
// One key both blinded values, single key needed for issuance reveal
|
// One key blinds both values, single key needed for issuance reveal
|
||||||
asset_keys.push_back(pwalletMain->GetBlindingKey(&blindingScript));
|
issuance_blinding_keys.push_back(pwalletMain->GetBlindingKey(&blindingScript));
|
||||||
token_keys.push_back(pwalletMain->GetBlindingKey(&blindingScript));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// If no wallet, or unable to unblind, leave it alone in next blinding step
|
// If no wallet, or unable to unblind, leave it alone in next blinding step
|
||||||
asset_keys.push_back(CKey());
|
issuance_blinding_keys.push_back(CKey());
|
||||||
token_keys.push_back(CKey());
|
|
||||||
} else {
|
} else if (confValue.IsExplicit()) {
|
||||||
// Without wallet, nothing to be done.
|
// Without wallet, nothing to be done.
|
||||||
asset_keys.push_back(CKey());
|
issuance_blinding_keys.push_back(CKey());
|
||||||
token_keys.push_back(CKey());
|
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
// Use wallet to generate blindingkey used directly as nonce
|
// Use wallet to generate blindingkey used directly as nonce
|
||||||
// as user is not "sending" to anyone.
|
// as user is not "sending" to anyone.
|
||||||
// Always assumed we want to blind here.
|
// Always assumed we want to blind here.
|
||||||
// TODO Signal intent for all blinding via API including replacing nonce commitment
|
// TODO Signal intent for all blinding via API including replacing nonce commitment
|
||||||
if (fUseWallet) {
|
if (fUseWallet) {
|
||||||
asset_keys[asset_keys.size()-1] = pwalletMain->GetBlindingKey(&blindingScript);
|
issuance_blinding_keys[issuance_blinding_keys.size()-1] = pwalletMain->GetBlindingKey(&blindingScript);
|
||||||
token_keys[token_keys.size()-1] = pwalletMain->GetBlindingKey(&blindingScript);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
} else {
|
||||||
|
// Null or invalid, don't try anything but append an empty key
|
||||||
|
issuance_blinding_keys.push_back(CKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -766,6 +768,7 @@ UniValue rawblindrawtransaction(const JSONRPCRequest& request)
|
||||||
"The input raw transaction cannot have already-blinded outputs.\n"
|
"The input raw transaction cannot have already-blinded outputs.\n"
|
||||||
"The output keys used can be specified by using a confidential address in createrawtransaction.\n"
|
"The output keys used can be specified by using a confidential address in createrawtransaction.\n"
|
||||||
"If an additional blinded output is required to make a balanced blinding, a 0-value unspendable output will be added. Since there is no access to the wallet the blinding pubkey from the last output with blinding key will be repeated.\n"
|
"If an additional blinded output is required to make a balanced blinding, a 0-value unspendable output will be added. Since there is no access to the wallet the blinding pubkey from the last output with blinding key will be repeated.\n"
|
||||||
|
"You can not blind issuances with this call.\n"
|
||||||
|
|
||||||
"\nArguments:\n"
|
"\nArguments:\n"
|
||||||
"1. \"hexstring\", (string, required) A hex-encoded raw transaction.\n"
|
"1. \"hexstring\", (string, required) A hex-encoded raw transaction.\n"
|
||||||
|
|
@ -903,9 +906,9 @@ UniValue rawblindrawtransaction(const JSONRPCRequest& request)
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
UniValue blindrawtransaction(const JSONRPCRequest& request)
|
UniValue blindrawtransaction(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
if (request.fHelp || (request.params.size() < 1 || request.params.size() > 4))
|
if (request.fHelp || (request.params.size() < 1 || request.params.size() > 5))
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"blindrawtransaction \"hexstring\" ( ignoreblindfail [\"assetcommitment,...\"] totalblinder )\n"
|
"blindrawtransaction \"hexstring\" ( ignoreblindfail [\"assetcommitment,...\"] blind_issuances \"totalblinder\" )\n"
|
||||||
"\nConvert one or more outputs of a raw transaction into confidential ones using only wallet inputs.\n"
|
"\nConvert one or more outputs of a raw transaction into confidential ones using only wallet inputs.\n"
|
||||||
"Returns the hex-encoded raw transaction.\n"
|
"Returns the hex-encoded raw transaction.\n"
|
||||||
"The output keys used can be specified by using a confidential address in createrawtransaction.\n"
|
"The output keys used can be specified by using a confidential address in createrawtransaction.\n"
|
||||||
|
|
@ -914,11 +917,13 @@ UniValue blindrawtransaction(const JSONRPCRequest& request)
|
||||||
"\nArguments:\n"
|
"\nArguments:\n"
|
||||||
"1. \"hexstring\", (string, required) A hex-encoded raw transaction.\n"
|
"1. \"hexstring\", (string, required) A hex-encoded raw transaction.\n"
|
||||||
"2. \"ignoreblindfail\"\" (bool, optional, default=true) Return a transaction even when a blinding attempt fails due to number of blinded inputs/outputs.\n"
|
"2. \"ignoreblindfail\"\" (bool, optional, default=true) Return a transaction even when a blinding attempt fails due to number of blinded inputs/outputs.\n"
|
||||||
"3. [ (array, optional) An array of input asset generators. If provided, this list must be empty, or match the final input commitment list, including ordering, to make a valid surjection proof. This list does not include generators for issuances, as these assets are inherently unblinded.\n"
|
"3. \"asset_commitments\" \n"
|
||||||
|
" [ (array, optional) An array of input asset generators. If provided, this list must be empty, or match the final input commitment list, including ordering, to make a valid surjection proof. This list does not include generators for issuances, as these assets are inherently unblinded.\n"
|
||||||
" \"assetcommitment\" (string, optional) A hex-encoded asset commitment, one for each input.\n"
|
" \"assetcommitment\" (string, optional) A hex-encoded asset commitment, one for each input.\n"
|
||||||
" Null commitments must be \"\".\n"
|
" Null commitments must be \"\".\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
"4. \"totalblinder\" (string, optional) Ignored for now.\n"
|
"4. \"blind_issuances\" (bool, optional, default=true) Blind the issuances found in the raw transaction or not. All issuances will be blinded if true. \n"
|
||||||
|
"5. \"totalblinder\" (string, optional) Ignored for now.\n"
|
||||||
|
|
||||||
"\nResult:\n"
|
"\nResult:\n"
|
||||||
"\"transaction\" (string) hex string of the transaction\n"
|
"\"transaction\" (string) hex string of the transaction\n"
|
||||||
|
|
@ -930,8 +935,10 @@ UniValue blindrawtransaction(const JSONRPCRequest& request)
|
||||||
RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
|
RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
|
||||||
} else if (request.params.size() == 3){
|
} else if (request.params.size() == 3){
|
||||||
RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL)(UniValue::VARR));
|
RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL)(UniValue::VARR));
|
||||||
|
} else if (request.params.size() == 4){
|
||||||
|
RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL)(UniValue::VARR)(UniValue::VBOOL));
|
||||||
} else {
|
} else {
|
||||||
RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL)(UniValue::VARR)(UniValue::VSTR));
|
RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL)(UniValue::VARR)(UniValue::VBOOL)(UniValue::VSTR));
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<unsigned char> txData(ParseHexV(request.params[0], "argument 1"));
|
vector<unsigned char> txData(ParseHexV(request.params[0], "argument 1"));
|
||||||
|
|
@ -966,8 +973,11 @@ UniValue blindrawtransaction(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool blind_issuances = request.params[3].isNull() || request.params[3].get_bool();
|
||||||
|
|
||||||
LOCK(pwalletMain->cs_wallet);
|
LOCK(pwalletMain->cs_wallet);
|
||||||
|
|
||||||
|
|
||||||
std::vector<uint256> input_blinds;
|
std::vector<uint256> input_blinds;
|
||||||
std::vector<uint256> input_asset_blinds;
|
std::vector<uint256> input_asset_blinds;
|
||||||
std::vector<CAsset> input_assets;
|
std::vector<CAsset> input_assets;
|
||||||
|
|
@ -976,6 +986,7 @@ UniValue blindrawtransaction(const JSONRPCRequest& request)
|
||||||
std::vector<uint256> output_asset_blinds;
|
std::vector<uint256> output_asset_blinds;
|
||||||
std::vector<CAsset> output_assets;
|
std::vector<CAsset> output_assets;
|
||||||
std::vector<CPubKey> output_pubkeys;
|
std::vector<CPubKey> output_pubkeys;
|
||||||
|
std::vector<CKey> blind_issuance_asset;
|
||||||
int n_blinded_ins = 0;
|
int n_blinded_ins = 0;
|
||||||
for (size_t nIn = 0; nIn < tx.vin.size(); nIn++) {
|
for (size_t nIn = 0; nIn < tx.vin.size(); nIn++) {
|
||||||
|
|
||||||
|
|
@ -1014,8 +1025,14 @@ UniValue blindrawtransaction(const JSONRPCRequest& request)
|
||||||
|
|
||||||
std::vector<CKey> asset_keys;
|
std::vector<CKey> asset_keys;
|
||||||
std::vector<CKey> token_keys;
|
std::vector<CKey> token_keys;
|
||||||
|
// This fills out issuance blinding data for you from the wallet itself
|
||||||
FillBlinds(tx, true, output_blinds, output_asset_blinds, output_pubkeys, asset_keys, token_keys);
|
FillBlinds(tx, true, output_blinds, output_asset_blinds, output_pubkeys, asset_keys, token_keys);
|
||||||
|
|
||||||
|
if (!blind_issuances) {
|
||||||
|
asset_keys.clear();
|
||||||
|
token_keys.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// How many are we trying to blind?
|
// How many are we trying to blind?
|
||||||
int numPubKeys = 0;
|
int numPubKeys = 0;
|
||||||
unsigned int keyIndex = 0;
|
unsigned int keyIndex = 0;
|
||||||
|
|
@ -1026,6 +1043,12 @@ UniValue blindrawtransaction(const JSONRPCRequest& request)
|
||||||
keyIndex = i;
|
keyIndex = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const auto& key : asset_keys) {
|
||||||
|
if (key.IsValid()) numPubKeys++;
|
||||||
|
}
|
||||||
|
for (const auto& key : token_keys) {
|
||||||
|
if (key.IsValid()) numPubKeys++;
|
||||||
|
}
|
||||||
|
|
||||||
if (numPubKeys == 0 && n_blinded_ins == 0) {
|
if (numPubKeys == 0 && n_blinded_ins == 0) {
|
||||||
// Vacuous, just return the transaction
|
// Vacuous, just return the transaction
|
||||||
|
|
@ -1046,7 +1069,7 @@ UniValue blindrawtransaction(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BlindTransaction(input_blinds, input_asset_blinds, input_assets, input_amounts, output_blinds, output_asset_blinds, output_pubkeys, std::vector<CKey>(), std::vector<CKey>(), tx, (auxiliary_generators.size() ? &auxiliary_generators : NULL)) != numPubKeys) {
|
if (BlindTransaction(input_blinds, input_asset_blinds, input_assets, input_amounts, output_blinds, output_asset_blinds, output_pubkeys, asset_keys, token_keys, tx, (auxiliary_generators.size() ? &auxiliary_generators : NULL)) != numPubKeys) {
|
||||||
// TODO Have more rich return values, communicating to user what has been blinded
|
// TODO Have more rich return values, communicating to user what has been blinded
|
||||||
// User may be ok not blinding something that for instance has no corresponding type on input
|
// User may be ok not blinding something that for instance has no corresponding type on input
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Unable to blind transaction: Are you sure each asset type to blind is represented in the inputs?"));
|
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Unable to blind transaction: Are you sure each asset type to blind is represented in the inputs?"));
|
||||||
|
|
@ -1567,7 +1590,7 @@ static const CRPCCommand commands[] =
|
||||||
{ "rawtransactions", "signrawtransaction", &signrawtransaction, false, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */
|
{ "rawtransactions", "signrawtransaction", &signrawtransaction, false, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */
|
||||||
{ "rawtransactions", "rawblindrawtransaction", &rawblindrawtransaction, false, {}},
|
{ "rawtransactions", "rawblindrawtransaction", &rawblindrawtransaction, false, {}},
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
{ "rawtransactions", "blindrawtransaction", &blindrawtransaction, true, {}},
|
{ "rawtransactions", "blindrawtransaction", &blindrawtransaction, true, {"hexstring", "ignoreblindfail", "asset_commitments", "blind_issuances", "totalblinder"}},
|
||||||
#endif
|
#endif
|
||||||
{ "blockchain", "gettxoutproof", &gettxoutproof, true, {"txids", "blockhash"} },
|
{ "blockchain", "gettxoutproof", &gettxoutproof, true, {"txids", "blockhash"} },
|
||||||
{ "blockchain", "verifytxoutproof", &verifytxoutproof, true, {"proof"} },
|
{ "blockchain", "verifytxoutproof", &verifytxoutproof, true, {"proof"} },
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue