* 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,
| 104 | * false, or omit the this argument (defaults to false), for scriptPubKeys. |
| 105 | */ |
| 106 | std::string ScriptToAsmStr(const CScript &script, |
| 107 | const bool fAttemptSighashDecode) { |
| 108 | std::string str; |
| 109 | opcodetype opcode; |
| 110 | std::vector<uint8_t> vch; |
| 111 | CScript::const_iterator pc = script.begin(); |
| 112 | while (pc < script.end()) { |
| 113 | if (!str.empty()) { |
| 114 | str += " "; |
| 115 | } |
| 116 | |
| 117 | if (!script.GetOp(pc, opcode, vch)) { |
| 118 | str += "[error]"; |
| 119 | return str; |
| 120 | } |
| 121 | |
| 122 | if (0 <= opcode && opcode <= OP_PUSHDATA4) { |
| 123 | if (CScriptNum::IsMinimallyEncoded(vch, MAX_SCRIPTNUM_BYTE_SIZE)) { |
| 124 | // Only render decimal number if minimally encoded and <8 bytes. |
| 125 | // Avoids rendering legitimate byte strings as decimal number. |
| 126 | str += strprintf( |
| 127 | "%d", |
| 128 | CScriptNum(vch, false, MAX_SCRIPTNUM_BYTE_SIZE).getint()); |
| 129 | } else { |
| 130 | // the IsUnspendable check makes sure not to try to decode |
| 131 | // OP_RETURN data that may match the format of a signature |
| 132 | if (fAttemptSighashDecode && !script.IsUnspendable()) { |
| 133 | std::string strSigHashDecode; |
| 134 | // goal: only attempt to decode a defined sighash type from |
| 135 | // data that looks like a signature within a scriptSig. This |
| 136 | // won't decode correctly formatted public keys in Pubkey or |
| 137 | // Multisig scripts due to the restrictions on the pubkey |
| 138 | // formats (see IsCompressedOrUncompressedPubKey) being |
| 139 | // incongruous with the checks in |
| 140 | // CheckTransactionSignatureEncoding. |
| 141 | uint32_t flags = SCRIPT_VERIFY_STRICTENC; |
| 142 | if (vch.back() & SIGHASH_FORKID) { |
| 143 | // If the transaction is using SIGHASH_FORKID, we need |
| 144 | // to set the appropriate flag. |
| 145 | // TODO: Remove after the Hard Fork. |
| 146 | flags |= SCRIPT_ENABLE_SIGHASH_FORKID; |
| 147 | } |
| 148 | if (CheckTransactionSignatureEncoding(vch, flags, |
| 149 | nullptr)) { |
| 150 | const uint8_t chSigHashType = vch.back(); |
| 151 | const auto it = mapSigHashTypes.find(chSigHashType); |
| 152 | if (it != mapSigHashTypes.end()) { |
| 153 | strSigHashDecode = "[" + it->second + "]"; |
| 154 | // remove the sighash type byte. it will be replaced |
| 155 | // by the decode. |
| 156 | vch.pop_back(); |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | str += HexStr(vch) + strSigHashDecode; |
| 161 | } else { |
| 162 | str += HexStr(vch); |
| 163 | } |