/**
  * @return bool
  */
 public function isMultisig()
 {
     if (count($this->decoded) < 3) {
         return false;
     }
     $final = end($this->decoded);
     if (!$final || !$final->isPush()) {
         return false;
     }
     $script = new Script($final->getData());
     $decoded = $script->getScriptParser()->decode();
     $count = count($decoded);
     $mOp = $decoded[0];
     $nOp = $decoded[$count - 2];
     if ($mOp->isPush() || $nOp->isPush()) {
         return false;
     }
     if ($mOp->getOp() < Opcodes::OP_0 || $nOp->getOp() > Opcodes::OP_16) {
         return false;
     }
     /** @var Operation[] $keys */
     $keys = array_slice($decoded, 1, -2);
     $keysValid = true;
     foreach ($keys as $key) {
         $keysValid &= $key->isPush() && PublicKey::isCompressedOrUncompressed($key->getData());
     }
     return $keysValid;
 }
 /**
  * @return bool
  */
 public function isMultisig()
 {
     if (count($this->evalScript) < 3) {
         return false;
     }
     $final = end($this->evalScript);
     if (!$final || !$final instanceof Buffer) {
         return false;
     }
     $script = new Script($final);
     $parsed = $script->getScriptParser()->parse();
     $count = count($parsed);
     $opCodes = $script->getOpCodes();
     $mOp = $parsed[0];
     $nOp = $parsed[$count - 2];
     $keys = array_slice($parsed, 1, -2);
     $keysValid = true;
     foreach ($keys as $key) {
         $keysValid &= $key instanceof Buffer && PublicKey::isCompressedOrUncompressed($key);
     }
     return $opCodes->cmp($opCodes->getOpByName($mOp), 'OP_0') >= 0 && $opCodes->cmp($opCodes->getOpByName($nOp), 'OP_16') <= 0 && $keysValid;
 }
Example #3
0
 /**
  * @param int|string $m
  * @param \BitWasp\Bitcoin\Key\PublicKeyInterface[] $keys
  */
 public function __construct($m, array $keys)
 {
     parent::__construct();
     $n = count($keys);
     if ($m > $n) {
         throw new \LogicException('Required number of sigs exceeds number of public keys');
     }
     if ($n > 16) {
         throw new \LogicException('Number of public keys is greater than 16');
     }
     $ops = $this->getOpCodes();
     $opM = $ops->getOp($ops->getOpByName('OP_1') - 1 + $m);
     $opN = $ops->getOp($ops->getOpByName('OP_1') - 1 + $n);
     $this->op($opM);
     foreach ($keys as $key) {
         if (!$key instanceof PublicKeyInterface) {
             throw new \LogicException('Values in $keys[] must be a PublicKey');
         }
         $this->keys[] = $key;
         $this->push($key->getBuffer());
     }
     $this->op($opN)->op('OP_CHECKMULTISIG');
     $this->m = $m;
 }
Example #4
0
 /**
  * P2shScript constructor.
  * @param ScriptInterface $script
  * @param Opcodes|null $opcodes
  */
 public function __construct(ScriptInterface $script, Opcodes $opcodes = null)
 {
     parent::__construct($script->getBuffer(), $opcodes);
     $this->outputScript = ScriptFactory::scriptPubKey()->payToScriptHash($script);
 }
Example #5
0
 /**
  * @param ScriptInterface $scriptSig
  * @param ScriptWitnessInterface $scriptWitness
  * @param int $flags
  * @return int
  */
 public function countWitnessSigOps(ScriptInterface $scriptSig, ScriptWitnessInterface $scriptWitness, $flags)
 {
     if ($flags & InterpreterInterface::VERIFY_WITNESS === 0) {
         return 0;
     }
     $program = null;
     if ($this->isWitness($program)) {
         /** @var WitnessProgram $program */
         return $this->witnessSigOps($program, $scriptWitness);
     }
     if ((new OutputClassifier($this))->isPayToScriptHash()) {
         $parsed = $scriptSig->getScriptParser()->decode();
         $subscript = new Script(end($parsed)->getData());
         if ($subscript->isWitness($program)) {
             /** @var WitnessProgram $program */
             return $this->witnessSigOps($program, $scriptWitness);
         }
     }
     return 0;
 }
Example #6
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;
 }