From fa2c2641bc91ded9ca8d89de93252c4d139389c2 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Wed, 8 Aug 2018 12:19:00 -0400 Subject: [PATCH] add RPC to deblind transactionwith blinding keys in wallet --- qa/rpc-tests/confidential_transactions.py | 12 ++++++- src/wallet/rpcwallet.cpp | 41 +++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/confidential_transactions.py b/qa/rpc-tests/confidential_transactions.py index 4ee2dd30a3..a14bb72ab2 100755 --- a/qa/rpc-tests/confidential_transactions.py +++ b/qa/rpc-tests/confidential_transactions.py @@ -115,7 +115,17 @@ class CTTest (BitcoinTestFramework): self.nodes[1].importblindingkey(address, blindingkey) # Check the auditor's gettransaction and listreceivedbyaddress # Needs rescan to update wallet txns - assert_equal(self.nodes[1].gettransaction(confidential_tx_id, True)['amount']["bitcoin"], value1) + conf_tx = self.nodes[1].gettransaction(confidential_tx_id, True) + assert_equal(conf_tx['amount']["bitcoin"], value1) + + # Make sure wallet can now deblind part of transaction + deblinded_tx = self.nodes[1].unblindrawtransaction(conf_tx['hex'])['hex'] + for output in self.nodes[1].decoderawtransaction(deblinded_tx)["vout"]: + if "value" in output and output["scriptPubKey"]["type"] != "fee": + assert_equal(output["scriptPubKey"]["addresses"][0], self.nodes[1].validateaddress(address)['unconfidential']) + found_unblinded = True + assert(found_unblinded) + assert_equal(self.nodes[1].gettransaction(raw_tx_id, True)['amount']["bitcoin"], value3) list_unspent = self.nodes[1].listunspent(1, 9999999, [], True, "bitcoin") assert_equal(list_unspent[0]['amount']+list_unspent[1]['amount'], value1+value3) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index c11c19e6e2..4447af2b9e 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2865,6 +2865,46 @@ UniValue listunspent(const JSONRPCRequest& request) return results; } +extern void FillBlinds(CMutableTransaction& tx, bool fUseWallet, std::vector& output_value_blinds, std::vector& output_asset_blinds, std::vector& output_pubkeys, std::vector& asset_keys, std::vector& token_keys); + +UniValue unblindrawtransaction(const JSONRPCRequest& request) +{ + if (!EnsureWalletIsAvailable(request.fHelp)) + return NullUniValue; + + if (request.fHelp || request.params.size() != 1) + throw runtime_error( + "unblindrawtransaction \"hex\"\n" + "\nRecovers unblinded transaction outputs from blinded outputs and issuance inputs when possible using wallet's known blinding keys, and strips related witness data.\n" + "\nArguments:\n" + "1. \"hex\" (string, required) The hex string of the raw transaction\n" + "\nResult:\n" + "{\n" + " \"hex\": \"value\", (string) The resulting unblinded raw transaction (hex-encoded string)\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("unblindrawtransaction", "\"blindedtransactionhex\"") + ); + + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)); + + CMutableTransaction tx; + if (!DecodeHexTx(tx, request.params[0].get_str())) + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); + + std::vector output_value_blinds; + std::vector output_asset_blinds; + std::vector output_pubkeys; + std::vector asset_keys; + std::vector token_keys; + FillBlinds(tx, true, output_value_blinds, output_asset_blinds, output_pubkeys, asset_keys, token_keys); + + UniValue result(UniValue::VOBJ); + result.push_back(Pair("hex", EncodeHexTx(tx))); + + return result; +} + UniValue fundrawtransaction(const JSONRPCRequest& request) { if (!EnsureWalletIsAvailable(request.fHelp)) @@ -4132,6 +4172,7 @@ static const CRPCCommand commands[] = { "wallet", "destroyamount", &destroyamount, false, {"asset", "amount", "comment"} }, { "wallet", "settxfee", &settxfee, true, {"amount"} }, { "wallet", "signmessage", &signmessage, true, {"address","message"} }, + { "wallet", "unblindrawtransaction", &unblindrawtransaction, true, {"hex"} }, { "wallet", "walletlock", &walletlock, true, {} }, { "wallet", "walletpassphrasechange", &walletpassphrasechange, true, {"oldpassphrase","newpassphrase"} }, { "wallet", "walletpassphrase", &walletpassphrase, true, {"passphrase","timeout"} },