forked from cheng/wallet
Merge remote-tracking branch 'origin/master' into docs
This commit is contained in:
commit
d95c4a1c71
55
.gitattributes
vendored
55
.gitattributes
vendored
@ -38,32 +38,37 @@ Makefile text eol=lf encoding=utf-8
|
||||
|
||||
# Force binary files to be binary
|
||||
|
||||
# Archives
|
||||
*.7z filter=lfs diff=lfs merge=lfs -text
|
||||
*.br filter=lfs diff=lfs merge=lfs -text
|
||||
*.gz filter=lfs diff=lfs merge=lfs -text
|
||||
*.tar filter=lfs diff=lfs merge=lfs -text
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
# Documents
|
||||
*.pdf filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
# Images
|
||||
*.gif filter=lfs diff=lfs merge=lfs -text
|
||||
*.ico filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
||||
*.pdf filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.psd filter=lfs diff=lfs merge=lfs -text
|
||||
*.webp filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
# Fonts
|
||||
*.woff2 filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
# Other
|
||||
*.exe filter=lfs diff=lfs merge=lfs -text
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
|
@ -11,3 +11,6 @@
|
||||
alias = ! git config --get-regexp ^alias\\. | sed -e s/^alias\\.// -e s/\\ /\\ =\\ / | grep -v ^'alias ' | sort
|
||||
[commit]
|
||||
gpgSign = true
|
||||
[submodule]
|
||||
recurse = true
|
||||
|
||||
|
12
.gitmodules
vendored
12
.gitmodules
vendored
@ -1,11 +1,9 @@
|
||||
[submodule "libsodium"]
|
||||
path = libsodium
|
||||
url = https://github.com/jedisct1/libsodium.git
|
||||
ignore = dirty
|
||||
[submodule "wxWidgets"]
|
||||
path = wxWidgets
|
||||
url = https://github.com/wxWidgets/wxWidgets.git
|
||||
ignore = dirty
|
||||
url = cpal.pw:~/libsodium.git
|
||||
[submodule "mpir"]
|
||||
path = mpir
|
||||
url = https://github.com/BrianGladman/mpir.git
|
||||
url = cpal.pw:~/mpir.git
|
||||
[submodule "wxWidgets"]
|
||||
path = wxWidgets
|
||||
url = cpal.pw:~/wxWidgets.git
|
||||
|
@ -25,11 +25,11 @@ namespace ro {
|
||||
// copy constructor
|
||||
sql(const sql& a) = delete;
|
||||
// move constructor
|
||||
sql(sql&& p) :std::unique_ptr<Icompiled_sql>(p.release()) { }
|
||||
sql(sql&& p) noexcept :std::unique_ptr<Icompiled_sql>(p.release()) { }
|
||||
// copy assignment
|
||||
sql& operator=(const sql) = delete;
|
||||
// Move assignment
|
||||
sql& operator=(sql&& p) {
|
||||
sql& operator=(sql&& p) noexcept {
|
||||
std::unique_ptr<Icompiled_sql>::reset(p.release());
|
||||
}
|
||||
sql(Icompiled_sql* p) :std::unique_ptr<Icompiled_sql>(p) {}
|
||||
|
@ -102,7 +102,7 @@ void display_wallet::OnClose(wxCloseEvent& event) {
|
||||
// and to object to the closing in a "file not saved" type situation.
|
||||
// https://docs.wxwidgets.org/trunk/classwx_close_event.html
|
||||
DestroyChildren();
|
||||
Destroy(); //Default handler will destroy the window. This is our handler for the user calling close,
|
||||
Destroy(); //Default handler will destroy the window. This is our handler for the user calling close,
|
||||
// replacing the default handler.'
|
||||
if (singletonFrame->m_panel ==this)singletonFrame->m_panel = nullptr;
|
||||
|
||||
|
@ -102,6 +102,105 @@ repository results in non portable surprises and complexity. Makes it hard
|
||||
for anyone else to build your project, because they will have to, by hand,
|
||||
tell your project where the libraries are on their system.
|
||||
|
||||
When one is developing code, you normally have a git branch. But
|
||||
the git commit of the master project in which the submodule is
|
||||
contained does not notice its subproject has changed, unless the
|
||||
subproject head has changed. And the subject project head will not
|
||||
change if it points to a name, rather than to a particular commit. For
|
||||
ones changes to a submodule to be reflected in the master project in
|
||||
any consistent or predictable way, the submodule has to be in
|
||||
detached head mode, with the head pointing directly to a commit,
|
||||
rather than pointing to a branch that points to a commit.
|
||||
|
||||
Git commands in master project do not look inside the subproject.
|
||||
They just look at the subproject's head.
|
||||
|
||||
This means that signing off on changes to a submodule is
|
||||
irrelevant. One signs off on the master project, which includes the
|
||||
hash of that submodule commit.
|
||||
|
||||
When one is changing submodules for the use of a particular
|
||||
project, making related changes in the master project and
|
||||
submodules, one should not track the changes by creating and
|
||||
updating branch names in the submodule, but by creating and
|
||||
updating branch names in the containing module, so that the
|
||||
commits in the submodule have no name in the submodule, the
|
||||
submodule is always in detached head state, albeit the head may be
|
||||
tagged. Names in submodules are primarily of value for
|
||||
amendments to the submodule as an independent module,
|
||||
intended to be used by multiple projects, and for this purpose, tags
|
||||
are better than branch names. wxWidgets releases are identified by
|
||||
tag, not by branch, and the names of branches are only used to
|
||||
communicate a particular project on the submodule to other people
|
||||
working on that project as their master project.
|
||||
|
||||
Branch names are not useful within a submodule, though
|
||||
submodule may well be, from the point of view of the primary
|
||||
developers, not a submodule but a module in its own right, used as
|
||||
a submodule in many different modules, so for them, branch names
|
||||
will be useful. But when you are modifying the submodules in a
|
||||
project as a single project, making related changes in the module
|
||||
and submodule, the names belong in the primary project module,
|
||||
Within the submodule, commits are nameless with detached head,
|
||||
the name in primary module naming a group of related commits in
|
||||
several submodules, which commits do not usually receive
|
||||
independent names of their own, even though the commits have to
|
||||
be made within the submodule, not in the containing module which
|
||||
names the complete set of interrelated commits.
|
||||
|
||||
In this case, working on submodules as part of a single larger project, you should set
|
||||
|
||||
```bash
|
||||
git config --local submodule.recurse true
|
||||
```
|
||||
|
||||
In the primary project, so that you conveniently push and pull a
|
||||
group of related changes as one thing, and the build for the whole
|
||||
project should treat the submodule libraries as having a
|
||||
dependency on module/.git/modules/submodule/HEAD, rather than
|
||||
checking every single file in the submodules every time to see
|
||||
if one has changed, for there could be an enormous number of
|
||||
them. The primary build should invoke the submodule build, which
|
||||
*will* check each file in the submodule for changes, only when the
|
||||
submodule detached head has changed. And therefore, you want it
|
||||
to change, you want the submodule head to be nameless and
|
||||
detached, whenever you modify a submodule as part of a larger
|
||||
project where you test your changes by rebuilding the whole
|
||||
project to make sure all your related changes fit together.
|
||||
|
||||
When tracking an upstream submodule that has submodules of its
|
||||
own, which have their own upstreams
|
||||
|
||||
Update your version with
|
||||
|
||||
```bash
|
||||
git pull upstream --recurse-submodules=on-demand «their-latest-release»
|
||||
```
|
||||
|
||||
Make sure things still work. Get everything working. (You do have unit test, right?)
|
||||
|
||||
then:
|
||||
|
||||
```bash
|
||||
git submodule foreach --recursive 'git push origin HEAD:«your-tracking-branch»'
|
||||
git submodule foreach --recursive 'git switch --detach'
|
||||
```
|
||||
|
||||
All of which, of course, presupposes you have already set unit tests,
|
||||
upstream, origin, and your tracking branch appropriately.
|
||||
|
||||
Even if your local modifications are nameless in your local
|
||||
submodule repository, on your remote submodule repository they
|
||||
need to have a name to be pushed to, hence you need to have a
|
||||
tracking branch in each of your remote images of each of your
|
||||
submodules, and that tracking branch will need to point to the root
|
||||
of a tree of all the nameless commits that the names and commits
|
||||
in your superproject that contains this submodules point to.
|
||||
|
||||
You want `.gitmodules` in your local image of the repository to
|
||||
reflect the location and fork of your new remote repository, with
|
||||
your remote as its `origin` and their remote as its `upstream`.
|
||||
|
||||
You need an enormous pile of source code, the work of many people over
|
||||
a very long time, and GitSubmodules allows this to scale, because the
|
||||
local great big pile of source code references many independent and
|
||||
@ -153,7 +252,6 @@ submodule and the next are such that one is only likely to make changes in
|
||||
one module at at time.
|
||||
|
||||
# Passphrases
|
||||
|
||||
All wallets now use random words - but you cannot carry an eighteen word random phrase though an airport in you head
|
||||
|
||||
Should use [grammatically correct passphrases](https://github.com/lungj/passphrase_generator).
|
||||
|
@ -43,13 +43,20 @@ many of the library files, and therefore git will abort the pull.
|
||||
"Contributor Code of Conduct"
|
||||
{target="_blank"}
|
||||
|
||||
`winConfigure.bat` also configures the repository you just created to use
|
||||
The winConfigure script builds everything, including the documents, but
|
||||
takes a while. Normally when you make changes to the source code you
|
||||
should rebuild just the program, using `wallet.sln` on windows.
|
||||
To rebuild the documents after editing them, `docs/mkdocs`
|
||||
|
||||
winConfigure.bat also configures the repository you just created to use
|
||||
`.gitconfig` in the repository, causing git to to implement GPG signed
|
||||
commits -- because [cryptographic software is under attack] from NSA
|
||||
entryists and shills, who seek to introduce backdoors.
|
||||
|
||||
This may be inconvenient if you do not have `gpg` installed and set up.
|
||||
|
||||
It also means that subsequent pulls and merges will require you to have `gpg `trust the key `public_key.gpg`, and if you submit a pull request, the puller will need to trust your `gpg` public key.
|
||||
|
||||
`.gitconfig` adds several git aliases:
|
||||
|
||||
1. `git lg` to display the gpg trust information for the last four commits.
|
||||
|
@ -219,7 +219,7 @@ void Frame::OnDeleteConfiguration(wxCommandEvent&)
|
||||
using ro::bin2hex, ro::to_base64_string;
|
||||
void Frame::NewWallet(wxFileName& filename, ristretto255::hash<256>& secret) {
|
||||
/*If creation fails, abort with exception. If it succeeds, set LastUsed to default filename.
|
||||
The exception in unit test should simply generate an error message, but if run during initialization,
|
||||
The exception in unit test should simply generate an error message, but if run during initialization,
|
||||
should bring up the more complex UI for constructing or selecting your wallet file.*/
|
||||
wxLogMessage(_wx("New wallet file %s"), filename.GetFullPath());
|
||||
std::unique_ptr<ISqlite3> db{ nullptr };
|
||||
|
3
frame.h
3
frame.h
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
template <typename T>
|
||||
// This class exists to record the needed to unbind a drop down menu action and delete
|
||||
// the corresponding item from the drop down menu when the handler is destroyed.
|
||||
// the corresponding item from the drop down menu when the handler is destroyed.
|
||||
// (Because the handler is a method of an object that is about to be destroyed.)
|
||||
// Also avoids the need for manually creating a new windowid to link each additional bind
|
||||
// to each menu item, thus avoids the likelihood of mismatching binds and menu entries.
|
||||
@ -91,4 +91,3 @@ public:
|
||||
};
|
||||
|
||||
extern Frame* singletonFrame;
|
||||
|
||||
|
@ -113,7 +113,7 @@ namespace ro {
|
||||
* and whose members have the spaceship operator
|
||||
* nonexistent arithemetic values of the shorter array
|
||||
* are considered zero
|
||||
* Existent non arithmetic values are considered greater than
|
||||
* Existent non arithmetic values are considered greater than
|
||||
* nonexistent non arithemetic values */
|
||||
template<class T, class U >
|
||||
std::enable_if_t<!ro::has_spaceship_v<T, U>, decltype(std::span(declval<T>())[0] <=> std::span(declval<U>())[0]) >operator <=>(
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 561e556dad078af581f338fe3de9ee6362d28b16
|
||||
Subproject commit 012e892841ed6edc521f88a23b55863c7afe4622
|
@ -43,7 +43,7 @@ extern const char sz_existing_secret[];
|
||||
extern const char sz_open_existing_wallet[];
|
||||
extern const char sz_existing_wallet[];
|
||||
extern const char sz_text_buffer_overflow[];
|
||||
extern const char sz_unknown_error[];
|
||||
extern const char sz_unknown_error[];
|
||||
|
||||
extern const char szAboutWallet[];
|
||||
extern const char szAboutTitle[];
|
||||
|
2
mpir
2
mpir
@ -1 +1 @@
|
||||
Subproject commit 33be9007f95b85230da2330ef3ed525896370cc2
|
||||
Subproject commit 7e09c025f6061863e58a2cc0a0aefa8b5fa8496b
|
@ -14,18 +14,54 @@ namespace ro {
|
||||
return id ^ (id >> 32);
|
||||
}
|
||||
|
||||
class charmap :public std::array<char, 0x100> {
|
||||
class charmap {
|
||||
public:
|
||||
std::array< char, 0x100> index{ 0, };
|
||||
charmap() = delete;
|
||||
constexpr charmap(const char* p, const char* q) {
|
||||
constexpr charmap(const char * p, const char * q) {
|
||||
while (unsigned int pu{ static_cast<unsigned char>(*p++) }) {
|
||||
assert((*this)[pu] == 0);
|
||||
(*this)[pu] = *q++;
|
||||
assert(index[pu] == 0);
|
||||
index[pu] = *q++;
|
||||
}
|
||||
assert(*(p - 1) == '\0' && *q == '\0');
|
||||
assert(*(p - 1) == '\0' && *q == '\0');
|
||||
/* when an instance of this class is declared constexpr,
|
||||
an assert does not trigger a run time error,
|
||||
because expression evaluated at compile time.
|
||||
Instead the compiler reports that the expression
|
||||
did not evaluate to a constant,
|
||||
|
||||
The error is confusing, because the error points to
|
||||
the declaration where the initialization was invoked,
|
||||
instead of pointing to the assert.
|
||||
*/
|
||||
}
|
||||
};
|
||||
|
||||
class charmapWithFixup {
|
||||
public:
|
||||
std::array< char, 0x100> index{ 0, };
|
||||
charmapWithFixup() = delete;
|
||||
constexpr charmapWithFixup(const char* p, const char* q) {
|
||||
while (unsigned int pu{ static_cast<unsigned char>(*p++) }) {
|
||||
assert(index[pu] == 0);
|
||||
index[pu] = *q++;
|
||||
}
|
||||
index['I'] = index['l']='0';
|
||||
assert(*(p - 1) == '\0' && *q == '\0');
|
||||
/* when an instance of this class is declared constexpr,
|
||||
an assert does not trigger a run time error,
|
||||
because expression evaluated at compile time.
|
||||
Instead the compiler reports that the expression
|
||||
did not evaluate to a constant,
|
||||
|
||||
The error is confusing, because the error points to
|
||||
the declaration where the initialization was invoked,
|
||||
instead of pointing to the assert.
|
||||
*/
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//template <> class base58<scalar> : public CompileSizedString<44> {};
|
||||
static_assert(sizeof(base58<point>) == 46, "base58 point strings unexpected size");
|
||||
|
||||
@ -33,17 +69,18 @@ namespace ro {
|
||||
static constexpr char index2MpirBase58[] { "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv" };
|
||||
|
||||
void map_base_from_mpir58(char* p) {
|
||||
static const charmap map(index2MpirBase58, index2cryptoBase58);
|
||||
while (unsigned int pu{ static_cast<unsigned char>(*p) }) {
|
||||
*p++ = map[pu];
|
||||
static constexpr charmap map(index2MpirBase58, index2cryptoBase58);
|
||||
while (uint8_t pu{ static_cast<uint8_t>(*p) }) {
|
||||
*p++ = map.index[pu];
|
||||
}
|
||||
}
|
||||
|
||||
void map_base_to_mpir58(const char* p, char* q, size_t count) {
|
||||
static const charmap map(index2cryptoBase58, index2MpirBase58);
|
||||
static constexpr charmap map(index2cryptoBase58, index2MpirBase58);
|
||||
static_assert(map.index[0xF0] == 0);
|
||||
while (count--) {
|
||||
unsigned int pu{ static_cast<unsigned char>(*p++) };
|
||||
char c{ map[pu] };
|
||||
char c{ map.index[pu] };
|
||||
if (c == '\0') throw NotBase58Exception();
|
||||
*q++ = c;
|
||||
}
|
||||
|
@ -143,4 +143,3 @@ template<> CompileSizedString < (sizeof(scalar) * 8 + 5) / 6>
|
||||
);
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
@ -597,7 +597,7 @@ namespace ristretto255 {
|
||||
// After loading a point as a blog from the network, from the database,
|
||||
// or from user data typed as text, have to check for validity.
|
||||
bool valid(void) const { return 0 != crypto_core_ristretto255_is_valid_point(&blob[0]); }
|
||||
explicit constexpr point(std::array<uint8_t, crypto_core_ristretto255_BYTES>&& in) :
|
||||
explicit constexpr point(std::array<uint8_t, crypto_core_ristretto255_BYTES>&& in) :
|
||||
blob{ std::forward<std::array<uint8_t, crypto_core_ristretto255_BYTES>>(in) } { };
|
||||
static_assert(crypto_core_ristretto255_BYTES == 32, "256 bit points expected");
|
||||
~point() = default;
|
||||
|
105
slash6.cpp
105
slash6.cpp
@ -15,11 +15,30 @@
|
||||
static constexpr uint8_t index2base64[]{
|
||||
"0123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz!$*+-_"
|
||||
};
|
||||
|
||||
/*
|
||||
control characters are stops
|
||||
! $ * + - permitted The characters "#%&'(),. are stops
|
||||
0-9 permitted The characters :;<=>? are stops
|
||||
A-Z and _ permitted, @ and [\]^ are stops
|
||||
a-z permitted. {|} ~` are stops, as is the mysterious control character 0x7F (del)
|
||||
*/
|
||||
// Unlike regular baseINV, and incompatible with it. Intended to encode stuff small enough
|
||||
// that it might be human typed and human transmitted, therefore maps 'o' and 'O' to '0', 'I' and
|
||||
// 'l' to '1'
|
||||
// uses six url safe additional characters !$*+-_ to bring it up to six bits
|
||||
//
|
||||
// But on reflection, useless, since human typed stuff like this should use Bitcoin's base 58 encoding
|
||||
// So going to switch to regular base64, despite the unreasonably immense amount of work I put into it.
|
||||
|
||||
// Unfortunately, Wireguard, with which I am going to need to interoperate, uses RFC4648, whose
|
||||
// algorithm is fundamentally different - no special treatment for I, O, o, and l, and uses =
|
||||
// to handle the case where you have boundary problems between eight and six bit groups.
|
||||
// They force everything to four character groups, using an = sign to indicate that the
|
||||
// bytes being represented stop before a multiple of three. https://www.base64encode.org
|
||||
|
||||
|
||||
|
||||
|
||||
static_assert(index2base64[63] == '_', "surprise numeral at 63");
|
||||
|
||||
// Being intended for small bits of data, assumes no whitespace within an entity
|
||||
@ -35,41 +54,71 @@ static_assert(index2base64[63] == '_', "surprise numeral at 63");
|
||||
// will return a number of bits less than the size of the input bit buffer, less than the bitcount
|
||||
// it was given.
|
||||
|
||||
// Table to convert ascii to six bit.
|
||||
static constexpr std::array<constexpr uint8_t, 0x100> ascii2six_ar{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //control characters
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //control characters
|
||||
0xff, 0x3a, 0xff, 0xff, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3c, 0x3d, 0xff, 0x3e, 0xff, 0xff, // ! $ * + - permitted The characters "#%&'(),. are stops
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 0-9 permitted The characters :;<=>? are stops
|
||||
0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x01, 0x12, 0x13, 0x14, 0x15, 0x16, 0x00,
|
||||
0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0xff, 0xff, 0xff, 0xff, 0x3f, // A-Z and _ permitted, @ and [\]^ are stops
|
||||
0xff, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x01, 0x2d, 0x2e, 0x00,
|
||||
0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, //a-z the characters {|} ~` are stops, as is the mysterious control character 0x7F (del)
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // utf8 multibyte characters, all stops.
|
||||
};
|
||||
|
||||
// Table to convert ascii to six bit as a good old fashioned non owning naked pointer to const,
|
||||
// whose storage is owned by a const static which exists until the program terminates.
|
||||
static const uint8_t *ascii2six{ &ascii2six_ar[0] };
|
||||
// Compile time execution is C++ is a pain, because expressions are apt to unpredictably lose
|
||||
// their constexpr character for reasons that are far from clear.
|
||||
//
|
||||
// You can declare anything reasonable to be constexpr, and the compiler will not issue an
|
||||
// error message until the code that attempts to use what you have declared constexpr is
|
||||
// invoked from somewhere else "expression does not evaluate to constant"
|
||||
//
|
||||
// an assert in an expression evaluated at compile time does not trigger a run time error,
|
||||
// Instead the compiler reports that the expression did not evaluate to a constant,
|
||||
//
|
||||
// The error is confusing, because the error points to the declaration where the initialization
|
||||
// was invoked,instead of pointing to the assert.
|
||||
|
||||
// To debug code intended to be run at compile time, exercise it at run time with
|
||||
// auto ptr(std::make_unique<Class>());
|
||||
// at run time;
|
||||
|
||||
class charindex {
|
||||
public:
|
||||
std::array< uint8_t, 0x100> index{ 0, };
|
||||
// this non const array will become constexpr and be constructed at compile time
|
||||
// when an instance of this class is created in a constexpr expression.
|
||||
charindex() = delete;
|
||||
constexpr charindex(const uint8_t* p) {
|
||||
uint8_t pu{ 0 };
|
||||
do { index[pu++] = 0xFF; } while (pu);
|
||||
uint8_t i{ 0 };
|
||||
while (pu = static_cast<uint8_t>(p[i])) {
|
||||
index[pu] = i;
|
||||
i++;
|
||||
assert(i != 0); //prevents unending execution,
|
||||
// inside a constexp, generates an "expression does not evaluate to constant"
|
||||
// error at compile time, rather than breaking at run time.
|
||||
}
|
||||
index['o'] = index['O'] = 0;
|
||||
index['l'] = index['I'] = 1;
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr charindex ascii2six_ar(index2base64);
|
||||
|
||||
//
|
||||
//
|
||||
// You really have to write compile time code in templates as a language, which is the totally
|
||||
// obscure and hard to use language apt to generate remarkably voluminous error messages
|
||||
// will little obvious connection to the actual problem, and surprising result that are ver
|
||||
// difficult to predict in advance or understand at all.
|
||||
// In general, the better solution is to have a routine that is called once and only once at the
|
||||
// beginning of the program, which initializes a bunch of static const values, if that solution is
|
||||
// adequate, or to have a preproces routine written in python which generates the required C
|
||||
// files and header files.
|
||||
|
||||
// After this experiment in compile time code, I swear off it.
|
||||
// Table to convert ascii to six bit as a good old fashioned non owning naked pointer to const,
|
||||
// whose storage is owned by a const static which exists until the program terminates.
|
||||
const uint8_t* const ascii2six{ &ascii2six_ar.index[0] };
|
||||
|
||||
void ascii2test() {
|
||||
for (unsigned int i{ 0 }; i < 0x100;i++) {
|
||||
char v = i;
|
||||
unsigned int j = ascii2six[i];
|
||||
char w = index2base64[j];
|
||||
if (j < 64) {
|
||||
assert(v == w || v == 'I' || v == 'l' || v == 'o' || v == 'O');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Decode does not have an input span of encoded characters, but a char *, because it assumes
|
||||
// the string is always terminated by an invalid character, such as the trailing null at the end of
|
||||
|
2
stdafx.h
2
stdafx.h
@ -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 == 1 && wxRELEASE_NUMBER == 6 && wxSUBRELEASE_NUMBER == 0, "expecting wxWidgets 3.1.6");
|
||||
static_assert(wxMAJOR_VERSION == 3 && wxMINOR_VERSION == 1 && wxRELEASE_NUMBER == 7 && wxSUBRELEASE_NUMBER == 0, "expecting wxWidgets 3.1.7");
|
||||
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");
|
||||
|
@ -21,6 +21,8 @@ Namespace testbed is only defined in this cpp file, hence nothing within
|
||||
If it needs to interact with the outside world, should post a message
|
||||
analogously to queue_error_message, which then calls back to a
|
||||
routine in this file.*/
|
||||
void ascii2test();
|
||||
extern const uint8_t* const ascii2six;
|
||||
|
||||
namespace testbed {
|
||||
using ristretto255::hash, ristretto255::hsh, ristretto255::scalar,
|
||||
@ -42,12 +44,13 @@ No mechanism for input is available. You generally do not need it because you
|
||||
Uncaught exceptions result in unit test failure, but not in an error
|
||||
message in the main program UI.
|
||||
|
||||
If using a dialog, exceptions within the dialog will result in an error message in the
|
||||
If using a dialog, exceptions within the dialog will result in an error message in the
|
||||
main program UI, rather than in the unit test result, since the unit test
|
||||
is over before the dialog runs.
|
||||
*/
|
||||
|
||||
void testbed() {
|
||||
// queue_error_message("hello world");
|
||||
ascii2test();
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 35a6d7b15fedfdb5198bb6c28b31cda33b2c2a76
|
||||
Subproject commit 14c6b431626b817bd7564f4ee3480299307533fa
|
Loading…
Reference in New Issue
Block a user