2022-02-16 00:53:01 -05:00
# include " stdafx.h "
2022-03-07 23:46:14 -05:00
using ro : : msec , ro : : msec_since_epoch , ro : : bin2hex , ro : : to_base64_string , ristretto255 : : hash ,
ristretto255 : : hsh , ristretto255 : : scalar ,
2022-02-16 00:53:01 -05:00
ristretto255 : : point , ro : : base58 ;
class FailureToThrowExpectedException : public MyException {
public :
using MyException : : MyException ;
FailureToThrowExpectedException ( ) noexcept :
MyException ( FailureToThrowExpectedException_sz ) { }
} ;
2022-03-26 23:46:34 -04:00
class EndUnitTestOfExceptions : public MyException {
2022-02-16 00:53:01 -05:00
public :
using MyException : : MyException ;
2022-03-26 23:46:34 -04:00
EndUnitTestOfExceptions ( ) noexcept :
2022-02-16 00:53:01 -05:00
MyException ( " \t \t End unit test " ) { }
} ;
int errorCode { 0 } ;
std : : string szError ;
static bool StartUnitTest ( void ) ;
static bool unexpected_unit_test ( void ) ;
static bool ( * unit_test_action ) ( void ) { & StartUnitTest } ;
static bool ( * next_action ) ( void ) { & unexpected_unit_test } ;
static bool noaction ( ) { return false ; } ;
static bool EndUnitTest ( void ) ;
static bool unexpected_unit_test ( ) {
unit_test_action = & EndUnitTest ;
next_action = unit_test_action ;
szError = " Faulty flow of control in unit test itself " ;
ILogError ( szError . c_str ( ) ) ;
errorCode = 1005 ;
return true ;
}
class UnitTestModalHook : public wxModalDialogHook
{
protected :
virtual int Enter ( wxDialog * dlg ) wxOVERRIDE
{
wxLogMessage (
2022-05-22 05:36:23 -04:00
wxT ( " Showing %s:%s dialog " ) ,
2022-02-16 00:53:01 -05:00
dlg - > GetClassInfo ( ) - > GetClassName ( ) ,
dlg - > GetLabel ( )
) ;
auto x = dlg - > GetId ( ) ;
switch ( x ) {
case myID_ERRORMESSAGE :
2022-05-22 05:36:23 -04:00
wxLogMessage ( wxT ( " \t Error message modal dialog " ) ) ;
2022-02-16 00:53:01 -05:00
unit_test_action = next_action ;
2022-05-22 05:36:23 -04:00
wxLogMessage ( wxT ( " \t Closing dialog " ) ) ;
2022-02-16 00:53:01 -05:00
return wxID_OK ;
default :
return wxID_NONE ;
}
}
} ;
static UnitTestModalHook modal_dialog_hook ;
static bool EndUnitTest ( ) {
unit_test_action = & noaction ;
modal_dialog_hook . Unregister ( ) ;
next_action = & unexpected_unit_test ;
static std : : string intestbed ( " Testbed: " ) ;
try {
testbed : : testbed ( ) ;
2022-03-26 23:46:34 -04:00
throw EndUnitTestOfExceptions ( ) ;
2022-02-16 00:53:01 -05:00
}
2022-03-26 23:46:34 -04:00
catch ( const EndUnitTestOfExceptions & ) { }
2022-02-16 00:53:01 -05:00
catch ( const std : : exception & e ) {
errorCode = 1001 ;
szError = intestbed + e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( . . . ) {
szError = intestbed + sz_unknown_error ;
errorCode = 1000 ;
ILogError ( szError . c_str ( ) ) ;
}
if ( errorCode = = 0 ) {
ILogMessage ( " Passed Unit Test " ) ;
}
else {
2022-05-22 05:36:23 -04:00
wxLogMessage ( wxT ( " \n Failed Unit Test \n unit test error %d \n %s " ) ,
2022-03-07 23:46:14 -05:00
errorCode , _wx ( szError . c_str ( ) )
) ;
2022-02-16 00:53:01 -05:00
}
if ( singletonApp - > m_unit_test & & ! singletonApp - > m_display ) {
2022-03-07 23:46:14 -05:00
singletonFrame - > Close ( ) ; //Shuts down program immediately.
// When the program is closed, now or later, will return errorCode.
2022-02-16 00:53:01 -05:00
}
return true ;
}
static bool curve_order ( void ) {
unit_test_action = & EndUnitTest ;
next_action = unit_test_action ;
2022-03-07 23:46:14 -05:00
ILogMessage (
" \t Checking mpz arbitrary precision integer conversions to cryptographic values. "
) ;
2022-02-16 00:53:01 -05:00
try {
scalar max ( - 1 ) ;
2022-03-07 23:46:14 -05:00
wxString curve_order_as_unreduced_scalar { _wx ( bin2hex ( scalar : : scOrder ) ) } ;
2022-02-16 00:53:01 -05:00
ro : : CompileSizedString < sizeof ( scalar ) * 2 > sz ;
mpz_get_str ( sz , 16 , mpir : : ristretto25519_curve_order ) ;
2022-03-07 23:46:14 -05:00
wxString curve_order_as_mpir_bigint { _wx ( sz ) } ;
if ( curve_order_as_unreduced_scalar ! = curve_order_as_mpir_bigint ) {
throw MyException ( " inconsistent curve order " ) ;
}
scalar sc_zero { 0 } ;
scalar sc_one { 1 } ;
scalar sc1 { scalar : : random ( ) } ;
scalar sc2 { scalar : : random ( ) } ;
assert ( sc1 ! = sc2 ) ;
assert ( sc1 < sc2 | | sc1 > sc2 ) ;
assert ( sc1 < scalar : : scOrder ) ;
assert ( max < scalar : : scOrder ) ;
assert ( max > sc_zero ) ;
assert ( max + sc_one = = scalar ( 0 ) ) ;
assert ( sc_one + max < scalar : : scOrder ) ;
assert ( ! ( sc_one < scalar : : scOrder + sc_one ) ) ;
assert ( sc_one = = scalar : : scOrder + sc_one ) ;
assert ( ( sc_one + max < scalar : : scOrder ) ) ;
assert ( sc1 . valid ( ) ) ;
assert ( ! scalar : : scOrder . valid ( ) ) ;
assert ( ! scalar ( 0 ) . valid ( ) ) ;
bool f = true
& & sc1 ! = sc2
& & sc1 < sc2 | | sc1 > sc2
& & ( sc1 < scalar : : scOrder
& & max < scalar : : scOrder
& & max > sc_zero
& & max + sc_one = = sc_zero
& & sc_one + max < scalar : : scOrder
& & ! ( sc_one < scalar : : scOrder + sc_one )
& & sc_one = = scalar : : scOrder + sc_one
& & ( sc_one + max < scalar : : scOrder )
& & sc1 . valid ( ) )
& & ! scalar : : scOrder . valid ( )
& & ! scalar ( 0 ) . valid ( ) ;
if ( ! f ) throw MyException ( " scalar range and validation messed up " ) ;
2022-02-16 00:53:01 -05:00
}
catch ( const std : : exception & e ) {
errorCode = 30 ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( . . . ) {
szError = sz_unknown_error ;
errorCode = 30 ;
ILogError ( szError . c_str ( ) ) ;
}
return true ;
}
static bool checkDataConversionsProduceExpected ( void ) {
unit_test_action = & curve_order ;
next_action = unit_test_action ;
ILogMessage ( " \t Checking hashing, string conversion, scalar and point generation. " ) ;
try {
char brownfox [ ] { " the quick brown fox jumped over the lazy dog " } ;
char * p_brownfox { brownfox } ;
std : : array < char , 27 > ar_brownfox { " the quick brown fox jumped " } ;
char * p_over { p_brownfox + 27 } ;
wxString wx_over { p_over } ;
2022-03-07 23:46:14 -05:00
* - - ar_brownfox . end ( ) = ' ' ; //fixes the trailing nul appended to ar_brownfox, so that it is
// no longer a null terminated string.
2022-02-16 00:53:01 -05:00
wxString wx_jumped ( & ar_brownfox [ 0 ] , std : : size ( ar_brownfox ) ) ;
hsh hsh1 ;
hsh hsh2 ;
hsh1 < < brownfox ;
hsh2 < < ar_brownfox < < wx_over . ToUTF8 ( ) ;
hash hash1 ( hsh1 ) ;
hash hash2 ( hsh2 ) ;
hash hash3 ( hsh ( ) < < ar_brownfox < < wx_over . ToUTF8 ( ) ) ;
if ( false
| | hash1 ! = hash2
| | hash1 ! = hash ( p_brownfox )
| | hash1 ! = hash3
| | hash ( p_brownfox ) ! = hash ( hsh ( ) < < ar_brownfox < < wx_over . ToUTF8 ( ) )
| | hash ( p_brownfox ) ! = hash ( ar_brownfox , wx_over . ToUTF8 ( ) )
| | hash ( brownfox ) ! = hash ( ar_brownfox , p_over )
) throw MyException ( sz_inconsistent_hash ) ;
{
scalar scl_b { scalar : : random ( ) } ;
point pt_a { scl_b . timesBase ( ) } ;
std : : string str_pt_a { & ( base58 ( pt_a ) ) [ 0 ] } ;
2022-03-07 23:46:14 -05:00
if ( pt_a ! = base58 < point > : : bin ( str_pt_a . c_str ( ) ) ) {
MyException ( " Round trip from and two base 58 representation failed " ) ;
}
2022-02-16 00:53:01 -05:00
}
{
point pt_b ;
try {
2022-03-07 23:46:14 -05:00
pt_b = base58 < point > : : bin (
" galvhAmKLYPjiEUbiDvE54pnKhhdYSxC3G5p9czHPuKaB not base 58 because uses 'l' "
) ;
2022-02-16 00:53:01 -05:00
throw FailureToThrowExpectedException ( ) ;
assert ( false ) ;
}
catch ( const NotBase58Exception & ) { }
try {
2022-03-07 23:46:14 -05:00
pt_b = base58 < point > : : bin (
" AWyxo34SopBAtWy9qH6RfheK3xUCmu9fgF4ZjHwT9RVrS wrong checksum "
) ;
2022-02-16 00:53:01 -05:00
throw FailureToThrowExpectedException ( ) ;
assert ( false ) ;
}
catch ( const BadStringRepresentationOfCryptoIdException & ) { }
try {
2022-03-07 23:46:14 -05:00
pt_b = base58 < point > : : bin (
" MaevYgZimDjzQWxbnHcNdMqkMVmjWpYEqippTfj9y6U7sM overlong error "
) ;
2022-02-16 00:53:01 -05:00
throw FailureToThrowExpectedException ( ) ;
assert ( false ) ;
}
catch ( const OversizeBase58String & ) { }
}
2022-03-07 23:46:14 -05:00
hash < 512 > hash_a { ar_brownfox , wx_over . ToUTF8 ( ) , hash1 , base58 < point > : : bin (
" AWyxo34SopBAtWy9qH6RfheK3xUCmu9fgF4ZjHwT9RVrP "
) } ;
2022-02-16 00:53:01 -05:00
std : : string str_hash_a { & ( base58 ( hash_a ) ) [ 0 ] } ;
scalar scl_a { hash_a } ;
std : : string str_sclr_a = & ( base58 ( scl_a ) ) [ 0 ] ;
assert ( base58 < scalar > : : bin ( str_sclr_a . c_str ( ) ) = = scl_a ) ;
point pt_a { scl_a . timesBase ( ) } ;
std : : string str_pt_a = & ( base58 ( pt_a ) ) [ 0 ] ;
assert ( base58 < point > : : bin ( str_pt_a . c_str ( ) ) = = pt_a ) ;
hash < 256 > hash_b { hash_a , str_hash_a , scl_a , str_sclr_a , pt_a , str_pt_a , 33 , 66ull } ;
2022-03-07 23:46:14 -05:00
if ( base58 ( hash_b ) . operator std : : string ( ) ! =
" i22EVNPsKRjdxYTZrPPu9mx6vnrBjosFix5F4gn2mb2kF "
) {
throw MyException ( " unexpected hash of transformations " ) ;
}
2022-02-16 00:53:01 -05:00
}
catch ( const std : : exception & e ) {
errorCode = 27 ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( . . . ) {
szError = sz_unknown_error ;
errorCode = 26 ;
ILogError ( szError . c_str ( ) ) ;
}
return true ;
}
static bool CheckForUtfEnvironment ( void ) {
ILogMessage ( " \t Checking for UTF locale. " ) ;
try {
bool utfEnvironment { true } ;
2022-05-22 05:36:23 -04:00
wxString utfError { wxT ( " " ) } ;
2022-02-16 00:53:01 -05:00
if constexpr ( b_WINDOWS ) {
auto ACP { GetACP ( ) } ;
utfEnvironment = utfEnvironment & & ( ACP = = 65001 ) ;
if ( ! utfEnvironment ) {
2022-05-22 05:36:23 -04:00
utfError + = wxString : : Format ( wxT ( " current code page %d—should be 65001☹, " ) , ACP ) ;
2022-02-16 00:53:01 -05:00
}
}
auto FontEncoding { wxLocale : : GetSystemEncoding ( ) } ;
utfEnvironment = utfEnvironment & & ( false
| | ( FontEncoding = = wxFONTENCODING_UTF8 )
| | ( FontEncoding = = wxFONTENCODING_UTF16BE )
| | ( FontEncoding = = wxFONTENCODING_UTF16LE )
| | ( FontEncoding = = wxFONTENCODING_UTF32BE )
| | ( FontEncoding = = wxFONTENCODING_UTF32LE )
| | ( FontEncoding = = wxFONTENCODING_SYSTEM )
) ;
if ( ! utfEnvironment ) {
2022-05-22 05:36:23 -04:00
utfError = wxString : : Format ( wxT ( " %swxFontEncoding %d—should be %d☹ " ) ,
2022-02-16 00:53:01 -05:00
utfError ,
FontEncoding ,
wxFONTENCODING_UTF8 ) ;
2022-05-22 05:36:23 -04:00
wxLogMessage ( wxT ( " %s " ) , utfError ) ;
2022-02-16 00:53:01 -05:00
}
if ( ! utfEnvironment ) { throw MyException ( utfError ) ; }
}
catch ( const std : : exception & e ) {
errorCode = 24 ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( . . . ) {
szError = sz_unknown_error ;
errorCode = 24 ;
ILogError ( szError . c_str ( ) ) ;
}
unit_test_action = & checkDataConversionsProduceExpected ;
return true ;
}
static bool Waiting_for_delayed_dummy_error_message ( void ) {
static int count ( 12 ) ;
if ( ( - - count ) ) {
ILogMessage ( " \t \t Waiting for second dummy error message " ) ;
}
else {
errorCode = 21 ;
szError = " Delayed dummy error message UI failed show up " ;
ILogError ( szError . c_str ( ) ) ;
unit_test_action = next_action ;
}
return true ;
}
class UnitTestOfException : public MyException {
public :
using MyException : : MyException ;
UnitTestOfException ( ) noexcept :
MyException ( " \t \t Not a real error, merely at test of error handling UI " ) { }
} ;
static bool TestDelayedErrorDialog ( void ) {
unit_test_action = & Waiting_for_delayed_dummy_error_message ;
next_action = & CheckForUtfEnvironment ;
ILogMessage ( " \t \t throwing exception " ) ;
2022-03-07 23:46:14 -05:00
throw UnitTestOfException ( ) ; //If we throw exception before setting the next unit test,
// this unit test gets endless recalled.
2022-02-16 00:53:01 -05:00
return true ;
}
static bool Waiting_for_dummy_error_message ( void ) {
static int count ( 12 ) ;
if ( ( - - count ) ) {
ILogMessage ( " \t \t Waiting for dummy error message " ) ;
}
else {
errorCode = 21 ;
szError = " Dummy error message UI failed show up " ;
ILogError ( szError . c_str ( ) ) ;
unit_test_action = next_action ;
}
return true ;
}
static bool TestErrorDialog ( void ) {
unit_test_action = & Waiting_for_dummy_error_message ;
next_action = & TestDelayedErrorDialog ;
ILogMessage ( " \t Test error handling UI. " ) ;
ILogMessage ( " \t \t posting delayed error message \n \t \t as if inside an exception handler or destructor " ) ;
auto event = new wxCommandEvent ( wxEVT_MENU , myID_ERRORMESSAGE ) ;
wxQueueEvent ( singletonFrame - > GetMenuBar ( ) , event ) ;
2022-04-02 22:07:41 -04:00
// wxQueueEvent(singletonApp, event);
2022-02-16 00:53:01 -05:00
unit_test_action = & Waiting_for_dummy_error_message ;
return true ;
}
static bool WalletCreationUI ( void ) {
// singletonFrame->menu_OnNewWallet.queue_event();
unit_test_action = & TestErrorDialog ;
return true ;
}
static bool OpenWallet ( void ) {
try {
2022-03-07 23:46:14 -05:00
/* If LastUsed is the empty string, check if default filename exists. If it exists, set
Last Used to default file name
If LastUsed is not the empty string , or no longer the empty string , attempt to open
indicated file . If open fails , or reading the opened file produces bad results , abort with
exception
If LastUsed is still the empty string , attempt to create default filename . 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 , should bring up the more complex UI for constructing or selecting your
wallet file . */
2022-02-16 00:53:01 -05:00
ILogMessage ( " \t Wallet file " ) ;
assert ( singletonApp - > pConfig ) ;
2022-05-22 05:36:23 -04:00
singletonApp - > pConfig - > SetPath ( wxT ( " /Wallet " ) ) ;
wxFileName LastUsedSqlite ( singletonApp - > pConfig - > Read ( wxT ( " LastUsed " ) , wxT ( " " ) ) ) ;
2022-02-16 00:53:01 -05:00
bool fWalletNameOk { false } ;
wxStandardPaths & StandardPaths ( wxStandardPaths : : Get ( ) ) ;
StandardPaths . UseAppInfo ( 3 ) ;
wxFileName DefaultSqlite ( StandardPaths . GetUserLocalDataDir ( ) , " default.wallet " ) ;
2022-05-22 05:36:23 -04:00
wxLogMessage ( wxT ( " \t \t LastUsed= \" %s \" " ) , LastUsedSqlite . GetFullPath ( ) ) ;
2022-02-16 00:53:01 -05:00
if ( ! LastUsedSqlite . IsOk ( ) | | ! LastUsedSqlite . HasName ( ) | | ! LastUsedSqlite . HasExt ( ) ) {
2022-05-22 05:36:23 -04:00
wxLogMessage ( wxT ( " \t \t Default= \" %s \" " ) , DefaultSqlite . GetFullPath ( ) ) ;
2022-02-16 00:53:01 -05:00
assert ( DefaultSqlite . IsOk ( ) & & DefaultSqlite . HasName ( ) & & DefaultSqlite . HasExt ( ) ) ;
if ( DefaultSqlite . FileExists ( ) ) {
LastUsedSqlite = DefaultSqlite ;
2022-05-22 05:36:23 -04:00
singletonApp - > pConfig - > Write ( wxT ( " LastUsed " ) , DefaultSqlite . GetFullPath ( ) ) ;
2022-02-16 00:53:01 -05:00
fWalletNameOk = true ;
}
}
else fWalletNameOk = true ;
std : : unique_ptr < ISqlite3 > db ;
if ( fWalletNameOk ) {
if ( ! LastUsedSqlite . FileExists ( ) ) throw MyException ( " Expected wallet file not found " ) ;
db . reset ( Sqlite3_open ( LastUsedSqlite . GetFullPath ( ) . ToUTF8 ( ) ) ) ;
sql_read_from_misc read_from_misc ( db . get ( ) ) ;
if ( ! read_from_misc ( 1 ) | | read_from_misc . value < int64_t > ( ) ! = WALLET_FILE_IDENTIFIER ) throw MyException ( " Unrecognizable wallet file format " ) ;
if ( ! read_from_misc ( 2 ) | | read_from_misc . value < int64_t > ( ) ! = WALLET_FILE_SCHEMA_VERSION_0_0 ) throw MyException ( " Unrecognized wallet schema " ) ;
if ( ! read_from_misc ( 4 ) ) throw MyException ( " Mastersecret missing " ) ;
ristretto255 : : CMasterSecret MasterSecret ( * read_from_misc . value < ristretto255 : : scalar > ( ) ) ;
ro : : sql read_keys ( db . get ( ) , R " |(SELECT * FROM " Keys " LIMIT 5;)| " ) ;
sql_read_name read_name ( db . get ( ) ) ;
// db.reset(nullptr);// Force error of premature destruction of Isqlite3
while ( read_keys . step ( ) = = Icompiled_sql : : ROW ) {
auto pubkey = read_keys . column < ristretto255 : : point > ( 0 ) ;
auto id = read_keys . column < int > ( 1 ) ;
auto use = read_keys . column < int > ( 2 ) ;
2022-03-07 23:46:14 -05:00
if ( use ! = 1 ) {
throw MyException ( R " |(Unknown secret key algorithm index in " Names " table) | " ) ;
}
if ( ! read_name ( id ) ) {
throw MyException ( R " |(No entry corresponding to public key in " Names " table) | " ) ;
}
2022-02-16 00:53:01 -05:00
const char * name = read_name . name ( ) ;
if ( MasterSecret ( name ) . timesBase ( ) ! = * pubkey ) throw MyException ( R " |(Public key of name fails to correspond)| " ) ;
2022-05-22 05:36:23 -04:00
wxLogMessage ( wxT ( " \t \t \" %s \" has expected public key 0x%s " ) , name , ( wxString ) ( bin2hex ( * pubkey ) ) ) ;
2022-02-16 00:53:01 -05:00
}
}
else {
// At this point in the code the filename LastUsedSqlite is a bad filename, normally the empty string, and the default wallet file does not exist in the default location.
// Construct default wallet and filename*/
wxFileName path { StandardPaths . GetUserLocalDataDir ( ) } ;
try {
// Disk operations to create wallet, which may throw.
// This try/catch block exists to catch disk io issues.
if ( ! path . DirExists ( ) ) path . Mkdir ( ) ;
if ( ! DefaultSqlite . DirExists ( ) ) DefaultSqlite . Mkdir ( ) ;
db . reset ( Sqlite3_create ( DefaultSqlite . GetFullPath ( ) . ToUTF8 ( ) ) ) ;
db - > exec ( R " |(
PRAGMA journal_mode = WAL ;
PRAGMA synchronous = 1 ;
BEGIN TRANSACTION ;
CREATE TABLE " Keys " (
" pubkey " BLOB NOT NULL UNIQUE PRIMARY KEY ,
" id " integer NOT NULL ,
" use " INTEGER NOT NULL ) ;
CREATE TABLE " Names " (
" name " TEXT NOT NULL UNIQUE
) ;
CREATE TABLE " Misc " (
" index " INTEGER NOT NULL UNIQUE PRIMARY KEY ,
" m " BLOB
) ;
COMMIT ; ) | " );
LastUsedSqlite = DefaultSqlite ;
2022-05-22 05:36:23 -04:00
singletonApp - > pConfig - > Write ( wxT ( " LastUsed " ) , DefaultSqlite . GetFullPath ( ) ) ;
wxLogMessage ( wxT ( " \t \t Constructing default wallet %s " ) , DefaultSqlite . GetFullPath ( ) ) ;
2022-02-16 00:53:01 -05:00
// We now have a working wallet file with no valid data. Attempting to create a strong random secret, a name, and public and private keys for that name.
2022-05-22 05:36:23 -04:00
wxLogMessage ( wxT ( " \t \t Generating random 128 bit wallet secret " ) ) ;
2022-02-16 00:53:01 -05:00
auto text_secret { DeriveTextSecret ( ristretto255 : : scalar : : random ( ) , 1 ) } ;
ro : : msec start_time { ro : : msec_since_epoch ( ) } ;
ristretto255 : : CMasterSecret MasterSecret ( DeriveStrongSecret ( & text_secret [ 0 ] ) ) ;
decltype ( start_time ) end_time { ro : : msec_since_epoch ( ) } ;
2022-05-22 05:36:23 -04:00
wxLogMessage ( wxT ( " \t \t Strong secret derivation took %d milliseconds " ) , ( end_time - start_time ) . count ( ) ) ;
2022-02-16 00:53:01 -05:00
sql_update_to_misc update_to_misc ( db . get ( ) ) ;
update_to_misc ( 1 , WALLET_FILE_IDENTIFIER ) ;
update_to_misc ( 2 , WALLET_FILE_SCHEMA_VERSION_0_0 ) ;
update_to_misc ( 3 , & text_secret [ 0 ] ) ;
update_to_misc ( 4 , MasterSecret ) ;
sql_insert_name insert_name ( db . get ( ) ) ;
const char cpsz [ ] { " Unit Tester " } ;
insert_name ( cpsz , MasterSecret ( cpsz ) . timesBase ( ) ) ;
}
catch ( const MyException & e ) {
ILogError ( R " |(Failed to create or failed to properly initialize wallet)| " ) ;
errorCode = 20 ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
} // End of wallet creation branch
}
catch ( const std : : exception & e ) {
errorCode = 20 ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( . . . ) {
szError = sz_unknown_error ;
errorCode = 20 ;
ILogError ( szError . c_str ( ) ) ;
}
unit_test_action = & WalletCreationUI ;
return true ;
}
static bool StandardPaths ( void ) {
wxStandardPaths & StandardPaths { wxStandardPaths : : Get ( ) } ;
StandardPaths . UseAppInfo ( 3 ) ;
ILogMessage ( " \t Standard paths " ) ;
wxLogMessage ( " \t \t wxStandardPaths::GetUserLocalDataDir() \t %s " , StandardPaths . GetUserLocalDataDir ( ) ) ;
wxLogMessage ( " \t \t wxStandardPaths::GetUserDataDir() \t %s " , StandardPaths . GetUserDataDir ( ) ) ;
wxLogMessage ( " \t \t wxStandardPaths::GetLocalDataDir() \t %s " , StandardPaths . GetLocalDataDir ( ) ) ;
unit_test_action = & OpenWallet ;
return true ;
}
static bool TestErrorHandlingUI ( void ) {
next_action = unit_test_action = & StandardPaths ;
throw UnitTestOfException ( ) ; //If we throw exception before setting the next unit test, this unit test gets endless recalled.
return true ;
}
static uintmax_t shared_secrets_per_second { 0 } ;
namespace ristretto255 {
static bool TestSecretGeneration ( void ) {
try {
ILogMessage ( " \t Test pseudorandom generation of secrets from scalar(7). " ) ;
auto text_secret { DeriveTextSecret ( scalar ( 7 ) , 1 ) } ;
if ( text_secret = = decltype ( text_secret ) { " Rmc mLSu mDk DhfV 9gBK kKj " } ) {
ILogMessage ( " \t \t Obtained expected text secret from scalar(7) " ) ;
}
else {
errorCode = 18 ;
szError = " Fail \t Unexpected text secret from scalar(7) " ;
ILogError ( szError . c_str ( ) ) ;
}
if ( std : : popcount ( 0x0123456789ABCDEFu ) ! = 0x20 ) throw MyException ( sz_bitcount_incorrect ) ;
if ( rounded_log2 ( 0x345678u ) ! = 22 ) throw MyException ( sz_rounded_log2_incorrect ) ;
{ uint64_t v { 0x123456789ABCDEFu } ;
for ( unsigned int i = 0 ; i < = 64 ; i + + ) {
if ( i ! = std : : countr_zero ( v ) ) throw MyException ( sz_count_of_trailing_zero_bits_incorrect ) ;
v < < = 1 ;
}
}
if ( ! ( singletonApp - > m_quick_unit_test ) ) {
2022-05-04 23:52:12 -04:00
auto start_time { std : : chrono : : high_resolution_clock : : now ( ) } ;
2022-02-16 00:53:01 -05:00
auto s1 { DeriveStrongSecret ( & text_secret [ 0 ] ) } ;
2022-05-04 23:52:12 -04:00
auto end_time { std : : chrono : : high_resolution_clock : : now ( ) } ;
2022-02-16 00:53:01 -05:00
if ( s1 = = scalar ( { 0x59 , 0xf6 , 0x73 , 0xb4 , 0xa0 , 0xc7 , 0x0d , 0x8b , 0x51 , 0xe5 , 0x87 , 0x7c , 0xf5 , 0xd7 , 0x6f , 0x55 , 0x31 , 0xa7 , 0x0b , 0x14 , 0x28 , 0x54 , 0x97 , 0x08 , 0x9f , 0x27 , 0x83 , 0xe1 , 0xc7 , 0x5f , 0x55 , 0x0f } ) ) {
wxLogMessage ( " \t \t Obtained expected strong scalar secret from scalar(7) " ) ;
}
else {
errorCode = 17 ;
szError = " Fail \t Unexpected strong scalar secret from text secret " ;
ILogError ( szError . c_str ( ) ) ;
}
2022-05-04 23:52:12 -04:00
auto time_taken { std : : chrono : : duration_cast < std : : chrono : : microseconds > ( end_time - start_time ) } ;
wxLogMessage ( " \t \t Strong secret derivation took %lld microseconds " , time_taken . count ( ) ) ;
uintmax_t strengthening = time_taken . count ( ) * shared_secrets_per_second / 1000000 ;
2022-02-16 00:53:01 -05:00
wxLogMessage ( " \t \t slows brute force password search by a factor of %ju " , strengthening ) ;
wxLogMessage ( " \t \t strengthens password by %u bits " ,
static_cast < unsigned int > ( rounded_log2 ( static_cast < uint32_t > ( strengthening ) ) ) ) ;
auto s2 { DeriveSecret ( s1 , 1 ) } ;
if ( s2 = = scalar ( { 0x02 , 0x98 , 0x0e , 0x7d , 0x12 , 0xe8 , 0x23 , 0xeb , 0xa2 , 0x08 , 0xa8 , 0x51 , 0x73 , 0x27 , 0x96 , 0xc6 , 0xb9 , 0x12 , 0x60 , 0x27 , 0x25 , 0x24 , 0x75 , 0xa3 , 0x4e , 0x2a , 0x6a , 0x44 , 0x56 , 0xab , 0x95 , 0x06 } ) ) {
ILogMessage ( " \t \t Obtained expected fast scalar secret from strong scalar secret " ) ;
}
else {
errorCode = 16 ;
szError = " Fail \t Unexpected fast scalar secret from strong scalar secret " ;
ILogError ( szError . c_str ( ) ) ;
}
}
else {
ILogMessage ( " \t \t Skipping test of strong secret generation in quick unit test, because strong secret generation is deliberately slow. " ) ;
}
}
catch ( const std : : exception & e ) {
errorCode = 16 ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( . . . ) {
szError = sz_unknown_error ;
errorCode = 16 ;
ILogError ( szError . c_str ( ) ) ;
}
unit_test_action = & TestErrorHandlingUI ;
return true ;
}
static bool TestShareSecretGenerationSpeed ( void ) {
ILogMessage ( " \t Test shared secret generation speed. " ) ;
try {
// throw MyException("fake failure to test failure handling");
2022-05-04 23:52:12 -04:00
unsigned int secrets { 10 } ;
2022-02-16 00:53:01 -05:00
scalar a { scalar : : random ( ) } ;
scalar b { scalar : : random ( ) } ;
scalar c ;
auto B { a . timesBase ( ) } ;
decltype ( B ) A , C ;
2022-05-04 23:52:12 -04:00
auto start_time { std : : chrono : : high_resolution_clock : : now ( ) } ;
2022-02-16 00:53:01 -05:00
for ( unsigned int i { secrets } ; i ; i - - ) {
c = a + b ;
C = c * B ;
a = b + c ;
A = a * C ;
b = c + a ;
B = b * A ;
}
2022-05-04 23:52:12 -04:00
auto end_time { std : : chrono : : high_resolution_clock : : now ( ) } ;
2022-02-16 00:53:01 -05:00
if ( ! B . valid ( ) ) { throw MyException ( " Unexpected invalid scalar " ) ; }
2022-05-04 23:52:12 -04:00
auto time_taken { std : : chrono : : duration_cast < std : : chrono : : microseconds > ( end_time - start_time ) } ;
wxLogMessage ( " \t \t %d shared secrets from public and private keys took %lld microseconds " , secrets * 3 , time_taken . count ( ) ) ;
if ( time_taken . count ( ) ) {
shared_secrets_per_second = secrets * 3000000 / time_taken . count ( ) ;
2022-02-16 00:53:01 -05:00
wxLogMessage ( " \t \t in one second, can generate %ju shared secrets " ,
shared_secrets_per_second
) ;
}
}
catch ( const std : : exception & e ) {
errorCode = 23 ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( . . . ) {
szError = sz_unknown_error ;
errorCode = 23 ;
ILogError ( szError . c_str ( ) ) ;
}
unit_test_action = & TestSecretGeneration ;
return true ;
}
static bool TestSignatures ( void ) {
try {
ILogMessage ( " \t Test Schnorr signatures. " ) ;
//Construct Ann's secret and public keys:
scalar sclrAnnSecretKey { scalar : : random ( ) } ;
point ptAnnPublicKey { sclrAnnSecretKey . timesBase ( ) } ;
// Ann signs the string "hello"
std : : array < char , 6 > szHello { " hello " } ;
// Ann creates signature.
signed_text sig (
sclrAnnSecretKey , // Signer's secret key
ptAnnPublicKey , // Signer's public key
szHello // Text to be signed.
) ;
2022-05-04 23:52:12 -04:00
auto start_time { std : : chrono : : high_resolution_clock : : now ( ) } ;
2022-02-16 00:53:01 -05:00
if ( sig . verify ( ) )
{
2022-05-04 23:52:12 -04:00
auto end_time { std : : chrono : : high_resolution_clock : : now ( ) } ;
auto time_taken { std : : chrono : : duration_cast < std : : chrono : : microseconds > ( end_time - start_time ) } ;
wxLogMessage ( " \t \t verification of Schnorr signature took %lld microseconds " , time_taken . count ( ) ) ;
2022-02-16 00:53:01 -05:00
ILogMessage ( " \t \t Schnorr Signature valid " ) ;
}
else {
errorCode = 9 ;
szError = " Fail \t Invalid signature. " ;
ILogError ( szError . c_str ( ) ) ;
}
// Testing signature vector, using a low, easily guessed, secret key
sig = signed_text ( scalar ( 0x7F ) , scalar ( 0x7F ) . timesBase ( ) , szHello ) ;
assert ( sig . verify ( ) ) ;
scalar sig_test_vector (
{
0x7b , 0x28 , 0xd4 , 0x49 , 0x99 , 0xed , 0xb2 , 0x40 ,
0x61 , 0x4d , 0x22 , 0x96 , 0x25 , 0x78 , 0xb6 , 0x3b ,
0x5f , 0x72 , 0xf7 , 0xde , 0x99 , 0x29 , 0xe2 , 0x50 ,
0x41 , 0xa5 , 0xcd , 0xaa , 0x5b , 0x0b , 0xff , 0x0d ,
}
) ;
if ( sig_test_vector = = sig . c ) {
ILogMessage ( " \t \t produced expected signature test vector " ) ;
}
else {
errorCode = 14 ;
ILogMessage ( ( " \t \t sig of test vector: " + to_base64_string ( sig . c ) ) . c_str ( ) ) ;
ILogMessage ( ( " \t expected sig of test vector: " + to_base64_string ( sig_test_vector ) ) . c_str ( ) ) ;
szError = " Fail \t Signature different from expected test vector. " ;
ILogError ( szError . c_str ( ) ) ;
}
std : : array < uint8_t , 6 > expected_serialized_int { 0x88 , 0x94 , 0x92 , 0x8d , 0x88 , 0x45 } ;
bool f { true } ;
// f = f && scalar(ro::deserialize<32>(ro::serialize(sig_test_vector))) == sig_test_vector;
// f = f && scalar(ro::deserialize<32>(&ro::serialize(sig_test_vector)[0])) == sig_test_vector;
f = f & & ro : : serialize ( 0x21U ) = = ro : : serialize ( int8_t ( 0x21 ) ) ;
f = f & & ro : : serialize ( 0x21 ) = = ro : : serialize ( int8_t ( 0x21 ) ) ;
f = f & & ro : : serialize ( - 60 ) = = ro : : serialize ( int8_t ( - 60 ) ) ;
f = f & & ro : : serialize ( - 8107 ) = = ro : : serialize ( int16_t ( - 8107 ) ) ;
f = f & & ro : : serialize ( 0x41U ) . size ( ) = = 1 ;
f = f & & ro : : serialize ( 0x2142U ) . size ( ) = = 2 ;
f = f & & ro : : serialize ( 0x4142U ) . size ( ) = = 3 ;
f = f & & ro : : serialize ( 0x4142434445464748U ) . size ( ) = = 9 ;
f = f & & ro : : serialize ( 0x8142434445464748U ) . size ( ) = = 10 ;
f = f & & ro : : serialize ( 0x4142434445U ) = = expected_serialized_int ;
f = f & & ro : : deserialize < uint64_t > ( ro : : serialize ( 0x4142434445U ) ) = = 0x4142434445U ;
f = f & & ro : : deserialize < uint64_t > ( ro : : serialize ( 0xFF41424344454647U ) ) = = 0xFF41424344454647U ;
f = f & & ro : : deserialize < int64_t > ( ro : : serialize ( 0x4142434445 ) ) = = 0x4142434445 ;
f = f & & ro : : deserialize < int64_t > ( ro : : serialize ( 0xFF41424344454647 ) ) = = 0xFF41424344454647 ;
f = f & & ro : : deserialize < int64_t > ( ro : : serialize ( int32_t ( - 8107 ) ) ) = = - 8107 ;
if ( f ) {
ILogMessage ( " \t \t ro:serialize ro:deserialize on integers produced expected result " ) ;
}
else {
errorCode = 15 ;
szError = " Fail \t ro:deserialize ro:deserialize on integers produced unexpected results. " ;
ILogError ( szError . c_str ( ) ) ;
}
2022-05-22 05:36:23 -04:00
wxLogMessage ( wxT ( " \t Libsodium constants \n \t \t sizeof(crypto_secretstream_xchacha20poly1305_state)=%d " ) , int ( sizeof ( crypto_secretstream_xchacha20poly1305_state ) ) ) ;
wxLogMessage ( wxT ( " \t \t crypto_generichash_KEYBYTES=%d " ) , crypto_generichash_KEYBYTES ) ;
wxLogMessage ( wxT ( " \t \t crypto_secretstream_xchacha20poly1305_KEYBYTES=%d " ) , crypto_secretstream_xchacha20poly1305_KEYBYTES ) ;
wxLogMessage ( wxT ( " \t \t crypto_secretstream_xchacha20poly1305_HEADERBYTES=%d " ) , crypto_secretstream_xchacha20poly1305_HEADERBYTES ) ;
wxLogMessage ( wxT ( " \t \t checksum size == crypto_secretstream_xchacha20poly1305_ABYTES ==%d " ) , crypto_secretstream_xchacha20poly1305_ABYTES ) ;
wxLogMessage ( wxT ( " \t \t crypto_pwhash_OPSLIMIT_MIN == \t %08x " ) , crypto_pwhash_OPSLIMIT_MIN ) ;
wxLogMessage ( wxT ( " \t \t crypto_pwhash_OPSLIMIT_MODERATE == \t %08x " ) , crypto_pwhash_OPSLIMIT_MODERATE ) ;
wxLogMessage ( wxT ( " \t \t crypto_pwhash_OPSLIMIT_SENSITIVE == \t %08x " ) , crypto_pwhash_OPSLIMIT_SENSITIVE ) ;
wxLogMessage ( wxT ( " \t \t crypto_pwhash_OPSLIMIT_MAX == \t %08x " ) , crypto_pwhash_OPSLIMIT_MAX ) ;
wxLogMessage ( wxT ( " \t \t crypto_pwhash_MEMLIMIT_MIN == \t %08x " ) , crypto_pwhash_MEMLIMIT_MIN ) ;
wxLogMessage ( wxT ( " \t \t crypto_pwhash_MEMLIMIT_MODERATE==%08x " ) , crypto_pwhash_MEMLIMIT_MODERATE ) ;
wxLogMessage ( wxT ( " \t \t crypto_pwhash_MEMLIMIT_SENSITIVE== \t %08x " ) , crypto_pwhash_MEMLIMIT_SENSITIVE ) ;
wxLogMessage ( wxT ( " \t \t crypto_auth_BYTES == \t \t %08x " ) , crypto_auth_BYTES ) ;
wxLogMessage ( wxT ( " \t \t crypto_stream_chacha20_NONCEBYTES \t %08x " ) , crypto_stream_chacha20_NONCEBYTES ) ;
wxLogMessage ( wxT ( " \t \t crypto_stream_chacha20_KEYBYTES == \t %08x " ) , crypto_stream_chacha20_KEYBYTES ) ;
wxLogMessage ( wxT ( " \t \t chacha20 is 2^(256+128) 512 bit pseudo random blocks " ) ) ;
wxLogMessage ( wxT ( " \t \t crypto_stream_xchacha20_NONCEBYTES \t %08x " ) , crypto_stream_xchacha20_NONCEBYTES ) ;
wxLogMessage ( wxT ( " \t \t crypto_stream_xchacha20_KEYBYTES == \t %08x " ) , crypto_stream_chacha20_KEYBYTES ) ;
wxLogMessage ( wxT ( " \t \t xchacha20 is 2^512 512 bit pseudo random blocks " ) ) ;
wxLogMessage ( wxT ( " \t \t min hash size is %d bits " ) , crypto_generichash_BYTES_MIN * 8 ) ;
wxLogMessage ( wxT ( " \t \t max hash size is %d bits " ) , crypto_generichash_BYTES_MAX * 8 ) ;
wxLogMessage ( wxT ( " \t \t crypto_shorthash_BYTES \t == %08x " ) , crypto_shorthash_BYTES ) ;
wxLogMessage ( wxT ( " \t \t crypto_shorthash_KEYBYTES \t == %08x " ) , crypto_shorthash_KEYBYTES ) ;
wxLogMessage ( wxT ( " \t \t crypto_auth_BYTES \t \t == %08x " ) , crypto_auth_BYTES ) ;
2022-02-16 00:53:01 -05:00
}
catch ( const std : : exception & e ) {
errorCode = 15 ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( . . . ) {
szError = sz_unknown_error ;
errorCode = 15 ;
ILogError ( szError . c_str ( ) ) ;
}
unit_test_action = & TestShareSecretGenerationSpeed ;
return true ;
}
static std : : array < point , 0x10 > ristretto_test_vector {
point ( { 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ) ,
point ( { 0xe2 , 0xf2 , 0xae , 0x0a , 0x6a , 0xbc , 0x4e , 0x71 , 0xa8 , 0x84 , 0xa9 , 0x61 , 0xc5 , 0x00 , 0x51 , 0x5f , 0x58 , 0xe3 , 0x0b , 0x6a , 0xa5 , 0x82 , 0xdd , 0x8d , 0xb6 , 0xa6 , 0x59 , 0x45 , 0xe0 , 0x8d , 0x2d , 0x76 } ) ,
point ( { 0x6a , 0x49 , 0x32 , 0x10 , 0xf7 , 0x49 , 0x9c , 0xd1 , 0x7f , 0xec , 0xb5 , 0x10 , 0xae , 0x0c , 0xea , 0x23 , 0xa1 , 0x10 , 0xe8 , 0xd5 , 0xb9 , 0x01 , 0xf8 , 0xac , 0xad , 0xd3 , 0x09 , 0x5c , 0x73 , 0xa3 , 0xb9 , 0x19 } ) ,
point ( { 0x94 , 0x74 , 0x1f , 0x5d , 0x5d , 0x52 , 0x75 , 0x5e , 0xce , 0x4f , 0x23 , 0xf0 , 0x44 , 0xee , 0x27 , 0xd5 , 0xd1 , 0xea , 0x1e , 0x2b , 0xd1 , 0x96 , 0xb4 , 0x62 , 0x16 , 0x6b , 0x16 , 0x15 , 0x2a , 0x9d , 0x02 , 0x59 } ) ,
point ( { 0xda , 0x80 , 0x86 , 0x27 , 0x73 , 0x35 , 0x8b , 0x46 , 0x6f , 0xfa , 0xdf , 0xe0 , 0xb3 , 0x29 , 0x3a , 0xb3 , 0xd9 , 0xfd , 0x53 , 0xc5 , 0xea , 0x6c , 0x95 , 0x53 , 0x58 , 0xf5 , 0x68 , 0x32 , 0x2d , 0xaf , 0x6a , 0x57 } ) ,
point ( { 0xe8 , 0x82 , 0xb1 , 0x31 , 0x01 , 0x6b , 0x52 , 0xc1 , 0xd3 , 0x33 , 0x70 , 0x80 , 0x18 , 0x7c , 0xf7 , 0x68 , 0x42 , 0x3e , 0xfc , 0xcb , 0xb5 , 0x17 , 0xbb , 0x49 , 0x5a , 0xb8 , 0x12 , 0xc4 , 0x16 , 0x0f , 0xf4 , 0x4e } ) ,
point ( { 0xf6 , 0x47 , 0x46 , 0xd3 , 0xc9 , 0x2b , 0x13 , 0x05 , 0x0e , 0xd8 , 0xd8 , 0x02 , 0x36 , 0xa7 , 0xf0 , 0x00 , 0x7c , 0x3b , 0x3f , 0x96 , 0x2f , 0x5b , 0xa7 , 0x93 , 0xd1 , 0x9a , 0x60 , 0x1e , 0xbb , 0x1d , 0xf4 , 0x03 } ) ,
point ( { 0x44 , 0xf5 , 0x35 , 0x20 , 0x92 , 0x6e , 0xc8 , 0x1f , 0xbd , 0x5a , 0x38 , 0x78 , 0x45 , 0xbe , 0xb7 , 0xdf , 0x85 , 0xa9 , 0x6a , 0x24 , 0xec , 0xe1 , 0x87 , 0x38 , 0xbd , 0xcf , 0xa6 , 0xa7 , 0x82 , 0x2a , 0x17 , 0x6d } ) ,
point ( { 0x90 , 0x32 , 0x93 , 0xd8 , 0xf2 , 0x28 , 0x7e , 0xbe , 0x10 , 0xe2 , 0x37 , 0x4d , 0xc1 , 0xa5 , 0x3e , 0x0b , 0xc8 , 0x87 , 0xe5 , 0x92 , 0x69 , 0x9f , 0x02 , 0xd0 , 0x77 , 0xd5 , 0x26 , 0x3c , 0xdd , 0x55 , 0x60 , 0x1c } ) ,
point ( { 0x02 , 0x62 , 0x2a , 0xce , 0x8f , 0x73 , 0x03 , 0xa3 , 0x1c , 0xaf , 0xc6 , 0x3f , 0x8f , 0xc4 , 0x8f , 0xdc , 0x16 , 0xe1 , 0xc8 , 0xc8 , 0xd2 , 0x34 , 0xb2 , 0xf0 , 0xd6 , 0x68 , 0x52 , 0x82 , 0xa9 , 0x07 , 0x60 , 0x31 } ) ,
point ( { 0x20 , 0x70 , 0x6f , 0xd7 , 0x88 , 0xb2 , 0x72 , 0x0a , 0x1e , 0xd2 , 0xa5 , 0xda , 0xd4 , 0x95 , 0x2b , 0x01 , 0xf4 , 0x13 , 0xbc , 0xf0 , 0xe7 , 0x56 , 0x4d , 0xe8 , 0xcd , 0xc8 , 0x16 , 0x68 , 0x9e , 0x2d , 0xb9 , 0x5f } ) ,
point ( { 0xbc , 0xe8 , 0x3f , 0x8b , 0xa5 , 0xdd , 0x2f , 0xa5 , 0x72 , 0x86 , 0x4c , 0x24 , 0xba , 0x18 , 0x10 , 0xf9 , 0x52 , 0x2b , 0xc6 , 0x00 , 0x4a , 0xfe , 0x95 , 0x87 , 0x7a , 0xc7 , 0x32 , 0x41 , 0xca , 0xfd , 0xab , 0x42 } ) ,
point ( { 0xe4 , 0x54 , 0x9e , 0xe1 , 0x6b , 0x9a , 0xa0 , 0x30 , 0x99 , 0xca , 0x20 , 0x8c , 0x67 , 0xad , 0xaf , 0xca , 0xfa , 0x4c , 0x3f , 0x3e , 0x4e , 0x53 , 0x03 , 0xde , 0x60 , 0x26 , 0xe3 , 0xca , 0x8f , 0xf8 , 0x44 , 0x60 } ) ,
point ( { 0xaa , 0x52 , 0xe0 , 0x00 , 0xdf , 0x2e , 0x16 , 0xf5 , 0x5f , 0xb1 , 0x03 , 0x2f , 0xc3 , 0x3b , 0xc4 , 0x27 , 0x42 , 0xda , 0xd6 , 0xbd , 0x5a , 0x8f , 0xc0 , 0xbe , 0x01 , 0x67 , 0x43 , 0x6c , 0x59 , 0x48 , 0x50 , 0x1f } ) ,
point ( { 0x46 , 0x37 , 0x6b , 0x80 , 0xf4 , 0x09 , 0xb2 , 0x9d , 0xc2 , 0xb5 , 0xf6 , 0xf0 , 0xc5 , 0x25 , 0x91 , 0x99 , 0x08 , 0x96 , 0xe5 , 0x71 , 0x6f , 0x41 , 0x47 , 0x7c , 0xd3 , 0x00 , 0x85 , 0xab , 0x7f , 0x10 , 0x30 , 0x1e } ) ,
point ( { 0xe0 , 0xc4 , 0x18 , 0xf7 , 0xc8 , 0xd9 , 0xc4 , 0xcd , 0xd7 , 0x39 , 0x5b , 0x93 , 0xea , 0x12 , 0x4f , 0x3a , 0xd9 , 0x90 , 0x21 , 0xbb , 0x68 , 0x1d , 0xfc , 0x33 , 0x02 , 0xa9 , 0xd9 , 0x9a , 0x2e , 0x53 , 0xe6 , 0x4e } )
} ;
static bool UnitTest ( void ) {
try {
ILogMessage ( " \t Begin ristretto255 test vectors. " ) ;
bool fFailed { false } ;
int cryptoError { 0 } ;
for ( auto const & x : ristretto_test_vector ) {
if ( ! x . valid ( ) ) {
cryptoError = 9 ;
}
}
if ( cryptoError ) {
errorCode = cryptoError ;
szError = " Fail \t Invalid test vectors. " ;
ILogError ( szError . c_str ( ) ) ;
}
2022-05-04 23:52:12 -04:00
auto start_time { std : : chrono : : high_resolution_clock : : now ( ) } ;
2022-02-16 00:53:01 -05:00
auto sclr_a = scalar : : random ( ) ;
auto sclr_b = scalar : : random ( ) ;
if ( sclr_a = = sclr_b ) throw MyException ( " random not very random " ) ;
auto sclr_c = sclr_a * sclr_b ;
if ( sclr_b ! = sclr_c / sclr_a ) throw MyException ( " multiplicative inverse not inverse " ) ;
if ( false
| | ! scalar : : random ( ) . valid ( )
| | point : : ptBase - point : : ptBase ! = point : : ptZero
| | scalar ( 1 ) * point : : ptBase ! = point : : ptBase
| | point : : ptZero ! = ristretto_test_vector [ 0x00 ]
| | point : : ptBase ! = ristretto_test_vector [ 0x01 ]
| | point : : ptZero + point : : ptBase ! = ristretto_test_vector [ 0x01 ]
| | point : : ptBase + point : : ptBase ! = ristretto_test_vector [ 0x02 ]
| | ristretto_test_vector [ 0x02 ] + point : : ptBase ! = ristretto_test_vector [ 0x03 ]
| | ristretto_test_vector [ 0x02 ] + ristretto_test_vector [ 0x02 ] ! = ristretto_test_vector [ 0x04 ]
| | point : : ptBase * 3 = = ristretto_test_vector [ 0x04 ]
| | scalar ( 4 ) . timesBase ( ) ! = ristretto_test_vector [ 0x04 ]
| | ristretto_test_vector [ 0x03 ] + ristretto_test_vector [ 0x02 ] ! = ristretto_test_vector [ 0x05 ]
| | ! ( true
& & ! point : : ptZero
& & false = = ! point : : ptBase
2022-03-07 23:46:14 -05:00
& & scalar ( 0 ) . valid ( ) = = false
& & scalar ( 1 ) . valid ( )
& & scalar : : random ( ) . valid ( )
2022-02-16 00:53:01 -05:00
& & ! ristretto_test_vector [ 0x00 ]
& & point : : ptBase * 6 = = ristretto_test_vector [ 0x06 ]
& & scalar ( 7 ) * point : : ptBase = = ristretto_test_vector [ 0x07 ]
& & point : : ptBase * 3 + point : : ptBase * 5 = = ristretto_test_vector [ 0x08 ]
& & ( point : : ptBase * scalar ( 3 ) ) * 3 = = ristretto_test_vector [ 0x09 ]
& & point : : ptBase * ( scalar ( 3 ) * 3 ) = = ristretto_test_vector [ 0x09 ]
& & point : : ptBase * 2 + point : : ptBase * 3 = = ristretto_test_vector [ 0x0A ] - ristretto_test_vector [ 0x05 ]
& & ! ( ristretto_test_vector [ 0x02 ] = = ristretto_test_vector [ 0x03 ] )
& & ( point : : ptBase * 2 + ristretto_test_vector [ 0x03 ] ) + point : : ptBase * 4 = = ristretto_test_vector [ 0x0B ] - scalar ( 2 ) * point : : ptBase
& & point : : ptBase * 2 + ristretto_test_vector [ 0x03 ] + scalar ( 4 ) * point : : ptBase = = ristretto_test_vector [ 0x0B ] - point : : ptBase * 2
& & ristretto_test_vector [ 0x0C ] - point : : ptBase * 4 = = point : : ptBase * 4 + ristretto_test_vector [ 0x02 ] * 2
& & ristretto_test_vector [ 0x0D ] + scalar ( - 1 ) * ristretto_test_vector [ 0x0B ] = = point : : ptBase * 2
& & ristretto_test_vector [ 0x0E ] = = scalar ( 2 ) * scalar ( 7 ) . timesBase ( )
& & ristretto_test_vector [ 0x0E ] = = scalar ( 2 ) * scalar ( 7 ) * point : : ptBase
& & ristretto_test_vector [ 0x0F ] = = scalar ( 6 ) * scalar ( 5 ) * point : : ptBase - scalar ( 0x0F ) . timesBase ( )
& & scalar ( 3 ) = = scalar ( 2 ) + scalar ( 1 )
& & scalar ( 3 ) = = scalar ( 4 ) + scalar ( - 1 )
& & scalar ( 0x0103 ) = = scalar ( 0xFE ) + scalar ( 5 )
2022-03-07 23:46:14 -05:00
& & scalar ( 0xDEADBEEF ) = = scalar ( 0xDEADBDDE ) + scalar ( 0x111 )
& & scalar ( 0xBEEFDEADBEEF ) = = scalar ( 0xBEEFDEADBDDE ) + scalar ( 0x111 )
2022-03-26 23:46:34 -04:00
& & scalar ( 0xBEEF0000000F ) + scalar ( - 0xBEEF0EADBEEF ) = = scalar ( int ( - 0xEADBEE0 ) )
2022-02-16 00:53:01 -05:00
)
)
{
errorCode = 9 ;
szError = " Fail \t Cryptographic operations fail to generate expected test vectors. " ;
ILogError ( szError . c_str ( ) ) ;
}
else
{
2022-05-04 23:52:12 -04:00
auto end_time { std : : chrono : : high_resolution_clock : : now ( ) } ;
auto time_to_do_crypto { std : : chrono : : duration_cast < std : : chrono : : microseconds > ( end_time - start_time ) } ;
2022-05-22 05:36:23 -04:00
wxLogMessage ( wxT ( " \t \t test of ristretto test vectors took %lld microseconds " ) , time_to_do_crypto . count ( ) ) ;
2022-02-16 00:53:01 -05:00
ILogMessage ( " \t Testing generation of shared secrets. " ) ;
2022-05-04 23:52:12 -04:00
start_time = std : : chrono : : high_resolution_clock : : now ( ) ;
2022-02-16 00:53:01 -05:00
scalar sclrAnonSessionSecretKey { scalar : : random ( ) } ;
point ptAnonSessionPublicKey { sclrAnonSessionSecretKey * point : : ptBase } ;
scalar sclrServerPemanentSecretKey { scalar : : random ( ) } ;
point ptServerPermanentPublicKey { sclrServerPemanentSecretKey * point : : ptBase } ;
const char * MessageTextToBeSecured = " hello " ;
hash < 512 > ServerCopyOfSharedSecret ( ( sclrServerPemanentSecretKey * ptAnonSessionPublicKey ) , MessageTextToBeSecured ) ;
hash < 512 > AnonCopyOfSharedSecret ( ( sclrAnonSessionSecretKey * ptServerPermanentPublicKey ) , MessageTextToBeSecured ) ;
// This method identifies Server to Anon, but because Anon's key is ephemeral, does not identify Anon to Server. For mutually identified encryption, Anon has to send a signature of the emphemeral public key by a non ephemeral public key inside the encrypted message, or a signature of the cleartext inside the encrypted message by a non ephemeral public key, depending on whether he wants to prove identity at all, prove identity to only Server, or to allow Server to prove it to anyone.
if ( ServerCopyOfSharedSecret ! = AnonCopyOfSharedSecret ) {
errorCode = 10 ;
szError = " Fail \t Shared secret was not successfully shared. " ;
ILogError ( szError . c_str ( ) ) ;
}
else {
2022-05-04 23:52:12 -04:00
end_time = std : : chrono : : high_resolution_clock : : now ( ) ;
auto time_taken { std : : chrono : : duration_cast < std : : chrono : : microseconds > ( end_time - start_time ) } ;
wxLogMessage ( _wx ( " \t shared secret generation both ways and comparison took %lld microseconds " ) , time_taken . count ( ) ) ;
2022-02-16 00:53:01 -05:00
}
ILogMessage ( " \t Testing hashing speed " ) ;
{
int hashes { 20000 } ;
point sharedSecretKey = sclrAnonSessionSecretKey * ptServerPermanentPublicKey ;
ServerCopyOfSharedSecret = hash < 512 > ( sharedSecretKey , MessageTextToBeSecured ) ;
2022-05-04 23:52:12 -04:00
start_time = std : : chrono : : high_resolution_clock : : now ( ) ;
2022-02-16 00:53:01 -05:00
for ( int i { 0 } ; i < hashes ; i + + ) {
sharedSecretKey . blob [ 3 ] = ServerCopyOfSharedSecret . blob [ 5 ] ;
ServerCopyOfSharedSecret = hash < 512 > ( sharedSecretKey , MessageTextToBeSecured ) ;
}
2022-05-04 23:52:12 -04:00
end_time = std : : chrono : : high_resolution_clock : : now ( ) ;
auto time_taken { std : : chrono : : duration_cast < std : : chrono : : microseconds > ( end_time - start_time ) } ;
2022-02-16 00:53:01 -05:00
{ bool f = false ; //dont optimize pointless calculation
for ( auto x : ServerCopyOfSharedSecret . blob ) { f = f | | x ; }
if ( f ) {
2022-05-04 23:52:12 -04:00
wxLogMessage ( _wx ( " \t \t %d hashes of pairs of shared secrets took %lld microseconds " ) , hashes , time_taken . count ( ) ) ;
wxLogMessage ( _wx ( " \t \t in one millisecond, can hash %lld short messages " ) , 1000LL * hashes / time_taken . count ( ) ) ;
2022-02-16 00:53:01 -05:00
}
}
}
ILogMessage ( " \t Testing hashing speed, hashes of hashes " ) ;
const char * _ = " hello " ;
hash a ( _ ) ;
hash b ( a ) ;
hash c ( b ) ;
if ( hash ( b , c ) ! = hash ( hsh ( ) < < b < < c ) ) throw MyException ( " inconsistent hashes generated " ) ;
constexpr int hashes { 3000 } ;
2022-05-04 23:52:12 -04:00
start_time = std : : chrono : : high_resolution_clock : : now ( ) ;
2022-02-16 00:53:01 -05:00
for ( int i { 0 } ; i < hashes ; i + + ) {
a = hash ( b , c ) ;
b = hash ( c , a ) ;
c = hash ( a , b ) ;
}
2022-05-04 23:52:12 -04:00
end_time = std : : chrono : : high_resolution_clock : : now ( ) ;
auto time_taken { std : : chrono : : duration_cast < std : : chrono : : microseconds > ( end_time - start_time ) } ;
2022-02-16 00:53:01 -05:00
{ bool f = false ; //dont optimize pointless calculation away
for ( auto x : c . blob ) { f = f | | x ; }
if ( f ) {
2022-05-04 23:52:12 -04:00
wxLogMessage ( _wx ( " \t \t %d hashes of a pair of hashes took %lld microseconds " ) , hashes * 3 , time_taken . count ( ) ) ;
if ( time_taken . count ( ) > 0 ) {
wxLogMessage ( _wx ( " \t \t in one millisecond, can hash %lld pairs of 256 bit hashes " ) , hashes * 3000ll / time_taken . count ( ) ) ;
2022-02-16 00:53:01 -05:00
}
}
}
uint8_t buff [ hashes * 3 * 64 ] ;
randombytes_buf ( std : : span < byte > ( buff ) ) ;
2022-05-04 23:52:12 -04:00
start_time = std : : chrono : : high_resolution_clock : : now ( ) ;
2022-02-16 00:53:01 -05:00
c = hash ( buff ) ;
2022-05-04 23:52:12 -04:00
end_time = std : : chrono : : high_resolution_clock : : now ( ) ;
time_taken = std : : chrono : : duration_cast < std : : chrono : : microseconds > ( end_time - start_time ) ;
2022-02-16 00:53:01 -05:00
{ bool f = false ; //dont optimize pointless calculation away
for ( auto x : c . blob ) { f = f | | x ; }
if ( f ) {
2022-05-04 23:52:12 -04:00
wxLogMessage ( _wx ( " \t \t one hash of %d bytes took %lld microseconds " ) , hashes * 3 * 64 , time_taken . count ( ) ) ;
2022-02-16 00:53:01 -05:00
}
}
}
}
catch ( const std : : exception & e ) {
errorCode = 10 ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( . . . ) {
szError = sz_unknown_error ;
errorCode = 10 ;
ILogError ( szError . c_str ( ) ) ;
}
unit_test_action = & TestSignatures ;
return true ;
}
} //end ristretto255 namespace
static void bigEndian ( std : : array < uint8_t , 8 > & out , uint64_t in ) {
for ( int i = 7 ; i > = 0 ; i - - ) {
out [ i ] = in & 0xFF ;
in = in > > 8 ;
}
}
static uint64_t shiftArbRight ( uint64_t in , unsigned int i ) {
if ( i > 0 ) {
//shifting right any number of bits
if ( i > 63 ) in = 0 ;
else in = ( in > > i ) ;
}
return in ;
}
static uint64_t shiftArbLeft ( uint64_t in , unsigned int i ) {
//shifting left any number of bits
if ( i > 0 ) {
if ( i > 63 ) in = 0 ;
else in = ( in < < i ) ;
}
return in ;
}
//extern std::array<const uint8_t, 0x100>reverseLookup();
static bool slash6UnitTest ( void ) {
try {
static int count { 0 } ;
if ( count = = 0 ) {
wxLogMessage ( _wx ( R " ( decoding slash6 test vector to get expected result vector) " ) ) ;
{
std : : array < uint8_t , 56 > a ;
a [ 51 ] = a [ 52 ] = a [ 53 ] = a [ 54 ] = a [ 55 ] = 0xcc ;
a [ 51 ] = 0xFF ;
decltype ( a ) expectedResult { 0x00 , 0x00 , 0x01 , 0x04 , 0x10 , 0x83 , 0x10 , 0x51 , 0x87 , 0x20 , 0x92 , 0x8b , 0x30 , 0xd3 , 0x8f , 0x41 , 0x14 , 0x93 , 0x51 , 0x55 , 0x97 , 0x61 , 0x96 , 0x9b , 0x71 , 0xd7 , 0x9f , 0x82 , 0x18 , 0xa3 , 0x92 , 0x59 , 0xa7 , 0xa2 , 0x9a , 0xab , 0xb2 , 0xdb , 0xaf , 0xc3 , 0x1c , 0xb3 , 0xd3 , 0x5d , 0xb7 , 0xe3 , 0x9e , 0xbb , 0xf3 , 0xdf , 0xbf , 0xff , 0xcc , 0xcc , 0xcc , 0xcc } ;
// Trying it with guard bytes at the end.
if ( base64_to_bits ( & a [ 0 ] , 0 , 408 , " 0oOlI123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz!$*+-_ " ) ! = 408
| | a ! = expectedResult ) {
errorCode = 11 ;
szError = " Fail \t unexpected result of test vector. " ;
ILogError ( szError . c_str ( ) ) ;
}
}
{
std : : array < uint8_t , 51 > a ;
decltype ( a ) expectedResult { 0x00 , 0x00 , 0x01 , 0x04 , 0x10 , 0x83 , 0x10 , 0x51 , 0x87 , 0x20 , 0x92 , 0x8b , 0x30 , 0xd3 , 0x8f , 0x41 , 0x14 , 0x93 , 0x51 , 0x55 , 0x97 , 0x61 , 0x96 , 0x9b , 0x71 , 0xd7 , 0x9f , 0x82 , 0x18 , 0xa3 , 0x92 , 0x59 , 0xa7 , 0xa2 , 0x9a , 0xab , 0xb2 , 0xdb , 0xaf , 0xc3 , 0x1c , 0xb3 , 0xd3 , 0x5d , 0xb7 , 0xe3 , 0x9e , 0xbb , 0xf3 , 0xdf , 0xbf } ;
// Trying it without guard bytes to provoke address sanitizer.
if ( base64_to_bits ( & a [ 0 ] , 0 , 408 , " 0oOlI123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz!$*+-_ " ) ! = 408
| | a ! = expectedResult ) {
errorCode = 11 ;
szError = " Fail \t unexpected result of test vector. " ;
ILogError ( szError . c_str ( ) ) ;
}
}
{
std : : array < uint8_t , 10 > buff ;
randombytes_buf ( buff ) ;
std : : array < char , 13 > txt ;
bits2base64 ( & buff [ 0 ] , 0 , 72 , txt ) ;
wxLogMessage ( _wx ( " \t random 72 bit integer: %s " ) , & txt [ 0 ] ) ;
wxLogMessage ( _wx ( " \t Random text secret %s " ) , & DeriveTextSecret ( ristretto255 : : scalar : : random ( ) , 1 ) [ 0 ] ) ;
}
}
std : : array < uint8_t , 8 > buff ;
randombytes_buf ( buff ) ;
std : : array < char , 9 * 8 / 6 + 1 > txt ;
decltype ( buff ) buff2 ;
randombytes_buf ( buff2 ) ;
randombytes_buf ( txt ) ;
decltype ( buff2 ) buff3 { buff2 } ;
unsigned int length { buff2 [ 1 ] } ;
length = length % 60 ;
unsigned int start { buff2 [ 2 ] } ;
start = start % ( 64 - length ) ;
unsigned int startDest { buff2 [ 3 ] } ;
startDest = startDest % ( 64 - length ) ;
uint64_t sourceAs64bitInt { 0 } ;
for ( auto x : buff ) sourceAs64bitInt = ( sourceAs64bitInt < < 8 ) | x ;
if ( count = = 0 ) wxLogMessage ( _wx ( " \t Generating slash6 representation of %u random bits and converting back: " ) , length ) ;
bits2base64 ( & buff [ 0 ] , start , length , txt ) ;
uint64_t originalStateOfDestination { 0 } ;
for ( auto x : buff2 ) originalStateOfDestination = ( originalStateOfDestination < < 8 ) | x ;
/*wxLogDebug("start=%u, length=%u", start, length);
wxLogDebug ( " %02x%02x%02x%02x%02x%02x%02x%02x " , buff [ 0 ] , buff [ 1 ] , buff [ 2 ] , buff [ 3 ] , buff [ 4 ] , buff [ 5 ] , buff [ 6 ] , buff [ 7 ] ) ;
wxLogDebug ( " %02x%02x%02x%02x%02x%02x%02x%02x " , buff2 [ 0 ] , buff2 [ 1 ] , buff2 [ 2 ] , buff2 [ 3 ] , buff2 [ 4 ] , buff2 [ 5 ] , buff2 [ 6 ] , buff2 [ 7 ] ) ; */
unsigned int newLength { base64_to_bits ( & buff2 [ 0 ] , startDest , length , & txt [ 0 ] ) } ;
if ( newLength ! = length ) {
errorCode = 11 ;
szError = " Fail \t BitBuffer length discrepancy. " ;
ILogError ( szError . c_str ( ) ) ;
}
/*wxLogDebug("startDest=%u", startDest);
wxLogDebug ( " %02x%02x%02x%02x%02x%02x%02x%02x " , buff2 [ 0 ] , buff2 [ 1 ] , buff2 [ 2 ] , buff2 [ 3 ] , buff2 [ 4 ] , buff2 [ 5 ] , buff2 [ 6 ] , buff2 [ 7 ] ) ; */
uint64_t finalStateOfDestination { 0 } ;
for ( auto x : buff2 ) finalStateOfDestination = ( finalStateOfDestination < < 8 ) | x ;
uint64_t src { shiftArbRight ( shiftArbLeft ( sourceAs64bitInt , start ) , ( 64 - length ) ) } ;
uint64_t dest { shiftArbRight ( shiftArbLeft ( finalStateOfDestination , startDest ) , ( 64 - length ) ) } ;
uint64_t destOriginalLeadingBits { shiftArbRight ( originalStateOfDestination , 64 - startDest ) } ;
uint64_t destFinalLeadingBits { shiftArbRight ( finalStateOfDestination , 64 - startDest ) } ;
uint64_t destOriginalTrailingBits { shiftArbLeft ( originalStateOfDestination , ( startDest + length ) ) } ;
uint64_t destFinalTrailingBits { shiftArbLeft ( finalStateOfDestination , ( startDest + length ) ) } ;
/*wxLogDebug("check bits %d", int(src));*/
if ( src ! = dest
| | destOriginalLeadingBits ! = destFinalLeadingBits
| | destOriginalTrailingBits ! = destFinalTrailingBits ) {
wxLogMessage ( _wx ( " start=%u, Destination start =%u, length=%u " ) , start , startDest , length ) ;
wxLogMessage ( _wx ( " %02x%02x%02x%02x%02x%02x%02x%02x " ) , buff [ 0 ] , buff [ 1 ] , buff [ 2 ] , buff [ 3 ] , buff [ 4 ] , buff [ 5 ] , buff [ 6 ] , buff [ 7 ] ) ;
wxLogMessage ( _wx ( " %02x%02x%02x%02x%02x%02x%02x%02x " ) , buff3 [ 0 ] , buff3 [ 1 ] , buff2 [ 3 ] , buff3 [ 3 ] , buff3 [ 4 ] , buff3 [ 5 ] , buff3 [ 6 ] , buff3 [ 7 ] ) ;
wxLogMessage ( _wx ( " %02x%02x%02x%02x%02x%02x%02x%02x " ) , buff2 [ 0 ] , buff2 [ 1 ] , buff2 [ 2 ] , buff2 [ 3 ] , buff2 [ 4 ] , buff2 [ 5 ] , buff2 [ 6 ] , buff2 [ 7 ] ) ;
if ( src ! = dest ) {
wxLogMessage ( _wx ( " Bits changed in move, %x, %x " ) , ( unsigned int ) src , ( unsigned int ) dest ) ;
}
if ( destOriginalLeadingBits ! = destFinalLeadingBits ) {
wxLogMessage ( _wx ( " Bits preceding bit buffer changed, %x, %x " ) , ( unsigned int ) destOriginalLeadingBits , ( unsigned int ) destFinalLeadingBits ) ;
}
if ( destOriginalTrailingBits ! = destFinalTrailingBits ) {
wxLogMessage ( _wx ( " Bits following bit buffer changed, %x, %x " ) , ( unsigned int ) destOriginalTrailingBits , ( unsigned int ) destFinalTrailingBits ) ;
}
errorCode = 12 ;
szError = " Fail \t BitBuffer discrepancy. " ;
ILogError ( szError . c_str ( ) ) ;
}
count + + ;
if ( count > 4 ) {
wxLogMessage ( _wx ( " \t Slash6 random bits test repeated %d times with different data, sizes, and positions " ) , count ) ;
unit_test_action = & ristretto255 : : UnitTest ;
}
// If you touch the slash6 encoding, try retesting with the number of tests tries set to one hundred thousand instead of five, to catch all code paths and weird special cases.
}
catch ( const std : : exception & e ) {
errorCode = 12 ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( . . . ) {
szError = sz_unknown_error ;
errorCode = 12 ;
ILogError ( szError . c_str ( ) ) ;
}
return true ;
}
static bool StartUnitTest ( void ) {
modal_dialog_hook . Register ( ) ;
ILogMessage ( " Begin Unit Test for code compiled " __DATE__ " " __TIME__ " . " ) ;
// singletonFrame->m_pLogWindow->GetFrame()->Raise();
unit_test_action = & slash6UnitTest ;
return true ;
}
void UnitTest ( wxIdleEvent & event ) {
if ( ( * unit_test_action ) ( ) ) event . RequestMore ( true ) ;
event . Skip ( ) ;
}