Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[backport] Backport #1121 and #1131 to elements-22.x for rc3 #1137

Merged
merged 18 commits into from
Aug 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ AC_PREREQ([2.69])
define(_CLIENT_VERSION_MAJOR, 22)
define(_CLIENT_VERSION_MINOR, 0)
define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_RC, 2)
define(_CLIENT_VERSION_RC, 3)
define(_CLIENT_VERSION_IS_RELEASE, true)
define(_COPYRIGHT_YEAR, 2021)
define(_COPYRIGHT_HOLDERS,[The %s developers])
Expand Down
4 changes: 3 additions & 1 deletion src/blindpsbt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,11 +361,13 @@ BlindingStatus BlindPSBT(PartiallySignedTransaction& psbt, std::map<uint32_t, st
if (secp256k1_generator_generate(secp256k1_blind_context, &ephemeral_input_tags.back(), asset.GetAsset().begin()) != 1) {
return BlindingStatus::INVALID_ASSET;
}
} else {
} else if (asset.IsCommitment()) {
// Parse the asset commitment as a generator (because it is)
if (secp256k1_generator_parse(secp256k1_blind_context, &ephemeral_input_tags.back(), asset.vchCommitment.data()) != 1) {
return BlindingStatus::INVALID_ASSET_COMMITMENT;
}
} else {
return BlindingStatus::INVALID_ASSET; // Missing asset
}

fixed_input_tags.emplace_back();
Expand Down
44 changes: 25 additions & 19 deletions src/psbt.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ template<typename Stream, typename... X>
void UnserializeFromVector(Stream& s, X&... args)
{
size_t expected_size = ReadCompactSize(s);
if (!expected_size) {
return; /* Zero size = no data to read */
}
size_t remaining_before = s.size();
UnserializeMany(s, args...);
size_t remaining_after = s.size();
Expand Down Expand Up @@ -343,15 +346,15 @@ struct PSBTInput
}

// Elements proprietary fields are only allowed with v2
// Issuance value
if (!m_issuance_value_commitment.IsNull()) {
SerializeToVector(s, CompactSizeWriter(PSBT_IN_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_IN_ISSUANCE_VALUE_COMMITMENT));
SerializeToVector(s, m_issuance_value_commitment);
}
// Issuance value + commitment
if (m_issuance_value != std::nullopt) {
SerializeToVector(s, CompactSizeWriter(PSBT_IN_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_IN_ISSUANCE_VALUE));
SerializeToVector(s, *m_issuance_value);
}
if (!m_issuance_value_commitment.IsNull()) {
SerializeToVector(s, CompactSizeWriter(PSBT_IN_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_IN_ISSUANCE_VALUE_COMMITMENT));
SerializeToVector(s, m_issuance_value_commitment);
}

// Issuance rangeproof
if (!m_issuance_rangeproof.empty()) {
Expand Down Expand Up @@ -995,8 +998,12 @@ struct PSBTOutput
SerializeHDKeypaths(s, hd_keypaths, CompactSizeWriter(PSBT_OUT_BIP32_DERIVATION));

if (m_psbt_version >= 2) {
// Write spk
if (script != std::nullopt) {
// Write amount and spk
if (amount != std::nullopt) {
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_AMOUNT));
SerializeToVector(s, *amount);
}
if (script.has_value()) {
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_SCRIPT));
s << *script;
}
Expand All @@ -1007,20 +1014,16 @@ struct PSBTOutput
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_OUT_VALUE_COMMITMENT));
SerializeToVector(s, m_value_commitment);
}
if (amount != std::nullopt) {
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_AMOUNT));
SerializeToVector(s, *amount);
}

// Asset
if (!m_asset_commitment.IsNull()) {
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_OUT_ASSET_COMMITMENT));
SerializeToVector(s, m_asset_commitment);
}
// Asset + commitment
if (!m_asset.IsNull()) {
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_OUT_ASSET));
SerializeToVector(s, m_asset);
}
if (!m_asset_commitment.IsNull()) {
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_OUT_ASSET_COMMITMENT));
SerializeToVector(s, m_asset_commitment);
}

// Value rangeproof
if (!m_value_rangeproof.empty()) {
Expand Down Expand Up @@ -1052,13 +1055,13 @@ struct PSBTOutput
SerializeToVector(s, *m_blinder_index);
}

// BLind value proof
// Blind value proof
if (!m_blind_value_proof.empty()) {
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_OUT_BLIND_VALUE_PROOF));
s << m_blind_value_proof;
}

// BLind asset proof
// Blind asset proof
if (!m_blind_asset_proof.empty()) {
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_OUT_BLIND_ASSET_PROOF));
s << m_blind_asset_proof;
Expand Down Expand Up @@ -1423,7 +1426,7 @@ struct PartiallySignedTransaction
// Scalar offsets
for (const uint256& scalar : m_scalar_offsets) {
SerializeToVector(s, CompactSizeWriter(PSBT_GLOBAL_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_GLOBAL_SCALAR), scalar);
SerializeToVector(s, std::vector<unsigned char>());
s << PSBT_SEPARATOR; /* Zero length data value */
}
}

Expand Down Expand Up @@ -1659,6 +1662,9 @@ struct PartiallySignedTransaction
m_scalar_offsets.insert(scalar);
break;
}
default:
known = false;
break;
}
}

Expand Down
40 changes: 40 additions & 0 deletions src/rpc/rawtransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2237,6 +2237,45 @@ static RPCHelpMan utxoupdatepsbt()
};
}

static RPCHelpMan parsepsbt()
{
return RPCHelpMan{"parsepsbt",
"\nparse and print a PSBT.\n",
{
{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"}
},
RPCResult {
RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::STR, "psbt", "The base64-encoded partially signed transaction"},
{RPCResult::Type::BOOL, "canonical", "Whether the input PSBT matches the output PSBT"}
}
},
RPCExamples {
HelpExampleCli("parsepsbt", "\"psbt\"")
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
RPCTypeCheck(request.params, {UniValue::VSTR}, true);

// Unserialize the PSBT
PartiallySignedTransaction psbtx;
std::string error;
if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("PSBT decode failed %s", error));
}

// Serialize the PSBT
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << psbtx;
const std::string encoded = EncodeBase64(ssTx);
UniValue result(UniValue::VOBJ);
result.pushKV("psbt", encoded);
result.pushKV("canonical", encoded == request.params[0].get_str());
return result;
},
};
}
#if 0
static RPCHelpMan joinpsbts()
{
Expand Down Expand Up @@ -3207,6 +3246,7 @@ static const CRPCCommand commands[] =
{ "rawtransactions", &createpsbt, },
{ "rawtransactions", &converttopsbt, },
{ "rawtransactions", &utxoupdatepsbt, },
{ "rawtransactions", &parsepsbt, },
#if 0
{ "rawtransactions", &joinpsbts, },
#endif
Expand Down
1 change: 1 addition & 0 deletions src/test/fuzz/rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
"getnewblockhex",
"getpakinfo",
"getsidechaininfo",
"parsepsbt",
"rawblindrawtransaction",
"rawissueasset",
"rawreissueasset",
Expand Down
11 changes: 5 additions & 6 deletions src/wallet/rpcdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2112,7 +2112,8 @@ RPCHelpMan importissuanceblindingkey()
RPCHelpMan dumpblindingkey()
{
return RPCHelpMan{"dumpblindingkey",
"\nDumps the private blinding key for a CT address in hex.",
"\nDumps the private blinding key for a CT address in hex."
"\nNote: If the address is not a CT address, looks for blinding key corresponding to this non-CT address.",
{
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The CT address"},
},
Expand All @@ -2134,17 +2135,15 @@ RPCHelpMan dumpblindingkey()
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
}
if (!IsBlindDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Not a CT address");
}
CScript script = GetScriptForDestination(dest);
CKey key;
key = pwallet->GetBlindingKey(&script);
if (key.IsValid()) {
CPubKey pubkey(key.GetPubKey());
if (pubkey == GetDestinationBlindingKey(dest)) {
return HexStr(Span<const unsigned char>(key.begin(), key.size()));
if (IsBlindDestination(dest) && pubkey != GetDestinationBlindingKey(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "CT address blinding key does not match the blinding key in wallet");
}
return HexStr(Span<const unsigned char>(key.begin(), key.size()));
}

throw JSONRPCError(RPC_WALLET_ERROR, "Blinding key for address is unknown");
Expand Down
5 changes: 5 additions & 0 deletions test/functional/feature_confidential_transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@ def run_test(self):

# Import the blinding key
blindingkey = self.nodes[2].dumpblindingkey(address2)

# Check that importing keys from non-CT address works as intended
blindingkey2 = self.nodes[2].dumpblindingkey(unconfidential_address2)
assert_equal(blindingkey, blindingkey2)

self.nodes[1].importblindingkey(address2, blindingkey)
# Check the auditor's gettransaction and listreceivedbyaddress
# Needs rescan to update wallet txns
Expand Down
Loading