Skip to content

[BREAKING CHANGES] Move agreement negotiation off-chain, keep only mutual commitment on-chain#105

Open
danielbui12 wants to merge 24 commits into
devfrom
tung/create_bucket_with_storage_fixes
Open

[BREAKING CHANGES] Move agreement negotiation off-chain, keep only mutual commitment on-chain#105
danielbui12 wants to merge 24 commits into
devfrom
tung/create_bucket_with_storage_fixes

Conversation

@danielbui12
Copy link
Copy Markdown
Contributor

@danielbui12 danielbui12 commented May 29, 2026

Primary Changes

  • pallet-storage-provider (Layer 0)

    • New establish_storage_agreement(provider, terms, sig) extrinsic — atomically verifies provider sig, checks replay window + expiry, creates bucket, opens agreement for primary provider.
    • New types: AgreementTerms (owner, max_bytes, duration, price_per_byte, valid_until, nonce), ProviderReplayStates (hwm + 256-bit bitmap per provider).
    • Sig scheme: MultiSignature::verify(blake2_256(SCALE(terms))) against the provider's registered public key.
    • Internal helper establish_storage_agreement_internal reused by pallet-s3-registry & pallet-drive-registry.
    • Removed: request_primary_agreement, request_replica_agreement, accept_agreement, withdraw/reject_agreement_request, create_bucket, create_bucket_with_storage, plus AgreementRequests
      storage + related events/errors.
    • New errors: InvalidProviderSignature, TermsExpired, NonceAlreadyUsed, NonceTooOld, TermsOwnerMismatch. New event: AgreementEstablished.
  • Layer 1

    • pallet-s3-registry::create_s3_bucket and pallet-drive-registry::create_drive now take (terms, sig) and call to pallet-storage-provider::establish_storage_agreement_internal; removed old & unused code.
  • client/ (Rust SDK)

    • Add new type AgreementTermsOf, and sign_terms() helper.
    • AdminClient::establish_storage_agreement(provider, terms, sig) replaces old flow.
    • ProviderClient::negotiate_terms(url, req) invokes POST /negotiate from provider-node to negotiate and get provider's signature on agreements.
    • Dropped all request/accept/withdraw/reject admin methods.
  • provider-node/

    • New POST /negotiate → provider allocates nonce (per request), signs terms, returns SignedTerms.
    • Introduce NonceCounter that bootstraps from chain hwm on cold start. NonceCounter is used to prevent signature replay attack.
    • Dropped the old request/accept agreement coordinator.

Issues

Follow-up TODO:

  • Rewire tests, examples, CI.
  • Updates client sdk, user-interfaces/ following new changes.
  • Update UI & e2e tests.
  • Update reference docs.
  • ...

`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.
@danielbui12 danielbui12 marked this pull request as ready for review May 29, 2026 10:42
@danielbui12 danielbui12 requested review from bkontur, ilchu and mudigal and removed request for bkontur and mudigal May 29, 2026 10:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Move agreement negotiation off-chain, keep only mutual commitment on-chain

2 participants