Esempio n. 1
0
function clear_incompatible_tx($binary_tx, $db, $my_tx)
{
    $LOG_MARKER = md5($binary_tx);
    $fatal_error = '';
    $wait_error = '';
    $to_user_id = '';
    // получим тип тр-ии и юзера
    list($type, $user_id, $third_var) = get_tx_type_and_user_id($binary_tx);
    if (!check_input_data($type, 'int')) {
        $fatal_error = 'error type';
    }
    if (!check_input_data($user_id, 'int')) {
        $fatal_error = 'error user_id';
    }
    if (!check_input_data($third_var, 'int')) {
        $fatal_error = 'error $third_var';
    }
    if ($type == ParseData::findType('cash_request_out')) {
        $to_user_id = $third_var;
    }
    if ($type == ParseData::findType('new_pct') || $type == ParseData::findType('new_reduction') || $type == ParseData::findType('new_max_promised_amounts') || $type == ParseData::findType('new_max_other_currencies')) {
        //  чтобы никому не слать эту тр-ю
        $for_self_use = 1;
        // $my_tx == true - это значит функция вызвана из pct_generator.php/reduction_generator.php
        // если же false, то она была спаршена query_tx или tesblock_generator и имела verified=0
        // а т.к. new_pct/new_reduction актуальны только 1 блок, то нужно её удалять
        if (!$my_tx) {
            $fatal_error = 'old new_pct/new_reduction/new_max_promised_amounts/new_max_other_currencies';
            $return = array($fatal_error, $wait_error, $for_self_use, $type, $user_id, $to_user_id);
            debug_print($return, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
            return $return;
        }
    } else {
        $for_self_use = 0;
    }
    // две тр-ии одного типа от одного юзера не должны попасть в один блок
    // исключение - перевод DC между юзерами
    if (!$fatal_error) {
        clear_incompatible_tx_sql($db, $type, $user_id, $wait_error);
        // если новая тр-ия - это запрос на удаление или изменение обещанной суммы, то нужно проверить
        // нет ли запросов на получение обещанных сумм к данному юзеру
        // а также, нужно проверить, нет ли от данного юзера тр-ии cash_request_in
        if ($type == ParseData::findType('del_promised_amount') || $type == ParseData::findType('change_promised_amount')) {
            debug_print('если новая тр-ия - это запрос на удаление банкноты, то нужно проверить, нет ли запросов на получение банкнот к данному юзеру, а также, нужно проверить, нет от данного юзера тр-ии cash_request_in', __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
            $num = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\t\tSELECT count(*)\n\t\t\t            FROM (\n\t\t\t\t            SELECT `user_id`\n\t\t\t\t            FROM `" . DB_PREFIX . "transactions`\n\t\t\t\t            WHERE (\n\t\t\t\t                             `third_var` = {$user_id} AND\n\t\t\t\t\t                         `verified`=1 AND\n\t\t\t\t\t                         `used` = 0\n\t\t\t\t\t                      )\n\t\t\t\t                          OR (\n\t\t\t\t\t                          `type` = " . ParseData::findType('cash_request_in') . " AND\n\t\t\t\t\t                          `user_id` = {$user_id}\n\t\t\t\t                         )\n\t\t\t\t\t\t\tUNION\n\t\t\t\t\t\t\tSELECT `user_id`\n\t\t\t\t\t\t\tFROM `" . DB_PREFIX . "transactions_testblock`\n\t\t\t\t\t\t\tWHERE (\n\t\t\t\t\t\t\t\t\t\t\t `third_var` = {$user_id}\n\t\t\t\t\t\t\t\t\t\t) OR (\n\t\t\t\t\t                         `type` = " . ParseData::findType('cash_request_in') . " AND\n\t\t\t\t\t                         `user_id` = {$user_id}\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)  AS `x`\n\t\t\t\t\t\t", 'fetch_one');
            debug_print('$num =' . $num, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
            if ($num) {
                $fatal_error = "`third_var` = {$user_id}";
            }
        }
        // если новая тр-ия - это запрос на получение наличных, то нужно проверить
        // нет ли у получающего юзера запросов на удаление или изменение обещанных сумм
        if ($type == ParseData::findType('cash_request_out')) {
            debug_print('если новая тр-ия - это запрос на получение банкнот, то нужно проверить, нет ли у получающего юзера запросов на удаление банкнот', __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
            $tx_data = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\t\tSELECT *\n\t\t\t            FROM (\n\t\t\t\t            SELECT `data`\n\t\t\t\t            FROM `" . DB_PREFIX . "transactions`\n\t\t\t\t            WHERE `type` IN (" . ParseData::findType('del_promised_amount') . ", " . ParseData::findType('change_promised_amount') . ") AND\n\t\t\t\t                         `user_id` = {$to_user_id} AND\n\t\t\t\t                         `verified`=1 AND\n\t\t\t\t                         `used` = 0\n\t\t\t\t\t\t\tUNION\n\t\t\t\t\t\t\tSELECT `data`\n\t\t\t\t\t\t\tFROM `" . DB_PREFIX . "transactions_testblock`\n\t\t\t\t\t\t\tWHERE `type` IN (" . ParseData::findType('del_promised_amount') . ", " . ParseData::findType('change_promised_amount') . ") AND\n\t\t\t\t\t\t\t\t\t\t `user_id` = {$to_user_id}\n\t\t\t\t\t\t)  AS `x`\n\t\t\t\t\t\t", 'fetch_one');
            debug_print('$tx_data =' . $tx_data, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
            if ($tx_data) {
                // откатим фронтальные записи
                $parsedata = new ParseData(ParseData::encode_length_plus_data($tx_data), $db);
                $parsedata->ParseDataRollbackFront();
                unset($parsedata);
                // Удаляем именно уже записанную тр-ию. При этом новая (cash_request_out) тр-ия успешно обработается
                $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\t\t\tDELETE\n\t\t\t                FROM `" . DB_PREFIX . "transactions`\n\t\t\t                WHERE `hash` = 0x" . md5($tx_data) . "\n\t\t\t\t\t\t\t");
                /*
                				 * создает проблемы для tesblock_is_ready
                				 *
                				 * $db->query( __FILE__, __LINE__,  __FUNCTION__,  __CLASS__, __METHOD__, "
                							DELETE
                			                FROM `".DB_PREFIX."transactions_testblock`
                			                WHERE `hash` = 0x".md5($tx_data)."
                							");*/
            }
        }
        // если новая тр-ия - это запрос на получение банкнот, то нужно проверить
        // нет ли у отправителя запроса на отправку DC, т.к. после списания может не остаться средств
        if ($type == ParseData::findType('cash_request_out')) {
            clear_incompatible_tx_sql_set($db, array('send_dc', 'new_forex_order', 'cf_send_dc'), $user_id, $wait_error);
        }
        // и наоборот
        if (in_array($type, array(ParseData::findType('send_dc'), ParseData::findType('new_forex_order'), ParseData::findType('cf_send_dc')))) {
            clear_incompatible_tx_sql($db, 'cash_request_out', $user_id, $wait_error);
        }
        // на всякий случай не даем попасть в один блок holidays и тр-им, где holidays используются
        if ($type == ParseData::findType('new_holidays')) {
            clear_incompatible_tx_sql($db, 'mining', $user_id, $wait_error);
        }
        if ($type == ParseData::findType('mining')) {
            clear_incompatible_tx_sql($db, 'new_holidays', $user_id, $wait_error);
        }
        if ($type == ParseData::findType('new_holidays')) {
            clear_incompatible_tx_sql($db, 'cash_request_in', $user_id, $wait_error);
        }
        if ($type == ParseData::findType('cash_request_in')) {
            clear_incompatible_tx_sql($db, 'new_holidays', $user_id, $wait_error);
        }
        if ($type == ParseData::findType('cash_request_out')) {
            clear_incompatible_tx_sql($db, 'new_holidays', $to_user_id, $wait_error);
        }
        // не должно попадать в одни блок new_miner_update и new_miner
        if ($type == ParseData::findType('new_miner')) {
            clear_incompatible_tx_sql($db, 'new_miner_update', $user_id, $wait_error);
        }
        if ($type == ParseData::findType('new_miner_update')) {
            clear_incompatible_tx_sql($db, 'new_miner', $user_id, $wait_error);
        }
        // не должно попадать в один блок смена нодовского ключа и тр-ии которые этим ключем подписываются
        if ($type == ParseData::findType('change_node_key') || $type == ParseData::findType('new_miner')) {
            clear_incompatible_tx_sql($db, 'new_miner_update', $user_id, $wait_error);
        }
        if ($type == ParseData::findType('change_node_key') || $type == ParseData::findType('new_miner')) {
            clear_incompatible_tx_sql($db, 'new_pct', $user_id, $wait_error);
        }
        if ($type == ParseData::findType('new_miner_update')) {
            clear_incompatible_tx_sql_set($db, array('change_node_key', 'new_miner'), $user_id, $wait_error);
        }
        if ($type == ParseData::findType('new_pct')) {
            clear_incompatible_tx_sql_set($db, array('change_node_key', 'new_miner'), $user_id, $wait_error);
        }
        if ($type == ParseData::findType('change_node_key') || $type == ParseData::findType('new_miner')) {
            clear_incompatible_tx_sql($db, 'new_reduction', $user_id, $wait_error);
        }
        // восстановление ключа
        if ($type == ParseData::findType('change_key_request')) {
            clear_incompatible_tx_sql_set($db, array('change_key_active'), $third_var, $wait_error);
        }
        if ($type == ParseData::findType('change_key_active')) {
            clear_incompatible_tx_sql_set($db, array('change_key_request'), 0, $wait_error, $user_id);
        }
        // нельзя удалить/изменить обещанную сумму и затем создать запрос на её майнинг
        if ($type == ParseData::findType('mining')) {
            clear_incompatible_tx_sql_set($db, array('del_promised_amount', 'change_promised_amount'), $user_id, $wait_error);
        }
        if (in_array($type, array(ParseData::findType('del_promised_amount'), ParseData::findType('change_promised_amount')))) {
            clear_incompatible_tx_sql($db, 'mining', $user_id, $wait_error);
        }
        // в 1 блоке только 1 майнинг от юзера
        if ($type == ParseData::findType('mining')) {
            clear_incompatible_tx_sql($db, 'mining', $user_id, $wait_error);
        }
        if ($type == ParseData::findType('mining')) {
            clear_incompatible_tx_sql($db, 'admin_ban_miners', 0, $wait_error);
        }
        if ($type == ParseData::findType('cash_request_out')) {
            clear_incompatible_tx_sql($db, 'admin_ban_miners', 0, $wait_error);
        }
        if ($type == ParseData::findType('new_promised_amount')) {
            clear_incompatible_tx_sql($db, 'admin_ban_miners', 0, $wait_error);
        }
        if ($type == ParseData::findType('admin_ban_miners')) {
            rollback_incompatible_tx(array('cash_request_out', 'change_host', 'new_promised_amount', 'change_node_key', 'new_pct', 'mining', 'votes_miner', 'votes_node_new_miner', 'votes_promised_amount', 'abuses', 'new_promised_amount', 'votes_complex'), 0, $wait_error);
        }
        if ($type == ParseData::findType('votes_miner')) {
            clear_incompatible_tx_sql_set($db, array('admin_ban_miners'), 0, $wait_error);
        }
        if ($type == ParseData::findType('votes_complex')) {
            clear_incompatible_tx_sql_set($db, array('admin_ban_miners'), 0, $wait_error);
        }
        if ($type == ParseData::findType('abuses')) {
            // admin_ban_miners преоритетнее, abuses надо вытеснять
            clear_incompatible_tx_sql_set($db, array('admin_ban_miners'), 0, $wait_error);
        }
        // дополнить
        if ($type == ParseData::findType('votes_node_new_miner')) {
            clear_incompatible_tx_sql_set($db, array('admin_ban_miners'), 0, $wait_error);
        }
        if ($type == ParseData::findType('votes_promised_amount')) {
            clear_incompatible_tx_sql_set($db, array('admin_ban_miners'), 0, $wait_error);
        }
        // нельзя голосовать за обещанную сумму юзера $promised_amount_user_id, если он меняет свое местоположение, т.к. сменится статус
        if ($type == ParseData::findType('votes_promised_amount')) {
            $promised_amount_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 . "promised_amount`\n\t\t\t\t\tWHERE  `id` = {$third_var}\n\t\t\t\t\tLIMIT 1\n\t\t\t\t\t", 'fetch_one');
            if ($promised_amount_user_id) {
                clear_incompatible_tx_sql_set($db, array('change_geolocation'), $promised_amount_user_id, $wait_error);
            }
        }
        // нельзя менять местоположение, если кто-то отдал голос за мою обещанную сумму
        if ($type == ParseData::findType('change_geolocation')) {
            $promised_amount_ids = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\tSELECT `id`\n\t\t\t\t\tFROM `" . DB_PREFIX . "promised_amount`\n\t\t\t\t\tWHERE  `user_id` = {$user_id}\n\t\t\t\t\t", 'array');
            $promised_amount_ids = implode(',', $promised_amount_ids);
            if ($promised_amount_ids) {
                $num = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\t\tSELECT count(*)\n\t\t\t\t\t\t    FROM (\n\t\t\t\t\t\t        SELECT `user_id`\n\t\t\t\t\t\t        FROM `" . DB_PREFIX . "transactions`\n\t\t\t\t\t\t        WHERE  (\n\t\t\t\t\t\t                        `type` = " . ParseData::findType('votes_promised_amount') . " AND `third_var` IN ({$promised_amount_ids})\n\t\t\t\t\t\t                      ) AND\n\t\t\t\t\t\t                     `verified`=1 AND\n\t\t\t\t\t\t                     `used` = 0\n\t\t\t\t\t\t\t\tUNION\n\t\t\t\t\t\t\t\tSELECT `user_id`\n\t\t\t\t\t\t\t\tFROM `" . DB_PREFIX . "transactions_testblock`\n\t\t\t\t\t\t\t\tWHERE  (\n\t\t\t\t\t\t                        `type` = " . ParseData::findType('votes_promised_amount') . " AND `third_var` IN ({$promised_amount_ids})\n\t\t\t\t\t\t                      )\n\t\t\t\t\t\t\t)  AS `x`\n\t\t\t\t\t\t", 'fetch_one');
                if ($num) {
                    $wait_error = 'votes_promised_amount change_geolocation';
                }
            }
        }
        // нельзя удалять CF-проект и в этом же блоке изменить его описание/профинансировать
        if ($type == ParseData::findType('del_cf_project')) {
            clear_incompatible_tx_sql_set($db, array('cf_comment', 'cf_send_dc', 'cf_project_change_category', 'cf_project_data'), 0, $wait_error, $third_var);
        }
        if (in_array($type, array(ParseData::findType('cf_comment'), ParseData::findType('cf_send_dc'), ParseData::findType('cf_project_change_category'), ParseData::findType('cf_project_data')))) {
            clear_incompatible_tx_sql_set($db, array('del_cf_project'), 0, $wait_error, $third_var);
        }
        // потом нужно сделать более тонко. но пока так. Если есть удаление проекта, тогда откатываем все тр-ии del_cf_funding
        if ($type == ParseData::findType('del_cf_project')) {
            rollback_incompatible_tx(array('del_cf_funding'));
        }
        // потом нужно сделать более тонко. но пока так. Если есть del_cf_funding, тогда откатываем все тр-ии удаления проектов
        if ($type == ParseData::findType('del_cf_funding')) {
            rollback_incompatible_tx(array('del_cf_project'));
        }
        // потом нужно сделать более тонко. но пока так. Если есть смена комиссии, то нельзя отправлять тр-ии, где указана комиссия
        if (in_array($type, array(ParseData::findType('cf_send_dc'), ParseData::findType('send_dc'), ParseData::findType('new_forex_order')))) {
            rollback_incompatible_tx(array('change_commission'));
        }
        if ($type == ParseData::findType('change_commission')) {
            clear_incompatible_tx_sql_set($db, array('cf_send_dc', 'send_dc', 'new_forex_order'), 0, $wait_error);
        }
        // Если есть смена коммиссий арбитров, то нельзя делать перевод монет, т.к. там может быть указана комиссия арбитра
        if (in_array($type, array(ParseData::findType('send_dc')))) {
            rollback_incompatible_tx(array('change_arbitrator_conditions'));
        }
        if ($type == ParseData::findType('change_arbitrator_conditions')) {
            clear_incompatible_tx_sql_set($db, array('send_dc'), 0, $wait_error);
        }
        // если идет смена списка арбитров, то у отправителя и у получателя может получиться нестыковка
        if (in_array($type, array(ParseData::findType('send_dc')))) {
            rollback_incompatible_tx(array('change_arbitrator_list'));
        }
        if ($type == ParseData::findType('change_arbitrator_list')) {
            clear_incompatible_tx_sql_set($db, array('send_dc'), 0, $wait_error);
        }
        // на всякий случай не даем попасть в один блок тр-ии отправки в CF-проект монет и другим тр-ям связанным с этим CF-проектом. Т.к. проект может завершиться и 2-я тр-я вызовет ошибку
        if ($type == ParseData::findType('cf_send_dc')) {
            clear_incompatible_tx_sql_set($db, array('cf_send_dc', 'cf_comment', 'del_cf_project', 'cf_project_change_category', 'cf_project_data'), 0, $wait_error, $third_var);
        }
        if (in_array($type, array(ParseData::findType('cf_send_dc'), ParseData::findType('cf_comment'), ParseData::findType('del_cf_project'), ParseData::findType('cf_project_change_category'), ParseData::findType('cf_project_data')))) {
            clear_incompatible_tx_sql_set($db, array('cf_send_dc'), 0, $wait_error, $third_var);
        }
        // нельзя удалять promised_amount и голосовать за него
        if ($type == ParseData::findType('del_promised_amount')) {
            clear_incompatible_tx_sql_set($db, array('votes_promised_amount'), 0, $wait_error, $third_var);
        }
        if ($type == ParseData::findType('votes_promised_amount')) {
            clear_incompatible_tx_sql_set($db, array('del_promised_amount'), 0, $wait_error, $third_var);
        }
        if ($type == ParseData::findType('new_max_promised_amounts')) {
            clear_incompatible_tx_sql_set($db, array('new_max_promised_amounts'), 0, $wait_error, $third_var);
        }
        if ($type == ParseData::findType('new_max_other_currencies')) {
            clear_incompatible_tx_sql_set($db, array('new_max_other_currencies'), 0, $wait_error, $third_var);
        }
        if ($type == ParseData::findType('new_pct')) {
            clear_incompatible_tx_sql_set($db, array('new_pct'), 0, $wait_error, $third_var);
        }
        if ($type == ParseData::findType('new_reductions')) {
            clear_incompatible_tx_sql_set($db, array('new_reductions'), 0, $wait_error, $third_var);
        }
        // в один блок должен попасть только один голос за один объект голосования. $third_var - объект голосования
        if (in_array($type, array(ParseData::findType('votes_promised_amount'), ParseData::findType('votes_miner'), ParseData::findType('votes_node_new_miner'), ParseData::findType('votes_complex')))) {
            $num = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\t\tSELECT count(*)\n\t\t\t\t            FROM (\n\t\t\t\t\t            SELECT `user_id`\n\t\t\t\t\t            FROM `" . DB_PREFIX . "transactions`\n\t\t\t\t\t            WHERE  `type` IN (" . ParseData::findType('votes_promised_amount') . ", " . ParseData::findType('votes_miner') . ", " . ParseData::findType('votes_node_new_miner') . ", " . ParseData::findType('votes_complex') . ") AND\n\t\t\t\t\t                          `third_var` = {$third_var} AND\n\t\t\t\t\t                          `verified`=1 AND\n\t\t\t\t\t                          `used` = 0\n\t\t\t\t\t\t\t\tUNION\n\t\t\t\t\t\t\t\tSELECT `user_id`\n\t\t\t\t\t\t\t\tFROM `" . DB_PREFIX . "transactions_testblock`\n\t\t\t\t\t\t\t\tWHERE `type` IN (" . ParseData::findType('votes_promised_amount') . ", " . ParseData::findType('votes_miner') . ", " . ParseData::findType('votes_node_new_miner') . ", " . ParseData::findType('votes_complex') . ") AND\n\t\t\t\t\t                          `third_var` = {$third_var}\n\t\t\t\t\t\t\t)  AS `x`\n\t\t\t\t\t\t", 'fetch_one');
            debug_print('$num =' . $num, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
            if ($num) {
                $wait_error = 'only 1 vote';
            }
        }
        // если новая тр-ия - это запрос, в котором юзер отдает наличные (cash_request_in)
        // то нужно проверить, не хочет ли юзер удалить или изменить одну из обещанных сумм
        if ($type == ParseData::findType('cash_request_in')) {
            debug_print('если новая тр-ия - это запрос, в котором юзер отдает банкноты (cash_request_in), то нужно проверить, не хочет ли юзер удалить одну из передаваемых банкнот', __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
            $tx_data = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\t\tSELECT *\n\t\t\t            FROM (\n\t\t\t\t            SELECT `data`\n\t\t\t\t            FROM `" . DB_PREFIX . "transactions`\n\t\t\t\t            WHERE `type` IN (" . ParseData::findType('del_promised_amount') . ", " . ParseData::findType('change_promised_amount') . ") AND\n\t\t\t\t                         `user_id` = {$user_id} AND\n\t\t\t\t                         `verified`=1 AND\n\t\t\t\t                         `used` = 0\n\t\t\t\t\t\t\tUNION\n\t\t\t\t\t\t\tSELECT `data`\n\t\t\t\t\t\t\tFROM `" . DB_PREFIX . "transactions_testblock`\n\t\t\t\t\t\t\tWHERE `type` IN (" . ParseData::findType('del_promised_amount') . ", " . ParseData::findType('change_promised_amount') . ") AND\n\t\t\t\t\t\t\t\t\t\t `user_id` = {$user_id}\n\t\t\t\t\t\t)  AS `x`\n\t\t\t\t\t\t", 'fetch_one');
            debug_print('$tx_data =' . $tx_data, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
            if ($tx_data) {
                // откатим фронтальные записи
                $parsedata = new ParseData(ParseData::encode_length_plus_data($tx_data), $db);
                $parsedata->ParseDataRollbackFront();
                unset($parsedata);
                // Удаляем именно уже записанную тр-ию. При этом новая (cash_request_in) тр-ия успешно обработается
                $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\t\t\tDELETE\n\t\t\t                FROM `" . DB_PREFIX . "transactions`\n\t\t\t                WHERE `hash` = 0x" . md5($tx_data) . "\n\t\t\t\t\t\t\t");
                /*
                 * создает проблемы для tesblock_is_ready
                 *
                $db->query( __FILE__, __LINE__,  __FUNCTION__,  __CLASS__, __METHOD__, "
                			DELETE
                			                FROM `".DB_PREFIX."transactions_testblock`
                			                WHERE `hash` = 0x".md5($tx_data)."
                			");
                */
            }
        }
        if ($type == ParseData::findType('change_primary_key')) {
            debug_print('если новая тр-я - это смена праймари ключа, то не должно быть никаких других тр-ий от этого юзера', __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
            $num = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\t\tSELECT count(*)\n\t\t\t\t            FROM (\n\t\t\t\t\t            SELECT `user_id`\n\t\t\t\t\t            FROM `" . DB_PREFIX . "transactions`\n\t\t\t\t\t            WHERE  `user_id` = {$user_id} AND\n\t\t\t\t\t                         `verified`=1 AND\n\t\t\t\t\t                         `used` = 0\n\t\t\t\t\t\t\t\tUNION\n\t\t\t\t\t\t\t\tSELECT `user_id`\n\t\t\t\t\t\t\t\tFROM `" . DB_PREFIX . "transactions_testblock`\n\t\t\t\t\t\t\t\tWHERE `user_id` = {$user_id}\n\t\t\t\t\t\t\t)  AS `x`\n\t\t\t\t\t\t", 'fetch_one');
            debug_print('$num =' . $num, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
            if ($num) {
                $wait_error = 'there are other tr-s';
            }
        }
        if ($type == ParseData::findType('admin_change_primary_key')) {
            debug_print('если новая тр-я - это смена праймари ключа, то не должно быть никаких других тр-ий от юзера, которому меняем ключ', __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
            $num = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\t\tSELECT count(*)\n\t\t\t\t            FROM (\n\t\t\t\t\t            SELECT `user_id`\n\t\t\t\t\t            FROM `" . DB_PREFIX . "transactions`\n\t\t\t\t\t            WHERE  `user_id` = {$third_var} AND\n\t\t\t\t\t                         `verified`=1 AND\n\t\t\t\t\t                         `used` = 0\n\t\t\t\t\t\t\t\tUNION\n\t\t\t\t\t\t\t\tSELECT `user_id`\n\t\t\t\t\t\t\t\tFROM `" . DB_PREFIX . "transactions_testblock`\n\t\t\t\t\t\t\t\tWHERE `user_id` = {$third_var}\n\t\t\t\t\t\t\t)  AS `x`\n\t\t\t\t\t\t", 'fetch_one');
            debug_print('$num =' . $num, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
            if ($num) {
                $wait_error = 'there are other tr-s';
            }
        }
        // любая тр-я от юзера не должна проходить, если уже есть тр-я со сменой праймари ключа или new_pct или new_reduction
        $num = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\t\tSELECT count(*)\n\t\t\t\t            FROM (\n\t\t\t\t\t            SELECT `user_id`\n\t\t\t\t\t            FROM `" . DB_PREFIX . "transactions`\n\t\t\t\t\t            WHERE  (\n\t\t\t\t\t\t                            (`type` = " . ParseData::findType('change_primary_key') . " AND `user_id` = {$user_id})\n\t\t\t\t\t\t                            OR\n\t\t\t\t\t\t                            (type IN (" . ParseData::findType('new_pct') . ", " . ParseData::findType('new_reduction') . ") )\n\t\t\t\t\t                          ) AND\n\t\t\t\t\t                         `verified`=1 AND\n\t\t\t\t\t                         `used` = 0\n\t\t\t\t\t\t\t\tUNION\n\t\t\t\t\t\t\t\tSELECT `user_id`\n\t\t\t\t\t\t\t\tFROM `" . DB_PREFIX . "transactions_testblock`\n\t\t\t\t\t\t\t\tWHERE  (\n\t\t\t\t\t\t                            (`type` = " . ParseData::findType('change_primary_key') . " AND `user_id` = {$user_id})\n\t\t\t\t\t\t                            OR\n\t\t\t\t\t\t                            (type IN (" . ParseData::findType('new_pct') . ", " . ParseData::findType('new_reduction') . ") )\n\t\t\t\t\t                          )\n\t\t\t\t\t\t\t)  AS `x`\n\t\t\t\t\t\t", 'fetch_one');
        debug_print('$num =' . $num, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
        if ($num) {
            $wait_error = 'have change_primary_key tx';
        }
        // если пришло new_pct, то нужно откатить следующие тр-ии
        if ($type == ParseData::findType('new_pct')) {
            rollback_incompatible_tx(array('new_reduction', 'change_node_key', 'new_miner', 'votes_promised_amount', 'send_dc', 'cash_request_in', 'mining', 'cf_send_dc', 'del_cf_project', 'new_forex_order', 'del_forex_order', 'for_repaid_fix', 'actualization_promised_amounts', 'del_cf_funding', 'admin_unban_miners', 'admin_ban_miners'));
        }
        // если пришло new_reduction, то нужно откатить следующие тр-ии
        if ($type == ParseData::findType('new_reduction')) {
            rollback_incompatible_tx(array('new_pct', 'change_node_key', 'new_miner', 'votes_promised_amount', 'send_dc', 'cash_request_in', 'mining', 'cf_send_dc', 'del_cf_project', 'new_forex_order', 'del_forex_order', 'for_repaid_fix', 'actualization_promised_amounts', 'del_cf_funding', 'admin_unban_miners', 'admin_ban_miners'));
        }
        // временно запрещаем 2 тр-ии любого типа от одного юзера, а то затрахался уже.
        $num = $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\tSELECT count(*)\n\t\t\t\t    FROM (\n\t\t\t\t\t\t\tSELECT `user_id`\n\t\t\t\t\t\t\tFROM `" . DB_PREFIX . "transactions`\n\t\t\t\t\t\t\tWHERE  `user_id` = {$user_id} AND\n\t\t\t\t                      `verified`=1 AND\n\t\t\t\t                      `used` = 0\n\t\t\t\t\t\t\tUNION\n\t\t\t\t\t\t\tSELECT `user_id`\n\t\t\t\t\t\t\tFROM `" . DB_PREFIX . "transactions_testblock`\n\t\t\t\t\t\t\tWHERE `user_id` = {$user_id}\n\t\t\t\t\t)  AS `x`\n\t\t\t\t", 'fetch_one');
        debug_print('$num =' . $num, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
        if ($num) {
            $wait_error = 'only 1 tx';
        }
    }
    if ($fatal_error) {
        debug_print('fatal[error] ==' . $fatal_error, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
    }
    if ($wait_error) {
        debug_print('wait[error] ==' . $wait_error, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
    }
    $return = array($fatal_error, $wait_error, $for_self_use, $type, $user_id, $third_var);
    debug_print($return, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
    return $return;
}
Esempio n. 2
0
 // наши тр-ии уже не актуальны, т.к. мы их откатили
 $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\tTRUNCATE TABLE `" . DB_PREFIX . "transactions_testblock`\n\t\t\t\t");
 // если всё нормально, то пишем в таблу testblock новые тр-ии и новые данные по юзеру их сгенерившему
 $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\tUPDATE `" . DB_PREFIX . "testblock`\n\t\t\t\tSET  `time` = {$parsedata->block_data['time']},\n\t\t\t\t\t\t`user_id` = {$parsedata->block_data['user_id']},\n\t\t\t\t\t\t`header_hash` = 0x{$new_header_hash},\n\t\t\t\t\t\t`signature` = 0x" . bin2hex($parsedata->block_data['sign']) . ",\n\t\t\t\t\t\t`mrkl_root` = 0x{$parsedata->mrkl_root}\n\t\t\t\t");
 ////debug_print($db->printsql()."\nAffectedRows=".$db->getAffectedRows() , __FILE__, __LINE__,  __FUNCTION__,  __CLASS__, __METHOD__);
 // и сами тр-ии пишем в отдельную таблу
 if ($tx) {
     do {
         debug_print('$tx=' . $tx, __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
         debug_print('$tx hex=' . bin2hex($tx), __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__);
         $tx_size = ParseData::decode_length($tx);
         // отчекрыжим одну транзакцию от списка транзакций
         $tx_binary_data = ParseData::string_shift($tx, $tx_size);
         // получим тип тр-ии и юзера
         // $type, $user_id, $to_user_id точно валидные, т.к. прошли фронт.проверку выше
         list($type, $user_id, $to_user_id) = get_tx_type_and_user_id($tx_binary_data);
         $md5 = md5($tx_binary_data);
         list(, $data_hex) = unpack("H*", $tx_binary_data);
         $file = save_tmp_644('FTT', "{$md5}\t{$data_hex}\t{$type}\t{$user_id}\t{$to_user_id}");
         $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\t\tLOAD DATA LOCAL INFILE  '{$file}'\n\t\t\t\t\t\tREPLACE INTO TABLE `" . DB_PREFIX . "transactions_testblock`\n\t\t\t\t\t\tFIELDS TERMINATED BY '\t'\n\t\t\t\t\t\t(@hash, @data, `type`, `user_id`, `third_var`)\n\t\t\t\t\t\tSET `hash` = UNHEX(@hash),\n\t\t\t\t\t\t\t   `data` = UNHEX(@data)\n\t\t\t\t\t\t");
         unlink($file);
         ////debug_print($db->printsql()."\nAffectedRows=".$db->getAffectedRows() , __FILE__, __LINE__,  __FUNCTION__,  __CLASS__, __METHOD__);
     } while ($tx);
 }
 // удаляем всё, где хэш больше нашего
 $db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\tDELETE FROM `" . DB_PREFIX . "queue_testblock`\n\t\t\t\tWHERE `head_hash` > 0x{$new_header_hash}\n\t\t");
 ////debug_print($db->printsql()."\nAffectedRows=".$db->getAffectedRows() , __FILE__, __LINE__,  __FUNCTION__,  __CLASS__, __METHOD__);
 #############################################
 // возможно нужно откатить и тр-ии с verified=1 и used=0 из transactions
 // т.к. в transactions может быть тр-ия на удаление банкноты
 // и в transactions_testblock только что была залита такая же тр-ия