diff --git a/docs/contribute.md b/docs/contribute.md index 7be317a..bf2bd04 100644 --- a/docs/contribute.md +++ b/docs/contribute.md @@ -1,6 +1,6 @@ --- title: Contribute -sidebar_position: 10 +sidebar_position: 13 --- Welcome Contributors! πŸŽ‰ diff --git a/docs/developer-guides/_category_.json b/docs/developer-guides/_category_.json index b34872a..faeeebf 100644 --- a/docs/developer-guides/_category_.json +++ b/docs/developer-guides/_category_.json @@ -1,5 +1,5 @@ { "label": "Developer Guides", - "position": 5, + "position": 6, "collapsed": true } diff --git a/docs/fluentbase-sdk/_category_.json b/docs/fluentbase-sdk/_category_.json index 595c41d..4afb240 100644 --- a/docs/fluentbase-sdk/_category_.json +++ b/docs/fluentbase-sdk/_category_.json @@ -1,5 +1,5 @@ { "label": "Fluentbase SDK", - "position": 4, + "position": 5, "collapsed": true } \ No newline at end of file diff --git a/docs/gblend/_category_.json b/docs/gblend/_category_.json index 2d06bfe..7a72e76 100644 --- a/docs/gblend/_category_.json +++ b/docs/gblend/_category_.json @@ -1,5 +1,5 @@ { "label": "Gblend", - "position": 3, + "position": 4, "collapsed": false } diff --git a/docs/get-started.md b/docs/get-started.md index 088eed1..d6a4ffe 100644 --- a/docs/get-started.md +++ b/docs/get-started.md @@ -38,7 +38,7 @@ The main audience for this documentation are smart contract developers deploying - + Study the Tech Dive deep into rWasm and blended execution architecture. @@ -55,7 +55,7 @@ The main audience for this documentation are smart contract developers deploying Developer Guides Deploy blended apps in minutes. Rust ↔ Solidity made simple. - + Study the Tech Dive deep into rWasm and blended execution architecture. diff --git a/docs/glossary.md b/docs/glossary.md index 75a6d3f..654ddcd 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -1,6 +1,6 @@ --- title: Glossary -sidebar_position: 8 +sidebar_position: 11 --- # Glossary @@ -11,23 +11,63 @@ Fluent's rWasm (reduced WebAssembly) virtual machine (VM) is a versatile VM that This allows for atomically composable apps using distinct programming language(s) and standards on a shared state execution environment. Each supported EE compiles to rWasm for execution, which employs a fully compatible Wasm binary representation optimized for zero-knowledge (zk) operations. +## rWasm + +rWasm (reduced WebAssembly) is Fluent's execution substrate. It is a simplified, deterministic subset of the Wasm binary format, designed so every program running on Fluent β€” from ordinary smart contracts to the runtimes that execute other VMs on top of it β€” can be proven under zero-knowledge without the full complexity of standard Wasm. + +Where standard Wasm is optimized for fast execution in browsers and servers, rWasm is optimized for verifiability. Memory semantics are stricter, trap behaviour is deterministic, and engine-metered fuel replaces ad-hoc gas accounting. EVM bytecode runs under rWasm through a delegated runtime; native Wasm contracts map to it directly; future VM integrations follow the same pattern. + +For most developers rWasm is invisible β€” you write Solidity or Rust, deploy, and the runtime router picks the right execution path. It becomes visible at the edges: when querying raw account data for a proof, when reasoning about fuel versus gas, or when auditing the boundary between runtime and host. See [Architecture Overview](system-architecture/overview.md). + ## The Fluent L2 The Fluent L2 is an Ethereum-centric zk-rollup for Wasm, EVM, and SVM based apps. It supports real-time composability between apps targeting different VMs, and "blended" apps composed of smart contracts mixed and matched between them. Interaction between the different types of contracts on the L2 happens under the hood and is both atomic and happens in real-time. ## The Fluentbase Framework -The Fluentbase framework is used to deploy smart contracts on Fluent as well as blockchains and verifiable compute environments that compile to rWasm. The framework’s execution layer supports arbitrary compute and the emulation of multiple VM targets. +The Fluentbase framework is used to deploy smart contracts on Fluent as well as blockchains and verifiable compute environments that compile to rWasm. The framework's execution layer supports arbitrary compute and the emulation of multiple VM targets. Fluentbase is optimized for proving efficiency and integrates with modular components (sequencers, DA layers, etc.) for the deployment of customizable blended execution networks. +## Ownable Account + +An ownable account is how Fluent attaches execution logic to an account without storing runtime bytecode inside every account that uses it. Every contract on Fluent lives in an account whose code field is a small wrapper carrying a magic header, an `owner_address` pointing to a delegated runtime, and runtime-specific metadata. When the account is called, REVM loads the executable code from the owner, not from the account itself β€” while keeping the original account as the storage target. + +This separation β€” account identity is local, execution logic is delegated β€” is what lets one state machine host EVM, Wasm, and SVM contracts together. A Solidity contract and a Rust contract end up as two ownable accounts pointing at two different delegated runtimes. They share the state trie, can call each other atomically, and the host mediates every privileged operation between them with the same rules. + +Ownership is set at deployment time based on the init code's magic prefix, and it cannot change afterwards β€” the account's execution class is part of its identity. See [Runtime Routing and Ownable Accounts](system-architecture/runtime-routing-and-ownable-accounts.md). + +## Delegated Runtime + +A delegated runtime is the execution code that an ownable account points at. Each supported VM family has its own: the delegated EVM runtime executes EVM bytecode, the delegated Wasm runtime executes Wasm, the Universal Token runtime implements a shared token surface, and future runtimes (like SVM) plug in the same way. + +Delegated runtimes are protocol-owned: their bytecode lives at fixed system addresses, is installed and replaced through a governed upgrade path, and is shared by every account that opts into its execution class. A bug fix or behaviour change in the delegated EVM runtime affects every EVM contract on Fluent at once β€” which is why runtime upgrades are treated as fork-critical change management. + +Delegated runtime addresses are not callable directly as normal contracts; the router blocks that path to keep user flows going through ownable-account semantics. See [Runtime Upgrade](system-architecture/runtime-upgrade.md). + +## Interruption Protocol + +The interruption protocol is the mechanism through which every privileged operation on Fluent is performed. Runtime code cannot touch shared state directly β€” when a contract needs to read storage, emit a log, spawn a nested call, or do anything else that affects state outside its own memory, it yields control to the host. The host performs the operation, validates it against protocol rules, and resumes the runtime from the saved execution point. + +The handshake has two verbs: `exec` starts or resumes a runtime frame with a fuel budget, and `resume` hands control back after a privileged action. A positive exit code from the runtime is a `call_id` β€” a handle into a saved resumable context β€” not a final status. The host uses this protocol to keep consensus-critical rules (ordering, charging, validation) in one place while allowing multiple runtime families to coexist on top. + +See [Interruption and Syscalls](system-architecture/interruption-and-syscalls.md) for the full handshake, syscall surfaces, and safety boundaries. + +## Fuel + +Fuel is Fluent's internal unit of runtime execution accounting. Where gas tracks EVM-visible economics β€” the same unit wallets quote, explorers display, and transactions pay in ETH β€” fuel meters the underlying rWasm work: every runtime step, every syscall, every host operation is charged in fuel. + +Gas and fuel are linked by a fixed deterministic conversion ratio (`FUEL_DENOM_RATE = 20`: each gas unit buys 20 fuel). At the start of a call the host derives a fuel budget from the remaining gas; when the runtime returns, any consumed or refunded fuel is translated back into gas settlement. Rounding behaviour at the conversion boundary is part of consensus correctness β€” every node performs it identically. + +For most smart contract development, fuel is invisible. It matters if you are writing a gas estimator, building a custom runtime, or auditing privileged charging paths. See [Gas and Fuel](system-architecture/gas-and-fuel.md). + ## Virtual Machine (VM) A virtual machine (VM) in the context of blockchains is a sandbox environment that executes smart contracts. Examples include the Ethereum Virtual Machine (EVM) and the Solana Virtual Machine (SVM). ## Execution Environment (EE) -The execution environment (EE) refers to the entire system where blockchain transactions are processed. It encompasses the state transition function (STF) of a protocol, which includes the virtual machine (VM) and additional protocol-specific checks and balances necessary for the network’s operation. +The execution environment (EE) refers to the entire system where blockchain transactions are processed. It encompasses the state transition function (STF) of a protocol, which includes the virtual machine (VM) and additional protocol-specific checks and balances necessary for the network's operation. These checks may involve gas calculations, nonce verification, and balance updates to ensure the proper execution of transactions. @@ -41,6 +81,14 @@ This allows developers to leverage the best features and tools from various VMs Zk-rollups are blockchain-based execution environments that post compressed data to the same onchain data availability network as the one responsible for verifying its cryptographic proofs. Proofs are examined and validated by a "verifier," which cryptographically ensures the integrity of all transactions. +## Preconfirmation + +Preconfirmation is the fast-finality step in Fluent's rollup pipeline. After a sequencer commits a batch and publishes its data to L1, a trusted-execution-environment (TEE) verifier β€” an AWS Nitro enclave whose signing key is cryptographically bound to a specific enclave image via an SP1-verified attestation β€” signs the batch root. This signed batch reaches the Preconfirmed state on the rollup contract well before the challenge window elapses, giving users a rapid execution attestation they can trust operationally. + +Preconfirmation is not the same as finalization. A preconfirmed batch is still challengeable; if a successful challenge proves it wrong, the batch can be reverted. Finalization happens later β€” either after a delay window without unresolved challenges, or immediately once all block commitments have been cryptographically proven. + +This distinction matters for the bridge: L2 β†’ L1 withdrawals from a preconfirmed-but-not-finalized batch enter an optimistic path guarded by a per-token rate cap. Finalized withdrawals are unrestricted. See [Rollup Architecture](system-architecture/rollup-architecture.md). + ## Wasm Wasm (WebAssembly) is a low-level, portable binary format and compilation target for high-level programming languages. General-purpose programming languages, such as Rust, TypeScript, and C++ compile to Wasm. diff --git a/docs/infrastructure/_category_.json b/docs/infrastructure/_category_.json index a40af35..c76a79f 100644 --- a/docs/infrastructure/_category_.json +++ b/docs/infrastructure/_category_.json @@ -1,5 +1,5 @@ { "label": "Infrastructure", - "position": 6, + "position": 7, "collapsed": true } diff --git a/docs/knowledge-base/_category_.json b/docs/knowledge-base/_category_.json index 0fcf2aa..c794c8a 100644 --- a/docs/knowledge-base/_category_.json +++ b/docs/knowledge-base/_category_.json @@ -1,5 +1,5 @@ { "label": "Knowledge Base", - "position": 7, + "position": 8, "collapsed": true } diff --git a/docs/resources.md b/docs/resources.md index 2f7e151..e0cf7c0 100644 --- a/docs/resources.md +++ b/docs/resources.md @@ -1,6 +1,6 @@ --- title: Resources -sidebar_position: 9 +sidebar_position: 12 --- Awesome Fluent Resources --- diff --git a/docs/system-architecture/_category_.json b/docs/system-architecture/_category_.json new file mode 100644 index 0000000..b1bf017 --- /dev/null +++ b/docs/system-architecture/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "System Architecture", + "position": 3, + "collapsed": false +} diff --git a/docs/system-architecture/bridge.md b/docs/system-architecture/bridge.md new file mode 100644 index 0000000..a4038c1 --- /dev/null +++ b/docs/system-architecture/bridge.md @@ -0,0 +1,125 @@ +--- +title: Bridge Architecture +sidebar_position: 10 +--- + +Fluent's bridge is the two-way interface between the L2 and Ethereum. It carries two kinds of traffic under two different trust models: **deposits** (L1 β†’ L2) are optimistic β€” they become spendable on the L2 once a rollup batch has consumed them β€” and **withdrawals** (L2 β†’ L1) are Merkle-proven against the rollup's batch root. The bridge is a family of contracts deployed symmetrically on both chains, layered on top of the [rollup's batch lifecycle](./rollup-architecture.md). + +This page describes the bridge at the protocol level: how a cross-chain message travels, where trust resides, and what stops an adversary from compromising either side. + +## Layered model + +The bridge follows the same three-layer pattern as the rest of the system, deployed symmetrically on each layer. + +![Bridge topology across L1 and L2, showing gateways on top of bridge contracts, with L1FluentBridge tied to the rollup and L2FluentBridge reading L1 oracles. Deposit traffic flows L1 to L2 via the sequencer; withdrawals flow L2 to L1 via Merkle proof against the rollup's batch root.](/img/system-architecture/bridge-topology.svg) + +**Gateways.** Per-asset entry points. `NativeGateway` bridges ETH. `ERC20Gateway` bridges ERC-20 tokens and drives pegged-token deployment on the receiving chain. Gateways wrap the bridge in token-specific deposit and withdraw semantics, consult optional safety registries (`Blacklist`, `FastWithdrawalList`), and validate that inbound messages came from their paired gateway on the other chain. + +**Bridge core.** `FluentBridge` is the shared base; `L1FluentBridge` and `L2FluentBridge` add chain-specific behaviour on top. The core handles message encoding, sequential nonces, per-message status tracking, and the gas-bounded execution of inbound messages via `ExcessivelySafeCall`. Message destinations must be on the bridge's gateway whitelist β€” both on the send path and on the receive path. + +**Settlement integration.** L1FluentBridge owns a FIFO queue of pending L1 β†’ L2 message hashes and a cursor that the rollup's `commitBatch` consumes. It also verifies withdrawals against the rollup's `batchRoot`. L2FluentBridge reads an on-chain `L1BlockOracle` for expiry checks and an `L1GasOracle` for outbound-fee computation. + +## L1 β†’ L2: the deposit lifecycle + +A user calls a gateway on L1 β€” typically `NativeGateway.sendNativeTokens(to)` or the ERC-20 equivalent. The gateway checks the blacklist, computes the bridged amount as `msg.value - bridge fee`, and wraps the destination-side receive call as calldata for the paired L2 gateway. It then invokes `L1FluentBridge.sendMessage{value: msg.value}(otherSideGateway, payload)`. + +The bridge does four things at send time: + +1. Rejects the send if the destination is not on the gateway whitelist (`GatewayNotWhitelisted`). +2. Rejects the send if the rollup is in its corruption state (`RollupCorrupted`) β€” no new deposits enter a paused rollup. +3. Takes the next nonce, computes `validUntilBlockNumber = block.number + receiveMessageDeadline`, hashes the full message, and emits `SentMessage`. +4. Appends the message hash to `_sentMessageHashes[_sentMessageBack++]` and freezes a per-slot processing deadline: `_sentMessageProcessByBlock[slot] = block.number + depositProcessingWindow`. + +Both deadlines β€” the receive expiry committed into the message hash and the per-slot processing window β€” are **frozen at send time**. Admin updates to either window parameter afterwards never retroactively affecting messages already in the queue. Each value is either hashed or stored once and never re-read. The `depositProcessingWindow` is bounded at `MAX_DEPOSIT_PROCESSING_WINDOW = 50_400` blocks (~7 days at 12 s/block) and must be strictly greater than zero. + +The rollup's sequencer commits batches via `Rollup.commitBatch`. That batch bundles the L2 transactions that execute the queued deposits; on L1, the rollup consumes the corresponding hashes via `consumeNextSentMessage` or `advanceSentMessageCursor`. Persistent semantics apply: consumed slots are not deleted β€” only the cursor moves forward. If a later `revertBatches` rewinds the rollup, `rewindSentMessageCursor` moves the bridge cursor backward to match, and the replacement batch re-consumes the same hashes. + +On L2, `RELAYER_ROLE` calls `L2FluentBridge.receiveMessage(...)`. The bridge enforces the next expected `receivedNonce`, reconstructs the message hash, and refuses duplicates. Then it checks the committed `validUntilBlockNumber` against the latest L1 block number read from `L1BlockOracle`. If the deadline has passed, the bridge marks the message `Failed`, emits `RollbackMessage` (which becomes part of the L2 block's `withdrawalRoot`), and returns without executing. Otherwise it forwards the call to the gateway via `ExcessivelySafeCall`, bounded by `executeGasLimit`. On Fluent L2, native ETH for inbound messages is minted by the chain's consensus layer before execution and burned on failure β€” the bridge balance is sufficient by protocol invariant. + +If execution reverts for any other reason β€” gateway bug, recipient contract revert, ERC-20 callback failure β€” the message status becomes `Failed`. Anyone can call `receiveFailedMessage` later to retry, which runs the same flow but with full `gasleft()` instead of the capped limit. The message can transition `Failed β†’ Success` exactly once; it cannot go back to `None`. + +## L2 β†’ L1: the withdrawal lifecycle + +A user calls a gateway on L2. The gateway checks the blacklist and forwards `msg.value` (including the bridge fee) to `L2FluentBridge.sendMessage`. The bridge charges an outbound fee derived from the L1 gas oracle: + +```text +fee = l1GasLimit * ((l1GasPrice * scalar / 1e18) + overhead) +``` + +The fee transfers to the configured `feeTreasury` in a call that happens *after* the message parameters have been snapshotted β€” so a malicious treasury can't observe or influence pre-snapshot state. The message hash is emitted in `SentMessage` and becomes part of the L2 block's `withdrawalRoot`, which is itself committed into the rollup's batch root at the next `commitBatch`. + +Once the originating batch reaches `Preconfirmed` (TEE-signed, Stage C of the [rollup pipeline](./rollup-architecture.md)) or `Finalized`, a relayer calls `L1FluentBridge.receiveMessageWithProof(batchIndex, blockHeader, ..., withdrawalProof, blockProof)`. The bridge runs two Merkle checks: the block header must be a leaf of the batch's `batchRoot`, and the message hash must be a leaf of the block's `withdrawalRoot`. Any failure reverts with `InvalidBlockProof` or `InvalidWithdrawalProof`. + +If the batch is still `Preconfirmed` rather than `Finalized`, the withdrawal enters the **optimistic path**: before releasing funds, the gateway consults the `FastWithdrawalList` rate-cap registry (covered below). If the batch is already `Finalized`, no rate limit applies. + +## Gateways + +A gateway does three things on top of the bridge: + +1. **Owns the token side of the transfer.** Locks on the origin chain, releases or mints on the destination β€” the exact mechanics depend on the asset and whether it uses a pegged or native representation. +2. **Verifies cross-chain origin.** During an in-flight receive, `bridge.getNativeSender()` returns the address that sent the message on the other chain. Gateways require this to match their configured `otherSideGateway` β€” otherwise the receive reverts with `MessageFromWrongGateway`. The value is cleared at the end of the receive, so it can't be observed outside an in-flight call. +3. **Delegates to the optimistic-withdrawal gate.** Every gateway receive calls `_consumeLimit(tokenKey, amount)` before releasing funds. The gate is a no-op unless the withdrawal is optimistic. + +Only the configured local bridge can call a gateway's receive functions (`onlyFluentBridge`). The bridge's `executeGasLimit` caps gas on first delivery; retries via `receiveFailedMessage` run with the caller's full transaction gas. + +Two optional safety registries sit alongside the gateways: + +- **`Blacklist`** is a UUPS-upgradeable denylist with an ERC-7201 storage namespace. Gateways consult it on outbound deposits: if either `msg.sender` or the recipient is blacklisted, the gateway reverts with `AddressBlacklisted`. A separate instance is deployed on each chain; `setBlacklistRegistry(address(0))` disables enforcement per gateway. +- **`FastWithdrawalList`** is the rate-cap registry for optimistic withdrawals, described next. + +## Optimistic withdrawals and FastWithdrawalList + +Preconfirmation gives withdrawals fast user-perceived finality β€” the batch is TEE-signed, the signing key is PCR0-bound via SP1 β€” but the batch is not yet cryptographically finalized. A later challenge can revert it. Releasing arbitrary amounts during the preconfirmation window is economically dangerous; releasing them after finalization is not. + +`FastWithdrawalList` is a per-chain, per-token rate-cap registry. Admin registers tokens with packed-`uint96` hourly and daily limits. The gateway, acting as `CONSUMER_ROLE`, calls `consumeUsage(token, amount)` on every optimistic-path withdrawal. Rolling windows are keyed by `block.timestamp / 1 hours` and `block.timestamp / 1 days` β€” a new window resets the counter for that token. + +Tokens can alias into a shared bucket: e.g. ETH and WETH registered under one canonical key, so an attacker cannot drain the cap twice by exploiting both parallel gateways. The alias is set by admin via `setAlias` and is enforced at consume time. + +The gate in `GatewayBase._consumeLimit` has four states: + +| `whitelistEnabled` | Batch status | Result | +|---|---|---| +| `false` | any | no-op | +| `true` | Finalized or no batch context | no-op | +| `true` | Preconfirmed, token **not** registered | revert `FastWithdrawalNotAllowed` | +| `true` | Preconfirmed, token registered | `consumeUsage` (rate-limited) | + +The "which batch is my withdrawal from" signal uses EIP-1153 transient storage: `L1FluentBridge.receiveMessageWithProof` writes the originating `batchIndex` into `_currentBatchIndex` for the duration of the receive, and `isCurrentBatchPreconfirmed()` reads it. Transient semantics mean the context auto-clears at transaction end and cannot leak into a subsequent call β€” no manual reset, no stale state. + +The `_whitelistEnabled` toggle is structurally tied to the registry address: `setWhitelistEnabled(true)` reverts if `_fastWithdrawalList` is unset, and clearing the registry (`setFastWithdrawalList(address(0))`) reverts while the whitelist is enabled. The "enabled but no list" misconfiguration is unreachable. + +## Safety boundaries + +The bridge has several consensus-grade invariants. Breaking any of them is either a protocol error or a path to fund loss. + +**Frozen per-message deadlines.** `validUntilBlockNumber` and `_sentMessageProcessByBlock[slot]` are snapshotted at send time. Admin updates to `receiveMessageDeadline` or `depositProcessingWindow` never retroactively affect in-flight messages. + +**Deposit liveness signals rollup corruption.** `L1FluentBridge.isOldestUnconsumedExpired()` returns true if the head of the queue missed its processing deadline. The rollup's `isRollupCorrupted()` consults this: if the sequencer stops processing deposits, the rollup halts. + +**Permissionless escape hatch β€” currently pauser-gated.** `skipExpiredDeposits` advances the cursor past expired head slots. It is guarded by `PAUSER_ROLE` in this release and explicitly marked temporary: each skipped slot is a permanently lost deposit until it is replaced by a user-initiated cancel/refund path. The interface comment reads *"TEMPORARY. Each skipped slot represents a permanently lost user deposit until the user-initiated cancel/refund mechanism replaces this function."* + +:::warning +`L1FluentBridge.rollbackMessageWithProof` is **not implemented in this release**. It currently reverts with `"NOT_IMPLEMENTED"`. The full flow (chainId guard, two Merkle proofs, ETH refund) is preserved in git history and will be restored in a future release together with the user-initiated cancel/refund path that replaces `skipExpiredDeposits`. Integrators should not assume L1 β†’ L2 message rollback is available today. +::: + +**Gateway whitelist is part of message authority.** Both `sendMessage` destinations and receive targets must be on the bridge's gateway whitelist. Deregistering a gateway stops further sends and rejects inbound messages targeting it; outbound messages already enqueued are unaffected. + +**Bounded execution.** `ExcessivelySafeCall` caps gas and return-data size on every cross-chain call. No griefing via huge return buffers, no unbounded gas drain. Receive functions use `nonReentrant`, and `to == address(this)` is rejected at both send and receive with `ForbiddenSelfCall` / `InvalidDestinationAddress`. + +**Rollup rebind is queue-safe.** `setRollup` reverts with `QueueNotEmpty` if the sent-message queue is non-empty. You cannot point the bridge at a new rollup while deposits are pending β€” the new rollup would have no knowledge of them. + +**One-shot message status.** Each message hash has exactly one terminal outcome per direction. `Failed β†’ Success` is allowed (via `receiveFailedMessage`); `Success β†’ anything` is not. Duplicate receive attempts revert with `MessageAlreadyReceived`. + +## Roles and operational expectations + +- **`DEFAULT_ADMIN_ROLE`** configures the rollup binding, oracles, gas price config, window parameters, and the gateway whitelist on the bridge. +- **`PAUSER_ROLE`** can pause or unpause the bridge and call `skipExpiredDeposits` on L1. +- **`RELAYER_ROLE`** is the only role allowed to call `receiveMessage` (L2) and `receiveMessageWithProof` (L1). It is not required on the send path β€” user sends are permissionless through the gateway. +- **Gateways** have their own `Ownable2Step` owners for per-gateway config (blacklist, fast list, remote pairing, bridge address). + +A few practical notes for operators: + +- `L1BlockOracle` and `L1GasOracle` are liveness dependencies of the L2 bridge. Stale oracles break expiry checks (risk of stranded or prematurely expired messages) and fee calculations. Monitor their freshness. +- `feeTreasury` must accept plain ETH transfers. The L2 outbound fee transfer uses a bare `call` β€” if the treasury address reverts on receive, `sendMessage` reverts with `FailedToDeductFee` and the user cannot bridge. +- Rotate `RELAYER_ROLE` through the same operational process as the sequencer key. A compromised relayer cannot forge messages (the hash and proofs are public), but it can censor delivery order on L2 by stalling `receiveMessage`. +- UUPS upgrades on the bridges, gateways, and safety registries are consensus-grade in the same sense as runtime upgrades (see [Runtime Upgrade](./runtime-upgrade.md)): deterministic artifacts, multisig authority, and coherent rollout. diff --git a/docs/system-architecture/execution-model.md b/docs/system-architecture/execution-model.md new file mode 100644 index 0000000..802a5f5 --- /dev/null +++ b/docs/system-architecture/execution-model.md @@ -0,0 +1,67 @@ +--- +title: Execution Model +sidebar_position: 2 +--- + +Fluent doesn't execute every contract with a single uniform engine. A transaction routes through REVM, REVM picks the runtime that should run the logic, and from that point REVM coordinates every state change that runtime makes. That's how EVM, Wasm, the Universal Token runtime, and future additions like SVM all live behind one commit model. + +This page walks through what that looks like during a normal call. + +## The components in play + +Five pieces of the execution layer do the heavy lifting inside a running node: + +- **REVM integration layer** β€” frame setup, the journal of tentative state changes, and the host side of every syscall. +- **Runtime executor** β€” runs rWasm modules in either **contract mode** (isolated, strict bounds, user contracts) or **system mode** (cached compiled executors, structured outputs, protocol-owned runtimes) and tracks the resumable context interruption uses. +- **Interruptible EVM runtime** β€” the delegated runtime contract that executes EVM bytecode inside Fluent, itself running under rWasm. +- **SDK and runtime-context layer** β€” contract-facing APIs and the structured envelope handling that system runtimes use to report side effects back to the host. +- **Shared types and constants** β€” syscall indexes, address maps, runtime limits, gas and fuel constants, wire structs. These define the protocol-level contract between runtime and host. + +Every concrete behavior on this page comes out of how those pieces interact. The other pages in this section zoom in on each one. + +## The normal call lifecycle + +A transaction lands on the node, REVM invokes the runtime, and the flow goes: + +![Sequence diagram showing call / create from User to REVM, invoke into the rWasm Runtime, and the two possible return paths: final result with journal commit, or interruption with host action and runtime resume.](/img/system-architecture/call-lifecycle.svg) + +1. REVM prepares the frame: input bytes, caller, value, context flags, a fuel budget derived from remaining gas. +2. It invokes the runtime with that input and fuel limit. +3. The runtime returns either a final result or an interruption request. The distinction is in the exit code: `<= 0` is a final status (success, revert, or an error class); `> 0` is an interruption, and its numeric value is the runtime's `call_id` β€” a handle into a saved execution context. +4. On a final result, REVM maps the exit code into an instruction result and applies the journal. +5. On an interruption, the host performs the requested operation β€” a storage read, a nested call, a metadata update, whatever the runtime asked for β€” then resumes the runtime with the answer, the fuel accounting delta, and any returned data. +6. The journal commits only when a frame completes successfully. + +Step 3 is the choke point. Every privileged operation in the system funnels through the same protocol, and that's what lets one state machine host multiple runtimes safely: each runtime is a deterministic function that yields to the host for anything it shouldn't do on its own. + +## Two execution modes + +Not every runtime is treated the same. The executor runs in one of two modes, and the choice affects everything from how fuel is metered to how side effects are transported. + +**Contract mode** runs untrusted user contracts. The execution context is isolated, all bounds and fuel are strictly enforced, and nothing about the call assumes privilege. Every ordinary Solidity or Rust contract takes this path. + +**System mode** is reserved for the small set of runtimes the protocol itself ships: the delegated EVM runtime, the delegated Wasm runtime, the Universal Token runtime, the runtime-upgrade precompile, the fee manager, the bridge. These get cached compiled executors (the runtime stays hot, not recompiled per call) and produce **structured output envelopes** instead of opaque return buffers. + +Mode selection is address-based: if the callee belongs to the system-runtime set defined in shared constants, the executor runs in system mode. Otherwise, contract mode. + +## Structured envelopes + +System runtimes need to say more than "here are my return bytes." One system call might need to report storage diffs, emitted logs, metadata transitions, and the outcome of a nested frame β€” all in a form the host can apply deterministically. The envelope contract is what gets that across the runtime-host boundary without ambiguity. + +There are three envelope shapes, one per lifecycle point: + +- **New-frame input envelope** β€” how a system runtime describes a new frame it wants the host to create (target, value, input, call kind). +- **Interruption outcome envelope** β€” the payload the host produces for the runtime to consume after a privileged action. +- **Final execution outcome envelope** β€” what a completed system call produces: return value, storage diff, logs, metadata updates, and the frame's final status. + +Contract-mode calls don't use envelopes. Their return path is a plain bytes buffer; state changes are journal entries the host writes during interruption handling. + +:::info +Envelope decoding is part of the consensus surface. A malformed envelope or a misinterpreted field can commit wrong side effects. Changing envelope shapes is a protocol change, not a refactor. +::: + +## The address map is part of consensus + +One subtlety: the set of addresses that triggers system mode is fixed in shared constants. That set includes the delegated runtime owners for each supported VM family (EVM, Wasm, SVM, Universal Token) and the protocol-owned contracts that run under privilege β€” runtime upgrade, fee manager, bridge, and so on. + +Changing this map changes routing. Adding an address pulls a new runtime into the privileged set; removing one breaks every deployment that relied on it. That's why the address map is versioned at the protocol level and never modified as an incidental change. diff --git a/docs/system-architecture/gas-and-fuel.md b/docs/system-architecture/gas-and-fuel.md new file mode 100644 index 0000000..afecb54 --- /dev/null +++ b/docs/system-architecture/gas-and-fuel.md @@ -0,0 +1,79 @@ +--- +title: Gas and Fuel +sidebar_position: 5 +--- + +Fluent charges work in two accounting units. **Gas** is what users pay with β€” the same EVM-visible unit wallets quote, explorers display, and transactions settle in ETH. **Fuel** is what the rWasm runtime consumes while executing. Every runtime step is metered in fuel; every transaction is paid in gas; a fixed deterministic conversion links them. + +If you're writing tooling that estimates costs, building a custom runtime, or auditing gas charging on privileged paths, this split matters. For ordinary contract development it's invisible. + +## Why two units + +Runtime execution, host operations, and EVM interpretation all need one shared accounting model. Gas alone doesn't work β€” it was designed around EVM opcodes, and Fluent runs more than the EVM. Fuel is the engine-level unit every runtime shares. Gas stays as the user-facing economic unit Ethereum-compatible tooling expects. + +One conversion ratio keeps them in lockstep. Anything a user pays gas for translates into a fuel budget the runtime consumes, and any fuel the runtime returns to the host translates back into gas settlement. + +## The conversion ratio + +The conversion is a fixed protocol constant: + +```text +FUEL_DENOM_RATE = 20 +``` + +Each unit of gas is worth 20 units of fuel. The runtime fuel limit for a call is derived from whatever gas is available when the call starts; any consumed or refunded fuel converts back into gas when the runtime returns or yields. Rounding at the conversion boundary is deterministic β€” every node performs it identically β€” because any divergence here is consensus-splitting. + +:::info +Changing `FUEL_DENOM_RATE` or the rounding rules at the conversion boundary is a fork-level change. Gas and fuel conversion is part of consensus correctness, not a tuning knob. +::: + +## How settlement works + +Inside a normal call or resume cycle, the host goes through four steps: + +1. Compute the runtime fuel limit from the gas remaining in the frame. +2. Invoke the runtime with that limit. +3. Receive back the fuel consumed and any fuel refunded. +4. Convert the deltas into gas and apply them to the interpreter's gas state. + +That happens on every runtime invocation and every resume. If the runtime doesn't consume its full budget, leftover fuel is refunded as gas. If it runs out of fuel mid-execution, the call aborts with an out-of-gas-class error. + +## Keeping the delegated EVM runtime in sync + +The delegated EVM runtime runs under rWasm, which creates a subtle accounting risk: the EVM runtime tracks committed gas locally for EVM-visible gas semantics, while the host tracks fuel consumed at the rWasm level. If those two diverge, user-visible gas usage stops matching what the runtime actually did. + +To prevent that, the delegated EVM runtime syncs its local committed-gas delta back to host-level fuel before every interruption and before every final return. The sync happens at well-defined boundaries so no EVM operation can hide gas usage by yielding before its gas is committed. + +## Import-level fuel schedules + +Every runtime import carries an explicit fuel formula β€” a charging procedure attached to the syscall index at compile or translation time. The formula shape depends on the operation: + +- **Constant.** Some state and control calls have a fixed cost. One charge per invocation, regardless of data size. +- **Linear in data size.** Copy, hash, and log operations scale with the bytes they touch. The per-byte rate is part of the import's fuel schedule. +- **Quadratic.** A few operations, notably `exec`, use a quadratic policy that reflects the work they trigger downstream. + +These formulas aren't optimization heuristics. They're part of the runtime's ABI: a contract compiled for Fluent expects specific charges on specific operations, and changing a formula changes the cost semantics of every existing contract that uses that import. + +## Engine-metered vs self-metered runtimes + +Not every system runtime meters fuel the same way. + +**Self-metered runtimes** charge fuel explicitly in their code. Every operation that costs fuel has a matching charge call, and the runtime does its own bookkeeping. + +**Engine-metered runtimes** let the execution engine meter configured precompiles automatically. The runtime doesn't charge itself; the engine inserts fuel accounting at compilation time. + +The Universal Token runtime is currently in the engine-metered set. This is a per-runtime policy decision, not a global behavior β€” which runtimes are engine-metered is part of the protocol's runtime classification and is versioned accordingly. + +## Calldata surcharge + +Large calldata payloads attract a quadratic surcharge above a threshold. The reason is practical block-data pressure control: without the surcharge, it's cheap to flood a block with enormous calldata that other users then pay to store and process. + +This is block economics, not runtime internals. It shows up in transaction cost estimation and in any tooling that predicts gas for data-heavy transactions. + +## Operational invariants + +A few rules the host enforces at every syscall entry: + +- **Never allocate large host buffers before bounding length.** Untrusted lengths are validated first; only then is memory allocated. Otherwise an untrusted caller can make the host allocate unbounded memory before any gas is charged. +- **Charge before expensive host work where feasible.** If a host operation is costly, its fuel is debited before the operation runs, not after. +- **Treat conversion and rounding as consensus surface.** No change to conversion, rounding, or charging order ships as a silent improvement. These are fork-level coordination events. diff --git a/docs/system-architecture/interruption-and-syscalls.md b/docs/system-architecture/interruption-and-syscalls.md new file mode 100644 index 0000000..535a64b --- /dev/null +++ b/docs/system-architecture/interruption-and-syscalls.md @@ -0,0 +1,113 @@ +--- +title: Interruption and Syscalls +sidebar_position: 4 +--- + +Runtime execution on Fluent isn't a single uninterrupted run. When a contract needs to read storage, emit an event, create a nested call, or touch shared state in any way, it doesn't do it. It yields back to the host, the host performs the operation, and the runtime resumes from where it stopped. That pattern β€” the **interruption protocol** β€” is how every privileged operation on Fluent is performed. + +This page covers the protocol itself and the two syscall surfaces layered on top of it. + +## The `exec` / `resume` handshake + +From the host's side, running a runtime frame is a deterministic handshake: + +1. The host calls `exec` with the runtime's input and a fuel budget. +2. The runtime executes until it either finishes or needs something. +3. If it needs something, it yields an interruption request. +4. The host performs the requested operation. +5. The host calls `resume` with the result, fuel accounting, and any returned data. +6. The runtime picks up from the saved point. + +Steps 2 through 5 repeat until the runtime returns a final result. There's no other path for a runtime to affect state or interact with the rest of the system. + +## How a yield is signalled + +The runtime's exit code is overloaded by protocol convention: + +- **`exit_code <= 0`** β€” the runtime is done. The value is a final status: success, revert, or a specific error class. Return bytes are the final output. +- **`exit_code > 0`** β€” the runtime is yielding. The value is a `call_id`, a transaction-scoped handle pointing at a saved execution context. Return bytes carry the encoded parameters of the syscall being requested. + +One exit integer carrying both "here is my result" and "here is my interruption" is economical, and it's also consensus-critical. Treating a positive exit as a final status would commit whatever's in the runtime's return buffer as if it were real output. That failure mode is called out in the [security invariants](./security-invariants.md). + +## The interruption payload + +When a runtime yields, the host decodes a payload containing: + +- the `call_id` identifying the saved context, +- the syscall parameters (syscall id, input byte range, fuel available, static-context flags), +- a gas snapshot for deterministic settlement on resume. + +The host uses `call_id` to find the saved context to resume later, validates the syscall parameters, and routes the syscall id into the host handler for that operation. + +## How the host handles an interruption + +Every interruption runs through the same sequence on the host side: + +1. Read the syscall input from the runtime's memory at the declared byte range. +2. Validate input lengths and state-context constraints. Reject oversized reads, malformed payloads, and mutating operations invoked from static context. +3. Charge gas according to the operation's fuel procedure. +4. Execute the host operation. Simple calls (hash, storage read) are immediate; compound operations (`CALL`, `CREATE`) spin up a new frame. +5. Return the immediate result, or β€” for frame-creating operations β€” wait for the nested frame to complete. +6. Store the interruption outcome for the resume phase to hand back to the runtime. + +Every step in this sequence is deterministic across nodes. Same inputs produce the same outputs, the same errors, and the same gas charges everywhere. Anything less would make the syscall a consensus-splitting surface. + +## The resume path + +After the host operation finishes, the runtime resumes with: + +- its `call_id` so the executor picks the right saved context, +- a mapped exit code translating the host action's outcome into a runtime-visible status, +- the returned data buffer, +- the consumed or refunded fuel, +- optionally a pointer at which the runtime wants fuel accounting written as a tuple. + +The runtime continues from the interrupted instruction, consumes or ignores the returned data, and either finishes or yields again. + +## Two syscall layers + +The interruption protocol has two sides, and they're not the same API. + +### Layer A β€” the runtime import layer + +The public import namespace exposed to runtime code is `fluentbase_v1preview`. This is what a contract compiled for Fluent sees as available imports: + +- input and output helpers, +- state selectors (deploy vs main entry, context queries), +- `exec` and `resume` themselves, +- fuel APIs for self-metered paths, +- hash and crypto builtins. + +Each import is bound to a syscall index and a fuel procedure at compile or translation time. Fuel formulas follow predictable shapes β€” constant, linear in data size, quadratic where appropriate β€” so every operation has a known cost up front, not one determined at runtime. + +The import table is part of protocol behavior. Changing it touches every contract that imports from it and every tool that produces compiled runtimes. + +### Layer B β€” the host interruption syscall IDs + +When an interruption arrives, the host routes it through its own handler set, indexed by `SYSCALL_ID_*` constants. These aren't exposed to contracts. They're the protocol-level operations the host knows how to perform: + +- storage, transient storage, and block-level access, +- call, create, and destroy flows, +- code, balance, and account queries, +- metadata ownership and metadata storage operations, +- the runtime-upgrade governance syscall. + +Layer A describes what a runtime can *ask for*. Layer B describes what the host actually *does*. They evolve together β€” change one side without the other and the protocol drifts. + +## Transaction-scoped context IDs + +Every `call_id` is transaction-scoped. Resumable contexts are created when a runtime frame starts, retained across interruptions within that frame, and forgotten when the transaction finalizes. Per-transaction reset clears recovery state and counters so no context leaks between independent flows. + +A few guarantees follow: + +- `call_id` values from one transaction aren't valid in another. +- A context resumes with the exact state it yielded, not a fresh one. +- Resume is root-only in the current runtime flow: nested user code can't call `resume` directly. Only the host drives resume, and only for the `call_id` the host is currently servicing. + +Protocol correctness depends on all three holding. Violations show up as call-id confusion or state leakage across frames β€” both enumerated explicitly in the [security invariants](./security-invariants.md). + +## System-runtime envelopes + +One more protocol surface lives on top of interruption, specific to system-mode runtimes: the structured envelopes introduced in the [execution model](./execution-model.md). When a system runtime yields or finalizes, its payload isn't an opaque return buffer β€” it's an envelope that explicitly carries return data, storage diffs, emitted logs, metadata updates, and frame outcomes. + +The host decodes the envelope and applies each piece deterministically. Without the envelope contract, the host would have to reconstruct side effects from ad-hoc return bytes β€” exactly the parser-driven ambiguity consensus-critical code should not have. diff --git a/docs/system-architecture/overview.md b/docs/system-architecture/overview.md new file mode 100644 index 0000000..bd66bfc --- /dev/null +++ b/docs/system-architecture/overview.md @@ -0,0 +1,45 @@ +--- +title: Architecture Overview +sidebar_position: 1 +--- + +Fluent is an Ethereum-aligned L2 that runs EVM, Wasm, and (soon) SVM contracts on a single shared state machine. This section skips the pitch for blended execution β€” [Blended 101](../knowledge-base/blended-101.md) covers that β€” and describes what the system actually looks like once a transaction lands on a node: who runs the code, where state lives, how privileged operations are gated, and how effects get committed. + +## Three layers + +A Fluent node has three cooperating layers, and most of the interesting engineering lives at their boundaries. + +![Three cooperating layers of a Fluent node: Node/Consensus Shell, Execution Coordination, and Runtime Execution, with call/commit flow up and exec/interruption flow down.](/img/system-architecture/three-layers.svg) + +**Node and consensus shell.** A modified [Reth](https://github.com/paradigmxyz/reth) stack handles networking, the mempool, block and transaction pipelines, and every JSON-RPC endpoint a wallet or indexer would expect. To an external client, a Fluent node looks like an Ethereum execution client β€” for most RPC calls, it behaves like one. + +**Execution coordination.** REVM plus its host handlers. This layer owns frame lifecycle (how a call's context is set up, nested, and torn down), the journal that records tentative state changes, and the syscall boundary where the runtime asks the host for things it cannot do itself. Every consensus-critical commit path lives here. + +**Runtime execution.** Contract code runs under Fluent's rWasm-centered executor in one of two modes: **contract mode** for untrusted user code (isolated, strict bounds, strict fuel), and **system mode** for the protocol's own delegated runtimes β€” EVM, Wasm, SVM, Universal Token. Both compile to the same substrate. The difference is how tightly bounded each mode is, and how deeply it hooks into the host. + +## Why execution and commit are split + +Running code and committing its effects are deliberately separate steps. A runtime executes until it needs something it cannot do β€” touch shared state, read another account, spawn a nested call β€” and then it yields. The host takes over, validates the request, performs the operation, and hands control back with a result. + +That split is why one chain can safely host multiple execution environments. The environments never mutate state directly; they speak to the host over a fixed protocol. The host is the only place consensus rules are enforced, and every runtime is an isolated consumer of that service. + +:::info +The yield-and-resume mechanism is called the **interruption protocol**. Every privileged operation on Fluent flows through it. Details in [Interruption and Syscalls](./interruption-and-syscalls.md). +::: + +## What rWasm brings to the picture + +rWasm β€” reduced WebAssembly β€” is Fluent's execution substrate. It's a Wasm-derived bytecode optimized for zero-knowledge proving, with deterministic semantics and engine-metered fuel. Wasm contracts map to it directly. EVM bytecode runs under a delegated EVM runtime that itself runs on rWasm. SVM ELF payloads go through their own delegated runtime. Everything converges on one proving surface. + +Day to day, app developers don't see this. You write Solidity or Rust, you deploy, and the runtime router picks the right execution path based on your init code. rWasm becomes visible at the edges: when a Solidity contract calls a Rust contract atomically, when you query raw account data for a proof, or when you notice that gas accounting has a second unit called fuel sitting underneath it. + +## What this section covers + +- [Execution Model](./execution-model.md) β€” normal call lifecycle, contract vs system modes, and the structured envelopes system runtimes use to hand state changes to the host. +- [Runtime Routing and Ownable Accounts](./runtime-routing-and-ownable-accounts.md) β€” how one state machine hosts many execution environments without duplicating runtime logic per account. +- [Interruption and Syscalls](./interruption-and-syscalls.md) β€” the `exec` / `resume` handshake and the two syscall surfaces on top of it. +- [Gas and Fuel](./gas-and-fuel.md) β€” why Fluent has two metering units and how they settle against each other. +- [State and RPC Compatibility](./state-and-rpc-compatibility.md) β€” shared state, ownable-account wrapping, and the two RPC views the node exposes. +- [Runtime Upgrade](./runtime-upgrade.md) β€” how privileged runtime bytecode is replaced, and what stops anyone else from doing it. +- [Security Invariants](./security-invariants.md) β€” the consensus-critical boundaries that hold the system together. +- [Rollup Architecture](./rollup-architecture.md) β€” how Fluent batches, commits, and settles to Ethereum. diff --git a/docs/system-architecture/rollup-architecture.md b/docs/system-architecture/rollup-architecture.md new file mode 100644 index 0000000..9db137a --- /dev/null +++ b/docs/system-architecture/rollup-architecture.md @@ -0,0 +1,129 @@ +--- +title: Rollup Architecture +sidebar_position: 9 +--- + +Fluent is an Ethereum-aligned L2 rollup. Every block produced on Fluent eventually settles to Ethereum under a cryptographic integrity story, and the way that story is composed β€” fast preconfirmation plus slow cryptographic adjudication β€” is what makes the chain usable and safe at the same time. + +This page describes the verification pipeline at the protocol level: how batches are committed, how data is made available, how execution is preconfirmed, how disputes are resolved, and how the system halts itself when something breaks. Running a node isn't covered here; see the node runbook in the upstream `fluentbase/docs`. + +## Shared state, execution-agnostic settlement + +Blended execution β€” EVM, Wasm, and (soon) SVM contracts sharing one state machine β€” is documented in [Blended 101](../knowledge-base/blended-101.md). What matters for settlement is that Fluent verifies rollup commitments over **block headers and data roots**, not over VM-specific execution traces. Adding a new execution environment doesn't change what the rollup proves; it changes what fits into a block the rollup already knows how to settle. + +Each batch is a sequential record identified by a root, a block span, a declared block count, an expected blob count, and timing windows for each phase. Verification parameters are frozen per batch at commit time, so retroactive governance edits can't change the security conditions of an in-flight batch. + +## Not pure optimistic, not pure validity + +Two well-known models sit on either side of what Fluent does. + +**Optimistic rollups** accept state transitions on the assumption that they're correct and rely on economic challenges to catch faults within a dispute window. They're cheap and fast in the happy path, but the dispute window dominates user-perceived finality. + +**Validity (ZK) rollups** require a succinct proof for every state transition before accepting it. Security is purely cryptographic at the transition level, but proving cost and latency are non-trivial, and prover decentralization is a hard open problem. + +Fluent is an **optimistic-ZK hybrid**. Commitments and data publication are fast. A TEE-based preconfirmation gives users rapid execution attestations. Challenges are economically bonded and resolved with SP1-backed proofs. Finalization has two modes: delay-based by default, proof-gated when block commitments are already proven. Users experience optimistic throughput; adversarial operation gets cryptographic adjudication. + +## The five-stage verification pipeline + +![Five-stage rollup verification pipeline: commitBatch, submitBlobs, preconfirmBatch, then finalizeBatches on the happy path; if disputed, challenge contracts resolve via SP1 proof into finalizeWithProofs, or the chain halts under rollupCorrupted and revertBatches.](/img/system-architecture/rollup-pipeline.svg) + +### Stage A β€” Batch commitment + +The sequencer commits a batch by calling `commitBatch` with: + +- the batch root, +- block-span continuity β€” `fromBlockHash` of the first block and `toBlockHash` of the last, +- the declared number of blocks, +- the expected blob count, +- deposit-consumption metadata. + +The contract enforces continuity across batches: the previous batch's `toBlockHash` must match the new batch's `fromBlockHash`. It records the block at which the commit happened, snapshots all timing windows in effect, and anchors the bridge sent-message cursor (`sentMessageCursorStart`) so an emergency revert has a deterministic rollback target. + +### Stage B β€” Blob publication and DA binding + +`submitBlobs` records EIP-4844 versioned blob hashes using the `blobhash` opcode. Blobs can be posted incrementally, but the batch only transitions from **Committed** to **Submitted** when the total submitted hash count equals the `expectedBlobs` value declared at commit time. + +The effect is a strong data-availability binding: on-chain adjudication is keyed to immutable blob hashes. Compression and serialization happen off-chain, but every downstream step β€” preconfirmation, challenge, resolution β€” is parameterized by the exact blob hash vector stored on-chain. Data published to the L1 blob store is what the protocol adjudicates over, and nothing else. + +### Stage C β€” TEE preconfirmation + +`preconfirmBatch` accepts a signature over `(chain id, verifier contract, batch root, blob hash list)` from a whitelisted AWS Nitro enclave. The Nitro verifier contract runs a two-phase filter on admitted signing keys: + +- **Attestation phase.** The enclave-derived public key is admitted only after an SP1 proof verifies the enclave's attestation. Public outputs of that proof include the pubkey and an attestation timestamp, and a bounded freshness window stops stale attestations from being replayed. +- **Batch-signature phase.** Only attested public keys are allowed to authorize batch signatures. The whitelist is maintained by governance; keys can be rotated or revoked. + +Fluent doesn't accept an arbitrary attester key. A key has to pass attestation verification before it's admitted, and the attestation is cryptographically bound to the expected enclave image measurement (PCR0) via the SP1 proof. + +### PCR0-bound key verification + +A critical detail: the enclave's signing identity isn't trusted on submission. The attestation pipeline verifies a statement whose public outputs include the enclave-derived pubkey and the attestation timestamp, and the SP1 proof is checked against the attestation program key before the pubkey is admitted for batch-signature checks. The sequence: + +1. The enclave session generates a signing identity. +2. Attestation evidence binds that identity to the expected enclave measurement context. +3. SP1 verification validates the attestation statement on-chain. +4. Only then is the pubkey accepted for batch-signature use. + +If an enclave image is modified outside the expected measurement, the attestation proof fails validation under the configured verification key, and the signer is never admitted. Preconfirmation signatures are grounded in a measured enclave context, not in an arbitrary off-chain key registration. + +### Stage D β€” Challenge and ZK resolution + +Fluent exposes two dispute objects: + +- `challengeBatchRoot` β€” disputes the batch root itself. +- `challengeBlock` β€” disputes a specific block inside a batch. + +Both require the exact challenger deposit and must arrive within challenge-window deadlines derived from the per-batch snapshots recorded at commit time. A challenged batch transitions to **Challenged**. For block-level disputes, commitments are verified against the committed batch Merkle root; for batch-root disputes, linkage to the previous batch's tail block is checked. + +Resolution uses proof-backed validation: + +- `resolveBlockChallenge` verifies the SP1 proof against the challenged block, its header, and the batch's blob hash context. +- `resolveBatchRootChallenge` verifies block-header chain consistency and recomputed batch-root agreement. + +Economic flows are explicit: when a prover successfully resolves a challenge, the challenger's deposit transfers to the prover. In emergency-revert paths, challengers can be refunded with configured incentive fees. + +:::info +Challenge initiation is currently role-gated β€” only specific operational participants can open disputes. This is a temporary trust configuration. The target end-state is permissionless challenge access where any qualified participant can trigger dispute resolution under the same proof rules. +::: + +### Stage E β€” Finalization modes + +Two finalization paths exist, and which one applies depends on what's happened to the batch: + +- **`finalizeBatches`** (delay-based) β€” the default. A batch finalizes once preconfirmation is done and the configured `finalizationDelay` has elapsed without an unresolved challenge. +- **`finalizeWithProofs`** (proof-gated) β€” accelerated. A batch can finalize as soon as all of its block commitments have been cryptographically proven, without waiting for the delay. + +Normal operation is throughput-oriented via delay-based finalization; adversarial operation is proof-oriented via proof-gated acceleration. Nothing requires every block to carry a proof up front. Proofs are produced when they're needed β€” to resolve disputes or to skip the delay window. + +## Corruption detection and safety halt + +Fluent treats certain protocol violations as reasons to stop making forward progress. The `_rollupCorrupted` state is a first-class safety gate, and it fires when either: + +- the bridge's deposit-liveness indicator shows the oldest unconsumed message has expired, or +- the oldest non-finalized batch exceeds the deadline of its current phase (blob submission, preconfirmation, or challenge resolution). + +Once corrupted, privileged emergency flow can call `revertBatches` to undo non-finalized batches, rewind the bridge consumption cursor, clean challenge and proof state, and re-open safe progress from a deterministic index. The design explicitly favors safety over liveness: if invariants have been violated, the chain halts state-changing progress until operators intervene. + +## Roles and trust model + +Fluent's rollup is operated by a set of explicit roles, each with a scoped responsibility: + +- `SEQUENCER` β€” orders transactions and commits batches. +- `PRECONFIRMATION` β€” produces TEE-backed preconfirmation signatures. +- `CHALLENGER` β€” initiates disputes (currently role-gated; target end-state is permissionless). +- `PROVER` β€” produces SP1 proofs to resolve disputes and to gate fast finalization. +- `EMERGENCY` β€” can trigger revert flows under the corruption conditions above. +- `admin` / upgrader β€” governs the contract set itself. + +"No centralized override over the state transition function" is not the same as "zero trust." Fluent reduces unilateral-override risk by combining immutable batch and data commitments, bonded adversarial participation in challenges, cryptographic proof verification for disputed transitions, and explicit role separation β€” but governance and role-based trust in upgrade and emergency controls remain part of the model. The accurate framing is **structured, compartmentalized trust with cryptographic fault containment**, not trustlessness. + +## Economic framing + +The pipeline is designed to exploit cheap data availability (EIP-4844 blobs) while keeping dispute-grade verification available on demand. In steady state, marginal transaction cost is low because expensive proof generation is shifted to adversarial or accelerated paths rather than required for every block up front. + +From a systems perspective, Fluent aims for a Pareto surface: + +- **optimistic throughput and low UX latency** in normal operation, +- **cryptographic recoverability and challenge enforceability** under fault, +- **deterministic rollback** when safety invariants are violated. + +For users, this is a rollup that feels fast in the happy path and audits cleanly under pressure. For protocol engineers, it's a template for composing TEE liveness with ZK correctness without collapsing into pure trust on one side or pure proving on the other. diff --git a/docs/system-architecture/runtime-routing-and-ownable-accounts.md b/docs/system-architecture/runtime-routing-and-ownable-accounts.md new file mode 100644 index 0000000..2aa9086 --- /dev/null +++ b/docs/system-architecture/runtime-routing-and-ownable-accounts.md @@ -0,0 +1,84 @@ +--- +title: Runtime Routing and Ownable Accounts +sidebar_position: 3 +--- + +Fluent hosts multiple execution environments on one state machine without duplicating runtime logic for every account. It does that by separating two things most chains conflate: **who owns the state** and **which engine runs the code**. An account always owns its storage, but its executable behavior is delegated to a runtime picked at deployment. + +This routing mechanism β€” ownable accounts β€” is what makes cross-VM composability work. A Solidity contract and a Rust contract end up in the same state trie, each with isolated storage, calling each other atomically, but each executed by the runtime that knows how to interpret its bytecode. + +## The ownable account format + +Every contract deployed on Fluent lives in an account whose code field is an **ownable-account wrapper**. The wrapper carries three things: + +- a **magic and version header** identifying the account as runtime-owned, +- an `owner_address` β€” the delegated runtime that should execute this account, +- **runtime metadata** bytes β€” context the runtime needs to interpret the account (original bytecode, compilation flags, class markers, anything runtime-family-specific). + +`owner_address` is the load-bearing field. When a call targets this account, REVM doesn't load code from the account itself. It loads code from the owner, and forwards the call into that delegated runtime with the account as the state target. + +## Create-time routing + +Which runtime owns a new account is decided at deployment. When init code arrives, the routing layer inspects the leading bytes for a magic prefix and picks a runtime accordingly: + +| Init code prefix | Delegated runtime | +|---|---| +| Wasm / rWasm magic | Wasm delegated runtime | +| SVM ELF payload *(feature-gated)* | SVM delegated runtime | +| `UNIVERSAL_TOKEN_MAGIC_BYTES = 0x45524320` (`"ERC "`) | Universal Token runtime | +| Anything else | Delegated EVM runtime | + +Two things happen next. The new account's code is set to the ownable-account wrapper pointing at the chosen runtime, and the original init payload is passed to the delegated runtime for whatever deploy-time logic that runtime defines β€” constructor execution, storage initialization, role assignment. + +After that, the account's execution class is frozen. There's no later toggle that switches a Solidity contract to the Wasm runtime. Ownership is established at deploy and is part of the account's identity. + +## Execution-time behavior + +When a routed account is called during a transaction: + +1. REVM sees the call target is an ownable account. +2. It reads `owner_address` from the wrapper. +3. It loads the delegated runtime's code from that owner address. +4. It keeps the original callee as the **state target** β€” storage reads and writes hit the callee's slots, not the runtime's. +5. It forwards the call input to the delegated runtime. + +The delegated runtime executes the account's logic from there. It can read and write the callee's storage, emit logs under the callee's address, and yield to the host for privileged operations like any other runtime frame. + +That's why many accounts can share one runtime implementation without leaking state between them: runtime code loads from the owner, but the storage domain is always the called account. + +## Direct calls to delegated runtime addresses are blocked + +An obvious attack is to target the delegated runtime address directly and skip the wrapper. If a user could call `owner_address` like a regular contract, they could execute runtime logic in the runtime's own storage domain instead of an ownable account's. + +The execution path rejects this. Delegated runtime addresses aren't callable as normal contracts; the router forces user-facing flows to go through an ownable account. + +:::warning +A call that targets a delegated runtime address directly is rejected at execution time. User flows must go through an ownable account, not bypass it. This is a consensus-safety boundary, not a UX preference. +::: + +## Metadata ownership rules + +The runtime metadata attached to an ownable account is mutable, but only by the runtime that owns the account. When a runtime frame tries to mutate metadata on a target account, two checks run: + +1. The target must be an ownable account. +2. The target's `owner_address` must match the caller's delegated runtime. + +If either check fails, the operation is rejected. That keeps one runtime family β€” say, the EVM runtime β€” from rewriting metadata on accounts owned by another family like the Wasm runtime. It's the mechanism that stops cross-runtime privilege bugs from becoming cross-runtime state corruption. + +Static-context mutations β€” anything invoked from a `STATICCALL` frame β€” are rejected for metadata operations regardless of ownership. + +## The Wasm-wrapper deploy rewrite + +One special path worth knowing about if you're auditing the deployment flow. The Wasm runtime's deploy output can contain a compiled rWasm payload followed by a constructor tail. In that case, the deployed code is rewritten: the account's code is set to the compiled rWasm bytecode directly, not to the ownable-account wrapper, and the constructor tail runs with the remaining deployment parameters. + +This supports Wasm-wrapper deployment flows where the final on-chain representation is the compiled artifact rather than a pointer to a delegated runtime. From an execution-semantics perspective the account is still routed consistently; the rewrite is a storage-level detail. + +## Why this model + +Three things fall out of ownable-account routing: + +**Shared runtime logic without per-account duplication.** One delegated Wasm runtime executes every Wasm contract. Fixing a bug or upgrading behavior happens in one place, not per-deployment. + +**Deterministic dispatch by owner.** Given an account's wrapper, the execution engine is decidable in constant time. The router reads one field. + +**Cross-environment composability over shared state.** A Solidity contract and a Rust contract are two ownable accounts pointing at two different delegated runtimes. They call each other, they share the state trie, and the host mediates every operation between them with the same rules. diff --git a/docs/system-architecture/runtime-upgrade.md b/docs/system-architecture/runtime-upgrade.md new file mode 100644 index 0000000..dbc469f --- /dev/null +++ b/docs/system-architecture/runtime-upgrade.md @@ -0,0 +1,63 @@ +--- +title: Runtime Upgrade +sidebar_position: 7 +--- + +Fluent's delegated runtimes β€” the EVM runtime, the Wasm runtime, the Universal Token runtime, and others β€” are protocol-owned bytecode. They decide how every ownable account in their class behaves. Fixing bugs and evolving behavior in those runtimes without a full node rewrite is a design goal. Making absolutely sure no one else can do it is another. + +Runtime upgrade is the privileged control plane for this. It's tightly constrained on every axis β€” who can call it, through what path, with what payload β€” because an unconstrained upgrade is a total compromise of the chain. + +## The upgrade flow + +A runtime replacement goes through five steps: + +1. The **governance owner** (an externally held key or multisig) calls the runtime-upgrade contract. +2. The contract **validates** the proposed Wasm artifact and **compiles** it to rWasm. +3. It invokes the **native upgrade syscall**, passing the target runtime address and the serialized rWasm module. +4. The **host** verifies the caller arrived through the upgrade precompile's execution path and installs the new code at the target address. +5. An **upgrade event** is emitted with the target, a genesis reference, and the new code's hash. + +The separation matters. Steps 1 and 2 are a contract the governance owner talks to. Step 3 is a syscall that contract is allowed to invoke. Step 4 is host enforcement, which exists precisely because contract-level authorization alone can't guarantee protocol safety. If an attacker found a way to call the upgrade syscall from somewhere that wasn't the upgrade precompile, step 4 is what rejects it. + +## Contract-level controls + +The upgrade contract exposes a minimal surface: + +- `upgradeTo(...)` β€” the main entry. Only the owner can call it. The argument is the target runtime address plus the new artifact. +- `changeOwner(...)` β€” transfers ownership. Assigning the zero address is rejected β€” there's no valid "burn the key" result from this path. +- `owner()` β€” returns the current owner. +- `renounceOwnership()` β€” sets the owner to a designated system address, effectively freezing upgrades through the owner-based path while leaving a deterministic default. + +A default-owner fallback is defined for the unset state, so the contract always has a well-formed owner to check against. + +## Host-side enforcement + +The upgrade syscall handler runs its own checks on top of whatever the contract enforces: + +- **Not callable in static context.** A `STATICCALL` frame can't trigger an upgrade, full stop. +- **Only reachable via the runtime-upgrade precompile's execution path.** The host checks which address the call came from and rejects anything that didn't arrive through the precompile. +- **Payload must decode correctly.** Malformed inputs are rejected before any state change. +- **Bytecode must be a valid rWasm payload.** Validation happens before installation β€” the runtime executor is never asked to load garbage. +- **Installation is deterministic.** The target account is loaded, its code field is replaced with the new bytecode, and the change commits in one host action. There's no multi-step install path where a partial update could leave the runtime undefined. + +Host-level checks are what make the overall system safe. Contract-level permissions alone would let a bug in the upgrade contract compromise every delegated runtime on the chain. The host rejects any attempt that didn't arrive through the one blessed execution path, regardless of contract state. + +:::warning +Runtime upgrade changes consensus behavior. Every upgrade is fork-critical change management: deterministic artifacts, coherent network rollout, and post-upgrade verification are not optional. +::: + +## The legacy testnet hook + +One carveout worth knowing about. A chain-id-gated legacy upgrade path exists for historical testnet behavior. It's temporary β€” documented as such β€” and should be read as compatibility debt rather than part of the target architecture. Mainnet doesn't use it; auditors should trace it but treat it as out-of-scope for the target security model. + +## Operational expectations + +Upgrading a runtime isn't like deploying a contract. A runtime change affects every account in that runtime's class retroactively, which means every user of the chain lives with the consequences. Treat every upgrade as fork-critical change management: + +- Produce **deterministic build artifacts** so the artifact installed on chain is byte-identical to what was audited. +- Use **multisig or operator quorum** on the governance owner. A single key with unilateral upgrade authority is a single point of failure. +- **Roll out coherently** across nodes. A chain where some nodes have upgraded and others haven't is a chain that will fork. +- **Verify post-upgrade.** Check the installed code hash against the expected artifact. Run smoke tests against runtime behavior. Confirm events fired with the expected metadata. +- **Keep an audit trail.** Who proposed, who approved, who triggered, what was installed, what the hash was. On-chain events help; the operational record matters too. + +Runtime extensibility is intentional. It's also one of the most sensitive pieces of infrastructure on the chain, and it should be operated accordingly. diff --git a/docs/system-architecture/security-invariants.md b/docs/system-architecture/security-invariants.md new file mode 100644 index 0000000..b0c709f --- /dev/null +++ b/docs/system-architecture/security-invariants.md @@ -0,0 +1,61 @@ +--- +title: Security Invariants +sidebar_position: 8 +--- + +The other pages in this section describe how Fluent works. This page is the list of things that cannot stop being true without the chain breaking. These are the consensus-critical invariants β€” break any one and the failure mode isn't a bug, it's a consensus split, a privilege escalation, or a host-level instability that affects every account on the chain. + +Anyone modifying runtime-host interaction code, syscall handlers, or upgrade paths should treat this as a review checklist. + +:::danger +Most critical bugs in this architecture are boundary violations, not ordinary application logic errors. Every invariant below is part of the consensus surface. +::: + +## Routing integrity + +New contracts must route to the correct delegated runtime class. User calls must not bypass routing by targeting a delegated runtime address directly. Metadata ownership boundaries between runtime families must hold. Two contracts with different intended runtimes are fundamentally different contracts, and routing is what enforces that. A misrouted deploy or a successful bypass means the same storage can be interpreted under two different runtime rules, which is how a chain executes contradictory state transitions. Mechanism: [Runtime Routing and Ownable Accounts](./runtime-routing-and-ownable-accounts.md). + +## Interruption integrity + +Positive exit codes are **call IDs**, not final statuses. A runtime yielding a positive exit is asking for host action, and its output buffer carries syscall parameters β€” not committed output. Resume must use the exact recoverable context associated with the `call_id`, and per-transaction reset must clear recovery state so no context survives past its owning transaction. Call-id confusion β€” treating a yield as a finalization or resuming the wrong context β€” corrupts execution flow and can leak state across frames. Mechanism: [Interruption and Syscalls](./interruption-and-syscalls.md). + +## Bounds-before-allocation + +Untrusted lengths must be validated before the host allocates memory to service them. Memory reads and writes must fail safely when they go out of bounds. Large copy paths β€” hashing, calldata, log emission β€” must carry explicit upper bounds. Without these checks, untrusted input can make the host allocate unboundedly and crash itself before any gas is charged, which is a DoS surface on every node simultaneously. + +## Static-call immutability + +State-changing operations must reject static context. That covers ordinary storage mutations, metadata mutations, account lifecycle operations (create, destroy), and privileged runtime state transitions like upgrade. `STATICCALL` exists so callers can invoke untrusted code knowing no state change can result. Any mutation that slips through the static check defeats that guarantee and silently changes the semantics of every existing contract that relies on it. + +## System-runtime envelope discipline + +For system-mode runtimes, structured output envelopes must decode deterministically across nodes. Storage diffs, logs, and metadata updates must only commit on a successful runtime exit β€” a fatal exit or a decode failure means *no* side effects are applied, not "whatever we managed to parse." Envelope mis-handling is how you commit wrong side effects from a runtime that didn't actually complete. + +## Upgrade authority boundaries + +The runtime-upgrade path must stay tightly scoped to the upgrade precompile's execution path on the host side. Authority defaults and owner transitions must be explicit and reviewed β€” no silent zero-owner assignment, no ambiguous fallback. Upgrade-authority compromise is full-system compromise; the safety here comes from layering contract-level permissioning under host-level path enforcement. Mechanism: [Runtime Upgrade](./runtime-upgrade.md). + +## Fatal-code containment + +Non-system user contracts must not be able to surface internal fatal runtime-only classes as normal outputs. Some error classes are meaningful only inside the host-runtime protocol (envelope-decode failures, recovery-state violations). Letting user contracts produce those classes as their return status lets applications impersonate protocol-level failures and confuse every downstream consumer. + +## Bridge hook consistency + +Bridge hooks rely on specific event shapes, data layouts, and ordering guarantees. Any change to the events, the runtime side, or the flow that produces them must update the bridge-side hook logic in the same change. Mismatch here mints, burns, or settles wrong amounts β€” the most expensive kind of bug a bridge can have. + +## Panic policy + +The release build profile is `panic = "abort"`. Consensus-critical paths must not rely on unwind-based recovery: a panic aborts the process, and any fallback that assumes the stack will be unwound before cleanup is wrong. Design error handling around explicit `Result` returns and anticipated failures. Don't rely on catching implicit panics. + +## Checklist for syscall-handler changes + +Any change that touches a syscall handler should confirm, explicitly, that it: + +- preserves strict input and state validation, +- preserves static-call rejection for mutating branches, +- keeps gas and fuel charging order deterministic, +- keeps allocation safety bounded and pre-validated, +- preserves ownership checks on metadata operations, +- keeps interruption and resume symmetry intact. + +If any box isn't clearly preserved, the change isn't ready to merge. These aren't style concerns. They're the boundaries this architecture depends on. diff --git a/docs/system-architecture/state-and-rpc-compatibility.md b/docs/system-architecture/state-and-rpc-compatibility.md new file mode 100644 index 0000000..aed188b --- /dev/null +++ b/docs/system-architecture/state-and-rpc-compatibility.md @@ -0,0 +1,63 @@ +--- +title: State and RPC Compatibility +sidebar_position: 6 +--- + +Fluent's state model is deliberately Ethereum-shaped on the outside: one trie, account addresses, balances, nonces, code hashes. But some contracts are stored in the runtime-managed **ownable-account wrapper** (see [Runtime Routing](./runtime-routing-and-ownable-accounts.md)), so what a wallet or indexer reads from a Fluent node isn't always the bytes sitting in storage. The wrapper carries execution metadata that would confuse Ethereum tooling, so the node exposes two RPC views β€” one normalized for compatibility, one raw for infrastructure. + +This page covers the shared-state model and the RPC split on top of it. + +## One shared state, many runtimes + +Every contract β€” EVM, Wasm, Universal Token, future runtimes like SVM β€” lives in the same account/state trie. No per-runtime storage silo, no bridge between VM environments, no separate address space. A Solidity contract and a Rust contract are two accounts in the same trie, and a call from one to the other is an ordinary in-transaction call, not a message passed across a boundary. + +That's the structural property that makes cross-runtime composability synchronous instead of asynchronous. Two contracts in different runtime families can call each other in a single transaction because the state they read and write is the same state. The host mediates every operation between them with the same rules, regardless of which runtime owns which account. + +The cost is that some accounts carry more than plain EVM bytecode in their code field. They carry a wrapper describing which runtime should execute them and what metadata that runtime needs. The RPC story starts there. + +## The ownable-account wrapper, briefly + +The full mechanics live in [Runtime Routing and Ownable Accounts](./runtime-routing-and-ownable-accounts.md). For RPC purposes what matters: the *code* field of an ownable account is not the contract's executable bytecode. It's a wrapper carrying a magic header, the delegated runtime address (`owner_address`), and runtime metadata. The executable bytecode lives at the delegated runtime's address, and the wrapper tells the node where to find it. + +An Ethereum-compatible client that reads this field expecting plain EVM bytecode gets confused: the wrapper isn't valid EVM code, the code hash doesn't match any EVM interpreter's expectations, bytecode-based identity checks fail. So the RPC layer has to make a choice. + +## Two views: compatibility and raw + +Fluent exposes every account-and-code RPC method in two forms: + +- **Compatibility view** β€” normalized for Ethereum tooling. For ownable accounts, the node extracts the EVM-facing bytecode from the underlying delegated runtime and returns it; code hashes are adjusted to match the extracted bytecode. +- **Raw view** β€” exactly what is stored. For ownable accounts, the node returns the wrapper bytes as-is, with the original code hash. No normalization. + +| Compatibility method | Raw method | Purpose | +|---|---|---| +| `eth_getCode` | `eth_getRawCode` | contract code bytes | +| `eth_getAccount` | `eth_getRawAccount` | account fields (balance, nonce, code hash) | +| `eth_getAccountInfo` | `eth_getRawAccountInfo` | combined account info + code payload | + +For accounts that aren't ownable β€” EOAs, plain contracts without a wrapper β€” both views return the same bytes. + +## When to use which + +**Compatibility methods** are the right choice for anything built on standard Ethereum assumptions: wallets, app SDKs, Etherscan-style explorers, bytecode-matching verification, generic `eth_*` consumers. These expect account fields shaped like EVM, and the compatibility view gives them exactly that. + +**Raw methods** are for infrastructure that needs the bytes that actually live in storage. Typical cases: + +- building or validating account and state proofs against the real trie, +- cross-checking state-root or witness pipelines, +- indexers that must preserve canonical stored bytes, +- debugging divergence between what a client sees and what is persisted, +- fork or fork-db tooling where cache keys or bytecode identity must match storage exactly. + +If you're writing a Fluent-aware explorer or a proving pipeline, you want raw. Otherwise, stick to compatibility and treat the extraction as invisible. + +## Difference from upstream Reth + +Fluent's node is based on a modified Reth, but upstream Reth doesn't know about ownable-account wrapping. Its `eth_getCode` returns whatever bytes are stored at the account's code field, period. On Fluent that behavior would leak the wrapper to every Ethereum client, which is exactly what the compatibility view is there to prevent. + +The fork carries the wrapped-account normalization logic. Default methods lean compatibility-first so downstream Ethereum tooling keeps working; raw methods are the explicit opt-in when you need storage-level truth. + +## Why the split exists + +Both views are necessary. Compatibility-only would leave proof systems and indexers with no way to address the bytes that actually live on-chain β€” every query would go through a normalization layer they can't invert. Raw-only would force every wallet and SDK to handle Fluent accounts specifically, breaking the "point your tool at the RPC" promise. + +Default methods compatibility-first, raw methods explicit. Ethereum tooling sees an Ethereum-shaped chain; Fluent-aware infrastructure sees everything as it is. diff --git a/docusaurus.config.js b/docusaurus.config.js index e937d15..f74d553 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -16,6 +16,10 @@ module.exports = { onBrokenLinks: "throw", onBrokenAnchors: "warn", onBrokenMarkdownLinks: "warn", + markdown: { + mermaid: true, + }, + themes: ["@docusaurus/theme-mermaid"], // favicon: 'img/logos/faviconDark.png', favicon: "img/logos/faviconPurple.png", organizationName: "Fluent", // Usually your GitHub org/user name. diff --git a/package-lock.json b/package-lock.json index c1e6c1a..aa06419 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@docusaurus/core": "^3.9.2", "@docusaurus/preset-classic": "^3.9.2", + "@docusaurus/theme-mermaid": "^3.9.2", "@mdx-js/react": "^3.0.0", "@wojtekmaj/react-daterange-picker": "^3.4.0", "axios": "^1.7.2", @@ -274,6 +275,19 @@ "node": ">=6.0.0" } }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "license": "MIT", + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -1987,6 +2001,49 @@ "node": ">=6.9.0" } }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.2.tgz", + "integrity": "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==", + "license": "MIT" + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-12.0.0.tgz", + "integrity": "sha512-fSL4KXjTl7cDgf0B5Rip9Q05BOrYvkJV/RrBTE/bKDN096E4hN/ySpcBK5B24T76dlQ2i32Zc3PAE27jFnFrKg==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "12.0.0", + "@chevrotain/types": "12.0.0" + } + }, + "node_modules/@chevrotain/gast": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-12.0.0.tgz", + "integrity": "sha512-1ne/m3XsIT8aEdrvT33so0GUC+wkctpUPK6zU9IlOyJLUbR0rg4G7ZiApiJbggpgPir9ERy3FRjT6T7lpgetnQ==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "12.0.0" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-12.0.0.tgz", + "integrity": "sha512-p+EW9MaJwgaHguhoqwOtx/FwuGr+DnNn857sXWOi/mClXIkPGl3rn7hGNWvo31HA3vyeQxjqe+H36yZJwYU8cA==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/types": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-12.0.0.tgz", + "integrity": "sha512-S+04vjFQKeuYw0/eW3U52LkAHQsB1ASxsPGsLPUyQgrZ2iNNibQrsidruDzjEX2JYfespXMG0eZmXlhA6z7nWA==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-12.0.0.tgz", + "integrity": "sha512-lB59uJoaGIfOOL9knQqQRfhl9g7x8/wqFkp13zTdkRu1huG9kg6IJs1O8hqj9rs6h7orGxHJUKb+mX3rPbWGhA==", + "license": "Apache-2.0" + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -3971,6 +4028,34 @@ "react": ">=16.0.0" } }, + "node_modules/@docusaurus/theme-mermaid": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.9.2.tgz", + "integrity": "sha512-5vhShRDq/ntLzdInsQkTdoKWSzw8d1jB17sNPYhA/KvYYFXfuVEGHLM6nrf8MFbV8TruAHDG21Fn3W4lO8GaDw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.9.2", + "@docusaurus/module-type-aliases": "3.9.2", + "@docusaurus/theme-common": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", + "mermaid": ">=11.6.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@mermaid-js/layout-elk": "^0.1.9", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@mermaid-js/layout-elk": { + "optional": true + } + } + }, "node_modules/@docusaurus/theme-search-algolia": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.9.2.tgz", @@ -4166,6 +4251,23 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, + "node_modules/@iconify/utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.0.tgz", + "integrity": "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==", + "license": "MIT", + "dependencies": { + "@antfu/install-pkg": "^1.1.0", + "@iconify/types": "^2.0.0", + "mlly": "^1.8.0" + } + }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -4410,6 +4512,15 @@ "react": ">=16" } }, + "node_modules/@mermaid-js/parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.1.0.tgz", + "integrity": "sha512-gxK9ZX2+Fex5zu8LhRQoMeMPEHbc73UKZ0FQ54YrQtUxE1VVhMwzeNtKRPAu5aXks4FasbMe4xB4bWrmq6Jlxw==", + "license": "MIT", + "dependencies": { + "langium": "^4.0.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -5154,6 +5265,259 @@ "@types/node": "*" } }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", + "license": "MIT" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", + "license": "MIT" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "license": "MIT", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "license": "MIT" + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", + "license": "MIT" + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", + "license": "MIT" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", + "license": "MIT" + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", + "license": "MIT" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "license": "MIT" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -5222,6 +5586,12 @@ "@types/send": "*" } }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "license": "MIT" + }, "node_modules/@types/gtag.js": { "version": "0.0.12", "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", @@ -5474,6 +5844,13 @@ "@types/node": "*" } }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -5510,6 +5887,16 @@ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "license": "ISC" }, + "node_modules/@upsetjs/venn.js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@upsetjs/venn.js/-/venn.js-2.0.0.tgz", + "integrity": "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==", + "license": "MIT", + "optionalDependencies": { + "d3-selection": "^3.0.0", + "d3-transition": "^3.0.1" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -5721,9 +6108,9 @@ } }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -6292,9 +6679,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -6635,6 +7022,34 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/chevrotain": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-12.0.0.tgz", + "integrity": "sha512-csJvb+6kEiQaqo1woTdSAuOWdN0WTLIydkKrBnS+V5gZz0oqBrp4kQ35519QgK6TpBThiG3V1vNSHlIkv4AglQ==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/cst-dts-gen": "12.0.0", + "@chevrotain/gast": "12.0.0", + "@chevrotain/regexp-to-ast": "12.0.0", + "@chevrotain/types": "12.0.0", + "@chevrotain/utils": "12.0.0" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.4.1.tgz", + "integrity": "sha512-PvVJm3oGqrveUVW2Vt/eZGeiAIsJszYweUcYwcskg9e+IubNYKKD+rHHem7A6XVO22eDAL+inxNIGAzZ/VIWlA==", + "license": "MIT", + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^12.0.0" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -6919,6 +7334,12 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "license": "MIT" + }, "node_modules/config-chain": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", @@ -7119,6 +7540,15 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "license": "MIT" }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "license": "MIT", + "dependencies": { + "layout-base": "^1.0.0" + } + }, "node_modules/cosmiconfig": { "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", @@ -7508,126 +7938,646 @@ "postcss": "^8.4.31" } }, - "node_modules/cssnano-preset-advanced": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-6.1.2.tgz", - "integrity": "sha512-Nhao7eD8ph2DoHolEzQs5CfRpiEP0xa1HBdnFZ82kvqdmbwVBUr2r1QuQ4t1pi+D1ZpqpcO4T+wy/7RxzJ/WPQ==", - "license": "MIT", + "node_modules/cssnano-preset-advanced": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-6.1.2.tgz", + "integrity": "sha512-Nhao7eD8ph2DoHolEzQs5CfRpiEP0xa1HBdnFZ82kvqdmbwVBUr2r1QuQ4t1pi+D1ZpqpcO4T+wy/7RxzJ/WPQ==", + "license": "MIT", + "dependencies": { + "autoprefixer": "^10.4.19", + "browserslist": "^4.23.0", + "cssnano-preset-default": "^6.1.2", + "postcss-discard-unused": "^6.0.5", + "postcss-merge-idents": "^6.0.3", + "postcss-reduce-idents": "^6.0.3", + "postcss-zindex": "^6.0.2" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-preset-default": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz", + "integrity": "sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "css-declaration-sorter": "^7.2.0", + "cssnano-utils": "^4.0.2", + "postcss-calc": "^9.0.1", + "postcss-colormin": "^6.1.0", + "postcss-convert-values": "^6.1.0", + "postcss-discard-comments": "^6.0.2", + "postcss-discard-duplicates": "^6.0.3", + "postcss-discard-empty": "^6.0.3", + "postcss-discard-overridden": "^6.0.2", + "postcss-merge-longhand": "^6.0.5", + "postcss-merge-rules": "^6.1.1", + "postcss-minify-font-values": "^6.1.0", + "postcss-minify-gradients": "^6.0.3", + "postcss-minify-params": "^6.1.0", + "postcss-minify-selectors": "^6.0.4", + "postcss-normalize-charset": "^6.0.2", + "postcss-normalize-display-values": "^6.0.2", + "postcss-normalize-positions": "^6.0.2", + "postcss-normalize-repeat-style": "^6.0.2", + "postcss-normalize-string": "^6.0.2", + "postcss-normalize-timing-functions": "^6.0.2", + "postcss-normalize-unicode": "^6.1.0", + "postcss-normalize-url": "^6.0.2", + "postcss-normalize-whitespace": "^6.0.2", + "postcss-ordered-values": "^6.0.2", + "postcss-reduce-initial": "^6.1.0", + "postcss-reduce-transforms": "^6.0.2", + "postcss-svgo": "^6.0.3", + "postcss-unique-selectors": "^6.0.4" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-utils": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.2.tgz", + "integrity": "sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "license": "CC0-1.0" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/cytoscape": { + "version": "3.33.2", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.2.tgz", + "integrity": "sha512-sj4HXd3DokGhzZAdjDejGvTPLqlt84vNFN8m7bGsOzDY5DyVcxIb2ejIXat2Iy7HxWhdT/N1oKyheJ5YdpsGuw==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "license": "MIT", + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "license": "MIT" + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "license": "ISC", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "license": "ISC", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "license": "ISC", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "license": "ISC", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "license": "ISC", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-dsv/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "license": "ISC", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", "dependencies": { - "autoprefixer": "^10.4.19", - "browserslist": "^4.23.0", - "cssnano-preset-default": "^6.1.2", - "postcss-discard-unused": "^6.0.5", - "postcss-merge-idents": "^6.0.3", - "postcss-reduce-idents": "^6.0.3", - "postcss-zindex": "^6.0.2" + "d3-path": "^3.1.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" + "node": ">=12" } }, - "node_modules/cssnano-preset-default": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz", - "integrity": "sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==", - "license": "MIT", + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", "dependencies": { - "browserslist": "^4.23.0", - "css-declaration-sorter": "^7.2.0", - "cssnano-utils": "^4.0.2", - "postcss-calc": "^9.0.1", - "postcss-colormin": "^6.1.0", - "postcss-convert-values": "^6.1.0", - "postcss-discard-comments": "^6.0.2", - "postcss-discard-duplicates": "^6.0.3", - "postcss-discard-empty": "^6.0.3", - "postcss-discard-overridden": "^6.0.2", - "postcss-merge-longhand": "^6.0.5", - "postcss-merge-rules": "^6.1.1", - "postcss-minify-font-values": "^6.1.0", - "postcss-minify-gradients": "^6.0.3", - "postcss-minify-params": "^6.1.0", - "postcss-minify-selectors": "^6.0.4", - "postcss-normalize-charset": "^6.0.2", - "postcss-normalize-display-values": "^6.0.2", - "postcss-normalize-positions": "^6.0.2", - "postcss-normalize-repeat-style": "^6.0.2", - "postcss-normalize-string": "^6.0.2", - "postcss-normalize-timing-functions": "^6.0.2", - "postcss-normalize-unicode": "^6.1.0", - "postcss-normalize-url": "^6.0.2", - "postcss-normalize-whitespace": "^6.0.2", - "postcss-ordered-values": "^6.0.2", - "postcss-reduce-initial": "^6.1.0", - "postcss-reduce-transforms": "^6.0.2", - "postcss-svgo": "^6.0.3", - "postcss-unique-selectors": "^6.0.4" + "d3-array": "2 - 3" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" }, - "peerDependencies": { - "postcss": "^8.4.31" + "engines": { + "node": ">=12" } }, - "node_modules/cssnano-utils": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.2.tgz", - "integrity": "sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==", - "license": "MIT", + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" + "node": ">=12" } }, - "node_modules/csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "license": "MIT", + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", "dependencies": { - "css-tree": "~2.2.0" + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" }, "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" } }, - "node_modules/csso/node_modules/css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "license": "MIT", + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", "dependencies": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" }, "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" + "node": ">=12" } }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "license": "CC0-1.0" - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "license": "MIT" + "node_modules/dagre-d3-es": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.14.tgz", + "integrity": "sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg==", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "lodash-es": "^4.17.21" + } }, "node_modules/dayjs": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "version": "1.11.20", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz", + "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==", "license": "MIT" }, "node_modules/debounce": { @@ -7791,6 +8741,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delaunator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz", + "integrity": "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==", + "license": "ISC", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -7973,6 +8932,15 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.1.tgz", + "integrity": "sha512-JahakDAIg1gyOm7dlgWSDjV4n7Ip2PKR55NIT6jrMfIgLFgWo81vdr1/QGqWtFNRqXP9UV71oVePtjqS2ebnPw==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/domutils": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", @@ -9232,6 +10200,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", + "license": "MIT" + }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -10133,6 +11107,15 @@ "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", "license": "MIT" }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -10628,6 +11611,31 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/katex": { + "version": "0.16.45", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.45.tgz", + "integrity": "sha512-pQpZbdBu7wCTmQUh7ufPmLr0pFoObnGUoL/yhtwJDgmmQpbkg/0HSVti25Fu4rmd1oCR6NGWe9vqTWuWv3GcNA==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -10637,6 +11645,11 @@ "json-buffer": "3.0.1" } }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -10655,6 +11668,24 @@ "node": ">=6" } }, + "node_modules/langium": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/langium/-/langium-4.2.2.tgz", + "integrity": "sha512-JUshTRAfHI4/MF9dH2WupvjSXyn8JBuUEWazB8ZVJUtXutT0doDlAv1XKbZ1Pb5sMexa8FF4CFBc0iiul7gbUQ==", + "license": "MIT", + "dependencies": { + "@chevrotain/regexp-to-ast": "~12.0.0", + "chevrotain": "~12.0.0", + "chevrotain-allstar": "~0.4.1", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", + "vscode-uri": "~3.1.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, "node_modules/latest-version": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", @@ -10680,6 +11711,12 @@ "shell-quote": "^1.8.3" } }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "license": "MIT" + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -10751,6 +11788,12 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "license": "MIT" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -10852,6 +11895,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/marked": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", + "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -11389,6 +12444,48 @@ "node": ">= 8" } }, + "node_modules/mermaid": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.14.0.tgz", + "integrity": "sha512-GSGloRsBs+JINmmhl0JDwjpuezCsHB4WGI4NASHxL3fHo3o/BRXTxhDLKnln8/Q0lRFRyDdEjmk1/d5Sn1Xz8g==", + "license": "MIT", + "dependencies": { + "@braintree/sanitize-url": "^7.1.1", + "@iconify/utils": "^3.0.2", + "@mermaid-js/parser": "^1.1.0", + "@types/d3": "^7.4.3", + "@upsetjs/venn.js": "^2.0.0", + "cytoscape": "^3.33.1", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.14", + "dayjs": "^1.11.19", + "dompurify": "^3.3.1", + "katex": "^0.16.25", + "khroma": "^2.1.0", + "lodash-es": "^4.17.23", + "marked": "^16.3.0", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", + "ts-dedent": "^2.2.0", + "uuid": "^11.1.0" + } + }, + "node_modules/mermaid/node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -13276,9 +14373,9 @@ "license": "ISC" }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -13296,6 +14393,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mlly": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", + "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==", + "license": "MIT", + "dependencies": { + "acorn": "^8.16.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.3" + } + }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", @@ -13768,6 +14877,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-manager-detector": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", + "license": "MIT" + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -13895,6 +15010,12 @@ "tslib": "^2.0.3" } }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", + "license": "MIT" + }, "node_modules/path-exists": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", @@ -13943,6 +15064,12 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -13976,6 +15103,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, "node_modules/plugin-image-zoom": { "version": "1.1.0", "resolved": "git+ssh://git@github.com/flexanalytics/plugin-image-zoom.git#8e1b866c79ed6d42cefc4c52f851f1dfd1d0c7de", @@ -13984,6 +15122,22 @@ "medium-zoom": "^1.0.8" } }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", + "license": "MIT" + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "license": "MIT", + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, "node_modules/polipop": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/polipop/-/polipop-1.0.0.tgz", @@ -15857,9 +17011,9 @@ } }, "node_modules/react-loadable-ssr-addon-v5-slorber": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", - "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.3.tgz", + "integrity": "sha512-GXfh9VLwB5ERaCsU6RULh7tkemeX15aNh6wuMEBtfdyMa7fFG8TXrhXlx1SoEK2Ty/l6XIkzzYIQmyaWW3JgdQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.10.3" @@ -16476,6 +17630,24 @@ "node": ">=0.10.0" } }, + "node_modules/robust-predicates": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz", + "integrity": "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==", + "license": "Unlicense" + }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "license": "MIT", + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, "node_modules/rtlcss": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.3.0.tgz", @@ -16529,6 +17701,12 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "license": "BSD-3-Clause" + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -16819,15 +17997,15 @@ } }, "node_modules/serve-handler": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.6.tgz", - "integrity": "sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==", + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.7.tgz", + "integrity": "sha512-CinAq1xWb0vR3twAv9evEU8cNWkXCb9kd5ePAHUKJBkOsUpR1wt/CvGdeca7vqumL1U5cSaeVQ6zZMxiJ3yWsg==", "license": "MIT", "dependencies": { "bytes": "3.0.0", "content-disposition": "0.5.2", "mime-types": "2.1.18", - "minimatch": "3.1.2", + "minimatch": "3.1.5", "path-is-inside": "1.0.2", "path-to-regexp": "3.3.0", "range-parser": "1.2.0" @@ -17509,6 +18687,12 @@ "postcss": "^8.4.31" } }, + "node_modules/stylis": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.4.0.tgz", + "integrity": "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==", + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -17705,6 +18889,15 @@ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", "license": "MIT" }, + "node_modules/tinyexec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", + "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinypool": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", @@ -17780,6 +18973,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "license": "MIT", + "engines": { + "node": ">=6.10" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -17820,6 +19022,12 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/ufo": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", + "license": "MIT" + }, "node_modules/undici-types": { "version": "7.10.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", @@ -18307,6 +19515,55 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "license": "MIT", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "license": "MIT" + }, "node_modules/watchpack": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", diff --git a/package.json b/package.json index 066e7cd..d84ae00 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "dependencies": { "@docusaurus/core": "^3.9.2", "@docusaurus/preset-classic": "^3.9.2", + "@docusaurus/theme-mermaid": "^3.9.2", "@mdx-js/react": "^3.0.0", "@wojtekmaj/react-daterange-picker": "^3.4.0", "axios": "^1.7.2", diff --git a/static/img/system-architecture/bridge-topology.svg b/static/img/system-architecture/bridge-topology.svg new file mode 100644 index 0000000..f823bb3 --- /dev/null +++ b/static/img/system-architecture/bridge-topology.svg @@ -0,0 +1,64 @@ + + + + + + + + + L1 Β· ETHEREUM + L2 Β· FLUENT + + + + + + + L1 Gateway + NativeGateway Β· ERC20Gateway + + + L2 Gateway + NativeGateway Β· ERC20Gateway + + + + L1FluentBridge + queue Β· proof verify Β· rollup hook + + + L2FluentBridge + receive Β· fee Β· expiry check + + + + Rollup + commitBatch Β· cursor Β· corruption + + + L1 Oracles (on L2) + L1BlockOracle Β· L1GasOracle + + + + + + + + + + + + + + + + + + + deposit (via sequencer) + + + + withdrawal (proof vs batchRoot) + diff --git a/static/img/system-architecture/call-lifecycle.svg b/static/img/system-architecture/call-lifecycle.svg new file mode 100644 index 0000000..a2c5521 --- /dev/null +++ b/static/img/system-architecture/call-lifecycle.svg @@ -0,0 +1,63 @@ + + + + + + + + + + User + + + REVM / Host + + + rWasm Runtime + + + + + + + + call / create + + + + + prepare frame input + fuel + + + invoke(input, fuel) + + + + [ final result ] + + + exit_code <= 0 + output + + + + + apply journal, commit + + + + + + [ interruption ] + + + exit_code > 0 (= call_id) + syscall payload + + + + + handle host action + + + resume(call_id, result) + + diff --git a/static/img/system-architecture/rollup-pipeline.svg b/static/img/system-architecture/rollup-pipeline.svg new file mode 100644 index 0000000..1a61cd1 --- /dev/null +++ b/static/img/system-architecture/rollup-pipeline.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + STAGE A + commitBatch + + + + STAGE B + submitBlobs + EIP-4844 DA + + + + STAGE C + preconfirmBatch + Nitro TEE + SP1 + + + + STAGE E + finalizeBatches + delay-based + + + + + + + + + disputed + + + + STAGE D + challengeBatchRoot + challengeBlock + + + + SP1 proof + + + + STAGE E + finalizeWithProofs + proof-gated + + + + unresolved + + + + SAFETY HALT + _rollupCorrupted + revertBatches + diff --git a/static/img/system-architecture/three-layers.svg b/static/img/system-architecture/three-layers.svg new file mode 100644 index 0000000..bc64ea6 --- /dev/null +++ b/static/img/system-architecture/three-layers.svg @@ -0,0 +1,34 @@ + + + + + + + + + + Node / Consensus Shell + modified Reth Β· networking, mempool, RPC + + + + Execution Coordination + REVM + host handlers + + + + Runtime Execution + rWasm Β· contract & system modes + + + + + call + commit + + + + + exec / resume + interruption +