upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/test_btfaddr.cpp
diff options
context:
space:
mode:
authorBitflash-sh <btf01@proton.me>2026-07-24 11:18:11 -0300
committerBitflash-sh <btf01@proton.me>2026-07-24 11:18:11 -0300
commit51d617e70f90a972185917ea0096c1ecef2bfa8b (patch)
tree9fbbcd867de9de9d0776afdd02f594ba312c46eb /src/test_btfaddr.cpp
Bitflash: fair-launch release
Satoshi's bitcoin-0.1.0 reborn with RandomX CPU proof of work, anonymous .btf addressing over Nostr with CGNAT rendezvous, automatic peer discovery, a headless Linux node, and Windows GUI wallet. Fair launch, no premine, 21M cap.
Diffstat (limited to 'src/test_btfaddr.cpp')
-rw-r--r--src/test_btfaddr.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/test_btfaddr.cpp b/src/test_btfaddr.cpp
new file mode 100644
index 0000000..b40dcc1
--- /dev/null
+++ b/src/test_btfaddr.cpp
@@ -0,0 +1,142 @@
1// Standalone tests for btfaddr (ported from Itzal hidden.rs tests).
2// Build (UCRT64):
3// g++ -std=gnu++14 -DSECP256K1_STATIC -I../deps/include test_btfaddr.cpp btfaddr.cpp \
4// -L../deps/lib -lsecp256k1 -lssl -lcrypto -o test_btfaddr.exe
5
6#include "btfaddr.h"
7#include <openssl/rand.h>
8#define SECP256K1_STATIC
9#include <secp256k1.h>
10#include <secp256k1_schnorrsig.h>
11#include <secp256k1_extrakeys.h>
12#include <nlohmann/json.hpp>
13#include <cstdio>
14#include <cstring>
15#include <string>
16
17using json = nlohmann::json;
18
19static int g_fail = 0;
20#define CHECK(cond, name) do { \
21 if (cond) { printf(" ok %s\n", name); } \
22 else { printf(" FAIL %s\n", name); g_fail++; } } while(0)
23
24static std::string ToUpper(const std::string& s)
25{
26 std::string r = s;
27 for (char& c : r) c = (char)toupper((unsigned char)c);
28 return r;
29}
30
31int main()
32{
33 secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
34 unsigned char seed[32]; RAND_bytes(seed, 32); secp256k1_context_randomize(ctx, seed);
35
36 printf("base32_roundtrips\n");
37 {
38 std::vector<std::vector<unsigned char>> cases;
39 std::string txt = "hello btf shadow 0123456789";
40 cases.push_back(std::vector<unsigned char>(txt.begin(), txt.end()));
41 cases.push_back(std::vector<unsigned char>(34, 0x00));
42 cases.push_back(std::vector<unsigned char>(34, 0xff));
43 for (auto& data : cases)
44 {
45 std::string enc = btf::Base32Encode(data.data(), data.size());
46 std::vector<unsigned char> dec;
47 bool ok = btf::Base32Decode(enc, dec);
48 // decode may include trailing partial byte handling; compare the meaningful prefix
49 CHECK(ok && dec.size() >= data.size() &&
50 memcmp(dec.data(), data.data(), data.size()) == 0, "roundtrip");
51 }
52 }
53
54 printf("address_roundtrips_and_is_lowercase_hostname\n");
55 {
56 unsigned char pk[32]; memset(pk, 7, 32);
57 std::string a = btf::Address(pk);
58 CHECK(a.size() > 4 && a.compare(a.size()-4, 4, ".btf") == 0, "ends with .btf");
59 CHECK(btf::IsBtf(a), "IsBtf true");
60 std::string label = a.substr(0, a.size()-4);
61 bool lc = true;
62 for (unsigned char c : label)
63 if (!((c >= 'a' && c <= 'z') || (c >= '2' && c <= '7'))) lc = false;
64 CHECK(lc, "label is lowercase base32 hostname");
65 unsigned char out[32];
66 CHECK(btf::ParseAddress(a, out) && memcmp(out, pk, 32) == 0, "parse round-trips");
67 CHECK(btf::ParseAddress(ToUpper(a), out) && memcmp(out, pk, 32) == 0, "parse case-insensitive");
68 }
69
70 printf("rejects_tampered_address\n");
71 {
72 unsigned char pk[32]; memset(pk, 9, 32);
73 std::string a = btf::Address(pk);
74 std::string t = a;
75 t[0] = (t[0] == 'a') ? 'b' : 'a';
76 unsigned char out[32];
77 CHECK(!(btf::ParseAddress(t, out) && memcmp(out, pk, 32) == 0), "tampered address rejected");
78 }
79
80 printf("rejects_non_btf\n");
81 {
82 unsigned char out[32];
83 CHECK(!btf::IsBtf("example.com"), "example.com not btf");
84 CHECK(!btf::ParseAddress("example.com", out), "parse example.com fails");
85 CHECK(!btf::ParseAddress("not-base-32-!!!.btf", out), "parse invalid base32 fails");
86 }
87
88 const std::string ENC_HEX = "aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899";
89
90 // helper: fresh keypair -> (seckey, xonly pubkey)
91 auto newKey = [&](unsigned char sk[32], unsigned char pk[32]) {
92 do { RAND_bytes(sk, 32); } while (!secp256k1_ec_seckey_verify(ctx, sk));
93 secp256k1_keypair kp; secp256k1_keypair_create(ctx, &kp, sk);
94 secp256k1_xonly_pubkey xp; secp256k1_keypair_xonly_pub(ctx, &xp, NULL, &kp);
95 secp256k1_xonly_pubkey_serialize(ctx, pk, &xp);
96 };
97
98 printf("descriptor_signs_and_self_certifies\n");
99 {
100 unsigned char sk[32], pk[32]; newKey(sk, pk);
101 std::string d = btf::SignDescriptor(ctx, sk, ENC_HEX, "meeting-node-abc", 1000);
102 CHECK(!d.empty(), "sign produced descriptor");
103 btf::Descriptor got;
104 CHECK(btf::VerifyDescriptor(ctx, d, pk, got), "own key verifies");
105 CHECK(got.meeting_node == "meeting-node-abc" && got.enc == ENC_HEX && got.created == 1000, "fields match");
106 unsigned char sk2[32], pk2[32]; newKey(sk2, pk2);
107 btf::Descriptor bad;
108 CHECK(!btf::VerifyDescriptor(ctx, d, pk2, bad), "different key rejected");
109 }
110
111 printf("descriptor_rejects_tampering\n");
112 {
113 unsigned char sk[32], pk[32]; newKey(sk, pk);
114 std::string d = btf::SignDescriptor(ctx, sk, ENC_HEX, "node-1", 5);
115 json j = json::parse(d); j["meeting_node"] = "evil-node";
116 btf::Descriptor o;
117 CHECK(!btf::VerifyDescriptor(ctx, j.dump(), pk, o), "tampered meeting_node rejected");
118 json j2 = json::parse(d); j2["enc"] = "00000000000000000000000000000000000000000000000000000000deadbeef";
119 CHECK(!btf::VerifyDescriptor(ctx, j2.dump(), pk, o), "tampered enc rejected");
120 }
121
122 printf("full_resolve_chain_from_address\n");
123 {
124 unsigned char sk[32], pk[32]; newKey(sk, pk);
125 std::string addr = btf::Address(pk);
126 unsigned char resolved[32];
127 CHECK(btf::ParseAddress(addr, resolved), "address parses");
128 std::string d = btf::SignDescriptor(ctx, sk, ENC_HEX, "meeting", 1);
129 btf::Descriptor o;
130 CHECK(btf::VerifyDescriptor(ctx, d, resolved, o), "descriptor verifies under resolved key");
131 }
132
133 // Show a sample address so we can eyeball the format
134 {
135 unsigned char sk[32], pk[32]; newKey(sk, pk);
136 printf("\nsample .btf address:\n %s\n", btf::Address(pk).c_str());
137 }
138
139 printf("\n%s (%d failures)\n", g_fail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED", g_fail);
140 secp256k1_context_destroy(ctx);
141 return g_fail == 0 ? 0 : 1;
142}