コード例 #1
0
 public function testValidateAddresses()
 {
     for ($i = 0; $i < 5; $i++) {
         $set = BitcoinLib::get_new_key_set(null, (bool) ($i % 2));
         $validate = $this->client->validateaddress($set['pubAdd']);
         // Ensure that the Bitcoind believes the address is valid, and that this matches what we think
         $this->assertTrue($validate['isvalid']);
         $this->assertEquals($validate['isvalid'], BitcoinLib::validate_address($set['pubAdd'], null, null));
     }
 }
コード例 #2
0
 /**
  * @param string $address
  * @param int    $value
  * @return $this
  * @throws \Exception
  */
 public function addRecipient($address, $value)
 {
     if (!BitcoinLib::validate_address($address)) {
         throw new \Exception("Invalid address [{$address}]");
     }
     // using this 'dirty' way of checking for a float since there's no other reliable way in PHP
     if (!is_int($value)) {
         throw new \Exception("Values should be in Satoshis (int)");
     }
     if ($value <= Blocktrail::DUST) {
         throw new \Exception("Values should be more than dust (" . Blocktrail::DUST . ")");
     }
     $this->addOutput(['address' => $address, 'value' => $value]);
     return $this;
 }
コード例 #3
0
ファイル: AddressController.php プロジェクト: CryptArc/xchain
 public function validateAddress($address)
 {
     $bitcoin = new BitcoinLib();
     $output = array();
     try {
         $validate = $bitcoin->validate_address($address);
     } catch (Exception $e) {
         $validate = false;
     }
     if (!$validate) {
         $output['result'] = false;
         $output['is_mine'] = false;
     } else {
         $output['result'] = true;
         $get = PaymentAddress::where('address', $address)->first();
         if ($get) {
             $output['is_mine'] = true;
         } else {
             $output['is_mine'] = false;
         }
     }
     return new Response($output);
 }
コード例 #4
0
 /**
  * this test requires / asumes that the test wallet it uses contains a balance
  *
  * we keep the wallet topped off with some coins,
  * but if some funny guy ever empties it or if you use your own API key to run the test then it needs to be topped off again
  *
  * @throws \Exception
  */
 public function testWalletTransactionWithoutMnemonics()
 {
     $client = $this->setupBlocktrailSDK();
     $primaryPrivateKey = BIP32::master_key(BIP39::mnemonicToSeedHex("give pause forget seed dance crawl situate hole keen", "password"), 'bitcoin', true);
     $wallet = $client->initWallet(["identifier" => "unittest-transaction", "primary_private_key" => $primaryPrivateKey, "primary_mnemonic" => false]);
     $this->assertEquals("unittest-transaction", $wallet->getIdentifier());
     $this->assertEquals("M/9999'", $wallet->getBlocktrailPublicKeys()[9999][1]);
     $this->assertEquals("tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ", $wallet->getBlocktrailPublicKeys()[9999][0]);
     $this->assertEquals("tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ", $wallet->getBlocktrailPublicKey("m/9999'")->key());
     $this->assertEquals("tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ", $wallet->getBlocktrailPublicKey("M/9999'")->key());
     list($confirmed, $unconfirmed) = $wallet->getBalance();
     $this->assertGreaterThan(0, $confirmed + $unconfirmed, "positive unconfirmed balance");
     $this->assertGreaterThan(0, $confirmed, "positive confirmed balance");
     list($path, $address) = $wallet->getNewAddressPair();
     $this->assertTrue(strpos($path, "M/9999'/0/") === 0);
     $this->assertTrue(BitcoinLib::validate_address($address, false, null));
     $value = BlocktrailSDK::toSatoshi(0.0002);
     $txHash = $wallet->pay([$address => $value]);
     $this->assertTrue(!!$txHash);
     sleep(1);
     // sleep to wait for the TX to be processed
     try {
         $tx = $client->transaction($txHash);
     } catch (ObjectNotFound $e) {
         $this->fail("404 for tx[{$txHash}] [" . gmdate('Y-m-d H:i:s') . "]");
     }
     $this->assertTrue(!!$tx, "check for tx[{$txHash}] [" . gmdate('Y-m-d H:i:s') . "]");
     $this->assertEquals($txHash, $tx['hash']);
     $this->assertTrue(count($tx['outputs']) <= 2);
     $this->assertTrue(in_array($value, array_column($tx['outputs'], 'value')));
 }
コード例 #5
0
 public function check_bitcoin_address($str)
 {
     return \BitWasp\BitcoinLib\BitcoinLib::validate_address($str, '05');
 }
コード例 #6
0
 public function testP2SHMultisig()
 {
     $n = 3;
     $m = 2;
     $k = [];
     $pk_list = [];
     for ($i = 0; $i < $n; $i++) {
         $k[$i] = BitcoinLib::get_new_key_set();
         $pk_list[] = $k[$i]['pubKey'];
     }
     $multisig = RawTransaction::create_multisig($m, RawTransaction::sort_multisig_keys($pk_list));
     $this->assertTrue(!!$multisig['address']);
     $this->assertTrue(BitcoinLib::validate_address($multisig['address']));
 }
コード例 #7
0
 /**
  * build inputs and outputs lists for TransactionBuilder
  *
  * @param TransactionBuilder $txBuilder
  * @return array
  * @throws \Exception
  */
 public function buildTx(TransactionBuilder $txBuilder)
 {
     $send = $txBuilder->getOutputs();
     $utxos = $txBuilder->getUtxos();
     foreach ($utxos as $utxo) {
         if (!$utxo->address || !$utxo->value || !$utxo->scriptPubKeyHex) {
             $tx = $this->sdk->transaction($utxo->hash);
             if (!$tx || !isset($tx['outputs'][$utxo->index])) {
                 throw new \Exception("Invalid output [{$utxo->hash}][{$utxo->index}]");
             }
             $output = $tx['outputs'][$utxo->index];
             if (!$utxo->address) {
                 $utxo->address = $output['address'];
             }
             if (!$utxo->value) {
                 $utxo->value = $output['value'];
             }
             if (!$utxo->scriptPubKeyHex) {
                 $utxo->scriptPubKeyHex = $output['script_hex'];
             }
         }
         if (!$utxo->path) {
             $address = $utxo->address;
             if (!BitcoinLib::validate_address($address)) {
                 throw new \Exception("Invalid address [{$address}]");
             }
             $utxo->path = $this->getPathForAddress($address);
         }
         if (!$utxo->redeemScript) {
             list(, $redeemScript) = $this->getRedeemScriptByPath($utxo->path);
             $utxo->redeemScript = $redeemScript;
         }
     }
     if (array_sum(array_map(function (UTXO $utxo) {
         return $utxo->value;
     }, $utxos)) < array_sum(array_column($send, 'value'))) {
         throw new \Exception("Atempting to spend more than sum of UTXOs");
     }
     list($fee, $change) = $this->determineFeeAndChange($txBuilder);
     if ($txBuilder->getValidateChange() !== null && $txBuilder->getValidateChange() != $change) {
         throw new \Exception("the amount of change suggested by the coin selection seems incorrect");
     }
     if ($txBuilder->getValidateFee() !== null && $txBuilder->getValidateFee() != $fee) {
         throw new \Exception("the fee suggested by the coin selection ({$txBuilder->getValidateFee()}) seems incorrect ({$fee})");
     }
     if ($change > 0) {
         $send[] = ['address' => $txBuilder->getChangeAddress() ?: $this->getNewAddress(), 'value' => $change];
     }
     // create raw transaction
     $inputs = array_map(function (UTXO $utxo) {
         return ['txid' => $utxo->hash, 'vout' => (int) $utxo->index, 'address' => $utxo->address, 'scriptPubKey' => $utxo->scriptPubKeyHex, 'value' => $utxo->value, 'path' => $utxo->path, 'redeemScript' => $utxo->redeemScript];
     }, $utxos);
     // outputs should be randomized to make the change harder to detect
     if ($txBuilder->shouldRandomizeChangeOuput()) {
         shuffle($send);
     }
     return [$inputs, $send];
 }
