Exemplo n.º 1
0
 /**
  * @param ScriptInterface $scriptSig
  * @param ScriptInterface $scriptPubKey
  * @param int $flags
  * @param Checker $checker
  * @param ScriptWitnessInterface|null $witness
  * @return bool
  */
 public function verify(ScriptInterface $scriptSig, ScriptInterface $scriptPubKey, $flags, Checker $checker, ScriptWitnessInterface $witness = null)
 {
     static $emptyWitness = null;
     if ($emptyWitness === null) {
         $emptyWitness = new ScriptWitness([]);
     }
     $witness = $witness ?: $emptyWitness;
     if (($flags & self::VERIFY_SIGPUSHONLY) != 0 && !$scriptSig->isPushOnly()) {
         return false;
     }
     $stack = new Stack();
     if (!$this->evaluate($scriptSig, $stack, 0, $flags, $checker)) {
         return false;
     }
     $backup = [];
     if ($flags & self::VERIFY_P2SH) {
         foreach ($stack as $s) {
             $backup[] = $s;
         }
     }
     if (!$this->evaluate($scriptPubKey, $stack, 0, $flags, $checker)) {
         return false;
     }
     if ($stack->isEmpty()) {
         return false;
     }
     if (false === $this->castToBool($stack[-1])) {
         return false;
     }
     $program = null;
     if ($flags & self::VERIFY_WITNESS) {
         if ($scriptPubKey->isWitness($program)) {
             /** @var WitnessProgram $program */
             if ($scriptSig->getBuffer()->getSize() !== 0) {
                 return false;
             }
             if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
                 return false;
             }
             $stack->resize(1);
         }
     }
     if ($flags & self::VERIFY_P2SH && (new OutputClassifier($scriptPubKey))->isPayToScriptHash()) {
         if (!$scriptSig->isPushOnly()) {
             return false;
         }
         $stack = new Stack();
         foreach ($backup as $i) {
             $stack->push($i);
         }
         // Restore mainStack to how it was after evaluating scriptSig
         if ($stack->isEmpty()) {
             return false;
         }
         // Load redeemscript as the scriptPubKey
         $scriptPubKey = new Script($stack->bottom());
         $stack->pop();
         if (!$this->evaluate($scriptPubKey, $stack, 0, $flags, $checker)) {
             return false;
         }
         if ($stack->isEmpty()) {
             return false;
         }
         if (!$this->castToBool($stack->bottom())) {
             return false;
         }
         if ($flags & self::VERIFY_WITNESS) {
             if ($scriptPubKey->isWitness($program)) {
                 /** @var WitnessProgram $program */
                 if ($scriptSig != ScriptFactory::create()->push($scriptPubKey->getBuffer())->getScript()) {
                     return false;
                     // SCRIPT_ERR_WITNESS_MALLEATED_P2SH
                 }
                 if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
                     return false;
                 }
                 $stack->resize(1);
             }
         }
     }
     if ($flags & self::VERIFY_CLEAN_STACK != 0) {
         if (!($flags & self::VERIFY_P2SH != 0 && $flags & self::VERIFY_WITNESS != 0)) {
             return false;
             // implied flags required
         }
         if (count($stack) != 1) {
             return false;
             // Cleanstack
         }
     }
     if ($flags & self::VERIFY_WITNESS) {
         if (!$flags & self::VERIFY_P2SH) {
             return false;
             //
         }
         if ($program === null && !$witness->isNull()) {
             return false;
             // SCRIPT_ERR_WITNESS_UNEXPECTED
         }
     }
     return true;
 }