Skip to content

Commit fdeaa49

Browse files
authored
Merge pull request #1137 from gwillen/release-backports-22
[backport] Backport #1121 and #1131 to elements-22.x for rc3
2 parents 22fc036 + a17887b commit fdeaa49

File tree

8 files changed

+98
-40
lines changed

8 files changed

+98
-40
lines changed

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ AC_PREREQ([2.69])
22
define(_CLIENT_VERSION_MAJOR, 22)
33
define(_CLIENT_VERSION_MINOR, 0)
44
define(_CLIENT_VERSION_BUILD, 0)
5-
define(_CLIENT_VERSION_RC, 2)
5+
define(_CLIENT_VERSION_RC, 3)
66
define(_CLIENT_VERSION_IS_RELEASE, true)
77
define(_COPYRIGHT_YEAR, 2021)
88
define(_COPYRIGHT_HOLDERS,[The %s developers])

src/blindpsbt.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,11 +361,13 @@ BlindingStatus BlindPSBT(PartiallySignedTransaction& psbt, std::map<uint32_t, st
361361
if (secp256k1_generator_generate(secp256k1_blind_context, &ephemeral_input_tags.back(), asset.GetAsset().begin()) != 1) {
362362
return BlindingStatus::INVALID_ASSET;
363363
}
364-
} else {
364+
} else if (asset.IsCommitment()) {
365365
// Parse the asset commitment as a generator (because it is)
366366
if (secp256k1_generator_parse(secp256k1_blind_context, &ephemeral_input_tags.back(), asset.vchCommitment.data()) != 1) {
367367
return BlindingStatus::INVALID_ASSET_COMMITMENT;
368368
}
369+
} else {
370+
return BlindingStatus::INVALID_ASSET; // Missing asset
369371
}
370372

371373
fixed_input_tags.emplace_back();

src/psbt.h

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ template<typename Stream, typename... X>
137137
void UnserializeFromVector(Stream& s, X&... args)
138138
{
139139
size_t expected_size = ReadCompactSize(s);
140+
if (!expected_size) {
141+
return; /* Zero size = no data to read */
142+
}
140143
size_t remaining_before = s.size();
141144
UnserializeMany(s, args...);
142145
size_t remaining_after = s.size();
@@ -343,15 +346,15 @@ struct PSBTInput
343346
}
344347

345348
// Elements proprietary fields are only allowed with v2
346-
// Issuance value
347-
if (!m_issuance_value_commitment.IsNull()) {
348-
SerializeToVector(s, CompactSizeWriter(PSBT_IN_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_IN_ISSUANCE_VALUE_COMMITMENT));
349-
SerializeToVector(s, m_issuance_value_commitment);
350-
}
349+
// Issuance value + commitment
351350
if (m_issuance_value != std::nullopt) {
352351
SerializeToVector(s, CompactSizeWriter(PSBT_IN_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_IN_ISSUANCE_VALUE));
353352
SerializeToVector(s, *m_issuance_value);
354353
}
354+
if (!m_issuance_value_commitment.IsNull()) {
355+
SerializeToVector(s, CompactSizeWriter(PSBT_IN_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_IN_ISSUANCE_VALUE_COMMITMENT));
356+
SerializeToVector(s, m_issuance_value_commitment);
357+
}
355358

356359
// Issuance rangeproof
357360
if (!m_issuance_rangeproof.empty()) {
@@ -995,8 +998,12 @@ struct PSBTOutput
995998
SerializeHDKeypaths(s, hd_keypaths, CompactSizeWriter(PSBT_OUT_BIP32_DERIVATION));
996999

9971000
if (m_psbt_version >= 2) {
998-
// Write spk
999-
if (script != std::nullopt) {
1001+
// Write amount and spk
1002+
if (amount != std::nullopt) {
1003+
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_AMOUNT));
1004+
SerializeToVector(s, *amount);
1005+
}
1006+
if (script.has_value()) {
10001007
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_SCRIPT));
10011008
s << *script;
10021009
}
@@ -1007,20 +1014,16 @@ struct PSBTOutput
10071014
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_OUT_VALUE_COMMITMENT));
10081015
SerializeToVector(s, m_value_commitment);
10091016
}
1010-
if (amount != std::nullopt) {
1011-
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_AMOUNT));
1012-
SerializeToVector(s, *amount);
1013-
}
10141017

1015-
// Asset
1016-
if (!m_asset_commitment.IsNull()) {
1017-
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_OUT_ASSET_COMMITMENT));
1018-
SerializeToVector(s, m_asset_commitment);
1019-
}
1018+
// Asset + commitment
10201019
if (!m_asset.IsNull()) {
10211020
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_OUT_ASSET));
10221021
SerializeToVector(s, m_asset);
10231022
}
1023+
if (!m_asset_commitment.IsNull()) {
1024+
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_OUT_ASSET_COMMITMENT));
1025+
SerializeToVector(s, m_asset_commitment);
1026+
}
10241027

10251028
// Value rangeproof
10261029
if (!m_value_rangeproof.empty()) {
@@ -1052,13 +1055,13 @@ struct PSBTOutput
10521055
SerializeToVector(s, *m_blinder_index);
10531056
}
10541057

1055-
// BLind value proof
1058+
// Blind value proof
10561059
if (!m_blind_value_proof.empty()) {
10571060
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_OUT_BLIND_VALUE_PROOF));
10581061
s << m_blind_value_proof;
10591062
}
10601063

