Repository navigation
feat(registry): version upgrade validation (#304) - #377
Conversation
Add an immutable, instance-storage audit trail to the registry's version upgrade lifecycle so every propose/commit/reject is recorded on-chain with who did what to which version of a module kind, and when. - shared: add `UpgradeAudit` payload (#[contracttype], published and stored with one identical schema), `UpgradeProposed` / `UpgradeCommitted` / `UpgradeRejected` canonical events, tuple-topic helpers, `UPGRADE_PROPOSAL_EXPIRY` (1 week) and `MAX_UPGRADE_AUDIT_ENTRIES` (32) constants, and a `require_valid_wasm_hash` guard (refuses the all-zero hash). - registry: append each successful lifecycle action to a newest-first ring buffer in instance storage, capped at MAX_UPGRADE_AUDIT_ENTRIES; expose `get_upgrade_history` / `get_upgrade_history_len`. Re-validate proposals at commit time (downgrade, expiry, wasm hash) so nothing stale can slip through. - refused attempts (unauthorized actor, downgrade, identical-WASM re-proposal) are deliberately not logged: Soroban invocations are atomic, so writes made on an error path are rolled back and could never be observed on-chain. Refusals stay visible off-chain as reverted transactions carrying their error code. - tests: registry unit tests covering event emission, log immutability, ring-buffer retention, and the identical-WASM/unauthorized edge cases; cross-crate tests in tests/src/upgrade_validation.rs driving the flow through deployed contract boundaries. Closes ASTROIDX556#300 Generated with Codebuff 🤖 Co-Authored-By: Codebuff <noreply@codebuff.com>
…version guards (ASTROIDX556#304) Make the Issue ASTROIDX556#304 validation surface explicit and fully tested: - add a module-level validation matrix documenting every check in the propose -> commit upgrade flow (authorization, downgrade protection, wasm-hash format, identical-WASM re-proposal, one-open-proposal, expiry, freeze) with the error each refusal reports, and noting that the register_version admin escape hatch carries the same guards. - add register_version_rejects_downgrades_and_repeats covering the monotonic version table: repeat and downgrade land InvalidState, strictly newer versions are accepted. No behavior change: the checks themselves ship in the ASTROIDX556#300 stacked branch; this commit makes the ASTROIDX556#304 scope explicit and locks it in with tests. Closes ASTROIDX556#304 Generated with Codebuff 🤖 Co-Authored-By: Codebuff <noreply@codebuff.com>
Merge Conflict — Action NeededThis pull request has merge conflicts with the base branch ( What to do: update your branch by merging or rebasing against |
|
@meem08 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! 🚀 |
CI Checks Failed — Action NeededThe continuous integration checks on this pull request are failing. I can't merge until all required checks pass. Failing checks:
What to do: review the failing checks in the "Checks" tab above, fix the issues in your code, and push the changes. |
CI Checks Failed — Action NeededThe continuous integration checks on this pull request are failing. I can't merge until all required checks pass. Failing checks:
What to do: review the failing checks in the "Checks" tab above, fix the issues in your code, and push the changes. |
CI Checks Failed — Action NeededThe continuous integration checks on this pull request are failing. I can't merge until all required checks pass. Failing checks:
What to do: review the failing checks in the "Checks" tab above, fix the issues in your code, and push the changes. |
CI Checks Failed — Action NeededThe continuous integration checks on this pull request are failing. I can't merge until all required checks pass. Failing checks:
What to do: review the failing checks in the "Checks" tab above, fix the issues in your code, and push the changes. |
Merge Conflict — Action NeededThis pull request has merge conflicts with the base branch ( What to do: update your branch by merging or rebasing against |
CI Checks Failed — Action NeededThe continuous integration checks on this pull request are failing. I can't merge until all required checks pass. Failing checks:
What to do: review the failing checks in the "Checks" tab above, fix the issues in your code, and push the changes. |
Merge Conflict — Action NeededThis pull request has merge conflicts with the base branch ( What to do: update your branch by merging or rebasing against |
CI Checks Failed — Action NeededThe continuous integration checks on this pull request are failing. I can't merge until all required checks pass. Failing checks:
What to do: review the failing checks in the "Checks" tab above, fix the issues in your code, and push the changes. |
Merge Conflict — Action NeededThis pull request has merge conflicts with the base branch ( What to do: update your branch by merging or rebasing against |
1 similar comment
Merge Conflict — Action NeededThis pull request has merge conflicts with the base branch ( What to do: update your branch by merging or rebasing against |
CI Checks Failed — Action NeededThe continuous integration checks on this pull request are failing. I can't merge until all required checks pass. Failing checks:
What to do: review the failing checks in the "Checks" tab above, fix the issues in your code, and push the changes. |
1 similar comment
CI Checks Failed — Action NeededThe continuous integration checks on this pull request are failing. I can't merge until all required checks pass. Failing checks:
What to do: review the failing checks in the "Checks" tab above, fix the issues in your code, and push the changes. |
CI Checks Failed — Action NeededThe continuous integration checks on this pull request are failing. I can't merge until all required checks pass. Failing checks:
What to do: review the failing checks in the "Checks" tab above, fix the issues in your code, and push the changes. |
1 similar comment
CI Checks Failed — Action NeededThe continuous integration checks on this pull request are failing. I can't merge until all required checks pass. Failing checks:
What to do: review the failing checks in the "Checks" tab above, fix the issues in your code, and push the changes. |
Merge Conflict — Action NeededThis pull request has merge conflicts with the base branch ( What to do: update your branch by merging or rebasing against |
CI Checks Failed — Action NeededThe continuous integration checks on this pull request are failing. I can't merge until all required checks pass. Failing checks:
What to do: review the failing checks in the "Checks" tab above, fix the issues in your code, and push the changes. |
Merge Conflict — Action NeededThis pull request has merge conflicts with the base branch ( What to do: update your branch by merging or rebasing against |
CI Checks Failed — Action NeededThe continuous integration checks on this pull request are failing. I can't merge until all required checks pass. Failing checks:
What to do: review the failing checks in the "Checks" tab above, fix the issues in your code, and push the changes. |
CI Checks Failed — Action NeededThe continuous integration checks on this pull request are failing. I can't merge until all required checks pass. Failing checks:
What to do: review the failing checks in the "Checks" tab above, fix the issues in your code, and push the changes. |
The merge from main kept the upgrade-audit callers but dropped their definitions: restore shared UpgradeAudit/events/constants/validation items from the ASTROIDX556#300 feature line, re-add the registry DataKey variants and upgrade-audit types, and close the truncated pending_proposal body that left impl RegistryContract unclosed. Deduplicate the mangled test import block and adapt the downgrade tests to register_version's monotonic guard (strictly greater than latest), as specified for ASTROIDX556#304. 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
Merge Conflict — Action NeededThis pull request has merge conflicts with the base branch ( What to do: update your branch by merging or rebasing against |
Closes #304
Summary
The Registry is the protocol's single source of truth for version upgrades, so replacing deployed bytecode must be impossible for an unauthorized caller, with malformed bytecode, and it must never be able to move a version backwards. This implements strict validation for proposing and committing contract Wasm upgrades in
contracts/registry/src/lib.rs.Validation matrix (implemented)
ModuleUpgraderpropose_upgradeUnauthorized(NotFoundfor an unknown org, so a typo is distinguishable from a permission failure)versionnon-zero and strictly greater than the kind's latestregister_versionInvalidInput/InvalidState— downgrade protectionwasm_hashwell-formed (all-zero hash refused) viarequire_valid_wasm_hashadd_approved_wasmInvalidInputInvalidInput— identical-WASM re-proposal refusedInvalidState— the upgrade path stays unambiguousUPGRADE_PROPOSAL_EXPIRY)NotFoundRegistryFrozenCommitting re-runs the full check set so nothing that went stale while a proposal was pending can slip through. Successful lifecycle actions emit structured
UpgradeProposed/UpgradeCommitted/UpgradeRejectedevents (canonical + tuple-topic form) and are appended to the immutable audit log; refused attempts revert atomically with their error code (Soroban rolls back any write made on an error path, so refusals are visible off-chain as reverted transactions).Acceptance criteria (from the issue)
contracts/registry/src/UpgradeProposed/UpgradeCommitted/UpgradeRejectedon success; refused attempts revert with the deterministic shared error)Tests
Unit (
contracts/registry/src/test.rs, 75 passing):Unauthorized, delegatedPolicyManager→Unauthorized, delegatedModuleUpgrader/ org owner / admin → allowed (stranger_and_delegated_non_upgrader_cannot_propose,org_owner_module_upgrader_and_admin_can_propose,audit_log_captures_unauthorized_attempts-successor)proposal_validation_rejects_unauthorized_and_downgrades,stale_proposal_cannot_shadow_a_committed_version,audit_log_captures_rejected_and_identical_wasm_attempts-successorrefused_upgrades_leave_no_audit_entriesrequire_valid_wasm_hashunit coverage + zero-hash refusalexpired_proposal_cannot_be_committedregister_version_rejects_downgrades_and_repeats— the admin escape hatch obeys the same monotonic version-table guard (repeat and downgrade →InvalidState, strictly newer accepted)Integration (
tests/src/upgrade_validation.rs): the propose → commit flow driven across deployed contract boundaries, unauthorized/downgrade rejections, rejection/withdrawal clearing the pending slot, double-commit refusal, and the wallet-facingis_wasm_approvedgate staying intact.Testing done locally
cargo test -p astroid-registry: 75/75 passed;cargo test -p astroid-integration-teststype-checks clean.cargo fmt --checkandcargo clippy -- -D warningsclean for the touched crates.mainafter feat(registry): version upgrade audit logging (#300) #375 lands (main has since gained unrelated budget/policy work); CI is the authoritative gate.