mirror of
https://github.com/oxen-io/oxen-core.git
synced 2023-12-14 02:22:56 +01:00
blobs for keys in db
This commit is contained in:
parent
3648ef28b2
commit
c95806223d
|
@ -154,7 +154,7 @@ T make_from_guts(std::string_view s) {
|
|||
if (s.size() != sizeof(T))
|
||||
throw std::runtime_error("Cannot reconstitute type: wrong type content size");
|
||||
T x;
|
||||
std::memcpy(&x, s.data(), sizeof(T));
|
||||
std::memcpy(static_cast<void*>(&x), s.data(), sizeof(T));
|
||||
return x;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <string_view>
|
||||
|
||||
#include "common/fs.h"
|
||||
#include <common/string_util.h>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
@ -50,6 +51,36 @@ namespace db
|
|||
st.bindNoCopy(i, static_cast<const void*>(blob.data()), blob.size());
|
||||
}
|
||||
|
||||
// Wrapper for extracting BLOB values from a query without unnecessary copying. This is intended
|
||||
// to be called via `db::get` such as:
|
||||
//
|
||||
// auto [num, data] = db::get<int, blob>(st);
|
||||
//
|
||||
// The `.data` string view here will point to the BLOB data directly. Note that this view remains
|
||||
// only value while the statement remains active, and so it must be used as needed immediately.
|
||||
// This also means that this is *unsuitable* for one-shot methods like `prepared_get` (which
|
||||
// finalize the statement before returning).
|
||||
struct blob {
|
||||
std::string_view data;
|
||||
blob(SQLite::Column&& col)
|
||||
: data{static_cast<const char*>(col.getBlob()), static_cast<size_t>(col.getBytes())} {}
|
||||
};
|
||||
|
||||
// Takes a primitive struct from which we can directly initialize from the stored blob value. The
|
||||
// type `T` must be usable with `make_from_guts`. Unlike `blob` this value *is* suitable for use
|
||||
// in a one-shot method.
|
||||
template <typename T>
|
||||
struct blob_guts {
|
||||
T value;
|
||||
blob_guts(SQLite::Column&& col)
|
||||
: value{tools::make_from_guts<T>(blob(std::move(col)).data)} {}
|
||||
|
||||
// Implicit rvalue-convertible to `T&&` so that you can use it somewhat transparently, for
|
||||
// example, allowing implicit conversion from a `std::tuple<..., blob_guts<T>>` into a
|
||||
// `std::tuple<..., T>`.
|
||||
operator T&&() && { return std::move(value); }
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename T>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "block.hpp"
|
||||
|
||||
#include <common/hex.h>
|
||||
#include <common/string_util.h>
|
||||
#include <cryptonote_basic/cryptonote_basic.h>
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
@ -426,27 +427,39 @@ namespace wallet
|
|||
return prepared_get<int64_t>("SELECT output_count FROM metadata WHERE id=0;");
|
||||
}
|
||||
void
|
||||
WalletDB::save_keys(const std::string& spend_priv_str, const std::string& spend_pub_str, const std::string& view_priv_str, const std::string& view_pub_str)
|
||||
WalletDB::save_keys(const std::shared_ptr<WalletKeys> keys)
|
||||
{
|
||||
const auto [db_spend_priv_str, db_spend_pub_str, db_view_priv_str, db_view_pub_str] = load_keys();
|
||||
const auto maybe_db_keys = load_keys();
|
||||
if (maybe_db_keys.has_value())
|
||||
{
|
||||
if ((tools::view_guts(maybe_db_keys->spend_privkey()) != tools::view_guts(keys->spend_privkey())) ||
|
||||
(tools::view_guts(maybe_db_keys->spend_pubkey()) != tools::view_guts(keys->spend_pubkey())) ||
|
||||
(tools::view_guts(maybe_db_keys->view_privkey()) != tools::view_guts(keys->view_privkey())) ||
|
||||
(tools::view_guts(maybe_db_keys->view_pubkey()) != tools::view_guts(keys->view_pubkey())))
|
||||
throw std::runtime_error("provided keys do not match database file");
|
||||
}
|
||||
|
||||
if ((not db_spend_priv_str.empty() && db_spend_priv_str != spend_priv_str) ||
|
||||
(not db_spend_pub_str.empty() && db_spend_pub_str != spend_pub_str) ||
|
||||
(not db_view_priv_str.empty() && db_view_priv_str != view_priv_str) ||
|
||||
(not db_view_pub_str.empty() && db_view_pub_str != view_pub_str))
|
||||
throw std::runtime_error("provided keys do not match database file");
|
||||
|
||||
prepared_exec("UPDATE metadata SET spend_priv = ?, spend_pub = ?, view_priv = ?, view_pub = ? where id = 0;",
|
||||
spend_priv_str,
|
||||
spend_pub_str,
|
||||
view_priv_str,
|
||||
view_pub_str);
|
||||
std::string(tools::view_guts(keys->spend_privkey())),
|
||||
std::string(tools::view_guts(keys->spend_pubkey())),
|
||||
std::string(tools::view_guts(keys->view_privkey())),
|
||||
std::string(tools::view_guts(keys->view_pubkey())));
|
||||
}
|
||||
|
||||
std::tuple<std::string, std::string, std::string, std::string>
|
||||
std::optional<DBKeys>
|
||||
WalletDB::load_keys()
|
||||
{
|
||||
return prepared_get<std::string, std::string, std::string, std::string>("SELECT spend_priv, spend_pub, view_priv, view_pub FROM metadata WHERE id=0");
|
||||
DBKeys keys;
|
||||
int32_t spend_key_exists = prepared_get<int32_t>("SELECT count(spend_priv) FROM metadata WHERE spend_priv IS NOT ''");
|
||||
if (not spend_key_exists)
|
||||
return std::nullopt;
|
||||
auto x = prepared_get<db::blob_guts<crypto::secret_key>, db::blob_guts<crypto::public_key>, db::blob_guts<crypto::secret_key>, db::blob_guts<crypto::public_key>>(
|
||||
"SELECT spend_priv, spend_pub, view_priv, view_pub FROM metadata WHERE id=0");
|
||||
keys.ssk = std::get<0>(x).value;
|
||||
keys.spk = std::get<1>(x).value;
|
||||
keys.vsk = std::get<2>(x).value;
|
||||
keys.vpk = std::get<3>(x).value;
|
||||
return keys;
|
||||
}
|
||||
|
||||
} // namespace wallet
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <sqlitedb/database.hpp>
|
||||
|
||||
#include "output.hpp"
|
||||
#include "walletkeys.hpp"
|
||||
|
||||
#include <optional>
|
||||
|
||||
|
@ -95,10 +96,10 @@ namespace wallet
|
|||
|
||||
// Saves keys to the database, will check if keys match if already exists and throw if different
|
||||
void
|
||||
save_keys(const std::string& spend_priv_str, const std::string& spend_pub_str, const std::string& view_priv_str, const std::string& view_pub_str);
|
||||
save_keys(const std::shared_ptr<WalletKeys> keys);
|
||||
|
||||
// Loads keys from an already created database
|
||||
std::tuple<std::string, std::string, std::string, std::string>
|
||||
std::optional<DBKeys>
|
||||
load_keys();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,10 +10,11 @@
|
|||
#include <optional>
|
||||
|
||||
#include "pending_transaction.hpp"
|
||||
#include "walletkeys.hpp"
|
||||
|
||||
namespace wallet
|
||||
{
|
||||
class Keyring
|
||||
class Keyring : public WalletKeys
|
||||
{
|
||||
public:
|
||||
Keyring(
|
||||
|
@ -144,6 +145,11 @@ namespace wallet
|
|||
crypto::secret_key view_private_key;
|
||||
crypto::public_key view_public_key;
|
||||
|
||||
const crypto::secret_key& spend_privkey() const override { return spend_private_key; }
|
||||
const crypto::public_key& spend_pubkey() const override { return spend_public_key; }
|
||||
const crypto::secret_key& view_privkey() const override { return view_private_key; }
|
||||
const crypto::public_key& view_pubkey() const override { return view_public_key; }
|
||||
|
||||
private:
|
||||
|
||||
hw::core::device_default key_device;
|
||||
|
|
|
@ -69,17 +69,12 @@ namespace wallet
|
|||
if (keyring)
|
||||
{
|
||||
keys = keyring;
|
||||
db->save_keys(
|
||||
tools::type_to_hex(keys->spend_private_key),
|
||||
tools::type_to_hex(keys->spend_public_key),
|
||||
tools::type_to_hex(keys->view_private_key),
|
||||
tools::type_to_hex(keys->view_public_key)
|
||||
);
|
||||
db->save_keys(keys);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto [spend_priv, spend_pub, view_priv, view_pub] = db->load_keys();
|
||||
keys = std::make_shared<wallet::Keyring>(spend_priv, spend_pub, view_priv, view_pub, nettype);
|
||||
const auto db_keys = db->load_keys();
|
||||
keys = std::make_shared<wallet::Keyring>(db_keys->spend_privkey(), db_keys->spend_pubkey(), db_keys->view_privkey(), db_keys->view_pubkey(), nettype);
|
||||
tx_scanner = TransactionScanner(keys, db);
|
||||
}
|
||||
db->add_address(0, 0, keys->get_main_address());
|
||||
|
|
19
src/wallet3/walletkeys.hpp
Normal file
19
src/wallet3/walletkeys.hpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
class WalletKeys {
|
||||
public:
|
||||
virtual const crypto::secret_key& spend_privkey() const = 0;
|
||||
virtual const crypto::public_key& spend_pubkey() const = 0;
|
||||
virtual const crypto::secret_key& view_privkey() const = 0;
|
||||
virtual const crypto::public_key& view_pubkey() const = 0;
|
||||
};
|
||||
|
||||
struct DBKeys : public WalletKeys {
|
||||
crypto::secret_key ssk, vsk;
|
||||
crypto::public_key spk, vpk;
|
||||
|
||||
const crypto::secret_key& spend_privkey() const override { return ssk; }
|
||||
const crypto::public_key& spend_pubkey() const override { return spk; }
|
||||
const crypto::secret_key& view_privkey() const override { return vsk; }
|
||||
const crypto::public_key& view_pubkey() const override { return vpk; }
|
||||
};
|
Loading…
Reference in a new issue