Skip to content

Commit 6132c01

Browse files
authored
Merge pull request #1121 from jgriffiths/pset_updates
PSET: Various fixes
2 parents 1efefc3 + 3be6e80 commit 6132c01

File tree

5 files changed

+87
-33
lines changed

5 files changed

+87
-33
lines changed

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",

0 commit comments

Comments
 (0)