@@ -28,11 +28,11 @@ static const CBigNum bnZero(0);
2828static const CBigNum bnOne (1 );
2929static const CBigNum bnFalse (0 );
3030static const CBigNum bnTrue (1 );
31- static const size_t nMaxNumSize = 4 ;
31+ static const size_t nDefaultMaxNumSize = 4 ;
3232
3333
34- CBigNum CastToBigNum (const valtype& vch)
35- {
34+ CBigNum CastToBigNum (const valtype & vch, const size_t nMaxNumSize = nDefaultMaxNumSize) {
35+
3636 if (vch.size () > nMaxNumSize)
3737 throw runtime_error (" CastToBigNum() : overflow" );
3838 // Get rid of extra leading zeros
@@ -228,10 +228,10 @@ const char* GetOpName(opcodetype opcode)
228228 case OP_CHECKSIGVERIFY : return " OP_CHECKSIGVERIFY" ;
229229 case OP_CHECKMULTISIG : return " OP_CHECKMULTISIG" ;
230230 case OP_CHECKMULTISIGVERIFY : return " OP_CHECKMULTISIGVERIFY" ;
231+ case OP_CHECKLOCKTIMEVERIFY : return " OP_CHECKLOCKTIMEVERIFY" ; /* former OP_NOP2 */
231232
232233 // expanson
233234 case OP_NOP1 : return " OP_NOP1" ;
234- case OP_NOP2 : return " OP_NOP2" ;
235235 case OP_NOP3 : return " OP_NOP3" ;
236236 case OP_NOP4 : return " OP_NOP4" ;
237237 case OP_NOP5 : return " OP_NOP5" ;
@@ -480,10 +480,79 @@ bool EvalScript(vector<vector<uchar> > &stack, const CScript &script, const CTra
480480 //
481481 // Control
482482 //
483- case OP_NOP:
484- case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5:
485- case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
486- break ;
483+ case (OP_NOP):
484+ break ;
485+
486+ case (OP_CHECKLOCKTIMEVERIFY): {
487+ /* Treat as OP_NOP2 if disabled */
488+ if (!(flags & SCRIPT_VERIFY_LOCKTIME))
489+ break ;
490+
491+ if (stack.size () < 1 )
492+ return (false );
493+
494+ // Note that elsewhere numeric opcodes are limited to
495+ // operands in the range -2**31+1 to 2**31-1, however it is
496+ // legal for opcodes to produce results exceeding that
497+ // range. This limitation is implemented by CScriptNum's
498+ // default 4-byte limit.
499+ //
500+ // If we kept to that limit we'd have a year 2038 problem,
501+ // even though the nLockTime field in transactions
502+ // themselves is uint32 which only becomes meaningless
503+ // after the year 2106.
504+ //
505+ // Thus as a special case we tell CastToBigNum to accept up
506+ // to 5-byte bignums, which are good until 2**39-1, well
507+ // beyond the 2**32-1 limit of the nLockTime field itself.
508+ const CBigNum nLockTime = CastToBigNum (stacktop (-1 ), 5 );
509+
510+ // In the rare event that the argument may be < 0 due to
511+ // some arithmetic being done first, you can always use
512+ // 0 MAX CHECKLOCKTIMEVERIFY.
513+ if (nLockTime < 0 )
514+ return (false );
515+
516+ // There are two times of nLockTime: lock-by-blockheight
517+ // and lock-by-blocktime, distinguished by whether
518+ // nLockTime < LOCKTIME_THRESHOLD.
519+ //
520+ // We want to compare apples to apples, so fail the script
521+ // unless the type of nLockTime being tested is the same as
522+ // the nLockTime in the transaction.
523+ if (!(((txTo.nLockTime < LOCKTIME_THRESHOLD) && (nLockTime < LOCKTIME_THRESHOLD)) ||
524+ ((txTo.nLockTime >= LOCKTIME_THRESHOLD) && (nLockTime >= LOCKTIME_THRESHOLD))))
525+ return (false );
526+
527+ // Now that we know we're comparing apples-to-apples,
528+ // the comparison is a simple numeric one.
529+ if (nLockTime > (int64_t )txTo.nLockTime )
530+ return (false );
531+
532+ // Finally the nLockTime feature can be disabled and thus
533+ // CHECKLOCKTIMEVERIFY bypassed if every txin has been
534+ // finalized by setting nSequence to maxint. The
535+ // transaction would be allowed into the blockchain, making
536+ // the opcode ineffective.
537+ //
538+ // Testing if this vin is not final is sufficient to
539+ // prevent this condition. Alternatively we could test all
540+ // inputs, but testing just this input minimizes the data
541+ // required to prove correct CHECKLOCKTIMEVERIFY execution.
542+ if (txTo.vin [nIn].IsFinal ())
543+ return (false );
544+ } break ;
545+
546+ case (OP_NOP1):
547+ case (OP_NOP3):
548+ case (OP_NOP4):
549+ case (OP_NOP5):
550+ case (OP_NOP6):
551+ case (OP_NOP7):
552+ case (OP_NOP8):
553+ case (OP_NOP9):
554+ case (OP_NOP10):
555+ break ;
487556
488557 case OP_IF:
489558 case OP_NOTIF:
@@ -2201,3 +2270,146 @@ bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigne
22012270 }
22022271 return false ;
22032272}
2273+
2274+
2275+ #include < boost/assign/list_of.hpp>
2276+
2277+ const map<uchar, string> mapSigHashTypes = boost::assign::map_list_of
2278+ (static_cast <uchar>(SIGHASH_ALL), string(" ALL" ))
2279+ (static_cast <uchar>(SIGHASH_ALL|SIGHASH_ANYONECANPAY), string(" ALL|ANYONECANPAY" ))
2280+ (static_cast <uchar>(SIGHASH_NONE), string(" NONE" ))
2281+ (static_cast <uchar>(SIGHASH_NONE|SIGHASH_ANYONECANPAY), string(" NONE|ANYONECANPAY" ))
2282+ (static_cast <uchar>(SIGHASH_SINGLE), string(" SINGLE" ))
2283+ (static_cast <unsigned char >(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY), string(" SINGLE|ANYONECANPAY" ));
2284+
2285+ /* *
2286+ * Create the assembly string representation of a CScript object.
2287+ * @param[in] script CScript object to convert into the asm string representation.
2288+ * @param[in] fAttemptSighashDecode Whether to attempt to decode sighash types on data within the script that matches the format
2289+ * of a signature. Only pass true for scripts you believe could contain signatures. For example,
2290+ * pass false, or omit the this argument (defaults to false), for scriptPubKeys.
2291+ */
2292+ std::string ScriptToAsmStr (const CScript &script, const bool fAttemptSighashDecode ) {
2293+ std::string str;
2294+ opcodetype opcode;
2295+ vector<uchar> vch;
2296+
2297+ CScript::const_iterator pc = script.begin ();
2298+ while (pc < script.end ()) {
2299+ if (!str.empty ()) {
2300+ str += " " ;
2301+ }
2302+ if (!script.GetOp (pc, opcode, vch)) {
2303+ str += " [error]" ;
2304+ return (str);
2305+ }
2306+ if ((0 <= opcode) && (opcode <= OP_PUSHDATA4)) {
2307+ if (vch.size () <= static_cast <vector<uchar>::size_type>(4 )) {
2308+ str += strprintf (" %d" , CBigNum (vch).getint ());
2309+ } else {
2310+ // the IsUnspendable check makes sure not to try to decode OP_RETURN data that may match the format of a signature
2311+ if (fAttemptSighashDecode && !script.IsUnspendable ()) {
2312+ string strSigHashDecode;
2313+ // goal: only attempt to decode a defined sighash type from data that looks like a signature within a scriptSig.
2314+ // this won't decode correctly formatted public keys in Pubkey or Multisig scripts due to
2315+ // the restrictions on the pubkey formats (see IsCompressedOrUncompressedPubKey) being incongruous with the
2316+ // checks in CheckSignatureEncoding.
2317+ if (CheckSignatureEncoding (vch, SCRIPT_VERIFY_STRICTENC)) {
2318+ const uchar chSigHashType = vch.back ();
2319+ if (mapSigHashTypes.count (chSigHashType)) {
2320+ strSigHashDecode = " [" + mapSigHashTypes.find (chSigHashType)->second + " ]" ;
2321+ vch.pop_back (); // remove the sighash type byte. it will be replaced by the decode.
2322+ }
2323+ }
2324+ str += HexStr (vch) + strSigHashDecode;
2325+ } else {
2326+ str += HexStr (vch);
2327+ }
2328+ }
2329+ } else {
2330+ str += GetOpName (opcode);
2331+ }
2332+ }
2333+ return (str);
2334+ }
2335+
2336+ #include < boost/algorithm/string/classification.hpp>
2337+ #include < boost/algorithm/string/predicate.hpp>
2338+ #include < boost/algorithm/string/replace.hpp>
2339+ #include < boost/algorithm/string/split.hpp>
2340+
2341+ static map<std::string, opcodetype> mapOpNames;
2342+
2343+ /* Script parser for unit tests;
2344+ * fills out CScript from std:string, returns 1 on success or 0 on failure */
2345+ bool ParseScript (const std::string &source, CScript &result) {
2346+ uint op;
2347+
2348+ /* One time action */
2349+ if (mapOpNames.empty ()) {
2350+ const char *name;
2351+ std::string strName;
2352+
2353+ /* Process opcode range [0x61:0xB9] */
2354+ for (op = OP_NOP; op <= OP_NOP10; op++) {
2355+ name = GetOpName ((opcodetype)op);
2356+ if (!strcmp (name, " OP_UNKNOWN" ))
2357+ continue ;
2358+
2359+ strName = std::string (name);
2360+ mapOpNames[strName] = (opcodetype)op;
2361+
2362+ /* Opcodes are recognised with or without OP_ */
2363+ boost::algorithm::replace_first (strName, " OP_" , " " );
2364+ mapOpNames[strName] = (opcodetype)op;
2365+ }
2366+ /* Insert OP_RESERVED (0x50) */
2367+ mapOpNames[std::string (" OP_RESERVED" )] = (opcodetype)0x50 ;
2368+ mapOpNames[std::string (" RESERVED" )] = (opcodetype)0x50 ;
2369+ /* Insert OP_NOP2 (0xB1); upgraded to OP_CHECKLOCKTIMEVERIFY */
2370+ mapOpNames[std::string (" OP_NOP2" )] = (opcodetype)0xB1 ;
2371+ mapOpNames[std::string (" NOP2" )] = (opcodetype)0xB1 ;
2372+ }
2373+
2374+ vector<string> words;
2375+ boost::algorithm::split (words, source, boost::algorithm::is_any_of (" \t\n " ),
2376+ boost::algorithm::token_compress_on);
2377+
2378+ for (std::vector<std::string>::const_iterator w = words.begin (); w != words.end (); w++) {
2379+ if (w->empty ()) {
2380+ /* Empty string, ignore; boost::split given '' will return one word */
2381+ continue ;
2382+ }
2383+ if (all (*w, boost::algorithm::is_digit ()) ||
2384+ ((boost::algorithm::starts_with (*w, " -" ) &&
2385+ all (string (w->begin () + 1 , w->end ()), boost::algorithm::is_digit ())))) {
2386+ /* Number */
2387+ int64 n = atoi64 (*w);
2388+ result << n;
2389+ continue ;
2390+ }
2391+ if (boost::algorithm::starts_with (*w, " 0x" ) && ((w->begin () + 2 ) != w->end ()) &&
2392+ IsHex (string (w->begin () + 2 , w->end ()))) {
2393+ /* Raw hex data, inserted NOT pushed into stack */
2394+ std::vector<uchar> raw = ParseHex (string (w->begin () + 2 , w->end ()));
2395+ result.insert (result.end (), raw.begin (), raw.end ());
2396+ continue ;
2397+ }
2398+ if ((w->size () >= 2 ) && boost::algorithm::starts_with (*w, " '" ) &&
2399+ boost::algorithm::ends_with (*w, " '" )) {
2400+ /* Single-quoted string, pushed as data. NOTE: this is poor-man's
2401+ * parsing, spaces/tabs/newlines in single-quoted strings won't work */
2402+ std::vector<uchar> value (w->begin () + 1 , w->end () - 1 );
2403+ result << value;
2404+ continue ;
2405+ }
2406+ if (mapOpNames.count (*w)) {
2407+ /* Opcode */
2408+ result << mapOpNames[*w];
2409+ continue ;
2410+ }
2411+ return (false );
2412+ }
2413+
2414+ return (true );
2415+ }
0 commit comments