1 // Copyright (c) 2009-2015 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>
23 string
FormatScript(const CScript
& script
)
26 CScript::const_iterator it
= script
.begin();
28 while (it
!= script
.end()) {
29 CScript::const_iterator it2
= it
;
30 vector
<unsigned char> vch
;
31 if (script
.GetOp2(it
, op
, &vch
)) {
35 } else if ((op
>= OP_1
&& op
<= OP_16
) || op
== OP_1NEGATE
) {
36 ret
+= strprintf("%i ", op
- OP_1NEGATE
- 1);
38 } else if (op
>= OP_NOP
&& op
<= OP_NOP10
) {
39 string
str(GetOpName(op
));
40 if (str
.substr(0, 3) == string("OP_")) {
41 ret
+= str
.substr(3, string::npos
) + " ";
46 ret
+= strprintf("0x%x 0x%x ", HexStr(it2
, it
- vch
.size()), HexStr(it
- vch
.size(), it
));
48 ret
+= strprintf("0x%x ", HexStr(it2
, it
));
52 ret
+= strprintf("0x%x ", HexStr(it2
, script
.end()));
55 return ret
.substr(0, ret
.size() - 1);
58 const map
<unsigned char, string
> mapSigHashTypes
=
59 boost::assign::map_list_of
60 (static_cast<unsigned char>(SIGHASH_ALL
), string("ALL"))
61 (static_cast<unsigned char>(SIGHASH_ALL
|SIGHASH_ANYONECANPAY
), string("ALL|ANYONECANPAY"))
62 (static_cast<unsigned char>(SIGHASH_NONE
), string("NONE"))
63 (static_cast<unsigned char>(SIGHASH_NONE
|SIGHASH_ANYONECANPAY
), string("NONE|ANYONECANPAY"))
64 (static_cast<unsigned char>(SIGHASH_SINGLE
), string("SINGLE"))
65 (static_cast<unsigned char>(SIGHASH_SINGLE
|SIGHASH_ANYONECANPAY
), string("SINGLE|ANYONECANPAY"))
69 * Create the assembly string representation of a CScript object.
70 * @param[in] script CScript object to convert into the asm string representation.
71 * @param[in] fAttemptSighashDecode Whether to attempt to decode sighash types on data within the script that matches the format
72 * of a signature. Only pass true for scripts you believe could contain signatures. For example,
73 * pass false, or omit the this argument (defaults to false), for scriptPubKeys.
75 string
ScriptToAsmStr(const CScript
& script
, const bool fAttemptSighashDecode
)
79 vector
<unsigned char> vch
;
80 CScript::const_iterator pc
= script
.begin();
81 while (pc
< script
.end()) {
85 if (!script
.GetOp(pc
, opcode
, vch
)) {
89 if (0 <= opcode
&& opcode
<= OP_PUSHDATA4
) {
90 if (vch
.size() <= static_cast<vector
<unsigned char>::size_type
>(4)) {
91 str
+= strprintf("%d", CScriptNum(vch
, false).getint());
93 // the IsUnspendable check makes sure not to try to decode OP_RETURN data that may match the format of a signature
94 if (fAttemptSighashDecode
&& !script
.IsUnspendable()) {
95 string strSigHashDecode
;
96 // goal: only attempt to decode a defined sighash type from data that looks like a signature within a scriptSig.
97 // this won't decode correctly formatted public keys in Pubkey or Multisig scripts due to
98 // the restrictions on the pubkey formats (see IsCompressedOrUncompressedPubKey) being incongruous with the
99 // checks in CheckSignatureEncoding.
100 if (CheckSignatureEncoding(vch
, SCRIPT_VERIFY_STRICTENC
, NULL
)) {
101 const unsigned char chSigHashType
= vch
.back();
102 if (mapSigHashTypes
.count(chSigHashType
)) {
103 strSigHashDecode
= "[" + mapSigHashTypes
.find(chSigHashType
)->second
+ "]";
104 vch
.pop_back(); // remove the sighash type byte. it will be replaced by the decode.
107 str
+= HexStr(vch
) + strSigHashDecode
;
113 str
+= GetOpName(opcode
);
119 string
EncodeHexTx(const CTransaction
& tx
)
121 CDataStream
ssTx(SER_NETWORK
, PROTOCOL_VERSION
);
123 return HexStr(ssTx
.begin(), ssTx
.end());
126 void ScriptPubKeyToUniv(const CScript
& scriptPubKey
,
127 UniValue
& out
, bool fIncludeHex
)
130 vector
<CTxDestination
> addresses
;
133 out
.pushKV("asm", ScriptToAsmStr(scriptPubKey
));
135 out
.pushKV("hex", HexStr(scriptPubKey
.begin(), scriptPubKey
.end()));
137 if (!ExtractDestinations(scriptPubKey
, type
, addresses
, nRequired
)) {
138 out
.pushKV("type", GetTxnOutputType(type
));
142 out
.pushKV("reqSigs", nRequired
);
143 out
.pushKV("type", GetTxnOutputType(type
));
145 UniValue
a(UniValue::VARR
);
146 BOOST_FOREACH(const CTxDestination
& addr
, addresses
)
147 a
.push_back(CBitcoinAddress(addr
).ToString());
148 out
.pushKV("addresses", a
);
151 void TxToUniv(const CTransaction
& tx
, const uint256
& hashBlock
, UniValue
& entry
)
153 entry
.pushKV("txid", tx
.GetHash().GetHex());
154 entry
.pushKV("hash", tx
.GetWitnessHash().GetHex());
155 entry
.pushKV("version", tx
.nVersion
);
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
.wit
.IsNull() && i
< tx
.wit
.vtxinwit
.size() && !tx
.wit
.vtxinwit
[i
].IsNull()) {
172 UniValue
txinwitness(UniValue::VARR
);
173 for (const auto& item
: tx
.wit
.vtxinwit
[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".