@ -1,4 +1,5 @@
# include " stdafx.h "
# include " stdafx.h "
static constexpr char SrcFilename [ ] { " src/unit_test.cpp " } ;
using ro : : msec , ro : : msec_since_epoch , ro : : bin2hex , ro : : to_base64_string , ristretto255 : : hash ,
using ro : : msec , ro : : msec_since_epoch , ro : : bin2hex , ro : : to_base64_string , ristretto255 : : hash ,
ristretto255 : : hsh , ristretto255 : : scalar ,
ristretto255 : : hsh , ristretto255 : : scalar ,
ristretto255 : : point , ro : : base58 ;
ristretto255 : : point , ro : : base58 ;
@ -68,6 +69,11 @@ static bool EndUnitTest() {
throw EndUnitTestOfExceptions ( ) ;
throw EndUnitTestOfExceptions ( ) ;
}
}
catch ( const EndUnitTestOfExceptions & ) { }
catch ( const EndUnitTestOfExceptions & ) { }
catch ( const MyException & e ) {
errorCode = e . what_num ( ) ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( const std : : exception & e ) {
catch ( const std : : exception & e ) {
errorCode = 1001 ;
errorCode = 1001 ;
szError = intestbed + e . what ( ) ;
szError = intestbed + e . what ( ) ;
@ -105,7 +111,7 @@ static bool curve_order(void) {
mpz_get_str ( sz , 16 , mpir : : ristretto25519_curve_order ) ;
mpz_get_str ( sz , 16 , mpir : : ristretto25519_curve_order ) ;
wxString curve_order_as_mpir_bigint { _wx ( sz ) } ;
wxString curve_order_as_mpir_bigint { _wx ( sz ) } ;
if ( curve_order_as_unreduced_scalar ! = curve_order_as_mpir_bigint ) {
if ( curve_order_as_unreduced_scalar ! = curve_order_as_mpir_bigint ) {
throw MyException ( " inconsistent curve order " );
throw MyException ( " inconsistent curve order " , __LINE__ , __func__ , SrcFilename );
}
}
scalar sc_zero { 0 } ;
scalar sc_zero { 0 } ;
scalar sc_one { 1 } ;
scalar sc_one { 1 } ;
@ -138,7 +144,12 @@ static bool curve_order(void) {
& & sc1 . valid ( ) )
& & sc1 . valid ( ) )
& & ! scalar : : scOrder . valid ( )
& & ! scalar : : scOrder . valid ( )
& & ! scalar ( 0 ) . valid ( ) ;
& & ! scalar ( 0 ) . valid ( ) ;
if ( ! f ) throw MyException ( " scalar range and validation messed up " ) ;
if ( ! f ) throw MyException ( " scalar range and validation messed up " , __LINE__ , __func__ , SrcFilename ) ;
}
catch ( const MyException & e ) {
errorCode = e . what_num ( ) ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
}
catch ( const std : : exception & e ) {
catch ( const std : : exception & e ) {
errorCode = 30 ;
errorCode = 30 ;
@ -180,14 +191,14 @@ static bool checkDataConversionsProduceExpected(void){
| | hash ( p_brownfox ) ! = hash ( hsh ( ) < < ar_brownfox < < wx_over . ToUTF8 ( ) )
| | hash ( p_brownfox ) ! = hash ( hsh ( ) < < ar_brownfox < < wx_over . ToUTF8 ( ) )
| | hash ( p_brownfox ) ! = hash ( ar_brownfox , wx_over . ToUTF8 ( ) )
| | hash ( p_brownfox ) ! = hash ( ar_brownfox , wx_over . ToUTF8 ( ) )
| | hash ( brownfox ) ! = hash ( ar_brownfox , p_over )
| | hash ( brownfox ) ! = hash ( ar_brownfox , p_over )
) throw MyException ( sz_inconsistent_hash );
) throw MyException ( sz_inconsistent_hash , __LINE__ , __func__ , SrcFilename );
{
{
scalar scl_b { scalar : : random ( ) } ;
scalar scl_b { scalar : : random ( ) } ;
point pt_a { scl_b . timesBase ( ) } ;
point pt_a { scl_b . timesBase ( ) } ;
std : : string str_pt_a { & ( base58 ( pt_a ) ) [ 0 ] } ;
std : : string str_pt_a { & ( base58 ( pt_a ) ) [ 0 ] } ;
if ( pt_a ! = base58 < point > : : bin ( str_pt_a . c_str ( ) ) ) {
if ( pt_a ! = base58 < point > : : bin ( str_pt_a . c_str ( ) ) ) {
throw MyException ( " Round trip from and two base 58 representation failed " );
throw MyException ( " Round trip from and two base 58 representation failed " , __LINE__ , __func__ , SrcFilename );
}
}
}
}
{
{
@ -231,9 +242,14 @@ static bool checkDataConversionsProduceExpected(void){
if ( base58 ( hash_b ) . operator std : : string ( ) ! =
if ( base58 ( hash_b ) . operator std : : string ( ) ! =
" i22EVNPsKRjdxYTZrPPu9mx6vnrBjosFix5F4gn2mb2kF "
" i22EVNPsKRjdxYTZrPPu9mx6vnrBjosFix5F4gn2mb2kF "
) {
) {
throw MyException ( " unexpected hash of transformations " );
throw MyException ( " unexpected hash of transformations " , __LINE__ , __func__ , SrcFilename );
}
}
}
}
catch ( const MyException & e ) {
errorCode = e . what_num ( ) ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( const std : : exception & e ) {
catch ( const std : : exception & e ) {
errorCode = 27 ;
errorCode = 27 ;
szError = e . what ( ) ;
szError = e . what ( ) ;
@ -277,6 +293,11 @@ static bool CheckForUtfEnvironment(void) {
}
}
if ( ! utfEnvironment ) { throw MyException ( utfError ) ; }
if ( ! utfEnvironment ) { throw MyException ( utfError ) ; }
}
}
catch ( const MyException & e ) {
errorCode = e . what_num ( ) ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( const std : : exception & e ) {
catch ( const std : : exception & e ) {
errorCode = 24 ;
errorCode = 24 ;
szError = e . what ( ) ;
szError = e . what ( ) ;
@ -386,12 +407,12 @@ static bool OpenWallet(void) {
else fWalletNameOk = true ;
else fWalletNameOk = true ;
std : : unique_ptr < ISqlite3 > db ;
std : : unique_ptr < ISqlite3 > db ;
if ( fWalletNameOk ) {
if ( fWalletNameOk ) {
if ( ! LastUsedSqlite . FileExists ( ) ) throw MyException ( " Expected wallet file not found " );
if ( ! LastUsedSqlite . FileExists ( ) ) throw MyException ( " Expected wallet file not found " , __LINE__ , __func__ , SrcFilename );
db . reset ( Sqlite3_open ( LastUsedSqlite . GetFullPath ( ) . ToUTF8 ( ) ) ) ;
db . reset ( Sqlite3_open ( LastUsedSqlite . GetFullPath ( ) . ToUTF8 ( ) ) ) ;
sql_read_from_misc read_from_misc ( db . get ( ) ) ;
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 ( 1 ) | | read_from_misc . value < int64_t > ( ) ! = WALLET_FILE_IDENTIFIER ) throw MyException ( " Unrecognizable wallet file format " , __LINE__ , __func__ , SrcFilename );
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 ( 2 ) | | read_from_misc . value < int64_t > ( ) ! = WALLET_FILE_SCHEMA_VERSION_0_0 ) throw MyException ( " Unrecognized wallet schema " , __LINE__ , __func__ , SrcFilename );
if ( ! read_from_misc ( 4 ) ) throw MyException ( " Mastersecret missing " );
if ( ! read_from_misc ( 4 ) ) throw MyException ( " Mastersecret missing " , __LINE__ , __func__ , SrcFilename );
ristretto255 : : CMasterSecret MasterSecret ( * read_from_misc . value < ristretto255 : : scalar > ( ) ) ;
ristretto255 : : CMasterSecret MasterSecret ( * read_from_misc . value < ristretto255 : : scalar > ( ) ) ;
ro : : sql read_keys ( db . get ( ) , R " |(SELECT * FROM " Keys " LIMIT 5;)| " ) ;
ro : : sql read_keys ( db . get ( ) , R " |(SELECT * FROM " Keys " LIMIT 5;)| " ) ;
sql_read_name read_name ( db . get ( ) ) ;
sql_read_name read_name ( db . get ( ) ) ;
@ -400,10 +421,10 @@ static bool OpenWallet(void) {
auto pubkey = read_keys . column < ristretto255 : : point > ( 1 ) ;
auto pubkey = read_keys . column < ristretto255 : : point > ( 1 ) ;
auto id = read_keys . column < int > ( 2 ) ;
auto id = read_keys . column < int > ( 2 ) ;
auto use = read_keys . column < int > ( 3 ) ;
auto use = read_keys . column < int > ( 3 ) ;
if ( use ! = 1 ) throw MyException ( sz_unknown_secret_key_algorithm );
if ( use ! = 1 ) throw MyException ( sz_unknown_secret_key_algorithm , __LINE__ , __func__ , SrcFilename );
if ( ! read_name ( id ) ) throw MyException ( sz_no_corresponding_entry );
if ( ! read_name ( id ) ) throw MyException ( sz_no_corresponding_entry , __LINE__ , __func__ , SrcFilename );
const char * name = read_name . name ( ) ;
const char * name = read_name . name ( ) ;
if ( MasterSecret ( name ) . timesBase ( ) ! = * pubkey ) throw MyException ( R " |(Public key of name fails to correspond)| " );
if ( MasterSecret ( name ) . timesBase ( ) ! = * pubkey ) throw MyException ( R " |(Public key of name fails to correspond)| " , __LINE__ , __func__ , SrcFilename );
wxLogMessage ( wxT ( " \t \t \" %s \" has expected public key 0x%s " ) , name , ( wxString ) ( bin2hex ( * pubkey ) ) ) ;
wxLogMessage ( wxT ( " \t \t \" %s \" has expected public key 0x%s " ) , name , ( wxString ) ( bin2hex ( * pubkey ) ) ) ;
}
}
}
}
@ -428,6 +449,7 @@ CREATE TABLE "Keys"(
" use " INTEGER NOT NULL ) ;
" use " INTEGER NOT NULL ) ;
CREATE UNIQUE INDEX i_pubkey ON Keys ( pubkey ) ;
CREATE UNIQUE INDEX i_pubkey ON Keys ( pubkey ) ;
CREATE UNIQUE INDEX i_id ON Keys ( use , id ) ;
CREATE TABLE " Names " (
CREATE TABLE " Names " (
" ROWID " INTEGER PRIMARY KEY ,
" ROWID " INTEGER PRIMARY KEY ,
@ -470,6 +492,11 @@ COMMIT;)|");
}
}
} // End of wallet creation branch
} // End of wallet creation branch
}
}
catch ( const MyException & e ) {
errorCode = e . what_num ( ) ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( const std : : exception & e ) {
catch ( const std : : exception & e ) {
errorCode = 20 ;
errorCode = 20 ;
szError = e . what ( ) ;
szError = e . what ( ) ;
@ -516,11 +543,11 @@ namespace ristretto255 {
szError = " Fail \t Unexpected text secret from scalar(7) " ;
szError = " Fail \t Unexpected text secret from scalar(7) " ;
ILogError ( szError . c_str ( ) ) ;
ILogError ( szError . c_str ( ) ) ;
}
}
if ( std : : popcount ( 0x0123456789ABCDEFu ) ! = 0x20 ) throw MyException ( sz_bitcount_incorrect );
if ( std : : popcount ( 0x0123456789ABCDEFu ) ! = 0x20 ) throw MyException ( sz_bitcount_incorrect , __LINE__ , __func__ , SrcFilename );
if ( rounded_log2 ( 0x345678u ) ! = 22 ) throw MyException ( sz_rounded_log2_incorrect );
if ( rounded_log2 ( 0x345678u ) ! = 22 ) throw MyException ( sz_rounded_log2_incorrect , __LINE__ , __func__ , SrcFilename );
{ uint64_t v { 0x123456789ABCDEFu } ;
{ uint64_t v { 0x123456789ABCDEFu } ;
for ( unsigned int i = 0 ; i < = 64 ; i + + ) {
for ( unsigned int i = 0 ; i < = 64 ; i + + ) {
if ( i ! = std : : countr_zero ( v ) ) throw MyException ( sz_count_of_trailing_zero_bits_incorrect );
if ( i ! = std : : countr_zero ( v ) ) throw MyException ( sz_count_of_trailing_zero_bits_incorrect , __LINE__ , __func__ , SrcFilename );
v < < = 1 ;
v < < = 1 ;
}
}
}
}
@ -556,6 +583,11 @@ namespace ristretto255 {
ILogMessage ( " \t \t Skipping test of strong secret generation in quick unit test, because strong secret generation is deliberately slow. " ) ;
ILogMessage ( " \t \t Skipping test of strong secret generation in quick unit test, because strong secret generation is deliberately slow. " ) ;
}
}
}
}
catch ( const MyException & e ) {
errorCode = e . what_num ( ) ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( const std : : exception & e ) {
catch ( const std : : exception & e ) {
errorCode = 16 ;
errorCode = 16 ;
szError = e . what ( ) ;
szError = e . what ( ) ;
@ -573,7 +605,7 @@ namespace ristretto255 {
static bool TestShareSecretGenerationSpeed ( void ) {
static bool TestShareSecretGenerationSpeed ( void ) {
ILogMessage ( " \t Test shared secret generation speed. " ) ;
ILogMessage ( " \t Test shared secret generation speed. " ) ;
try {
try {
// throw MyException("fake failure to test failure handling" );
// throw MyException("fake failure to test failure handling" , __LINE__, __func__, SrcFilename );
unsigned int secrets { 10 } ;
unsigned int secrets { 10 } ;
scalar a { scalar : : random ( ) } ;
scalar a { scalar : : random ( ) } ;
scalar b { scalar : : random ( ) } ;
scalar b { scalar : : random ( ) } ;
@ -590,7 +622,8 @@ static bool TestShareSecretGenerationSpeed(void) {
B = b * A ;
B = b * A ;
}
}
auto end_time { std : : chrono : : high_resolution_clock : : now ( ) } ;
auto end_time { std : : chrono : : high_resolution_clock : : now ( ) } ;
if ( ! B . valid ( ) ) { throw MyException ( " Unexpected invalid scalar " ) ; }
if ( ! B . valid ( ) ) { throw MyException ( " Unexpected invalid scalar " , __LINE__ , __func__ , SrcFilename ) ;
}
auto time_taken { std : : chrono : : duration_cast < std : : chrono : : microseconds > ( end_time - start_time ) } ;
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 ( ) ) ;
wxLogMessage ( " \t \t %d shared secrets from public and private keys took %lld microseconds " , secrets * 3 , time_taken . count ( ) ) ;
if ( time_taken . count ( ) ) {
if ( time_taken . count ( ) ) {
@ -600,6 +633,11 @@ static bool TestShareSecretGenerationSpeed(void) {
) ;
) ;
}
}
}
}
catch ( const MyException & e ) {
errorCode = e . what_num ( ) ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( const std : : exception & e ) {
catch ( const std : : exception & e ) {
errorCode = 23 ;
errorCode = 23 ;
szError = e . what ( ) ;
szError = e . what ( ) ;
@ -738,6 +776,11 @@ static bool TestShareSecretGenerationSpeed(void) {
wxLogMessage ( wxT ( " \t \t crypto_shorthash_KEYBYTES \t == %08x " ) , crypto_shorthash_KEYBYTES ) ;
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 ) ;
wxLogMessage ( wxT ( " \t \t crypto_auth_BYTES \t \t == %08x " ) , crypto_auth_BYTES ) ;
}
}
catch ( const MyException & e ) {
errorCode = e . what_num ( ) ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( const std : : exception & e ) {
catch ( const std : : exception & e ) {
errorCode = 15 ;
errorCode = 15 ;
szError = e . what ( ) ;
szError = e . what ( ) ;
@ -790,9 +833,9 @@ static bool TestShareSecretGenerationSpeed(void) {
auto start_time { std : : chrono : : high_resolution_clock : : now ( ) } ;
auto start_time { std : : chrono : : high_resolution_clock : : now ( ) } ;
auto sclr_a = scalar : : random ( ) ;
auto sclr_a = scalar : : random ( ) ;
auto sclr_b = scalar : : random ( ) ;
auto sclr_b = scalar : : random ( ) ;
if ( sclr_a = = sclr_b ) throw MyException ( " random not very random " );
if ( sclr_a = = sclr_b ) throw MyException ( " random not very random " , __LINE__ , __func__ , SrcFilename );
auto sclr_c = sclr_a * sclr_b ;
auto sclr_c = sclr_a * sclr_b ;
if ( sclr_b ! = sclr_c / sclr_a ) throw MyException ( " multiplicative inverse not inverse " );
if ( sclr_b ! = sclr_c / sclr_a ) throw MyException ( " multiplicative inverse not inverse " , __LINE__ , __func__ , SrcFilename );
if ( false
if ( false
| | ! scalar : : random ( ) . valid ( )
| | ! scalar : : random ( ) . valid ( )
| | point : : ptBase - point : : ptBase ! = point : : ptZero
| | point : : ptBase - point : : ptBase ! = point : : ptZero
@ -894,13 +937,13 @@ static bool TestShareSecretGenerationSpeed(void) {
hash (
hash (
hsh ( ) < < first < < second
hsh ( ) < < first < < second
)
)
) throw MyException ( " inconsistent hashes generated on strings " );
) throw MyException ( " inconsistent hashes generated on strings " , __LINE__ , __func__ , SrcFilename );
const char * _ = " hello " ;
const char * _ = " hello " ;
hash a ( _ ) ;
hash a ( _ ) ;
hash b ( a ) ;
hash b ( a ) ;
hash c ( b ) ;
hash c ( b ) ;
if ( hash ( b , c ) ! = hash ( hsh ( ) < < b < < c )
if ( hash ( b , c ) ! = hash ( hsh ( ) < < b < < c )
) throw MyException ( " inconsistent hashes generated " );
) throw MyException ( " inconsistent hashes generated " , __LINE__ , __func__ , SrcFilename );
constexpr int hashes { 3000 } ;
constexpr int hashes { 3000 } ;
start_time = std : : chrono : : high_resolution_clock : : now ( ) ;
start_time = std : : chrono : : high_resolution_clock : : now ( ) ;
for ( int i { 0 } ; i < hashes ; i + + ) {
for ( int i { 0 } ; i < hashes ; i + + ) {
@ -937,6 +980,11 @@ static bool TestShareSecretGenerationSpeed(void) {
}
}
}
}
catch ( const MyException & e ) {
errorCode = e . what_num ( ) ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( const std : : exception & e ) {
catch ( const std : : exception & e ) {
errorCode = 10 ;
errorCode = 10 ;
szError = e . what ( ) ;
szError = e . what ( ) ;
@ -1083,6 +1131,11 @@ static bool slash6UnitTest(void) {
}
}
// 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.
// 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 MyException & e ) {
errorCode = e . what_num ( ) ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
catch ( const std : : exception & e ) {
catch ( const std : : exception & e ) {
errorCode = 12 ;
errorCode = 12 ;
szError = e . what ( ) ;
szError = e . what ( ) ;