From 7ac589552dc1919f182c0efc730821806cfdc9ca Mon Sep 17 00:00:00 2001 From: edtubbs Date: Fri, 22 Mar 2024 18:00:46 -0500 Subject: [PATCH] blockchain: moved chainwork to blockindex block: removed chainwork from block header block: added chainwork parameter to deserialize functions chainparams: added chainwork to genesis blocks and checkpoints headersdb: added chainwork parameter to set_chainpoint_start headersdb_file: added chainwork to genesis block and checkpoint spv: added chainwork parameter to set checkpoint validation: added chainwork parameter to check_auxpow arith_uint256: updated add and sub_arith_uint256 to work from LSB airht_uint256: updated set_compact to direct assignment arith_uint256: updated sub_arith_uint256 to unsigned borrow arith_uint256: updated sub_arith_uint256 to handle underflow arith_uint256: added arith_shift functions to header pow: updated target check with arith_uint256_is_zero pow: updated uint256_cmp to work from MSB to LSB pow: updated check_pow to swap_bytes in hash tests: updated net and block tests tests: added arith_uint256 tests make: added arith_uint256 tests --- CMakeLists.txt | 1 + Makefile.am | 1 + include/dogecoin/arith_uint256.h | 2 + include/dogecoin/block.h | 5 +- include/dogecoin/blockchain.h | 1 + include/dogecoin/chainparams.h | 6 +- include/dogecoin/headersdb.h | 2 +- include/dogecoin/headersdb_file.h | 4 +- include/dogecoin/validation.h | 2 +- src/arith_uint256.c | 26 +++-- src/block.c | 11 +-- src/chainparams.c | 18 +++- src/headersdb_file.c | 20 ++-- src/pow.c | 9 +- src/spv.c | 2 +- src/validation.c | 6 +- test/arith_uint256_tests.c | 156 ++++++++++++++++++++++++++++++ test/block_tests.c | 7 +- test/net_tests.c | 25 ++--- test/unittester.c | 2 + 20 files changed, 242 insertions(+), 64 deletions(-) create mode 100644 test/arith_uint256_tests.c diff --git a/CMakeLists.txt b/CMakeLists.txt index a3f59e710..31c7dd4ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -303,6 +303,7 @@ IF(USE_TESTS) TARGET_SOURCES(tests ${visibility} test/address_tests.c test/aes_tests.c + test/arith_uint256_tests.c test/base58_tests.c test/bip32_tests.c test/bip39_tests.c diff --git a/Makefile.am b/Makefile.am index 20052ada1..d9bbf2250 100644 --- a/Makefile.am +++ b/Makefile.am @@ -180,6 +180,7 @@ if USE_TESTS noinst_PROGRAMS += tests tests_LDADD = libdogecoin.la $(ASM_LIB_FILES) tests_SOURCES = \ + test/arith_uint256_tests.c \ test/address_tests.c \ test/aes_tests.c \ test/base58_tests.c \ diff --git a/include/dogecoin/arith_uint256.h b/include/dogecoin/arith_uint256.h index c48b2017b..7d8877120 100644 --- a/include/dogecoin/arith_uint256.h +++ b/include/dogecoin/arith_uint256.h @@ -53,6 +53,8 @@ typedef base_uint_ arith_uint256; void arith_negate(arith_uint256* input); arith_uint256* init_arith_uint256(); +void arith_shift_left(arith_uint256* input, unsigned int shift); +void arith_shift_right(arith_uint256* input, unsigned int shift); arith_uint256* set_compact(arith_uint256* hash, uint32_t compact, dogecoin_bool *pf_negative, dogecoin_bool *pf_overflow); uint8_t* arith_to_uint256(const arith_uint256* a); arith_uint256* uint_to_arith(const uint256* a); diff --git a/include/dogecoin/block.h b/include/dogecoin/block.h index 07c20c9d5..cb95a4ee9 100644 --- a/include/dogecoin/block.h +++ b/include/dogecoin/block.h @@ -55,7 +55,6 @@ typedef struct dogecoin_block_header_ { uint32_t bits; uint32_t nonce; auxpow auxpow[1]; - uint256 chainwork; } dogecoin_block_header; typedef struct dogecoin_auxpow_block_ { @@ -75,8 +74,8 @@ LIBDOGECOIN_API dogecoin_block_header* dogecoin_block_header_new(); LIBDOGECOIN_API void dogecoin_block_header_free(dogecoin_block_header* header); LIBDOGECOIN_API dogecoin_auxpow_block* dogecoin_auxpow_block_new(); LIBDOGECOIN_API void dogecoin_auxpow_block_free(dogecoin_auxpow_block* block); -LIBDOGECOIN_API int dogecoin_block_header_deserialize(dogecoin_block_header* header, struct const_buffer* buf, const dogecoin_chainparams *params); -LIBDOGECOIN_API int deserialize_dogecoin_auxpow_block(dogecoin_auxpow_block* block, struct const_buffer* buffer, const dogecoin_chainparams *params); +LIBDOGECOIN_API int dogecoin_block_header_deserialize(dogecoin_block_header* header, struct const_buffer* buf, const dogecoin_chainparams *params, uint256* chainwork); +LIBDOGECOIN_API int deserialize_dogecoin_auxpow_block(dogecoin_auxpow_block* block, struct const_buffer* buffer, const dogecoin_chainparams *params, uint256* chainwork); LIBDOGECOIN_API void dogecoin_block_header_serialize(cstring* s, const dogecoin_block_header* header); LIBDOGECOIN_API void dogecoin_block_header_copy(dogecoin_block_header* dest, const dogecoin_block_header* src); LIBDOGECOIN_API dogecoin_bool dogecoin_block_header_hash(dogecoin_block_header* header, uint256 hash); diff --git a/include/dogecoin/blockchain.h b/include/dogecoin/blockchain.h index 937afe808..ce90ad5bd 100644 --- a/include/dogecoin/blockchain.h +++ b/include/dogecoin/blockchain.h @@ -40,6 +40,7 @@ LIBDOGECOIN_BEGIN_DECL typedef struct dogecoin_blockindex { uint32_t height; uint256 hash; + uint256 chainwork; dogecoin_block_header header; struct dogecoin_blockindex* prev; } dogecoin_blockindex; diff --git a/include/dogecoin/chainparams.h b/include/dogecoin/chainparams.h index d76a3c015..5830149eb 100644 --- a/include/dogecoin/chainparams.h +++ b/include/dogecoin/chainparams.h @@ -47,11 +47,13 @@ typedef struct dogecoin_chainparams_ { uint32_t b58prefix_bip32_pubkey; const unsigned char netmagic[4]; uint256 genesisblockhash; + uint256 genesisblockchainwork; int default_port; dogecoin_dns_seed dnsseeds[8]; dogecoin_bool strict_id; dogecoin_bool auxpow_id; uint256 pow_limit; + uint256 minimumchainwork; } dogecoin_chainparams; typedef struct dogecoin_checkpoint_ { @@ -66,8 +68,8 @@ extern const dogecoin_chainparams dogecoin_chainparams_test; extern const dogecoin_chainparams dogecoin_chainparams_regtest; // the mainnet checkpoints, needs a fix size -extern const dogecoin_checkpoint dogecoin_mainnet_checkpoint_array[22]; -extern const dogecoin_checkpoint dogecoin_testnet_checkpoint_array[18]; +extern const dogecoin_checkpoint dogecoin_mainnet_checkpoint_array[23]; +extern const dogecoin_checkpoint dogecoin_testnet_checkpoint_array[19]; LIBDOGECOIN_API const dogecoin_chainparams* chain_from_b58_prefix(const char* address); LIBDOGECOIN_API int chain_from_b58_prefix_bool(char* address); diff --git a/include/dogecoin/headersdb.h b/include/dogecoin/headersdb.h index de8a69f16..2ee60cf74 100644 --- a/include/dogecoin/headersdb.h +++ b/include/dogecoin/headersdb.h @@ -52,7 +52,7 @@ typedef struct dogecoin_headers_db_interface_ dogecoin_blockindex* (*getchaintip)(void *db); dogecoin_bool (*disconnect_tip)(void *db); dogecoin_bool (*has_checkpoint_start)(void *db); - void (*set_checkpoint_start)(void *db, uint256 hash, uint32_t height); + void (*set_checkpoint_start)(void *db, uint256 hash, uint32_t height, uint256 chainwork); } dogecoin_headers_db_interface; LIBDOGECOIN_END_DECL diff --git a/include/dogecoin/headersdb_file.h b/include/dogecoin/headersdb_file.h index e568da95f..f089ddb0a 100644 --- a/include/dogecoin/headersdb_file.h +++ b/include/dogecoin/headersdb_file.h @@ -63,7 +63,7 @@ dogecoin_blockindex * dogecoin_headersdb_find(dogecoin_headers_db* db, uint256 h dogecoin_blockindex * dogecoin_headersdb_getchaintip(dogecoin_headers_db* db); dogecoin_bool dogecoin_headersdb_disconnect_tip(dogecoin_headers_db* db); dogecoin_bool dogecoin_headersdb_has_checkpoint_start(dogecoin_headers_db* db); -void dogecoin_headersdb_set_checkpoint_start(dogecoin_headers_db* db, uint256 hash, uint32_t height); +void dogecoin_headersdb_set_checkpoint_start(dogecoin_headers_db* db, uint256 hash, uint32_t height, uint256 chainwork); static const dogecoin_headers_db_interface dogecoin_headers_db_interface_file = { (void* (*)(const dogecoin_chainparams*, dogecoin_bool))dogecoin_headers_db_new, @@ -74,7 +74,7 @@ static const dogecoin_headers_db_interface dogecoin_headers_db_interface_file = (dogecoin_blockindex* (*)(void *))dogecoin_headersdb_getchaintip, (dogecoin_bool (*)(void *))dogecoin_headersdb_disconnect_tip, (dogecoin_bool (*)(void *))dogecoin_headersdb_has_checkpoint_start, - (void (*)(void *, uint256, uint32_t))dogecoin_headersdb_set_checkpoint_start + (void (*)(void *, uint256, uint32_t, uint256))dogecoin_headersdb_set_checkpoint_start }; LIBDOGECOIN_END_DECL diff --git a/include/dogecoin/validation.h b/include/dogecoin/validation.h index c4197b294..f1f9d7b1f 100644 --- a/include/dogecoin/validation.h +++ b/include/dogecoin/validation.h @@ -45,7 +45,7 @@ LIBDOGECOIN_BEGIN_DECL LIBDOGECOIN_API uint32_t get_chainid(uint32_t version); LIBDOGECOIN_API dogecoin_bool is_auxpow(uint32_t version); LIBDOGECOIN_API dogecoin_bool is_legacy(uint32_t version); -LIBDOGECOIN_API dogecoin_bool check_auxpow(dogecoin_auxpow_block* block, dogecoin_chainparams* params); +LIBDOGECOIN_API dogecoin_bool check_auxpow(dogecoin_auxpow_block* block, dogecoin_chainparams* params, uint256* chainwork); LIBDOGECOIN_API dogecoin_bool dogecoin_block_header_scrypt_hash(cstring* s, uint256* hash); LIBDOGECOIN_END_DECL diff --git a/src/arith_uint256.c b/src/arith_uint256.c index 08f447a20..18fc39361 100644 --- a/src/arith_uint256.c +++ b/src/arith_uint256.c @@ -88,9 +88,9 @@ arith_uint256* set_compact(arith_uint256* hash, uint32_t compact, dogecoin_bool uint32_t word = compact & 0x007fffff; if (size <= 3) { word >>= 8 * (3 - size); - memcpy_safe(&hash->pn[0], &word, sizeof word); + hash->pn[0] = word; } else { - memcpy_safe(&hash->pn[0], &word, sizeof word); + hash->pn[0] = word; arith_shift_left(hash, 8 * (size - 3)); } if (pf_negative) *pf_negative = word != 0 && (compact & 0x00800000) != 0; @@ -152,21 +152,27 @@ arith_uint256* div_arith_uint256(arith_uint256* a, arith_uint256* b) { arith_uint256* add_arith_uint256(arith_uint256* a, arith_uint256* b) { arith_uint256* result = init_arith_uint256(); uint64_t carry = 0; - for (int i = WIDTH - 1; i >= 0; i--) { + for (int i = 0; i < WIDTH; i++) { uint64_t sum = (uint64_t)a->pn[i] + b->pn[i] + carry; - result->pn[i] = sum; // This will only keep the lower 32 bits - carry = sum >> 32; // This will keep the upper 32 bits (carry) + result->pn[i] = (uint32_t)sum; // This will only keep the lower 32 bits + carry = sum >> 32; // Carry is the upper 32 bits } return result; } arith_uint256* sub_arith_uint256(arith_uint256* a, arith_uint256* b) { + if (arith_uint256_less_than(a, b)) { + // Handle underflow if necessary + return NULL; + } arith_uint256* result = init_arith_uint256(); - int64_t carry = 0; - for (int i = WIDTH - 1; i >= 0; i--) { - int64_t diff = (uint64_t)a->pn[i] - b->pn[i] - carry; - result->pn[i] = diff; // This will only keep the lower 32 bits - carry = (diff < 0) ? 1 : 0; // If diff is negative, there's a borrow + uint64_t borrow = 0; + for (int i = 0; i < WIDTH; i++) { + uint64_t diff = (uint64_t)a->pn[i] - b->pn[i] - borrow; + result->pn[i] = (uint32_t)diff; // Keep only lower 32 bits + // If diff is less than zero when interpreted as signed, there's a borrow. + // Note: This checks the high bit of the 64-bit diff calculation for borrow. + borrow = (diff > (uint64_t)UINT32_MAX) ? 1 : 0; } return result; } diff --git a/src/block.c b/src/block.c index 57d1e7719..45d33be70 100644 --- a/src/block.c +++ b/src/block.c @@ -168,7 +168,6 @@ dogecoin_block_header* dogecoin_block_header_new() { header->auxpow->check = check; header->auxpow->ctx = header; header->auxpow->is = false; - dogecoin_mem_zero(&header->chainwork, DOGECOIN_HASH_LENGTH); return header; } @@ -310,10 +309,11 @@ void print_block(dogecoin_auxpow_block* block) { * @param header The header object to be constructed. * @param buf The buffer to deserialize from. * @param params The chain parameters. + * @param chainwork The computed chainwork. * * @return 1 if deserialization was successful, 0 otherwise. */ -int dogecoin_block_header_deserialize(dogecoin_block_header* header, struct const_buffer* buf, const dogecoin_chainparams *params) { +int dogecoin_block_header_deserialize(dogecoin_block_header* header, struct const_buffer* buf, const dogecoin_chainparams *params, uint256* chainwork) { dogecoin_auxpow_block* block = dogecoin_auxpow_block_new(); if (!deser_s32(&block->header->version, buf)) return false; @@ -329,7 +329,7 @@ int dogecoin_block_header_deserialize(dogecoin_block_header* header, struct cons return false; dogecoin_block_header_copy(header, block->header); if ((block->header->version & 0x100) != 0 && buf->len) { - if (!deserialize_dogecoin_auxpow_block(block, buf, params)) { + if (!deserialize_dogecoin_auxpow_block(block, buf, params, chainwork)) { printf("%s:%d:%s:%s\n", __FILE__, __LINE__, __func__, strerror(errno)); return false; } @@ -339,7 +339,7 @@ int dogecoin_block_header_deserialize(dogecoin_block_header* header, struct cons return true; } -int deserialize_dogecoin_auxpow_block(dogecoin_auxpow_block* block, struct const_buffer* buffer, const dogecoin_chainparams *params) { +int deserialize_dogecoin_auxpow_block(dogecoin_auxpow_block* block, struct const_buffer* buffer, const dogecoin_chainparams *params, uint256* chainwork) { if (buffer->len > DOGECOIN_MAX_P2P_MSG_SIZE) { return printf("\ntransaction is invalid or to large.\n\n"); } @@ -428,7 +428,7 @@ int deserialize_dogecoin_auxpow_block(dogecoin_auxpow_block* block, struct const return false; } - if (!check_auxpow(block, (dogecoin_chainparams*)params)) { + if (!check_auxpow(block, (dogecoin_chainparams*)params, chainwork)) { printf("check_auxpow failed!\n"); return false; } @@ -473,7 +473,6 @@ void dogecoin_block_header_copy(dogecoin_block_header* dest, const dogecoin_bloc dest->auxpow->check = src->auxpow->check; dest->auxpow->ctx = src->auxpow->ctx; dest->auxpow->is = src->auxpow->is; - memcpy_safe(&dest->chainwork, &src->chainwork, sizeof(src->chainwork)); } /** diff --git a/src/chainparams.c b/src/chainparams.c index 85096ca9e..8eaa73dd1 100644 --- a/src/chainparams.c +++ b/src/chainparams.c @@ -39,11 +39,13 @@ const dogecoin_chainparams dogecoin_chainparams_main = { 0x02facafd, // starts with dgub {0xc0, 0xc0, 0xc0, 0xc0}, // pch msg prefixes (magic bytes) {0x91, 0x56, 0x35, 0x2c, 0x18, 0x18, 0xb3, 0x2e, 0x90, 0xc9, 0xe7, 0x92, 0xef, 0xd6, 0xa1, 0x1a, 0x82, 0xfe, 0x79, 0x56, 0xa6, 0x30, 0xf0, 0x3b, 0xbe, 0xe2, 0x36, 0xce, 0xda, 0xe3, 0x91, 0x1a}, + {0x10, 0x00, 0x10, 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}, 22556, {{"seed.multidoge.org"}, {{1}}}, true, 0x0062, - {0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} // pow limit + {0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // pow limit + {0x9b, 0xa4, 0x46, 0xf2, 0x6c, 0xa8, 0x2a, 0x3d, 0x99, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; const dogecoin_chainparams dogecoin_chainparams_test = { @@ -56,11 +58,13 @@ const dogecoin_chainparams dogecoin_chainparams_test = { 0x043587cf, // starts with tpub {0xfc, 0xc1, 0xb7, 0xdc}, // pch msg prefixes (magic bytes) {0x9e, 0x55, 0x50, 0x73, 0xd0, 0xc4, 0xf3, 0x64, 0x56, 0xdb, 0x89, 0x51, 0xf4, 0x49, 0x70, 0x4d, 0x54, 0x4d, 0x28, 0x26, 0xd9, 0xaa, 0x60, 0x63, 0x6b, 0x40, 0x37, 0x46, 0x26, 0x78, 0x0a, 0xbb}, + {0x10, 0x00, 0x10, 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}, 44556, {{"testseed.jrn.me.uk"}, {{0}}}, false, 0x0062, - {0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} // pow limit + {0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // pow limit + {0x26, 0x9a, 0xff, 0x62, 0x2f, 0x0f, 0x54, 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} }; const dogecoin_chainparams dogecoin_chainparams_regtest = { @@ -73,11 +77,13 @@ const dogecoin_chainparams dogecoin_chainparams_regtest = { 0x043587cf, // starts with tpub {0xfa, 0xbf, 0xb5, 0xda}, // pch msg prefixes (magic bytes) {0xa5, 0x73, 0xe9, 0x1c, 0x17, 0x72, 0x07, 0x6c, 0x0d, 0x40, 0xf7, 0x0e, 0x44, 0x08, 0xc8, 0x3a, 0x31, 0x70, 0x5f, 0x29, 0x6a, 0xe6, 0xe7, 0x62, 0x9d, 0x4a, 0xdc, 0xb5, 0xa3, 0x60, 0x21, 0x3d}, + {0x02, 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}, 18332, {{"testseed.jrn.me.uk"}, {{0}}}, true, 0x0062, - {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} // pow limit + {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // pow limit + {0x02, 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} }; const dogecoin_checkpoint dogecoin_mainnet_checkpoint_array[] = { @@ -102,7 +108,8 @@ const dogecoin_checkpoint dogecoin_mainnet_checkpoint_array[] = { {3606083, "954c7c66dee51f0a3fb1edb26200b735f5275fe54d9505c76ebd2bcabac36f1e", 1613218169, 0x1a03d764}, {3854173, "e4b4ecda4c022406c502a247c0525480268ce7abbbef632796e8ca1646425e75", 1628934997, 0x1a03ca36}, {3963597, "2b6927cfaa5e82353d45f02be8aadd3bfd165ece5ce24b9bfa4db20432befb5d", 1635884460, 0x1a037bc9}, - {4303965, "ed7d266dcbd8bb8af80f9ccb8deb3e18f9cc3f6972912680feeb37b090f8cee0", 1657646310, 0x1a0344f5}}; + {4303965, "ed7d266dcbd8bb8af80f9ccb8deb3e18f9cc3f6972912680feeb37b090f8cee0", 1657646310, 0x1a0344f5}, + {5050000, "e7d4577405223918491477db725a393bcfc349d8ee63b0a4fde23cbfbfd81dea", 1705383360, 0x1a019541}}; const dogecoin_checkpoint dogecoin_testnet_checkpoint_array[] = { {0, "bb0a78264637406b6360aad926284d544d7049f45189db5664f3c4d07350559e", 1391503289, 0x1e0ffff0}, @@ -122,7 +129,8 @@ const dogecoin_checkpoint dogecoin_testnet_checkpoint_array[] = { {3062910, "113c41c00934f940a41f99d18b2ad9aefd183a4b7fe80527e1e6c12779bd0246", 1613218844, 0x1e0e2221}, {3286675, "07fef07a255d510297c9189dc96da5f4e41a8184bc979df8294487f07fee1cf3", 1628932841, 0x1e0fffff}, {3445426, "70574db7856bd685abe7b0a8a3e79b29882620645bd763b01459176bceb58cd1", 1635884611, 0x1e0fffff}, - {3976284, "af23c3e750bb4f2ce091235f006e7e4e2af453d4c866282e7870471dcfeb4382", 1657646588, 0x1e0fffff}}; + {3976284, "af23c3e750bb4f2ce091235f006e7e4e2af453d4c866282e7870471dcfeb4382", 1657646588, 0x1e0fffff}, + {5900000, "199bea6a442310589cbb50a193a30b097c228bd5a0f21af21e4e53dd57c382d3", 1703511130, 0x1e0fffff}}; const dogecoin_chainparams* chain_from_b58_prefix(const char* address) { /* determine address prefix for network chainparams */ diff --git a/src/headersdb_file.c b/src/headersdb_file.c index b88ca3b56..993ae474c 100644 --- a/src/headersdb_file.c +++ b/src/headersdb_file.c @@ -89,6 +89,7 @@ dogecoin_headers_db* dogecoin_headers_db_new(const dogecoin_chainparams* chainpa db->genesis.height = 0; db->genesis.prev = NULL; memcpy_safe(db->genesis.hash, chainparams->genesisblockhash, DOGECOIN_HASH_LENGTH); + memcpy_safe(db->genesis.chainwork, chainparams->genesisblockchainwork, DOGECOIN_HASH_LENGTH); db->chaintip = &db->genesis; db->chainbottom = &db->genesis; @@ -231,7 +232,7 @@ dogecoin_bool dogecoin_headers_db_load(dogecoin_headers_db* db, const char *file { dogecoin_blockindex *chainheader = dogecoin_calloc(1, sizeof(dogecoin_blockindex)); chainheader->height = height; - if (!dogecoin_block_header_deserialize(&chainheader->header, &cbuf_all, db->params)) { + if (!dogecoin_block_header_deserialize(&chainheader->header, &cbuf_all, db->params, &chainheader->chainwork)) { dogecoin_block_header_free(&chainheader->header); dogecoin_free(chainheader); fprintf(stderr, "\nError: Invalid data found.\n"); @@ -295,8 +296,7 @@ dogecoin_blockindex * dogecoin_headers_db_connect_hdr(dogecoin_headers_db* db, s *connected = false; dogecoin_blockindex *blockindex = dogecoin_calloc(1, sizeof(dogecoin_blockindex)); - if (!dogecoin_block_header_deserialize(&blockindex->header, buf, db->params)) - { + if (!dogecoin_block_header_deserialize(&blockindex->header, buf, db->params, &blockindex->chainwork)) { fprintf(stderr, "Error deserializing block header\n"); return blockindex; } @@ -333,7 +333,7 @@ dogecoin_blockindex * dogecoin_headers_db_connect_hdr(dogecoin_headers_db* db, s dogecoin_block_header_serialize(s, (const dogecoin_block_header*) &blockindex->header); dogecoin_block_header_scrypt_hash(s, &hash); cstr_free(s, true); - if (!check_pow(&hash, blockindex->header.bits, db->params, &blockindex->header.chainwork)) { + if (!check_pow(&hash, blockindex->header.bits, db->params, &blockindex->chainwork)) { printf("%s:%d:%s : non-AUX proof of work failed : %s\n", __FILE__, __LINE__, __func__, strerror(errno)); return blockindex; } @@ -343,14 +343,14 @@ dogecoin_blockindex * dogecoin_headers_db_connect_hdr(dogecoin_headers_db* db, s blockindex->height = connect_at->height+1; arith_uint256* connect_at_chainwork = init_arith_uint256(); - memcpy(connect_at_chainwork, connect_at->header.chainwork, sizeof(connect_at->header.chainwork)); + memcpy(connect_at_chainwork, connect_at->chainwork, sizeof(connect_at->chainwork)); arith_uint256* blockindex_chainwork = init_arith_uint256(); - memcpy(blockindex_chainwork, blockindex->header.chainwork, sizeof(blockindex->header.chainwork)); + memcpy(blockindex_chainwork, blockindex->chainwork, sizeof(blockindex->chainwork)); arith_uint256* chaintip_chainwork = init_arith_uint256(); - memcpy(chaintip_chainwork, db->chaintip->header.chainwork, sizeof(db->chaintip->header.chainwork)); + memcpy(chaintip_chainwork, db->chaintip->chainwork, sizeof(db->chaintip->chainwork)); arith_uint256* added_chainwork = add_arith_uint256(connect_at_chainwork, blockindex_chainwork); - memcpy(blockindex->header.chainwork, (const arith_uint256*) added_chainwork, sizeof(blockindex->header.chainwork)); + memcpy(blockindex->chainwork, (const arith_uint256*) added_chainwork, sizeof(blockindex->chainwork)); // Free the dynamically allocated memory dogecoin_free(connect_at_chainwork); @@ -564,10 +564,12 @@ dogecoin_bool dogecoin_headersdb_has_checkpoint_start(dogecoin_headers_db* db) { * @param db The headers database. * @param hash The hash of the block that is the checkpoint. * @param height The height of the block that this is a checkpoint for. + * @param chainwork The chainwork of the block that this is a checkpoint for. */ -void dogecoin_headersdb_set_checkpoint_start(dogecoin_headers_db* db, uint256 hash, uint32_t height) { +void dogecoin_headersdb_set_checkpoint_start(dogecoin_headers_db* db, uint256 hash, uint32_t height, uint256 chainwork) { db->chainbottom = dogecoin_calloc(1, sizeof(dogecoin_blockindex)); db->chainbottom->height = height; memcpy_safe(db->chainbottom->hash, hash, sizeof(uint256)); + memcpy_safe(db->chainbottom->chainwork, chainwork, sizeof(uint256)); db->chaintip = db->chainbottom; } diff --git a/src/pow.c b/src/pow.c index 6f19d162f..89eaffd40 100644 --- a/src/pow.c +++ b/src/pow.c @@ -30,7 +30,7 @@ #include dogecoin_bool uint256_cmp(const uint256 a, const uint256 b) { - for (int i = 0; i <= 31; i++) { + for (int i = 31; i >= 0; i--) { if (a[i] > b[i]) { return true; } else if (a[i] < b[i]) { @@ -44,16 +44,16 @@ dogecoin_bool check_pow(uint256* hash, unsigned int nbits, const dogecoin_chainp dogecoin_bool f_negative, f_overflow; arith_uint256* target = init_arith_uint256(); target = set_compact(target, nbits, &f_negative, &f_overflow); - swap_bytes((uint8_t*)target, sizeof (arith_uint256)); uint8_t* target_uint256 = dogecoin_malloc(sizeof(uint256)); memcpy(target_uint256, target, sizeof(arith_uint256)); - if (f_negative || (const uint8_t*)target == 0 || f_overflow || uint256_cmp(target_uint256, params->pow_limit)) { + if (f_negative || arith_uint256_is_zero(target) || f_overflow || uint256_cmp(target_uint256, params->pow_limit)) { printf("%d:%s: f_negative: %d target == 0: %d f_overflow: %d\n", __LINE__, __func__, f_negative, (const uint8_t*)target == 0, f_overflow); dogecoin_free(target); dogecoin_free(target_uint256); return false; } + swap_bytes((uint8_t*)hash, sizeof(uint256)); if (uint256_cmp((const uint8_t*)hash, target_uint256)) { char* rtn_str = utils_uint8_to_hex((const uint8_t*)hash, 32); char hash_str[65] = ""; @@ -76,9 +76,6 @@ dogecoin_bool check_pow(uint256* hash, unsigned int nbits, const dogecoin_chainp arith_uint256* one = init_arith_uint256(); one->pn[0] = 1; // Set the lowest word to 1 - swap_bytes((uint8_t*)neg_target, sizeof(arith_uint256)); - swap_bytes((uint8_t*)target, sizeof(arith_uint256)); - // hashes = ~target / (target + 1) arith_uint256* target_plus_one = add_arith_uint256(target, one); arith_uint256* hashes = div_arith_uint256(neg_target, target_plus_one); diff --git a/src/spv.c b/src/spv.c index 04c21b30e..7a6dcd8bf 100644 --- a/src/spv.c +++ b/src/spv.c @@ -339,7 +339,7 @@ void dogecoin_net_spv_fill_block_locator(dogecoin_spv_client *client, vector *bl utils_uint256_sethex((char *)checkpoint[i].hash, (uint8_t *)hash); vector_add(blocklocators, (void *)hash); if (!client->headers_db->has_checkpoint_start(client->headers_db_ctx)) { - client->headers_db->set_checkpoint_start(client->headers_db_ctx, *hash, checkpoint[i].height); + client->headers_db->set_checkpoint_start(client->headers_db_ctx, *hash, checkpoint[i].height, (uint8_t*)client->chainparams->minimumchainwork); } } } diff --git a/src/validation.c b/src/validation.c index 24d708713..148238b41 100644 --- a/src/validation.c +++ b/src/validation.c @@ -64,7 +64,7 @@ dogecoin_bool is_legacy(uint32_t version) { || (version == 2 && get_chainid(version) == 0); } -dogecoin_bool check_auxpow(dogecoin_auxpow_block* block, dogecoin_chainparams* params) { +dogecoin_bool check_auxpow(dogecoin_auxpow_block* block, dogecoin_chainparams* params, uint256* chainwork) { /* Except for legacy blocks with full version 1, ensure that the chain ID is correct. Legacy blocks are not allowed since the merge-mining start, which is checked in AcceptBlockHeader @@ -86,7 +86,7 @@ dogecoin_bool check_auxpow(dogecoin_auxpow_block* block, dogecoin_chainparams* p dogecoin_block_header_scrypt_hash(s, &hash); cstr_free(s, true); - if (!check_pow(&hash, block->header->bits, params, &block->header->chainwork)) { + if (!check_pow(&hash, block->header->bits, params, chainwork)) { printf("%s:%d:%s : non-AUX proof of work failed : %s\n", __FILE__, __LINE__, __func__, strerror(errno)); return false; } @@ -108,7 +108,7 @@ dogecoin_bool check_auxpow(dogecoin_auxpow_block* block, dogecoin_chainparams* p dogecoin_block_header_serialize(s2, block->parent_header); dogecoin_block_header_scrypt_hash(s2, &parent_hash); cstr_free(s2, true); - if (!check_pow(&parent_hash, block->header->bits, params, &block->header->chainwork)) { + if (!check_pow(&parent_hash, block->header->bits, params, chainwork)) { printf("%s:%d:%s : AUX proof of work failed: %s\n", __FILE__, __LINE__, __func__, strerror(errno)); return false; } diff --git a/test/arith_uint256_tests.c b/test/arith_uint256_tests.c new file mode 100644 index 000000000..84f5c6a51 --- /dev/null +++ b/test/arith_uint256_tests.c @@ -0,0 +1,156 @@ +/********************************************************************** + * Copyright (c) 2024 edtubbs * + * Copyright (c) 2024 The Dogecoin Foundation * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include +#include +#include +#include + +#include +#include + +void test_init_and_negate() +{ + // Test initialization to zero + arith_uint256* zero = init_arith_uint256(); + for (int i = 0; i < WIDTH; i++) { + assert(zero->pn[i] == 0); // All parts should be zero-initialized + } + + // Test negation from zero to max and max to zero + arith_uint256* max_val = init_arith_uint256(); + for (int i = 0; i < WIDTH; i++) { + max_val->pn[i] = UINT32_MAX; + } + arith_negate(max_val); + for (int i = 0; i < WIDTH; i++) { + assert(max_val->pn[i] == 0); // Negation should bring max value to zero + } + + dogecoin_free(zero); + dogecoin_free(max_val); +} + +void test_shift_operations() +{ + // Shift left and right by various amounts + arith_uint256* one = init_arith_uint256(); + one->pn[0] = 1; + arith_uint256* shifted = init_arith_uint256(); + + for (unsigned int shift = 1; shift <= 256; shift++) { + memcpy(shifted, one, sizeof(arith_uint256)); // Reset + arith_shift_left(shifted, shift); + arith_shift_right(shifted, shift); + assert(shifted->pn[0] == (shift > 256 ? 0 : (shift == 256 ? 0 : 1))); // Expect original value or zero if shifted completely out + } + + dogecoin_free(one); + dogecoin_free(shifted); +} + +void test_set_compact() +{ + struct { + uint32_t compact; + const char* expectedHex; + bool expectedNegative; + bool expectedOverflow; + } testCases[] = { + {0x0, "0000000000000000000000000000000000000000000000000000000000000000", false, false}, + {0x00123456, "0000000000000000000000000000000000000000000000000000000000000000", false, false}, + {0x01003456, "0000000000000000000000000000000000000000000000000000000000000000", false, false}, + {0x02000056, "0000000000000000000000000000000000000000000000000000000000000000", false, false}, + {0x03000000, "0000000000000000000000000000000000000000000000000000000000000000", false, false}, + {0x04000000, "0000000000000000000000000000000000000000000000000000000000000000", false, false}, + {0x00923456, "0000000000000000000000000000000000000000000000000000000000000000", false, false}, + {0x01803456, "0000000000000000000000000000000000000000000000000000000000000000", false, false}, + {0x02800056, "0000000000000000000000000000000000000000000000000000000000000000", false, false}, + {0x03800000, "0000000000000000000000000000000000000000000000000000000000000000", false, false}, + {0x04800000, "0000000000000000000000000000000000000000000000000000000000000000", false, false}, + {0x01123456, "0000000000000000000000000000000000000000000000000000000000000012", false, false}, + {0x20123456, "1234560000000000000000000000000000000000000000000000000000000000", false, false}, + {0xff123456, "", false, true}, // This case indicates overflow, the expectedHex is empty. + }; + + for (size_t i = 0; i < sizeof(testCases) / sizeof(testCases[0]); i++) { + dogecoin_bool pfNegative = 0; + dogecoin_bool pfOverflow = 0; + arith_uint256* num = set_compact(init_arith_uint256(), testCases[i].compact, &pfNegative, &pfOverflow); + + arith_uint256* expectedNum = init_arith_uint256(); + utils_uint256_sethex((char*)testCases[i].expectedHex, (uint8_t*)expectedNum->pn); + + debug_print("Test #%zu: Compact = %08x\n", i + 1, testCases[i].compact); + if (!testCases[i].expectedOverflow) { + debug_print("Expected: %s, Got: %s\n", utils_uint8_to_hex((const uint8_t*)expectedNum->pn, sizeof(expectedNum->pn)), utils_uint8_to_hex((const uint8_t*)num->pn, sizeof(num->pn))); + assert(memcmp(num->pn, expectedNum->pn, sizeof(num->pn)) == 0); + } + + assert(pfNegative == testCases[i].expectedNegative); + assert(pfOverflow == testCases[i].expectedOverflow); + + dogecoin_free(num); + dogecoin_free(expectedNum); + } +} + +void test_arithmetic_and_comparison_operations() +{ + struct { + const char* a_hex; + const char* b_hex; + const char* sum_hex; + const char* diff_hex; // `a_hex - b_hex`, assuming `a >= b` for simplicity + } testVectors[] = { + {"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE", "01", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD"}, + {"01", "01", "02", "00"}, + {"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE", "02", "00", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC"}, + {"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "01", "00", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"}, + {"01", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "00", NULL}, + // Add more vectors as needed + }; + + for (size_t i = 0; i < sizeof(testVectors) / sizeof(testVectors[0]); i++) { + arith_uint256* a = init_arith_uint256(); + utils_uint256_sethex((char*)testVectors[i].a_hex, (uint8_t*)a->pn); + arith_uint256* b = init_arith_uint256(); + utils_uint256_sethex((char*)testVectors[i].b_hex, (uint8_t*)b->pn); + + arith_uint256* sum = add_arith_uint256(a, b); + arith_uint256* expectedSum = init_arith_uint256(); + utils_uint256_sethex((char*)testVectors[i].sum_hex, (uint8_t*)expectedSum->pn); + assert(memcmp(sum->pn, expectedSum->pn, sizeof(sum->pn)) == 0); + + arith_uint256* diff = sub_arith_uint256(a, b); + arith_uint256* expectedDiff = init_arith_uint256(); + debug_print("Test #%zu: a = %s, b = %s\n", i + 1, testVectors[i].a_hex, testVectors[i].b_hex); + if (testVectors[i].diff_hex != NULL) { + utils_uint256_sethex((char*)testVectors[i].diff_hex, (uint8_t*)expectedDiff->pn); + debug_print("Expected: %s, Got: %s\n", testVectors[i].diff_hex, utils_uint8_to_hex((const uint8_t*)diff->pn, sizeof(diff->pn))); + assert(memcmp(diff->pn, expectedDiff->pn, sizeof(diff->pn)) == 0); + } else { + assert(diff == NULL); + } + + dogecoin_free(a); + dogecoin_free(b); + dogecoin_free(sum); + dogecoin_free(diff); + dogecoin_free(expectedSum); + dogecoin_free(expectedDiff); + } +} + +int test_arith_uint256() { + test_init_and_negate(); + test_shift_operations(); + test_set_compact(); + test_arithmetic_and_comparison_operations(); + + return 0; +} diff --git a/test/block_tests.c b/test/block_tests.c index d31d41475..e9cb16a95 100644 --- a/test/block_tests.c +++ b/test/block_tests.c @@ -55,13 +55,14 @@ void test_block_header() const struct blockheadertest* test = &block_header_tests[i]; uint8_t header_data[80]; uint256 hash_data; + uint256 chainwork = {0}; utils_hex_to_bin(test->hexheader, header_data, 160, &outlen); utils_hex_to_bin(test->hexhash, hash_data, sizeof(hash_data), &outlen); dogecoin_block_header* header = dogecoin_block_header_new(); struct const_buffer buf = {header_data, 80}; - dogecoin_block_header_deserialize(header, &buf, block_header_tests[i].params); + dogecoin_block_header_deserialize(header, &buf, block_header_tests[i].params, &chainwork); // Check the copies are the same dogecoin_block_header* header_copy = dogecoin_block_header_new(); @@ -90,7 +91,6 @@ void test_block_header() // Check chainwork (genesis block only) if (i == 0) { arith_uint256* target = init_arith_uint256(); - uint256 chainwork = {0}; cstring* s = cstr_new_sz(64); dogecoin_bool f_negative, f_overflow; uint256* hash = dogecoin_uint256_vla(1); @@ -169,6 +169,7 @@ void test_block_header() u_assert_str_eq(headercheck, blockheader_h371338); uint256 checkhash; + uint256 chainwork; dogecoin_block_header_hash(&bheader, (uint8_t *)&checkhash); char hashhex[sizeof(checkhash) * 2 + 1]; utils_bin_to_hex(checkhash, sizeof(checkhash), hashhex); @@ -178,7 +179,7 @@ void test_block_header() struct const_buffer buf; buf.p = blockheader_ser->str; buf.len = blockheader_ser->len; - dogecoin_block_header_deserialize(&bheadercheck, &buf, &dogecoin_chainparams_main); + dogecoin_block_header_deserialize(&bheadercheck, &buf, &dogecoin_chainparams_main, &chainwork); u_assert_str_eq(utils_uint8_to_hex(bheader.prev_block, sizeof(bheader.prev_block)), utils_uint8_to_hex(bheadercheck.prev_block, sizeof(bheadercheck.prev_block))); cstr_free(blockheader_ser, true); dogecoin_block_header_hash(&bheaderprev, (uint8_t *)&checkhash); diff --git a/test/net_tests.c b/test/net_tests.c index d7fd90601..e07b581b7 100644 --- a/test/net_tests.c +++ b/test/net_tests.c @@ -15,12 +15,12 @@ /** * The timer_cb function is called every 60 seconds to check if the node has been - * connected for more than 5 minutes. + * connected for more than 5 minutes. * If it has, the node is disconnected - * + * * @param node The node that the timer is being called on. * @param now The current time in seconds. - * + * * @return static dogecoin_bool (uint8_t) */ static dogecoin_bool timer_cb(dogecoin_node *node, uint64_t *now) @@ -35,9 +35,9 @@ static dogecoin_bool timer_cb(dogecoin_node *node, uint64_t *now) /** * This function is called by the * logger when it needs to write to the log - * + * * @param format The format string. - * + * * @return 1 */ DISABLE_WARNING_PUSH @@ -54,11 +54,11 @@ DISABLE_WARNING_POP /** * It parses a command from the network - * + * * @param node The node that received the message. * @param hdr The header of the message. * @param buf The buffer containing the message. - * + * * @return Nothing. */ dogecoin_bool parse_cmd(struct dogecoin_node_ *node, dogecoin_p2p_msg_hdr *hdr, struct const_buffer *buf) @@ -71,11 +71,11 @@ dogecoin_bool parse_cmd(struct dogecoin_node_ *node, dogecoin_p2p_msg_hdr *hdr, /** * We send a getheaders message to the node, and then we send a getdata message to the node - * + * * @param node The node that received the message. * @param hdr The header of the message. * @param buf The buffer containing the message payload. - * + * * @return Nothing. */ void postcmd(struct dogecoin_node_ *node, dogecoin_p2p_msg_hdr *hdr, struct const_buffer *buf) @@ -83,7 +83,8 @@ void postcmd(struct dogecoin_node_ *node, dogecoin_p2p_msg_hdr *hdr, struct cons if (strcmp(hdr->command, "block") == 0) { dogecoin_block_header header; - if (!dogecoin_block_header_deserialize(&header, buf, node->nodegroup->chainparams)) return; + uint256 chainwork; + if (!dogecoin_block_header_deserialize(&header, buf, node->nodegroup->chainparams, &chainwork)) return; uint32_t vsize; if (!deser_varlen(&vsize, buf)) return; @@ -154,7 +155,7 @@ void postcmd(struct dogecoin_node_ *node, dogecoin_p2p_msg_hdr *hdr, struct cons /** * When a node's connection state changes, this function is called - * + * * @param node The node that the connection state changed for. */ void node_connection_state_changed(struct dogecoin_node_ *node) @@ -234,7 +235,7 @@ void test_net_basics_plus_download_block() group->postcmd_cb = postcmd; group->node_connection_state_changed_cb = node_connection_state_changed; group->handshake_done_cb = handshake_done; - + dogecoin_node_group_connect_next_nodes(group); dogecoin_node_group_event_loop(group); diff --git a/test/unittester.c b/test/unittester.c index 98c0a0af9..aaf5d05be 100644 --- a/test/unittester.c +++ b/test/unittester.c @@ -38,6 +38,7 @@ extern void test_address(); extern void test_aes(); +extern void test_arith_uint256(); extern void test_base58(); extern void test_base64(); extern void test_bip32(); @@ -115,6 +116,7 @@ int main() u_run_test(test_address); u_run_test(test_aes); + u_run_test(test_arith_uint256); u_run_test(test_base58); u_run_test(test_base64); u_run_test(test_bip32);