コード例 #1
0
 /**
  * @param TransactionInterface $tx
  * @param int $inputToExtract
  * @return $this
  */
 public function extractSigs(TransactionInterface $tx, $inputToExtract)
 {
     $parsed = $tx->getInput($inputToExtract)->getScript()->getScriptParser()->decode();
     $size = count($parsed);
     switch ($this->getScriptType()) {
         case OutputClassifier::PAYTOPUBKEYHASH:
             // Supply signature and public key in scriptSig
             if ($size === 2) {
                 $this->signatures = [TransactionSignatureFactory::fromHex($parsed[0]->getData(), $this->ecAdapter)];
                 $this->publicKeys = [PublicKeyFactory::fromHex($parsed[1]->getData(), $this->ecAdapter)];
             }
             break;
         case OutputClassifier::PAYTOPUBKEY:
             // Only has a signature in the scriptSig
             if ($size === 1) {
                 $this->signatures = [TransactionSignatureFactory::fromHex($parsed[0]->getData(), $this->ecAdapter)];
             }
             break;
         case OutputClassifier::MULTISIG:
             $redeemScript = $this->getRedeemScript();
             $this->signatures = array_fill(0, count($this->publicKeys), null);
             if ($size > 2 && $size <= $this->scriptInfo->getKeyCount() + 2) {
                 $sigHash = $tx->getSignatureHash();
                 $sigSort = new SignatureSort($this->ecAdapter);
                 $sigs = new \SplObjectStorage();
                 foreach (array_slice($parsed, 1, -1) as $item) {
                     /** @var \BitWasp\Bitcoin\Script\Parser\Operation $item */
                     if ($item->isPush()) {
                         $txSig = TransactionSignatureFactory::fromHex($item->getData(), $this->ecAdapter);
                         $hash = $sigHash->calculate($redeemScript, $inputToExtract, $txSig->getHashType());
                         $linked = $sigSort->link([$txSig->getSignature()], $this->publicKeys, $hash);
                         foreach ($this->publicKeys as $key) {
                             if ($linked->contains($key)) {
                                 $sigs[$key] = $txSig;
                             }
                         }
                     }
                 }
                 // We have all the signatures from the input now. array_shift the sigs for a public key, as it's encountered.
                 foreach ($this->publicKeys as $idx => $key) {
                     $this->signatures[$idx] = isset($sigs[$key]) ? $sigs[$key] : null;
                 }
             }
             break;
     }
     return $this;
 }
コード例 #2
0
ファイル: Checker.php プロジェクト: nmarley/bitcoin-php
 /**
  * @param ScriptInterface $script
  * @param BufferInterface $sigBuf
  * @param BufferInterface $keyBuf
  * @param int $sigVersion
  * @param int $flags
  * @return bool
  * @throws ScriptRuntimeException
  */
 public function checkSig(ScriptInterface $script, BufferInterface $sigBuf, BufferInterface $keyBuf, $sigVersion, $flags)
 {
     $this->checkSignatureEncoding($sigBuf, $flags)->checkPublicKeyEncoding($keyBuf, $flags);
     try {
         $txSignature = TransactionSignatureFactory::fromHex($sigBuf->getHex());
         $publicKey = PublicKeyFactory::fromHex($keyBuf->getHex());
         if ($sigVersion === 1) {
             $hasher = new V1Hasher($this->transaction, $this->amount);
         } else {
             $hasher = new Hasher($this->transaction);
         }
         $hash = $hasher->calculate($script, $this->nInput, $txSignature->getHashType());
         return $this->adapter->verify($hash, $publicKey, $txSignature->getSignature());
     } catch (\Exception $e) {
         return false;
     }
 }
コード例 #3
0
ファイル: Interpreter.php プロジェクト: sbwdlihao/bitcoin-php
 /**
  * @param ScriptInterface $script
  * @param Buffer $sigBuf
  * @param Buffer $keyBuf
  * @return bool
  * @throws ScriptRuntimeException
  * @throws \Exception
  */
 private function checkSig(ScriptInterface $script, Buffer $sigBuf, Buffer $keyBuf)
 {
     $this->checkSignatureEncoding($sigBuf)->checkPublicKeyEncoding($keyBuf);
     try {
         $txSignature = TransactionSignatureFactory::fromHex($sigBuf->getHex());
         $publicKey = PublicKeyFactory::fromHex($keyBuf->getHex());
         return $this->ecAdapter->verify($this->transaction->getSignatureHash()->calculate($script, $this->inputToSign, $txSignature->getHashType()), $publicKey, $txSignature->getSignature());
     } catch (\Exception $e) {
         return false;
     }
 }
コード例 #4
0
 /**
  * @param TransactionInterface $tx
  * @return Transaction
  */
 public function fixTransaction(Peer $sender, TransactionInterface $tx, &$wasMalleated = false)
 {
     $c = count($tx->getInputs());
     $new = new TransactionInputCollection();
     for ($i = 0; $i < $c; $i++) {
         $input = $tx->getInput($i);
         $script = $input->getScript();
         $classify = ScriptFactory::scriptSig()->classify($input->getScript());
         $this->inputs++;
         if ($classify->isPayToPublicKeyHash()) {
             $parsed = $input->getScript()->getScriptParser()->parse();
             $txSig = TransactionSignatureFactory::fromHex($parsed[0]);
             $txSig = $this->fixSig($sender, $txSig, $wasMalleated);
             $script = ScriptFactory::create()->push($txSig->getBuffer())->push($parsed[1])->getScript();
         }
         $new->addInput(new TransactionInput($input->getTransactionId(), $input->getVout(), $script, $input->getSequence()));
     }
     return new Transaction($tx->getVersion(), $new, $tx->getOutputs(), $tx->getLockTime());
 }
