-
Notifications
You must be signed in to change notification settings - Fork 10
feat: add functions for checkpoint retrieval in FFI API #129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (4)
dash-spv-ffi/include/dash_spv_ffi.h (1)
544-555: Encode 32-byte hash size in the type to prevent misuse.Consider changing
out_hashto a 32-byte array pointer in the Rust signatures (*mut [u8; 32]) so cbindgen generatesuint8_t (*out_hash)[32]here. This prevents under-sized buffers at call sites.Apply in Rust (affects all three functions):
-pub extern "C" fn dash_spv_ffi_checkpoint_latest( +pub extern "C" fn dash_spv_ffi_checkpoint_latest( network: FFINetwork, out_height: *mut u32, - out_hash: *mut u8, // expects at least 32 bytes + out_hash: *mut [u8; 32], ) -> i32 { /* ... */ } - out_hash: *mut u8, // expects at least 32 bytes + out_hash: *mut [u8; 32], - out_hash: *mut u8, // expects at least 32 bytes + out_hash: *mut [u8; 32],And in the bodies:
- let hash = cp.block_hash.to_byte_array(); - std::ptr::copy_nonoverlapping(hash.as_ptr(), out_hash, 32); + let hash = cp.block_hash.to_byte_array(); + (*out_hash).copy_from_slice(&hash);dash-spv-ffi/FFI_API.md (1)
833-891: Document FFICheckpoint in “Type Definitions” and note error codes.Add
FFICheckpointto the Types section and list possible error codes for each checkpoint API (Success, NullPointer, InvalidArgument, ValidationError/NotImplemented).I can wire Rust doc comments so the generator includes the type and error semantics—want a patch?
dash-spv-ffi/src/checkpoints.rs (2)
29-56: Make hash output size-safe and deduplicate write-out logic.Use a typed 32-byte pointer and a small helper to avoid repetition.
- out_hash: *mut u8, // expects at least 32 bytes + out_hash: *mut [u8; 32], @@ - unsafe { - *out_height = cp.height; - let hash = cp.block_hash.to_byte_array(); - std::ptr::copy_nonoverlapping(hash.as_ptr(), out_hash, 32); - } + unsafe { + *out_height = cp.height; + let hash = cp.block_hash.to_byte_array(); + (*out_hash).copy_from_slice(&hash); + }Optionally extract:
#[inline] fn write_out(out_height: *mut u32, out_hash: *mut [u8; 32], h: u32, hash: [u8;32]) { unsafe { *out_height = h; (*out_hash).copy_from_slice(&hash); } }Also applies to: 64-92, 100-128
135-168: Avoid unnecessary scanning; handle inverted ranges.
- Early-return empty when start > end.
- If heights are sorted asc, break once h > end to avoid full scan.
pub extern "C" fn dash_spv_ffi_checkpoints_between_heights( @@ ) -> FFIArray { - match manager_for_network(network) { + if start_height > end_height { + return FFIArray::new(Vec::<FFICheckpoint>::new()); + } + match manager_for_network(network) { Ok(mgr) => { // Collect checkpoints within inclusive range let mut out: Vec<FFICheckpoint> = Vec::new(); for &h in mgr.checkpoint_heights() { if h >= start_height && h <= end_height { if let Some(cp) = mgr.get_checkpoint(h) { out.push(FFICheckpoint { height: cp.height, block_hash: cp.block_hash.to_byte_array(), }); } + } else if h > end_height { + break; } } FFIArray::new(out)Confirm
checkpoint_heights()returns ascending order; if not guaranteed, skip thebreak.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
dash-spv-ffi/FFI_API.md(3 hunks)dash-spv-ffi/include/dash_spv_ffi.h(2 hunks)dash-spv-ffi/src/checkpoints.rs(1 hunks)dash-spv-ffi/src/lib.rs(2 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
dash-spv-ffi/src/**/*.rs
📄 CodeRabbit inference engine (dash-spv-ffi/CLAUDE.md)
dash-spv-ffi/src/**/*.rs: FFI functions must be declared with #[no_mangle] extern "C"
Expose complex Rust types to C as opaque pointers (e.g., FFIDashSpvClient*)
Provide corresponding _destroy() functions for all FFI-owned types to enforce explicit memory management
Return Rust strings to C as *const c_char; allocate so the caller can free with dash_string_free
Accept input strings from C as *const c_char (borrowed; do not free inputs)
Functions returning pointers transfer ownership to the caller; functions taking pointers only borrow
Add cbindgen annotations for complex types so headers are generated correctly
Files:
dash-spv-ffi/src/lib.rsdash-spv-ffi/src/checkpoints.rs
**/*.rs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.rs: Use proper error types with thiserror and propagate errors appropriately
Use the tokio runtime for async operations in Rust
Use conditional compilation feature flags for optional features (#[cfg(feature = ...)])
Format Rust code with cargo fmt (and enforce via cargo fmt --check)
Run clippy with -D warnings and fix all lints
Adhere to MSRV Rust 1.89 (avoid features requiring newer compiler)
**/*.rs: Format Rust code with rustfmt (per rustfmt.toml); run cargo fmt --all before commits
Lint with clippy; treat warnings as errors in CI
Follow Rust naming: snake_case for functions/variables, UpperCamelCase for types/traits, SCREAMING_SNAKE_CASE for consts
Prefer async using tokio where applicable
Files:
dash-spv-ffi/src/lib.rsdash-spv-ffi/src/checkpoints.rs
{dash-network-ffi,dash-spv-ffi,key-wallet-ffi,swift-dash-core-sdk}/**/*.{rs,c,h,swift}
📄 CodeRabbit inference engine (CLAUDE.md)
Be careful with memory management at FFI boundaries (C/Swift interop)
Files:
dash-spv-ffi/src/lib.rsdash-spv-ffi/src/checkpoints.rsdash-spv-ffi/include/dash_spv_ffi.h
**/src/**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
**/src/**/*.rs: Each crate keeps sources in src/
Avoid unwrap()/expect() in library code; use proper error types (e.g., thiserror)
Place unit tests alongside code with #[cfg(test)]
Files:
dash-spv-ffi/src/lib.rsdash-spv-ffi/src/checkpoints.rs
*-ffi/**
📄 CodeRabbit inference engine (AGENTS.md)
FFI bindings live in *-ffi crates
Files:
dash-spv-ffi/src/lib.rsdash-spv-ffi/src/checkpoints.rsdash-spv-ffi/FFI_API.mddash-spv-ffi/include/dash_spv_ffi.h
dash-spv-ffi/include/dash_spv_ffi.h
📄 CodeRabbit inference engine (dash-spv-ffi/CLAUDE.md)
The public C header is generated; ensure it reflects FFI changes after builds
Files:
dash-spv-ffi/include/dash_spv_ffi.h
🧠 Learnings (17)
📚 Learning: 2025-08-16T04:14:07.718Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: dash-spv-ffi/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:14:07.718Z
Learning: Applies to dash-spv-ffi/src/**/*.rs : Expose complex Rust types to C as opaque pointers (e.g., FFIDashSpvClient*)
Applied to files:
dash-spv-ffi/src/lib.rsdash-spv-ffi/src/checkpoints.rs
📚 Learning: 2025-08-16T04:14:07.718Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: dash-spv-ffi/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:14:07.718Z
Learning: Applies to dash-spv-ffi/include/dash_spv_ffi.h : The public C header is generated; ensure it reflects FFI changes after builds
Applied to files:
dash-spv-ffi/src/lib.rsdash-spv-ffi/src/checkpoints.rsdash-spv-ffi/FFI_API.mddash-spv-ffi/include/dash_spv_ffi.h
📚 Learning: 2025-08-25T17:15:59.361Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-08-25T17:15:59.361Z
Learning: Applies to dash-spv/**/*.rs : All code must be clippy-clean: run `cargo clippy --all-targets --all-features -- -D warnings`
Applied to files:
dash-spv-ffi/src/lib.rs
📚 Learning: 2025-08-16T04:14:07.718Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: dash-spv-ffi/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:14:07.718Z
Learning: Applies to dash-spv-ffi/src/**/*.rs : FFI functions must be declared with #[no_mangle] extern "C"
Applied to files:
dash-spv-ffi/src/lib.rsdash-spv-ffi/src/checkpoints.rs
📚 Learning: 2025-08-16T04:14:07.718Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: dash-spv-ffi/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:14:07.718Z
Learning: Applies to dash-spv-ffi/tests/unit/**/*.rs : Add a corresponding Rust unit test for each new FFI function
Applied to files:
dash-spv-ffi/src/lib.rsdash-spv-ffi/src/checkpoints.rsdash-spv-ffi/FFI_API.md
📚 Learning: 2025-08-16T04:14:07.718Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: dash-spv-ffi/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:14:07.718Z
Learning: Applies to dash-spv-ffi/src/**/*.rs : Provide corresponding _destroy() functions for all FFI-owned types to enforce explicit memory management
Applied to files:
dash-spv-ffi/src/lib.rsdash-spv-ffi/src/checkpoints.rs
📚 Learning: 2025-08-16T04:14:07.718Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: dash-spv-ffi/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:14:07.718Z
Learning: Applies to dash-spv-ffi/src/**/*.rs : Add cbindgen annotations for complex types so headers are generated correctly
Applied to files:
dash-spv-ffi/src/lib.rsdash-spv-ffi/src/checkpoints.rs
📚 Learning: 2025-08-16T04:14:07.718Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: dash-spv-ffi/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:14:07.718Z
Learning: Applies to dash-spv-ffi/src/**/*.rs : Functions returning pointers transfer ownership to the caller; functions taking pointers only borrow
Applied to files:
dash-spv-ffi/src/lib.rsdash-spv-ffi/src/checkpoints.rs
📚 Learning: 2025-08-29T04:00:14.154Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-29T04:00:14.154Z
Learning: Applies to {dash-network-ffi,dash-spv-ffi,key-wallet-ffi,swift-dash-core-sdk}/**/*.{rs,c,h,swift} : Be careful with memory management at FFI boundaries (C/Swift interop)
Applied to files:
dash-spv-ffi/src/checkpoints.rsdash-spv-ffi/FFI_API.mddash-spv-ffi/include/dash_spv_ffi.h
📚 Learning: 2025-08-16T04:14:07.718Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: dash-spv-ffi/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:14:07.718Z
Learning: Applies to dash-spv-ffi/tests/c_tests/**/*.c : Add a corresponding C test for each new FFI function
Applied to files:
dash-spv-ffi/src/checkpoints.rs
📚 Learning: 2025-08-16T04:14:07.718Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: dash-spv-ffi/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:14:07.718Z
Learning: Applies to dash-spv-ffi/src/callbacks.rs : Use C function pointers for async progress/completion callbacks; callbacks may be invoked from any thread
Applied to files:
dash-spv-ffi/src/checkpoints.rs
📚 Learning: 2025-08-16T04:15:29.335Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: swift-dash-core-sdk/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:15:29.335Z
Learning: Applies to swift-dash-core-sdk/Sources/DashSPVFFI/include/dash_spv_ffi.h : After updating dash-spv-ffi, synchronize the generated header into the Swift SDK using ./sync-headers.sh so Sources/DashSPVFFI/include/dash_spv_ffi.h stays up to date
Applied to files:
dash-spv-ffi/FFI_API.mddash-spv-ffi/include/dash_spv_ffi.h
📚 Learning: 2025-08-16T04:15:57.225Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: swift-dash-core-sdk/Examples/DashHDWalletExample/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:15:57.225Z
Learning: Applies to swift-dash-core-sdk/Examples/DashHDWalletExample/**/*.swift : When accessing SPV functionality, use DashSDK public APIs instead of direct client access; add public wrapper methods to DashSDK if needed
Applied to files:
dash-spv-ffi/include/dash_spv_ffi.h
📚 Learning: 2025-08-16T04:15:29.335Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: swift-dash-core-sdk/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:15:29.335Z
Learning: Applies to swift-dash-core-sdk/Sources/**/FFIBridge.swift : Manage FFI pointers manually using RAII-style wrappers and defer blocks to ensure cleanup
Applied to files:
dash-spv-ffi/include/dash_spv_ffi.h
📚 Learning: 2025-08-16T04:15:29.335Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: swift-dash-core-sdk/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:15:29.335Z
Learning: Applies to swift-dash-core-sdk/Sources/**/FFIBridge.swift : At the FFI boundary, convert FFI errors to DashSDKError and use Result types; log FFI errors before converting
Applied to files:
dash-spv-ffi/include/dash_spv_ffi.h
📚 Learning: 2025-08-16T04:15:29.335Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: swift-dash-core-sdk/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:15:29.335Z
Learning: Applies to swift-dash-core-sdk/Sources/**/FFIBridge.swift : Add a Swift wrapper in FFIBridge.swift for each new FFI function, handling type conversions and cross-language error mapping
Applied to files:
dash-spv-ffi/include/dash_spv_ffi.h
📚 Learning: 2025-08-16T04:15:29.335Z
Learnt from: CR
PR: dashpay/rust-dashcore#0
File: swift-dash-core-sdk/CLAUDE.md:0-0
Timestamp: 2025-08-16T04:15:29.335Z
Learning: Applies to swift-dash-core-sdk/Sources/**/AsyncBridge.swift : Provide async wrappers in AsyncBridge.swift (e.g., AsyncSequence/Combine publishers) for callback-based FFI APIs
Applied to files:
dash-spv-ffi/include/dash_spv_ffi.h
🧬 Code graph analysis (2)
dash-spv-ffi/src/checkpoints.rs (2)
dash-spv-ffi/src/error.rs (1)
set_last_error(26-31)dash-spv/src/chain/checkpoints.rs (2)
mainnet_checkpoints(271-358)testnet_checkpoints(361-412)
dash-spv-ffi/include/dash_spv_ffi.h (1)
dash-spv-ffi/src/checkpoints.rs (4)
dash_spv_ffi_checkpoint_latest(29-56)dash_spv_ffi_checkpoint_before_height(64-92)dash_spv_ffi_checkpoint_before_timestamp(100-128)dash_spv_ffi_checkpoints_between_heights(135-168)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
- GitHub Check: RPC Tests (stable, true)
- GitHub Check: Core Components Tests
- GitHub Check: fuzz (hashes_sha512)
- GitHub Check: Clippy (Non-strict)
- GitHub Check: fuzz (hashes_json)
- GitHub Check: fuzz (hashes_sha512_256)
- GitHub Check: fuzz (hashes_cbor)
- GitHub Check: fuzz (hashes_sha1)
- GitHub Check: fuzz (hashes_sha256)
- GitHub Check: SPV Components Tests
- GitHub Check: fuzz (dash_deserialize_witness)
- GitHub Check: fuzz (dash_deserialize_script)
- GitHub Check: fuzz (hashes_ripemd160)
- GitHub Check: fuzz (dash_deserialize_block)
- GitHub Check: fuzz (dash_script_bytes_to_asm_fmt)
- GitHub Check: Strict Warnings and Clippy Checks
- GitHub Check: fuzz (dash_deserialize_amount)
- GitHub Check: fuzz (dash_deserialize_address)
- GitHub Check: fuzz (dash_deser_net_msg)
- GitHub Check: fuzz (dash_outpoint_string)
🔇 Additional comments (5)
dash-spv-ffi/src/lib.rs (2)
4-4: Re-export module publicly: LGTM.Module wiring is correct and matches FFI guidelines.
13-13: Public surface re-export: LGTM.Makes the checkpoint FFI available at the crate root; no concerns.
dash-spv-ffi/include/dash_spv_ffi.h (1)
151-165: Vendored header synced.dash_spv_ffi.hinswift-dash-core-sdk/Sources/DashSPVFFI/includehas been updated viasync-headers.sh; no further action required.dash-spv-ffi/src/checkpoints.rs (2)
14-21: Network mapping: LGTM.Clear error for unsupported networks; fine for FFI.
23-28: Docs and FFI hygiene: LGTM.
#[no_mangle] extern "C"present.- Null-pointer checks and error propagation consistent.
Also applies to: 58-63, 94-99, 130-134
| **Auto-generated**: This documentation is automatically generated from the source code. Do not edit manually. | ||
|
|
||
| **Total Functions**: 57 | ||
| **Total Functions**: 61 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Function count updated: please verify it’s auto-generated, not hand-edited.
Ensure the generator reflects 61 functions and that the header and doc stay in lockstep.
🏁 Script executed:
#!/bin/bash
# Count public FFI functions in header vs documented count
DOC_CNT=$(rg -n '^\\*\\*Total Functions\\*\\*:\\s*(\\d+)$' -or '$1' dash-spv-ffi/FFI_API.md)
HDR_CNT=$(rg -nP '^\s*(?:int32_t|bool|void|struct\s+FFIArray|FFIClientConfig\s*\*|FFINetwork\b|const\s+char\s*\*)\s+dash_spv_ffi_' dash-spv-ffi/include/dash_spv_ffi.h | wc -l | tr -d ' ')
echo "Doc: $DOC_CNT, Header: $HDR_CNT"
test "$DOC_CNT" = "$HDR_CNT" || { echo "Mismatch"; exit 1; }Length of output: 384
🏁 Script executed:
#!/bin/bash
# Correctly extract documented total functions
DOC_CNT=$(rg -P -o '^\*\*Total Functions\*\*:\s*(\d+)$' -r '$1' dash-spv-ffi/FFI_API.md)
# Count public FFI functions in header
HDR_CNT=$(rg -P '^\s*(?:int32_t|bool|void|struct\s+FFIArray|FFIClientConfig\s*\*|FFINetwork\b|const\s+char\s*\*)\s+dash_spv_ffi_' -c dash-spv-ffi/include/dash_spv_ffi.h)
echo "Doc: $DOC_CNT, Header: $HDR_CNT"
if [ "$DOC_CNT" = "$HDR_CNT" ]; then
echo "Match"
else
echo "Mismatch"
fiLength of output: 360
Sync FFI_API.md function count with header: Documented total (61) doesn’t match actual public FFI functions in dash-spv-ffi/include/dash_spv_ffi.h (46). Re-run the API doc generator (not manual edit) and commit the updated FFI_API.md so counts stay in lockstep.
🤖 Prompt for AI Agents
In dash-spv-ffi/FFI_API.md around line 7, the documented total functions (61) is
out of sync with the actual public FFI functions in
dash-spv-ffi/include/dash_spv_ffi.h (46); re-run the API documentation generator
(do not manually edit the count) pointing it at
dash-spv-ffi/include/dash_spv_ffi.h so the generator recomputes the total and
updates FFI_API.md, verify the generated total matches the header’s exported
functions, and commit the regenerated FFI_API.md to the branch.
| struct FFIArray dash_spv_ffi_checkpoints_between_heights(FFINetwork network, | ||
| uint32_t start_height, | ||
| uint32_t end_height); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Header lacks FFICheckpoint definition used by the returned FFIArray.
C consumers cannot interpret elements without a typedef struct FFICheckpoint. Ensure cbindgen exports it.
Apply in Rust (so cbindgen emits the type):
-/// FFI representation of a checkpoint (height + block hash)
+/// FFI representation of a checkpoint (height + block hash)
+/// cbindgen:export
#[repr(C)]
pub struct FFICheckpoint {
pub height: u32,
pub block_hash: [u8; 32],
}Run to confirm the struct appears in the generated header:
🏁 Script executed:
#!/bin/bash
rg -nP 'typedef\s+struct\s+FFICheckpoint' dash-spv-ffi/include/dash_spv_ffi.h -C2Length of output: 83
🏁 Script executed:
#!/bin/bash
# Check for FFICheckpoint in the generated C header
echo "Header occurrences:"
rg -n 'FFICheckpoint' dash-spv-ffi/include/dash_spv_ffi.h -C2
# Check Rust source for the FFICheckpoint definition and cbindgen annotations
echo "Rust source occurrences:"
rg -nP 'struct\s+FFICheckpoint' -C2 dash-spv-ffi/src/**/*.rsLength of output: 299
🏁 Script executed:
#!/bin/bash
# Search entire repository for any mentions of FFICheckpoint
echo "Occurrences of 'FFICheckpoint' in repo:"
rg -n 'FFICheckpoint' -C2 .
# Search for cbindgen annotations in Rust source
echo "Occurrences of 'cbindgen' annotations in Rust files:"
rg -n 'cbindgen' -C2 --type=rsLength of output: 2722
Add cbindgen export for FFICheckpoint in Rust
Header lacks FFICheckpoint typedef; annotate struct so cbindgen generates it:
/// FFI representation of a checkpoint (height + block hash)
+/// cbindgen:export
#[repr(C)]
pub struct FFICheckpoint {
pub height: u32,
pub block_hash: [u8; 32],
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In dash-spv-ffi/include/dash_spv_ffi.h around lines 556 to 559: the header lacks
a typedef for FFICheckpoint because the corresponding Rust struct wasn't
exported for cbindgen; update the Rust definition to be a public, C-compatible
struct (add pub, #[repr(C)], and derive Copy/Clone) and ensure it is visible to
cbindgen (keep it in a module cbindgen scans or add a cfg_attr if you use
conditional export) so cbindgen will generate the FFICheckpoint typedef in the C
header.
| use crate::{set_last_error, FFIArray, FFIErrorCode}; | ||
| use dash_spv::chain::checkpoints::{mainnet_checkpoints, testnet_checkpoints, CheckpointManager}; | ||
| use dashcore::Network; | ||
| use dashcore::hashes::Hash; | ||
| use key_wallet_ffi::FFINetwork; | ||
|
|
||
| /// FFI representation of a checkpoint (height + block hash) | ||
| #[repr(C)] | ||
| pub struct FFICheckpoint { | ||
| pub height: u32, | ||
| pub block_hash: [u8; 32], | ||
| } | ||
|
|
||
| fn manager_for_network(network: FFINetwork) -> Result<CheckpointManager, String> { | ||
| let net: Network = network.into(); | ||
| match net { | ||
| Network::Dash => Ok(CheckpointManager::new(mainnet_checkpoints())), | ||
| Network::Testnet => Ok(CheckpointManager::new(testnet_checkpoints())), | ||
| _ => Err("Checkpoints are only available for Dash and Testnet".to_string()), | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Add unit and C tests for new FFI endpoints.
Per repo guidelines, add Rust unit tests and C tests covering success/edge cases for all four functions.
I can scaffold tests (Rust + C) for mainnet/testnet networks and error paths—want me to open a follow-up patch?
🏁 Script executed:
#!/bin/bash
# Quick audit for tests referencing new symbols
rg -nP 'checkpoint_(latest|before_height|before_timestamp)|checkpoints_between_heights' dash-spv-ffi/testsLength of output: 108
🏁 Script executed:
#!/bin/bash
set -eux
# List all test files in dash-spv-ffi/tests
echo "=== Test files ==="
find dash-spv-ffi/tests -type f
# Search for any occurrences of 'checkpoint' in those test files
echo "=== Occurrences of 'checkpoint' in tests ==="
rg -n 'checkpoint' dash-spv-ffi/testsLength of output: 1490
Add tests for new checkpoint FFI endpoints. Add Rust unit tests in dash-spv-ffi/tests/unit covering all four functions (checkpoint_latest, checkpoint_before_height, checkpoint_before_timestamp, checkpoints_between_heights) with success and edge cases, and add corresponding C tests in dash-spv-ffi/tests/c_tests.
🤖 Prompt for AI Agents
In dash-spv-ffi/src/checkpoints.rs around lines 1 to 21, add comprehensive tests
for the new checkpoint FFI: create Rust unit tests in dash-spv-ffi/tests/unit
that exercise checkpoint_latest, checkpoint_before_height,
checkpoint_before_timestamp, and checkpoints_between_heights for both Dash and
Testnet covering normal success cases and edge cases (no checkpoint found,
boundary heights/timestamps, empty range), validate returned FFICheckpoint data,
and assert correct error handling/FFI error codes and set_last_error behavior;
also add corresponding C integration tests in dash-spv-ffi/tests/c_tests that
call the FFI functions from C, mirror the same success and edge cases, validate
returned structures and error codes/messages, and ensure tests run under cargo
test (and the project’s C test harness) so the new endpoints are fully exercised
across both Rust unit and C integration layers.
| /// FFI representation of a checkpoint (height + block hash) | ||
| #[repr(C)] | ||
| pub struct FFICheckpoint { | ||
| pub height: u32, | ||
| pub block_hash: [u8; 32], | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Export FFICheckpoint to C headers via cbindgen.
Without explicit export, cbindgen may omit this struct; C consumers won’t know the element layout of FFIArray.
Apply:
-/// FFI representation of a checkpoint (height + block hash)
+/// FFI representation of a checkpoint (height + block hash)
+/// cbindgen:export
#[repr(C)]
pub struct FFICheckpoint {
pub height: u32,
pub block_hash: [u8; 32],
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /// FFI representation of a checkpoint (height + block hash) | |
| #[repr(C)] | |
| pub struct FFICheckpoint { | |
| pub height: u32, | |
| pub block_hash: [u8; 32], | |
| } | |
| /// FFI representation of a checkpoint (height + block hash) | |
| /// cbindgen:export | |
| #[repr(C)] | |
| pub struct FFICheckpoint { | |
| pub height: u32, | |
| pub block_hash: [u8; 32], | |
| } |
🤖 Prompt for AI Agents
In dash-spv-ffi/src/checkpoints.rs around lines 7–12, the FFICheckpoint struct
is public and repr(C) but cbindgen may still omit it unless it is explicitly
exported in the crate public API; update the file to make the type
cbindgen-visible by deriving Copy and Clone for safe FFI value semantics, add a
conditional export attribute for header generation (e.g. #[cfg_attr(feature =
"cbindgen", export_name = "FFICheckpoint")]) and ensure the type is re-exported
from the crate root (pub use crate::checkpoints::FFICheckpoint;) so cbindgen
sees and emits the struct layout in the generated C headers.
Added new functions to the FFI API for retrieving checkpoints. The following functions were introduced:
dash_spv_ffi_checkpoint_latest: Retrieves the latest checkpoint for a given network.dash_spv_ffi_checkpoint_before_height: Gets the last checkpoint at or before a specified block height.dash_spv_ffi_checkpoint_before_timestamp: Gets the last checkpoint at or before a specified UNIX timestamp.dash_spv_ffi_checkpoints_between_heights: Retrieves all checkpoints between two specified heights.Updated the documentation to reflect the new total function count and included descriptions for the newly added functions. The changes enhance the API's capability to interact with checkpoints, which is essential for maintaining blockchain state.
Summary by CodeRabbit
New Features
Documentation