all_tx_parser(); $transactions = ''; $mrkl_array = array(); // берем все данные из очереди. Они уже были проверены ранее, и можно их не проверять, а просто брать $res = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\tSELECT *\n\t\t\tFROM `" . DB_PREFIX . "transactions`\n\t\t\tWHERE `used`=0 AND\n\t\t\t\t\t\t `verified` = 1\n\t\t\t"); $used_transactions = ''; $max_user_id = 0; // т.к. queue_parser_testblock.php пишет в таблы testblock и transactions_testblock нужно локать эти таблы while ($row = $db->fetchArray($res)) { debug_print($row, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); // читаем первый байт, чтобы узнать какого типа транзакция $transaction_type = binary_dec(substr($row['data'], 0, 1)); print 'data=' . $row['data'] . "\n"; print '$transaction_type = ' . $transaction_type . "\n"; // пишем в блок размер транзакции и её саму $length = encode_length(strlen($row['data'])); print '$length=' . $length . "\n"; $transactions .= $length . $row['data']; // заодно получим хэши для общего хэша тр-ий $mrkl_array[] = hash('sha256', hash('sha256', $row['data'])); // все тр-ии блока пишутся в отдельную таблу transaction_testblock. // чтобы другим нодам слать только недостающие тр-ии $md5 = md5($row['data']); list(, $data_hex) = unpack("H*", $row['data']); $file = save_tmp_644('FTT', "{$md5}\t{$data_hex}\t{$row['type']}\t{$row['user_id']}\t{$row['third_var']}"); $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\tLOAD DATA LOCAL INFILE '{$file}'\n\t\t\t\tIGNORE INTO TABLE `" . DB_PREFIX . "transactions_testblock`\n\t\t\t\tFIELDS TERMINATED BY '\t'\n\t\t\t\t(@hash, @data, `type`, `user_id`, `third_var`)\n\t\t\t\tSET `hash` = UNHEX(@hash),\n\t\t\t\t\t `data` = UNHEX(@data)\n\t\t\t\t"); unlink($file); //debug_print($db->printsql(), __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); debug_print('AffectedRows=' . $db->getAffectedRows(), __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); // после обработки транзакции удаляем из БД $used_transactions .= '0x' . bin2hex($row['hash']) . ',';
// разбираем присланные данные $binary_data = $_POST['data']; $add_sql = ''; if ($binary_data) { $tr_array = array(); // получим хэши тр-ий, которые надо исключить do { list(, $tr) = unpack("H*", ParseData::string_shift($binary_data, 16)); // проверим if (!check_input_data($tr, 'md5')) { die('error md5 (' . $tr . ')'); } $add_sql .= $tr . ','; } while ($binary_data); $add_sql = substr($add_sql, 0, -1); $add_sql = "WHERE `id` NOT IN ({$add_sql})"; } // сами тр-ии $transactions = ''; $res = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\tSELECT `data`\n\t\tFROM `" . DB_PREFIX . "transactions_testblock`\n\t\t{$add_sql}\n\t\t"); while ($row = $db->fetchArray($res)) { $length = encode_length(strlen($row['data'])); $transactions .= $length . $row['data']; } $response_binary_data .= encode_length(strlen($transactions)) . $transactions; // порядок тр-ий $res = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\tSELECT `hash`\n\t\tFROM `" . DB_PREFIX . "transactions_testblock`\n\t\tORDER BY `id` ASC\n\t\t"); while ($row = $db->fetchArray($res)) { $response_binary_data .= $row['hash']; } print $response_binary_data;
// т.к. это приведет к попаднию в блок некорректной тр-ии, что приведет к сбою пула if ($data[0] > @$pool_commission[$currency_id][0]) { die($data[0] . ' > ' . @$pool_commission[$currency_id][0]); } if ($data[1] > @$pool_commission[$currency_id][1]) { die($data[1] . ' > ' . @$pool_commission[$currency_id][1]); } } } if (empty($_SESSION['restricted'])) { foreach ($commission_decode as $currency_id => $data) { $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\t\tINSERT INTO `" . DB_PREFIX . MY_PREFIX . "my_commission` (\n\t\t\t\t\t\t\t\t`currency_id`,\n\t\t\t\t\t\t\t\t`pct`,\n\t\t\t\t\t\t\t\t`min`,\n\t\t\t\t\t\t\t\t`max`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tVALUES (\n\t\t\t\t\t\t\t\t{$currency_id},\n\t\t\t\t\t\t\t\t{$data[0]},\n\t\t\t\t\t\t\t\t{$data[1]},\n\t\t\t\t\t\t\t\t{$data[2]}\n\t\t\t\t\t\t\t)\n\t ON DUPLICATE KEY UPDATE `pct`={$data[0]}, `min`={$data[0]}, `max`={$data[0]}\n\t "); //print $db->printsql(); } } $data = dec_binary($type, 1) . dec_binary($time, 4) . encode_length(strlen($user_id)) . $user_id . encode_length(strlen($commission)) . $commission . $bin_signatures; break; case 'change_key_active': $secret = hextobin($_REQUEST['secret']); $data = dec_binary($type, 1) . dec_binary($time, 4) . ParseData::encode_length_plus_data($user_id) . ParseData::encode_length_plus_data($secret) . $bin_signatures; break; case 'change_key_close': $data = dec_binary($type, 1) . dec_binary($time, 4) . ParseData::encode_length_plus_data($user_id) . $bin_signatures; break; case 'change_key_request': $to_user_id = $_REQUEST['to_user_id']; $data = dec_binary($type, 1) . dec_binary($time, 4) . ParseData::encode_length_plus_data($user_id) . ParseData::encode_length_plus_data($to_user_id) . $bin_signatures; break; case 'admin_change_primary_key': $for_user_id = $_REQUEST['for_user_id']; $new_public_key = hextobin($_REQUEST['new_public_key']);
main_lock(); $my_user_id = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\tSELECT `user_id`\n\t\t\t\t\tFROM `" . DB_PREFIX . MY_PREFIX . "my_table`\n\t\t\t\t\t", 'fetch_one'); $node_private_key = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\tSELECT `private_key`\n\t\t\t\t\tFROM `" . DB_PREFIX . MY_PREFIX . "my_node_keys`\n\t\t\t\t\tWHERE `block_id` = (SELECT max(`block_id`) FROM `" . DB_PREFIX . MY_PREFIX . "my_node_keys` )\n\t\t\t\t\t", 'fetch_one'); if (!$my_user_id || !$node_private_key) { main_unlock(); exit; } require_once ABSPATH . 'phpseclib/Math/BigInteger.php'; require_once ABSPATH . 'phpseclib/Crypt/Random.php'; require_once ABSPATH . 'phpseclib/Crypt/Hash.php'; require_once ABSPATH . 'phpseclib/Crypt/RSA.php'; $rsa = new Crypt_RSA(); extract($rsa->createKey(1024)); $publickey = clear_public_key($publickey); $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\tINSERT INTO `" . DB_PREFIX . MY_PREFIX . "my_node_keys` (\n\t\t\t\t`public_key`,\n\t\t\t\t`private_key`\n\t\t\t)\n\t\t\tVALUES (\n\t\t\t\t0x{$publickey},\n\t\t\t\t'{$privatekey}'\n\t\t\t)"); $time = time(); // подписываем нашим нод-ключем данные транзакции $data_for_sign = ParseData::findType('change_node_key') . ",{$time},{$my_user_id},{$publickey}"; $rsa = new Crypt_RSA(); $rsa->loadKey($node_private_key); $rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1); $signature = $rsa->sign($data_for_sign); print '$node_private_key=' . $node_private_key . "\n"; print '$data_for_sign=' . $data_for_sign . "\n"; print 'strlen($signature)=' . strlen($signature) . "\n"; print 'strlen($publickey)=' . strlen($publickey) . "\n"; // создаем новую транзакцию $bin_public_key = hextobin($publickey); $data = dec_binary(ParseData::findType('change_node_key'), 1) . dec_binary($time, 4) . encode_length(strlen($my_user_id)) . $my_user_id . encode_length(strlen($bin_public_key)) . $bin_public_key . encode_length(strlen($signature)) . $signature; insert_tx($data, $db); main_unlock();
function RollbackTo($binary_data, $skip_current = false, $only_front = false) { debug_print("RollbackTo binary_data " . bin2hex($binary_data), __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); if ($only_front) { debug_print('$only_front=true', __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); } if ($binary_data) { // вначале нужно получить размеры всех тр-ий, чтобы пройтись по ним в обратном порядке $bin_for_size = $binary_data; $sizes_arr = array(); do { $transaction_size = $this->decode_length($bin_for_size); if (!$transaction_size) { break; } $sizes_arr[] = $transaction_size; // удалим тр-ию $this->string_shift($bin_for_size, $transaction_size); } while ($bin_for_size); $sizes_arr = array_reverse($sizes_arr); debug_print('$sizes_arr:' . print_r_hex($sizes_arr), __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); for ($i = 0; $i < sizeof($sizes_arr); $i++) { debug_print("RollbackTo binary_data [{$i}]", __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); // обработка тр-ий может занять много времени, нужно отметиться upd_deamon_time($this->db); // отчекрыжим одну транзакцию $transaction_binary_data = $this->string_shift_reverse($binary_data, $sizes_arr[$i]); debug_print("transaction_binary_data = " . $transaction_binary_data, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); $transaction_binary_data_ = $transaction_binary_data; // узнаем кол-во байт, которое занимает размер $size_ = strlen(encode_length($sizes_arr[$i])); // удалим размер $this->string_shift_reverse($binary_data, $size_); $this->tx_hash = md5($transaction_binary_data); $this->transaction_array = $this->parse_transaction($transaction_binary_data); debug_print($this->transaction_array, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); $fns_name = self::$MainArray[$this->transaction_array[1]]; $fns_name_init = $fns_name . '_init'; $fns_name_Rollback = $fns_name . '_rollback'; $fns_name_Rollback_Front = $fns_name . '_rollback_front'; unset($this->tx_data); $this->{$fns_name_init}(); debug_print($this->tx_data, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); // если дошли до тр-ии, которая вызвала ошибку, то откатываем только фронтальную проверку if ($i == 0) { if ($skip_current) { // тр-ия, которая вызвала ошибку закончилась еще до фронт. проверки, т.е. откатывать по ней вообще нечего continue; } // если успели дойти только до половины фронтальной функции if ($this->half_rollback) { $fns_name_Rollback_Front = $fns_name . '_rollback_front_0'; } // откатываем только фронтальную проверку $this->{$fns_name_Rollback_Front}(); } else { if ($only_front) { $this->{$fns_name_Rollback_Front}(); } else { $this->{$fns_name_Rollback_Front}(); $this->{$fns_name_Rollback}(); } } $this->delete_log_tx($transaction_binary_data_); // ===================>ради эксперимента if ($only_front) { $this->db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\t\t\t\t\tUPDATE `" . DB_PREFIX . "transactions`\n\t\t\t\t\t\t\t\t\tSET `verified` = 0\n\t\t\t\t\t\t\t\t\tWHERE `hash` = 0x{$this->tx_hash}\n\t\t\t\t\t\t\t\t\t"); } else { $this->db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\t\t\tUPDATE `" . DB_PREFIX . "transactions`\n\t\t\t\t\t\t\tSET `used` = 0\n\t\t\t\t\t\t\tWHERE `hash` = 0x{$this->tx_hash}\n\t\t\t\t\t\t\t"); } } } }