(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_account, R.move_as_ok());
    }
  });
  auto a = ton::create_tl_object(addr_.workchain, addr_.addr);
  auto query = ton::serialize_tl_object(ton::create_tl_object(
                                            ton::create_tl_lite_block_id(block_id_), std::move(a)),
                                        true);
  td::actor::send_closure(CoreActorInterface::instance_actor_id(), &CoreActorInterface::send_lite_query,
                          std::move(query), std::move(P));
}
void HttpQueryRunMethod::got_account(td::BufferSlice data) {
  auto F = ton::fetch_tl_object(std::move(data), true);
  if (F.is_error()) {
    abort_query(F.move_as_error());
    return;
  }
  auto f = F.move_as_ok();
  data_ = std::move(f->state_);
  proof_ = std::move(f->proof_);
  shard_proof_ = std::move(f->shard_proof_);
  block_id_ = ton::create_block_id(f->id_);
  res_block_id_ = ton::create_block_id(f->shardblk_);
  finish_query();
}
void HttpQueryRunMethod::finish_query() {
  if (promise_) {
    auto page = [&]() -> std::string {
      HttpAnswer A{"account", prefix_};
      A.set_account_id(addr_);
      A.set_block_id(res_block_id_);
      block::AccountState account_state;
      account_state.blk = block_id_;
      account_state.shard_blk = res_block_id_;
      account_state.shard_proof = std::move(shard_proof_);
      account_state.proof = std::move(proof_);
      account_state.state = std::move(data_);
      auto r_info = account_state.validate(block_id_, addr_);
      if (r_info.is_error()) {
        A.abort(r_info.move_as_error());
        return A.finish();
      }
      auto info = r_info.move_as_ok();
      if (info.root.is_null()) {
        A.abort(PSTRING() << "account state of " << addr_ << " is empty (cannot run method `" << method_name_ << "`)");
        return A.finish();
      }
      block::gen::Account::Record_account acc;
      block::gen::AccountStorage::Record store;
      block::CurrencyCollection balance;
      if (!(tlb::unpack_cell(info.root, acc) && tlb::csr_unpack(acc.storage, store) &&
            balance.validate_unpack(store.balance))) {
        A.abort("error unpacking account state");
        return A.finish();
      }
      int tag = block::gen::t_AccountState.get_tag(*store.state);
      switch (tag) {
        case block::gen::AccountState::account_uninit:
          A.abort(PSTRING() << "account " << addr_ << " not initialized yet (cannot run any methods)");
          return A.finish();
        case block::gen::AccountState::account_frozen:
          A.abort(PSTRING() << "account " << addr_ << " frozen (cannot run any methods)");
          return A.finish();
      }
      CHECK(store.state.write().fetch_ulong(1) == 1);  // account_init$1 _:StateInit = AccountState;
      block::gen::StateInit::Record state_init;
      CHECK(tlb::csr_unpack(store.state, state_init));
      auto code = state_init.code->prefetch_ref();
      auto data = state_init.data->prefetch_ref();
      auto stack = td::make_ref(std::move(params_));
      td::int64 method_id = (td::crc16(td::Slice{method_name_}) & 0xffff) | 0x10000;
      stack.write().push_smallint(method_id);
      long long gas_limit = vm::GasLimits::infty;
      // OstreamLogger ostream_logger(ctx.error_stream);
      // auto log = create_vm_log(ctx.error_stream ? &ostream_logger : nullptr);
      vm::GasLimits gas{gas_limit};
      LOG(DEBUG) << "creating VM";
      vm::VmState vm{code, std::move(stack), gas, 1, data, vm::VmLog()};
      vm.set_c7(prepare_vm_c7(info.gen_utime, info.gen_lt, acc.addr, balance));  // tuple with SmartContractInfo
      // vm.incr_stack_trace(1);    // enable stack dump after each step
      int exit_code = ~vm.run();
      if (exit_code != 0) {
        A.abort(PSTRING() << "VM terminated with error code " << exit_code);
        return A.finish();
      }
      stack = vm.get_stack_ref();
      {
        std::ostringstream os;
        os << "result: ";
        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 << "