mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-16 13:01:19 +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;
|
||||
|
||||
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()) {
|
||||
// Rangeproof must exist
|
||||
if (tx.wit.vtxinwit.size() <= nIn) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Transaction issuance is already blinded but has no attached rangeproof."));
|
||||
}
|
||||
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 asset_blinding_factor;
|
||||
CAmount amount;
|
||||
|
|
@ -728,29 +730,29 @@ void FillBlinds(CMutableTransaction& tx, bool fUseWallet, std::vector<uint256>&
|
|||
// Wipe out confidential info from issuance
|
||||
vchRangeproof.clear();
|
||||
confValue = CConfidentialValue(amount);
|
||||
// One key both blinded values, single key needed for issuance reveal
|
||||
asset_keys.push_back(pwalletMain->GetBlindingKey(&blindingScript));
|
||||
token_keys.push_back(pwalletMain->GetBlindingKey(&blindingScript));
|
||||
// One key blinds both values, single key needed for issuance reveal
|
||||
issuance_blinding_keys.push_back(pwalletMain->GetBlindingKey(&blindingScript));
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
// If no wallet, or unable to unblind, leave it alone in next blinding step
|
||||
asset_keys.push_back(CKey());
|
||||
token_keys.push_back(CKey());
|
||||
} else {
|
||||
issuance_blinding_keys.push_back(CKey());
|
||||
|
||||
} else if (confValue.IsExplicit()) {
|
||||
// Without wallet, nothing to be done.
|
||||
asset_keys.push_back(CKey());
|
||||
token_keys.push_back(CKey());
|
||||
issuance_blinding_keys.push_back(CKey());
|
||||
#ifdef ENABLE_WALLET
|
||||
// Use wallet to generate blindingkey used directly as nonce
|
||||
// as user is not "sending" to anyone.
|
||||
// Always assumed we want to blind here.
|
||||
// TODO Signal intent for all blinding via API including replacing nonce commitment
|
||||
if (fUseWallet) {
|
||||
asset_keys[asset_keys.size()-1] = pwalletMain->GetBlindingKey(&blindingScript);
|
||||
token_keys[token_keys.size()-1] = pwalletMain->GetBlindingKey(&blindingScript);
|
||||
issuance_blinding_keys[issuance_blinding_keys.size()-1] = pwalletMain->GetBlindingKey(&blindingScript);
|
||||
}
|
||||
#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 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"
|
||||
"You can not blind issuances with this call.\n"
|
||||
|
||||
"\nArguments:\n"
|
||||
"1. \"hexstring\", (string, required) A hex-encoded raw transaction.\n"
|
||||
|
|
@ -903,9 +906,9 @@ UniValue rawblindrawtransaction(const JSONRPCRequest& request)
|
|||
#ifdef ENABLE_WALLET
|
||||
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(
|
||||
"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"
|
||||
"Returns the hex-encoded raw transaction.\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"
|
||||
"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"
|
||||
"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"
|
||||
" Null commitments must be \"\".\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"
|
||||
"\"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));
|
||||
} else if (request.params.size() == 3){
|
||||
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 {
|
||||
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"));
|
||||
|
|
@ -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);
|
||||
|
||||
|
||||
std::vector<uint256> input_blinds;
|
||||
std::vector<uint256> input_asset_blinds;
|
||||
std::vector<CAsset> input_assets;
|
||||
|
|
@ -976,6 +986,7 @@ UniValue blindrawtransaction(const JSONRPCRequest& request)
|
|||
std::vector<uint256> output_asset_blinds;
|
||||
std::vector<CAsset> output_assets;
|
||||
std::vector<CPubKey> output_pubkeys;
|
||||
std::vector<CKey> blind_issuance_asset;
|
||||
int n_blinded_ins = 0;
|
||||
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> 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);
|
||||
|
||||
if (!blind_issuances) {
|
||||
asset_keys.clear();
|
||||
token_keys.clear();
|
||||
}
|
||||
|
||||
// How many are we trying to blind?
|
||||
int numPubKeys = 0;
|
||||
unsigned int keyIndex = 0;
|
||||
|
|
@ -1026,6 +1043,12 @@ UniValue blindrawtransaction(const JSONRPCRequest& request)
|
|||
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) {
|
||||
// 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
|
||||
// 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?"));
|
||||
|
|
@ -1567,7 +1590,7 @@ static const CRPCCommand commands[] =
|
|||
{ "rawtransactions", "signrawtransaction", &signrawtransaction, false, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */
|
||||
{ "rawtransactions", "rawblindrawtransaction", &rawblindrawtransaction, false, {}},
|
||||
#ifdef ENABLE_WALLET
|
||||
{ "rawtransactions", "blindrawtransaction", &blindrawtransaction, true, {}},
|
||||
{ "rawtransactions", "blindrawtransaction", &blindrawtransaction, true, {"hexstring", "ignoreblindfail", "asset_commitments", "blind_issuances", "totalblinder"}},
|
||||
#endif
|
||||
{ "blockchain", "gettxoutproof", &gettxoutproof, true, {"txids", "blockhash"} },
|
||||
{ "blockchain", "verifytxoutproof", &verifytxoutproof, true, {"proof"} },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue