예제 #1
0
 public function testDecodeRedeemScript()
 {
     // Random samples from txs in the blockchain
     $samples = ["5221032c6aa78662cc43a3bb0f8f850d0c45e18d0a49c61ec69db87e072c88d7a9b6e9210353581fd2fc745d17264af8cb8cd507d82c9658962567218965e750590e41c41e21024fe45dd4749347d281fd5348f56e883ee3a00903af899301ac47ba90f904854f53ae", "5141048ff228400b3056084121fa83658c43858e3826d59ddc6cfd033df80565f8cc96e09e26e6a2320958a999cb82030d781698176a591424cf4f66b5644e7c8e690a41040f63d3a4b5d797b8ceb443ae54a45b7bb0465a792844e104e31eda18f8a0b0b8f42adaac0002bac7aae6a5cd4106be45172463e9caf44aa567da486455063d1152ae", "524104664547a29ffc51db8d46377c1c6611914e11a9c36a83992e642b6c3aa1f0017eee1d77d6d0e4f3b82be92067b39d7f62fe2da7b680e3e306402bf53f8dd5ef04410496cb89ca7f8f244808b4a50ee80e9acd12f801d33646aa9a50eb4a6b550f6520b4204a79f0192a30fc8c7b0eef18d49b3b720373f6b2b928023ae4b463c2c4eb52ae", "522102c33586c016c66158f921c54e30628d682627839d0297f800050b981ab298b58a2102bd4d0115f28b4ac3122e89ebab628f1de2db0a3947721f2fe9b17f9b96e2204052ae", "524104192944fe1ecf2bb78174a282a3b7d3a457bb40993a6785853cfcedf5bb6f67fd453db59b4e2cfd864480c86d816b383b0be51f82444f7bca0cdaa12e002b25da4104738bcb941b0ca59dad113393c212be91b4bb648efce44567bd372ffac64c6f373d2d928a34c6d1d98fced6a6b03852fc592eef7534d23b801a714e11f1a061ac410491ccd85240d31e84e40586d0bf10a1f1e9d309bffac8e179534be2a28310e92c486d9c7e47ee76e23f6b6f390075e16cf08b6ce9c3d2383c5a3a20b6598d224e53ae", "52410453e1bb5aa30c3711ac64ca03a38d7f248db3b31a2559efa8a4cb6fa63b5356e9d2cb8c26b722d7f984cc51ba6bfceb2e5306249f6ba626e73de1d412f2e8d4594104be2c03fe4f9aa55dea54812822a563138b4c12651ce3d1161b246c47379838ae1f7a0df55e6b475c2cddd278bcd130898a21e319e1bc02da86876efb9fcb621c4104cf5189fa8b6457a5e06f652ef8666499574632bc5c75f51fb049dcc93638309f493594e4bd6b1d6ac92f6d77cc52db255b92f20749b237927fb2a60d7c887a1053ae", "5241048c1bbabfd38a9d462443e9bd99e133f512efa9548743ffb3f544dcc83b9b0356780796678519987ba04a054445e0cea2a60f1cafc1dbcc97c412338771b094374104bf5d3c29bad79db8f541b0d1095ef1f8ba4e8eda75936dcec81ac72599121b561f2b4ce9a2947cf0a5498888ee8e2a918c7e595da8fa1ae5b28df607e5fc29bb4104d79d37c0f322442bea954bb3fda3a97b24b113152a638316a1fbd44673e28967cefca7c3ed366ed41bbc0978dc308efab89f6e9010912d1e6c3fed0d4dc2b63d53ae", "5121031b9abc9a11a4a078509969f12de3129bf81060b001742e05cd8041a7e7402bcb51ae", "5241043a0f00454bdcd92698bebd22de0785c8dd190144115b3eced47f26796e24c3050faa3cb3b46a5a868a8f77f7f08ddda7c90952ca07bc18fc9765b8f0bc28cdd941044d7e454064678f032c6a845a986a41e20ae224a7843eb397637e7d1df2c80762b0a14d348cb2a4261cf83fba77d1e025a9eaaf251e1a23f9caabb4c9c5fba5314104ba5b7a9ce88ee36d8689e6a70e847b88d2ddcd12a008195f5b841f88485e14d6a3abc4120e721a50655ce3ba63606ba7ac927254f89ec3d0dea3bfe1d7b2797653ae", "5241046bcd91262b52419bdb0a88cc628e6eeed8ca7c60857a04be80c9cef320a775881d01b439cefc6e814f713c753be596fb65b5575f9e99583cd50776474e80adc14104b730f446201772dbc67d39f72fe9ef2e966066718070a4248874fb237a325dfa43073a893f95ae713d40194bac5d6cb23d25616e0966286c9c7416afe7214ac84104b31a45c0362e0c56e868bb7563334b3b35eb0f4af810648e45e365c46eaf983a155b6ec834db5143a7df47780fbf7e9f6ac5c3d45837b6c76b0c9c4c864feee453ae", "524104f10d42e5a5dc24dabe524dc305f9deab2c5b58c42aa83833d1d2ad38c9b796b4756a99e60bfee19e92424f3aa919fb63377b6d8d35d091d6a5de62b58b8c8d7721025563ee4b549f5a7d3dfb046a088815c69ebd44b389a78342ccb01e77d89465a752ae", "522102c48bf0c25bf78fbe98988ef8f27ee05284f79c550e987a88e1237872c030ab8021026f6020210361586f02c93cfb926fed3d240b7f11b1a5694b36c826561abd3932210352057bbf5c024edd3630606689956c52104150d1c494b1d92ca6c7243d5eeb7453ae", "522102d7297e56bc410c2d1671cd2694686400f59061bef1bbb6f7e3269dacbbdce53e2102421a4efafabd2534116deb6c00a01831de71c62c53a5e718b852ccd81a7ff98c52ae", "522102d7297e56bc410c2d1671cd2694686400f59061bef1bbb6f7e3269dacbbdce53e2102421a4efafabd2534116deb6c00a01831de71c62c53a5e718b852ccd81a7ff98c52ae", "52210374763369da3dca422b64e13ae1cf81a5f68dd09a1efcd463b5511fe7a436207a21021d7e25870057383faad795f651b3f5844c4d3ebb1e3a31e444e6a21d9af371642102c5463df6e77f7f659d123ca19e079ef9ec08e1ddfa4a1bcb4814902b2b1ad41c53ae", "5241046dae34916bec595e73b3fabfd1aad2158994fee1a5bc19216654dc49b47f1976a26d7a6d3c7b713f8650121812253a206c4cd7f1e7b453e8e700c720e99c60564104fcb3a8fd045eb2c77a45fdfed73317c22b4ab40de5950c944ff8b1cf45eb83aaafc8d987fe1706d10febc6277223569e0df10881b8cea2435b4fa3bdabf41ad021036c06d0a475646980d4ede31b6b4864946fe7fb54fa15102b03ac16a56c4300f053ae", "524104d403a9ec23cb289734645337a079c636ecc47b6015ebd88e972741948ddd65a708f8238f1da4b8f70945ae57288a4bc406e3811a0b83b4e610565cc83a5faff741046c82c6671ada6c430d8ea81b27ecae04fa9f0b4ab14bcceb89c589ea0d7b1919565221ef6c2004a6204f1d6d616eb770c13dbda3cdf271f2ae6fe5a654b5a42e2102e3929380fccb603649a8dd775ec2b1e81748b2749503e039530330f1a5b448bf53ae", "5221039bf1c1ec550815dee677d1b391a03f5f501abe6fd9817b2486bc03aa7ae038d8410437d0fd54cbbe8d4e6bd12d19b1c863d3cfbce71c4b31541546685c090d9572a2d2f5f30c58d45c7141cf29b7fe83002f29abccc9c290b7dba6eed9e9d773d1bc2102521e92a6b26db346cb8e2a27ceb2ec83905f3f8d3f8d52634c82c3ad8d0f188a53ae"];
     foreach ($samples as $sample) {
         $raw = RawTransaction::decode_redeem_script($sample);
         $this->assertTrue(is_array($raw));
     }
 }
