(std::move(data), true);
  if (F.is_error()) {
    abort_query(F.move_as_error());
    return;
  }
  auto f = F.move_as_ok();
  state_proof_ = std::move(f->state_proof_);
  config_proof_ = std::move(f->config_proof_);
  finish_query();
}
void HttpQueryConfig::finish_query() {
  if (promise_) {
    auto page = [&]() -> std::string {
      HttpAnswer A{"config", prefix_};
      A.set_block_id(block_id_);
      auto R = block::check_extract_state_proof(block_id_, state_proof_.as_slice(), config_proof_.as_slice());
      if (R.is_error()) {
        A.abort(PSTRING() << "masterchain state proof for " << block_id_.to_str()
                          << " is invalid : " << R.move_as_error());
        return A.finish();
      }
      try {
        auto res = block::Config::extract_from_state(R.move_as_ok(), 0);
        if (res.is_error()) {
          A.abort(PSTRING() << "cannot unpack configuration: " << res.move_as_error());
          return A.finish();
        }
        auto config = res.move_as_ok();
        if (params_.size() > 0) {
          A << "params: ";
          for (int i : params_) {
            auto value = config->get_config_param(i);
            if (value.not_null()) {
              A << "" << i << " ";
            }
          }
          A << "
";
          for (int i : params_) {
            auto value = config->get_config_param(i);
            if (value.not_null()) {
              A << HttpAnswer::ConfigParam{i, value};
            } else {
              A << HttpAnswer::Error{td::Status::Error(404, PSTRING() << "empty param " << i)};
            }
          }
        } else {
          A << "params: ";
          config->foreach_config_param([&](int i, td::Ref value) {
            if (value.not_null()) {
              A << "" << i << " ";
            }
            return true;
          });
          A << "
";
          config->foreach_config_param([&](int i, td::Ref value) {
            if (value.not_null()) {
              A << HttpAnswer::ConfigParam{i, value};
            }
            return true;
          });
        }
      } catch (vm::VmError &err) {
        A.abort(PSTRING() << "error while traversing configuration: " << err.get_msg());
      } catch (vm::VmVirtError &err) {
        A.abort(PSTRING() << "virtualization error while traversing configuration: " << err.get_msg());
      }
      return A.finish();
    }();
    auto R = MHD_create_response_from_buffer(page.length(), const_cast(page.c_str()), MHD_RESPMEM_MUST_COPY);
    MHD_add_response_header(R, "Content-Type", "text/html");
    promise_.set_value(std::move(R));
  }
  stop();
}
HttpQuerySendForm::HttpQuerySendForm(std::string prefix, td::Promise promise)
    : HttpQueryCommon(prefix, std::move(promise)) {
}
HttpQuerySendForm::HttpQuerySendForm(std::map opts, std::string prefix,
                                     td::Promise promise)
    : HttpQueryCommon(prefix, std::move(promise)) {
}
void HttpQuerySendForm::start_up() {
  finish_query();
}
void HttpQuerySendForm::finish_query() {
  if (promise_) {
    auto page = [&]() -> std::string {
      HttpAnswer A{"send", prefix_};
      A << "";
      return A.finish();
    }();
    auto R = MHD_create_response_from_buffer(page.length(), const_cast(page.c_str()), MHD_RESPMEM_MUST_COPY);
    MHD_add_response_header(R, "Content-Type", "text/html");
    promise_.set_value(std::move(R));
  }
  stop();
}
HttpQuerySend::HttpQuerySend(std::string prefix, td::BufferSlice data, td::Promise promise)
    : HttpQueryCommon(prefix, std::move(promise)), data_(std::move(data)) {
}
HttpQuerySend::HttpQuerySend(std::map opts, std::string prefix,
                             td::Promise promise)
    : HttpQueryCommon(prefix, std::move(promise)) {
  auto it = opts.find("filedata");
  if (it != opts.end()) {
    data_ = td::BufferSlice{it->second};
  } else {
    error_ = td::Status::Error("no file data");
    return;
  }
}
void HttpQuerySend::start_up() {
  if (error_.is_error()) {
    abort_query(std::move(error_));
    return;
  }
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result R) {
    if (R.is_error()) {
      td::actor::send_closure(SelfId, &HttpQuerySend::abort_query, R.move_as_error());
    } else {
      td::actor::send_closure(SelfId, &HttpQuerySend::got_result, R.move_as_ok());
    }
  });
  auto query =
      ton::serialize_tl_object(ton::create_tl_object(std::move(data_)), true);
  td::actor::send_closure(CoreActorInterface::instance_actor_id(), &CoreActorInterface::send_lite_query,
                          std::move(query), std::move(P));
}
void HttpQuerySend::got_result(td::BufferSlice data) {
  auto F = ton::fetch_tl_object(std::move(data), true);
  if (F.is_error()) {
    abort_query(F.move_as_error());
  } else {
    status_ = F.move_as_ok()->status_;
  }
  finish_query();
}
void HttpQuerySend::finish_query() {
  if (promise_) {
    auto page = [&]() -> std::string {
      HttpAnswer A{"send", prefix_};
      if (status_ >= 0) {
        A << HttpAnswer::Notification{"success"};
      } else {
        A << HttpAnswer::Error{td::Status::Error(status_, "failed")};
      }
      return A.finish();
    }();
    auto R = MHD_create_response_from_buffer(page.length(), const_cast(page.c_str()), MHD_RESPMEM_MUST_COPY);
    MHD_add_response_header(R, "Content-Type", "text/html");
    promise_.set_value(std::move(R));
  }
  stop();
}
HttpQueryRunMethod::HttpQueryRunMethod(ton::BlockIdExt block_id, block::StdAddress addr, std::string method_name,
                                       std::vector params, std::string prefix,
                                       td::Promise promise)
    : HttpQueryCommon(std::move(prefix), std::move(promise))
    , block_id_(block_id)
    , addr_(addr)
    , method_name_(std::move(method_name))
    , params_(std::move(params)) {
}
HttpQueryRunMethod::HttpQueryRunMethod(std::map opts, std::string prefix,
                                       td::Promise promise)
    : HttpQueryCommon(std::move(prefix), std::move(promise)) {
  auto R = parse_block_id(opts, true);
  if (R.is_ok()) {
    block_id_ = R.move_as_ok();
    if (!block_id_.is_valid()) {
      block_id_.id.workchain = ton::masterchainId;
      block_id_.id.shard = ton::shardIdAll;
      block_id_.id.seqno = static_cast(0xffffffff);
      block_id_.root_hash.set_zero();
      block_id_.file_hash.set_zero();
    }
  } else {
    error_ = R.move_as_error();
    return;
  }
  auto R2 = parse_account_addr(opts);
  if (R2.is_ok()) {
    addr_ = R2.move_as_ok();
  } else {
    error_ = R2.move_as_error();
    return;
  }
  auto it = opts.find("method");
  if (it == opts.end()) {
    error_ = td::Status::Error("no method");
    return;
  } else {
    method_name_ = it->second;
  }
  it = opts.find("params");
  if (it != opts.end()) {
    auto R3 = vm::parse_stack_entries(it->second);
    if (R3.is_error()) {
      error_ = R3.move_as_error();
      return;
    }
    params_ = R3.move_as_ok();
  }
}
void HttpQueryRunMethod::start_up_query() {
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result R) {
    if (R.is_error()) {
      td::actor::send_closure(SelfId, &HttpQueryRunMethod::abort_query, R.move_as_error_prefix("litequery failed: "));
    } else {
      td::actor::send_closure(SelfId, &HttpQueryRunMethod::got_result, R.move_as_ok());
    }
  });
  auto a = ton::create_tl_object(addr_.workchain, addr_.addr);
  td::int64 method_id = (td::crc16(td::Slice{method_name_}) & 0xffff) | 0x10000;
  // serialize params
  vm::CellBuilder cb;
  td::Ref cell;
  if (!(vm::Stack{params_}.serialize(cb) && cb.finalize_to(cell))) {
    return abort_query(td::Status::Error("cannot serialize stack with get-method parameters"));
  }
  auto params_serialized = vm::std_boc_serialize(std::move(cell));
  if (params_serialized.is_error()) {
    return abort_query(params_serialized.move_as_error_prefix("cannot serialize stack with get-method parameters : "));
  }
  auto query = ton::serialize_tl_object(
      ton::create_tl_object(
          0x17, ton::create_tl_lite_block_id(block_id_), std::move(a), method_id, params_serialized.move_as_ok()),
      true);
  td::actor::send_closure(CoreActorInterface::instance_actor_id(), &CoreActorInterface::send_lite_query,
                          std::move(query), std::move(P));
}
void HttpQueryRunMethod::got_result(td::BufferSlice data) {
  auto F = ton::fetch_tl_object(std::move(data), true);
  if (F.is_error()) {
    return abort_query(F.move_as_error());
  }
  auto f = F.move_as_ok();
  auto page = [&]() -> std::string {
    HttpAnswer A{"account", prefix_};
    A.set_account_id(addr_);
    A.set_block_id(ton::create_block_id(f->id_));
    if (f->exit_code_ != 0) {
      A.abort(PSTRING() << "VM terminated with error code " << f->exit_code_);
      return A.finish();
    }
    std::ostringstream os;
    os << "result: ";
    if (f->result_.empty()) {
      os << "";
    } else {
      auto r_cell = vm::std_boc_deserialize(f->result_);
      if (r_cell.is_error()) {
        A.abort(PSTRING() << "cannot deserialize VM result boc: " << r_cell.move_as_error());
        return A.finish();
      }
      auto cs = vm::load_cell_slice(r_cell.move_as_ok());
      td::Ref stack;
      if (!(vm::Stack::deserialize_to(cs, stack, 0) && cs.empty_ext())) {
        A.abort("VM result boc cannot be deserialized");
        return A.finish();
      }
      stack->dump(os, 3);
    }
    A << HttpAnswer::CodeBlock{os.str()};
    return A.finish();
  }();
  auto R = MHD_create_response_from_buffer(page.length(), const_cast(page.c_str()), MHD_RESPMEM_MUST_COPY);
  MHD_add_response_header(R, "Content-Type", "text/html");
  promise_.set_value(std::move(R));
  stop();
}
HttpQueryStatus::HttpQueryStatus(std::string prefix, td::Promise promise)
    : HttpQueryCommon(std::move(prefix), std::move(promise)) {
}
HttpQueryStatus::HttpQueryStatus(std::map opts, std::string prefix,
                                 td::Promise promise)
    : HttpQueryCommon(std::move(prefix), std::move(promise)) {
}
void HttpQueryStatus::start_up() {
  if (error_.is_error()) {
    abort_query(std::move(error_));
    return;
  }
  auto P =
      td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result R) {
        if (R.is_error()) {
          td::actor::send_closure(SelfId, &HttpQueryStatus::abort_query, R.move_as_error());
        } else {
          td::actor::send_closure(SelfId, &HttpQueryStatus::got_results, R.move_as_ok());
        }
      });
  td::actor::send_closure(CoreActorInterface::instance_actor_id(), &CoreActorInterface::get_results, 60, std::move(P));
}
void HttpQueryStatus::got_results(CoreActorInterface::RemoteNodeStatusList results) {
  results_ = std::move(results);
  finish_query();
}
void HttpQueryStatus::finish_query() {
  if (promise_) {
    auto page = [&]() -> std::string {
      std::map> m;
      HttpAnswer A{"status", prefix_};
      A << "\n"
        << "
\n"
        << "| ip";
      for (auto &x : results_.results) {
        A << " | " << static_cast(x->ts_.at_unix()) << "";
      }
      A << " | 
\n";
      for (td::uint32 i = 0; i < results_.ips.size(); i++) {
        A << "";
        if (results_.ips[i].is_valid()) {
          A << "| " << results_.ips[i] << "";
        } else {
          A << " | hidden";
        }
        td::uint32 j = 0;
        for (auto &X : results_.results) {
          if (!X->values_[i].is_valid()) {
            A << " | FAIL";
          } else {
            if (m[j].count(X->values_[i].id.seqno) == 0) {
              m[j].insert(X->values_[i].id.seqno);
              A << " | values_[i]} << "\">" << X->values_[i].id.seqno
                << "";
            } else {
              A << " | " << X->values_[i].id.seqno << "";
            }
          }
          j++;
        }
        A << " | 
\n";
      }
      A << "