Skip to content

Handle FFI ownership, CI gates, online-node GC, and threat model - #681

Merged
RyanKung merged 21 commits into
masterfrom
codex/issues-667-670-651-671
Aug 21, 2026
Merged

Handle FFI ownership, CI gates, online-node GC, and threat model#681
RyanKung merged 21 commits into
masterfrom
codex/issues-667-670-651-671

Conversation

@RyanKung

@RyanKung RyanKung commented Aug 15, 2026

Copy link
Copy Markdown
Member

Closes #667.
Closes #670.
Closes #651.
Closes #671.

Supersedes #677, #678, #679, and #680.

Summary:

  • Sync package metadata to 0.17.0 across the Rust workspace and npm/browser package so published artifacts report the same version.
  • Remove obsolete protoc setup from QACI/release workflows; RPC DTOs are plain serde structs now and node/core builds no longer require protobuf generation.
  • Remove PR/release-path Swatinem/rust-cache steps so CI no longer fails before execution when GitHub codeload rate-limits external action downloads.
  • Pin GitHub Actions to immutable commit SHAs. The inline # v3/# v4 comments record which upstream tag the SHA came from; the workflow now executes the reviewed commit, not a mutable tag ref.
  • Add CI security gates: cargo-deny dependency policy, focused Miri coverage, and Linux FFI ASan/LSan coverage.
  • Miri is Rust's interpreter for catching undefined behavior in unsafe-sensitive code paths. This PR runs it with strict provenance on core modules that do not require native sockets, wall-clock interpretation, or expensive crypto searches.
  • Scope sanitizer rustflags to the Linux test target so host/proc-macro dependencies are not compiled with ASan flags.
  • Replace FFI raw Arc reconstruction with an opaque destructible provider handle, add explicit provider/string free APIs, and update the Python FFI wrapper/tests.
  • Break the FFI provider callback reference cycle during destroy and add a Weak regression assertion so provider ownership is actually released.
  • Resolve the dependency-policy gate without vendored serializer code: remove advisory ignores, exclude SNARK extension/example crates at cargo-deny graph construction, and replace the former bincode/wincode wire wrapper with rings-codec backed by postcard.
  • The codec change is intentional because this project does not require pre-release wire compatibility. Keeping bincode/wincode would either preserve a protocol we are willing to change or require carrying local serializer patches for gaps such as 128-bit integer handling. The maintained path is now rings-codec; old bincode crates remain only where unrelated transitive dependencies still pull them in.
  • Delete third_party/serde-wincode and root/standalone path patches; refresh root, frontend, dweb, and proof-demo locks so Node/core/browser paths use rings-codec without vendored serializer code.
  • Add codec regression coverage for stable postcard bytes, i128/u128 roundtrips, serialized-size accounting, and trailing-byte rejection.
  • Add online-node registry GC/compaction: expired/superseded descriptors are removed through verified signed descriptor state.
  • Fix storage Data compaction correctness: delayed compaction preserves post-floor writes, keeps newer register floors monotone, and prevents stale adds from resurrecting after compact/reset races.
  • Refactor Data compaction into named transformations instead of a mutable double-loop, and align new tests with the test_... naming style.
  • Add repository-level overlay threat model documentation that makes the DID/Sybil boundary explicit and links security-sensitive docs to it.

Latest local validation after review cleanup:

  • cargo +nightly-2026-07-02 fmt --all
  • cargo test -p rings-codec
  • cargo test -p rings-core dht::entry::tests

