Skip to content

Commit 21ccb9f

Browse files
instagibbslaanwj
authored andcommitted
Add option to return non-segwit serialization via rpc
Github-Pull: bitcoin#9194 Rebased-From: 835c75acaac004c3315395dcd7d1f193dfb9e5da
1 parent a710a43 commit 21ccb9f

File tree

9 files changed

+40
-9
lines changed

9 files changed

+40
-9
lines changed

qa/rpc-tests/segwit.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from test_framework.address import script_to_p2sh, key_to_p2pkh
1414
from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG
1515
from io import BytesIO
16+
from test_framework.mininode import FromHex
1617

1718
NODE_0 = 0
1819
NODE_1 = 1
@@ -83,8 +84,8 @@ def setup_chain(self):
8384

8485
def setup_network(self):
8586
self.nodes = []
86-
self.nodes.append(start_node(0, self.options.tmpdir, ["-logtimemicros", "-debug", "-walletprematurewitness"]))
87-
self.nodes.append(start_node(1, self.options.tmpdir, ["-logtimemicros", "-debug", "-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness"]))
87+
self.nodes.append(start_node(0, self.options.tmpdir, ["-logtimemicros", "-debug", "-walletprematurewitness", "-rpcserialversion=0"]))
88+
self.nodes.append(start_node(1, self.options.tmpdir, ["-logtimemicros", "-debug", "-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-rpcserialversion=2"]))
8889
self.nodes.append(start_node(2, self.options.tmpdir, ["-logtimemicros", "-debug", "-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness"]))
8990
connect_nodes(self.nodes[1], 0)
9091
connect_nodes(self.nodes[2], 1)
@@ -210,7 +211,20 @@ def run_test(self):
210211
block = self.nodes[2].generate(1) #block 432 (first block with new rules; 432 = 144 * 3)
211212
sync_blocks(self.nodes)
212213
assert_equal(len(self.nodes[2].getrawmempool()), 0)
213-
assert_equal(len(self.nodes[2].getblock(block[0])["tx"]), 5)
214+
segwit_tx_list = self.nodes[2].getblock(block[0])["tx"]
215+
assert_equal(len(segwit_tx_list), 5)
216+
217+
print("Verify block and transaction serialization rpcs return differing serializations depending on rpc serialization flag")
218+
# Note: node1 has version 2, which is simply >0 and will catch future upgrades in tests
219+
assert(self.nodes[2].getblock(block[0], False) != self.nodes[0].getblock(block[0], False))
220+
assert(self.nodes[1].getblock(block[0], False) == self.nodes[2].getblock(block[0], False))
221+
for i in range(len(segwit_tx_list)):
222+
tx = FromHex(CTransaction(), self.nodes[2].gettransaction(segwit_tx_list[i])["hex"])
223+
assert(self.nodes[2].getrawtransaction(segwit_tx_list[i]) != self.nodes[0].getrawtransaction(segwit_tx_list[i]))
224+
assert(self.nodes[1].getrawtransaction(segwit_tx_list[i], 0) == self.nodes[2].getrawtransaction(segwit_tx_list[i]))
225+
assert(self.nodes[0].getrawtransaction(segwit_tx_list[i]) != self.nodes[2].gettransaction(segwit_tx_list[i])["hex"])
226+
assert(self.nodes[1].getrawtransaction(segwit_tx_list[i]) == self.nodes[2].gettransaction(segwit_tx_list[i])["hex"])
227+
assert(self.nodes[0].getrawtransaction(segwit_tx_list[i]) == bytes_to_hex_str(tx.serialize_without_witness()))
214228

215229
print("Verify witness txs without witness data are invalid after the fork")
216230
self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][2], False)

src/core_io.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ extern std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::strin
2525

2626
// core_write.cpp
2727
extern std::string FormatScript(const CScript& script);
28-
extern std::string EncodeHexTx(const CTransaction& tx);
28+
extern std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags = 0);
2929
extern void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
3030
extern void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry);
3131

