feat: add related_contracts() WASM export, full RelatedContracts API, and proptest fuzzing#59
Closed
xotatera wants to merge 6 commits intofreenet:mainfrom
Closed
feat: add related_contracts() WASM export, full RelatedContracts API, and proptest fuzzing#59xotatera wants to merge 6 commits intofreenet:mainfrom
xotatera wants to merge 6 commits intofreenet:mainfrom
Conversation
Add WASM FFI export for related_contracts() so the runtime can query a contract's declared dependencies before validation. Also includes RelatedContract with timeout/ttl fields, RelatedContractsContainer with cycle detection and depth limiting, and ContractInterface default method for declaring dependencies upfront. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
set_initial_depth allows sharing depth budget across nested dependency resolution. RelatedMode derives Copy+Clone for ergonomic use in mocks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…served fields - increment_depth now uses >= (consistent with request_with_tracking) - merge() preserves max(self.depth, other.depth) instead of discarding - timeout/ttl on RelatedContract documented as reserved for future use Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tainer logic Property-based tests found and fixed a bug where increment_depth() could exceed MAX_REQUEST_DEPTH when set_initial_depth was called first. Also clamps set_initial_depth to MAX and derives Clone on ValidateResult. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Contracts that depend on other contracts had no way to declare their dependencies upfront. The runtime had to discover dependencies reactively through
ValidateResult::RequestRelatedresponses, causing unnecessary round-trips.RelatedContractsContaineralso lacked depth/cycle tracking, making it vulnerable to infinite loops from malicious or buggy contracts.Approach
WASM Export for Upfront Dependency Declaration
related_contracts()WASM export (zero-arg, returns serializedVec<RelatedContract>) lets contracts declare dependencies at compile timeContractInterfacetrait gets a defaultrelated_contracts()method (returns empty vec)freenet-macrosgenerates the FFI wrapper automaticallyinner_related_contractsinwasm_interface.rshandles serialization across the WASM boundaryFull RelatedContracts API
RelatedContracts: query helpers (len,is_empty,contains,get,insert,resolved_count,pending_count,all_resolved)RelatedContract: builder pattern withwith_timeout/with_ttl(reserved for future runtime enforcement)RelatedMode: derivesCopy + Clonefor ergonomic use in mock/test codeValidateResult: derivesClone(needed by proptest strategies)RelatedContractsContainer Safety
request_depth+seenset for depth limiting and cycle detectionMAX_REQUEST_DEPTH = 10with documented effective budgetset_initial_depth()for sharing depth budget across nested resolutionrequest_with_tracking()combines depth check + cycle detectionincrement_depth()checks before incrementing (bug found by proptest)merge()preserves max depth and unions seen setsset_initial_depth()clamps to MAX (bug found by proptest)Proptest Fuzzing
Property-based tests that already found and fixed 2 bugs:
increment_depth()could overshootMAX_REQUEST_DEPTHwhenset_initial_depthwas called first (incremented before checking)set_initial_depth()accepted values above MAX without clamping12 proptest tests covering:
UpdateData(all 6 variants),ValidateResult,RelatedContracts,RelatedContractinto_owned()preserves serialized formresolved_count + pending_count == lenFrom<RelatedContracts>splits resolved/not_found correctlyFrom<Vec<UpdateData>>extracts only RelatedState variantsTesting
cargo fmt && cargo clippycleanPROPTEST_CASES=1000Files Changed
rust-macros/src/contract_impl.rsrelated_contracts()FFI exportrust/Cargo.tomlproptestdev-dependencyrust/src/contract_composition.rsrelated_contracts()toContractComponenttraitrust/src/contract_interface/encoding.rsrust/src/contract_interface/trait_def.rsrelated_contracts()toContractInterfacerust/src/contract_interface/update.rsrust/src/contract_interface/wasm_interface.rsinner_related_contractsWASM boundary helperrust/src/memory.rswasm_return_0argfor zero-arg WASM exports[AI-assisted - Claude]