Earlier validation on this PR branch:

  • cargo +nightly fmt --all --check
  • taplo format --check
  • git diff --check
  • cargo deny --offline --locked --exclude rings-snark --exclude rings-snark-example --exclude rings-snark-extension check -A unmatched-source advisories licenses bans sources
  • cargo check -p rings-core -p rings-transport -p rings-node --features ffi
  • cargo check -p rings-snark
  • cargo test -p rings-codec
  • cargo test -p rings-core
  • cargo test -p rings-core storage::sled::test --features default
  • cargo test -p rings-core ecc::tests::test_recover --features default
  • cargo test -p rings-core ecc::elgamal::impls::secp256k1 --features default
  • cargo test -p rings-node --features ffi ffi_ -- --nocapture
  • cargo test -p rings-node test_processor_create_offer --features node -- --nocapture
  • cargo build -p rings-node --features ffi
  • RINGS_FFI_REQUIRE_LIBRARY=1 /tmp/rings-ffi-venv.3G7LK7/bin/python -m pytest examples/ffi/tests/test_rings_ffi.py -q
  • cargo clippy -p rings-codec -p rings-core -p rings-node -p rings-transport --features ffi --all-targets -- -D warnings
  • cargo tree -p rings-codec
  • cargo tree -i bincode@1.3.3
  • (cd frontend && cargo check --target=wasm32-unknown-unknown)
  • (cd examples/dweb && cargo check --target=wasm32-unknown-unknown)
  • (cd examples/proof-demo && cargo check --target=wasm32-unknown-unknown)
  • (cd frontend && cargo test --release --target=wasm32-unknown-unknown webview_node_fetches_page_resources_through_browser_onion_exit -- --nocapture) (local geckodriver exited with SIGKILL before executing tests)
  • npm install --package-lock-only --ignore-scripts
  • actionlint .github/workflows/qaci.yml .github/workflows/release-build.yml
  • ruby -e 'require "yaml"; ARGV.each { |path| YAML.load_file(path); puts "ok #{path}" }' .github/workflows/qaci.yml .github/workflows/release-build.yml

@cursor

cursor Bot commented Aug 15, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@a37ce9120846195fa4ece8f58b268e6043cb2f26 # v3

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's different between this commitment and tag v3, I didnt get any info from your PR body

--exclude rings-snark-extension \
check -A unmatched-source advisories licenses bans sources

miri_core:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is "MIRI"

Comment thread crates/codec/src/lib.rs Outdated
pub fn deserialize<T>(bytes: &[u8]) -> Result<T>
where T: DeserializeOwned {
let (value, remaining) = postcard::take_from_bytes(bytes).map_err(Error::deserialize)?;
if !remaining.is_empty() {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use match here.
return earlier is not good code style

Comment thread crates/codec/src/lib.rs Outdated
}

#[test]
fn roundtrip_and_size_match() -> std::result::Result<(), Box<dyn StdError>> {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a test function, should be named as 'test_blabalbal_blablba'

Ok(())
}

#[test]

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad func name, a test function should be named as 'test_xxxx'

destination: StorageSyncDestination::PhysicalOwner(Did::from(50u32)),
data: entries.clone(),
});
let serialized_bytes = bincode::serialized_size(&message).map_err(Error::BincodeSerialize)?;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from PR body, i cant see clear reason for removing bincode, you should describe the detail

Comment thread crates/core/src/dht/entry.rs Outdated
}

fn ensure_overwrite_stamp_after(self, actor: Did, floor: Option<EntryVersion>) -> Result<Self> {
if self.crdt.register.is_some() {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not do earlier return, bad code style

Comment thread crates/core/src/dht/entry.rs Outdated
) -> Result<Option<(Encoded, EntryDot)>> {
let covered_by_compaction = dot.version < floor;
if covered_by_compaction && removal_values.contains(&value) {
return Ok(None);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad code style

Comment thread crates/core/src/dht/entry.rs Outdated
value: Encoded,
dot: EntryDot,
) -> Result<Option<(Encoded, EntryDot)>> {
let covered_by_compaction = dot.version < floor;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can ust match dot.version < floor { true =>xxx, false =? xxx} here, clean and simple

/// Post: every current visible payload not listed in `removals` is preserved
/// under the greatest observed register floor, and older tombstone metadata
/// is pruned by that floor.
pub fn compact_data(&self, removals: Self, actor: Did) -> Result<Self> {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function is too long and too complex, refine it.

use chacha20poly1305::ChaCha20Poly1305;
use chacha20poly1305::Key;
use chacha20poly1305::Nonce;
use elliptic_curve::point::AffineCoordinates;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Describe why Your choose elliptic_curve instead of libsecp256k1, whats then benifit

@RyanKung
RyanKung merged commit cbc3080 into master Aug 21, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant