function CheckBlockHeader() { // инфа о предыдущем блоке (т.е. последнем занесенном) if (!$this->prev_block) { // инфа может быть передана прямо в массиве $this->get_prev_block($this->block_data['block_id'] - 1); } //$this->get_info_block(); убрано, т.к. CheckBlockHeader используется и при сборе новых блоков при вилке // для локальных тестов if ($this->prev_block['block_id'] == 1) { $ini_array = parse_ini_file(ABSPATH . "config.ini", true); if (isset($ini_array['local']['start_block_id'])) { $this->prev_block['block_id'] = $ini_array['local']['start_block_id']; } } debug_print("this->prev_block: " . print_r_hex($this->prev_block), __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); debug_print("this->block_data: " . print_r_hex($this->block_data), __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); // меркель рут нужен для проверки подписи блока, а также проверки лимитов MAX_TX_SIZE и MAX_TX_COUNT if ($this->block_data['block_id'] == 1) { $this->global_variables['max_tx_size'] = 1024 * 1024; $first = true; } else { $first = false; } $this->mrkl_root = self::getMrklroot($this->binary_data, $this->global_variables, $first); // проверим время if (!check_input_data($this->block_data['time'], 'int')) { return 'error time'; } // проверим уровень if (!check_input_data($this->block_data['level'], 'level')) { return 'error level'; } // получим значения для сна $sleep_data = $this->db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\tSELECT `value`\n\t\t\t\t\tFROM `" . DB_PREFIX . "variables`\n\t\t\t\t\tWHERE `name` = 'sleep'\n\t\t\t\t\t", 'fetch_one'); $sleep_data = json_decode($sleep_data, true); debug_print("sleep_data:", __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); //print_R($sleep_data); // узнаем время, которые было затрачено в ожидании is_ready предыдущим блоком $is_ready_sleep = testblock::get_is_ready_sleep($this->prev_block['level'], $sleep_data['is_ready']); // сколько сек должен ждать нод, перед тем, как начать генерить блок, если нашел себя в одном из уровней. $generator_sleep = testblock::get_generator_sleep($this->block_data['level'], $sleep_data['generator']); // сумма is_ready всех предыдущих уровней, которые не успели сгенерить блок $is_ready_sleep2 = testblock::get_is_ready_sleep_sum($this->block_data['level'], $sleep_data['is_ready']); debug_print("is_ready_sleep={$is_ready_sleep}\ngenerator_sleep={$generator_sleep}\nis_ready_sleep2={$is_ready_sleep2}", __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); debug_print('prev_block:' . print_r_hex($this->prev_block), __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); debug_print('block_data:' . print_r_hex($this->block_data), __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); // не слишком ли рано прислан этот блок. допустима погрешность = error_time if (!$first) { if ($this->prev_block['time'] + $is_ready_sleep + $generator_sleep + $is_ready_sleep2 - $this->block_data['time'] > $this->global_variables['error_time']) { return "error block time {$this->prev_block['time']} + {$is_ready_sleep} + {$generator_sleep} + {$is_ready_sleep2} - {$this->block_data['time']} > {$this->global_variables['error_time']}\n"; } } // исключим тех, кто сгенерил блок с бегущими часами if ($this->block_data['time'] > time()) { return "error block time"; } // проверим ID блока if (!check_input_data($this->block_data['block_id'], 'int')) { return 'block_id'; } // проверим, верный ли ID блока if (!$first) { if ($this->block_data['block_id'] != $this->prev_block['block_id'] + 1) { return "error block_id ({$this->block_data['block_id']}!=" . ($this->prev_block['block_id'] + 1) . ")"; } } // проверим, есть ли такой майнер и заодно получим public_key // ================================== my_table заменить =============================================== $this->node_public_key = $this->db->query(__FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__, "\n\t\t\t\t\tSELECT `node_public_key`\n\t\t\t\t\tFROM `" . DB_PREFIX . "miners_data`\n\t\t\t\t\tWHERE `user_id` = {$this->block_data['user_id']}\n\t\t\t\t\tLIMIT 1\n\t\t\t\t\t", 'fetch_one'); if (!$first) { if (!$this->node_public_key) { return 'user_id'; } } // SIGN от 128 байта до 512 байт. Подпись от TYPE, BLOCK_ID, PREV_BLOCK_HASH, TIME, USER_ID, LEVEL, MRKL_ROOT $for_sign = "0,{$this->block_data['block_id']},{$this->prev_block['hash']},{$this->block_data['time']},{$this->block_data['user_id']},{$this->block_data['level']},{$this->mrkl_root}"; debug_print("checkSign", __FILE__, __LINE__, __FUNCTION__, __CLASS__, __METHOD__); // проверяем подпись if (!$first) { $error = self::checkSign($this->node_public_key, $for_sign, $this->block_data['sign'], true); if ($error) { return $error; } } }