1 // Copyright (c) 2009-2016 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
8 #include "primitives/transaction.h"
9 #include "script/script.h"
10 #include "script/standard.h"
11 #include "serialize.h"
15 #include "utilmoneystr.h"
16 #include "utilstrencodings.h"
18 #include <boost/assign/list_of.hpp>
19 #include <boost/foreach.hpp>
21 std::string
FormatScript(const CScript
& script
)
24 CScript::const_iterator it
= script
.begin();
26 while (it
!= script
.end()) {
27 CScript::const_iterator it2
= it
;
28 std::vector
<unsigned char> vch
;
29 if (script
.GetOp2(it
, op
, &vch
)) {
33 } else if ((op
>= OP_1
&& op
<= OP_16
) || op
== OP_1NEGATE
) {
34 ret
+= strprintf("%i ", op
- OP_1NEGATE
- 1);
36 } else if (op
>= OP_NOP
&& op
<= OP_NOP10
) {
37 std::string
str(GetOpName(op
));
38 if (str
.substr(0, 3) == std::string("OP_")) {
39 ret
+= str
.substr(3, std::string::npos
) + " ";
44 ret
+= strprintf("0x%x 0x%x ", HexStr(it2
, it
- vch
.size()), HexStr(it
- vch
.size(), it
));
46 ret
+= strprintf("0x%x ", HexStr(it2
, it
));
50 ret
+= strprintf("0x%x ", HexStr(it2
, script
.end()));
53 return ret
.substr(0, ret
.size() - 1);
56 const std::map
<unsigned char, std::string
> mapSigHashTypes
=
57 boost::assign::map_list_of
58 (static_cast<unsigned char>(SIGHASH_ALL
), std::string("ALL"))
59 (static_cast<unsigned char>(SIGHASH_ALL
|SIGHASH_ANYONECANPAY
), std::string("ALL|ANYONECANPAY"))
60 (static_cast<unsigned char>(SIGHASH_NONE
), std::string("NONE"))
61 (static_cast<unsigned char>(SIGHASH_NONE
|SIGHASH_ANYONECANPAY
), std::string("NONE|ANYONECANPAY"))
62 (static_cast<unsigned char>(SIGHASH_SINGLE
), std::string("SINGLE"))
63 (static_cast<unsigned char>(SIGHASH_SINGLE
|SIGHASH_ANYONECANPAY
), std::string("SINGLE|ANYONECANPAY"))
67 * Create the assembly string representation of a CScript object.
68 * @param[in] script CScript object to convert into the asm string representation.
69 * @param[in] fAttemptSighashDecode Whether to attempt to decode sighash types on data within the script that matches the format
70 * of a signature. Only pass true for scripts you believe could contain signatures. For example,
71 * pass false, or omit the this argument (defaults to false), for scriptPubKeys.
73 std::string
ScriptToAsmStr(const CScript
& script
, const bool fAttemptSighashDecode
)
77 std::vector
<unsigned char> vch
;
78 CScript::const_iterator pc
= script
.begin();
79 while (pc
< script
.end()) {
83 if (!script
.GetOp(pc
, opcode
, vch
)) {
87 if (0 <= opcode
&& opcode
<= OP_PUSHDATA4
) {
88 if (vch
.size() <= static_cast<std::vector
<unsigned char>::size_type
>(4)) {
89 str
+= strprintf("%d", CScriptNum(vch
, false).getint());
91 // the IsUnspendable check makes sure not to try to decode OP_RETURN data that may match the format of a signature
92 if (fAttemptSighashDecode
&& !script
.IsUnspendable()) {
93 std::string strSigHashDecode
;
94 // goal: only attempt to decode a defined sighash type from data that looks like a signature within a scriptSig.
95 // this won't decode correctly formatted public keys in Pubkey or Multisig scripts due to
96 // the restrictions on the pubkey formats (see IsCompressedOrUncompressedPubKey) being incongruous with the
97 // checks in CheckSignatureEncoding.
98 if (CheckSignatureEncoding(vch
, SCRIPT_VERIFY_STRICTENC
, NULL
)) {
99 const unsigned char chSigHashType
= vch
.back();
100 if (mapSigHashTypes
.count(chSigHashType
)) {
101 strSigHashDecode
= "[" + mapSigHashTypes
.find(chSigHashType
)->second
+ "]";
102 vch
.pop_back(); // remove the sighash type byte. it will be replaced by the decode.
105 str
+= HexStr(vch
) + strSigHashDecode
;
111 str
+= GetOpName(opcode
);
117 std::string
EncodeHexTx(const CTransaction
& tx
, const int serializeFlags
)
119 CDataStream
ssTx(SER_NETWORK
, PROTOCOL_VERSION
| serializeFlags
);
121 return HexStr(ssTx
.begin(), ssTx
.end());
124 void ScriptPubKeyToUniv(const CScript
& scriptPubKey
,
125 UniValue
& out
, bool fIncludeHex
)
128 std::vector
<CTxDestination
> addresses
;
131 out
.pushKV("asm", ScriptToAsmStr(scriptPubKey
));
133 out
.pushKV("hex", HexStr(scriptPubKey
.begin(), scriptPubKey
.end()));
135 if (!ExtractDestinations(scriptPubKey
, type
, addresses
, nRequired
)) {
136 out
.pushKV("type", GetTxnOutputType(type
));
140 out
.pushKV("reqSigs", nRequired
);
141 out
.pushKV("type", GetTxnOutputType(type
));
143 UniValue
a(UniValue::VARR
);
144 BOOST_FOREACH(const CTxDestination
& addr
, addresses
)
145 a
.push_back(CBitcoinAddress(addr
).ToString());
146 out
.pushKV("addresses", a
);
149 void TxToUniv(const CTransaction
& tx
, const uint256
& hashBlock
, UniValue
& entry
)
151 entry
.pushKV("txid", tx
.GetHash().GetHex());
152 entry
.pushKV("hash", tx
.GetWitnessHash().GetHex());
153 entry
.pushKV("version", tx
.nVersion
);
154 entry
.pushKV("size", (int)::GetSerializeSize(tx
, SER_NETWORK
, PROTOCOL_VERSION
));
155 entry
.pushKV("vsize", (GetTransactionWeight(tx
) + WITNESS_SCALE_FACTOR
- 1) / WITNESS_SCALE_FACTOR
);
156 entry
.pushKV("locktime", (int64_t)tx
.nLockTime
);
158 UniValue
vin(UniValue::VARR
);
159 for (unsigned int i
= 0; i
< tx
.vin
.size(); i
++) {
160 const CTxIn
& txin
= tx
.vin
[i
];
161 UniValue
in(UniValue::VOBJ
);
163 in
.pushKV("coinbase", HexStr(txin
.scriptSig
.begin(), txin
.scriptSig
.end()));
165 in
.pushKV("txid", txin
.prevout
.hash
.GetHex());
166 in
.pushKV("vout", (int64_t)txin
.prevout
.n
);
167 UniValue
o(UniValue::VOBJ
);
168 o
.pushKV("asm", ScriptToAsmStr(txin
.scriptSig
, true));
169 o
.pushKV("hex", HexStr(txin
.scriptSig
.begin(), txin
.scriptSig
.end()));
170 in
.pushKV("scriptSig", o
);
171 if (!tx
.vin
[i
].scriptWitness
.IsNull()) {
172 UniValue
txinwitness(UniValue::VARR
);
173 for (const auto& item
: tx
.vin
[i
].scriptWitness
.stack
) {
174 txinwitness
.push_back(HexStr(item
.begin(), item
.end()));
176 in
.pushKV("txinwitness", txinwitness
);
179 in
.pushKV("sequence", (int64_t)txin
.nSequence
);
182 entry
.pushKV("vin", vin
);
184 UniValue
vout(UniValue::VARR
);
185 for (unsigned int i
= 0; i
< tx
.vout
.size(); i
++) {
186 const CTxOut
& txout
= tx
.vout
[i
];
188 UniValue
out(UniValue::VOBJ
);
190 UniValue
outValue(UniValue::VNUM
, FormatMoney(txout
.nValue
));
191 out
.pushKV("value", outValue
);
192 out
.pushKV("n", (int64_t)i
);
194 UniValue
o(UniValue::VOBJ
);
195 ScriptPubKeyToUniv(txout
.scriptPubKey
, o
, true);
196 out
.pushKV("scriptPubKey", o
);
199 entry
.pushKV("vout", vout
);
201 if (!hashBlock
.IsNull())
202 entry
.pushKV("blockhash", hashBlock
.GetHex());
204 entry
.pushKV("hex", EncodeHexTx(tx
)); // the hex-encoded transaction. used the name "hex" to be consistent with the verbose output of "getrawtransaction".