forked from cheng/wallet
362b7e653c
Which affected all documentation files.
564 lines
32 KiB
Markdown
564 lines
32 KiB
Markdown
---
|
||
title: Building the project and its libraries in Visual Studio
|
||
...
|
||
# Instructions for wxWidgets
|
||
|
||
## Setting wxWidgets project in Visual Studio
|
||
|
||
First set up your environment variables as described in [Directory Structure
|
||
Microsoft Windows](../set_up_build_environments.html#dirstruct).
|
||
|
||
Run the wxWidgets windows setup, wxMSW-X.X.X-Setup.exe. The project will
|
||
build with wxMSW-3.1.2, and will not build with earlier versions. Or just
|
||
unzip the file into the target directory, as the install does not in fact do
|
||
any useful configuration.
|
||
|
||
Build instructions are in `%WXWIN%\docs\msw\install.txt` The setup program
|
||
for wxWidgets should set the environment variable WXWIN correctly, but does
|
||
not do so. Manually set the WXWIN environment variable
|
||
|
||
When building in Visual Studio, have to retarget the solution to use the
|
||
current libraries, retarget to use x64, and change the code generation
|
||
default in every project versions from Multithreaded Dll to Multithreaded
|
||
(select all projects except the custom build project, then go to
|
||
properties/C++/code generation/Runtime). The DLL change has to be done
|
||
separately for release and debug builds, since Debug uses the MTd libraries,
|
||
and Release uses the MT libraries.
|
||
|
||
A Visual Studio project needs the library build by the wxWidget Visual Studio
|
||
project, an nmake project needs the library built by the wxWidget makefile.vs
|
||
|
||
If you build roWallet under nmake, using Visual Studio tools, you should
|
||
build your wxWidgets libraries using the using nmake – fmakefile.vc, not the
|
||
wxWidget Visual Studio project files.
|
||
|
||
If you build roWallet using the Visual Studio project, you should build your
|
||
wxWidgets libraries using Visual Studio and the wxWidgets Visual Studio
|
||
project files.
|
||
|
||
UDP sockets seem seriously under supported and undocumented in
|
||
wxWidgets, though theoretically present.
|
||
|
||
The [discussion](http://www.wxwidgets.org/search/?q=datagrams "wx Widgets Datagrams"),
|
||
however, makes up for the paucity of documentation.
|
||
|
||
wxWidgets somehow neglects to mention that you need to use the
|
||
different and entirely incompatible UDP specific system calls, `recvfrom()`
|
||
and `sendto()` and instead of `read()` and `write()`
|
||
|
||
If using C sockets, need to pull in completely different header files on
|
||
Unix than on Windows, including Winsock2 rather than Winsock on
|
||
windows, but these completely different header files pull in almost the
|
||
same routines that work in almost the same way.
|
||
|
||
```C
|
||
#ifdef _WIN64
|
||
#include <winsock2.h>
|
||
#else
|
||
#include <sys/socket.h>
|
||
#include <netinet/in.h>
|
||
#include <arpa/inet.h>
|
||
#include <sys/wait.h>
|
||
#include <netdb.h>
|
||
#endif
|
||
```
|
||
|
||
If using wxWidgets, need to build with
|
||
|
||
```c++
|
||
#define WXWIN_COMPATIBILITY_3_0 0
|
||
#define wxUSE_COMPILER_TLS 2
|
||
#define wxUSE_STD_CONTAINERS 1
|
||
#define wxUSE_IPV6 1
|
||
```
|
||
|
||
in `%WXWIN%\include\wx\msw\setup.h`
|
||
|
||
And for gnu builds, `./configure && make && make install`, have to
|
||
change them separately and again in configure. What `configure` actually
|
||
does is difficult to understand and predict, so I have put asserts in the code
|
||
to detect and complain about unsatisfactory settings.
|
||
|
||
```C++
|
||
#ifdef _WIN64
|
||
constexpr bool b_WINDOWS = true;
|
||
#else
|
||
constexpr bool b_WINDOWS = false;
|
||
#endif
|
||
static_assert( __cplusplus >= 201703l, "Out of date C syntax");
|
||
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");
|
||
static_assert(wxUSE_STD_CONTAINERS_COMPATIBLY == 1, "interoperability between stl and wxWidgets broken");
|
||
static_assert(wxUSE_STD_CONTAINERS == 1, "wxWidgets api out of date");
|
||
```
|
||
|
||
The two wxWidgets libraries that you build can co-exist because stored in
|
||
different directories of `%WXWIN%`. Unfortunately the visual studio build
|
||
projects default to the multithreaded dll, which breaks every other library,
|
||
because multithreaded, rather than multithreaded dll, is the usual windows
|
||
default used by statically linked libraries. so each subproject in the
|
||
wxWidgets Visual Studio project has to be changed to link to multithreaded,
|
||
rather than multithreaded DLL. This is a bug, or at least an inconvenient
|
||
deviation from usual practice, in the current release of wxWidgets.
|
||
|
||
If built by a visual studio project, the wxWidgets build constructs a header
|
||
file in a build location for visual studio projects to use, if built by nmake
|
||
under visual studio tools, the build constructs a header file in another
|
||
build location for nmake projects to use.
|
||
|
||
```c++
|
||
#ifdef _DEBUG
|
||
#pragma comment(lib, "wxbase31ud.lib")
|
||
#else
|
||
#pragma comment(lib, "wxbase31u.lib")
|
||
#endif
|
||
```
|
||
|
||
You are going to have to setup the environment variables %GSL%, %SODIUM% and
|
||
%WXWIN% on your windows machines for my visual studio project files to work
|
||
and going to have to build libsodium and wxWidgets in Visual Studio.
|
||
|
||
## Moving a sample from the samples directory
|
||
|
||
To an unrelated directory tree.
|
||
|
||
Create an empty desktop project using Visual Studio Wizard. Change the build
|
||
type displayed at the top of Visual Studio from Debug X86 to Debug X64
|
||
|
||
In Solution Explorer (a palette-window of the VisualStudio-mainwindow), click
|
||
on the project name, then click on the properties icon, the little wrench,
|
||
and then in the left pane of the Property Pages dialog box, expand
|
||
Configuration Properties and select VC++ Directories. Additional include- or
|
||
lib-paths are specifyable there.
|
||
|
||
Set General/C++ Language Standard to ISO(S++17) Standard (std::c++17)
|
||
|
||
Add to the include paths (`properties/configuration properties/VC++
|
||
Directories/Include Directories`
|
||
|
||
```
|
||
$(GSL)\include
|
||
$(WXWIN)\include\msvc
|
||
$(WXWIN)\include
|
||
$(SODIUM)\src\libsodium\include
|
||
```
|
||
|
||
Add to the lib path (`properties/configuration properties/VC++
|
||
Directories/Library Directories`) the location of the wxWidgets libraries
|
||
|
||
```
|
||
$(WXWIN)\lib\vc_x64_lib\
|
||
$(SODIUM)\Build\Debug\x64
|
||
```
|
||
|
||
Set Linker/System to Windows (/SUBSYSTEM:WINDOWS). This is always set to
|
||
CONSOLE, for no sane reason, even if you tell it to create an empty windows
|
||
project.
|
||
|
||
Put unit test command line arguments (-dt) in Configuration/Debugging/Command
|
||
Arguments.
|
||
|
||
Add the header, source, and resource files. The C++ option will then become
|
||
available in properties. Be mindful that if you edit a wxWidgets \*.rc file
|
||
in Visual Studio, Visual Studio destroys it.
|
||
|
||
Set C/++/Code Generation/Runtime Library to Multi-threaded Debug(/MTd) in
|
||
place of multi threaded DLL. When you switch back and forth between release
|
||
and debug, this is apt to be set incorrectly, for reasons that are hard to
|
||
keep track of.
|
||
|
||
Set C++/Preprocessor to \_DEBUG, \_WINDOWS, in place of \_DEBUG, \_CONSOLE
|
||
for the Debug version, and \_NDEBUG, \_WINDOWS for the release version. If
|
||
you compile a release version without defining \_NDEBUG, a flood of mystery
|
||
linker error messages ensue, caused by the fact that I use \_NDEBUG to select
|
||
library version, which is an improvement on the previous Visual Studio
|
||
behavior, where Visual Studio cheerfully generated an executable that
|
||
mysteriously just died at runtime because of mismatched libraries.
|
||
|
||
These instructions lifted wholesale from:\
|
||
[Creating wxWidgets Programs with Visual Studio 2017](https://usingcpp.wordpress.com/2018/02/15/creating-wxwidgets-programs-with-visual-studio-2017-part-1/)\
|
||
[Hello World Example](https://docs.wxwidgets.org/stable/overview_helloworld.html)
|
||
|
||
When you add the sqlite3.c amalgamation, make sure to mark it as not using
|
||
precompiled headers before the first attempt to compile it, otherwise it
|
||
breaks horribly, (C++ format precompiled headers being incompatible with C
|
||
precompiled headers) and when you belatedly turn off the precompiled headers,
|
||
some data that Visual Studio has generated hangs around, so that turning off
|
||
the precompiled headers fails fix the problem.
|
||
|
||
Similarly, if you do a typo in the include paths. Remains stuck on the old
|
||
include paths even if you fix it. To do a real clean, close down visual
|
||
studio, delete the directories generated by visual studio, and *then* your
|
||
edits to the configuration will propagate properly
|
||
|
||
wxWidgets for visual studio should be [installed by the windows installer]
|
||
(https://www.wxwidgets.org/downloads/), then follow the instructions in
|
||
`%WXWIN%\docs\msw\install.md`, after adjusting the visual studio projectg
|
||
files to build with multithreaded, rather than multithreaded DLL, for to
|
||
avoid DLL hell, we are not building with Microsoft DLLs. Set Project to X64.
|
||
|
||
Visual Studio resource editor will destroy a resource file that is intended
|
||
for wxWidgets. WxWidgets resource files should only be edited in a text
|
||
editor.
|
||
|
||
The native Icon format of wxWidgets is xpm, which does not have built in
|
||
support for multiple icon sizes, multiple color resolutions, and partial
|
||
transparency. The greenfish icon editor works to convert any icon format to
|
||
any other, (though it forgets to include the const qualifier) but, sad to
|
||
say, native wxWidgets icons, xpm, are lowest common denominator, therefore,
|
||
crap. And xpm format is also crap, a crap representation of crap data, making
|
||
windows native bitmap format look good by comparison.
|
||
|
||
Most of the documentation for wxWidgets is the samples directory, which is
|
||
set up to build only in the samples directory. To move a project out of the
|
||
samples directory, and get it compiling in the environment you have set up
|
||
for your code in Visual Studio, copy the sample, and copy the resources its
|
||
needs into your target directory, then correct the sample, so that instead of
|
||
looking for resources relative to itself, in the wxWidgets directory, it
|
||
looks for its rc file and stuff in its new home directory. You will need the
|
||
resource files from the root of the samples, and possibly some files from
|
||
samples/images.
|
||
|
||
Due to a persistent bug in visual studio, probably need to delete the
|
||
generated project studio files so that the new values will take effect. Do
|
||
not touch \*.rc files with Visual Studio resource editor, or it will break
|
||
them.
|
||
|
||
## wxWidgets on Windows with Mingw
|
||
|
||
I never succeeded in doing this, so there are probably no end of gotchas of
|
||
which I am unaware.
|
||
|
||
1. [Run the wxWidgets windows setup, wxMSW-X.X.X-Setup.exe]
|
||
(https://github.com/wxWidgets/wxWidgets/releases/). The project will build
|
||
with wxMSW-3.1.2, and will not build with earlier versions
|
||
|
||
2. [Build wxWidgets]
|
||
(http://wiki.codeblocks.org/index.php/WxWindowsQuickRef). See also the
|
||
instructions in wxWidgets-X.X.X/docs/msw/install.txt, or
|
||
docs/msw-X.X.X/install.md. CodeBlocks on windows wants you to build in the
|
||
command window.
|
||
|
||
3. Install [Code::Blocks](http://www.codeblocks.org/downloads).
|
||
|
||
4. Do the Code::Blocks [hello world tutorial]
|
||
(http://wiki.codeblocks.org/index.php?title=WxSmith_tutorial%3a_Hello_world).
|
||
|
||
But Code::Blocks looks suspiciously dead.
|
||
|
||
## wxWidgets on Ubuntu
|
||
|
||
Install build essentials, and gtk (gtk being the build essentials for Ubuntu
|
||
GUI) The native and home environment of wxWidgets is the Mate fork of Gnome,
|
||
and it is behavior in all other environments is derived from this behavior.
|
||
|
||
sudo apt-get install libgtk-3-dev build-essential checkinstall
|
||
|
||
These instructions copied from
|
||
[How to compile and install wxWidgets on Ubuntu/Debian/Linux Mint](https://www.binarytides.com/install-wxwidgets-Ubuntu/) more or
|
||
less wholesale.
|
||
|
||
Download [`Source code tar.gz`](https://github.com/wxWidgets/wxWidgets/releases/) from the latest releases.
|
||
|
||
Place the source in the directory `code/wxWidgets/`.
|
||
|
||
See the instructions in
|
||
`code/wxWidgets/docs/gtk/install.txt`
|
||
|
||
```bash
|
||
cd code/wxWidgets
|
||
mkdir gtk-build
|
||
cd gtk-build/
|
||
./configure --disable-shared --enable-unicode
|
||
make
|
||
```
|
||
|
||
## Memory management in wxWidgets
|
||
|
||
In C++17, if you are using exceptions, everything is owned by the stack, and
|
||
heap values are owned by stack variables which release the heap value in
|
||
their destructor. `std::unique_ptr` and `std::shared_ptr`, and your own
|
||
custom heap owning objects.
|
||
|
||
In wxWidgets, ownership is complicated, because different aspects of
|
||
ownership are owned in different hierarchies.
|
||
|
||
The destructors of modal windows get called in the normal fashion, but modeless windows are always referenced in derived code by non owning
|
||
pointers pointing into the heap. They are owned by their parent window
|
||
when their constructor calls its base constructor, and their derived
|
||
destructor somehow mysteriously gets called by wxWidgets after
|
||
wxWidgets finishes destroying all the windows that the higher level
|
||
window owns.
|
||
|
||
Suppose you have a complicated window with a complicated hierarchy of
|
||
modeless windows in a complicated hierarchy of sizers.
|
||
|
||
Suppose it wants to destroy one of its many children?
|
||
|
||
Then it asks the child for the child's sizer, detaches it, calls destroy
|
||
on the child, which somehow eventually calls the highly derived
|
||
child destructor, and tells the sizers to do layout again.
|
||
|
||
A sizer full of windows can be treated as if it was an owning window by
|
||
calling wxSizer::Clear on it with the argument to delete child windows.
|
||
But otherwise the owning window that wants to delete one particular
|
||
window by derived code has to do so by non owning pointers pointing into
|
||
the heap
|
||
|
||
wxWidgets has a windows hierarchy, with windows owning windows, with memory
|
||
ownership by windows, and events being passed up the hierarchy.
|
||
|
||
wxWidgets has the bind hierarchy, where an object can get events from an
|
||
object with a different lifetime, so it has to unbind in its destructor.
|
||
(Exept in the normal case where all graphical objects get constructed at the
|
||
start of the program and destructed at the end of the program.)
|
||
|
||
And wxWidgets has the sizer hierarchy, which allocates screen space to
|
||
child windows within the parent window.
|
||
|
||
Sizer objects have to be detached, and then explicitly deleted, and child
|
||
windows have to be detached from the sizer hierarchy, then explicitly
|
||
destroyed. And then you call layout on the master sizer of the owning window.
|
||
|
||
And then you have the tab hierachy. You have to tell the main window the tab
|
||
order of its child windows, which is by default the order of their creation.
|
||
|
||
If you are potentially managing an indefinitely large number of windows,
|
||
like a browser, you need the wxNotebook control. (Which lacks a close
|
||
button on the tabs)
|
||
|
||
So, most complex case: You have sizer that acts like a window within a
|
||
larger window. It is a sizer within a larger sizer. It gets constructed in
|
||
response to user events, and destructed in response to user events, while
|
||
the main window continues. The windows within the frame are direct
|
||
children of larger window, and they are also children of the sizer, which is
|
||
a child of the main sizer, which is owned and controlled by the larger
|
||
window.
|
||
|
||
But, for future integration with wxNotebook, probably best to put it into an
|
||
object of type wxPanel. So you define an object that will contain ordinary
|
||
dumb pointers to all these objects, which takes the parent window and the
|
||
parent sizer as a arguments. On construction it constructs all the wxWidgets
|
||
child windows that it needs, with the main window as their window parent,
|
||
puts them into its sizer and prepends its sizer to the main sizer as their
|
||
sizer grandparent, binds them, calls layout on the main sizer, and on
|
||
destruction unbinds them, detaches them from their sizer, calls delete on the
|
||
sizer objects, then destroy on the window objects and then calls layout on
|
||
the main sizer.
|
||
|
||
But the way the experts do it is to make that object a wxPanel window.
|
||
|
||
On construction, first construct windows, then put them into the sizer, then
|
||
bind them, then call layout. On destruction, first unbind, then detach from
|
||
sizer, then destroy sizer objects, then destroy windows objects, then call
|
||
layout on the main sizer.
|
||
|
||
## wxAppConsole
|
||
|
||
Generates an event based program with no gui, console input and console
|
||
output. Should use only objects in wxBase. wxBase is a separate library, and
|
||
you should avoid linking to all the other libraries, except wxNet, and not
|
||
even wxCore, because if you are linking to another library, the other
|
||
routines in the other library will expect a gui.
|
||
|
||
Our program that synchronizes with other peers is going to need to run as a
|
||
daemon on Linux and service on windows, with no UI except it talks to the
|
||
client wallet, which will run as a regular gui program, possibly on another
|
||
machine far away.
|
||
|
||
It is probably easier if we use the same library, wxWidgets, for OS
|
||
independence for both daemon and client.
|
||
|
||
## wxWidgets support
|
||
|
||
[wxWidgets mailing list.]
|
||
(https://www.wxwidgets.org/support/mailing-lists/guide/) I have never used
|
||
this. I have often had my share of grief on wxWidgets, but by the time I
|
||
reduced it to a problem capable of being addressed on the mailing list, the
|
||
problem was always solved.
|
||
|
||
Which tells me that wxWidgets is pretty good, and the considerable grief that
|
||
it generates is only that which is inevitable on a multiplatform gui.
|
||
|
||
# Instructions for Libsodium
|
||
|
||
Supports Ristretto25519, the crypto tool that I am competent to use. Nothing else seems to support this.
|
||
|
||
[Libsodium](https://download.libsodium.org/libsodium/content/) is the authoritative library, derived most directly from Bernstein.
|
||
|
||
git clone https://github.com/jedisct1/libsodium.git
|
||
cd libsodium
|
||
|
||
Compiled as a separate project under visual studio. Retarget the solution to use the current libraries, retarget to use x64, and change the code generation default (properties/C++/code For the your visual studio project to include the sodium.h file, have to define SODIUM_STATIC before including the header file when linking to the static sodium library.
|
||
|
||
```h
|
||
#define SODIUM_STATIC
|
||
#include <sodium.h>
|
||
#pragma comment(lib, "libsodium.lib")
|
||
```
|
||
|
||
To link to libsodium.lib have to add `$(SODIUM)\Build\Debug\x64` to Visual Studio/project properties/linker/General/Additional Library Directories, where SODIUM is the environment variable pointing to the root libsodium directory, and similarly for the Release version of your code `$(SODIUM)\Build\Release\x64`. Assembly code is disabled by default, need to re-enable it once unit test works with encrypted utd communication.
|
||
|
||
We need to eventually re-organize as a git subproject and autotools subproject, but, for the moment, it is a separate library project, hence the environment variable SODIUM.
|
||
|
||
Might be better to not use environment variables $(SODIUM) and to use Git submodules and autotools submodules instead, was wxWidgets does internally.
|
||
|
||
Set the libsodium project properties to DebugLib x64
|
||
|
||
Set the libsodium project properties/General/configuration type to static (should be static already if you have selected Debug Lib and ReleaseLib)
|
||
|
||
It provides all the crypto algorithms you need, including Argon2 for password stretching, and freedom from NSA. Neglects to include base 58 encoding. Wrote my own base 64 library, which differs from the standard base 64 library in being oriented to small items, addressing arbitrary bit fields rather than blocks of three bytes, in being url safe, and in mapping 0, o, and O to zero, and mapping 1, i, I, and l to one, to allow for human entry.
|
||
|
||
Going to need an algorithm for generating passphrases, but passphrases will be hashed and argoned,
|
||
|
||
# Instructions for Sqlite
|
||
|
||
Sqlite is not incorporated as an already built library, nor as a library at
|
||
all, but as source code.
|
||
|
||
When you add the sqlite3.c amalgamation, make sure to mark it as not using
|
||
precompiled headers before the first attempt to compile it, otherwise it
|
||
breaks horribly, (C++ format precompiled headers being incompatible with C
|
||
precompiled headers) and when you belatedly turn off the precompiled headers,
|
||
some data that Visual Studio has generated hangs around, so that turning off
|
||
the precompiled headers fails fix the problem.
|
||
|
||
Similarly, if you do a typo in the include paths. Remains stuck on the old
|
||
include paths even if you fix it. To do a real clean, close down visual
|
||
studio, delete the directories generated by visual studio, and *then* your
|
||
edits to the configuration will propagate properly
|
||
|
||
[SQLite](https://sqlite.org/index.html)
|
||
|
||
[Download](https://sqlite.org/download.html)
|
||
|
||
When creating the database, should turn WAL on:`PRAGMA journal_mode=WAL; PRAGMA synchronous=1;` but before distributing it, make sure the WAL file has been cleaned out with sqlite3_close().
|
||
|
||
Wal mode ensures that we never get a busy error from normal business, only under abnormal conditions, provided that only one thread in one process ever writes to the the database. Which means we do not face the hard problem of handling the busy error.
|
||
|
||
We have also chosen our threading model so that database connections and their associated compiled sql statements are thread local, but one database connection can be connected to many databases, and each database can have many database connections from many threads and many processes
|
||
|
||
Wal mode in the default settings means that writes are normally instantaneous, because they do not hit the disk, but every so often, on completing a transaction, four megabytes get written to disk (which saves a whole lot of read/writes to disk, replacing them with sequential writes without too many reads). So it is probably not a good idea to download large amounts of data from the internet on the UI thread, because every so often the write thread is going to do four megabyes of actual write to actual disk.
|
||
|
||
In Wal mode, recently “written” transaction data will be read from memory.
|
||
So it is a premature optimization to keep data in program memory, when the
|
||
same data is probably in Wal memory or in cache.
|
||
|
||
Because Wal writes are near instantaneous, multiple threads writing seldom
|
||
block each other – but if one thread is busy writing while the previous
|
||
thread is busy flushing four megabytes of actual data to disk, the Wal file
|
||
may grow excessively. According to the documentation, a write thread does the
|
||
flushing, but it looks to me that a background thread does the flushing.
|
||
|
||
But the UI thread will typically only be doing reads and writes every now and
|
||
then, so if one has only one continually writing thread, you don’t have to
|
||
use restart or full which means you very rarely get busy calls, so do not
|
||
have to handle them elegantly and efficiently.
|
||
|
||
I suspect that the wal file gets cleaned mighty fast, so before doing anything clever, measure.by running `PRAGMA wal_checkpoint` every minute or so, which returns a table of one row and three columns telling you how much stuff needs to be written when the checkpoint started, and how much was going to be written when it completed, leaving another thread working on actually writing it. (Two PRAGMA wal_checkpoints in rapid succession are apt to give the same answer) Also log how long the checkpoint took. If the second column is substantially larger than a thousand, and the third column is kind of small, you have a checkpoint problem. This problem is unlikely to happen, because the disk has a much bigger pipe than the network, so it looks to me that with the usual settings, wal and passive checkpointing, all the actual disk write IO is going to take place in a backround thread, because we are just not going to be disk bound on updates and writes. We may find ourselves disk bound on random access reads, but Wal, transactions, and checkpoints are not relevant to that problem.
|
||
|
||
```bash
|
||
del C:\Users\studi\AppData\Local\RoBlockchain\RoData3cx8bdx.sqlite
|
||
sqlite3 C:\Users\studi\AppData\Local\RoBlockchain\RoData3cx8bdx.sqlite
|
||
```
|
||
|
||
Where the file `RoData3cx8bdx.sqlite` contains:
|
||
|
||
```sql
|
||
PRAGMA encoding = "UTF-8";
|
||
PRAGMA journal_mode=WAL;
|
||
PRAGMA foreign_keys = OFF;
|
||
PRAGMA synchronous = 1;
|
||
CREATE TABLE w( --wallets
|
||
PublicKey BLOB PRIMARY KEY NOT NULL UNIQUE,
|
||
Name TEXT NOT NULL UNIQUE, – automatically creates index
|
||
PetName TEXT,
|
||
title TEXT
|
||
);
|
||
CREATE TABLE MasterSecret(
|
||
PublicKey BLOB PRIMARY KEY NOT NULL UNIQUE,
|
||
Secret BLOB,
|
||
Expires INTEGER NOT NULL,
|
||
FOREIGN KEY(PublicKey) REFERENCES w(PublicKey)
|
||
);
|
||
INSERT INTO w VALUES(X'deadbeef','Adam',NULL,NULL);
|
||
.dump
|
||
.output RoData3cx8bdx.sql
|
||
.dump
|
||
.exit
|
||
```
|
||
|
||
We are stashing everything in the user specific directory `wxStandardPaths::GetAppDocumentsDir()`
|
||
and the user specific database, which is wrong. Eventually we will need two databases, one global to all users on a particular machine, which you select when you install, and one for each particular user, that gets generated when the particular user first runs his wallet.
|
||
|
||
Further confusing matters, wxConfigBase settings are always per user on windows.
|
||
|
||
At the moment, only one database and one config object.
|
||
|
||
In our own code, we don’t need to issue `PRAGMA synchronous = 1; PRAGMA
|
||
foreign_keys = ON;` because we modify the sqlite3.c with the following:
|
||
|
||
I need to customize the sqlite3.c almalgamation with my own custom compile options as follows.
|
||
|
||
```C
|
||
//My custom compile options
|
||
#define SQLITE_DQS 0 //Doublequote names, single quote strings. This setting disables the double – quoted string literal misfeature.
|
||
#define SQLITE_THREADSAFE 2 //One thread, one database connection. Data structures such as compiled SQL are threadlocal. But sqlite3 is empowered to do its own multithreading. Many databases per database connection. Database connection and compiled sql statements are threadlocal. last_insert_rowid() is not subject to race conditions in this mode, returning the most recent rowid generated by the thread.
|
||
#define SQLITE_DEFAULT_MEMSTATUS 0 //Don’t track memory usage. Disables the ability of the program using sqlite3 to monitor its memory usage. This setting causes the sqlite3_status() interfaces that track memory usage to be disabled. This helps the sqlite3_malloc() routines run much faster, and since SQLite uses sqlite3_malloc() internally, this helps to make the entire library faster.
|
||
#define SQLITE_DEFAULT_WAL_SYNCHRONOUS 1 // in WAL mode, recent changes to the database might be rolled back by a power loss, but the database will not be corrupted. Furthermore, transaction commit is much faster in WAL mode using synchronous=NORMAL than with the default synchronous=FULL. For these reasons, it is recommended that the synchronous setting be changed from FULL to NORMAL when switching to WAL mode. This compile-time option will accomplish that.
|
||
#define SQLITE_DEFAULT_FOREIGN_KEYS 0 //Dont handle foreign key constraints. Programmer has to do it himself.
|
||
#define SQLITE_LIKE_DOESNT_MATCH_BLOBS 1 //Blobs are not strings. Historically, SQLite has allowed BLOB operands to the LIKE and GLOB operators. But having a BLOB as an operand of LIKE or GLOB complicates and slows the LIKE optimization. When this option is set, it means that the LIKE and GLOB operators always return FALSE if either operand is a BLOB. That simplifies the implementation of the LIKE optimization and allows queries that use the LIKE optimization to run faster.
|
||
#define SQLITE_MAX_EXPR_DEPTH 0 //Setting the maximum expression parse-tree depth to zero disables all checking of the expression parse-tree depth, which simplifies the code resulting in faster execution, and helps the parse tree to use less memory.
|
||
#define SQLITE_OMIT_DECLTYPE 1 // By omitting the (seldom-needed) ability to return the declared type of columns from the result set of query, prepared statements can be made to consume less memory.
|
||
#define SQLITE_OMIT_DEPRECATED 1
|
||
#define SQLITE_DQS 0 //Don’t accept double quoted string literals.
|
||
#define SQLITE_OMIT_PROGRESS_CALLBACK 1
|
||
#define SQLITE_OMIT_SHARED_CACHE 1
|
||
#define SQLITE_OMIT_UTF16 1
|
||
#define SQLITE_USE_ALLOCA 1 //Make use of alloca() for dynamically allocating temporary stack space for use within a single function, on systems that support alloca(). Without this option, temporary space is allocated from the heap
|
||
#define SQLITE_OMIT_LOAD_EXTENSION 1
|
||
#define SQLITE_TEMP_STORE 3 //Temporary files are in memory
|
||
#define SQLITE_OMIT_AUTOINIT 1 //.The SQLite library needs to be initialized using a call to sqlite3_initialize() before certain interfaces are used.This initialization normally happens automatically the first time it is needed.However, with the SQLITE_OMIT_AUTOINIT option, the automatic initialization is omitted.This helps many API calls to run a little faster(since they do not have to check to see if initialization has already occurredand then run initialization if it has not previously been invoked) but it also means that the application must call sqlite3_initialize() manually.If SQLite is compiled with – DSQLITE_OMIT_AUTOINIT and a routine like sqlite3_malloc() or sqlite3_vfs_find() or sqlite3_open() is invoked without first calling sqlite3_initialize(), the likely result will be a segfault
|
||
//end my custom compile options*/
|
||
```
|
||
|
||
[To compile the standard sqlite3.exe tool](https://www.sqlite.org/howtocompile.html).
|
||
|
||
We don’t need to issue `PRAGMA journal_mode=WAL; PRAGMA schema.synchronous
|
||
= 1;` in our own code except if we create a new database, which our code will
|
||
typically not do, because our install will copy a working database.
|
||
|
||
In our code, we do need to issue `PRAGMA optimize;` on close.
|
||
|
||
Missing from their short summary of the C interface is:
|
||
|
||
```C
|
||
/*
|
||
** Return UTF-8 encoded English language explanation of the most recent
|
||
** error.
|
||
*/
|
||
SQLITE_API const char *sqlite3_errmsg(sqlite3 *db)
|
||
```
|
||
|
||
The general rule being that for any unexpected value of rc, any value other than `SQLITE_OK`, `SQLITE_ROW`, and `SQLITE_DONE`, display that message. `sqlite3_exec` wraps this, but we should probably not use `sqlite3_exec`.
|
||
|
||
SQlite’s pragma for identifying that something is the right application file format does not seem to work, or maybe it does work and there is some magic that I am not aware of. But this does not matter, because it only protects against Murphy, not Machiavelli, and we are going to need to guard against Machiavelli.
|
||
|
||
We need to make sure that compiled sql statements are only compiled after the database connection is live, and destroyed before the database is closed.
|
||
|
||
The order of construction and destruction within an object is
|
||
|
||
- First, and only for the constructor of the most derived class as described below, virtual base classes shall be initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base class names in the derived class base-specifier-list.
|
||
- Then, direct base classes shall be initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
|
||
- Then, non-static data members shall be initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
|
||
- Finally, the compound-statement of the constructor body is executed. \[ Note: the declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization.
|
||
|
||
Objects on the stack are destroyed in the reverse of the order that they were declared.
|
||
|
||
The gui object that enables the user to manipulate the contents of the database should contain the database connection, and the compiled sql objects that manipulate the database, declared in that order, so that they get destroyed in that reverse order, compiled sql being destroyed before the database connection is destroyed, and so that in order to create the gui to manipulate the database, we have to first construction a database connection. Since the creation could throw, and we need to handle the throw in the gui, we need a gui already constructed, which then attempts to construct more gui, and informs the user if the construction fails.
|
||
|
||
So the outer gui figures out a plausible database name, and then attempts to construct the inner gui whose constructor then attempts to open a database connection and make sure the database is in a good state, and throws if it cannot construct a good connection to a good database.
|
||
|
||
To protect against Machiavelli, peers have to by default check the early part of the block chain to make sure it has the correct hash, preferably in obfuscated and undocumented code, accessed through a define located in a rather random header file so that Machiavelli will have to audit my code, then supply his victims with the new code as well as the new database. Or just hard code the genesis block, though Machiavelli will have an easier time finding that one. Maybe both. Hard code the genesis block, and have obfuscated hard code for the early blocks.
|