public function handle_order_tx_submission($order, $incoming_tx, $user_bip32_key) { $this->CI->load->model('transaction_cache_model'); $currently_unsigned = strlen($order['partially_signed_transaction']) == 0; if ($currently_unsigned) { $start_tx = trim($order['unsigned_transaction']); } else { $start_tx = trim($order['partially_signed_transaction']); } $json = str_replace("'", '', $order['json_inputs']); $decode_current_tx = \BitWasp\BitcoinLib\RawTransaction::decode($start_tx); $decode_incoming_tx = \BitWasp\BitcoinLib\RawTransaction::decode($incoming_tx); // Does incoming tx match expected spend? $check = $this->CI->transaction_cache_model->check_if_expected_spend($decode_incoming_tx['vout'], $order['id']); if ($check !== $order['address']) { return 'Invalid transaction.'; } // General check that signatures match tx $validate = \BitWasp\BitcoinLib\RawTransaction::validate_signed_transaction($incoming_tx, $json); if ($validate == FALSE) { return 'Invalid signature.'; } $decode_redeem_script = \BitWasp\BitcoinLib\RawTransaction::decode_redeem_script($order['redeemScript']); if (!$currently_unsigned and $user_bip32_key['provider'] == 'JS') { // Need to build the sig from this tx into the last. $copy = $decode_incoming_tx; foreach ($copy['vin'] as $i => &$input) { $script = explode(" ", $input['scriptSig']['asm']); $sig1 = \BitWasp\BitcoinLib\RawTransaction::_encode_vint(strlen($script[1]) / 2) . $script[1]; $old_script = explode(" ", $decode_current_tx['vin'][$i]['scriptSig']['asm']); $sig2 = \BitWasp\BitcoinLib\RawTransaction::_encode_vint(strlen($old_script[1]) / 2) . $old_script[1]; $redeem_script = '4c' . \BitWasp\BitcoinLib\RawTransaction::_encode_vint(strlen($order['redeemScript']) / 2) . $order['redeemScript']; $input['scriptSig']['hex'] = '00' . $sig1 . $sig2 . $redeem_script; } $incoming_tx = \BitWasp\BitcoinLib\RawTransaction::encode($copy); // Now need to reorder sigs! $assoc = $this->associate_sigs_with_keys($incoming_tx, $json, $this->CI->bw_config->currencies[0]['crypto_magic_byte']); foreach ($copy['vin'] as $i => &$input) { $input['scriptSig']['hex'] = \BitWasp\BitcoinLib\RawTransaction::_apply_sig_scripthash_multisig($assoc[$i], array('public_keys' => $decode_redeem_script['keys'], 'script' => $order['redeemScript'])); } $incoming_tx = \BitWasp\BitcoinLib\RawTransaction::encode($copy); $decode_incoming_tx = \BitWasp\BitcoinLib\RawTransaction::decode($incoming_tx); } // Compare signatures! $old_sig_map = $this->associate_sigs_with_keys($start_tx, $json, $this->CI->bw_config->currencies[0]['crypto_magic_byte']); // Now check current signatures against users key. submittee must have signed. $key_sig_map = $this->associate_sigs_with_keys($incoming_tx, $json, $this->CI->bw_config->currencies[0]['crypto_magic_byte']); foreach ($key_sig_map as $i => $input_sig_map) { // If the number of sigs hasn't increased, or no sig from the current user exists.. if (count($old_sig_map) > 0 && count($input_sig_map) <= count($old_sig_map[$i]) or !isset($input_sig_map[$user_bip32_key['public_key']])) { return 'Incorrect signature!'; } } // Broadcast tx if fully signed! if (!$currently_unsigned) { $this->CI->transaction_cache_model->to_broadcast($incoming_tx); $this->sendrawtransaction($incoming_tx); } return TRUE; }