aboutsummaryrefslogtreecommitdiff
path: root/src/core_write.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core_write.cpp')
-rw-r--r--src/core_write.cpp105
1 files changed, 87 insertions, 18 deletions
diff --git a/src/core_write.cpp b/src/core_write.cpp
index c3babec2f..b0993a131 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,23 +10,22 @@
#include "script/standard.h"
#include "serialize.h"
#include "streams.h"
-#include "univalue/univalue.h"
+#include <univalue.h>
#include "util.h"
#include "utilmoneystr.h"
#include "utilstrencodings.h"
+#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>
-using namespace std;
-
-string FormatScript(const CScript& script)
+std::string FormatScript(const CScript& script)
{
- string ret;
+ std::string ret;
CScript::const_iterator it = script.begin();
opcodetype op;
while (it != script.end()) {
CScript::const_iterator it2 = it;
- vector<unsigned char> vch;
+ std::vector<unsigned char> vch;
if (script.GetOp2(it, op, &vch)) {
if (op == OP_0) {
ret += "0 ";
@@ -34,17 +33,17 @@ string FormatScript(const CScript& script)
} else if ((op >= OP_1 && op <= OP_16) || op == OP_1NEGATE) {
ret += strprintf("%i ", op - OP_1NEGATE - 1);
continue;
- } else if (op >= OP_NOP && op <= OP_CHECKMULTISIGVERIFY) {
- string str(GetOpName(op));
- if (str.substr(0, 3) == string("OP_")) {
- ret += str.substr(3, string::npos) + " ";
+ } else if (op >= OP_NOP && op <= OP_NOP10) {
+ std::string str(GetOpName(op));
+ if (str.substr(0, 3) == std::string("OP_")) {
+ ret += str.substr(3, std::string::npos) + " ";
continue;
}
}
if (vch.size() > 0) {
ret += strprintf("0x%x 0x%x ", HexStr(it2, it - vch.size()), HexStr(it - vch.size(), it));
} else {
- ret += strprintf("0x%x", HexStr(it2, it));
+ ret += strprintf("0x%x ", HexStr(it2, it));
}
continue;
}
@@ -54,9 +53,70 @@ string FormatScript(const CScript& script)
return ret.substr(0, ret.size() - 1);
}
-string EncodeHexTx(const CTransaction& tx)
+const std::map<unsigned char, std::string> mapSigHashTypes =
+ boost::assign::map_list_of
+ (static_cast<unsigned char>(SIGHASH_ALL), std::string("ALL"))
+ (static_cast<unsigned char>(SIGHASH_ALL|SIGHASH_ANYONECANPAY), std::string("ALL|ANYONECANPAY"))
+ (static_cast<unsigned char>(SIGHASH_NONE), std::string("NONE"))
+ (static_cast<unsigned char>(SIGHASH_NONE|SIGHASH_ANYONECANPAY), std::string("NONE|ANYONECANPAY"))
+ (static_cast<unsigned char>(SIGHASH_SINGLE), std::string("SINGLE"))
+ (static_cast<unsigned char>(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY), std::string("SINGLE|ANYONECANPAY"))
+ ;
+
+/**
+ * Create the assembly string representation of a CScript object.
+ * @param[in] script CScript object to convert into the asm string representation.
+ * @param[in] fAttemptSighashDecode Whether to attempt to decode sighash types on data within the script that matches the format
+ * of a signature. Only pass true for scripts you believe could contain signatures. For example,
+ * pass false, or omit the this argument (defaults to false), for scriptPubKeys.
+ */
+std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode)
{
- CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
+ std::string str;
+ opcodetype opcode;
+ std::vector<unsigned char> vch;
+ CScript::const_iterator pc = script.begin();
+ while (pc < script.end()) {
+ if (!str.empty()) {
+ str += " ";
+ }
+ if (!script.GetOp(pc, opcode, vch)) {
+ str += "[error]";
+ return str;
+ }
+ if (0 <= opcode && opcode <= OP_PUSHDATA4) {
+ if (vch.size() <= static_cast<std::vector<unsigned char>::size_type>(4)) {
+ str += strprintf("%d", CScriptNum(vch, false).getint());
+ } else {
+ // the IsUnspendable check makes sure not to try to decode OP_RETURN data that may match the format of a signature
+ if (fAttemptSighashDecode && !script.IsUnspendable()) {
+ std::string strSigHashDecode;
+ // goal: only attempt to decode a defined sighash type from data that looks like a signature within a scriptSig.
+ // this won't decode correctly formatted public keys in Pubkey or Multisig scripts due to
+ // the restrictions on the pubkey formats (see IsCompressedOrUncompressedPubKey) being incongruous with the
+ // checks in CheckSignatureEncoding.
+ if (CheckSignatureEncoding(vch, SCRIPT_VERIFY_STRICTENC, NULL)) {
+ const unsigned char chSigHashType = vch.back();
+ if (mapSigHashTypes.count(chSigHashType)) {
+ strSigHashDecode = "[" + mapSigHashTypes.find(chSigHashType)->second + "]";
+ vch.pop_back(); // remove the sighash type byte. it will be replaced by the decode.
+ }
+ }
+ str += HexStr(vch) + strSigHashDecode;
+ } else {
+ str += HexStr(vch);
+ }
+ }
+ } else {
+ str += GetOpName(opcode);
+ }
+ }
+ return str;
+}
+
+std::string EncodeHexTx(const CTransaction& tx, const int serialFlags)
+{
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | serialFlags);
ssTx << tx;
return HexStr(ssTx.begin(), ssTx.end());
}
@@ -65,10 +125,10 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
UniValue& out, bool fIncludeHex)
{
txnouttype type;
- vector<CTxDestination> addresses;
+ std::vector<CTxDestination> addresses;
int nRequired;
- out.pushKV("asm", scriptPubKey.ToString());
+ out.pushKV("asm", ScriptToAsmStr(scriptPubKey));
if (fIncludeHex)
out.pushKV("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
@@ -89,11 +149,13 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry)
{
entry.pushKV("txid", tx.GetHash().GetHex());
+ entry.pushKV("hash", tx.GetWitnessHash().GetHex());
entry.pushKV("version", tx.nVersion);
entry.pushKV("locktime", (int64_t)tx.nLockTime);
UniValue vin(UniValue::VARR);
- BOOST_FOREACH(const CTxIn& txin, tx.vin) {
+ for (unsigned int i = 0; i < tx.vin.size(); i++) {
+ const CTxIn& txin = tx.vin[i];
UniValue in(UniValue::VOBJ);
if (tx.IsCoinBase())
in.pushKV("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
@@ -101,9 +163,16 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry)
in.pushKV("txid", txin.prevout.hash.GetHex());
in.pushKV("vout", (int64_t)txin.prevout.n);
UniValue o(UniValue::VOBJ);
- o.pushKV("asm", txin.scriptSig.ToString());
+ o.pushKV("asm", ScriptToAsmStr(txin.scriptSig, true));
o.pushKV("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
in.pushKV("scriptSig", o);
+ if (!tx.vin[i].scriptWitness.IsNull()) {
+ UniValue txinwitness(UniValue::VARR);
+ for (const auto& item : tx.vin[i].scriptWitness.stack) {
+ txinwitness.push_back(HexStr(item.begin(), item.end()));
+ }
+ in.pushKV("txinwitness", txinwitness);
+ }
}
in.pushKV("sequence", (int64_t)txin.nSequence);
vin.push_back(in);