Merge branch 'master' of ../../wallet into docs
This commit is contained in:
commit
8c07e05a82
@ -8,7 +8,7 @@ In a Git bash command prompt, `cd` to the directory where you intend to
|
||||
install the source code.
|
||||
|
||||
```bash
|
||||
git clone --recursive git@cpal.pw:~/wallet
|
||||
git clone --recursive git@rho.la:~/wallet
|
||||
```
|
||||
|
||||
Then launch the visual studio X64 native tools command prompt. `cd` to the
|
||||
|
18
src/ILog.h
18
src/ILog.h
@ -10,17 +10,25 @@ void ILogDebug(const char*);
|
||||
void queue_error_message(const char*); //Used for error conditions within a destructor because you cannot throw within a destructor
|
||||
void queue_fatal_error(const char*); //Used for fatal error conditions within a destructor in place of FatalException because you cannot throw within a destructor
|
||||
|
||||
struct sqlite3;
|
||||
|
||||
class MyException: public std::exception {
|
||||
private:
|
||||
std::string err;
|
||||
int err_number;
|
||||
public:
|
||||
virtual ~MyException() override = default;
|
||||
MyException() = delete;
|
||||
explicit MyException(const std::string &m) noexcept :err(m){}
|
||||
explicit MyException(const char* sz) noexcept :err(sz) {}
|
||||
explicit MyException(const std::string &m) noexcept :err(m.c_str()),err_number(-1){}
|
||||
explicit MyException(const char* sz) noexcept :err(sz),err_number(-1) {}
|
||||
explicit MyException(const char* sz, int i) noexcept :err(sz), err_number(i) {}
|
||||
explicit MyException(int, sqlite3*) noexcept;
|
||||
virtual const char* what() const override {
|
||||
return err.c_str();
|
||||
}
|
||||
virtual const int what_num() const {
|
||||
return err_number;
|
||||
}
|
||||
};
|
||||
|
||||
class FatalException : public MyException {
|
||||
@ -35,12 +43,6 @@ public:
|
||||
HashReuseException() noexcept;
|
||||
};
|
||||
|
||||
class SQLexception : public MyException {
|
||||
public:
|
||||
using MyException::MyException;
|
||||
SQLexception() noexcept;
|
||||
};
|
||||
|
||||
class NonUtf8DataInDatabase : public MyException {
|
||||
public:
|
||||
using MyException::MyException;
|
||||
|
@ -24,7 +24,7 @@ void sqlite3_init() {
|
||||
if (sqlite3_initialize() != SQLITE_OK) {
|
||||
errorCode = 7;
|
||||
szError = "Fatal Error: Sqlite library did not init.";
|
||||
// Cannot log the error, because logging not set up yet, so logging itself causes an exception
|
||||
// Cannot log the error, because logging not set up yet, so logging itself causes an exception
|
||||
throw FatalException(szError.c_str());
|
||||
}
|
||||
}
|
||||
@ -35,7 +35,7 @@ static int callback(void* NotUsed, int argc, char** argv, char** azColName) {
|
||||
std::string str;
|
||||
str.reserve(256);
|
||||
for (int i = 0; i < argc; i++) {
|
||||
str =str + "\t\"" + azColName[i]+ R"|("=)|" + (argv[i]!=nullptr ? argv[i] : "NULL");
|
||||
str = str + "\t\"" + azColName[i] + R"|("=)|" + (argv[i] != nullptr ? argv[i] : "NULL");
|
||||
}
|
||||
ILogMessage(str.c_str());
|
||||
return 0;
|
||||
@ -52,7 +52,7 @@ public:
|
||||
pdb = nullptr;
|
||||
#endif
|
||||
int rc =sqlite3_open_v2(dbName, &pdb, flags, nullptr);
|
||||
if (rc != SQLITE_OK) throw SQLexception(error_message(rc, pdb));
|
||||
if (rc != SQLITE_OK) throw MyException(rc, pdb);
|
||||
assert(pdb != nullptr);
|
||||
// pdb can never be nullptr, since the sqlite3_open_v2 command always initializes
|
||||
// it even if open fails
|
||||
@ -62,7 +62,7 @@ public:
|
||||
char* zErrMsg = nullptr;
|
||||
int rc = sqlite3_exec(pdb, szsql, callback, nullptr, &zErrMsg);
|
||||
if (rc != SQLITE_OK) {
|
||||
SQLexception e(std::string("SQL Exec Error: ") + zErrMsg);
|
||||
auto e = MyException(zErrMsg, rc);
|
||||
sqlite3_free(zErrMsg);
|
||||
throw e;
|
||||
}
|
||||
@ -90,6 +90,11 @@ ISqlite3* Sqlite3_open(const char * db_name) {
|
||||
return new ISqlite3Impl(db_name, SQLITE_OPEN_READWRITE);
|
||||
}
|
||||
|
||||
MyException::MyException(int i, sqlite3* pdb) noexcept:
|
||||
err_number(i),
|
||||
err(error_message(i, pdb))
|
||||
{}
|
||||
|
||||
// Factory method to create database.
|
||||
ISqlite3 * Sqlite3_create(const char* db_name) {
|
||||
return new ISqlite3Impl(db_name, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
|
||||
@ -101,10 +106,10 @@ class IcompiledImpl_sql :
|
||||
friend class ISqlite3Impl;
|
||||
private:
|
||||
sqlite3_stmt *pStmt;
|
||||
ISqlite3Impl *pdbImplOwn;
|
||||
ISqlite3Impl*pdbImplOwn;
|
||||
auto e(int rc) {
|
||||
assert(rc != SQLITE_OK);
|
||||
return SQLexception(error_message(rc, pdbImplOwn->pdb));
|
||||
return MyException(rc, pdbImplOwn->pdb);
|
||||
}
|
||||
public:
|
||||
IcompiledImpl_sql() = delete;
|
||||
@ -192,7 +197,7 @@ public:
|
||||
// from n blocks to n+1 blocks when a single transaction updates the root and anciliary data.
|
||||
// We will build the blockchain hash table in postfix format, with patricia tree nodes that
|
||||
// have skiplink format stored only in memory and rebuilt each startup so that it grows append only,
|
||||
throw SQLexception("Abnormal busy database");
|
||||
throw MyException("Abnormal busy database", 2^14+2);
|
||||
break;
|
||||
case SQLITE_MISUSE:
|
||||
//ret = MISUSE;
|
||||
|
@ -114,8 +114,9 @@ namespace ro {
|
||||
result step() {
|
||||
return (*this)->Isqlite3_step();
|
||||
}
|
||||
|
||||
void final_step() {
|
||||
if (step() != result::DONE) throw SQLexception("SQL: Unexpected rows remaining");
|
||||
if (step() != result::DONE) throw MyException("SQL: Unexpected rows remaining", 16384);
|
||||
}
|
||||
void reset() {
|
||||
(*this)->Isqlite3_reset();
|
||||
@ -183,12 +184,15 @@ class sql_insert_name {
|
||||
ro::sql csql_into_names;
|
||||
ro::sql csql_namekey_into_keys;
|
||||
ro::sql csql_commit;
|
||||
ro::sql csql_rollback;
|
||||
public:
|
||||
sql_insert_name(ISqlite3* p) :
|
||||
csql_begin(p, R"|(BEGIN;)|"),
|
||||
csql_into_names(p, R"|(INSERT OR ROLLBACK INTO "Names" VALUES(?1);)|"),
|
||||
csql_namekey_into_keys(p, R"|(INSERT OR ROLLBACK INTO "Keys" VALUES(?1, last_insert_rowid(), 1);)|"),
|
||||
csql_commit(p, R"|(COMMIT;)|") {}
|
||||
csql_begin(p, R"|(BEGIN IMMEDIATE;)|"),
|
||||
csql_into_names(p, R"|(INSERT OR FAIL INTO "Names" VALUES(?1);)|"),
|
||||
csql_namekey_into_keys(p, R"|(INSERT OR FAIL INTO "Keys" VALUES(?1, last_insert_rowid(), 1);)|"),
|
||||
csql_commit(p, R"|(COMMIT;)|"),
|
||||
csql_rollback(p, R"|(ROLLBACK;)|")
|
||||
{}
|
||||
sql_insert_name(const std::unique_ptr<ISqlite3>& p) : sql_insert_name(p.get()) {}
|
||||
void operator()(const char* psz, const ristretto255::point& pt) {
|
||||
csql_begin.do_one();
|
||||
@ -196,9 +200,18 @@ public:
|
||||
csql_into_names.do_one(psz);
|
||||
csql_namekey_into_keys.do_one(pt);
|
||||
}
|
||||
catch (const std::exception & e) {
|
||||
csql_commit.do_one();
|
||||
throw e;
|
||||
catch (const MyException& e) {
|
||||
csql_rollback.do_one();
|
||||
if (e.what_num() == 19) {
|
||||
throw MyException("Name already in database");
|
||||
}
|
||||
else {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (const std::exception &) {
|
||||
csql_rollback.do_one();
|
||||
throw;
|
||||
}
|
||||
csql_commit.do_one();
|
||||
}
|
||||
|
@ -79,10 +79,10 @@ void display_wallet::close_menu_event_handler(wxCommandEvent& event) {
|
||||
|
||||
void display_wallet::add_name_event_handler(wxCommandEvent& event) {
|
||||
wxTextEntryDialog dialog(this,
|
||||
"This is a small sample\n"
|
||||
"A long, long string to test out the text entrybox",
|
||||
"Please enter a string",
|
||||
"Default value",
|
||||
R"("A Zooko name has a human readable name,
|
||||
and a public key defined by the name and the wallet master secret)",
|
||||
"Create a Zooko name",
|
||||
"",
|
||||
wxOK | wxCANCEL);
|
||||
if (dialog.ShowModal() == wxID_OK)
|
||||
{
|
||||
|
@ -65,7 +65,7 @@ Frame::Frame(wxString wxs)
|
||||
m_panel(),
|
||||
m_LastUsedSqlite()
|
||||
{
|
||||
try {
|
||||
try {
|
||||
assert(singletonFrame == nullptr);
|
||||
singletonFrame = this;
|
||||
SetIcon(wxICON(AAArho));
|
||||
@ -150,14 +150,29 @@ try {
|
||||
menuBar->EnableTop(1, false); //disable edit menu.
|
||||
// child controls
|
||||
m_LastUsedSqlite.Assign(singletonApp->pConfig->Read(wxT("/Wallet/LastUsed"), wxT("")));
|
||||
if (!m_LastUsedSqlite.IsOk() || !m_LastUsedSqlite.HasName() || !m_LastUsedSqlite.HasExt()) {
|
||||
m_panel = new welcome_to_rhocoin(this); //Owner is "this", via the base class wxFrame. m_panel is a
|
||||
// non owning pointer in the derived class that duplicates the owning pointer in the base class.
|
||||
wxPanel* panel{ nullptr };
|
||||
try {
|
||||
if (m_LastUsedSqlite.IsOk())
|
||||
{ //Try to load an existing file.
|
||||
panel = new display_wallet(this, m_LastUsedSqlite);
|
||||
}
|
||||
else {
|
||||
panel = new welcome_to_rhocoin(this);
|
||||
}
|
||||
}
|
||||
else {
|
||||
display_wallet* panel = new display_wallet(this, m_LastUsedSqlite);
|
||||
m_panel = panel;
|
||||
catch (const std::exception& e) {
|
||||
// if the attempt to load an existing wallet file fails,
|
||||
// we have to complete startup somehow.
|
||||
|
||||
queue_error_message(e.what());
|
||||
panel = new welcome_to_rhocoin(this); //Owner is "this", via the base class wxFrame.
|
||||
}
|
||||
// m_panel is a non owning pointer in the derived class that duplicates the
|
||||
// owning pointer in the base class. This looks like a violation of DIY.
|
||||
// but I have the concept of the primary child of the frame window, while
|
||||
// wxWidgets lacks that concept.
|
||||
// m_panel signifies the child window of the frame that currently matters.
|
||||
m_panel = panel;
|
||||
this->RestorePositionFromConfig(ClientToWindowSize(m_panel->GetBestSize()));
|
||||
SetClientSize(GetClientSize());
|
||||
}
|
||||
@ -230,7 +245,7 @@ void Frame::NewWallet(wxFileName& filename, ristretto255::hash<256>& secret) {
|
||||
db->exec(R"|(
|
||||
PRAGMA journal_mode = WAL;
|
||||
PRAGMA synchronous = 1;
|
||||
BEGIN TRANSACTION;
|
||||
BEGIN IMMEDIATE TRANSACTION;
|
||||
CREATE TABLE "Keys"(
|
||||
"pubkey" BLOB NOT NULL UNIQUE PRIMARY KEY,
|
||||
"id" integer NOT NULL,
|
||||
|
@ -129,8 +129,6 @@ FatalException::FatalException() noexcept :
|
||||
MyException(R"|(unspecified fatal exception)|") {};
|
||||
HashReuseException::HashReuseException() noexcept :
|
||||
MyException(R"|(finalized the same hash constructor twice or more)|") {};
|
||||
SQLexception::SQLexception() noexcept :
|
||||
MyException(R"|(SQL Exception)|") {};
|
||||
BadDataException::BadDataException() noexcept :
|
||||
MyException(R"|(Bad data exception)|") {};
|
||||
NonUtf8DataInDatabase::NonUtf8DataInDatabase() noexcept :
|
||||
|
@ -62,7 +62,7 @@ constexpr bool b_WINDOWS = false;
|
||||
static_assert(wxUSE_UNSAFE_WXSTRING_CONV == 1,
|
||||
R"(In fully utf environment, (wallet.manifest plus
|
||||
/utf-8 compile option) all string conversions are safe.)");
|
||||
static_assert(wxMAJOR_VERSION == 3 && wxMINOR_VERSION == 2 && wxRELEASE_NUMBER == 0 && wxSUBRELEASE_NUMBER == 1, "expecting wxWidgets 3.1.7");
|
||||
static_assert(wxMAJOR_VERSION == 3 && wxMINOR_VERSION == 2 && wxRELEASE_NUMBER == 2 && wxSUBRELEASE_NUMBER == 1 && wxVERSION_STRING == wxT("wxWidgets 3.2.2.1"), "expecting wxWidgets 3.2.2.1");
|
||||
static_assert(wxUSE_IPV6 == 1, "IP6 unavailable in wxWidgets");
|
||||
static_assert(WXWIN_COMPATIBILITY_3_0 == 0, "wxWidgets api out of date");
|
||||
static_assert(wxUSE_COMPILER_TLS == (b_WINDOWS ? 2 : 1), "out of date workarounds in wxWidgets for windows bugs");
|
||||
|
@ -424,7 +424,7 @@ static bool OpenWallet(void) {
|
||||
db->exec(R"|(
|
||||
PRAGMA journal_mode = WAL;
|
||||
PRAGMA synchronous = 1;
|
||||
BEGIN TRANSACTION;
|
||||
BEGIN IMMEDIATE TRANSACTION;
|
||||
CREATE TABLE "Keys"(
|
||||
"pubkey" BLOB NOT NULL UNIQUE PRIMARY KEY,
|
||||
"id" integer NOT NULL,
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 2648eb4da156a751a377cfe96b91faa03e535c10
|
||||
Subproject commit 02e885c6f079c6e12a632f92cd7cfcceecf0c39b
|
Loading…
Reference in New Issue
Block a user