1061-
// BLind asset proof
1064+
// Blind asset proof
10621065
if (!m_blind_asset_proof.empty()) {
10631066
SerializeToVector(s, CompactSizeWriter(PSBT_OUT_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_OUT_BLIND_ASSET_PROOF));
10641067
s << m_blind_asset_proof;
@@ -1423,7 +1426,7 @@ struct PartiallySignedTransaction
14231426
// Scalar offsets
14241427
for (const uint256& scalar : m_scalar_offsets) {
14251428
SerializeToVector(s, CompactSizeWriter(PSBT_GLOBAL_PROPRIETARY), PSBT_ELEMENTS_ID, CompactSizeWriter(PSBT_ELEMENTS_GLOBAL_SCALAR), scalar);
1426-
SerializeToVector(s, std::vector<unsigned char>());
1429+
s << PSBT_SEPARATOR; /* Zero length data value */
14271430
}
14281431
}
14291432

@@ -1659,6 +1662,9 @@ struct PartiallySignedTransaction
16591662
m_scalar_offsets.insert(scalar);
16601663
break;
16611664
}
1665+
default:
1666+
known = false;
1667+
break;
16621668
}
16631669
}
16641670

src/rpc/rawtransaction.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,6 +2237,45 @@ static RPCHelpMan utxoupdatepsbt()
22372237
};
22382238
}
22392239

2240+
static RPCHelpMan parsepsbt()
2241+
{
2242+
return RPCHelpMan{"parsepsbt",
2243+
"\nparse and print a PSBT.\n",
2244+
{
2245+
{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"}
2246+
},
2247+
RPCResult {
2248+
RPCResult::Type::OBJ, "", "",
2249+
{
2250+
{RPCResult::Type::STR, "psbt", "The base64-encoded partially signed transaction"},
2251+
{RPCResult::Type::BOOL, "canonical", "Whether the input PSBT matches the output PSBT"}
2252+
}
2253+
},
2254+
RPCExamples {
2255+
HelpExampleCli("parsepsbt", "\"psbt\"")
2256+
},
2257+
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
2258+
{
2259+
RPCTypeCheck(request.params, {UniValue::VSTR}, true);
2260+
2261+
// Unserialize the PSBT
2262+
PartiallySignedTransaction psbtx;
2263+
std::string error;
2264+
if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
2265+
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("PSBT decode failed %s", error));
2266+
}
2267+
2268+
// Serialize the PSBT
2269+
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
2270+
ssTx << psbtx;
2271+
const std::string encoded = EncodeBase64(ssTx);
2272+
UniValue result(UniValue::VOBJ);
2273+
result.pushKV("psbt", encoded);
2274+
result.pushKV("canonical", encoded == request.params[0].get_str());
2275+
return result;
2276+
},
2277+
};
2278+
}
22402279
#if 0
22412280
static RPCHelpMan joinpsbts()
22422281
{
@@ -3207,6 +3246,7 @@ static const CRPCCommand commands[] =
32073246
{ "rawtransactions", &createpsbt, },
32083247
{ "rawtransactions", &converttopsbt, },
32093248
{ "rawtransactions", &utxoupdatepsbt, },
3249+
{ "rawtransactions", &parsepsbt, },
32103250
#if 0
32113251
{ "rawtransactions", &joinpsbts, },
32123252
#endif

src/test/fuzz/rpc.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
179179
"getnewblockhex",
180180
"getpakinfo",
181181
"getsidechaininfo",
182+
"parsepsbt",
182183
"rawblindrawtransaction",
183184
"rawissueasset",
184185
"rawreissueasset",

src/wallet/rpcdump.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,7 +2112,8 @@ RPCHelpMan importissuanceblindingkey()
21122112
RPCHelpMan dumpblindingkey()
21132113
{
21142114
return RPCHelpMan{"dumpblindingkey",
2115-
"\nDumps the private blinding key for a CT address in hex.",
2115+
"\nDumps the private blinding key for a CT address in hex."
2116+
"\nNote: If the address is not a CT address, looks for blinding key corresponding to this non-CT address.",
21162117
{
21172118
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The CT address"},
21182119
},
@@ -2134,17 +2135,15 @@ RPCHelpMan dumpblindingkey()
21342135
if (!IsValidDestination(dest)) {
21352136
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
21362137
}
2137-
if (!IsBlindDestination(dest)) {
2138-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Not a CT address");
2139-
}
21402138
CScript script = GetScriptForDestination(dest);
21412139
CKey key;
21422140
key = pwallet->GetBlindingKey(&script);
21432141
if (key.IsValid()) {
21442142
CPubKey pubkey(key.GetPubKey());
2145-
if (pubkey == GetDestinationBlindingKey(dest)) {
2146-
return HexStr(Span<const unsigned char>(key.begin(), key.size()));
2143+
if (IsBlindDestination(dest) && pubkey != GetDestinationBlindingKey(dest)) {
2144+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "CT address blinding key does not match the blinding key in wallet");
21472145
}
2146+
return HexStr(Span<const unsigned char>(key.begin(), key.size()));
21482147
}
21492148

21502149
throw JSONRPCError(RPC_WALLET_ERROR, "Blinding key for address is unknown");

test/functional/feature_confidential_transactions.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,11 @@ def run_test(self):
272272

273273
# Import the blinding key
274274
blindingkey = self.nodes[2].dumpblindingkey(address2)
275+
276+
# Check that importing keys from non-CT address works as intended
277+
blindingkey2 = self.nodes[2].dumpblindingkey(unconfidential_address2)
278+
assert_equal(blindingkey, blindingkey2)
279+
275280
self.nodes[1].importblindingkey(address2, blindingkey)
276281
# Check the auditor's gettransaction and listreceivedbyaddress
277282
# Needs rescan to update wallet txns

0 commit comments

Comments
 (0)