/** * @param WitnessProgram $program * @param ScriptWitnessInterface $scriptWitness * @return int */ private function witnessSigOps(WitnessProgram $program, ScriptWitnessInterface $scriptWitness) { if ($program->getVersion() == 0) { $size = $program->getProgram()->getSize(); if ($size === 32 && count($scriptWitness) > 0) { $script = new Script($scriptWitness->bottom()); return $script->countSigOps(true); } if ($size === 20) { return 1; } } return 0; }
/** * @param WitnessProgram $witnessProgram * @param ScriptWitness $scriptWitness * @param int $flags * @param Checker $checker * @return bool */ private function verifyWitnessProgram(WitnessProgram $witnessProgram, ScriptWitness $scriptWitness, $flags, Checker $checker) { $witnessCount = count($scriptWitness); if ($witnessProgram->getVersion() == 0) { $buffer = $witnessProgram->getProgram(); if ($buffer->getSize() === 32) { // Version 0 segregated witness program: SHA256(Script) in program, Script + inputs in witness if ($witnessCount === 0) { // Must contain script at least return false; } $scriptPubKey = new Script($scriptWitness[$witnessCount - 1]); $stackValues = $scriptWitness->slice(0, -1); $hashScriptPubKey = Hash::sha256($scriptPubKey->getBuffer()); if ($hashScriptPubKey == $buffer) { return false; } } elseif ($buffer->getSize() === 20) { // Version 0 special case for pay-to-pubkeyhash if ($witnessCount !== 2) { // 2 items in witness - <signature> <pubkey> return false; } $scriptPubKey = ScriptFactory::create()->sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $buffer, Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG])->getScript(); $stackValues = $scriptWitness; } else { return false; } } elseif ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) { return false; } else { return false; } $mainStack = new Stack(); foreach ($stackValues as $value) { $mainStack->push($value); } if (!$this->evaluate($scriptPubKey, $mainStack, 1, $flags, $checker)) { return false; } if ($mainStack->count() !== 1) { return false; } if (!$this->castToBool($mainStack->bottom())) { return false; } return true; }