コード例 #8
0
 /**
  * Create
  *
  * This function creates a raw transaction from an array of inputs,
  * and an array of outputs. It takes essentially the same data is
  * bitcoind's createrawtransaction function.
  *
  * Inputs: Each input is a child array of [txid, vout, and optionally a sequence number.]
  * Outputs: Each output is a key in the array: address => $value.
  *
  * @param   array  $inputs
  * @param   array  $outputs [address => value, ] or [[address, value], ]
  *                          or [['address' => address, 'value' => value], ]
  *                          or [['scriptPubKey' => scriptPubKey, 'value' => value], ]
  * @param   string $magic_byte
  * @param   string $magic_p2sh_byte
  * @return  string|FALSE
  */
 public static function create($inputs, $outputs, $magic_byte = null, $magic_p2sh_byte = null)
 {
     $magic_byte = BitcoinLib::magicByte($magic_byte);
     $magic_p2sh_byte = BitcoinLib::magicP2SHByte($magic_p2sh_byte);
     $tx_array = array('version' => '1');
     // Inputs is the set of [txid/vout/scriptPubKey]
     $tx_array['vin'] = array();
     foreach ($inputs as $i => $input) {
         if (!isset($input['txid']) || strlen($input['txid']) !== 64 || !isset($input['vout']) || !is_numeric($input['vout'])) {
             throw new \InvalidArgumentException("Invalid input [{$i}]");
         }
         $tx_array['vin'][] = ['txid' => $input['txid'], 'vout' => $input['vout'], 'sequence' => isset($input['sequence']) ? $input['sequence'] : 4294967295, 'scriptSig' => ['hex' => '']];
     }
     // Outputs is the set of [address/amount]
     $tx_array['vout'] = array();
     foreach ($outputs as $k => $v) {
         $address = null;
         $scriptPubKey = null;
         if (is_numeric($k)) {
             if (!is_array($v)) {
                 throw new \InvalidArgumentException("outputs should be [address => value, ] or [[address, value], ]" . "or [['address' => address, 'value' => value], ] or [['scriptPubKey' => scriptPubKey, 'value' => value], ]");
             }
             if (isset($v['scriptPubKey']) && isset($v['value'])) {
                 $scriptPubKey = $v['scriptPubKey'];
                 $value = $v['value'];
             } else {
                 if (isset($v['address']) && isset($v['value'])) {
                     $address = $v['address'];
                     $value = $v['value'];
                 } else {
                     if (count($v) == 2 && isset($v[0]) && isset($v[1])) {
                         $address = $v[0];
                         $value = $v[1];
                     } else {
                         throw new \InvalidArgumentException("outputs should be [address => value, ] or [[address, value], ]" . "or [['address' => address, 'value' => value], ] or [['scriptPubKey' => scriptPubKey, 'value' => value], ]");
                     }
                 }
             }
         } else {
             $address = $k;
             $value = $v;
         }
         if (!is_int($value)) {
             throw new \InvalidArgumentException("Values should be in Satoshis [{$value}]");
         }
         if (!$scriptPubKey) {
             if (!BitcoinLib::validate_address($address, $magic_byte, $magic_p2sh_byte)) {
                 throw new \InvalidArgumentException("Invalid address [{$address}]");
             }
             $decode_address = BitcoinLib::base58_decode($address);
             $version = substr($decode_address, 0, 2);
             $hash = substr($decode_address, 2, 40);
             if ($version == $magic_p2sh_byte) {
                 // OP_HASH160 <scriptHash> OP_EQUAL
                 $scriptPubKey = "a914{$hash}87";
             } else {
                 // OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
                 $scriptPubKey = "76a914{$hash}88ac";
             }
         }
         $tx_array['vout'][] = ['value' => $value, 'scriptPubKey' => ['hex' => $scriptPubKey]];
     }
     $tx_array['locktime'] = 0;
     return self::encode($tx_array);
 }
コード例 #9
0
 public function testBase58CheckEncodeP2SH()
 {
     $cnt = (getenv('BITCOINLIB_EXTENSIVE_TESTING') ?: 1) * 50;
     for ($i = 0; $i < $cnt; $i++) {
         // random, 20-byte string.
         $hex = (string) bin2hex(mcrypt_create_iv(20, \MCRYPT_DEV_URANDOM));
         // 'manually' create address
         $encode = BitcoinLib::base58_encode_checksum($this->p2shAddressVersion . $hex);
         $decode = BitcoinLib::base58_decode_checksum($encode);
         // validate 'manually' created address
         $this->assertTrue(BitcoinLib::validate_address($encode, $this->addressVersion, $this->p2shAddressVersion));
         // validate 'manually' created address without specifying the address version
         //  relying on the defaults
         $this->assertTrue(BitcoinLib::validate_address($encode));
         // validate 'manually' created address
         //  disable address version and P2S address version specifically
         $this->assertTrue(BitcoinLib::validate_address($encode, false, null));
         $this->assertFalse(BitcoinLib::validate_address($encode, null, false));
         // validate 'manually'
         $this->assertTrue($hex == $decode);
         // create address
         $check2 = BitcoinLib::hash160_to_address($hex, $this->p2shAddressVersion);
         // validate created address
         $this->assertTrue(BitcoinLib::validate_address($check2, $this->addressVersion, $this->p2shAddressVersion));
         // validate created address without specifying the address version
         //  relying on the defaults
         $this->assertTrue(BitcoinLib::validate_address($check2));
         // validate created address
         //  disable address version and P2S address version specifically
         $this->assertTrue(BitcoinLib::validate_address($check2, false, null));
         $this->assertFalse(BitcoinLib::validate_address($check2, null, false));
         // validate 'manually'
         $this->assertTrue($check2 == $encode);
         // create address,  without specifying the address version
         //  relying on the defaults
         $check3 = BitcoinLib::hash160_to_address($hex, 'p2sh');
         // validate created address
         $this->assertTrue(BitcoinLib::validate_address($check3, $this->addressVersion, $this->p2shAddressVersion));
         // validate created address without specifying the address version
         //  relying on the defaults
         $this->assertTrue(BitcoinLib::validate_address($check3));
         // validate created address
         //  disable address version and P2S address version specifically
         $this->assertTrue(BitcoinLib::validate_address($check3, false, null));
         $this->assertFalse(BitcoinLib::validate_address($check3, null, false));
         // validate 'manually'
         $this->assertTrue($check3 == $encode);
     }
 }