public function createSampleTXO($payment_address = null, $overrides = []) { if ($payment_address === null) { $payment_address = app('PaymentAddressHelper')->createSamplePaymentAddress(); } $account = AccountHandler::getAccount($payment_address, 'default'); // build a real script $script = ScriptFactory::scriptPubKey()->payToAddress(AddressFactory::fromString($payment_address['address'])); $attributes = array_merge(['txid' => $this->nextTXID(), 'n' => 0, 'script' => $script->getBuffer()->getHex(), 'amount' => 54321, 'type' => TXO::CONFIRMED, 'spent' => false, 'green' => false], $overrides); $txo_model = $this->txo_repository->create($payment_address, $account, $attributes); return $txo_model; }
/** * @param UtxoView $view * @param TransactionInterface $tx * @return int */ public function getP2shSigOps(UtxoView $view, TransactionInterface $tx) { if ($tx->isCoinbase()) { return 0; } $nSigOps = 0; $scriptPubKey = ScriptFactory::scriptPubKey(); for ($i = 0, $c = count($tx->getInputs()); $i < $c; $i++) { $input = $tx->getInput($i); $outputScript = $view->fetchByInput($input)->getOutput()->getScript(); if ($scriptPubKey->classify($outputScript)->isPayToScriptHash()) { $nSigOps += $outputScript->countP2shSigOps($input->getScript()); } } return $nSigOps; }
/** * @param ScriptInterface $script * @param ScriptInterface|null $redeemScript * @return \BitWasp\Bitcoin\Script\ScriptInfo\ScriptInfoInterface */ public function load(ScriptInterface $script, ScriptInterface $redeemScript = null) { $classifier = ScriptFactory::scriptPubKey()->classify($script); if ($classifier->isPayToScriptHash()) { if (null === $redeemScript) { throw new \InvalidArgumentException('Redeem script is required when output is P2SH'); } $handler = new ScriptHash($redeemScript); } elseif ($classifier->isMultisig()) { $handler = new Multisig($script); } elseif ($classifier->isPayToPublicKey()) { $handler = new PayToPubkey($script); } elseif ($classifier->isPayToPublicKeyHash()) { $handler = new PayToPubkeyHash($script); } else { throw new \InvalidArgumentException('Unparsable script type'); } return $handler; }
/** * @param ScriptInterface $redeemScript */ public function __construct(ScriptInterface $redeemScript) { $classifier = ScriptFactory::scriptPubKey()->classify($redeemScript); if ($classifier->isPayToScriptHash()) { throw new \InvalidArgumentException('Provided script is a pay-to-script-hash output script'); } switch ($classifier->classify()) { case OutputClassifier::MULTISIG: $handler = new Multisig($redeemScript); break; case OutputClassifier::PAYTOPUBKEY: $handler = new PayToPubkey($redeemScript); break; case OutputClassifier::PAYTOPUBKEYHASH: $handler = new PayToPubkeyHash($redeemScript); break; default: throw new \InvalidArgumentException('redeemScript not yet supported'); } $this->redeemScript = $redeemScript; $this->outputScript = ScriptFactory::scriptPubKey()->payToScriptHash($redeemScript); $this->p2shAddress = AddressFactory::fromScript($redeemScript); $this->handler = $handler; }
/** * Create an output paying $value to an Address. * * @param AddressInterface $address * @param $value * @return $this */ public function payToAddress(AddressInterface $address, $value) { // Create Script from address, then create an output. $this->addOutput(new TransactionOutput($value, ScriptFactory::scriptPubKey()->payToAddress($address))); return $this; }
$bitcoinUrl = "bitcoin:" . $requirements[0]->address . "?amount=" . $request->valuebtc . "&r=" . $url; //$bitcoinUrl = "bitcoin:?r=" . $url; //echo $bitcoinUrl . "\n"; return $app['twig']->render('info.html.twig', ['request' => $request->to_array(), 'requirements' => $reqs, 'address' => $reqs[0]['address'], 'url' => $url, 'bitcoinUrl' => $bitcoinUrl]); })->bind('info'); $app->match('/new', function (\Symfony\Component\HttpFoundation\Request $request) use($app) { // some default data for when the form is displayed the first time /** @var \Symfony\Component\Form\FormFactory $factory */ $factory = $app['form.factory']; $form = $factory->createBuilder()->add('address', 'text', array('attr' => array('class' => 'form-control', 'placeholder' => 'Bitcoin address'), 'constraints' => [new \Symfony\Component\Validator\Constraints\NotBlank(), new \BitWasp\Payments\Application\Validator\BitcoinAddress()]))->add('value', 'text', array('attr' => array('class' => 'form-control', 'placeholder' => 'Amount in satoshis'), 'constraints' => new \Symfony\Component\Validator\Constraints\NotBlank()))->add('send', 'submit', array('attr' => array('class' => 'btn btn-lg btn-primary btn-block')))->getForm(); if ('POST' == $request->getMethod()) { $form->bind($request); if ($form->isValid()) { $data = $form->getData(); $address = \BitWasp\Bitcoin\Address\AddressFactory::fromString($data['address']); $script = \BitWasp\Bitcoin\Script\ScriptFactory::scriptPubKey()->payToAddress($address); $txOut = new \BitWasp\Bitcoin\Transaction\TransactionOutput($data['value'], $script); $slug = bin2hex(openssl_random_pseudo_bytes(32)); $signer = new \BitWasp\Bitcoin\PaymentProtocol\PaymentRequestSigner('none'); $builder = new \BitWasp\Bitcoin\PaymentProtocol\PaymentRequestBuilder($signer, 'main', time()); $builder->addOutput($txOut); $details = $builder->getPaymentDetails(); $details->setPaymentUrl($app->url('request.payment', ['slug' => $slug])); $request = $builder->getPaymentRequest(); $totalValue = $data['value']; $amount = new \BitWasp\Bitcoin\Amount(); $dbRequest = \BitWasp\Payments\Db\Request::create(['slug' => $slug, 'value' => $totalValue, 'valueBtc' => $amount->toBtc($data['value']), 'payment_request' => $request->serialize()]); $output = \BitWasp\Payments\Db\OutputRequirement::create(['request_id' => $dbRequest->id, 'value' => $data['value'], 'valueBtc' => $amount->toBtc($data['value']), 'address' => $data['address'], 'script' => $txOut->getScript()->getBinary()]); $app['request_api']->pushRequest($slug, [$output]); return $app->redirect($app['url_generator']->generate('info', array('slug' => $dbRequest->slug))); }
<?php require "../vendor/autoload.php"; use BitWasp\Buffertools\Buffer; use BitWasp\Bitcoin\Key\PrivateKeyFactory; use BitWasp\Bitcoin\Script\ScriptFactory; use BitWasp\Bitcoin\Transaction\OutPoint; use BitWasp\Bitcoin\Transaction\TransactionFactory; use BitWasp\Bitcoin\Script\WitnessProgram; use BitWasp\Bitcoin\Bitcoin; $wif = 'QP3p9tRpTGTefG4a8jKoktSWC7Um8qzvt8wGKMxwWyW3KTNxMxN7'; $s = \BitWasp\Bitcoin\Network\NetworkFactory::bitcoinSegnet(); Bitcoin::setNetwork($s); $ec = \BitWasp\Bitcoin\Bitcoin::getEcAdapter(); $key = PrivateKeyFactory::fromWif($wif); echo $key->getPublicKey()->getAddress()->getAddress() . PHP_EOL; $outpoint = new OutPoint(Buffer::hex('703f50920bff10e1622117af81b622d8bbd625460e61909cc3f8b8ee78a59c0d', 32), 0); $scriptPubKey = ScriptFactory::scriptPubKey()->payToPubKeyHash($key->getPublicKey()); $value = 100000000; $txOut = new \BitWasp\Bitcoin\Transaction\TransactionOutput($value, $scriptPubKey); $destination = new WitnessProgram(0, $key->getPubKeyHash()); $p2sh = new \BitWasp\Bitcoin\Script\P2shScript($destination->getScript()); $tx = TransactionFactory::build()->spendOutPoint($outpoint)->output(95590000, $p2sh->getOutputScript())->get(); $signed = new \BitWasp\Bitcoin\Transaction\Factory\Signer($tx, $ec); $signed->sign(0, $key, $txOut); $ss = $signed->get(); echo $ss->getHex() . PHP_EOL;
/** * @param AddressInterface $address * @param $value * @return PaymentRequestBuilder */ public function addAddressPayment(AddressInterface $address, $value) { $script = ScriptFactory::scriptPubKey()->payToAddress($address); $output = new TransactionOutput($value, $script); return $this->addOutput($output); }
<?php require "../vendor/autoload.php"; use BitWasp\Bitcoin\Bitcoin; use BitWasp\Bitcoin\Key\PrivateKeyFactory; use BitWasp\Bitcoin\Script\ScriptFactory; use BitWasp\Bitcoin\Transaction\Factory\TxSigner; use BitWasp\Bitcoin\Transaction\Factory\TxBuilder; $ecAdapter = Bitcoin::getEcAdapter(); // Two users independently create private keys. $pk1 = PrivateKeyFactory::fromHex('421c76d77563afa1914846b010bd164f395bd34c2102e5e99e0cb9cf173c1d87'); $pk2 = PrivateKeyFactory::fromHex('f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162'); // They exchange public keys, and a multisignature address is made. $redeemScript = ScriptFactory::scriptPubKey()->multisig(2, [$pk1->getPublicKey(), $pk2->getPublicKey()]); $os = ScriptFactory::scriptPubKey()->payToScriptHash($redeemScript); // The address is funded with a transaction (fake, for the purposes of this script). // You would do getrawtransaction normall $fundTx = (new TxBuilder())->input('4141414141414141414141414141414141414141414141414141414141414141', 0)->output(50, $os)->get(); // One party wants to spend funds. He creates a transaction spending the funding tx to his address. $spendTx = (new TxBuilder())->spendOutputFrom($fundTx, 0)->payToAddress(50, $pk1->getAddress())->get(); // Two parties sign the transaction (can be done in steps) $signer = new TxSigner($ecAdapter, $spendTx); $signer->sign(0, $pk1, $os, $redeemScript)->sign(0, $pk2, $os, $redeemScript); $rawTx = $signer->get()->getHex(); echo "Fully signed transaction: " . $signer->get()->getHex() . "\n";
/** * Returns the redeemScript. Note - keys are already sorted in the constructor, so this is not required in ScriptFactory. * * @return \BitWasp\Bitcoin\Script\ScriptInterface */ public function getRedeemScript() { return ScriptFactory::scriptPubKey()->multisig($this->m, array_map(function (HierarchicalKey $key) { return $key->getPublicKey(); }, $this->keys)); }
/** * @param TransactionInterface $tx * @return bool */ public function isRelevantAndUpdate(TransactionInterface $tx) { $this->updateEmptyFull(); $found = false; if ($this->isFull()) { return true; } if ($this->isEmpty()) { return false; } // Check if the txid hash is in the filter $txHash = $tx->getTxId(); if ($this->containsData($txHash)) { $found = true; } // Check for relevant output scripts. We add the outpoint to the filter if found. foreach ($tx->getOutputs() as $vout => $output) { $script = $output->getScript(); $parser = $script->getScriptParser(); foreach ($parser as $exec) { if ($exec->isPush() && $this->containsData($exec->getData())) { $found = true; if ($this->isUpdateAll()) { $this->insertOutPoint($tx->makeOutPoint($vout)); } else { if ($this->isUpdatePubKeyOnly()) { $type = ScriptFactory::scriptPubKey()->classify($script); if ($type->isMultisig() || $type->isPayToPublicKey()) { $this->insertOutPoint($tx->makeOutPoint($vout)); } } } } } } if ($found) { return true; } foreach ($tx->getInputs() as $txIn) { if ($this->containsOutPoint($txIn->getOutPoint())) { return true; } $parser = $txIn->getScript()->getScriptParser(); foreach ($parser as $exec) { if ($exec->isPush() > 0 && $this->containsData($exec->getData())) { return true; } } } return false; }
<?php use BitWasp\Bitcoin\Bitcoin; use BitWasp\Bitcoin\Network\NetworkFactory; use BitWasp\Bitcoin\Script\ScriptFactory; use BitWasp\Bitcoin\Key\PrivateKeyFactory; use BitWasp\Bitcoin\Rpc\RpcFactory; use BitWasp\Bitcoin\Miner\Miner; require __DIR__ . "/../vendor/autoload.php"; // init network (TESTNET) Bitcoin::setNetwork(NetworkFactory::bitcoinTestnet()); // generate a privatekey so we can received the BTC $privKey = PrivateKeyFactory::create(true); var_dump($privKey->toWif()); // get latest block from RPC $rpc = RpcFactory::bitcoind(getenv('BITCOINLIB_RPC_HOST') ?: 'localhost', "18332", getenv('BITCOINLIB_RPC_USER') ?: 'bitcoin', getenv('BITCOINLIB_RPC_PASSWORD') ?: 'YOUR_PASSWORD'); $latest = $rpc->getblock($rpc->getbestblockhash()); // mining in the future \o/ $timestamp = time() + 3600 * 2; // create script to pay ourselves $script = ScriptFactory::scriptPubKey()->payToPubKey($privKey->getPublicKey()); // init miner $miner = new Miner(Bitcoin::getMath(), $latest->getHeader(), $script, null, $timestamp, 2, true); // let's GO! var_dump("mining!"); $block = $miner->run(); // result var_dump($block->getHeader()->getBlockHash()); echo $block->getBuffer();
/** * @param ScriptInterface $scriptSig * @return int */ public function countP2shSigOps(ScriptInterface $scriptSig) { if (!ScriptFactory::scriptPubKey()->classify($this)->isPayToScriptHash()) { return $this->countSigOps(true); } $parser = $scriptSig->getScriptParser(); $data = null; foreach ($parser as $exec) { if ($exec->getOp() > Opcodes::OP_16) { return 0; } if ($exec->isPush()) { $data = $exec->getData(); } } if (!$data instanceof BufferInterface) { return 0; } return (new Script($data))->countSigOps(true); }
/** * @return Script */ public function getOutputScript() { return ScriptFactory::scriptPubKey()->payToScriptHash($this); }
/** * @param AddressInterface $address * @param NetworkInterface $network * @return \React\Promise\Promise */ public function addressListUnspent(AddressInterface $address, NetworkInterface $network = null) { return $this->client->request('blockchain.address.listunspent', [$address->getAddress($network)])->then(function (Response $response) use($address) { return array_map(function (array $value) use($address) { return new Utxo($value['tx_hash'], $value['tx_pos'], new TransactionOutput($value['value'], ScriptFactory::scriptPubKey()->payToAddress($address))); }, $response->getResult()); }); }
/** * @param Buffer $secret * @param PublicKeyInterface $a1 * @param PublicKeyInterface $a2 * @param PublicKeyInterface $b1 * @param PublicKeyInterface $b2 * @return ScriptInterface */ public function payToLightningChannel(Buffer $secret, PublicKeyInterface $a1, PublicKeyInterface $a2, PublicKeyInterface $b1, PublicKeyInterface $b2) { return ScriptFactory::create()->op('OP_DEPTH')->op('OP_3')->op('OP_EQUAL')->op('OP_IF')->op('OP_HASH160')->push(Hash::sha256ripe160($secret))->op('OP_EQUALVERIFY')->concat(ScriptFactory::scriptPubKey()->multisig(2, [$a1, $b1]))->op('OP_ELSE')->concat(ScriptFactory::scriptPubKey()->multisig(2, [$a2, $b2]))->op('OP_ENDIF')->getScript(); }
/** * 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); }
<?php require "../vendor/autoload.php"; use BitWasp\Buffertools\Buffer; use BitWasp\Bitcoin\Crypto\Hash; use BitWasp\Bitcoin\Key\PrivateKeyFactory; use BitWasp\Bitcoin\Transaction\TransactionFactory; use BitWasp\Bitcoin\Script\ScriptFactory; $ent = Hash::sha256(new Buffer('abc')); $priv = PrivateKeyFactory::fromHex($ent); $publicKey = $priv->getPublicKey(); $outputScript = ScriptFactory::scriptPubKey()->payToPubKeyHash($publicKey); $tx = TransactionFactory::build()->input('10001234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234', 0)->payToAddress(50, $publicKey->getAddress())->get(); $signed = TransactionFactory::sign($tx)->sign(0, $priv, $outputScript)->get(); echo $signed->getHex(); $consensus = ScriptFactory::consensus(); $validator = $signed->validator(); var_dump($validator->checkSignatures($consensus, [$outputScript]));