Skip to content

Commit

Permalink
Merge pull request #1137 from gwillen/release-backports-22
Browse files Browse the repository at this point in the history
[backport] Backport #1121 and #1131 to elements-22.x for rc3
  • Loading branch information
psgreco authored Aug 9, 2022
2 parents 22fc036 + a17887b commit fdeaa49
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 40 deletions.
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

0 comments on commit fdeaa49

Please sign in to comment.