Repository navigation
[Phase E5] Version escrow storage and migrate legacy records - #156
damilare0813 wants to merge 15 commits into
Conversation
|
@damilare0813 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
|
This PR has merge conflicts with |
|
@damilare0813 Thanks for the PR. It can't be merged yet. To unblock it: CI is failing. Here's what broke:
Please fix these errors and run the same steps locally before pushing ( Merge conflicts: this branch conflicts with Push to this same branch and CI will re-run. Once it's green and conflict-free, it'll be reviewed for merge. |
|
@afeezorobsco-cyber I resolved the conflicts with main and pushed the update. The escrow contract test suite passes. Please review and merge when ready. |
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared files like Automated message. It won't repeat unless the PR conflicts again after your next push. |
# Conflicts: # ROADMAP.md # contracts/escrow/src/lib.rs
|
@afeezorobsco-cyber I resolved the merge conflicts and verified the storage migration regression tests pass. The PR description now has a standalone |
4e462b4 to
14ad0db
Compare
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared files like Automated message. It won't repeat unless the PR conflicts again after your next push. |
# Conflicts: # ROADMAP.md # contracts/escrow/src/lib.rs
|
@afeezorobsco-cyber I updated this branch with the latest main and resolved the conflicts while preserving the storage migration coverage. The full escrow Rust test suite and formatting check pass. Please review and merge when ready. |
|
@afeezorobsco-cyber This branch now includes the latest main and is conflict-free. The full escrow Rust test suite and formatting check pass. Please review and merge when ready. |
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared files like Automated message. It won't repeat unless the PR conflicts again after your next push. |
|
@damilare0813 CI is failing on this branch against the latest SDK bindings match contract WASM
cd contracts/escrow && cargo build --target wasm32v1-none --release
stellar contract bindings typescript --wasm target/wasm32v1-none/release/docforum_escrow.wasm --output-dir /tmp/escrow-bindings --overwrite
cp /tmp/escrow-bindings/src/index.ts ../../sdk/src/generated/contract-client.ts( This PR also conflicts with |
|
@afeezorobsco-cyber I resolved the merge conflicts against the latest main, preserved this PR’s feature, regenerated the contract bindings, and updated the affected test snapshots. The escrow contract tests pass. Could you please review the update and merge when ready? |
|
@damilare0813 CI is failing on this branch against the latest SDK bindings match contract WASM
cd contracts/escrow && cargo build --target wasm32v1-none --release
stellar contract bindings typescript --wasm target/wasm32v1-none/release/docforum_escrow.wasm --output-dir /tmp/escrow-bindings --overwrite
cp /tmp/escrow-bindings/src/index.ts ../../sdk/src/generated/contract-client.ts( |
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
1 similar comment
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
1 similar comment
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
|
@damilare0813 This PR conflicts with git fetch upstream
git rebase upstream/main
# fix the conflicts, then
git push --force-with-leaseIf the conflict is in |
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
1 similar comment
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
|
@damilare0813 This PR conflicts with git fetch upstream
git rebase upstream/main
# fix the conflicts, then
git push --force-with-leaseIf the conflict is in |
…DocForum#37) Resolve the conflicts with origin/main (d74b961) and fix the failing "SDK bindings match contract WASM" check: - contracts/escrow/src/lib.rs: keep the tagged StoredEscrowData V1-V4 layout next to main's pooled-escrow types. Every escrow read and write now goes through load_escrow/save_escrow (pooled create/contribute/ claim_refund, rotate_releaser, top_up, refund and settle included), so no record is written in the untagged layout. - Error code collision: main's InvalidReleaser keeps 24. The new UnsupportedStorageVersion moves to 35, the next free discriminant. - sdk/src/generated/contract-client.ts: regenerated with stellar CLI 28.1.0 from the release WASM. The only change against main is the new UnsupportedStorageVersion error. scripts/check-generated-bindings.sh passes. - contracts/escrow/test_snapshots: regenerated by cargo test. A second run leaves them byte-identical. - changelog.d/37-versioned-storage-layout.md: changelog fragment. Validation: cargo test (all binaries, --test-threads=1 and default) passes, cargo build --target wasm32v1-none --release passes, scripts/check-resource-baseline.py passes, and the SDK typecheck, build and test:offline pass.
The PR branch on damilare0813/docforum-escrow moved to 6ea5f1f after this branch was fetched. The merge adds no file changes against this branch, so the tree is unchanged. Recorded here so the push is a fast-forward and that commit is not dropped.
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
|
Note for maintainers: the PR body is stale. It describes a V3 layout and does not mention V4 or the merge with main's pooled-escrow types. cargo fmt --check fails on main's existing code (lib.rs, cancel.rs, pooled.rs, model.rs, malicious_token.rs). This PR's own storage_migration.rs is clean. The fork's workflow run needs maintainer approval. |
|
Rebased onto the latest No While I was in there I also fixed Regenerated SDK bindings with Stellar CLI 28.1.0 (no diff beyond the one new |
|
@afeezorobsco-cyber this is ready for a look whenever you have a moment. |
|
@damilare0813 CI is failing at Resource cost baseline: Your change makes |
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
|
@afeezorobsco-cyber I reduced |
|
@damilare0813 Heads-up: #268 just changed how contract PRs work in this repo. Your PR changes
This should also make your next merge from |
# Conflicts: # contracts/escrow/src/lib.rs # contracts/escrow/test_snapshots/acceptance_requires_the_payee_and_only_works_while_funded.1.json # contracts/escrow/test_snapshots/callback_cannot_reenter_create_escrow.1.json # contracts/escrow/test_snapshots/callback_cannot_reenter_refund.1.json # contracts/escrow/test_snapshots/callback_cannot_reenter_release.1.json # contracts/escrow/test_snapshots/callback_error_reverts_release_but_does_not_block_refund.1.json # contracts/escrow/test_snapshots/cancel_after_release_is_rejected.1.json # contracts/escrow/test_snapshots/cancel_after_releaser_refund_is_rejected.1.json # contracts/escrow/test_snapshots/cancel_after_timeout_refund_is_rejected.1.json # contracts/escrow/test_snapshots/cancel_is_not_available_without_requires_acceptance.1.json # contracts/escrow/test_snapshots/cancel_only_returns_that_escrows_amount.1.json # contracts/escrow/test_snapshots/cancel_pays_the_sponsored_refund_to_not_the_funder.1.json # contracts/escrow/test_snapshots/cancel_requires_the_payers_signature.1.json # contracts/escrow/test_snapshots/cancel_stays_rejected_after_accept_even_much_later.1.json # contracts/escrow/test_snapshots/cancel_still_works_after_refund_after_has_passed_if_still_funded.1.json # contracts/escrow/test_snapshots/claim_refund_emits_an_event.1.json # contracts/escrow/test_snapshots/claiming_requires_the_contributors_signature.1.json # contracts/escrow/test_snapshots/configured_allowlist_accepts_listed_token_and_rejects_unlisted_token.1.json # contracts/escrow/test_snapshots/contribute_emits_an_event.1.json # contracts/escrow/test_snapshots/contribute_rejects_lying_transfer.1.json # contracts/escrow/test_snapshots/contribute_rejects_short_delivery.1.json # contracts/escrow/test_snapshots/contributor_cannot_claim_another_contributors_funds.1.json # contracts/escrow/test_snapshots/create_bounds_the_releaser_set_size.1.json # contracts/escrow/test_snapshots/create_escrow_accepts_deadline_strictly_in_the_future.1.json # contracts/escrow/test_snapshots/create_escrow_assigns_sequential_ids.1.json # contracts/escrow/test_snapshots/create_escrow_locks_funds_and_reports_funded.1.json # contracts/escrow/test_snapshots/create_escrow_rejects_condition_ref_that_is_too_long.1.json # contracts/escrow/test_snapshots/double_cancel_is_rejected_and_pays_out_once.1.json # contracts/escrow/test_snapshots/double_claim_is_rejected.1.json # contracts/escrow/test_snapshots/double_refund_pays_refund_to_once.1.json # contracts/escrow/test_snapshots/duplicate_approvals_from_one_releaser_cannot_satisfy_the_threshold.1.json # contracts/escrow/test_snapshots/each_listed_approver_must_actually_authorize_the_invocation.1.json # contracts/escrow/test_snapshots/empty_allowlist_preserves_open_token_behavior.1.json # contracts/escrow/test_snapshots/escrow_without_requires_acceptance_still_releases_and_refunds_as_before.1.json # contracts/escrow/test_snapshots/explicit_refund_to_equal_to_payer_behaves_like_the_default.1.json # contracts/escrow/test_snapshots/failed_claim_leaves_the_contribution_intact.1.json # contracts/escrow/test_snapshots/failed_payout_leaves_the_escrow_funded.1.json # contracts/escrow/test_snapshots/failed_round_refunds_every_contributor_exactly.1.json # contracts/escrow/test_snapshots/funder_calling_refund_after_the_deadline_cannot_steer_the_money_to_itself.1.json # contracts/escrow/test_snapshots/get_escrow_exposes_the_stored_parties_and_deadline.1.json # contracts/escrow/test_snapshots/get_escrow_reports_no_deadline_when_none_was_set.1.json # contracts/escrow/test_snapshots/invalid_contributions_are_rejected.1.json # contracts/escrow/test_snapshots/legacy_creation_keeps_acceptance_opt_out.1.json # contracts/escrow/test_snapshots/multiple_contributors_recorded_independently.1.json # contracts/escrow/test_snapshots/neither_funder_nor_refund_to_may_trigger_a_refund_before_the_deadline.1.json # contracts/escrow/test_snapshots/no_contributor_cap_each_claim_is_independent.1.json # contracts/escrow/test_snapshots/non_member_approver_is_rejected.1.json # contracts/escrow/test_snapshots/omitted_refund_to_defaults_to_payer.1.json # contracts/escrow/test_snapshots/omitted_refund_to_timeout_refund_still_goes_to_payer.1.json # contracts/escrow/test_snapshots/only_the_stored_payer_may_cancel.1.json # contracts/escrow/test_snapshots/opted_in_contract_payee_receives_release_callback.1.json # contracts/escrow/test_snapshots/ordinary_escrows_are_unaffected.1.json # contracts/escrow/test_snapshots/partial_funding_records_and_blocks_release.1.json # contracts/escrow/test_snapshots/payer_cancel_before_accept_refunds_payer_in_full.1.json # contracts/escrow/test_snapshots/pooled_creation_respects_the_token_allowlist.1.json # contracts/escrow/test_snapshots/pooled_creation_validation.1.json # contracts/escrow/test_snapshots/push_paths_and_top_up_reject_pooled_escrows.1.json # contracts/escrow/test_snapshots/quorum_escrow_stores_the_releaser_set_and_threshold.1.json # contracts/escrow/test_snapshots/quorum_release_invokes_opted_in_contract_payee.1.json # contracts/escrow/test_snapshots/race_accept_lands_first_then_cancel_fails_and_payee_keeps_the_escrow.1.json # contracts/escrow/test_snapshots/race_cancel_lands_first_then_accept_fails_and_payer_keeps_the_funds.1.json # contracts/escrow/test_snapshots/reaching_the_target_releases_the_pooled_total.1.json # contracts/escrow/test_snapshots/reentrant_transfer_cannot_double_release.1.json # contracts/escrow/test_snapshots/refund_entitlements_are_order_independent.1.json # contracts/escrow/test_snapshots/refund_entitlements_are_order_independent.2.json # contracts/escrow/test_snapshots/refund_entitlements_are_order_independent.3.json # contracts/escrow/test_snapshots/refund_rejects_after_release.1.json # contracts/escrow/test_snapshots/refund_rejects_unauthorized_caller.1.json # contracts/escrow/test_snapshots/refund_to_is_fixed_at_creation_and_visible_via_get_escrow.1.json # contracts/escrow/test_snapshots/refund_transfers_funds_back_to_payer_and_marks_refunded.1.json # contracts/escrow/test_snapshots/refund_with_approvals_rejects_duplicates_and_short_thresholds.1.json # contracts/escrow/test_snapshots/refund_with_approvals_returns_funds_to_the_payer.1.json # contracts/escrow/test_snapshots/release_and_refund_can_never_share_funds.1.json # contracts/escrow/test_snapshots/release_is_rejected_before_time_and_allowed_at_the_exact_boundary.1.json # contracts/escrow/test_snapshots/release_lock_does_not_restrict_releaser_refunds.1.json # contracts/escrow/test_snapshots/release_rejects_after_refund.1.json # contracts/escrow/test_snapshots/release_rejects_double_release.1.json # contracts/escrow/test_snapshots/release_rejects_unauthorized_caller.1.json # contracts/escrow/test_snapshots/release_still_pays_the_payee_not_refund_to.1.json # contracts/escrow/test_snapshots/release_time_equal_to_creation_time_is_valid_and_releasable_immediately.1.json # contracts/escrow/test_snapshots/release_time_equal_to_refund_deadline_is_valid.1.json # contracts/escrow/test_snapshots/release_transfers_funds_to_payee_and_marks_released.1.json # contracts/escrow/test_snapshots/release_wins_at_the_deadline_and_timeout_refund_then_fails.1.json # contracts/escrow/test_snapshots/release_with_approvals_is_gated_by_full_funding_too.1.json # contracts/escrow/test_snapshots/release_with_exactly_threshold_distinct_approvals_pays_the_payee.1.json # contracts/escrow/test_snapshots/release_with_fewer_than_threshold_approvals_is_rejected.1.json # contracts/escrow/test_snapshots/release_with_more_than_threshold_approvals_succeeds.1.json # contracts/escrow/test_snapshots/releaser_can_still_release_after_the_deadline.1.json # contracts/escrow/test_snapshots/releaser_cannot_pay_out_after_cancel.1.json # contracts/escrow/test_snapshots/releaser_refund_goes_to_refund_to_not_the_funder.1.json # contracts/escrow/test_snapshots/releaser_refund_still_works_before_deadline.1.json # contracts/escrow/test_snapshots/releasers_can_still_release_after_the_deadline.1.json # contracts/escrow/test_snapshots/repeated_contributions_accumulate_per_payer.1.json # contracts/escrow/test_snapshots/required_acceptance_blocks_release_until_payee_accepts.1.json # contracts/escrow/test_snapshots/rotation_rejects_contract_and_payee_as_new_releaser.1.json # contracts/escrow/test_snapshots/rotation_rejects_wrong_releaser_and_non_funded_escrows.1.json # contracts/escrow/test_snapshots/rotation_requires_both_stored_parties_and_updates_the_releaser.1.json # contracts/escrow/test_snapshots/settled_approvals_cannot_be_replayed.1.json # contracts/escrow/test_snapshots/settled_escrow_cannot_be_refunded_to_refund_to_afterwards.1.json # contracts/escrow/test_snapshots/single_caller_release_on_a_quorum_escrow_needs_the_approval_path.1.json # contracts/escrow/test_snapshots/single_releaser_escrow_behaves_as_a_one_of_one_quorum.1.json # contracts/escrow/test_snapshots/the_beneficiary_refund_to_never_has_to_sign.1.json # contracts/escrow/test_snapshots/timeout_refund_at_the_exact_deadline_goes_to_refund_to.1.json # contracts/escrow/test_snapshots/timeout_refund_by_a_stranger_goes_to_refund_to.1.json # contracts/escrow/test_snapshots/timeout_refund_by_stranger_succeeds_after_deadline.1.json # contracts/escrow/test_snapshots/timeout_refund_by_stranger_succeeds_at_the_exact_deadline.1.json # contracts/escrow/test_snapshots/timeout_refund_cannot_pay_anyone_but_the_payer.1.json # contracts/escrow/test_snapshots/timeout_refund_fails_after_release.1.json # contracts/escrow/test_snapshots/timeout_refund_fails_after_releaser_refund.1.json # contracts/escrow/test_snapshots/timeout_refund_rejected_before_deadline.1.json # contracts/escrow/test_snapshots/timeout_refund_still_needs_no_approvals_on_a_quorum_escrow.1.json # contracts/escrow/test_snapshots/timeout_refund_wins_at_the_deadline_and_release_then_fails.1.json # contracts/escrow/test_snapshots/top_up_adds_funds_to_the_same_funded_escrow.1.json # contracts/escrow/test_snapshots/top_up_after_cancel_is_rejected.1.json # contracts/escrow/test_snapshots/top_up_before_accept_is_fully_returned_by_cancel.1.json # contracts/escrow/test_snapshots/top_up_emits_an_event.1.json # contracts/escrow/test_snapshots/top_up_rejects_invalid_payer_amount_overflow_and_settled_state.1.json # contracts/escrow/test_snapshots/two_escrows_keep_their_own_refund_to.1.json # contracts/escrow/test_snapshots/without_deadline_releaser_refund_still_works.1.json # contracts/escrow/test_snapshots/without_deadline_stranger_refund_stays_unauthorized_even_forever_after.1.json # sdk/src/generated/contract-client.ts
|
Synced this branch with current main and resolved the merge conflict. Kept CONTRACT_VERSION at 2.3.0, added the required issue #37 minor fragment and provisional UnsupportedStorageVersion code 3700, and migrated legacy funded records to V5 while seeding liability accounting on first rewrite. Full Rust tests, the contract-change check, and generated-binding check pass. GitHub reports mergeable=true; Malware scan is still pending. @afeezorobsco-cyber, please recheck when convenient. |
|
@damilare0813 This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared docs like Automated message. It won't repeat unless the PR conflicts again after your next push. |
[Phase E5] Version escrow storage and migrate legacy records
Closes #37
Problem
Soroban persists a
#[contracttype]struct as anScVal::Mapkeyed byfield name. Every time
EscrowDatahas gained a field —refund_after(ADR 0004), the releaser set and quorum threshold (ADR 0007), the
callback/acceptance flags, and now
refund_to(ADR 0009) andrelease_not_before— a reader built for the new shape fails to decode anolder record, because the map's key set has to match the struct exactly.
There was no explicit policy for reading old records or for what happens
when a layout is neither the current shape nor a recognized old one.
Implementation
StoredEscrowData, atagged enum (
V1..V4) of version-specific structs. New writesalways use
V4, the current 14-field record (refund_toandrelease_not_beforeincluded).V1-V3stay around only to decodeold records; their field sets never change again.
load_escrowadditionally recognizes the exact bare, untaggedScVal::Mapshapes written before this scheme existed: 7 fields(pre-ADR-0004), 8 fields (pre-releaser-sets), 12 fields (pre-
refund_to/release_not_before), and the current untagged 14-field map. Any othershape — including a tagged enum variant that doesn't decode, or
anything else — fails closed with the new
Error::UnsupportedStorageVersion(code 35, the next free discriminant; it does not collide with main's
InvalidReleaser = 24).get_status/get_escrownevermutate storage. The next state-changing call on a given escrow
(
release,refund,refund_with_approvals,cancel,accept,rotate_releaser,top_up, or a pooledcontribute/claim_refund)writes the record back as tagged
V4through a singlesave_escrowhelper, so every write path uses the same tagged layout — there is no
remaining call site that writes the untagged shape.
mainnow has, including pooled escrows(issue [Phase E5] Pooled escrows funded by multiple payers with pro-rata refunds #113):
create_pooled_escrowbuilds and stores itsEscrowDatathrough the same
save_escrowpath, so a pooled escrow's body isalways written as
V4from the start. There is no older pooled layoutto migrate —
create_pooled_escrownever existed before this scheme.Pooled escrows' separate
PooledandContributionrecords areuntouched — they are not part of
StoredEscrowData.mainadded a dedicatedDataKey::Statusentry soget_statuscan skip decoding the fullbody. That key is written by the same
save_statushelper everywherethe escrow status changes (creation and settlement).
get_statusreadsit directly when present, and falls back to the versioned loader (with
the same migration-on-write guarantee) for any record predating that
key — covered by a new test,
legacy_record_without_status_key_reports_status_from_the_escrow_body.new
UnsupportedStorageVersionerror variant, sosdk/src/generated/contract-client.tswas regenerated with the pinnedStellar CLI (28.1.0) — the only diff against
main's bindings is thatone error entry.
docs/adr/0008and the "Persistent storage layout policy" note inARCHITECTURE_ESSENTIALS.mdare updated to describe the current V4layout, the four recognized pre-version map shapes, and how pooled
escrows and the status key fit in (they previously described an
earlier, now-superseded V3/three-shape design from before this branch
picked up
main's pooled-escrow and status-key work).changelog.d/37-versioned-storage-layout.mdfragment (notROADMAP.md— seechangelog.d/README.md) is updated to match.ROADMAP.mditself is unchanged frommain; issue [Phase E5] Versioned storage layout and a migration strategy forEscrowData#37 has no existingchecklist line to tick there.
Merging with main
This branch previously conflicted with
mainafter #257 (pooledescrows) and #260 (the status read key) landed there. This PR now merges
origin/mainand resolves both conflicts by keepingmain's behavior andfolding it into the versioned-storage scheme:
main's directenv.storage().persistent().set(&DataKey::Escrow(...), ...)/...set(&DataKey::Status(...), ...)call sites (increate_pooled_escrow,create_escrow_inner, andsettle) now goes throughsave_escrow/save_statusinstead, so pooled-escrow creation and every settlementwrite the tagged
V4layout and the status key together.ARCHITECTURE_ESSENTIALS.md's "Persistent storage layout policy" note(added by this branch) and
main's custom-releaser-account paragraphare both kept, in
main's order.Validation
scripts/check-generated-bindings.shwith the pinned Stellar CLI(28.1.0): bindings match the rebuilt contract WASM, no diff.
cargo testincontracts/escrow: full suite green, including new andupdated
tests/storage_migration.rscases (legacy 7/8/12-field maps,tagged V1/V2, the status-key fallback, and a pooled-escrow write
check). Snapshot updates committed; a second
cargo testrun leaves theworking tree clean.
cargo fmt --check,cargo clippy --all-targets: no errors.cargo fmt --checkstill reports the same pre-existing diffs thatmainitself has (
benches/resource_profile.rsand a handful of lines insrc/lib.rs/tests unrelated to this change) — confirmed byte-identicalto
main's own copies of those files, so this isn't something this PRintroduced or needs to fix.
cargo build --target wasm32v1-none --release: succeeds.npm ci --ignore-scripts,npm run typecheck,npm run build,npm run test:offline(64 tests) andnpm run test:unit(56 tests) allpass.
Closes #37