/**
  * @param Parser $parser
  * @return PrivateKey
  */
 public function fromParser(Parser &$parser)
 {
     $bytes = $parser->readBytes(32);
     $multiplier = $bytes->getInt();
     $privateKey = PrivateKeyFactory::fromInt($multiplier, false, $this->ecAdapter);
     return $privateKey;
 }
 /**
  * @param string $hexPrivateKey
  * @param bool $compressed
  * @return PrivateKeyInterface
  * @throws BlockCypherInvalidPrivateKeyException
  */
 public static function importPrivateKeyFromHex($hexPrivateKey, $compressed = true)
 {
     $privateKey = null;
     try {
         $privateKey = PrivateKeyFactory::fromHex($hexPrivateKey, $compressed);
     } catch (\Exception $e) {
         throw new BlockCypherInvalidPrivateKeyException('Invalid private key format, hex expected.' . $e->getMessage());
     }
     return $privateKey;
 }
 /**
  * @param Parser $parser
  * @return HierarchicalKey
  * @throws ParserOutOfRange
  */
 public function fromParser(Parser &$parser)
 {
     try {
         list($bytes, $depth, $parentFingerprint, $sequence, $chainCode, $keyData) = $this->getTemplate()->parse($parser);
         $bytes = $bytes->getHex();
     } catch (ParserOutOfRange $e) {
         throw new ParserOutOfRange('Failed to extract HierarchicalKey from parser');
     }
     if ($bytes !== $this->network->getHDPubByte() && $bytes !== $this->network->getHDPrivByte()) {
         throw new \InvalidArgumentException("HD key magic bytes do not match network magic bytes");
     }
     $key = $this->network->getHDPrivByte() == $bytes ? PrivateKeyFactory::fromHex($keyData->slice(1)->getHex(), true, $this->ecAdapter) : PublicKeyFactory::fromHex($keyData->getHex(), $this->ecAdapter);
     return new HierarchicalKey($this->ecAdapter, $depth, $parentFingerprint, $sequence, $chainCode, $key);
 }
 /**
  * @param string $wif
  * @return PrivateKeyInterface
  * @throws InvalidPrivateKey
  * @throws Base58ChecksumFailure
  */
 public function parse($wif)
 {
     $payload = Base58::decodeCheck($wif)->slice(1);
     $size = $payload->getSize();
     if (33 === $size) {
         $compressed = true;
         $payload = $payload->slice(0, 32);
     } else {
         if (32 === $size) {
             $compressed = false;
         } else {
             throw new InvalidPrivateKey("Private key should be always be 32 or 33 bytes (depending on if it's compressed)");
         }
     }
     return PrivateKeyFactory::fromInt($payload->getInt(), $compressed);
 }
 /**
  * @param Buffer $entropy
  * @param EcAdapterInterface $ecAdapter
  * @return HierarchicalKey
  */
 public static function fromEntropy(Buffer $entropy, EcAdapterInterface $ecAdapter = null)
 {
     $ecAdapter = $ecAdapter ?: Bitcoin::getEcAdapter();
     $hash = Hash::hmac('sha512', $entropy, new Buffer('Bitcoin seed', null, $ecAdapter->getMath()));
     return new HierarchicalKey($ecAdapter, 0, 0, 0, $hash->slice(32, 32)->getInt(), PrivateKeyFactory::fromHex($hash->slice(0, 32)->getHex(), true, $ecAdapter));
 }
use BitWasp\Bitcoin\Script\ScriptFactory;
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
<?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;
 /**
  * Pass a secret exponent (integer)
  * @param integer|string $secret
  * @param EcAdapterInterface $ecAdapter
  * @return ElectrumKey
  */
 public static function fromSecretExponent($secret, EcAdapterInterface $ecAdapter = null)
 {
     $ecAdapter = $ecAdapter ?: Bitcoin::getEcAdapter();
     return new ElectrumKey($ecAdapter, PrivateKeyFactory::fromInt($secret, false, $ecAdapter));
 }
Example #9
0
<?php

