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/foreach.hpp>
20 std::string
FormatScript(const CScript
& script
)
23 CScript::const_iterator it
= script
.begin();
25 while (it
!= script
.end()) {
26 CScript::const_iterator it2
= it
;
27 std::vector
<unsigned char> vch
;
28 if (script
.GetOp2(it
, op
, &vch
)) {
32 } else if ((op
>= OP_1
&& op
<= OP_16
) || op
== OP_1NEGATE
) {
33 ret
+= strprintf("%i ", op
- OP_1NEGATE
- 1);
35 } else if (op
>= OP_NOP
&& op
<= OP_NOP10
) {
36 std::string
str(GetOpName(op
));
37 if (str
.substr(0, 3) == std::string("OP_")) {
38 ret
+= str
.substr(3, std::string::npos
) + " ";
43 ret
+= strprintf("0x%x 0x%x ", HexStr(it2
, it
- vch
.size()), HexStr(it
- vch
.size(), it
));
45 ret
+= strprintf("0x%x ", HexStr(it2
, it
));
49 ret
+= strprintf("0x%x ", HexStr(it2
, script
.end()));
52 return ret
.substr(0, ret
.size() - 1);
55 const std::map
<unsigned char, std::string
> mapSigHashTypes
= {
56 {static_cast<unsigned char>(SIGHASH_ALL
), std::string("ALL")},
57 {static_cast<unsigned char>(SIGHASH_ALL
|SIGHASH_ANYONECANPAY
), std::string("ALL|ANYONECANPAY")},
58 {static_cast<unsigned char>(SIGHASH_NONE
), std::string("NONE")},
59 {static_cast<unsigned char>(SIGHASH_NONE
|SIGHASH_ANYONECANPAY
), std::string("NONE|ANYONECANPAY")},
60 {static_cast<unsigned char>(SIGHASH_SINGLE
), std::string("SINGLE")},
61 {static_cast<unsigned char>(SIGHASH_SINGLE
|SIGHASH_ANYONECANPAY
), std::string("SINGLE|ANYONECANPAY")},
65 * Create the assembly string representation of a CScript object.
66 * @param[in] script CScript object to convert into the asm string representation.
67 * @param[in] fAttemptSighashDecode Whether to attempt to decode sighash types on data within the script that matches the format
68 * of a signature. Only pass true for scripts you believe could contain signatures. For example,
69 * pass false, or omit the this argument (defaults to false), for scriptPubKeys.
71 std::string
ScriptToAsmStr(const CScript
& script
, const bool fAttemptSighashDecode
)
75 std::vector
<unsigned char> vch
;
76 CScript::const_iterator pc
= script
.begin();
77 while (pc
< script
.end()) {
81 if (!script
.GetOp(pc
, opcode
, vch
)) {
85 if (0 <= opcode
&& opcode
<= OP_PUSHDATA4
) {
86 if (vch
.size() <= static_cast<std::vector
<unsigned char>::size_type
>(4)) {
87 str
+= strprintf("%d", CScriptNum(vch
, false).getint());
89 // the IsUnspendable check makes sure not to try to decode OP_RETURN data that may match the format of a signature
90 if (fAttemptSighashDecode
&& !script
.IsUnspendable()) {
91 std::string strSigHashDecode
;
92 // goal: only attempt to decode a defined sighash type from data that looks like a signature within a scriptSig.
93 // this won't decode correctly formatted public keys in Pubkey or Multisig scripts due to
94 // the restrictions on the pubkey formats (see IsCompressedOrUncompressedPubKey) being incongruous with the
95 // checks in CheckSignatureEncoding.
96 if (CheckSignatureEncoding(vch
, SCRIPT_VERIFY_STRICTENC
, NULL
)) {
97 const unsigned char chSigHashType
= vch
.back();
98 if (mapSigHashTypes
.count(chSigHashType
)) {
99 strSigHashDecode
= "[" + mapSigHashTypes
.find(chSigHashType
)->second
+ "]";
100 vch
.pop_back(); // remove the sighash type byte. it will be replaced by the decode.
103 str
+= HexStr(vch
) + strSigHashDecode
;
109 str
+= GetOpName(opcode
);
115 std::string
EncodeHexTx(const CTransaction
& tx
, const int serializeFlags
)
117 CDataStream
ssTx(SER_NETWORK
, PROTOCOL_VERSION
| serializeFlags
);
119 return HexStr(ssTx
.begin(), ssTx
.end());
122 void ScriptPubKeyToUniv(const CScript
& scriptPubKey
,
123 UniValue
& out
, bool fIncludeHex
)
126 std::vector
<CTxDestination
> addresses
;
129 out
.pushKV("asm", ScriptToAsmStr(scriptPubKey
));
131 out
.pushKV("hex", HexStr(scriptPubKey
.begin(), scriptPubKey
.end()));
133 if (!ExtractDestinations(scriptPubKey
, type
, addresses
, nRequired
)) {
134 out
.pushKV("type", GetTxnOutputType(type
));
138 out
.pushKV("reqSigs", nRequired
);
139 out
.pushKV("type", GetTxnOutputType(type
));
141 UniValue
a(UniValue::VARR
);
142 for (const CTxDestination
& addr
: addresses
)
143 a
.push_back(CBitcoinAddress(addr
).ToString());
144 out
.pushKV("addresses", a
);
147 void TxToUniv(const CTransaction
& tx
, const uint256
& hashBlock
, UniValue
& entry
)
149 entry
.pushKV("txid", tx
.GetHash().GetHex());
150 entry
.pushKV("hash", tx
.GetWitnessHash().GetHex());
151 entry
.pushKV("version", tx
.nVersion
);
152 entry
.pushKV("size", (int)::GetSerializeSize(tx
, SER_NETWORK
, PROTOCOL_VERSION
));
153 entry
.pushKV("vsize", (GetTransactionWeight(tx
) + WITNESS_SCALE_FACTOR
- 1) / WITNESS_SCALE_FACTOR
);
154 entry
.pushKV("locktime", (int64_t)tx
.nLockTime
);
156 UniValue
vin(UniValue::VARR
);
157 for (unsigned int i
= 0; i
< tx
.vin
.size(); i
++) {
158 const CTxIn
& txin
= tx
.vin
[i
];
159 UniValue
in(UniValue::VOBJ
);
161 in
.pushKV("coinbase", HexStr(txin
.scriptSig
.begin(), txin
.scriptSig
.end()));
163 in
.pushKV("txid", txin
.prevout
.hash
.GetHex());
164 in
.pushKV("vout", (int64_t)txin
.prevout
.n
);
165 UniValue
o(UniValue::VOBJ
);
166 o
.pushKV("asm", ScriptToAsmStr(txin
.scriptSig
, true));
167 o
.pushKV("hex", HexStr(txin
.scriptSig
.begin(), txin
.scriptSig
.end()));
168 in
.pushKV("scriptSig", o
);
169 if (!tx
.vin
[i
].scriptWitness
.IsNull()) {
170 UniValue
txinwitness(UniValue::VARR
);
171 for (const auto& item
: tx
.vin
[i
].scriptWitness
.stack
) {
172 txinwitness
.push_back(HexStr(item
.begin(), item
.end()));
174 in
.pushKV("txinwitness", txinwitness
);
177 in
.pushKV("sequence", (int64_t)txin
.nSequence
);
180 entry
.pushKV("vin", vin
);
182 UniValue
vout(UniValue::VARR
);
183 for (unsigned int i
= 0; i
< tx
.vout
.size(); i
++) {
184 const CTxOut
& txout
= tx
.vout
[i
];
186 UniValue
out(UniValue::VOBJ
);
188 UniValue
outValue(UniValue::VNUM
, FormatMoney(txout
.nValue
));
189 out
.pushKV("value", outValue
);
190 out
.pushKV("n", (int64_t)i
);
192 UniValue
o(UniValue::VOBJ
);
193 ScriptPubKeyToUniv(txout
.scriptPubKey
, o
, true);
194 out
.pushKV("scriptPubKey", o
);
197 entry
.pushKV("vout", vout
);
199 if (!hashBlock
.IsNull())
200 entry
.pushKV("blockhash", hashBlock
.GetHex());
202 entry
.pushKV("hex", EncodeHexTx(tx
)); // the hex-encoded transaction. used the name "hex" to be consistent with the verbose output of "getrawtransaction".