From 149a893d3b2e24df38c0651d40039646fb6c4db0 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 | 101 +++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index b1e6d677f87207..035067ac2c2c73 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,103 @@ 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)))); +// } catch (const std::exception& exc) { +// // Fall through. +// } +// throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Compressed TX decode failed"); +// }, +// }; +// } + static RPCHelpMan decodescript() { return RPCHelpMan{ @@ -2007,6 +2106,8 @@ void RegisterRawTransactionRPCCommands(CRPCTable& t) {"rawtransactions", &getrawtransaction}, {"rawtransactions", &createrawtransaction}, {"rawtransactions", &decoderawtransaction}, + {"rawtransactions", &compressrawtransaction}, + //{"rawtransactions", &decompressrawtransaction}, {"rawtransactions", &decodescript}, {"rawtransactions", &combinerawtransaction}, {"rawtransactions", &signrawtransactionwithkey},