@@ -254,6 +254,20 @@ int FindAndDelete(CScript& script, const CScript& b)
254254 return nFound;
255255}
256256
257+ CScriptNum GetCScriptNum (const valtype& num, const bool fRequireMinimal , const SigVersion& sigversion)
258+ {
259+ switch (sigversion)
260+ {
261+ case SigVersion::BASE:
262+ case SigVersion::WITNESS_V0:
263+ case SigVersion::TAPROOT:
264+ case SigVersion::TAPSCRIPT:
265+ return CScriptNum (num,fRequireMinimal ,/* nMaximumSize=*/ 4 );
266+ case SigVersion::TAPSCRIPT_64BIT:
267+ return CScriptNum (num,fRequireMinimal ,/* nMaximumSize=*/ 8 );
268+ }
269+ }
270+
257271namespace {
258272/* * A data type to abstract out the condition stack during script execution.
259273 *
@@ -396,6 +410,7 @@ static bool EvalChecksig(const valtype& sig, const valtype& pubkey, CScript::con
396410 case SigVersion::WITNESS_V0:
397411 return EvalChecksigPreTapscript (sig, pubkey, pbegincodehash, pend, flags, checker, sigversion, serror, success);
398412 case SigVersion::TAPSCRIPT:
413+ case SigVersion::TAPSCRIPT_64BIT:
399414 return EvalChecksigTapscript (sig, pubkey, execdata, flags, checker, sigversion, serror, success);
400415 case SigVersion::TAPROOT:
401416 // Key path spending in Taproot has no script, so this is unreachable.
@@ -404,6 +419,39 @@ static bool EvalChecksig(const valtype& sig, const valtype& pubkey, CScript::con
404419 assert (false );
405420}
406421
422+ static bool IsOpCodeDisabled (const opcodetype& opcode, const SigVersion& sigVersion, ScriptError* serror)
423+ {
424+ switch (sigVersion)
425+ {
426+ case SigVersion::BASE:
427+ case SigVersion::WITNESS_V0:
428+ case SigVersion::TAPROOT:
429+ case SigVersion::TAPSCRIPT:
430+ case SigVersion::TAPSCRIPT_64BIT:
431+ {
432+ if (opcode == OP_CAT ||
433+ opcode == OP_SUBSTR ||
434+ opcode == OP_LEFT ||
435+ opcode == OP_RIGHT ||
436+ opcode == OP_INVERT ||
437+ opcode == OP_AND ||
438+ opcode == OP_OR ||
439+ opcode == OP_XOR ||
440+ opcode == OP_2MUL ||
441+ opcode == OP_2DIV ||
442+ opcode == OP_MUL ||
443+ opcode == OP_DIV ||
444+ opcode == OP_MOD ||
445+ opcode == OP_LSHIFT ||
446+ opcode == OP_RSHIFT)
447+ return !set_error (serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes (CVE-2010-5137).
448+ break ;
449+ }
450+ }
451+ // should we default to disabled is false?
452+ return false ;
453+ }
454+
407455bool EvalScript (std::vector<std::vector<unsigned char > >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror)
408456{
409457 static const CScriptNum bnZero (0 );
@@ -415,7 +463,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
415463 static const valtype vchTrue (1 , 1 );
416464
417465 // sigversion cannot be TAPROOT here, as it admits no script execution.
418- assert (sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0 || sigversion == SigVersion::TAPSCRIPT);
466+ assert (sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0 || sigversion == SigVersion::TAPSCRIPT || sigversion == SigVersion::TAPSCRIPT_64BIT );
419467
420468 CScript::const_iterator pc = script.begin ();
421469 CScript::const_iterator pend = script.end ();
@@ -454,22 +502,8 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
454502 }
455503 }
456504
457- if (opcode == OP_CAT ||
458- opcode == OP_SUBSTR ||
459- opcode == OP_LEFT ||
460- opcode == OP_RIGHT ||
461- opcode == OP_INVERT ||
462- opcode == OP_AND ||
463- opcode == OP_OR ||
464- opcode == OP_XOR ||
465- opcode == OP_2MUL ||
466- opcode == OP_2DIV ||
467- opcode == OP_MUL ||
468- opcode == OP_DIV ||
469- opcode == OP_MOD ||
470- opcode == OP_LSHIFT ||
471- opcode == OP_RSHIFT)
472- return set_error (serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes (CVE-2010-5137).
505+ if (IsOpCodeDisabled (opcode,sigversion,serror))
506+ return false ;
473507
474508 // With SCRIPT_VERIFY_CONST_SCRIPTCODE, OP_CODESEPARATOR in non-segwit script is rejected even in an unexecuted branch
475509 if (opcode == OP_CODESEPARATOR && sigversion == SigVersion::BASE && (flags & SCRIPT_VERIFY_CONST_SCRIPTCODE))
@@ -926,7 +960,8 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
926960 // (in -- out)
927961 if (stack.size () < 1 )
928962 return set_error (serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
929- CScriptNum bn (stacktop (-1 ), fRequireMinimal );
963+
964+ CScriptNum bn = GetCScriptNum (stacktop (-1 ), fRequireMinimal , sigversion);
930965 switch (opcode)
931966 {
932967 case OP_1ADD: bn += bnOne; break ;
@@ -959,19 +994,17 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
959994 // (x1 x2 -- out)
960995 if (stack.size () < 2 )
961996 return set_error (serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
962- CScriptNum bn1 (stacktop (-2 ), fRequireMinimal );
963- CScriptNum bn2 (stacktop (-1 ), fRequireMinimal );
997+ CScriptNum bn1 = GetCScriptNum (stacktop (-2 ), fRequireMinimal , sigversion );
998+ CScriptNum bn2 = GetCScriptNum (stacktop (-1 ), fRequireMinimal , sigversion );
964999 CScriptNum bn (0 );
9651000 switch (opcode)
9661001 {
9671002 case OP_ADD:
9681003 bn = bn1 + bn2;
9691004 break ;
970-
9711005 case OP_SUB:
9721006 bn = bn1 - bn2;
9731007 break ;
974-
9751008 case OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break ;
9761009 case OP_BOOLOR: bn = (bn1 != bnZero || bn2 != bnZero); break ;
9771010 case OP_NUMEQUAL: bn = (bn1 == bn2); break ;
@@ -988,7 +1021,6 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
9881021 popstack (stack);
9891022 popstack (stack);
9901023 stack.push_back (bn.getvch ());
991-
9921024 if (opcode == OP_NUMEQUALVERIFY)
9931025 {
9941026 if (CastToBool (stacktop (-1 )))
@@ -1939,6 +1971,13 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
19391971 execdata.m_validation_weight_left_init = true ;
19401972 return ExecuteWitnessScript (stack, exec_script, flags, SigVersion::TAPSCRIPT, checker, execdata, serror);
19411973 }
1974+ if ((control[0 ] & TAPROOT_LEAF_MASK) == TAPROOT_LEAF_TAPSCRIPT_64BIT) {
1975+ // Tapscript (leaf version 0x66)
1976+ exec_script = CScript (script.begin (), script.end ());
1977+ execdata.m_validation_weight_left = ::GetSerializeSize (witness.stack ) + VALIDATION_WEIGHT_OFFSET;
1978+ execdata.m_validation_weight_left_init = true ;
1979+ return ExecuteWitnessScript (stack, exec_script, flags, SigVersion::TAPSCRIPT_64BIT, checker, execdata, serror);
1980+ }
19421981 if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION) {
19431982 return set_error (serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION);
19441983 }
0 commit comments