aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2016-12-06 08:21:14 +0100
committerWladimir J. van der Laan <laanwj@gmail.com>2016-12-06 08:21:57 +0100
commited8d693c71b01caa310922f883b3915c09bb6a35 (patch)
tree62eadd8c5279b73c053b0704d5eae5ce7f2436f4
parent7d5d44969b4ab46a5146a46b4ed1ed7704d71c63 (diff)
parent412bab22b23036962509d2655b68cccd726b6ba4 (diff)
Merge #9194: Add option to return non-segwit serialization via rpc
412bab2 Adapt ZMQ/rest serialization to take rpcserialversion arg (instagibbs) bc7ff8d Add option to return non-segwit serialization via rpc (Gregory Sanders)
-rwxr-xr-xqa/rpc-tests/segwit.py20
-rw-r--r--src/core_io.h2
-rw-r--r--src/core_write.cpp4
-rw-r--r--src/init.cpp4
-rw-r--r--src/rest.cpp4
-rw-r--r--src/rpc/blockchain.cpp2
-rw-r--r--src/rpc/rawtransaction.cpp2
-rw-r--r--src/rpc/server.cpp8
-rw-r--r--src/rpc/server.h5
-rw-r--r--src/wallet/rpcwallet.cpp2
-rw-r--r--src/zmq/zmqpublishnotifier.cpp5
11 files changed, 45 insertions, 13 deletions
diff --git a/qa/rpc-tests/segwit.py b/qa/rpc-tests/segwit.py
index 41a1b3b20f..7aa72cca34 100755
--- a/qa/rpc-tests/segwit.py
+++ b/qa/rpc-tests/segwit.py
@@ -13,6 +13,7 @@ from test_framework.mininode import sha256, ripemd160, CTransaction, CTxIn, COut
from test_framework.address import script_to_p2sh, key_to_p2pkh
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
from io import BytesIO
+from test_framework.mininode import FromHex
NODE_0 = 0
NODE_1 = 1
@@ -84,8 +85,8 @@ class SegWitTest(BitcoinTestFramework):
def setup_network(self):
self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, ["-logtimemicros", "-debug", "-walletprematurewitness"]))
- self.nodes.append(start_node(1, self.options.tmpdir, ["-logtimemicros", "-debug", "-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness"]))
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-logtimemicros", "-debug", "-walletprematurewitness", "-rpcserialversion=0"]))
+ self.nodes.append(start_node(1, self.options.tmpdir, ["-logtimemicros", "-debug", "-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-rpcserialversion=2"]))
self.nodes.append(start_node(2, self.options.tmpdir, ["-logtimemicros", "-debug", "-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness"]))
connect_nodes(self.nodes[1], 0)
connect_nodes(self.nodes[2], 1)
@@ -211,7 +212,20 @@ class SegWitTest(BitcoinTestFramework):
block = self.nodes[2].generate(1) #block 432 (first block with new rules; 432 = 144 * 3)
sync_blocks(self.nodes)
assert_equal(len(self.nodes[2].getrawmempool()), 0)
- assert_equal(len(self.nodes[2].getblock(block[0])["tx"]), 5)
+ segwit_tx_list = self.nodes[2].getblock(block[0])["tx"]
+ assert_equal(len(segwit_tx_list), 5)
+
+ print("Verify block and transaction serialization rpcs return differing serializations depending on rpc serialization flag")
+ # Note: node1 has version 2, which is simply >0 and will catch future upgrades in tests
+ assert(self.nodes[2].getblock(block[0], False) != self.nodes[0].getblock(block[0], False))
+ assert(self.nodes[1].getblock(block[0], False) == self.nodes[2].getblock(block[0], False))
+ for i in range(len(segwit_tx_list)):
+ tx = FromHex(CTransaction(), self.nodes[2].gettransaction(segwit_tx_list[i])["hex"])
+ assert(self.nodes[2].getrawtransaction(segwit_tx_list[i]) != self.nodes[0].getrawtransaction(segwit_tx_list[i]))
+ assert(self.nodes[1].getrawtransaction(segwit_tx_list[i], 0) == self.nodes[2].getrawtransaction(segwit_tx_list[i]))
+ assert(self.nodes[0].getrawtransaction(segwit_tx_list[i]) != self.nodes[2].gettransaction(segwit_tx_list[i])["hex"])
+ assert(self.nodes[1].getrawtransaction(segwit_tx_list[i]) == self.nodes[2].gettransaction(segwit_tx_list[i])["hex"])
+ assert(self.nodes[0].getrawtransaction(segwit_tx_list[i]) == bytes_to_hex_str(tx.serialize_without_witness()))
print("Verify witness txs without witness data are invalid after the fork")
self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][2], False)
diff --git a/src/core_io.h b/src/core_io.h
index 88425ed4fb..7642bc6d6e 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -26,7 +26,7 @@ std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strN
// core_write.cpp
std::string FormatScript(const CScript& script);
-std::string EncodeHexTx(const CTransaction& tx);
+std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags = 0);
void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry);
diff --git a/src/core_write.cpp b/src/core_write.cpp
index ea01ddc10d..9f859ba9e1 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -116,9 +116,9 @@ string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode)
return str;
}
-string EncodeHexTx(const CTransaction& tx)
+string EncodeHexTx(const CTransaction& tx, const int serialFlags)
{
- CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | serialFlags);
ssTx << tx;
return HexStr(ssTx.begin(), ssTx.end());
}
diff --git a/src/init.cpp b/src/init.cpp
index ba5fe4152a..71971a7642 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -380,6 +380,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-port=<port>", strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), Params(CBaseChainParams::MAIN).GetDefaultPort(), Params(CBaseChainParams::TESTNET).GetDefaultPort()));
strUsage += HelpMessageOpt("-proxy=<ip:port>", _("Connect through SOCKS5 proxy"));
strUsage += HelpMessageOpt("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), DEFAULT_PROXYRANDOMIZE));
+ 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));
strUsage += HelpMessageOpt("-seednode=<ip>", _("Connect to a node to retrieve peer addresses, and disconnect"));
strUsage += HelpMessageOpt("-timeout=<n>", strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT));
strUsage += HelpMessageOpt("-torcontrol=<ip>:<port>", strprintf(_("Tor control port to use if onion listening enabled (default: %s)"), DEFAULT_TOR_CONTROL));
@@ -984,6 +985,9 @@ bool AppInitParameterInteraction()
if (GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS))
nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM);
+ if (GetArg("-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) < 0)
+ return InitError("rpcserialversion must be non-negative.");
+
nMaxTipAge = GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE);
fEnableReplacement = GetBoolArg("-mempoolreplacement", DEFAULT_ENABLE_REPLACEMENT);
diff --git a/src/rest.cpp b/src/rest.cpp
index 6379061f8f..6b6b7401f6 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -228,7 +228,7 @@ static bool rest_block(HTTPRequest* req,
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
}
- CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
+ CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
ssBlock << block;
switch (rf) {
@@ -368,7 +368,7 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true))
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
- CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
ssTx << tx;
switch (rf) {
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index e6d80f06a3..1139c2aa5c 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -751,7 +751,7 @@ UniValue getblock(const JSONRPCRequest& request)
if (!fVerbose)
{
- CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
+ CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
ssBlock << block;
std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
return strHex;
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 48769a5335..1229a00c5f 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -223,7 +223,7 @@ UniValue getrawtransaction(const JSONRPCRequest& request)
if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
- string strHex = EncodeHexTx(*tx);
+ string strHex = EncodeHexTx(*tx, RPCSerializationFlags());
if (!fVerbose)
return strHex;
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index 164e0f00e2..2122819398 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -497,4 +497,12 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6
deadlineTimers.emplace(name, std::unique_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000)));
}
+int RPCSerializationFlags()
+{
+ int flag = 0;
+ if (GetArg("-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) == 0)
+ flag |= SERIALIZE_TRANSACTION_NO_WITNESS;
+ return flag;
+}
+
CRPCTable tableRPC;
diff --git a/src/rpc/server.h b/src/rpc/server.h
index c59886222c..4fac68a51f 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -19,6 +19,8 @@
#include <univalue.h>
+static const unsigned int DEFAULT_RPC_SERIALIZE_VERSION = 1;
+
class CRPCCommand;
namespace RPCServer
@@ -198,4 +200,7 @@ void StopRPC();
std::string JSONRPCExecBatch(const UniValue& vReq);
void RPCNotifyBlockChange(bool ibd, const CBlockIndex *);
+// Retrieves any serialization flags requested in command line argument
+int RPCSerializationFlags();
+
#endif // BITCOIN_RPCSERVER_H
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index d4e21b542d..5a4fcc743c 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -1792,7 +1792,7 @@ UniValue gettransaction(const JSONRPCRequest& request)
ListTransactions(wtx, "*", 0, false, details, filter);
entry.push_back(Pair("details", details));
- string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
+ string strHex = EncodeHexTx(static_cast<CTransaction>(wtx), RPCSerializationFlags());
entry.push_back(Pair("hex", strHex));
return entry;
diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp
index 99d42ab526..a11256dfd5 100644
--- a/src/zmq/zmqpublishnotifier.cpp
+++ b/src/zmq/zmqpublishnotifier.cpp
@@ -7,6 +7,7 @@
#include "zmqpublishnotifier.h"
#include "validation.h"
#include "util.h"
+#include "rpc/server.h"
static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers;
@@ -166,7 +167,7 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
LogPrint("zmq", "zmq: Publish rawblock %s\n", pindex->GetBlockHash().GetHex());
const Consensus::Params& consensusParams = Params().GetConsensus();
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
{
LOCK(cs_main);
CBlock block;
@@ -186,7 +187,7 @@ bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &tr
{
uint256 hash = transaction.GetHash();
LogPrint("zmq", "zmq: Publish rawtx %s\n", hash.GetHex());
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
ss << transaction;
return SendMessage(MSG_RAWTX, &(*ss.begin()), ss.size());
}