200 lines
7.0 KiB
C
200 lines
7.0 KiB
C
/*
|
|
* NIP-61 Nutzaps Test Suite
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "../nostr_core/nostr_core.h"
|
|
|
|
static int tests_run = 0;
|
|
static int tests_passed = 0;
|
|
|
|
#define TEST_ASSERT(cond, msg) do { \
|
|
tests_run++; \
|
|
if (cond) { tests_passed++; printf("✅ %s\n", msg); } \
|
|
else { printf("❌ %s\n", msg); } \
|
|
} while (0)
|
|
|
|
static int hex_to_bytes32(const char* hex, unsigned char out[32]) {
|
|
return nostr_hex_to_bytes(hex, out, 32) == 0 ? 0 : -1;
|
|
}
|
|
|
|
static void test_nutzap_info_roundtrip(void) {
|
|
printf("\n=== test_nutzap_info_roundtrip ===\n");
|
|
|
|
const char* sk_hex = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
|
unsigned char sk[32];
|
|
TEST_ASSERT(hex_to_bytes32(sk_hex, sk) == 0, "parse private key");
|
|
|
|
char* relays[] = {"wss://relay1.example.com", "wss://relay2.example.com"};
|
|
|
|
char* mint1_units[] = {"usd", "sat"};
|
|
char* mint2_units[] = {"sat"};
|
|
|
|
nostr_nip61_mint_entry_t mints[2];
|
|
memset(mints, 0, sizeof(mints));
|
|
mints[0].url = "https://mint1.example.com";
|
|
mints[0].units = mint1_units;
|
|
mints[0].unit_count = 2;
|
|
mints[1].url = "https://mint2.example.com";
|
|
mints[1].units = mint2_units;
|
|
mints[1].unit_count = 1;
|
|
|
|
nostr_nip61_nutzap_info_t info;
|
|
memset(&info, 0, sizeof(info));
|
|
info.relay_urls = relays;
|
|
info.relay_count = 2;
|
|
info.mints = mints;
|
|
info.mint_count = 2;
|
|
strcpy(info.pubkey, "02eaee8939e3565e48cc62967e2fde9d8e2a4b3ec0081f29eceff5c64ef10ac1ed");
|
|
|
|
cJSON* evt = nostr_nip61_create_nutzap_info_event(&info, sk, 0);
|
|
TEST_ASSERT(evt != NULL, "create nutzap info event");
|
|
|
|
nostr_nip61_nutzap_info_t out;
|
|
memset(&out, 0, sizeof(out));
|
|
int rc = nostr_nip61_parse_nutzap_info_event(evt, &out);
|
|
TEST_ASSERT(rc == NOSTR_SUCCESS, "parse nutzap info event");
|
|
TEST_ASSERT(out.relay_count == 2, "relay count");
|
|
TEST_ASSERT(out.mint_count == 2, "mint count");
|
|
TEST_ASSERT(strcmp(out.pubkey, info.pubkey) == 0, "pubkey value");
|
|
|
|
nostr_nip61_free_nutzap_info(&out);
|
|
cJSON_Delete(evt);
|
|
}
|
|
|
|
static void test_nutzap_event_and_filters(void) {
|
|
printf("\n=== test_nutzap_event_and_filters ===\n");
|
|
|
|
const char* sk_hex = "91ba716fa9e7ea2fcbad360cf4f8e0d312f73984da63d90f524ad61a6a1e7dbe";
|
|
unsigned char sk[32];
|
|
TEST_ASSERT(hex_to_bytes32(sk_hex, sk) == 0, "parse private key");
|
|
|
|
nostr_cashu_proof_t proofs[1];
|
|
memset(proofs, 0, sizeof(proofs));
|
|
strcpy(proofs[0].id, "005c2502034d4f12");
|
|
proofs[0].amount = 1;
|
|
proofs[0].secret = "[\"P2PK\",{\"nonce\":\"n1\",\"data\":\"02eaee8939e3565e48cc62967e2fde9d8e2a4b3ec0081f29eceff5c64ef10ac1ed\"}]";
|
|
proofs[0].C = "02277c66191736eb72fce9d975d08e3191f8f96afb73ab1eec37e4465683066d3f";
|
|
|
|
nostr_nip61_nutzap_data_t in;
|
|
memset(&in, 0, sizeof(in));
|
|
in.content = "Thanks for this great idea.";
|
|
in.proofs = proofs;
|
|
in.proof_count = 1;
|
|
in.mint_url = "https://mint1.example.com";
|
|
strcpy(in.recipient_pubkey, "e9fbced3a42dcf551486650cc752ab354347dd413b307484e4fd1818ab53f991");
|
|
strcpy(in.nutzapped_event_id, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
|
strcpy(in.nutzapped_relay_hint, "wss://relay.example.com");
|
|
in.nutzapped_kind = 1;
|
|
|
|
cJSON* evt = nostr_nip61_create_nutzap_event(&in, sk, 0);
|
|
TEST_ASSERT(evt != NULL, "create nutzap event");
|
|
|
|
nostr_nip61_nutzap_data_t out;
|
|
memset(&out, 0, sizeof(out));
|
|
int rc = nostr_nip61_parse_nutzap_event(evt, &out);
|
|
TEST_ASSERT(rc == NOSTR_SUCCESS, "parse nutzap event");
|
|
TEST_ASSERT(out.proof_count == 1, "proof count");
|
|
TEST_ASSERT(strcmp(out.mint_url, in.mint_url) == 0, "mint url");
|
|
TEST_ASSERT(strcmp(out.recipient_pubkey, in.recipient_pubkey) == 0, "recipient pubkey");
|
|
|
|
cJSON* info_filter = nostr_nip61_create_nutzap_info_filter(in.recipient_pubkey);
|
|
TEST_ASSERT(info_filter != NULL, "create nutzap info filter");
|
|
|
|
const char* mints[] = {"https://mint1.example.com", "https://mint2.example.com"};
|
|
cJSON* nz_filter = nostr_nip61_create_nutzap_filter(in.recipient_pubkey, mints, 2, 1700000000);
|
|
TEST_ASSERT(nz_filter != NULL, "create nutzap filter");
|
|
|
|
cJSON* redeem_evt = nostr_nip61_create_redemption_event(
|
|
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
"wss://sender-relay.example.com",
|
|
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
|
"wss://my-relay.example.com",
|
|
1,
|
|
sk,
|
|
0
|
|
);
|
|
TEST_ASSERT(redeem_evt != NULL, "create redemption event");
|
|
|
|
nostr_nip61_free_nutzap_data(&out);
|
|
cJSON_Delete(redeem_evt);
|
|
cJSON_Delete(nz_filter);
|
|
cJSON_Delete(info_filter);
|
|
cJSON_Delete(evt);
|
|
}
|
|
|
|
static void test_nutzap_verify(void) {
|
|
printf("\n=== test_nutzap_verify ===\n");
|
|
|
|
const char* sk_hex = "96f6fa197aa07477ab88f6981118466ae3a982faab8ad5db9d5426870c73d220";
|
|
unsigned char sk[32];
|
|
TEST_ASSERT(hex_to_bytes32(sk_hex, sk) == 0, "parse private key");
|
|
|
|
char* relays[] = {"wss://relay.example.com"};
|
|
char* mint_units[] = {"sat"};
|
|
|
|
nostr_nip61_mint_entry_t mint;
|
|
memset(&mint, 0, sizeof(mint));
|
|
mint.url = "https://mint-verify.example.com";
|
|
mint.units = mint_units;
|
|
mint.unit_count = 1;
|
|
|
|
nostr_nip61_nutzap_info_t info;
|
|
memset(&info, 0, sizeof(info));
|
|
info.relay_urls = relays;
|
|
info.relay_count = 1;
|
|
info.mints = &mint;
|
|
info.mint_count = 1;
|
|
strcpy(info.pubkey, "02eaee8939e3565e48cc62967e2fde9d8e2a4b3ec0081f29eceff5c64ef10ac1ed");
|
|
|
|
cJSON* info_evt = nostr_nip61_create_nutzap_info_event(&info, sk, 0);
|
|
TEST_ASSERT(info_evt != NULL, "create info event for verify");
|
|
|
|
nostr_cashu_proof_t proof;
|
|
memset(&proof, 0, sizeof(proof));
|
|
strcpy(proof.id, "005c2502034d4f12");
|
|
proof.amount = 1;
|
|
proof.secret = "[\"P2PK\",{\"nonce\":\"n1\",\"data\":\"02eaee8939e3565e48cc62967e2fde9d8e2a4b3ec0081f29eceff5c64ef10ac1ed\"}]";
|
|
proof.C = "02277c66191736eb72fce9d975d08e3191f8f96afb73ab1eec37e4465683066d3f";
|
|
|
|
nostr_nip61_nutzap_data_t nz;
|
|
memset(&nz, 0, sizeof(nz));
|
|
nz.content = "zap";
|
|
nz.proofs = &proof;
|
|
nz.proof_count = 1;
|
|
nz.mint_url = "https://mint-verify.example.com";
|
|
strcpy(nz.recipient_pubkey, "e9fbced3a42dcf551486650cc752ab354347dd413b307484e4fd1818ab53f991");
|
|
|
|
cJSON* nz_evt = nostr_nip61_create_nutzap_event(&nz, sk, 0);
|
|
TEST_ASSERT(nz_evt != NULL, "create nutzap event for verify");
|
|
|
|
int rc = nostr_nip61_verify_nutzap(nz_evt, info_evt);
|
|
TEST_ASSERT(rc == NOSTR_SUCCESS, "verify nutzap against info");
|
|
|
|
cJSON_Delete(nz_evt);
|
|
cJSON_Delete(info_evt);
|
|
}
|
|
|
|
int main(void) {
|
|
printf("NIP-61 Nutzaps Tests\n");
|
|
printf("====================\n");
|
|
|
|
if (nostr_init() != NOSTR_SUCCESS) {
|
|
printf("❌ Failed to initialize NOSTR library\n");
|
|
return 1;
|
|
}
|
|
|
|
test_nutzap_info_roundtrip();
|
|
test_nutzap_event_and_filters();
|
|
test_nutzap_verify();
|
|
|
|
printf("\n=== Test Summary ===\n");
|
|
printf("Passed: %d/%d\n", tests_passed, tests_run);
|
|
|
|
nostr_cleanup();
|
|
return (tests_passed == tests_run) ? 0 : 1;
|
|
}
|