use BitWasp\Bitcoin\Bitcoin;
use BitWasp\Bitcoin\Address;
use BitWasp\Bitcoin\Key\PrivateKeyFactory;
use BitWasp\Bitcoin\Network\Network;
require __DIR__ . "/../vendor/autoload.php";
$network = Bitcoin::getNetwork();
$privateKey = PrivateKeyFactory::create(true);
$publicKey = $privateKey->getPublicKey();
echo "Key Info\n";
echo " - Compressed? " . ($privateKey->isCompressed() ? 'yes' : 'no') . "\n";
echo "Private key\n";
echo " - WIF: " . $privateKey->toWif($network) . "\n";
echo " - Hex: " . $privateKey->getBuffer() . "\n";
echo " - Dec: " . $privateKey->getSecretMultiplier() . "\n";
echo "Public Key\n";
echo " - Hex: " . $publicKey->getBuffer() . "\n";
echo " - Hash: " . $publicKey->getPubKeyHash() . "\n";
echo " - Address: " . $publicKey->getAddress() . "\n";
Example #10
0
 /**
  * @param PrivateKeyInterface $oldPrivate
  * @param string $newBinary
  * @return \BitWasp\Bitcoin\Key\PrivateKey
  */
 private function getRelatedPrivateKey(PrivateKeyInterface $oldPrivate, $newBinary)
 {
     return PrivateKeyFactory::fromHex(bin2hex($newBinary), $oldPrivate->isCompressed(), $this);
 }
// https://github.com/Bit-Wasp/bitcoin-php
// Run on console:
// php -f .\sample\transaction-api\CreateTransactionWithThirdPartySoftware.php
use BitWasp\Bitcoin\Address\AddressFactory;
use BitWasp\Bitcoin\Bitcoin;
use BitWasp\Bitcoin\Key\PrivateKeyFactory;
use BitWasp\Bitcoin\Transaction\TransactionBuilder;
use BitWasp\Bitcoin\Transaction\TransactionFactory;
require __DIR__ . '/../bootstrap.php';
$debug = false;
Bitcoin::setNetwork(\BitWasp\Bitcoin\Network\NetworkFactory::bitcoinTestnet());
$network = Bitcoin::getNetwork();
$ecAdapter = Bitcoin::getEcAdapter();
// Import private key
$compressed = true;
$privateKey = PrivateKeyFactory::fromHex('1551558c3b75f46b71ec068f9e341bf35ee6df361f7b805deb487d8a4d5f055e', $compressed);
if ($debug) {
    echo "[Key: " . $privateKey->toWif($network) . "]\n";
    echo "[Address " . $privateKey->getAddress()->getAddress($network) . "]\n";
}
// In order to run the sample you will need:
// 1.- Use the faucet to fund source address
// Faucet https://accounts.blockcypher.com/testnet-faucet?a=n3D2YXwvpoPg8FhcWpzJiS3SvKKGD8AXZ4
// 2.- Get unspent transaction outputs (UTXOs) and select one:
// https://api.blockcypher.com/v1/btc/test3/addrs/n3D2YXwvpoPg8FhcWpzJiS3SvKKGD8AXZ4?unspentOnly=true
// 3.- Get the hex tx for the selected UTXO:
// https://live.blockcypher.com/btc-testnet/tx/e7f034f4a56999d04d8a3a8f07dca10e87cd4a7fd2a779e9ecd41c57afec84f8/
// 4.- Copy Tx Hex and paste here:
$txHex = '0100000001b674eafd9c1a79402661e7e7b37746145869260c29263f213f6f120ea8a95574010000006b483045022100ac406c14ef2da774d64d5504340fd278a827a99941cf0bef26fdff17c191ffa4022016a69a281ec1fcdf22c34543ff97a5c332ed12856fb44e525cf8ba3aea7c2d4101210274cb62e999bdf96c9b4ef8a2b44c1ac54d9de879e2ee666fdbbf0e1a03090cdfffffffff02e8030000000000001976a914a93806b8ae200fffca565f7cf9ef3ab17d4ffe8888ac204e0000000000001976a914edeed3ce7f485e44bc33969af08ec9250510f83f88ac00000000';
$myTx = TransactionFactory::fromHex($txHex);
$spendOutput = 0;
 protected function signTx($private_key_wif, $tx_builder, $transaction_outputs)
 {
     $private_key = PrivateKeyFactory::fromWif($private_key_wif);
     $transaction = $tx_builder->get();
     $signer = new Signer($transaction, Bitcoin::getEcAdapter());
     // sign each input script
     foreach ($transaction_outputs as $offset => $transaction_output) {
         $signer->sign($offset, $private_key, $transaction_output);
     }
     $signed_transaction = $signer->get();
     return $signed_transaction;
 }
