From d5fde7d37584b97dcbd8a70e020cd837b0f256c3 Mon Sep 17 00:00:00 2001 From: Tom Briar Date: Tue, 11 Jul 2023 16:55:45 -0400 Subject: [PATCH] rpc: Added RPC endpoints for Compressed Transactions --- src/rpc/rawtransaction.cpp | 102 +++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index b1e6d677f87207..9a4ff2075d36f7 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -494,6 +496,104 @@ static RPCHelpMan decoderawtransaction() }; } +static RPCHelpMan compressrawtransaction() +{ + return RPCHelpMan{"compressrawtransaction", + "Return a JSON object representing the compressed, serialized, hex-encoded transaction.", + { + {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction hex string"}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "result", "The compressed transaction hex string"}, + {RPCResult::Type::ARR, "warnings", "", + { + {RPCResult::Type::STR_HEX, "warning", "Warnings given for each input"} + }} + } + }, + RPCExamples{ + HelpExampleCli("compressrawtransaction", "\"hexstring\"") + + HelpExampleRpc("compressrawtransaction", "\"hexstring\"") + }, + [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue +{ + const NodeContext& node = EnsureAnyNodeContext(request.context); + + UniValue r(UniValue::VOBJ); + UniValue warnings(UniValue::VARR); + CMutableTransaction mtx; + if (DecodeHexTx(mtx, request.params[0].get_str(), true, true)) { + CTransaction tx = CTransaction(mtx); + LOCK(cs_main); + std::vector warning_strings; + std::tuple> cinputstup = EnsureChainman(node).ActiveChainstate().CompressOutPoints(tx, warning_strings); + CCompressedTransaction ctx = CCompressedTransaction(CTransaction(mtx), std::get<0>(cinputstup), std::get<1>(cinputstup)); + for (const auto& warning : warning_strings) { + warnings.push_back(warning); + } + for (size_t index = 0; index < ctx.vin().size(); index++) { + if (ctx.vin()[index].warning() != "") warnings.push_back(strprintf("UTXO(%u): %s", index, ctx.vin()[index].warning())); + } + + DataStream stream; + ctx.Serialize(stream); + std::vector hex(stream.size()); + stream.read(MakeWritableByteSpan(hex)); + + r.pushKV("result", HexStr(hex)); + r.pushKV("warnings", warnings); + return r; + } + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); +}, + }; +} + +static RPCHelpMan decompressrawtransaction() +{ + return RPCHelpMan{"decompressrawtransaction", + "Return a JSON object representing the decompressed, serialized, hex-encoded transaction.", + { + {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The compressed transaction hex string"}, + }, + RPCResult{ + RPCResult::Type::STR_HEX, "result", "The decompressed transaction hex string" + }, + RPCExamples{ + HelpExampleCli("decompressrawtransaction", "\"hexstring\"") + + HelpExampleRpc("decompressrawtransaction", "\"hexstring\"") + }, + [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue +{ + const NodeContext& node = EnsureAnyNodeContext(request.context); + UniValue r(UniValue::VOBJ); + try { + DataStream ssData(ParseHex(request.params[0].get_str())); + CCompressedTransaction tx = CCompressedTransaction(deserialize, ssData); + LOCK(cs_main); + + std::vector prevouts = EnsureChainman(node).ActiveChainstate().UncompressOutPoints(tx); + std::vector coins = FindCoins(node, prevouts); + std::vector outs; + outs.reserve(coins.size()); + for (auto& coin : coins) { + outs.push_back(coin.out); + } + +// std::tuple, std::vector> Index = std::make_tuple(prevouts, outs); +// if (std::get<0>(Index).size() != std::get<1>(Index).size() || std::get<1>(Index).size() != tx.vin().size()) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Compressed TX decode failed"); +// return EncodeHexTx(CTransaction(CMutableTransaction(tx, std::get<0>(Index), std::get<1>(Index)))); + return "0x03"; + } catch (const std::exception& exc) { + // Fall through. + } + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Compressed TX decode failed"); +}, + }; +} + static RPCHelpMan decodescript() { return RPCHelpMan{ @@ -2007,6 +2107,8 @@ void RegisterRawTransactionRPCCommands(CRPCTable& t) {"rawtransactions", &getrawtransaction}, {"rawtransactions", &createrawtransaction}, {"rawtransactions", &decoderawtransaction}, + {"rawtransactions", &compressrawtransaction}, + {"rawtransactions", &decompressrawtransaction}, {"rawtransactions", &decodescript}, {"rawtransactions", &combinerawtransaction}, {"rawtransactions", &signrawtransactionwithkey},