use BitWasp\Bitcoin\Key\PrivateKeyFactory; use BitWasp\Bitcoin\Key\PublicKeyFactory; use BitWasp\Bitcoin\Address\AddressFactory; use BitWasp\Bitcoin\Rpc\RpcFactory; $network = Bitcoin::getNetwork(); $host = '127.0.0.1'; $port = '18332'; $user = getenv('BITCOINLIB_RPC_USER') ?: 'bitcoinrpc'; $pass = getenv('BITCOINLIB_RPC_PASSWORD') ?: 'BBpsLqmCCx7Vp8sRd5ygDxFkHZBgWLTTi55QwWgN6Ng6'; Bitcoin::setNetwork(\BitWasp\Bitcoin\Network\NetworkFactory::bitcoinTestnet()); $network = Bitcoin::getNetwork(); $ecAdapter = Bitcoin::getEcAdapter(); $bitcoind = RpcFactory::bitcoind($host, $port, $user, $pass); $privateKey1 = PrivateKeyFactory::fromHex('17a2209250b59f07a25b560aa09cb395a183eb260797c0396b82904f918518d5', true); $privateKey2 = PrivateKeyFactory::fromHex('17a2209250b59f07a25b560aa09cb395a183eb260797c0396b82904f918518d6', true); $redeemScript = ScriptFactory::multisig(2, array($privateKey1->getPublicKey(), $privateKey2->getPublicKey())); $multisig = $redeemScript->getAddress(); echo "[P2SH address: " . $multisig->getAddress($network) . " ]\n"; echo "[private key order: " . implode(", ", array_map(function (PublicKeyInterface $publicKey) use($privateKey1, $privateKey2) { if ($publicKey->getBinary() == $privateKey1->getPublicKey()->getBinary()) { return "1"; } else { return "2"; } }, $redeemScript->getKeys())) . "]\n"; $myTx = $bitcoind->getrawtransaction('6d4f5d2cce43660c29e03a794497da3f204312358ca6a6e47035ef916ce19db9', true); $spendOutput = 0; $recipient = AddressFactory::fromString('n1b2a9rFvuU9wBgBaoWngNvvMxRV94ke3x'); echo "[Send to: " . $recipient->getAddress($network) . " \n"; // Prep work - importing from a tx will only bring container to contents of $new - no metadata $new = new \BitWasp\Bitcoin\Transaction\TransactionBuilder($ecAdapter);
/** * Returns the redeemScript. Note - keys are already sorted in the constructor, so this is not required in ScriptFactory. * * @return \BitWasp\Bitcoin\Script\RedeemScript */ public function getRedeemScript() { return ScriptFactory::multisig($this->m, array_map(function (HierarchicalKey $key) { return $key->getPublicKey(); }, $this->keys)); }
/** * @param Buffer $secret * @param PublicKeyInterface $a1 * @param PublicKeyInterface $a2 * @param PublicKeyInterface $b1 * @param PublicKeyInterface $b2 * @return Script */ 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::multisig(2, [$a1, $b1]))->op('OP_ELSE')->concat(ScriptFactory::multisig(2, [$a2, $b2]))->op('OP_ENDIF'); }
<?php require "../vendor/autoload.php"; use BitWasp\Bitcoin\Bitcoin; use BitWasp\Bitcoin\Key\PrivateKeyFactory; use BitWasp\Bitcoin\Script\ScriptFactory; use BitWasp\Bitcoin\Transaction\Transaction; use BitWasp\Bitcoin\Transaction\TransactionInput; use BitWasp\Bitcoin\Transaction\TransactionOutput; use BitWasp\Bitcoin\Transaction\TransactionBuilder; use BitWasp\Bitcoin\Transaction\TransactionFactory; $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::multisig(2, [$pk1->getPublicKey(), $pk2->getPublicKey()]); $outputScript = $redeemScript->getOutputScript(); // The address is funded with a transaction (fake, for the purposes of this script). // You would do getrawtransaction normally $spendTx = new Transaction(); $spendTx->getInputs()->addInput(new TransactionInput('4141414141414141414141414141414141414141414141414141414141414141', 0)); $spendTx->getOutputs()->addOutput(new TransactionOutput(50, $outputScript)); // One party wants to spend funds. He creates a transaction spending the funding tx to his address. $builder = new TransactionBuilder($ecAdapter); $builder->spendOutput($spendTx, 0)->payToAddress($pk1->getAddress(), 50)->signInputWithKey($pk1, $outputScript, 0, $redeemScript)->signInputWithKey($pk2, $outputScript, 0, $redeemScript); $rawTx = $builder->getTransaction()->getHex(); echo "Fully signed transaction: " . $builder->getTransaction()->getHex() . "\n";