<?php

require "../vendor/autoload.php";
use BitWasp\Bitcoin\Bitcoin;
use BitWasp\Bitcoin\Transaction\TransactionFactory;
$ecAdapter = Bitcoin::getEcAdapter();
$math = $ecAdapter->getMath();
$privHex1 = '421c76d77563afa1914846b010bd164f395bd34c2102e5e99e0cb9cf173c1d87';
$privHex2 = 'f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162';
$redeemScriptHex = '52410443f3ce7c4ddf438900a6662420511ea48321f8cedd3e63943700b07ac9752a6bf18230095730b18f2d3c3dbdc0a892ca62b1722730f183d370963d6f4d3e20c84104f260c8b554e9d0921c507fb231d0e226ba17462078825c56170facb6567dcec700750bd529f4361da21f59fbfc7d0bce319fdef4e7c524e82d3e313e92b1b34752ae';
$txid = '4141414141414141414141414141414141414141414141414141414141414141';
$vout = 0;
$amount = '161662670';
$fee = '12345';
$amountAfterFee = $math->sub($amount, $fee);
// Two users independently create private keys.
$pk1 = \BitWasp\Bitcoin\Key\PrivateKeyFactory::fromHex($privHex1);
$pk2 = \BitWasp\Bitcoin\Key\PrivateKeyFactory::fromHex($privHex2);
$outpoint = new \BitWasp\Bitcoin\Transaction\OutPoint(\BitWasp\Buffertools\Buffer::hex($txid), $vout);
$redeemScript = new \BitWasp\Bitcoin\Script\P2shScript(\BitWasp\Bitcoin\Script\ScriptFactory::fromHex($redeemScriptHex));
$os = $redeemScript->getOutputScript();
// One party (pk1) wants to spend funds. He creates a transaction spending the funding tx to his address.
$spendTx = TransactionFactory::build()->spendOutPoint($outpoint)->payToAddress($amountAfterFee, $pk1->getAddress())->get();
// Two parties sign the transaction (can be done in steps)
$signer = TransactionFactory::sign($spendTx);
$signer->sign(0, $pk1, $os, $redeemScript)->sign(0, $pk2, $os, $redeemScript);
$signed = $signer->get();
$fundTx = TransactionFactory::build()->input('4d7adb19fff03892a11924f2a9188e36dbbdf0f3bb341b6514475e4df238184b', 0)->output(1000000, $os)->get();
echo $fundTx->getHex() . "\n";
echo $fundTx->getTxId()->getHex() . "\n";
echo "Fully signed transaction: " . $signed->getHex() . "\n";
 public static function addressFromWIF($wif)
 {
     $private_key_instance = PrivateKeyFactory::fromWif($wif);
     $address_instance = $private_key_instance->getAddress();
     return $address_instance->getAddress();
 }
<?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";
 /**
  * @param string $privateKey
  * @throws \Exception
  */
 private function checkHexPrivateKey($privateKey)
 {
     if (!is_string($privateKey)) {
         throw new \Exception("Invalid private key format. String expected.");
     }
     try {
         PrivateKeyFactory::fromHex($privateKey);
     } catch (\Exception $e) {
         throw new \Exception("Invalid private key format. Hex format expected.");
     }
 }
<?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]));