Merge remote-tracking branch 'origin/docs' into cmake
This commit is contained in:
commit
4ad66f5c13
55
.gitattributes
vendored
55
.gitattributes
vendored
@ -38,32 +38,37 @@ Makefile text eol=lf encoding=utf-8
|
|||||||
|
|
||||||
# Force binary files to be binary
|
# Force binary files to be binary
|
||||||
|
|
||||||
# Archives
|
###############################################################################
|
||||||
*.7z filter=lfs diff=lfs merge=lfs -text
|
# Set default behavior for command prompt diff.
|
||||||
*.br filter=lfs diff=lfs merge=lfs -text
|
#
|
||||||
*.gz filter=lfs diff=lfs merge=lfs -text
|
# This is need for earlier builds of msysgit that does not have it on by
|
||||||
*.tar filter=lfs diff=lfs merge=lfs -text
|
# default for csharp files.
|
||||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
# Note: This is only used by command line
|
||||||
|
###############################################################################
|
||||||
# Documents
|
#*.cs diff=csharp
|
||||||
*.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 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
|
# diff behavior for common document formats
|
||||||
#
|
#
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
[core]
|
[core]
|
||||||
autocrlf = input
|
autocrlf = input
|
||||||
whitespace = -tab-in-indent,tabwidth=4,indent-with-non-tab,trailing-space,space-before-tab
|
whitespace = -tab-in-indent,tabwidth=4,indent-with-non-tab,trailing-space,space-before-tab
|
||||||
|
whitespace = fix
|
||||||
safecrlf=warn
|
safecrlf=warn
|
||||||
[apply]
|
[apply]
|
||||||
whitespace = fix
|
whitespace = fix
|
||||||
@ -15,3 +16,5 @@
|
|||||||
recurseSubmodules = on-demand
|
recurseSubmodules = on-demand
|
||||||
[fetch]
|
[fetch]
|
||||||
recurseSubmodules = on-demand
|
recurseSubmodules = on-demand
|
||||||
|
[diff]
|
||||||
|
submodule = log
|
||||||
|
12
.gitmodules
vendored
12
.gitmodules
vendored
@ -1,11 +1,9 @@
|
|||||||
[submodule "libsodium"]
|
[submodule "libsodium"]
|
||||||
path = libsodium
|
path = libsodium
|
||||||
url = https://github.com/jedisct1/libsodium.git
|
url = cpal.pw:~/libsodium.git
|
||||||
ignore = dirty
|
|
||||||
[submodule "wxWidgets"]
|
|
||||||
path = wxWidgets
|
|
||||||
url = https://github.com/wxWidgets/wxWidgets.git
|
|
||||||
ignore = dirty
|
|
||||||
[submodule "mpir"]
|
[submodule "mpir"]
|
||||||
path = 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
|
// copy constructor
|
||||||
sql(const sql& a) = delete;
|
sql(const sql& a) = delete;
|
||||||
// move constructor
|
// 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
|
// copy assignment
|
||||||
sql& operator=(const sql) = delete;
|
sql& operator=(const sql) = delete;
|
||||||
// Move assignment
|
// Move assignment
|
||||||
sql& operator=(sql&& p) {
|
sql& operator=(sql&& p) noexcept {
|
||||||
std::unique_ptr<Icompiled_sql>::reset(p.release());
|
std::unique_ptr<Icompiled_sql>::reset(p.release());
|
||||||
}
|
}
|
||||||
sql(Icompiled_sql* p) :std::unique_ptr<Icompiled_sql>(p) {}
|
sql(Icompiled_sql* p) :std::unique_ptr<Icompiled_sql>(p) {}
|
||||||
|
@ -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,
|
for anyone else to build your project, because they will have to, by hand,
|
||||||
tell your project where the libraries are on their system.
|
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
|
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
|
a very long time, and GitSubmodules allows this to scale, because the
|
||||||
local great big pile of source code references many independent and
|
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.
|
one module at at time.
|
||||||
|
|
||||||
# Passphrases
|
# Passphrases
|
||||||
|
|
||||||
All wallets now use random words - but you cannot carry an eighteen word random phrase though an airport in you head
|
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).
|
Should use [grammatically correct passphrases](https://github.com/lungj/passphrase_generator).
|
||||||
|
@ -188,7 +188,7 @@ way. Going to use base52 for any purposes for which my bright idea
|
|||||||
would have been useful, so should be rewritten to base64 regardless.
|
would have been useful, so should be rewritten to base64 regardless.
|
||||||
|
|
||||||
Using the hash of shared state goes together with immutable
|
Using the hash of shared state goes together with immutable
|
||||||
append only Merkle-patricia trees like ham and eggs, though you
|
append only Merkle‑patricia trees like ham and eggs, though you
|
||||||
don't need to keep the potentially enormous data structure around.
|
don't need to keep the potentially enormous data structure around.
|
||||||
When a connection has no activity for a little while, you can discard
|
When a connection has no activity for a little while, you can discard
|
||||||
everything except a very small amount of data, primarily the keys,
|
everything except a very small amount of data, primarily the keys,
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
body {
|
body {
|
||||||
max-width: 30em;
|
max-width: 30em;
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
|
font-family: "Georgia, Times New Roman", Times, serif;
|
||||||
|
font-style: normal;
|
||||||
|
font-variant: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
font-stretch: normal;
|
||||||
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
|
@ -49,13 +49,15 @@ takes a while. Normally when you make changes to the source code you
|
|||||||
should rebuild just the program, using `wallet.sln` on windows.
|
should rebuild just the program, using `wallet.sln` on windows.
|
||||||
To rebuild the documents after editing them, `docs/mkdocs.sh`
|
To rebuild the documents after editing them, `docs/mkdocs.sh`
|
||||||
|
|
||||||
winConfigure.bat also configures the repository you just created to
|
winConfigure.bat also configures the repository you just created to use
|
||||||
to use `.gitconfig` in the repository, causing git to to implement
|
`.gitconfig` in the repository, causing git to to implement GPG signed
|
||||||
GPG signed commits -- because [cryptographic software is under attack]
|
commits -- because [cryptographic software is under attack] from NSA
|
||||||
from NSA entryists and shills, who seek to introduce backdoors.
|
entryists and shills, who seek to introduce backdoors.
|
||||||
|
|
||||||
This may be inconvenient if you do not have `gpg` installed and set up.
|
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:
|
`.gitconfig` adds several git aliases:
|
||||||
|
|
||||||
1. `git lg` to display the gpg trust information for the last few commits.
|
1. `git lg` to display the gpg trust information for the last few commits.
|
||||||
@ -80,6 +82,13 @@ of Trust is too complicated and too user hostile to be workable or safe.
|
|||||||
|
|
||||||
Never --sign any Gpg key related to this project. --lsign it.
|
Never --sign any Gpg key related to this project. --lsign it.
|
||||||
|
|
||||||
|
`gitconfig` disallows merges unless you have told `gpg` to trust the
|
||||||
|
public key corresponding to the private key that signed the tip of
|
||||||
|
the root. So part of the pull request process is getting the puller to
|
||||||
|
trust your public key, and you will not be able to pull updates
|
||||||
|
unless you tell `gpg` to trust the key that is in the root directory as
|
||||||
|
`public_key.gpg`.
|
||||||
|
|
||||||
Never check any Gpg key related to this project against a public
|
Never check any Gpg key related to this project against a public
|
||||||
gpg key repository. It should not be there.
|
gpg key repository. It should not be there.
|
||||||
|
|
||||||
|
@ -176,6 +176,12 @@ Setting up an actual server is similar to setting up the virtual machine
|
|||||||
modelling it, except you have to worry about the server getting overloaded
|
modelling it, except you have to worry about the server getting overloaded
|
||||||
and locking up.
|
and locking up.
|
||||||
|
|
||||||
|
On an actual server, you probably want to totally disable passwords by corrupting the shadow file once you have `ssh` working.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
usermod -L root
|
||||||
|
```
|
||||||
|
|
||||||
If a server is configured with an [ample swap file] an overloaded server will
|
If a server is configured with an [ample swap file] an overloaded server will
|
||||||
lock up and have to be ungracefully powered down, which can corrupt the data
|
lock up and have to be ungracefully powered down, which can corrupt the data
|
||||||
on the server. If the swap file is inadequate, the OOM killer will shut
|
on the server. If the swap file is inadequate, the OOM killer will shut
|
||||||
|
52
docs/set_upstream.sh
Normal file
52
docs/set_upstream.sh
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
echo intended to be run in the event of moving repositories
|
||||||
|
git remote -v
|
||||||
|
git remote set-url origin git@cpal.pw:~/wallet.git
|
||||||
|
git submodule foreach --recursive 'git remote -v'
|
||||||
|
cd libsodium
|
||||||
|
git remote set-url origin git@cpal.pw:~/libsodium.git
|
||||||
|
git remote set-url upstream https://github.com/jedisct1/libsodium.git
|
||||||
|
cd ..
|
||||||
|
cd mpir
|
||||||
|
git remote set-url origin git@cpal.pw:~/mpir.git
|
||||||
|
git remote set-url upstream https://github.com/BrianGladman/mpir.git
|
||||||
|
cd ..
|
||||||
|
cd wxWidgets
|
||||||
|
git remote set-url origin git@cpal.pw:~/wxWidgets.git
|
||||||
|
git remote set-url upstream https://github.com/wxWidgets/wxWidgets.git
|
||||||
|
cd ..
|
||||||
|
cd wxWidgets/3rdparty/catch
|
||||||
|
git remote set-url origin git@cpal.pw:~/Catch.git
|
||||||
|
git remote set-url upstream https://github.com/wxWidgets/Catch.git
|
||||||
|
cd ../../..
|
||||||
|
cd wxWidgets/3rdparty/nanosvg
|
||||||
|
git remote set-url origin git@cpal.pw:~/nanosvg
|
||||||
|
git remote set-url upstream https://github.com/wxWidgets/nanosvg
|
||||||
|
cd ../../..
|
||||||
|
cd wxWidgets/3rdparty/pcre
|
||||||
|
git remote set-url origin git@cpal.pw:~/pcre
|
||||||
|
git remote set-url upstream https://github.com/wxWidgets/pcre
|
||||||
|
cd ../../..
|
||||||
|
cd wxWidgets/src/expat
|
||||||
|
git remote set-url origin git@cpal.pw:~/libexpat.git
|
||||||
|
git remote set-url upstream https://github.com/wxWidgets/libexpat.git
|
||||||
|
cd ../../..
|
||||||
|
cd wxWidgets/src/jpeg
|
||||||
|
git remote set-url origin git@cpal.pw:~/libjpeg-turbo.git
|
||||||
|
git remote set-url upstream https://github.com/wxWidgets/libjpeg-turbo.git
|
||||||
|
cd ../../..
|
||||||
|
cd wxWidgets/src/png
|
||||||
|
git remote set-url origin git@cpal.pw:~/libpng.git
|
||||||
|
git remote set-url upstream https://github.com/wxWidgets/libpng.git
|
||||||
|
cd ../../..
|
||||||
|
cd wxWidgets/src/tiff
|
||||||
|
git remote set-url origin git@cpal.pw:~/libtiff.git
|
||||||
|
git remote set-url upstream https://github.com/wxWidgets/libtiff.git
|
||||||
|
cd ../../..
|
||||||
|
cd wxWidgets/src/zlib
|
||||||
|
git remote set-url origin git@cpal.pw:~/zlib.git
|
||||||
|
git remote set-url upstream https://github.com/wxWidgets/zlib.git
|
||||||
|
cd ../../..
|
||||||
|
winConfigure.sh
|
@ -264,6 +264,40 @@ So, you can navigate to whole world’s public conversation through
|
|||||||
approved links and reply-to links – but not every spammer, scammer, and
|
approved links and reply-to links – but not every spammer, scammer, and
|
||||||
shill in the world can fill your feed with garbage.
|
shill in the world can fill your feed with garbage.
|
||||||
|
|
||||||
|
## Algorithm and data structure.
|
||||||
|
|
||||||
|
For this to work, the underlying structure needs to be something based on
|
||||||
|
the same principles as Git and git repositories, except that Git relies on
|
||||||
|
SSL and the Certificate Authority system to locate a repository, which
|
||||||
|
dangerous centralization would fail under the inevitable attack. It needs to
|
||||||
|
have instead for its repository name system a Kamelia distributed has
|
||||||
|
table within which local repositories find the network addresses of remote
|
||||||
|
repositories on the basis of the public key of a Zooko identity of a person
|
||||||
|
who pushed a tag or a branch to that repository, a branch being a thread,
|
||||||
|
and the branch head in this case being the most recent response to a thread
|
||||||
|
by a person you are following.
|
||||||
|
|
||||||
|
The Distributed hash table key will be:\
|
||||||
|
`human readable area of interest name/#public key of zooko name/
|
||||||
|
human readable branch name/#hash of data item`\
|
||||||
|
so that items that are likely to be looked up together will likely be near
|
||||||
|
each other on the same physical disk, and transmitted over the same
|
||||||
|
network connection. When someone approves of a text, then it goes into a
|
||||||
|
repository he controls or has write access to, and gets a corresponding key
|
||||||
|
in the distributed hash table.
|
||||||
|
|
||||||
|
The messages of the people you are following are likely to be in a
|
||||||
|
relatively small number of repositories, even if the total number of
|
||||||
|
repositories out there is enormous and the number of hashes in each
|
||||||
|
repository is enormous, so this algorithm and data structure will scale, and
|
||||||
|
the responses to that thread that they have approved, by people you are not
|
||||||
|
following, will be commits in that repository, that, by pushing their latest
|
||||||
|
response to that thread to a public repository, they committed to that
|
||||||
|
repository.
|
||||||
|
|
||||||
|
Each repository contains all the material the poster has approved, resulting
|
||||||
|
in considerable duplication, but not enormous duplication.
|
||||||
|
|
||||||
The underlying protocol and mechanism is that when you are following
|
The underlying protocol and mechanism is that when you are following
|
||||||
Bob, you get a Bob feed from a machine controlled by Bob, or controlled
|
Bob, you get a Bob feed from a machine controlled by Bob, or controlled
|
||||||
by someone that Bob has chosen to act on his behalf, and that when Bob
|
by someone that Bob has chosen to act on his behalf, and that when Bob
|
||||||
|
@ -14,18 +14,54 @@ namespace ro {
|
|||||||
return id ^ (id >> 32);
|
return id ^ (id >> 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
class charmap :public std::array<char, 0x100> {
|
class charmap {
|
||||||
public:
|
public:
|
||||||
|
std::array< char, 0x100> index{ 0, };
|
||||||
charmap() = delete;
|
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++) }) {
|
while (unsigned int pu{ static_cast<unsigned char>(*p++) }) {
|
||||||
assert((*this)[pu] == 0);
|
assert(index[pu] == 0);
|
||||||
(*this)[pu] = *q++;
|
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> {};
|
//template <> class base58<scalar> : public CompileSizedString<44> {};
|
||||||
static_assert(sizeof(base58<point>) == 46, "base58 point strings unexpected size");
|
static_assert(sizeof(base58<point>) == 46, "base58 point strings unexpected size");
|
||||||
|
|
||||||
@ -33,17 +69,18 @@ namespace ro {
|
|||||||
static constexpr char index2MpirBase58[] { "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv" };
|
static constexpr char index2MpirBase58[] { "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv" };
|
||||||
|
|
||||||
void map_base_from_mpir58(char* p) {
|
void map_base_from_mpir58(char* p) {
|
||||||
static const charmap map(index2MpirBase58, index2cryptoBase58);
|
static constexpr charmap map(index2MpirBase58, index2cryptoBase58);
|
||||||
while (unsigned int pu{ static_cast<unsigned char>(*p) }) {
|
while (uint8_t pu{ static_cast<uint8_t>(*p) }) {
|
||||||
*p++ = map[pu];
|
*p++ = map.index[pu];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void map_base_to_mpir58(const char* p, char* q, size_t count) {
|
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--) {
|
while (count--) {
|
||||||
unsigned int pu{ static_cast<unsigned char>(*p++) };
|
unsigned int pu{ static_cast<unsigned char>(*p++) };
|
||||||
char c{ map[pu] };
|
char c{ map.index[pu] };
|
||||||
if (c == '\0') throw NotBase58Exception();
|
if (c == '\0') throw NotBase58Exception();
|
||||||
*q++ = c;
|
*q++ = c;
|
||||||
}
|
}
|
||||||
|
105
slash6.cpp
105
slash6.cpp
@ -15,11 +15,30 @@
|
|||||||
static constexpr uint8_t index2base64[]{
|
static constexpr uint8_t index2base64[]{
|
||||||
"0123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz!$*+-_"
|
"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
|
// 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
|
// that it might be human typed and human transmitted, therefore maps 'o' and 'O' to '0', 'I' and
|
||||||
// 'l' to '1'
|
// 'l' to '1'
|
||||||
// uses six url safe additional characters !$*+-_ to bring it up to six bits
|
// 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");
|
static_assert(index2base64[63] == '_', "surprise numeral at 63");
|
||||||
|
|
||||||
// Being intended for small bits of data, assumes no whitespace within an entity
|
// 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
|
// will return a number of bits less than the size of the input bit buffer, less than the bitcount
|
||||||
// it was given.
|
// 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
|
// 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.
|
// 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
|
// 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
|
// 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
|
// will little obvious connection to the actual problem, and surprising result that are ver
|
||||||
// difficult to predict in advance or understand at all.
|
// 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
|
// 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
|
// 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,
|
static_assert(wxUSE_UNSAFE_WXSTRING_CONV == 1,
|
||||||
R"(In fully utf environment, (wallet.manifest plus
|
R"(In fully utf environment, (wallet.manifest plus
|
||||||
/utf-8 compile option) all string conversions are safe.)");
|
/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(wxUSE_IPV6 == 1, "IP6 unavailable in wxWidgets");
|
||||||
static_assert(WXWIN_COMPATIBILITY_3_0 == 0, "wxWidgets api out of date");
|
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_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
|
If it needs to interact with the outside world, should post a message
|
||||||
analogously to queue_error_message, which then calls back to a
|
analogously to queue_error_message, which then calls back to a
|
||||||
routine in this file.*/
|
routine in this file.*/
|
||||||
|
void ascii2test();
|
||||||
|
extern const uint8_t* const ascii2six;
|
||||||
|
|
||||||
namespace testbed {
|
namespace testbed {
|
||||||
using ristretto255::hash, ristretto255::hsh, ristretto255::scalar,
|
using ristretto255::hash, ristretto255::hsh, ristretto255::scalar,
|
||||||
@ -49,5 +51,6 @@ If using a dialog, exceptions within the dialog will result in an error message
|
|||||||
|
|
||||||
void testbed() {
|
void testbed() {
|
||||||
// queue_error_message("hello world");
|
// queue_error_message("hello world");
|
||||||
|
ascii2test();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ set -e
|
|||||||
set -x
|
set -x
|
||||||
git submodule foreach --recursive 'git reset --hard'
|
git submodule foreach --recursive 'git reset --hard'
|
||||||
git submodule foreach --recursive 'git clean -xdf'
|
git submodule foreach --recursive 'git clean -xdf'
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive --remote
|
||||||
git config --local include.path ../.gitconfig
|
git config --local include.path ../.gitconfig
|
||||||
set +e
|
set +e
|
||||||
set +x
|
set +x
|
||||||
|
Loading…
Reference in New Issue
Block a user