1
0
Fork 0
forked from lthn/blockchain

fix: crypto test PRNG determinism, checkpoint hashes, and Zano address remnants

The crypto test PRNG was non-deterministic because setup_random() seeded
the state but grant_random_initialize_no_lock() overwrote it with
/dev/urandom on the first random call. Calling it before memset ensures
the initialized flag is set, preventing the overwrite.

Also adds --generate mode to crypto-tests for future vector regeneration,
updates checkpoint hashes for multisig_and_checkpoints (height 15) and
gen_no_attchments_in_coinbase (height 12), and replaces hardcoded Zano
addresses/URLs with Lethean equivalents in manual test scaffolding.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude 2026-02-06 13:17:11 +00:00
parent 4120a9a664
commit 7ee2265cae
No known key found for this signature in database
GPG key ID: AF404715446AEB41
6 changed files with 92 additions and 37 deletions

View file

@ -708,7 +708,7 @@ bool gen_no_attchments_in_coinbase::init_config_set_cp(currency::core& c, size_t
// different checkpoints due to different block versions for different hardforks -> different hashes
if (crc.is_hardfork_active_for_height(ZANO_HARDFORK_03, 11) && !crc.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, 11))
{
m_checkpoints.add_checkpoint(12, "70fbbd33d88ccaa26f9fe64d102bcff2572494009339de9fab7158a40633fbb5");
m_checkpoints.add_checkpoint(12, "0300604e3c4018c79f4d81fbc0d15b3206956a95efc237f70c963db926773728");
}
else
{

View file

@ -1638,7 +1638,7 @@ multisig_and_checkpoints::multisig_and_checkpoints()
bool multisig_and_checkpoints::set_cp(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
currency::checkpoints checkpoints;
checkpoints.add_checkpoint(15, "a78fa870608991aa773d5d5aaf684ac77fea30c3e103b00d3c05c15912215c31");
checkpoints.add_checkpoint(15, "bd41e498afb84ca8bdcf9c1890ab48902dc1f202ce7c2a84cb9fa16c4a526d62");
c.set_checkpoints(std::move(checkpoints));
return true;

View file

@ -30,28 +30,40 @@ bool operator !=(const ec_scalar &a, const ec_scalar &b) {
bool operator !=(const ec_point &a, const ec_point &b) {
return 0 != memcmp(&a, &b, sizeof(ec_point));
}
/*
bool operator !=(const secret_key &a, const secret_key &b) {
return 0 != memcmp(&a, &b, sizeof(secret_key));
static string tohex(const void *data, size_t len) {
string res;
res.reserve(len * 2);
const unsigned char *p = reinterpret_cast<const unsigned char *>(data);
for (size_t i = 0; i < len; i++) {
char buf[3];
snprintf(buf, sizeof(buf), "%02x", p[i]);
res += buf;
}
return res;
}
bool operator !=(const key_derivation &a, const key_derivation &b) {
return 0 != memcmp(&a, &b, sizeof(key_derivation));
}*/
template<typename T>
static string tohex(const T &v) { return tohex(&v, sizeof(T)); }
int main(int argc, char *argv[]) {
fstream input;
string cmd;
size_t test = 0;
bool error = false;
bool generate = false;
setup_random();
if (argc != 2) {
cerr << "invalid arguments" << endl;
if (argc == 3 && string(argv[1]) == "--generate") {
generate = true;
input.open(argv[2], ios_base::in);
} else if (argc == 2) {
input.open(argv[1], ios_base::in);
} else {
cerr << "usage: crypto-tests [--generate] <tests.txt>" << endl;
return 1;
}
input.open(argv[1], ios_base::in);
for (;;) {
++test;
input.exceptions(ios_base::badbit);
@ -64,14 +76,18 @@ int main(int argc, char *argv[]) {
bool expected = false, actual = false;
get(input, scalar, expected);
actual = check_scalar(scalar);
if (expected != actual) {
if (generate) {
cout << "check_scalar " << tohex(scalar) << " " << (actual ? "true" : "false") << endl;
} else if (expected != actual) {
goto error;
}
} else if (cmd == "random_scalar") {
ec_scalar expected, actual;
get(input, expected);
random_scalar(actual);
if (expected != actual) {
if (generate) {
cout << "random_scalar " << tohex(actual) << endl;
} else if (expected != actual) {
goto error;
}
} else if (cmd == "hash_to_scalar") {
@ -79,7 +95,9 @@ int main(int argc, char *argv[]) {
ec_scalar expected, actual;
get(input, data, expected);
hash_to_scalar(data.data(), data.size(), actual);
if (expected != actual) {
if (generate) {
cout << "hash_to_scalar " << (data.empty() ? "x" : tohex(data.data(), data.size())) << " " << tohex(actual) << endl;
} else if (expected != actual) {
goto error;
}
} else if (cmd == "generate_keys") {
@ -87,7 +105,9 @@ int main(int argc, char *argv[]) {
secret_key expected2, actual2;
get(input, expected1, expected2);
generate_keys(actual1, actual2);
if (expected1 != actual1 || expected2 != actual2) {
if (generate) {
cout << "generate_keys " << tohex(actual1) << " " << tohex(actual2) << endl;
} else if (expected1 != actual1 || expected2 != actual2) {
goto error;
}
} else if (cmd == "check_key") {
@ -95,7 +115,9 @@ int main(int argc, char *argv[]) {
bool expected, actual;
get(input, key, expected);
actual = check_key(key);
if (expected != actual) {
if (generate) {
cout << "check_key " << tohex(key) << " " << (actual ? "true" : "false") << endl;
} else if (expected != actual) {
goto error;
}
} else if (cmd == "secret_key_to_public_key") {
@ -107,7 +129,11 @@ int main(int argc, char *argv[]) {
get(input, expected2);
}
actual1 = secret_key_to_public_key(sec, actual2);
if (expected1 != actual1 || (expected1 && expected2 != actual2)) {
if (generate) {
cout << "secret_key_to_public_key " << tohex(sec) << " " << (actual1 ? "true" : "false");
if (actual1) cout << " " << tohex(actual2);
cout << endl;
} else if (expected1 != actual1 || (expected1 && expected2 != actual2)) {
goto error;
}
} else if (cmd == "generate_key_derivation") {
@ -120,7 +146,11 @@ int main(int argc, char *argv[]) {
get(input, expected2);
}
actual1 = generate_key_derivation(key1, key2, actual2);
if (expected1 != actual1 || (expected1 && expected2 != actual2)) {
if (generate) {
cout << "generate_key_derivation " << tohex(key1) << " " << tohex(key2) << " " << (actual1 ? "true" : "false");
if (actual1) cout << " " << tohex(actual2);
cout << endl;
} else if (expected1 != actual1 || (expected1 && expected2 != actual2)) {
goto error;
}
} else if (cmd == "derive_public_key") {
@ -134,7 +164,11 @@ int main(int argc, char *argv[]) {
get(input, expected2);
}
actual1 = derive_public_key(derivation, output_index, base, actual2);
if (expected1 != actual1 || (expected1 && expected2 != actual2)) {
if (generate) {
cout << "derive_public_key " << tohex(derivation) << " " << output_index << " " << tohex(base) << " " << (actual1 ? "true" : "false");
if (actual1) cout << " " << tohex(actual2);
cout << endl;
} else if (expected1 != actual1 || (expected1 && expected2 != actual2)) {
goto error;
}
} else if (cmd == "derive_secret_key") {
@ -144,7 +178,9 @@ int main(int argc, char *argv[]) {
secret_key expected, actual;
get(input, derivation, output_index, base, expected);
derive_secret_key(derivation, output_index, base, actual);
if (expected != actual) {
if (generate) {
cout << "derive_secret_key " << tohex(derivation) << " " << output_index << " " << tohex(base) << " " << tohex(actual) << endl;
} else if (expected != actual) {
goto error;
}
} else if (cmd == "generate_signature") {
@ -154,7 +190,9 @@ int main(int argc, char *argv[]) {
signature expected, actual;
get(input, prefix_hash, pub, sec, expected);
generate_signature(prefix_hash, pub, sec, actual);
if (expected != actual) {
if (generate) {
cout << "generate_signature " << tohex(prefix_hash) << " " << tohex(pub) << " " << tohex(sec) << " " << tohex(actual) << endl;
} else if (expected != actual) {
goto error;
}
} else if (cmd == "check_signature") {
@ -164,7 +202,9 @@ int main(int argc, char *argv[]) {
bool expected = false, actual = false;
get(input, prefix_hash, pub, sig, expected);
actual = check_signature(prefix_hash, pub, sig);
if (expected != actual) {
if (generate) {
cout << "check_signature " << tohex(prefix_hash) << " " << tohex(pub) << " " << tohex(sig) << " " << (actual ? "true" : "false") << endl;
} else if (expected != actual) {
goto error;
}
} else if (cmd == "hash_to_point") {
@ -172,7 +212,9 @@ int main(int argc, char *argv[]) {
ec_point expected, actual;
get(input, h, expected);
hash_to_point(h, actual);
if (expected != actual) {
if (generate) {
cout << "hash_to_point " << tohex(h) << " " << tohex(actual) << endl;
} else if (expected != actual) {
goto error;
}
} else if (cmd == "hash_to_ec") {
@ -180,7 +222,9 @@ int main(int argc, char *argv[]) {
ec_point expected, actual;
get(input, key, expected);
hash_to_ec(key, actual);
if (expected != actual) {
if (generate) {
cout << "hash_to_ec " << tohex(key) << " " << tohex(actual) << endl;
} else if (expected != actual) {
goto error;
}
} else if (cmd == "generate_key_image") {
@ -189,7 +233,9 @@ int main(int argc, char *argv[]) {
key_image expected, actual;
get(input, pub, sec, expected);
generate_key_image(pub, sec, actual);
if (expected != actual) {
if (generate) {
cout << "generate_key_image " << tohex(pub) << " " << tohex(sec) << " " << tohex(actual) << endl;
} else if (expected != actual) {
goto error;
}
} else if (cmd == "generate_ring_signature") {
@ -214,7 +260,11 @@ int main(int argc, char *argv[]) {
getvar(input, pubs_count * sizeof(signature), expected.data());
actual.resize(pubs_count);
generate_ring_signature(prefix_hash, image, pubs.data(), pubs_count, sec, sec_index, actual.data());
if (expected != actual) {
if (generate) {
cout << "generate_ring_signature " << tohex(prefix_hash) << " " << tohex(image) << " " << pubs_count;
for (i = 0; i < pubs_count; i++) cout << " " << tohex(vpubs[i]);
cout << " " << tohex(sec) << " " << sec_index << " " << tohex(actual.data(), pubs_count * sizeof(signature)) << endl;
} else if (expected != actual) {
goto error;
}
} else if (cmd == "check_ring_signature") {
@ -237,7 +287,11 @@ int main(int argc, char *argv[]) {
getvar(input, pubs_count * sizeof(signature), sigs.data());
get(input, expected);
actual = check_ring_signature(prefix_hash, image, pubs.data(), pubs_count, sigs.data());
if (expected != actual) {
if (generate) {
cout << "check_ring_signature " << tohex(prefix_hash) << " " << tohex(image) << " " << pubs_count;
for (i = 0; i < pubs_count; i++) cout << " " << tohex(vpubs[i]);
cout << " " << tohex(sigs.data(), pubs_count * sizeof(signature)) << " " << (actual ? "true" : "false") << endl;
} else if (expected != actual) {
goto error;
}
} else {

View file

@ -7,5 +7,6 @@
#include "crypto-tests.h"
void setup_random(void) {
grant_random_initialize_no_lock();
memset(&state, 42, sizeof(union hash_state));
}

View file

@ -33,11 +33,11 @@ void run_plain_wallet_api_test()
LOG_PRINT_L0("Creating instance...");
//plain_wallet::set_bundle_working_dir("E:\\tmp\\check_export");
std::string s = plain_wallet::init("195.201.107.230", "33333", boost::dll::program_location().parent_path().string(), 1);
std::string s = plain_wallet::init("127.0.0.1", "36941", boost::dll::program_location().parent_path().string(), 1);
//s = plain_wallet::get_export_private_info("E:\\tmp\\check_export");
std::string res = plain_wallet::sync_call("get_seed_phrase_info", 0, "{\"seed_phrase\":\"aZxat4HAWriVQ3enkGcVsrZRdMseAJswG3CSEwTqZS246VsFQ53w26eZstYsu1jWE74Atz9ajLxFnBsVTafncWNH5SMv4zHFaTS:1780c4d5dd7e97cc4a75ea8baa7977d12ef948b9a6dddc2a9a37e5e22ac7180e:1599495055\"}");
std::string res = plain_wallet::sync_call("get_seed_phrase_info", 0, "{\"seed_phrase\":\"iTHNHvUTA2gR7gSb854s58SpAyqtR5aCNcfzBzVHjhvPcw2gQ2PHDiwT48U4ZyLVjtLxev8fAQ7NaGLZe6ihTSgp7gL45MJTCK:1780c4d5dd7e97cc4a75ea8baa7977d12ef948b9a6dddc2a9a37e5e22ac7180e:1599495055\"}");
// res = plain_wallet::restore("footstep knowledge fur capture honey minute carefully peaceful lovely crawl lunch government nightmare friendship myself sign possibly plan flower depression bread rainbow wrong hardly dark chest",
@ -50,7 +50,7 @@ void run_plain_wallet_api_test()
res = plain_wallet::close_wallet(0);
res = plain_wallet::invoke(0, "{\"method\":\"transfer\",\"params\":{\"destinations\":[{\"amount\":10000000000,\"address\":\"aZxat4HAWriVQ3enkGcVsrZRdMseAJswG3CSEwTqZS246VsFQ53w26eZstYsu1jWE74Atz9ajLxFnBsVTafncWNH5SMv4zHFaTS\"}],\"fee\":10000000000,\"mixin\":1011111,\"payment_id\":\"\",\"push_payer\":true,\"hide_receiver\":false}}");
res = plain_wallet::invoke(0, "{\"method\":\"transfer\",\"params\":{\"destinations\":[{\"amount\":10000000000,\"address\":\"iTHNHvUTA2gR7gSb854s58SpAyqtR5aCNcfzBzVHjhvPcw2gQ2PHDiwT48U4ZyLVjtLxev8fAQ7NaGLZe6ihTSgp7gL45MJTCK\"}],\"fee\":10000000000,\"mixin\":1011111,\"payment_id\":\"\",\"push_payer\":true,\"hide_receiver\":false}}");
//epee::misc_utils::sleep_no_w(10000000);

View file

@ -74,7 +74,7 @@ void test_plain_wallet()
{
//std::string res = plain_wallet::init("195.201.107.230", "33340", "C:\\Users\\roky\\home\\", 0);
//std::string res = plain_wallet::init("", "", "C:\\Users\\roky\\home\\", 0);
std::string res = plain_wallet::init("https://node.zano.org", "443", "C:\\Users\\roky\\home\\", LOG_LEVEL_2);
std::string res = plain_wallet::init("127.0.0.1", "36941", "C:\\Users\\roky\\home\\", LOG_LEVEL_2);
//std::string res = plain_wallet::init("127.0.0.1", "12111", "C:\\Users\\roky\\home22\\", 0);
plain_wallet::configure_object conf = AUTO_VAL_INIT(conf);
@ -112,9 +112,9 @@ void test_plain_wallet()
epee::misc_utils::sleep_no_w(2000);
//res = plain_wallet::sync_call("reset_connection_url", 0, "195.201.107.230:33336");
//res = plain_wallet::sync_call("reset_connection_url", 0, "https://node.zano.org:443");
//res = plain_wallet::sync_call("reset_connection_url", 0, "https://zano.cakewallet.com");
//res = plain_wallet::sync_call("reset_connection_url", 0, "https://zano.api.wombat.systems:443");
//res = plain_wallet::sync_call("reset_connection_url", 0, "127.0.0.1:36941");
//res = plain_wallet::sync_call("reset_connection_url", 0, "127.0.0.1:36941");
//res = plain_wallet::sync_call("reset_connection_url", 0, "127.0.0.1:36941");
//res = plain_wallet::sync_call("reset_connection_url", 0, "http://127.0.0.1:11211");
@ -178,7 +178,7 @@ void test_plain_wallet()
std::string res3 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
//invoke_body = "{\r\n \"method\": \"transfer\",\r\n \"params\": {\r\n \"destinations\": [\r\n {\r\n \"amount\": \"1000000000000\",\r\n \"address\": \"ZxD9oVwGwW6ULix9Pqttnr7JDpaoLvDVA1KJ9eA9KRxPMRZT5X7WwtU94XH1Z6q6XTMxNbHmbV2xfZ429XxV6fST2DxEg4BQV\",\r\n \"asset_id\": \"cc4e69455e63f4a581257382191de6856c2156630b3fba0db4bdd73ffcfb36b6\"\r\n }\r\n ],\r\n \"fee\": 10000000000,\r\n \"mixin\": 10,\r\n \"payment_id\": \"\",\r\n \"comment\": \"\",\r\n \"push_payer\": false,\r\n \"hide_receiver\": true\r\n }\r\n}";
//invoke_body = "{\r\n \"method\": \"transfer\",\r\n \"params\": {\r\n \"destinations\": [\r\n {\r\n \"amount\": \"1000000000000\",\r\n \"address\": \"iTHNHvUTA2gR7gSb854s58SpAyqtR5aCNcfzBzVHjhvPcw2gQ2PHDiwT48U4ZyLVjtLxev8fAQ7NaGLZe6ihTSgp7gL45MJTCK\",\r\n \"asset_id\": \"cc4e69455e63f4a581257382191de6856c2156630b3fba0db4bdd73ffcfb36b6\"\r\n }\r\n ],\r\n \"fee\": 10000000000,\r\n \"mixin\": 10,\r\n \"payment_id\": \"\",\r\n \"comment\": \"\",\r\n \"push_payer\": false,\r\n \"hide_receiver\": true\r\n }\r\n}";
//std::string res4 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
//LOG_PRINT_L0(res);