diff --git a/flake.lock b/flake.lock index 3a0e27f..b0b82c2 100644 --- a/flake.lock +++ b/flake.lock @@ -24,17 +24,17 @@ "rust-rapidsnark": "rust-rapidsnark" }, "locked": { - "lastModified": 1781525456, - "narHash": "sha256-SOH9dY1Jg8JmfqMWMZ9YzbGQgWL+ifJ4z+8tHW/4zWs=", + "lastModified": 1781681576, + "narHash": "sha256-o/NvjwdX0Bi5eQVnUv3/J122QJclTIufHSJHBjuT5Zs=", "owner": "logos-blockchain", "repo": "logos-blockchain", - "rev": "4efdf816e2a3d1447096c3f64c9e230769eb4ecb", + "rev": "93b44bd9ff277546df240ca857a20003da953409", "type": "github" }, "original": { "owner": "logos-blockchain", - "ref": "4efdf816e2a3d1447096c3f64c9e230769eb4ecb", "repo": "logos-blockchain", + "rev": "93b44bd9ff277546df240ca857a20003da953409", "type": "github" } }, diff --git a/flake.nix b/flake.nix index aad4675..9a958dc 100644 --- a/flake.nix +++ b/flake.nix @@ -3,8 +3,7 @@ inputs = { logos-module-builder.url = "github:logos-co/logos-module-builder"; - # v0.1.3-rc.10-compatible + rust-rapidsnark nix fixes + cli commands + leader_claim C binding - logos-blockchain.url = "github:logos-blockchain/logos-blockchain?ref=4efdf816e2a3d1447096c3f64c9e230769eb4ecb"; + logos-blockchain.url = "github:logos-blockchain/logos-blockchain?rev=93b44bd9ff277546df240ca857a20003da953409"; # claimable vouchers C binding }; outputs = inputs@{ logos-module-builder, ... }: diff --git a/src/logos_blockchain_module.cpp b/src/logos_blockchain_module.cpp index 1dbe22f..9904023 100644 --- a/src/logos_blockchain_module.cpp +++ b/src/logos_blockchain_module.cpp @@ -626,6 +626,36 @@ std::string LogosBlockchainModule::leader_claim() { return bytes_to_hex(reinterpret_cast(&value), TX_HASH_BYTES); } +std::string LogosBlockchainModule::wallet_get_claimable_vouchers() { + if (!node) { + return "Error: The node is not running."; + } + + auto [value, error] = get_claimable_vouchers(node, nullptr); + if (!is_ok(&error)) { + return "Error: Failed to get claimable vouchers: " + std::to_string(error); + } + + json obj; + obj["tip"] = bytes_to_hex(reinterpret_cast(&value.tip), ADDRESS_BYTES); + obj["vouchers"] = json::array(); + + for (size_t i = 0; i < value.len; ++i) { + const ClaimableVoucher& voucher = value.vouchers[i]; + obj["vouchers"].push_back({ + {"commitment", bytes_to_hex(reinterpret_cast(&voucher.commitment), ADDRESS_BYTES)}, + {"nullifier", bytes_to_hex(reinterpret_cast(&voucher.nullifier), ADDRESS_BYTES)}, + }); + } + + const OperationStatus free_status = free_claimable_vouchers(value); + if (!is_ok(&free_status)) { + fprintf(stderr, "Failed to free claimable vouchers. Error: %d\n", free_status); + } + + return obj.dump(); +} + // Blend std::string LogosBlockchainModule::blend_join_as_core_node( @@ -772,4 +802,3 @@ std::string LogosBlockchainModule::get_cryptarchia_info() { } return obj.dump(); } - diff --git a/src/logos_blockchain_module.h b/src/logos_blockchain_module.h index 9ebde0d..df672e4 100644 --- a/src/logos_blockchain_module.h +++ b/src/logos_blockchain_module.h @@ -76,6 +76,7 @@ public: ); std::vector wallet_get_known_addresses(); std::string leader_claim(); + std::string wallet_get_claimable_vouchers(); // Blend std::string blend_join_as_core_node( diff --git a/tests/mocks/mock_logos_blockchain.cpp b/tests/mocks/mock_logos_blockchain.cpp index 19e13f5..2fb5115 100644 --- a/tests/mocks/mock_logos_blockchain.cpp +++ b/tests/mocks/mock_logos_blockchain.cpp @@ -16,6 +16,7 @@ static uint8_t s_mockAddr1[32]; static uint8_t s_mockAddr2[32]; static uint8_t s_mockAddr3[32]; static uint8_t* s_mockAddrs[] = { s_mockAddr0, s_mockAddr1, s_mockAddr2, s_mockAddr3 }; +static ClaimableVoucher s_mockClaimableVouchers[4]; extern "C" { @@ -169,6 +170,34 @@ OperationStatus free_known_addresses(KnownAddresses addrs) { return 0; } +FfiClaimableVouchersResult get_claimable_vouchers(LogosBlockchainNode* node, const HeaderId* optional_tip) { + LOGOS_CMOCK_RECORD("get_claimable_vouchers"); + FfiClaimableVouchersResult result; + int err = LOGOS_CMOCK_RETURN(int, "get_claimable_vouchers_error"); + result.error = err; + if (err == 0) { + int count = LOGOS_CMOCK_RETURN(int, "get_claimable_vouchers_count"); + if (count > 4) count = 4; + memset(result.value.tip, 0xAA, sizeof(HeaderId)); + for (int i = 0; i < count; ++i) { + memset(s_mockClaimableVouchers[i].commitment, 0x10 + i, sizeof(Hash)); + memset(s_mockClaimableVouchers[i].nullifier, 0x20 + i, sizeof(Hash)); + } + result.value.vouchers = s_mockClaimableVouchers; + result.value.len = static_cast(count); + } else { + memset(result.value.tip, 0, sizeof(HeaderId)); + result.value.vouchers = nullptr; + result.value.len = 0; + } + return result; +} + +OperationStatus free_claimable_vouchers(ClaimableVouchers vouchers) { + LOGOS_CMOCK_RECORD("free_claimable_vouchers"); + return 0; +} + BlendHashResult blend_join_as_core_node( LogosBlockchainNode* node, const uint8_t* provider_id, diff --git a/tests/stubs/logos_blockchain.h b/tests/stubs/logos_blockchain.h index 7455a95..2b5ce96 100644 --- a/tests/stubs/logos_blockchain.h +++ b/tests/stubs/logos_blockchain.h @@ -70,6 +70,17 @@ typedef struct { size_t len; } KnownAddresses; +typedef struct { + Hash commitment; + Hash nullifier; +} ClaimableVoucher; + +typedef struct { + HeaderId tip; + ClaimableVoucher* vouchers; + size_t len; +} ClaimableVouchers; + // Cryptarchia consensus info typedef struct { uint8_t lib[32]; @@ -85,6 +96,7 @@ typedef struct { uint64_t value; OperationStatus error; } BalanceResult; typedef struct { Hash value; OperationStatus error; } TransferHashResult; typedef struct { TxHash value; OperationStatus error; } FfiLeaderClaimResult; typedef struct { KnownAddresses value; OperationStatus error; } KnownAddressesResult; +typedef struct { ClaimableVouchers value; OperationStatus error; } FfiClaimableVouchersResult; typedef struct { Hash value; OperationStatus error; } BlendHashResult; typedef struct { char* value; OperationStatus error; } StringResult; typedef struct { CryptarchiaInfo* value; OperationStatus error; } CryptarchiaInfoResult; @@ -140,6 +152,8 @@ TransferHashResult transfer_funds(LogosBlockchainNode* node, const TransferFunds FfiLeaderClaimResult leader_claim(LogosBlockchainNode* node); KnownAddressesResult get_known_addresses(LogosBlockchainNode* node); OperationStatus free_known_addresses(KnownAddresses addrs); +FfiClaimableVouchersResult get_claimable_vouchers(LogosBlockchainNode* node, const HeaderId* optional_tip); +OperationStatus free_claimable_vouchers(ClaimableVouchers vouchers); // Blend BlendHashResult blend_join_as_core_node( diff --git a/tests/test_blockchain.cpp b/tests/test_blockchain.cpp index a9ad982..7046cf3 100644 --- a/tests/test_blockchain.cpp +++ b/tests/test_blockchain.cpp @@ -594,6 +594,40 @@ LOGOS_TEST(wallet_get_known_addresses_returns_empty_on_ffi_failure) { delete module; } +LOGOS_TEST(wallet_get_claimable_vouchers_returns_json) { + auto t = LogosTestContext("blockchain_module"); + TempDir tmpDir; + auto* module = createStartedModule(t, tmpDir); + LOGOS_ASSERT_TRUE(module != nullptr); + + t.mockCFunction("get_claimable_vouchers_error").returns(0); + t.mockCFunction("get_claimable_vouchers_count").returns(2); + + std::string result = module->wallet_get_claimable_vouchers(); + LOGOS_ASSERT_FALSE(starts_with(result, "Error:")); + LOGOS_ASSERT_TRUE(contains(result, "\"vouchers\"")); + LOGOS_ASSERT_TRUE(contains(result, std::string(64, 'a'))); + LOGOS_ASSERT_TRUE(contains(result, std::string(64, '1'))); + LOGOS_ASSERT_TRUE(contains(result, "20202020")); + LOGOS_ASSERT(t.cFunctionCalled("get_claimable_vouchers")); + LOGOS_ASSERT(t.cFunctionCalled("free_claimable_vouchers")); + delete module; +} + +LOGOS_TEST(wallet_get_claimable_vouchers_returns_error_on_ffi_failure) { + auto t = LogosTestContext("blockchain_module"); + TempDir tmpDir; + auto* module = createStartedModule(t, tmpDir); + LOGOS_ASSERT_TRUE(module != nullptr); + + t.mockCFunction("get_claimable_vouchers_error").returns(1); + + std::string result = module->wallet_get_claimable_vouchers(); + LOGOS_ASSERT_TRUE(starts_with(result, "Error:")); + LOGOS_ASSERT_TRUE(contains(result, "Failed to get claimable vouchers")); + delete module; +} + // Blend LOGOS_TEST(blend_join_as_core_node_returns_declaration_id) {