コード例 #5
0
ファイル: InputSigner.php プロジェクト: nmarley/bitcoin-php
 /**
  * @return $this
  */
 public function extractSignatures()
 {
     $type = (new OutputClassifier($this->txOut->getScript()))->classify();
     $scriptPubKey = $this->txOut->getScript();
     $scriptSig = $this->tx->getInput($this->nInput)->getScript();
     if ($type === OutputClassifier::PAYTOPUBKEYHASH || $type === OutputClassifier::PAYTOPUBKEY || $type === OutputClassifier::MULTISIG) {
         $values = [];
         foreach ($scriptSig->getScriptParser()->decode() as $o) {
             $values[] = $o->getData();
         }
         $this->extractFromValues($type, $scriptPubKey, $values, 0);
     }
     if ($type === OutputClassifier::PAYTOSCRIPTHASH) {
         $decodeSig = $scriptSig->getScriptParser()->decode();
         if (count($decodeSig) > 0) {
             $redeemScript = new Script(end($decodeSig)->getData());
             $p2shType = (new OutputClassifier($redeemScript))->classify();
             if (count($decodeSig) > 1) {
                 $decodeSig = array_slice($decodeSig, 0, -1);
             }
             $internalSig = [];
             foreach ($decodeSig as $operation) {
                 $internalSig[] = $operation->getData();
             }
             $this->redeemScript = $redeemScript;
             $this->extractFromValues($p2shType, $redeemScript, $internalSig, 0);
             $type = $p2shType;
         }
     }
     $witnesses = $this->tx->getWitnesses();
     if ($type === OutputClassifier::WITNESS_V0_KEYHASH) {
         $this->requiredSigs = 1;
         if (isset($witnesses[$this->nInput])) {
             $witness = $witnesses[$this->nInput];
             $this->signatures = [TransactionSignatureFactory::fromHex($witness[0], $this->ecAdapter)];
             $this->publicKeys = [PublicKeyFactory::fromHex($witness[1], $this->ecAdapter)];
         }
     } else {
         if ($type === OutputClassifier::WITNESS_V0_SCRIPTHASH) {
             if (isset($witnesses[$this->nInput])) {
                 $witness = $witnesses[$this->nInput];
                 $witCount = count($witnesses[$this->nInput]);
                 if ($witCount > 0) {
                     $witnessScript = new Script($witness[$witCount - 1]);
                     $vWitness = $witness->all();
                     if (count($vWitness) > 1) {
                         $vWitness = array_slice($witness->all(), 0, -1);
                     }
                     $witnessType = (new OutputClassifier($witnessScript))->classify();
                     $this->extractFromValues($witnessType, $witnessScript, $vWitness, 1);
                     $this->witnessScript = $witnessScript;
                 }
             }
         }
     }
     return $this;
 }
コード例 #6
0
 /**
  * @param TransactionInterface $tx
  * @param $inputToExtract
  * @return $this
  */
 public function extractSigs(TransactionInterface $tx, $inputToExtract)
 {
     $inputs = $tx->getInputs();
     $parsed = $inputs[$inputToExtract]->getScript()->getScriptParser()->decode();
     $size = count($parsed);
     switch ($this->getScriptType()) {
         case OutputClassifier::PAYTOPUBKEYHASH:
             // Supply signature and public key in scriptSig
             if ($size === 2) {
                 $this->signatures = [TransactionSignatureFactory::fromHex($parsed[0]->getData(), $this->ecAdapter)];
                 $this->publicKeys = [PublicKeyFactory::fromHex($parsed[1]->getData(), $this->ecAdapter)];
             }
             break;
         case OutputClassifier::PAYTOPUBKEY:
             // Only has a signature in the scriptSig
             if ($size === 1) {
                 $this->signatures = [TransactionSignatureFactory::fromHex($parsed[0]->getData(), $this->ecAdapter)];
             }
             break;
         case OutputClassifier::MULTISIG:
             $redeemScript = $this->getRedeemScript();
             $keys = $this->scriptInfo->getKeys();
             foreach ($keys as $idx => $key) {
                 $this->setSignature($idx, null);
             }
             if ($size > 2 && $size <= $this->scriptInfo->getKeyCount() + 2) {
                 $sigs = [];
                 foreach ($keys as $key) {
                     $sigs[$key->getPubKeyHash()->getHex()] = [];
                 }
                 // Extract Signatures (as buffers), then compile arrays of [pubkeyHash => signature]
                 $sigHash = new Hasher($tx);
                 foreach (array_slice($parsed, 1, -1) as $item) {
                     /** @var \BitWasp\Bitcoin\Script\Parser\Operation $item */
                     if ($item->isPush()) {
                         $txSig = TransactionSignatureFactory::fromHex($item->getData(), $this->ecAdapter);
                         $linked = $this->ecAdapter->associateSigs([$txSig->getSignature()], $sigHash->calculate($redeemScript, $inputToExtract, $txSig->getHashType()), $keys);
                         if (count($linked)) {
                             $key = array_keys($linked)[0];
                             $sigs[$key] = array_merge($sigs[$key], [$txSig]);
                         }
                     }
                 }
                 // We have all the signatures from the tx now. array_shift the sigs for a public key, as it's encountered.
                 foreach ($keys as $idx => $key) {
                     $hash = $key->getPubKeyHash()->getHex();
                     $this->setSignature($idx, isset($sigs[$hash]) ? array_shift($sigs[$hash]) : null);
                 }
             }
             break;
     }
     return $this;
 }