From ae775b5b311982a3d932a9e34ddc94ce597dcaaf Mon Sep 17 00:00:00 2001
From: Jeff Garzik <jgarzik@bitpay.com>
Date: Mon, 23 Jun 2014 23:10:24 -0400
Subject: [PATCH] Consolidate CTransaction hex encode/decode into core_io.h,
 core_{read,write}.cpp

---
 src/Makefile.am           |  3 +++
 src/core_io.h             | 14 ++++++++++++++
 src/core_read.cpp         | 25 +++++++++++++++++++++++++
 src/core_write.cpp        | 15 +++++++++++++++
 src/rpcmining.cpp         |  5 ++---
 src/rpcrawtransaction.cpp | 39 ++++++++++++---------------------------
 src/rpcwallet.cpp         |  5 ++---
 7 files changed, 73 insertions(+), 33 deletions(-)
 create mode 100644 src/core_io.h
 create mode 100644 src/core_read.cpp
 create mode 100644 src/core_write.cpp

diff --git a/src/Makefile.am b/src/Makefile.am
index ff2374759..4e5914642 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -75,6 +75,7 @@ BITCOIN_CORE_H = \
   coins.h \
   compat.h \
   core.h \
+  core_io.h \
   crypter.h \
   db.h \
   hash.h \
@@ -185,6 +186,8 @@ libbitcoin_common_a_SOURCES = \
   chainparams.cpp \
   coins.cpp \
   core.cpp \
+  core_read.cpp \
+  core_write.cpp \
   hash.cpp \
   key.cpp \
   keystore.cpp \
diff --git a/src/core_io.h b/src/core_io.h
new file mode 100644
index 000000000..257dac362
--- /dev/null
+++ b/src/core_io.h
@@ -0,0 +1,14 @@
+#ifndef __BITCOIN_CORE_IO_H__
+#define __BITCOIN_CORE_IO_H__
+
+#include <string>
+
+class CTransaction;
+
+// core_read.cpp
+extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
+
+// core_write.cpp
+extern std::string EncodeHexTx(const CTransaction& tx);
+
+#endif // __BITCOIN_CORE_IO_H__
diff --git a/src/core_read.cpp b/src/core_read.cpp
new file mode 100644
index 000000000..937dcd9c1
--- /dev/null
+++ b/src/core_read.cpp
@@ -0,0 +1,25 @@
+
+#include <vector>
+#include "core_io.h"
+#include "core.h"
+#include "serialize.h"
+
+using namespace std;
+
+bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx)
+{
+    if (!IsHex(strHexTx))
+        return false;
+
+    vector<unsigned char> txData(ParseHex(strHexTx));
+    CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
+    try {
+        ssData >> tx;
+    }
+    catch (std::exception &e) {
+        return false;
+    }
+
+    return true;
+}
+
diff --git a/src/core_write.cpp b/src/core_write.cpp
new file mode 100644
index 000000000..960974df8
--- /dev/null
+++ b/src/core_write.cpp
@@ -0,0 +1,15 @@
+
+#include "core_io.h"
+#include "core.h"
+#include "serialize.h"
+#include "util.h"
+
+using namespace std;
+
+string EncodeHexTx(const CTransaction& tx)
+{
+    CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
+    ssTx << tx;
+    return HexStr(ssTx.begin(), ssTx.end());
+}
+
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index cbb4ab2f8..edab427cb 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -10,6 +10,7 @@
 #include "main.h"
 #include "miner.h"
 #include "pow.h"
+#include "core_io.h"
 #ifdef ENABLE_WALLET
 #include "db.h"
 #include "wallet.h"
@@ -472,9 +473,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
 
         Object entry;
 
-        CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
-        ssTx << tx;
-        entry.push_back(Pair("data", HexStr(ssTx.begin(), ssTx.end())));
+        entry.push_back(Pair("data", EncodeHexTx(tx)));
 
         entry.push_back(Pair("hash", txHash.GetHex()));
 
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 1efe38e83..a7aeb8f00 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -5,6 +5,7 @@
 
 #include "base58.h"
 #include "core.h"
+#include "core_io.h"
 #include "init.h"
 #include "keystore.h"
 #include "main.h"
@@ -182,9 +183,7 @@ Value getrawtransaction(const Array& params, bool fHelp)
     if (!GetTransaction(hash, tx, hashBlock, true))
         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
 
-    CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
-    ssTx << tx;
-    string strHex = HexStr(ssTx.begin(), ssTx.end());
+    string strHex = EncodeHexTx(tx);
 
     if (!fVerbose)
         return strHex;
@@ -388,9 +387,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
         rawTx.vout.push_back(out);
     }
 
-    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
-    ss << rawTx;
-    return HexStr(ss.begin(), ss.end());
+    return EncodeHexTx(rawTx);
 }
 
 Value decoderawtransaction(const Array& params, bool fHelp)
@@ -444,15 +441,12 @@ Value decoderawtransaction(const Array& params, bool fHelp)
             + HelpExampleRpc("decoderawtransaction", "\"hexstring\"")
         );
 
-    vector<unsigned char> txData(ParseHexV(params[0], "argument"));
-    CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
+    RPCTypeCheck(params, list_of(str_type));
+
     CTransaction tx;
-    try {
-        ssData >> tx;
-    }
-    catch (std::exception &e) {
+
+    if (!DecodeHexTx(tx, params[0].get_str()))
         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
-    }
 
     Object result;
     TxToJSON(tx, 0, result);
@@ -723,9 +717,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
     }
 
     Object result;
-    CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
-    ssTx << mergedTx;
-    result.push_back(Pair("hex", HexStr(ssTx.begin(), ssTx.end())));
+    result.push_back(Pair("hex", EncodeHexTx(mergedTx)));
     result.push_back(Pair("complete", fComplete));
 
     return result;
@@ -754,25 +746,18 @@ Value sendrawtransaction(const Array& params, bool fHelp)
             + HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
         );
 
+    RPCTypeCheck(params, list_of(str_type)(bool_type));
 
     // parse hex string from parameter
-    vector<unsigned char> txData(ParseHexV(params[0], "parameter"));
-    CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
     CTransaction tx;
+    if (!DecodeHexTx(tx, params[0].get_str()))
+        throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+    uint256 hashTx = tx.GetHash();
 
     bool fOverrideFees = false;
     if (params.size() > 1)
         fOverrideFees = params[1].get_bool();
 
-    // deserialize binary data stream
-    try {
-        ssData >> tx;
-    }
-    catch (std::exception &e) {
-        throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
-    }
-    const uint256 &hashTx = tx.GetHash();
-
     CCoinsViewCache &view = *pcoinsTip;
     CCoins existingCoins;
     bool fHaveMempool = mempool.exists(hashTx);
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index 5b83fe900..667ca33ce 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -4,6 +4,7 @@
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include "base58.h"
+#include "core_io.h"
 #include "rpcserver.h"
 #include "init.h"
 #include "net.h"
@@ -1550,9 +1551,7 @@ Value gettransaction(const Array& params, bool fHelp)
     ListTransactions(wtx, "*", 0, false, details, filter);
     entry.push_back(Pair("details", details));
 
-    CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
-    ssTx << static_cast<CTransaction>(wtx);
-    string strHex = HexStr(ssTx.begin(), ssTx.end());
+    string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
     entry.push_back(Pair("hex", strHex));
 
     return entry;