Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/rest_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1300,25 +1300,25 @@ namespace lws

struct import_request
{
using request = rpc::account_credentials;
using request = rpc::import_request;
using response = rpc::import_response;

static expect<response> handle(request req, connection_data& data, std::function<async_complete>&&)
{
bool new_request = false;
bool fulfilled = false;
{
auto user = open_account(req, data.global->disk.clone());
auto user = open_account(req.creds, data.global->disk.clone());
if (!user)
return user.error();

data.passed_login = true;
if (user->first.start_height == db::block_id(0))
if (user->first.start_height <= db::block_id(req.from_height))
fulfilled = true;
else
{
const expect<db::request_info> info =
user->second.get_request(db::request::import_scan, req.address);
user->second.get_request(db::request::import_scan, req.creds.address);

if (!info)
{
Expand All @@ -1331,7 +1331,7 @@ namespace lws
} // close reader

if (new_request)
MONERO_CHECK(data.global->disk.clone().import_request(req.address, db::block_id(0)));
MONERO_CHECK(data.global->disk.clone().import_request(req.creds.address, db::block_id(req.from_height)));

const char* status = new_request ?
"Accepted, waiting for approval" : (fulfilled ? "Approved" : "Waiting for Approval");
Expand Down
12 changes: 12 additions & 0 deletions src/rpc/light_wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "wire/traits.h"
#include "wire/vector.h"
#include "wire/wrapper/array.h"
#include "wire/wrapper/defaulted.h"
#include "wire/wrappers_impl.h"

namespace
Expand Down Expand Up @@ -361,6 +362,17 @@ namespace lws
);
}

void rpc::read_bytes(wire::json_reader& source, import_request& self)
{
std::string address;
wire::object(source,
wire::field("address", std::ref(address)),
wire::field("view_key", std::ref(unwrap(unwrap(self.creds.key)))),
WIRE_FIELD_DEFAULTED(from_height, unsigned(0))
);
convert_address(address, self.creds.address);
}

void rpc::write_bytes(wire::json_writer& dest, const import_response& self)
{
wire::object(dest,
Expand Down
8 changes: 8 additions & 0 deletions src/rpc/light_wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,14 @@ namespace rpc
void write_bytes(wire::json_writer&, const get_subaddrs_response&);


struct import_request
{
import_request() = delete;
account_credentials creds;
std::uint64_t from_height;
};
void read_bytes(wire::json_reader&, import_request&);

struct import_response
{
import_response() = delete;
Expand Down
55 changes: 49 additions & 6 deletions tests/unit/rest.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,11 @@ namespace

LWS_CASE("rest_server")
{
lws::db::account_address account{};
lws::db::account_address account_address{};
crypto::secret_key view{};
crypto::generate_keys(account.spend_public, view);
crypto::generate_keys(account.view_public, view);
const std::string address = lws::db::address_string(account);
crypto::generate_keys(account_address.spend_public, view);
crypto::generate_keys(account_address.view_public, view);
const std::string address = lws::db::address_string(account_address);
const std::string viewkey = epee::to_hex::string(epee::as_byte_span(unwrap(unwrap(view))));

SETUP("Database and login")
Expand All @@ -139,9 +139,9 @@ LWS_CASE("rest_server")

const lws::db::block_info last_block =
MONERO_UNWRAP(MONERO_UNWRAP(db.start_read()).get_last_block());
const auto get_account = [&db, &account] () -> lws::db::account
const auto get_account = [&db, &account_address] () -> lws::db::account
{
return MONERO_UNWRAP(MONERO_UNWRAP(db.start_read()).get_account(account)).second;
return MONERO_UNWRAP(MONERO_UNWRAP(db.start_read()).get_account(account_address)).second;
};

enet::http::http_simple_client client{};
Expand Down Expand Up @@ -193,6 +193,49 @@ LWS_CASE("rest_server")
EXPECT(response == "{\"per_byte_fee\":39,\"fee_mask\":1000,\"amount\":\"0\",\"fees\":[40,41]}");
}

SECTION("Import from height")
{
EXPECT(account.start_height != lws::db::block_id(0));

const std::string scan_height = std::to_string(std::uint64_t(account.scan_height));
const std::string start_height = std::to_string(std::uint64_t(account.start_height));
const std::string import_height = std::to_string(std::uint64_t(account.start_height) - 1);
message = "{\"address\":\"" + address + "\",\"view_key\":\"" + viewkey + "\"}";
response = invoke(client, "/get_address_info", message);
EXPECT(response ==
"{\"locked_funds\":\"0\","
"\"total_received\":\"0\","
"\"total_sent\":\"0\","
"\"scanned_height\":" + scan_height + "," +
"\"scanned_block_height\":" + scan_height + ","
"\"start_height\":" + start_height + ","
"\"transaction_height\":" + scan_height + ","
"\"blockchain_height\":" + scan_height + "}"
);

message = "{\"address\":\"" + address + "\",\"view_key\":\"" + viewkey + "\", \"from_height\":" + import_height + "}";
response = invoke(client, "/import_wallet_request", message);
EXPECT(response ==
"{\"import_fee\":\"0\","
"\"status\":\"Accepted, waiting for approval\","
"\"new_request\":true,"
"\"request_fulfilled\":false}"
);

EXPECT(db.accept_requests(lws::db::request::import_scan, {std::addressof(account_address), 1}));
response = invoke(client, "/get_address_info", message);
EXPECT(response ==
"{\"locked_funds\":\"0\","
"\"total_received\":\"0\","
"\"total_sent\":\"0\","
"\"scanned_height\":" + import_height + "," +
"\"scanned_block_height\":" + import_height + ","
"\"start_height\":" + import_height + ","
"\"transaction_height\":" + scan_height + ","
"\"blockchain_height\":" + scan_height + "}"
);
}

SECTION("One Receive, Zero Spends")
{
const std::string scan_height = std::to_string(std::uint64_t(account.scan_height) + 5);
Expand Down
Loading