diff --git a/.gitattributes b/.gitattributes index d1a00e1..9e9a0f8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 # diff --git a/.gitconfig b/.gitconfig index de3488f..507547f 100644 --- a/.gitconfig +++ b/.gitconfig @@ -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 + diff --git a/.gitmodules b/.gitmodules index a333793..d7903af 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/db_accessors.h b/db_accessors.h index 61c0860..c065d62 100644 --- a/db_accessors.h +++ b/db_accessors.h @@ -25,11 +25,11 @@ namespace ro { // copy constructor sql(const sql& a) = delete; // move constructor - sql(sql&& p) :std::unique_ptr(p.release()) { } + sql(sql&& p) noexcept :std::unique_ptr(p.release()) { } // copy assignment sql& operator=(const sql) = delete; // Move assignment - sql& operator=(sql&& p) { + sql& operator=(sql&& p) noexcept { std::unique_ptr::reset(p.release()); } sql(Icompiled_sql* p) :std::unique_ptr(p) {} diff --git a/display_wallet.cpp b/display_wallet.cpp index 42e488d..133f485 100644 --- a/display_wallet.cpp +++ b/display_wallet.cpp @@ -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; diff --git a/docs/libraries.md b/docs/libraries.md index 2692e93..b0f0981 100644 --- a/docs/libraries.md +++ b/docs/libraries.md @@ -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). diff --git a/docs/rootDocs/README.md b/docs/rootDocs/README.md index e3a166c..9e11f6e 100644 --- a/docs/rootDocs/README.md +++ b/docs/rootDocs/README.md @@ -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. diff --git a/frame.cpp b/frame.cpp index 530dc1f..f18e2c8 100644 --- a/frame.cpp +++ b/frame.cpp @@ -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 db{ nullptr }; diff --git a/frame.h b/frame.h index 45a7a0d..302a3a3 100644 --- a/frame.h +++ b/frame.h @@ -1,7 +1,7 @@ #pragma once template // 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; - diff --git a/introspection_of_standard_C_types.h b/introspection_of_standard_C_types.h index a327418..a0146f2 100644 --- a/introspection_of_standard_C_types.h +++ b/introspection_of_standard_C_types.h @@ -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 std::enable_if_t, decltype(std::span(declval())[0] <=> std::span(declval())[0]) >operator <=>( diff --git a/libsodium b/libsodium index 561e556..012e892 160000 --- a/libsodium +++ b/libsodium @@ -1 +1 @@ -Subproject commit 561e556dad078af581f338fe3de9ee6362d28b16 +Subproject commit 012e892841ed6edc521f88a23b55863c7afe4622 diff --git a/localization.h b/localization.h index 0606243..c29c4aa 100644 --- a/localization.h +++ b/localization.h @@ -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[]; diff --git a/mpir b/mpir index 33be900..7e09c02 160000 --- a/mpir +++ b/mpir @@ -1 +1 @@ -Subproject commit 33be9007f95b85230da2330ef3ed525896370cc2 +Subproject commit 7e09c025f6061863e58a2cc0a0aefa8b5fa8496b diff --git a/mpir_and_base58.cpp b/mpir_and_base58.cpp index 1f7ce61..57c4846 100644 --- a/mpir_and_base58.cpp +++ b/mpir_and_base58.cpp @@ -14,18 +14,54 @@ namespace ro { return id ^ (id >> 32); } - class charmap :public std::array { + 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(*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(*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 : public CompileSizedString<44> {}; static_assert(sizeof(base58) == 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(*p) }) { - *p++ = map[pu]; + static constexpr charmap map(index2MpirBase58, index2cryptoBase58); + while (uint8_t pu{ static_cast(*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(*p++) }; - char c{ map[pu] }; + char c{ map.index[pu] }; if (c == '\0') throw NotBase58Exception(); *q++ = c; } diff --git a/ristretto255.cpp b/ristretto255.cpp index 0a3c2e6..8e2e37c 100644 --- a/ristretto255.cpp +++ b/ristretto255.cpp @@ -143,4 +143,3 @@ template<> CompileSizedString < (sizeof(scalar) * 8 + 5) / 6> ); return sz; } - diff --git a/ristretto255.h b/ristretto255.h index 2892367..0460991 100644 --- a/ristretto255.h +++ b/ristretto255.h @@ -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&& in) : + explicit constexpr point(std::array&& in) : blob{ std::forward>(in) } { }; static_assert(crypto_core_ristretto255_BYTES == 32, "256 bit points expected"); ~point() = default; diff --git a/slash6.cpp b/slash6.cpp index 06fb72b..8598b45 100644 --- a/slash6.cpp +++ b/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 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()); +// 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(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 diff --git a/stdafx.h b/stdafx.h index 3980af4..c348c77 100644 --- a/stdafx.h +++ b/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"); diff --git a/testbed.cpp b/testbed.cpp index c6dc1b6..b76514e 100644 --- a/testbed.cpp +++ b/testbed.cpp @@ -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(); } } diff --git a/wxWidgets b/wxWidgets index 35a6d7b..14c6b43 160000 --- a/wxWidgets +++ b/wxWidgets @@ -1 +1 @@ -Subproject commit 35a6d7b15fedfdb5198bb6c28b31cda33b2c2a76 +Subproject commit 14c6b431626b817bd7564f4ee3480299307533fa