<?php

use BitWasp\BitcoinLib\BitcoinLib;
use BitWasp\BitcoinLib\RawTransaction;
require_once __DIR__ . '/../vendor/autoload.php';
while (!isset($redeem_script)) {
    echo "Enter redeem script: ";
    $line = trim(fgets(STDIN));
    $decode_redeem_script = RawTransaction::decode_redeem_script($line);
    if ($decode_redeem_script == FALSE) {
        echo "[ERROR]- Not a valid script!\n";
        unset($decode_redeem_script);
    } else {
        $redeem_script = $line;
        echo "Learned about {$decode_redeem_script['m']} of {$decode_redeem_script['n']} address: " . BitcoinLib::public_key_to_address($redeem_script, '05') . "\n";
    }
}
echo "Enter WIF encoded private keys: \n (1): ";
$private_keys = array();
while ("\n" != ($line = fgets(STDIN))) {
    $line = trim($line);
    $t = BitcoinLib::validate_WIF($line, '80');
    var_dump($t);
    if (BitcoinLib::validate_WIF($line, '80') == TRUE) {
        $private_keys[] = $line;
    } else {
        echo "Not a valid private key.\n";
    }
    echo " (" . (count($private_keys) + 1) . "): ";
}
// Initialize wallet
예제 #3
0
 /**
  * Details
  * Buyer URI: purchases/details/<order_id>
  * Vendor URI: orders/details/<order_id>
  * Admin URI: admin/orders/<order_id>
  *
  * Order details page. Shows buyer/vendor/admin the details of the
  * the order.
  *
  * @param    int $order_id
  */
 public function details($order_id)
 {
     if (!(is_numeric($order_id) && $order_id >= 0)) {
         redirect('');
     }
     $data['order'] = $this->order_model->get($order_id);
     // no restriction on buyer/vendor
     if ($data['order'] == FALSE) {
         redirect('');
     }
     // Work out if the user is allowed to view this order.
     if (!$this->current_user->user_role == 'Admin' && !($this->current_user->user_id == $data['order']['buyer']['id']) && !($this->current_user->user_id == $data['order']['vendor']['id'])) {
         redirect('');
     }
     // Only allow access when the order is confirmed by the buyer.
     if ($data['order']['progress'] == '0') {
         redirect('');
     }
     if ($this->current_user->user_role == 'Buyer') {
         $data['action_page'] = 'purchases/details/' . $order_id;
         $data['cancel_page'] = 'purchases';
     } else {
         if ($this->current_user->user_role == 'Vendor') {
             $data['action_page'] = 'orders/details/' . $order_id;
             $data['cancel_page'] = 'orders';
         } else {
             if ($this->current_user->user_role == 'Admin') {
                 $data['action_page'] = 'admin/order/' . $order_id;
                 $data['cancel_page'] = 'admin/orders';
             }
         }
     }
     $this->load->model('transaction_cache_model');
     $this->load->model('bip32_model');
     $this->load->model('review_model');
     $child_key_id = $data['order'][strtolower($this->current_user->user_role) . '_public_key'];
     $data['my_multisig_key'] = $this->bip32_model->get_child_key($child_key_id);
     $data['wallet_salt'] = $this->users_model->wallet_salt($this->current_user->user_id);
     $this->load->library('bw_bitcoin');
     $html = $this->bw_bitcoin->js_html($data['order']['redeemScript'], $data['order']['unsigned_transaction']);
     if (is_array($data['my_multisig_key'])) {
         $data['signing_info'] = array('parent_extended_public_key' => $data['my_multisig_key']['parent_extended_public_key'], 'extended_public_key' => $data['my_multisig_key']['extended_public_key'], 'bip32_provider' => $data['my_multisig_key']['provider'], 'full_key_index' => "m/0'/0/" . $data['my_multisig_key']['key_index'], 'key_index' => "m/0'/0/" . $data['my_multisig_key']['key_index'], 'public_key' => $data['my_multisig_key']['public_key'], 'partially_signed_transaction' => $data['order']['partially_signed_transaction'], 'unsigned_transaction' => $data['order']['unsigned_transaction'], 'wallet_salt' => $data['wallet_salt'], 'crafted_html' => $html);
         $ident = strtolower($data['my_multisig_key']['provider']);
         $this->_partial("sign_form_output", "orders/details_form_" . $ident);
         if ($ident == 'js') {
             $data['header_meta'] = $this->load->view('orders/add_signature_js', $data['signing_info'], TRUE);
             $this->load->model('users_model');
         } elseif ($ident == 'onchain') {
             $this->load->library('onchainlib');
             $tx_crc = substr(hash('sha256', $data['order']['partially_signed_transaction'] == '' ? $data['order']['unsigned_transaction'] : $data['order']['partially_signed_transaction']), 0, 8);
             $data['onchain_sign'] = $this->onchainlib->sign_request($data['order']['id'], $tx_crc);
         }
     }
     // Only allow a vendor to refund, if the progress is either 3 or 4 (not yet dispatched)
     $data['can_refund'] = ($this->current_user->user_role == 'Vendor' and in_array($data['order']['progress'], array('3', '4')));
     $data['display_sign_form'] = (bool) (($data['order']['vendor_selected_upfront'] == '1' or $data['order']['vendor_selected_escrow'] == '0') and $data['order']['progress'] == '3' && $this->current_user->user_role == 'Buyer' or $data['order']['progress'] == '4' && $this->current_user->user_role == 'Vendor' or ($data['order']['vendor_selected_escrow'] == '1' and $data['order']['vendor_selected_upfront'] == '0' and $data['order']['progress'] == '4' && $this->current_user->user_role == 'Vendor' or $data['order']['progress'] == '5' && $this->current_user->user_role == 'Buyer') or ($data['order']['progress'] == '6' and $data['order']['partially_signed_transaction'] == '' or $data['order']['partially_signed_transaction'] !== '' and $data['order']['partially_signing_user_id'] !== $this->current_user->user_id) or ($data['order']['progress'] == '8' and $data['order']['partially_signed_transaction'] == '' or $data['order']['partially_signed_transaction'] !== '' and $data['order']['partially_signing_user_id'] !== $this->current_user->user_id));
     $data['display_sign_msg'] = $data['order']['partially_signed_transaction'] == '' ? 'Please add first signature.' : 'Please sign to complete transaction.';
     // Only allow access to the form handling script if the form is allowed to be displayed.
     if ($data['display_sign_form'] == TRUE) {
         // JS
         if ($this->input->post('submit_js_signed_transaction') == 'Submit Transaction') {
             if ($this->form_validation->run('submit_js_signed_transaction') == TRUE) {
                 $check = $this->bw_bitcoin->handle_order_tx_submission($data['order'], $this->input->post('js_transaction'), $data['my_multisig_key']);
                 if (is_string($check)) {
                     $data['invalid_transaction_error'] = $check;
                 } else {
                     if ($check == TRUE) {
                         if (strlen($data['order']['partially_signed_transaction']) > 0) {
                             $this->current_user->set_return_message('Transaction has been submitted, and will be processed shortly.', 'success');
                             redirect($data['action_page']);
                         } else {
                             if ($data['order']['progress'] == '3') {
                                 // Buyer must sign early before vendor dispatches.
                                 $update = array('partially_signed_transaction' => $this->input->post('js_transaction'), 'partially_signing_user_id' => $this->current_user->user_id, 'partially_signed_time' => time());
                                 $this->order_model->progress_order($order_id, '3', '4', $update);
                             } else {
                                 if ($data['order']['progress'] == '4') {
                                     // Vendor indicates they have dispatched.
                                     $update = array('partially_signed_transaction' => $this->input->post('js_transaction'), 'partially_signing_user_id' => $this->current_user->user_id, 'partially_signed_time' => time(), 'dispatched_time' => time(), 'dispatched' => '1');
                                     $this->order_model->progress_order($order_id, '4', '5', $update);
                                 } else {
                                     if ($data['order']['progress'] == '6') {
                                         $update = array('partially_signed_transaction' => $this->input->post('js_transaction'), 'partially_signing_user_id' => $this->current_user->user_id, 'partially_signed_time' => time());
                                         $this->order_model->update_order($order_id, $update);
                                     } else {
                                         if ($data['order']['progress'] == '8') {
                                             $update = array('partially_signed_transaction' => $this->input->post('js_transaction'), 'partially_signing_user_id' => $this->current_user->user_id, 'partially_signed_time' => time());
                                             $this->order_model->update_order($order_id, $update);
                                         }
                                     }
                                 }
                             }
                             $this->current_user->set_return_message('Your partially signed transaction has been saved!', 'success');
                             redirect($data['action_page']);
                         }
                     }
                 }
             }
         }
         // Manual
         if ($this->input->post('submit_signed_transaction') == 'Submit Transaction') {
             if ($this->form_validation->run('input_transaction') == TRUE) {
                 $validate = $this->bw_bitcoin->handle_order_tx_submission($data['order'], $this->input->post('partially_signed_transaction'), $data['my_multisig_key']);
                 if (is_string($validate)) {
                     $data['invalid_transaction_error'] = $validate;
                 } else {
                     if ($validate == TRUE) {
                         if (strlen($data['order']['partially_signed_transaction']) > 0) {
                             $this->current_user->set_return_message('Transaction has been submitted, and will be processed shortly.', 'success');
                             redirect($data['action_page']);
                         } else {
                             if ($data['order']['progress'] == '3') {
                                 // Buyer must sign early before vendor dispatches.
                                 $update = array('partially_signed_transaction' => $this->input->post('partially_signed_transaction'), 'partially_signing_user_id' => $this->current_user->user_id, 'partially_signed_time' => time());
                                 $this->order_model->progress_order($order_id, '3', '4', $update);
                             } else {
                                 if ($data['order']['progress'] == '4') {
                                     // Vendor indicates they have dispatched.
                                     $update = array('partially_signed_transaction' => $this->input->post('partially_signed_transaction'), 'partially_signing_user_id' => $this->current_user->user_id, 'partially_signed_time' => time(), 'dispatched_time' => time(), 'dispatched' => '1');
                                     $this->order_model->progress_order($order_id, '4', '5', $update);
                                 } else {
                                     if ($data['order']['progress'] == '6') {
                                         $update = array('partially_signed_transaction' => $this->input->post('partially_signed_transaction'), 'partially_signing_user_id' => $this->current_user->user_id, 'partially_signed_time' => time());
                                         $this->order_model->update_order($order_id, $update);
                                     } else {
                                         if ($data['order']['progress'] == '8') {
                                             $update = array('partially_signed_transaction' => $this->input->post('partially_signed_transaction'), 'partially_signing_user_id' => $this->current_user->user_id, 'partially_signed_time' => time());
                                             $this->order_model->update_order($order_id, $update);
                                         }
                                     }
                                 }
                             }
                             $this->current_user->set_return_message('Your partially signed transaction has been saved!', 'success');
                             redirect($data['action_page']);
                         }
                     }
                 }
             }
         }
     }
     $data['redeem_script'] = RawTransaction::decode_redeem_script($data['order']['redeemScript']);
     $data['addrs'] = array($data['order']['buyer_payout'] => 'buyer', $data['order']['vendor_payout'] => 'vendor');
     if (isset($data['order']['public_keys']['admin'])) {
         $data['addrs'][BitcoinLib::public_key_to_address($data['order']['public_keys']['admin']['public_key'], $this->bw_config->currencies[0]['crypto_magic_byte'])] = 'admin';
     }
     if (strlen($data['order']['partially_signed_transaction']) > 0) {
         $data['raw_tx'] = RawTransaction::decode($data['order']['partially_signed_transaction']);
         $data['signer'] = $this->accounts_model->get(array('id' => $data['order']['partially_signing_user_id']));
     } else {
         if (strlen($data['order']['unsigned_transaction']) > 0) {
             $data['raw_tx'] = RawTransaction::decode($data['order']['unsigned_transaction']);
         }
     }
     $checkStrangeAddress = function () use($data) {
         $tx_addrs = array();
         foreach ($data['raw_tx']['vout'] as $vout) {
             $tx_addrs[] = $vout['scriptPubKey']['addresses'][0];
         }
         return count($tx_addrs) != count(array_intersect($tx_addrs, array_keys($data['addrs'])));
     };
     $data['strange_address'] = isset($data['raw_tx']) ? $checkStrangeAddress() : FALSE;
     $data['fees']['shipping_cost'] = $data['order']['shipping_costs'];
     $data['fees']['fee'] = $data['order']['fees'];
     $data['fees']['escrow_fees'] = $data['order']['extra_fees'];
     $data['fees']['total'] = $data['order']['shipping_costs'] + $data['order']['fees'];
     if ($this->current_user->user_role == 'Buyer' && $data['order']['paid_time'] == '') {
         $this->load->library('ciqrcode');
         $data['payment_url'] = "bitcoin:{$data['order']['address']}?amount={$data['order']['order_price']}&message=Order+{$data['order']['id']}&label=Order+{$data['order']['id']}";
         $data['qr'] = $this->ciqrcode->generate_base64(array('data' => $data['payment_url']));
     }
     $data['page'] = 'orders/details';
     $data['title'] = 'Order Details: #' . $data['order']['id'];
     $this->_render($data['page'], $data);
 }
예제 #4
0
 public function js_html($redeem_script, $raw_transaction)
 {
     if (strlen($redeem_script) == '0' || strlen($raw_transaction) == '0') {
         return '';
     }
     $this->CI->load->model('transaction_cache_model');
     $decode_rs = \BitWasp\BitcoinLib\RawTransaction::decode_redeem_script($redeem_script);
     $pubkey_list = '';
     foreach ($decode_rs['keys'] as $i => $key) {
         $pubkey_list .= '    "' . $key . '"' . ($i < 2 ? ',' : '') . "\n";
     }
     $p2sh_info = \BitWasp\BitcoinLib\RawTransaction::create_multisig(2, $decode_rs['keys']);
     $decode_tx = \BitWasp\BitcoinLib\RawTransaction::decode($raw_transaction);
     $utxos = "";
     foreach ($decode_tx['vin'] as $vin => $input) {
         $tx_info = $this->CI->transaction_cache_model->get_payment($input['txid']);
         $utxos .= "\n{\n    address: '{$p2sh_info['address']}',\n    txid: '{$tx_info['tx_id']}',\n    vout: {$tx_info['vout']},\n    scriptPubKey: '{$tx_info['pkScript']}',\n    confirmations: 10,\n    amount: " . $tx_info['value'] . "\n}" . ($vin < count($decode_tx['vin']) - 1 ? ',' : '') . "\n";
         //".($current_block-$tx_info['block_height']).",
     }
     $outs = '';
     foreach ($decode_tx['vout'] as $vout => $output) {
         $outs .= '{
 address: "' . $output['scriptPubKey']['addresses'][0] . '",
 amount: ' . $output['value'] . "\n}" . ($vout < count($decode_tx['vout']) - 1 ? ',' : '');
     }
     $json = "\nvar pubkeys = [\n{$pubkey_list}\n];\n\nvar opts = {\n    nreq: 2,\n    pubkeys: pubkeys\n};\n\nvar serialized_pubkeys = [];\nfor (var i=0; i<3; i++) {\n    serialized_pubkeys.push(new bitcore.buffertools.Buffer(opts.pubkeys[i],'hex'));\n}\n\nvar script = bitcore.Script.createMultisig(opts.nreq, serialized_pubkeys, {noSorting: true});\nvar hash   = bitcore.util.sha256ripe160(script.getBuffer());\n\n\nvar p2shScript = script.serialize().toString('hex');\nvar p2shAddress = new bitcore.Address.fromScript(p2shScript).toString();\nconsole.log('got address: '+p2shAddress);\n\nvar utxos = [\n{$utxos}\n];\n\nvar outs = [\n{$outs}\n];\n\nvar hashMap = {};\nhashMap[p2shAddress] = p2shScript;\n        ";
     return $json;
 }