[BREAKING CHANGES] Move agreement negotiation off-chain, keep only mutual commitment on-chain#105
Open
danielbui12 wants to merge 24 commits into
Open
[BREAKING CHANGES] Move agreement negotiation off-chain, keep only mutual commitment on-chain#105danielbui12 wants to merge 24 commits into
danielbui12 wants to merge 24 commits into
Conversation
`create_bucket_with_storage` takes an explicit provider account; then the pallet then performs an O(1) lookup of that single provider and re-validates all constraints before opening the agreement
Adding new AgreementTerms type for data signing Adding ReplayWindow and ProviderReplayState to prevent signature replay
Introduce a single-call flow where a provider signs storage terms off-chain and the owner redeems them on-chain, replacing the request/accept dance for primary agreements.
Bucket creation and agreement opening are folded into one atomic extrinsic.
Primitives (`storage-primitives`):
- `AgreementTerms<AccountId, Balance, BlockNumber>`: provider-signed quote carrying owner, max_bytes, duration, price_per_byte, valid_until, nonce.
- `ReplayWindow`: per-provider 256-slot sliding window over signed nonces (`hwm` + 32-byte bitmap, LSB = hwm). `try_accept(nonce)` shifts the bitmap on forward jumps and rejects duplicates (`AlreadyUsed`) or out-of-window pasts (`TooOld`). Covered by 7 unit tests including out-of-order, edge, and large-jump cases.
Pallet (`pallet-storage-provider`):
- `ProviderReplayState` storage map (`AccountId -> ReplayWindow`).
- `establish_storage_agreement` extrinsic + pub `establish_storage_agreement_internal(owner, provider, terms, sig)` helper for Layer 1 reuse. Verifies `MultiSignature` over `blake2_256(SCALE(terms))`, checks `valid_until`, advances the replay window, then runs the existing provider/capacity/stake/duration/price validation before creating the bucket + primary agreement.
- New errors: `InvalidProviderSignature`, `TermsExpired`, `NonceAlreadyUsed`, `NonceTooOld`, `TermsOwnerMismatch`.
- New event: `StorageAgreementEstablished { bucket_id, provider, owner, terms, expires_at }`. Named `Storage*` so a future `establish_replica_sync_agreement` flow can sit alongside.
The legacy `create_bucket_with_storage` extrinsic is left in place for now; it will be removed in a follow-up once callers migrate.
Refactor replica agreement creation to use the same provider-signed terms flow as establish_storage_agreement, eliminating the pending request/accept stage. - recover `replica_params` in `AgreementTerms` - migrate `request_agreement` extrinsic to `establish_replica_agreement`: redeems provider-signed terms against an existing bucket, verifying signature and replay window before opening the agreement atomically. - migrate `request_replica_agreement_internal` to `establish_replica_agreement_internal`: mirrors `establish_storage_agreement_internal` for higher-layer pallets. - Drop the `AgreementRequest` storage and struct, the cleanup_bucket drain loop, the `AgreementRequested`/`AgreementRejected`/`AgreementRequestWithdrawn` events, and the now-unused request-related errors. - Add `ReplicaAgreementEstablished` event and `MissingReplicaTerms` error. The pallets in storage-interfaces/, benchmarks, tests, and client SDK still reference the old names and need a follow-up pass.
Update pallet/src/tests.rs to exercise the establish_storage_agreement / establish_replica_agreement extrinsics that replaced the legacy request/accept flow, and drop create_bucket / create_bucket_with_storage which are no longer exist. Test helpers: - Add sr25519 signing helpers (generate_provider_public_key, sign_terms) that use the runtime keystore registered in mock.rs. - Add primary_terms / replica_terms builders and a register_signing_provider helper for the common setup. And more test cases for new extrinsics & changes.
- Remove benchmarks for deleted extrinsics. - Add establish_storage_agreement and establish_replica_agreement benchmarks covering signature verification + replay-window mutation + bucket / agreement insertion costs. - Update helper functions, other benchmarks regarding new changes.
- Update create_s3_bucket now takes (name, provider, terms, sig) and calls establish_storage_agreement_internal for the Layer 0 bucket + primary agreement atomically. - `create_s3_bucket_with_storage` is removed. - Drop NoProvidersAvailable, AgreementRequestFailed, Layer0BucketCreationFailed errors, and return Layer 0 errors directly. - Update tests following changes
pallet-drive-registry - create_drive is updated following new flow. - allocate_bucket_for_user is removed. - Remove unnecessary code, update tests and benchmarks runtime - drop genesis bucket on Layer 0
- Add client/src/agreement.rs with the AgreementTermsOf mirror type, NegotiateRequest / SignedTerms wire shapes, a hex-bytes MultiSignature serde adapter, and a sign_terms helper that matches the on-chain blake2_256(SCALE(terms)) verification. - AdminClient: replace create_bucket + request_agreement + withdraw_agreement_request + terminate-style request/accept helpers with establish_storage_agreement(provider, terms, sig), which parses the new BucketCreated event to surface the bucket id. - ProviderClient: drop accept_agreement / list_pending_requests / reject_agreement_request; add mock negotiate_terms HTTP client that POSTs to a provider node `/negotiate` endpoint and returns SignedTerms. - Update complete_workflow.rs, and tests to the new flow.
…-node - Add provider-node/src/negotiate.rs: - NonceCounter: atomic monotonic counter persisted to disk on every allocation, can continue with on-chain hwm. - sign_terms() mirrors the on-chain verifier: blake2_256(SCALE(terms)) → sr25519 sign → MultiSignature::Sr25519. - Wire POST negotiate in api.rs: allocates the next nonce, builds AgreementTerms, signs, then returns SignedTerms (error 503 if the node has no signing key). - command.rs: drop start_agreement_coordinator; replace with setup_nonce_counter. - Delete provider-node/src/agreement_coordinator.rs.
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.
Primary Changes
pallet-storage-provider(Layer 0)establish_storage_agreement(provider, terms, sig)extrinsic — atomically verifies provider sig, checks replay window + expiry, creates bucket, opens agreement for primary provider.AgreementTerms (owner, max_bytes, duration, price_per_byte, valid_until, nonce),ProviderReplayStates (hwm + 256-bit bitmap per provider).MultiSignature::verify(blake2_256(SCALE(terms)))against the provider's registered public key.establish_storage_agreement_internalreused bypallet-s3-registry&pallet-drive-registry.storage + related events/errors.
Layer 1
pallet-s3-registry::create_s3_bucketandpallet-drive-registry::create_drivenow take (terms, sig) and call topallet-storage-provider::establish_storage_agreement_internal; removed old & unused code.client/ (Rust SDK)
AgreementTermsOf, andsign_terms()helper.AdminClient::establish_storage_agreement(provider, terms, sig)replaces old flow.ProviderClient::negotiate_terms(url, req)invokes POST/negotiatefromprovider-nodeto negotiate and get provider's signature on agreements.provider-node/
/negotiate→ provider allocates nonce (per request), signs terms, returnsSignedTerms.NonceCounterthat bootstraps from chainhwmon cold start.NonceCounteris used to prevent signature replay attack.Issues
Follow-up TODO:
user-interfaces/following new changes.