Fix cashuB byte-string token encoding and add live testnut redeem-regenerate cashuB integration coverage
This commit is contained in:
+43
-2
@@ -53,6 +53,14 @@ static char* cashu_strdup(const char* s) {
|
||||
return out;
|
||||
}
|
||||
|
||||
static int cashu_is_hex_string_len(const char* s, size_t expected_len) {
|
||||
if (!s || strlen(s) != expected_len) return 0;
|
||||
for (size_t i = 0; i < expected_len; i++) {
|
||||
if (!isxdigit((unsigned char)s[i])) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t cashu_write_callback(void* contents, size_t size, size_t nmemb, void* userp) {
|
||||
cashu_http_response_t* response = (cashu_http_response_t*)userp;
|
||||
size_t total_size = size * nmemb;
|
||||
@@ -1418,6 +1426,12 @@ static int cashu_extract_token_json(cJSON* root, cashu_decoded_token_t* out) {
|
||||
return NOSTR_ERROR_CASHU_JSON_PARSE_FAILED;
|
||||
}
|
||||
|
||||
if (!cashu_is_hex_string_len(secret->valuestring, 64) ||
|
||||
!cashu_is_hex_string_len(C->valuestring, 66)) {
|
||||
cashu_free_decoded_token(out);
|
||||
return NOSTR_ERROR_CASHU_JSON_PARSE_FAILED;
|
||||
}
|
||||
|
||||
snprintf(out->proofs[i].id, sizeof(out->proofs[i].id), "%s", id_s);
|
||||
out->proofs[i].amount = (uint64_t)cJSON_GetNumberValue(amount);
|
||||
out->proofs[i].secret = cashu_strdup(secret->valuestring);
|
||||
@@ -1522,6 +1536,20 @@ static int cashu_cbor_write_text(cashu_cbor_buf_t* b, const char* s) {
|
||||
return NOSTR_SUCCESS;
|
||||
}
|
||||
|
||||
static int cashu_cbor_write_bytes(cashu_cbor_buf_t* b, const unsigned char* data, size_t n) {
|
||||
if (!b || (!data && n > 0)) return NOSTR_ERROR_INVALID_INPUT;
|
||||
int rc = cashu_cbor_write_type_uint(b, 2, (uint64_t)n);
|
||||
if (rc != NOSTR_SUCCESS) return rc;
|
||||
|
||||
rc = cashu_cbor_buf_reserve(b, n);
|
||||
if (rc != NOSTR_SUCCESS) return rc;
|
||||
if (n > 0) {
|
||||
memcpy(b->data + b->len, data, n);
|
||||
b->len += n;
|
||||
}
|
||||
return NOSTR_SUCCESS;
|
||||
}
|
||||
|
||||
static int cashu_encode_token_a(const cashu_decoded_token_t* token,
|
||||
char** token_string_out) {
|
||||
cJSON* root = cJSON_CreateObject();
|
||||
@@ -1638,14 +1666,27 @@ static int cashu_encode_token_b(const cashu_decoded_token_t* token,
|
||||
rc = cashu_cbor_write_type_uint(&b, 0, p->amount);
|
||||
if (rc != NOSTR_SUCCESS) goto fail;
|
||||
|
||||
if (!cashu_is_hex_string_len(p->secret, 64) || !cashu_is_hex_string_len(p->C, 66)) {
|
||||
rc = NOSTR_ERROR_INVALID_INPUT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
unsigned char secret_bytes[32] = {0};
|
||||
unsigned char C_bytes[33] = {0};
|
||||
if (nostr_hex_to_bytes(p->secret, secret_bytes, 32) != 0 ||
|
||||
nostr_hex_to_bytes(p->C, C_bytes, 33) != 0) {
|
||||
rc = NOSTR_ERROR_INVALID_INPUT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = cashu_cbor_write_text(&b, "s");
|
||||
if (rc != NOSTR_SUCCESS) goto fail;
|
||||
rc = cashu_cbor_write_text(&b, p->secret);
|
||||
rc = cashu_cbor_write_bytes(&b, secret_bytes, sizeof(secret_bytes));
|
||||
if (rc != NOSTR_SUCCESS) goto fail;
|
||||
|
||||
rc = cashu_cbor_write_text(&b, "c");
|
||||
if (rc != NOSTR_SUCCESS) goto fail;
|
||||
rc = cashu_cbor_write_text(&b, p->C);
|
||||
rc = cashu_cbor_write_bytes(&b, C_bytes, sizeof(C_bytes));
|
||||
if (rc != NOSTR_SUCCESS) goto fail;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
#define NOSTR_CORE_H
|
||||
|
||||
// Version information (auto-updated by increment_and_push.sh)
|
||||
#define VERSION "v0.5.10"
|
||||
#define VERSION "v0.5.11"
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 5
|
||||
#define VERSION_PATCH 10
|
||||
#define VERSION_PATCH 11
|
||||
|
||||
/*
|
||||
* NOSTR Core Library - Complete API Reference
|
||||
|
||||
Binary file not shown.
Binary file not shown.
+191
-43
@@ -41,6 +41,18 @@ static int tests_passed = 0;
|
||||
else { printf("❌ %s\n", msg); } \
|
||||
} while (0)
|
||||
|
||||
static int make_secret_hex(const char* seed, char out_secret_hex[65]) {
|
||||
if (!seed || !out_secret_hex) return NOSTR_ERROR_INVALID_INPUT;
|
||||
|
||||
unsigned char h[32] = {0};
|
||||
if (nostr_sha256((const unsigned char*)seed, strlen(seed), h) != 0) {
|
||||
return NOSTR_ERROR_CRYPTO_FAILED;
|
||||
}
|
||||
|
||||
nostr_bytes_to_hex(h, 32, out_secret_hex);
|
||||
return NOSTR_SUCCESS;
|
||||
}
|
||||
|
||||
static int secret_to_Y_hex(const char* secret, char out_Y_hex[67]) {
|
||||
if (!secret || !out_Y_hex) return NOSTR_ERROR_INVALID_INPUT;
|
||||
|
||||
@@ -344,8 +356,13 @@ static void test_live_mint_and_receive(const char* mint_url) {
|
||||
TEST_ASSERT(q1_check.paid == 1, "mint quote paid (1 sat)");
|
||||
if (rc != NOSTR_SUCCESS || q1_check.paid != 1) goto cleanup;
|
||||
|
||||
char secret1[160];
|
||||
snprintf(secret1, sizeof(secret1), "nostr-step1-mint-%ld", (long)time(NULL));
|
||||
char secret1[65];
|
||||
char secret1_seed[160];
|
||||
snprintf(secret1_seed, sizeof(secret1_seed), "nostr-step1-mint-%ld", (long)time(NULL));
|
||||
rc = make_secret_hex(secret1_seed, secret1);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "derive hex secret for initial mint");
|
||||
if (rc != NOSTR_SUCCESS) goto cleanup;
|
||||
|
||||
char B1[67], C1[67], Y1[67];
|
||||
unsigned char r1[32];
|
||||
rc = cashu_blind_message(secret1, info.pubkey, B1, r1);
|
||||
@@ -450,62 +467,63 @@ static void test_live_mint_and_receive(const char* mint_url) {
|
||||
rc = cashu_decode_token(token_b, &decoded_b);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "decode cashuB token");
|
||||
TEST_ASSERT(decoded_b.proof_count == 1 && decoded_b.proofs[0].amount == 1, "cashuB decoded amount");
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS && decoded_b.proof_count == 1 &&
|
||||
strcmp(decoded_b.proofs[0].secret, minted_proof.secret) == 0 &&
|
||||
strcmp(decoded_b.proofs[0].C, minted_proof.C) == 0,
|
||||
"cashuB decoded proof preserves secret/C");
|
||||
|
||||
cashu_free_decoded_token(&decoded_a);
|
||||
cashu_free_decoded_token(&decoded_b);
|
||||
free(token_a);
|
||||
free(token_b);
|
||||
|
||||
/* Step 1: swap freshly minted 1 sat proof and verify state transition */
|
||||
char secret1_swap[160], B1_swap[67], C1_swap[67], Y1_swap[67];
|
||||
/* Step 1: redeem received cashuB token at mint (swap) and verify state transition */
|
||||
nostr_cashu_proof_t received_proof;
|
||||
memset(&received_proof, 0, sizeof(received_proof));
|
||||
snprintf(received_proof.id, sizeof(received_proof.id), "%s", decoded_b.proofs[0].id);
|
||||
received_proof.amount = decoded_b.proofs[0].amount;
|
||||
received_proof.secret = decoded_b.proofs[0].secret;
|
||||
received_proof.C = decoded_b.proofs[0].C;
|
||||
|
||||
char secret1_swap[65], B1_swap[67], C1_swap[67], Y1_swap[67];
|
||||
unsigned char r1_swap[32];
|
||||
snprintf(secret1_swap, sizeof(secret1_swap), "nostr-step1-swap-%ld", (long)time(NULL));
|
||||
char secret1_swap_seed[160];
|
||||
snprintf(secret1_swap_seed, sizeof(secret1_swap_seed), "nostr-step1-swap-%ld", (long)time(NULL));
|
||||
rc = make_secret_hex(secret1_swap_seed, secret1_swap);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "derive hex secret for step1 swap output");
|
||||
if (rc != NOSTR_SUCCESS) goto cleanup;
|
||||
|
||||
rc = cashu_blind_message(secret1_swap, info.pubkey, B1_swap, r1_swap);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "blind message for step1 swap output");
|
||||
if (rc != NOSTR_SUCCESS) goto cleanup;
|
||||
printf("[DBG] step1 input proof id=%s amount=%llu\n", minted_proof.id, (unsigned long long)minted_proof.amount);
|
||||
printf("[DBG] step1 input secret=%s\n", minted_proof.secret);
|
||||
printf("[DBG] step1 input C=%s\n", minted_proof.C);
|
||||
printf("[DBG] step1 input proof id=%s amount=%llu\n", received_proof.id, (unsigned long long)received_proof.amount);
|
||||
printf("[DBG] step1 input secret=%s\n", received_proof.secret);
|
||||
printf("[DBG] step1 input C=%s\n", received_proof.C);
|
||||
printf("[DBG] step1 output B_=%s\n", B1_swap);
|
||||
debug_print_hex_bytes("r1_swap", r1_swap, 32);
|
||||
|
||||
cashu_blinded_output_t s1_out;
|
||||
memset(&s1_out, 0, sizeof(s1_out));
|
||||
snprintf(s1_out.id, sizeof(s1_out.id), "%s", minted_proof.id);
|
||||
s1_out.amount = 1;
|
||||
snprintf(s1_out.id, sizeof(s1_out.id), "%s", received_proof.id);
|
||||
s1_out.amount = received_proof.amount;
|
||||
snprintf(s1_out.B_, sizeof(s1_out.B_), "%s", B1_swap);
|
||||
|
||||
cashu_swap_request_t s1_req;
|
||||
memset(&s1_req, 0, sizeof(s1_req));
|
||||
s1_req.inputs = &minted_proof;
|
||||
s1_req.inputs = &received_proof;
|
||||
s1_req.input_count = 1;
|
||||
s1_req.outputs = &s1_out;
|
||||
s1_req.output_count = 1;
|
||||
|
||||
cJSON* s1_body = NULL;
|
||||
rc = cashu_build_swap_request(&s1_req, &s1_body);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS && s1_body != NULL, "build swap request (step1)");
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS && s1_body != NULL, "build swap request from received cashuB proof (step1)");
|
||||
if (rc != NOSTR_SUCCESS || !s1_body) goto cleanup;
|
||||
|
||||
char* s1_req_str = cJSON_PrintUnformatted(s1_body);
|
||||
if (s1_req_str) {
|
||||
printf("Step1 swap request: %s\n", s1_req_str);
|
||||
free(s1_req_str);
|
||||
}
|
||||
|
||||
cJSON* s1_resp_json = NULL;
|
||||
rc = cashu_mint_swap(mint_url, s1_body, &s1_resp_json, 15);
|
||||
cJSON_Delete(s1_body);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS && s1_resp_json != NULL, "swap call (step1)");
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS && s1_resp_json != NULL, "swap call from received cashuB proof (step1)");
|
||||
if (rc != NOSTR_SUCCESS || !s1_resp_json) {
|
||||
printf("Step1 swap rc=%d, response_json=%s\n", rc, s1_resp_json ? "yes" : "no");
|
||||
if (s1_resp_json) {
|
||||
char* s1_err = cJSON_PrintUnformatted(s1_resp_json);
|
||||
if (s1_err) {
|
||||
printf("Step1 swap error payload: %s\n", s1_err);
|
||||
free(s1_err);
|
||||
}
|
||||
}
|
||||
cJSON_Delete(s1_resp_json);
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -514,37 +532,148 @@ static void test_live_mint_and_receive(const char* mint_url) {
|
||||
memset(&s1_resp, 0, sizeof(s1_resp));
|
||||
rc = cashu_parse_swap_response(s1_resp_json, &s1_resp);
|
||||
cJSON_Delete(s1_resp_json);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS && s1_resp.signature_count >= 1, "parse swap response (step1)");
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS && s1_resp.signature_count >= 1, "parse swap response from received cashuB proof (step1)");
|
||||
if (rc != NOSTR_SUCCESS || s1_resp.signature_count < 1) {
|
||||
cashu_mint_free_swap_response(&s1_resp);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
printf("[DBG] step1 swap C_: %s\n", s1_resp.signatures[0].C_);
|
||||
rc = cashu_unblind_signature(s1_resp.signatures[0].C_, pk1, r1_swap, C1_swap);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "unblind swap signature (step1)");
|
||||
printf("[DBG] step1 swap C : %s\n", C1_swap);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "unblind swap signature from received cashuB proof (step1)");
|
||||
cashu_mint_free_swap_response(&s1_resp);
|
||||
if (rc != NOSTR_SUCCESS) goto cleanup;
|
||||
|
||||
rc = secret_to_Y_hex(secret1_swap, Y1_swap);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "derive Y for step1 swapped proof");
|
||||
printf("[DBG] step1 Y(old)=%s\n", Y1);
|
||||
printf("[DBG] step1 Y(new)=%s\n", Y1_swap);
|
||||
if (rc != NOSTR_SUCCESS) goto cleanup;
|
||||
|
||||
const char* ys_step1[2] = {Y1, Y1_swap};
|
||||
cashu_checkstate_response_t st1;
|
||||
rc = run_checkstate(mint_url, ys_step1, 2, &st1);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "checkstate after step1 swap");
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "checkstate after redeeming received cashuB proof");
|
||||
if (rc == NOSTR_SUCCESS) {
|
||||
const char* old_state = find_state_for_y(&st1, Y1);
|
||||
const char* new_state = find_state_for_y(&st1, Y1_swap);
|
||||
TEST_ASSERT(old_state != NULL && strcmp(old_state, "SPENT") == 0, "old proof marked SPENT after step1 swap");
|
||||
TEST_ASSERT(new_state != NULL && strcmp(new_state, "UNSPENT") == 0, "new proof marked UNSPENT after step1 swap");
|
||||
TEST_ASSERT(old_state != NULL && strcmp(old_state, "SPENT") == 0, "received proof marked SPENT after redemption");
|
||||
TEST_ASSERT(new_state != NULL && strcmp(new_state, "UNSPENT") == 0, "new proof marked UNSPENT after redemption");
|
||||
cashu_mint_free_checkstate_response(&st1);
|
||||
}
|
||||
|
||||
/* Step 1b: create new cashuB token from redeemed balance and redeem it again */
|
||||
nostr_cashu_proof_t regenerated_proof;
|
||||
memset(®enerated_proof, 0, sizeof(regenerated_proof));
|
||||
snprintf(regenerated_proof.id, sizeof(regenerated_proof.id), "%s", received_proof.id);
|
||||
regenerated_proof.amount = received_proof.amount;
|
||||
regenerated_proof.secret = secret1_swap;
|
||||
regenerated_proof.C = C1_swap;
|
||||
|
||||
cashu_decoded_token_t token_regen;
|
||||
memset(&token_regen, 0, sizeof(token_regen));
|
||||
token_regen.mint_url = (char*)mint_url;
|
||||
token_regen.proofs = ®enerated_proof;
|
||||
token_regen.proof_count = 1;
|
||||
|
||||
char* token_b_regen = NULL;
|
||||
rc = cashu_encode_token(&token_regen, CASHU_TOKEN_FORMAT_B, &token_b_regen);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS && token_b_regen != NULL, "encode regenerated cashuB token");
|
||||
if (rc != NOSTR_SUCCESS || !token_b_regen) goto cleanup;
|
||||
|
||||
cashu_decoded_token_t decoded_b_regen;
|
||||
memset(&decoded_b_regen, 0, sizeof(decoded_b_regen));
|
||||
rc = cashu_decode_token(token_b_regen, &decoded_b_regen);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS && decoded_b_regen.proof_count == 1, "decode regenerated cashuB token");
|
||||
free(token_b_regen);
|
||||
if (rc != NOSTR_SUCCESS || decoded_b_regen.proof_count != 1) {
|
||||
cashu_free_decoded_token(&decoded_b_regen);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
char secret1_swap2[65], B1_swap2[67], C1_swap2[67], Y1_swap2[67];
|
||||
unsigned char r1_swap2[32];
|
||||
char secret1_swap2_seed[160];
|
||||
snprintf(secret1_swap2_seed, sizeof(secret1_swap2_seed), "nostr-step1b-swap-%ld", (long)time(NULL));
|
||||
rc = make_secret_hex(secret1_swap2_seed, secret1_swap2);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "derive hex secret for step1b redemption output");
|
||||
if (rc != NOSTR_SUCCESS) {
|
||||
cashu_free_decoded_token(&decoded_b_regen);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = cashu_blind_message(secret1_swap2, info.pubkey, B1_swap2, r1_swap2);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "blind message for step1b redemption output");
|
||||
if (rc != NOSTR_SUCCESS) {
|
||||
cashu_free_decoded_token(&decoded_b_regen);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cashu_blinded_output_t s1b_out;
|
||||
memset(&s1b_out, 0, sizeof(s1b_out));
|
||||
snprintf(s1b_out.id, sizeof(s1b_out.id), "%s", decoded_b_regen.proofs[0].id);
|
||||
s1b_out.amount = decoded_b_regen.proofs[0].amount;
|
||||
snprintf(s1b_out.B_, sizeof(s1b_out.B_), "%s", B1_swap2);
|
||||
|
||||
cashu_swap_request_t s1b_req;
|
||||
memset(&s1b_req, 0, sizeof(s1b_req));
|
||||
s1b_req.inputs = decoded_b_regen.proofs;
|
||||
s1b_req.input_count = 1;
|
||||
s1b_req.outputs = &s1b_out;
|
||||
s1b_req.output_count = 1;
|
||||
|
||||
cJSON* s1b_body = NULL;
|
||||
rc = cashu_build_swap_request(&s1b_req, &s1b_body);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS && s1b_body != NULL, "build swap request from regenerated cashuB token (step1b)");
|
||||
if (rc != NOSTR_SUCCESS || !s1b_body) {
|
||||
cashu_free_decoded_token(&decoded_b_regen);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cJSON* s1b_resp_json = NULL;
|
||||
rc = cashu_mint_swap(mint_url, s1b_body, &s1b_resp_json, 15);
|
||||
cJSON_Delete(s1b_body);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS && s1b_resp_json != NULL, "swap call from regenerated cashuB token (step1b)");
|
||||
if (rc != NOSTR_SUCCESS || !s1b_resp_json) {
|
||||
cJSON_Delete(s1b_resp_json);
|
||||
cashu_free_decoded_token(&decoded_b_regen);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cashu_swap_response_t s1b_resp;
|
||||
memset(&s1b_resp, 0, sizeof(s1b_resp));
|
||||
rc = cashu_parse_swap_response(s1b_resp_json, &s1b_resp);
|
||||
cJSON_Delete(s1b_resp_json);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS && s1b_resp.signature_count >= 1, "parse swap response from regenerated cashuB token (step1b)");
|
||||
if (rc != NOSTR_SUCCESS || s1b_resp.signature_count < 1) {
|
||||
cashu_mint_free_swap_response(&s1b_resp);
|
||||
cashu_free_decoded_token(&decoded_b_regen);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = cashu_unblind_signature(s1b_resp.signatures[0].C_, pk1, r1_swap2, C1_swap2);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "unblind swap signature from regenerated cashuB token (step1b)");
|
||||
cashu_mint_free_swap_response(&s1b_resp);
|
||||
if (rc != NOSTR_SUCCESS) {
|
||||
cashu_free_decoded_token(&decoded_b_regen);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = secret_to_Y_hex(secret1_swap2, Y1_swap2);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "derive Y for step1b swapped proof");
|
||||
if (rc == NOSTR_SUCCESS) {
|
||||
const char* ys_step1b[1] = {Y1_swap2};
|
||||
cashu_checkstate_response_t st1b;
|
||||
int rc_st1b = run_checkstate(mint_url, ys_step1b, 1, &st1b);
|
||||
TEST_ASSERT(rc_st1b == NOSTR_SUCCESS, "checkstate after regenerated cashuB redemption");
|
||||
if (rc_st1b == NOSTR_SUCCESS) {
|
||||
const char* s1b_state = find_state_for_y(&st1b, Y1_swap2);
|
||||
TEST_ASSERT(s1b_state != NULL && strcmp(s1b_state, "UNSPENT") == 0,
|
||||
"proof from regenerated cashuB redemption is UNSPENT");
|
||||
cashu_mint_free_checkstate_response(&st1b);
|
||||
}
|
||||
}
|
||||
|
||||
cashu_free_decoded_token(&decoded_b_regen);
|
||||
cashu_free_decoded_token(&decoded_b);
|
||||
|
||||
/* Step 2: mint 8 and swap into [2,4,2] */
|
||||
cashu_mint_quote_t q8;
|
||||
memset(&q8, 0, sizeof(q8));
|
||||
@@ -558,9 +687,14 @@ static void test_live_mint_and_receive(const char* mint_url) {
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS && q8_check.paid == 1, "check mint quote paid (8 sat)");
|
||||
if (rc != NOSTR_SUCCESS || q8_check.paid != 1) goto cleanup;
|
||||
|
||||
char secret8[160], B8[67], C8[67], Y8[67];
|
||||
char secret8[65], B8[67], C8[67], Y8[67];
|
||||
unsigned char r8[32];
|
||||
snprintf(secret8, sizeof(secret8), "nostr-step2-mint8-%ld", (long)time(NULL));
|
||||
char secret8_seed[160];
|
||||
snprintf(secret8_seed, sizeof(secret8_seed), "nostr-step2-mint8-%ld", (long)time(NULL));
|
||||
rc = make_secret_hex(secret8_seed, secret8);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "derive hex secret for mint 8");
|
||||
if (rc != NOSTR_SUCCESS) goto cleanup;
|
||||
|
||||
rc = cashu_blind_message(secret8, info.pubkey, B8, r8);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "blind message for mint 8");
|
||||
if (rc != NOSTR_SUCCESS) goto cleanup;
|
||||
@@ -619,14 +753,19 @@ static void test_live_mint_and_receive(const char* mint_url) {
|
||||
if (rc != NOSTR_SUCCESS || change_count < 2) goto cleanup;
|
||||
|
||||
uint64_t out_amts[3] = {2, change_parts[0], change_parts[1]};
|
||||
char out_secrets[3][160];
|
||||
char out_secrets[3][65];
|
||||
char out_B[3][67];
|
||||
unsigned char out_r[3][32];
|
||||
cashu_blinded_output_t split_out[3];
|
||||
memset(split_out, 0, sizeof(split_out));
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
snprintf(out_secrets[i], sizeof(out_secrets[i]), "nostr-step2-swap-%d-%ld", i, (long)time(NULL));
|
||||
char out_seed[160];
|
||||
snprintf(out_seed, sizeof(out_seed), "nostr-step2-swap-%d-%ld", i, (long)time(NULL));
|
||||
rc = make_secret_hex(out_seed, out_secrets[i]);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "derive hex secret for step2 output");
|
||||
if (rc != NOSTR_SUCCESS) goto cleanup;
|
||||
|
||||
rc = cashu_blind_message(out_secrets[i], info.pubkey, out_B[i], out_r[i]);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "blind message for step2 output");
|
||||
if (rc != NOSTR_SUCCESS) goto cleanup;
|
||||
@@ -751,9 +890,18 @@ static void test_live_mint_and_receive(const char* mint_url) {
|
||||
TEST_ASSERT(strcmp(parsed_token.proofs[0].secret, nip60_proof.secret) == 0, "parsed proof secret matches original");
|
||||
TEST_ASSERT(strcmp(parsed_token.proofs[0].C, nip60_proof.C) == 0, "parsed proof C matches original");
|
||||
|
||||
char secret3[160], B3[67], C3[67], Y3[67];
|
||||
char secret3[65], B3[67], C3[67], Y3[67];
|
||||
unsigned char r3[32];
|
||||
snprintf(secret3, sizeof(secret3), "nostr-step3-swap-%ld", (long)time(NULL));
|
||||
char secret3_seed[160];
|
||||
snprintf(secret3_seed, sizeof(secret3_seed), "nostr-step3-swap-%ld", (long)time(NULL));
|
||||
rc = make_secret_hex(secret3_seed, secret3);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "derive hex secret for step3 swap output");
|
||||
if (rc != NOSTR_SUCCESS) {
|
||||
nostr_nip60_free_token_data(&parsed_token);
|
||||
cJSON_Delete(token_evt);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = cashu_blind_message(secret3, info.pubkey, B3, r3);
|
||||
TEST_ASSERT(rc == NOSTR_SUCCESS, "blind message for step3 swap output");
|
||||
if (rc != NOSTR_SUCCESS) {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user