(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 << "
";
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();
}