/** * @param UtxoView $utxoView * @param TransactionInterface $tx * @return ScriptValidationInterface */ public function queue(UtxoView $utxoView, TransactionInterface $tx) { for ($i = 0, $c = count($tx->getInputs()); $i < $c; $i++) { $output = $utxoView->fetchByInput($tx->getInput($i))->getOutput(); $witness = isset($tx->getWitnesses()[$i]) ? $tx->getWitness($i) : null; $this->results[] = $this->consensus->verify($tx, $output->getScript(), $i, $output->getValue(), $witness); } return $this; }
/** * @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; }
/** * @param TransactionInterface $transaction * @return BufferInterface */ public function serialize(TransactionInterface $transaction) { $math = Bitcoin::getMath(); $int8le = new Int8($math, ByteOrder::LE); $int32le = new Int32($math, ByteOrder::LE); $uint32le = new Uint32($math, ByteOrder::LE); $varint = new VarInt($math, ByteOrder::LE); $vector = new Vector($varint, function () { }); $binary = $int32le->write($transaction->getVersion()); $flags = 0; if (!$transaction->getWitnesses()->isNull()) { $flags |= 1; } if ($flags) { $binary .= $int8le->write(0); $binary .= $int8le->write($flags); } $binary .= $vector->write($transaction->getInputs()->all()); $binary .= $vector->write($transaction->getOutputs()->all()); if ($flags & 1) { foreach ($transaction->getWitnesses() as $witness) { $binary .= $witness->getBuffer()->getBinary(); } } $binary .= $uint32le->write($transaction->getLockTime()); return new Buffer($binary); }
/** * @param ConsensusInterface $consensus * @param int $nInput * @param TransactionOutputInterface $output * @return bool */ public function checkSignature(ConsensusInterface $consensus, $nInput, TransactionOutputInterface $output) { $witnesses = $this->transaction->getWitnesses(); $witness = isset($witnesses[$nInput]) ? $witnesses[$nInput] : null; return $consensus->verify($this->transaction, $output->getScript(), $nInput, $output->getValue(), $witness); }
/** * @param array $array * @return $this */ private function replace(array $array = []) { $this->transaction = new Transaction(array_key_exists('version', $array) ? $array['version'] : $this->transaction->getVersion(), array_key_exists('inputs', $array) ? $array['inputs'] : $this->transaction->getInputs(), array_key_exists('outputs', $array) ? $array['outputs'] : $this->transaction->getOutputs(), array_key_exists('witness', $array) ? $array['witness'] : $this->transaction->getWitnesses(), array_key_exists('nLockTime', $array) ? $array['nLockTime'] : $this->transaction->getLockTime()); return $this; }