From 335842dc641955a8203efb4888086b9926c5ef74 Mon Sep 17 00:00:00 2001 From: Ian Clarke Date: Thu, 13 Aug 2026 22:41:08 -0500 Subject: [PATCH] docs: state must be idempotent commutative monoid, not just commutative The manual pages, FAQ, and slides described contract state merge as only requiring commutativity, but the whitepaper and stdlib trait docs require associativity and idempotence too (state forms an idempotent commutative monoid / join-semilattice). Align wording across the site. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_018gMSXHaQ2rXKGfAVWKqk11 --- hugo-site/content/about/faq/index.md | 4 ++-- hugo-site/content/build/manual/components/contracts.md | 5 +++-- hugo-site/content/build/manual/contract-abi.md | 7 ++++--- .../content/build/manual/further-reading/delta-sync.md | 5 +++-- hugo-site/content/build/manual/tutorial.md | 6 +++--- hugo-site/content/build/manual/upgrading-contracts.md | 9 +++++---- .../slides/hard-problems/decentralized-consistency.html | 2 +- 7 files changed, 21 insertions(+), 17 deletions(-) diff --git a/hugo-site/content/about/faq/index.md b/hugo-site/content/about/faq/index.md index 72dbf59e..fef748e0 100644 --- a/hugo-site/content/about/faq/index.md +++ b/hugo-site/content/about/faq/index.md @@ -170,8 +170,8 @@ values (or "state"). Specifically, they govern: 2. **Modification Rules:** Under what circumstances can the value be modified? A contract might stipulate that any modification must be signed by a specific key. 3. **Efficient Synchronization:** How to efficiently synchronize values between peers? Freenet - ensures eventual consistency by treating values as commutative monoids, allowing updates in any - order while still producing the same result. + ensures eventual consistency by treating values as idempotent commutative monoids, allowing + updates in any order, or applied more than once, while still producing the same result. This unique architectural approach makes Freenet a powerful, general-purpose platform for building decentralized systems that are scalable and interoperable by default. diff --git a/hugo-site/content/build/manual/components/contracts.md b/hugo-site/content/build/manual/components/contracts.md index e8cb9508..82b92657 100644 --- a/hugo-site/content/build/manual/components/contracts.md +++ b/hugo-site/content/build/manual/components/contracts.md @@ -37,9 +37,10 @@ concept similar to As a very simple example, if the contract's state is a single number, then the contract could define the merging of two states as the maximum of the two numbers. -In mathematical terms, a contract defines a +In mathematical terms, a contract defines an idempotent [commutative monoid](https://mathworld.wolfram.com/CommutativeMonoid.html) on the contract's state - -but you can ignore this if you're not a mathematician. +merging is associative, commutative, and applying the same update twice has no extra effect - but +you can ignore this if you're not a mathematician. #### Efficient State Synchronization diff --git a/hugo-site/content/build/manual/contract-abi.md b/hugo-site/content/build/manual/contract-abi.md index 6954051f..d41de3ad 100644 --- a/hugo-site/content/build/manual/contract-abi.md +++ b/hugo-site/content/build/manual/contract-abi.md @@ -146,9 +146,10 @@ design here. Freeing a result before the host reads it is a use-after-free. ## Behavioural requirement -`update_state` must be commutative with respect to deltas. Applying a set of deltas in any order has -to converge on the same state. The network deprioritizes contracts that violate this, so it is a -correctness requirement rather than a style note. See +`update_state` must be associative, commutative, and idempotent with respect to deltas. Applying a +set of deltas in any order — including applying the same delta more than once — has to converge on +the same state. The network deprioritizes contracts that violate this, so it is a correctness +requirement rather than a style note. See [Delta-Sync](/build/manual/further-reading/delta-sync/) for the reasoning. ## Delegates diff --git a/hugo-site/content/build/manual/further-reading/delta-sync.md b/hugo-site/content/build/manual/further-reading/delta-sync.md index d5167b88..4b13dca0 100644 --- a/hugo-site/content/build/manual/further-reading/delta-sync.md +++ b/hugo-site/content/build/manual/further-reading/delta-sync.md @@ -33,8 +33,9 @@ Instead of relying on heavyweight consensus mechanisms, Freenet adopts a (to our In Freenet, every value stored under a given key must be **mergeable**, meaning that different versions can be combined into a consistent state. To ensure consistency, merging must be -order-independent, always producing the same result regardless of the sequence in which states are -combined (a property known as a commutative monoid). Rather than imposing a rigid, universal merge +order-independent and safe to repeat, always producing the same result regardless of the sequence +in which states are combined or whether the same update is applied more than once (a property +known as an idempotent commutative monoid). Rather than imposing a rigid, universal merge strategy, Freenet leverages **WebAssembly (Wasm) contracts** to define custom synchronization rules. Each Wasm contract is authored to specify how data should be merged, allowing synchronization to be tailored to the unique requirements of the application. This flexibility is essential because diff --git a/hugo-site/content/build/manual/tutorial.md b/hugo-site/content/build/manual/tutorial.md index cbc81c61..292318f6 100644 --- a/hugo-site/content/build/manual/tutorial.md +++ b/hugo-site/content/build/manual/tutorial.md @@ -75,10 +75,10 @@ A standard web application that connects to the local Freenet Kernel via WebSock Freenet is a distributed system where peers may receive updates in different orders. Your contract must handle this correctly. -### Commutative Monoids +### Idempotent Commutative Monoids -Contract state must form a **commutative monoid**: updates can be applied in any order and still -produce the same final state. +Contract state must form an **idempotent commutative monoid**: updates can be applied in any +order, and applying the same update more than once, and still produce the same final state. Commutative synchronization between peers diff --git a/hugo-site/content/build/manual/upgrading-contracts.md b/hugo-site/content/build/manual/upgrading-contracts.md index 37e56669..9892a463 100644 --- a/hugo-site/content/build/manual/upgrading-contracts.md +++ b/hugo-site/content/build/manual/upgrading-contracts.md @@ -151,9 +151,10 @@ key. Because anyone can PUT, this is only _safe_ if the following hold. An app t **not** get safe carry-forward, and you must design them in before your first release — you cannot retrofit them onto data that is already live. -- **Mergeable / commutative state.** The new contract must be able to fold the old state into its - own deterministically. In practice this means your state is a commutative monoid — the same - requirement that makes Freenet sync work at all (see +- **Mergeable / commutative / idempotent state.** The new contract must be able to fold the old + state into its own deterministically, including re-folding the same old state more than once + without changing the result. In practice this means your state is an idempotent commutative + monoid — the same requirement that makes Freenet sync work at all (see [Contracts](/build/manual/components/contracts/#state-synchronization-and-merging)). - **Strictly self-authorizing `validate_state`.** The new contract must re-verify _every byte_ it accepts, trusting nothing about who delivered it. Every field in state must be covered by a @@ -247,7 +248,7 @@ Before you publish a new contract or delegate version: `wasm-opt` version is pinned or recorded. - [ ] A CI guard fails the build if the WASM hash changed without the old `code_hash` being added to your legacy registry (`freenet-migrate-build`'s hash-guard, or an equivalent script). -- [ ] State is mergeable/commutative and `validate_state` re-verifies **every** field's signature +- [ ] State is mergeable/commutative/idempotent and `validate_state` re-verifies **every** field's signature (fail closed). - [ ] User-facing identities are derived from keys, never from a contract key. - [ ] Delegates shipped an **export handler in v1**; you have the author signing key to authorize diff --git a/hugo-site/static/slides/hard-problems/decentralized-consistency.html b/hugo-site/static/slides/hard-problems/decentralized-consistency.html index c09aa92c..ca39d869 100644 --- a/hugo-site/static/slides/hard-problems/decentralized-consistency.html +++ b/hugo-site/static/slides/hard-problems/decentralized-consistency.html @@ -15,7 +15,7 @@

Decentralized Consistency

  • Consistency without central authority: the hardest problem in distributed systems
  • Bitcoin context: ~$7–8B/year electricity, ~175 TWh (Cambridge Centre for Alternative Finance), just to agree on who owns what
  • Our approach: state = arbitrary bytes, contract provides merge function
  • -
  • Key property: merge(A,B) = merge(B,A), associative, has identity, aka "commutative monoid"
  • +
  • Key property: merge(A,B) = merge(B,A), associative, has identity, merge(A,A) = A, aka "idempotent commutative monoid"
  • Result: peers receive updates in any order, guaranteed convergence. No leader election, no voting, no proof-of-work
  • Contracts are WASM, with full flexibility in defining state and merge logic