/** * @param TransactionInterface $tx * @param integer $inputToExtract * @throws \Exception */ public function extractSigs(TransactionInterface $tx, $inputToExtract) { $parsed = $tx->getInputs()->getInput($inputToExtract)->getScript()->getScriptParser()->parse(); $size = count($parsed); switch ($this->getScriptType()) { case OutputClassifier::PAYTOPUBKEYHASH: // Supply signature and public key in scriptSig if ($size == 2) { $this->setSignatures([TransactionSignatureFactory::fromHex($parsed[0]->getHex(), $this->ecAdapter->getMath())]); $this->setPublicKeys([PublicKeyFactory::fromHex($parsed[1]->getHex(), $this->ecAdapter)]); } break; case OutputClassifier::PAYTOPUBKEY: // Only has a signature in the scriptSig if ($size == 1) { $this->setSignatures([TransactionSignatureFactory::fromHex($parsed[0]->getHex(), $this->ecAdapter->getMath())]); } break; case OutputClassifier::MULTISIG: $keys = $this->getRedeemScript()->getKeys(); foreach ($keys as $idx => $key) { $this->setSignature($idx, null); } if ($size > 2 && $size <= $this->getRedeemScript()->getKeyCount() + 2) { $sigs = []; foreach ($keys as $key) { $sigs[$key->getPubKeyHash()->getHex()] = []; } // Extract Signatures (as buffers), then compile arrays of [pubkeyHash => signature] $sigHash = new SignatureHash($tx); foreach (array_slice($parsed, 1, -1) as $item) { if ($item instanceof Buffer) { $txSig = TransactionSignatureFactory::fromHex($item, $this->ecAdapter->getMath()); $linked = $this->ecAdapter->associateSigs([$txSig->getSignature()], $sigHash->calculate($this->getRedeemScript(), $inputToExtract, $txSig->getHashType()), $this->getRedeemScript()->getKeys()); 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; } }