src/core_write.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode)
116116
return str;
117117
}
118118

119-
string EncodeHexTx(const CTransaction& tx)
119+
string EncodeHexTx(const CTransaction& tx, const int serialFlags)
120120
{
121-
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
121+
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | serialFlags);
122122
ssTx << tx;
123123
return HexStr(ssTx.begin(), ssTx.end());
124124
}

src/init.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ std::string HelpMessage(HelpMessageMode mode)
364364
strUsage += HelpMessageOpt("-port=<port>", strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), Params(CBaseChainParams::MAIN).GetDefaultPort(), Params(CBaseChainParams::TESTNET).GetDefaultPort()));
365365
strUsage += HelpMessageOpt("-proxy=<ip:port>", _("Connect through SOCKS5 proxy"));
366366
strUsage += HelpMessageOpt("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), DEFAULT_PROXYRANDOMIZE));
367+
strUsage += HelpMessageOpt("-rpcserialversion", strprintf(_("Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(>0) (default: %d)"), DEFAULT_RPC_SERIALIZE_VERSION));
367368
strUsage += HelpMessageOpt("-seednode=<ip>", _("Connect to a node to retrieve peer addresses, and disconnect"));
368369
strUsage += HelpMessageOpt("-timeout=<n>", strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT));
369370
strUsage += HelpMessageOpt("-torcontrol=<ip>:<port>", strprintf(_("Tor control port to use if onion listening enabled (default: %s)"), DEFAULT_TOR_CONTROL));
@@ -982,6 +983,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
982983
if (GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS))
983984
nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM);
984985

986+
if (GetArg("-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) < 0)
987+
return InitError("rpcserialversion must be non-negative.");
988+
985989
nMaxTipAge = GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE);
986990

987991
fEnableReplacement = GetBoolArg("-mempoolreplacement", DEFAULT_ENABLE_REPLACEMENT);

src/rpc/blockchain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ UniValue getblock(const UniValue& params, bool fHelp)
607607

608608
if (!fVerbose)
609609
{
610-
CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
610+
CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
611611
ssBlock << block;
612612
std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
613613
return strHex;

src/rpc/rawtransaction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp)
209209
if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true))
210210
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
211211

212-
string strHex = EncodeHexTx(tx);
212+
string strHex = EncodeHexTx(tx, RPCSerializationFlags());
213213

214214
if (!fVerbose)
215215
return strHex;

src/rpc/server.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,4 +495,12 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6
495495
deadlineTimers.insert(std::make_pair(name, boost::shared_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000))));
496496
}
497497

498+
int RPCSerializationFlags()
499+
{
500+
int flag = 0;
501+
if (GetArg("-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) == 0)
502+
flag |= SERIALIZE_TRANSACTION_NO_WITNESS;
503+
return flag;
504+
}
505+
498506
CRPCTable tableRPC;

src/rpc/server.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
#include <univalue.h>
2121

22+
static const unsigned int DEFAULT_RPC_SERIALIZE_VERSION = 1;
23+
2224
class CRPCCommand;
2325

2426
namespace RPCServer
@@ -195,4 +197,7 @@ void InterruptRPC();
195197
void StopRPC();
196198
std::string JSONRPCExecBatch(const UniValue& vReq);
197199

200+
// Retrieves any serialization flags requested in command line argument
201+
int RPCSerializationFlags();
202+
198203
#endif // BITCOIN_RPCSERVER_H

src/wallet/rpcwallet.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1780,7 +1780,7 @@ UniValue gettransaction(const UniValue& params, bool fHelp)
17801780
ListTransactions(wtx, "*", 0, false, details, filter);
17811781
entry.push_back(Pair("details", details));
17821782

1783-
string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
1783+
string strHex = EncodeHexTx(static_cast<CTransaction>(wtx), RPCSerializationFlags());
17841784
entry.push_back(Pair("hex", strHex));
17851785

17861786
return entry;

0 commit comments

Comments
 (0)