diff options
author | Gregory Sanders <gsanders87@gmail.com> | 2016-11-20 09:54:51 -0500 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2016-12-05 08:11:03 +0100 |
commit | 21ccb9f2530af996fc0a58df418837a08b75781f (patch) | |
tree | cd4e268c67c09a0462b3a149871fcefa4d44886a | |
parent | a710a4304033eea581e463a5fb0502bdb8991aa1 (diff) |
Add option to return non-segwit serialization via rpc
Github-Pull: #9194
Rebased-From: 835c75acaac004c3315395dcd7d1f193dfb9e5da
-rwxr-xr-x | qa/rpc-tests/segwit.py | 20 | ||||
-rw-r--r-- | src/core_io.h | 2 | ||||
-rw-r--r-- | src/core_write.cpp | 4 | ||||
-rw-r--r-- | src/init.cpp | 4 | ||||
-rw-r--r-- | src/rpc/blockchain.cpp | 2 | ||||
-rw-r--r-- | src/rpc/rawtransaction.cpp | 2 | ||||
-rw-r--r-- | src/rpc/server.cpp | 8 | ||||
-rw-r--r-- | src/rpc/server.h | 5 | ||||
-rw-r--r-- | src/wallet/rpcwallet.cpp | 2 |
9 files changed, 40 insertions, 9 deletions
diff --git a/qa/rpc-tests/segwit.py b/qa/rpc-tests/segwit.py index 493ad2e67c..4b4fdf8b11 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 @@ -83,8 +84,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) @@ -210,7 +211,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 b559d44bf5..44a732b697 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -25,7 +25,7 @@ extern std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::strin // core_write.cpp extern std::string FormatScript(const CScript& script); -extern std::string EncodeHexTx(const CTransaction& tx); +extern std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags = 0); extern void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); extern 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 bbdab14ee0..8e40c4388d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -364,6 +364,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)); @@ -982,6 +983,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) 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/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index a38b3fc607..b4d53a9f3d 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -607,7 +607,7 @@ UniValue getblock(const UniValue& params, bool fHelp) 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 b2bbb8b3ed..2719829e65 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -209,7 +209,7 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) 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 102c776314..deeabcb8d7 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -495,4 +495,12 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6 deadlineTimers.insert(std::make_pair(name, boost::shared_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 b5ccc153d0..1ed8f2466d 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 @@ -195,4 +197,7 @@ void InterruptRPC(); void StopRPC(); std::string JSONRPCExecBatch(const UniValue& vReq); +// 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 fdb7a53d3b..17bda050c3 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1780,7 +1780,7 @@ UniValue gettransaction(const UniValue& params, bool fHelp) 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; |