feat(smart-contract): migrate a node contract to another node in the same farm - #1113
Open
sameh-farouk wants to merge 3 commits into
Open
feat(smart-contract): migrate a node contract to another node in the same farm#1113sameh-farouk wants to merge 3 commits into
sameh-farouk wants to merge 3 commits into
Conversation
…same farm Adds `migrate_node_contract(contract_id, node_id, deployment_hash)` at call index 22, restricted to `RestrictedOrigin` (root or 3/5 council). It moves a live node contract to another node in the same farm without cancelling it, so a farmer can empty a machine and power it down without destroying the tenant's contract. The extrinsic bills the contract first, settling at the source node's cost basis, then re-reads it because billing can mutate or remove it. It moves the entry in `ContractIDByNodeIDAndHash` behind an equality guard, since `update_node_contract` never enforced hash uniqueness and a key may already point at a different live contract. `ContractPaymentState.last_updated_seconds` is stamped unconditionally. It moves the booking, not the workload. The source node deprovisions its copy on its next reconciliation and deletes the disks, so preserving data is the caller's responsibility before calling. See docs/architecture/0027 for the full reasoning and docs/misc/migrate_node_contract.md for the operational runbook. Also brings the two report handlers into line with each other. Both already skipped a report naming a contract that does not exist, silently and for free; a report naming a contract that exists but sits on another node was handled the opposite way, aborting the whole batch and charging for it. Both now skip and log. That asymmetry was unreachable before this change, since cancellation removes the contract and the missing-contract guards catch it. Weight is parameterised on `max(source, destination)` active-contract count, following the convention established in 526158f. The measured weights.rs still needs regenerating via workflow 060 before merge. Fixes a pre-existing bug in the integration harness where TMP_DIR was "\tmp", which Python reads as TAB + "mp".
The NodeContractResources section opened by explaining that the tenant is not over-billed by a migration. That is true but it documents a non-event: billing continues at the same quantity on the same schedule, so describing it at length mostly plants the doubt it then answers. What survives is the warning, which three reviewers of this change independently tried to "fix" by clearing the entry. Rewritten to stand on its own so the dangling reference to the removed paragraph goes with it. Also drops "retiring the 2012 generation means 122" from the context. The number carried no unit, and the sentence already lands with 74 contracts across 29 twins.
…into the code The ADR read as an implementation walkthrough: it narrated what the extrinsic does in execution order, re-telling mechanics that already carry comments at their own sites. That duplicates the code and goes stale the moment either side moves. Reorganised around the eight decisions actually taken, each with its reasoning and what it costs. Preconditions move into their own section, since an operator wants them as a list rather than buried in rationale. Nothing is dropped: the call_index 23 forward constraint, the transaction_version reasoning, the ZOS-forced ordering, certification repricing and the weight ceiling are all still here. The "do not clear NodeContractResources" warning becomes a comment in _migrate_node_contract, next to the mutation where someone would be tempted. Three reviewers of this change proposed clearing it; the warning belongs where that edit would be written, not in a document they may not open.
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.
Closes #1112.
Adds
migrate_node_contract(contract_id, node_id, deployment_hash)at call index 22, council/root only. Moves a live node contract to another node in the same farm without cancelling it, so a farmer can empty a machine and power it down without destroying the tenant's contract.It moves the booking, not the workload. The source node deprovisions its copy on its next reconciliation and deletes the disks, so getting the data off first is the caller's job. What survives that cancellation does not is the contract itself — id, billing continuity, payee, reserved IPs — and therefore something to redeploy against.
Refuses
Non-
Createdcontracts, cross-farm moves, either node opted out of v3 billing or under a rent contract, and a destination that is standby, dedicated, or already holds the same deployment hash.Also in here
Both report handlers now skip a stale entry instead of aborting the whole batch. They already did this for a contract that does not exist; a contract that exists on another node was handled the opposite way, aborting and charging. That asymmetry was unreachable until this feature — nothing else leaves a live contract pointing elsewhere.
Docs
docs/architecture/0027-migrate-node-contract.mdfor the reasoning,docs/misc/migrate_node_contract.mdfor the runbook.Tests: 473 passing incl. 19 new unit tests and a council-driven integration case.