diff --git a/.config/cspell.yaml b/.config/cspell.yaml new file mode 100644 index 0000000000..43e0f10097 --- /dev/null +++ b/.config/cspell.yaml @@ -0,0 +1,19 @@ +version: "0.2" +language: en-US +ignoreRegExpList: + - Urls + - markdownCodeBlock +patterns: + - name: markdownCodeBlock + pattern: "/^(?:```|~~~)[\\s\\S]*?^(?:```|~~~)/gm" +ignorePaths: + - target + - docs/external/build + - docs/external/node_modules + - node_modules + - "**/package-lock.json" +words: + - grpcurl + - Merkle + - Miden + - RocksDB diff --git a/.config/markdownlint-cli2.yaml b/.config/markdownlint-cli2.yaml index 95221ee645..b78abf95a3 100644 --- a/.config/markdownlint-cli2.yaml +++ b/.config/markdownlint-cli2.yaml @@ -1,2 +1,7 @@ config: line-length: false + # Docusaurus pages use frontmatter `title` for sidebar/browser metadata and an explicit H1 for + # page content. Do not count the frontmatter title as a page title, otherwise every page with both + # fields trips MD025/single-title. + single-title: + front_matter_title: "" diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml deleted file mode 100644 index 105f1bc0e9..0000000000 --- a/.github/workflows/build-docs.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: build-docs - -# Limits workflow concurrency to only the latest commit in the PR. -concurrency: - group: "${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}" - cancel-in-progress: true - -on: - push: - branches: [main, next] - paths: - - "docs/external/**" - - ".github/workflows/build-docs.yml" - pull_request: - types: [opened, reopened, synchronize] - paths: - - "docs/external/**" - - ".github/workflows/build-docs.yml" - workflow_dispatch: - -permissions: - contents: read - -jobs: - build-docs: - name: Build Documentation - runs-on: ubuntu-24.04 - - steps: - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - persist-credentials: false - - - name: Setup Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version: "20" - cache: "npm" - cache-dependency-path: docs/external/package-lock.json - - - name: Install dependencies - working-directory: ./docs/external - run: npm ci - - - name: Build documentation - working-directory: ./docs/external - run: npm run build:dev diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c405f1d42..f34406baaa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,11 +13,9 @@ on: - next paths-ignore: - "**.txt" - - "docs/**" pull_request: paths-ignore: - "**.txt" - - "docs/**" env: # Shared prefix key for the Rust caches. @@ -176,6 +174,30 @@ jobs: - name: Build docs run: cargo doc --no-deps --workspace --all-features --locked + external-docs: + name: docs - external + runs-on: ubuntu-24.04 + env: + # Docusaurus checks for package updates during builds and may try to write to a user config + # directory. Disable that notifier in CI so docs output is limited to build/link failures. + NO_UPDATE_NOTIFIER: "1" + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + - name: Setup Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: "22.18.0" + cache: "npm" + cache-dependency-path: docs/external/package-lock.json + - name: Install dependencies + working-directory: ./docs/external + run: npm ci + - name: Build documentation and check links + working-directory: ./docs/external + run: npm run build:dev + # Ensure the stress-test still functions by running some cheap benchmarks. stress-test: name: stress test @@ -267,10 +289,17 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: persist-credentials: false + - name: Setup Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: "22.18.0" - uses: taiki-e/install-action@055f5df8c3f65ea01cd41e9dc855becd88953486 # v2.75.18 with: tool: typos@1.42.0 + - name: Install CSpell + run: npm install --global cspell@10.0.1 - run: make typos-check + - run: make markdown-spellcheck fmt: name: lint - formatting diff --git a/.github/workflows/trigger-deploy-docs.yml b/.github/workflows/publish-external-docs.yml similarity index 64% rename from .github/workflows/trigger-deploy-docs.yml rename to .github/workflows/publish-external-docs.yml index 568e6541fb..823994ece6 100644 --- a/.github/workflows/trigger-deploy-docs.yml +++ b/.github/workflows/publish-external-docs.yml @@ -1,19 +1,26 @@ -name: Trigger Aggregator Docs Rebuild +name: Publish External Docs on: push: branches: [next] paths: - - "docs/external**" + - "docs/external/**" + - ".github/workflows/publish-external-docs.yml" + workflow_dispatch: + +concurrency: + group: "${{ github.workflow }} @ ${{ github.ref }}" + cancel-in-progress: true + +permissions: + contents: read jobs: notify: + name: Trigger aggregator docs rebuild runs-on: ubuntu-24.04 environment: deploy-docs - permissions: - contents: read - steps: - name: Send repository_dispatch to aggregator uses: peter-evans/repository-dispatch@a628c95fd17070f003ea24579a56e6bc89b25766 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f65982a4d..0e2038e09d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -280,7 +280,7 @@ - Refactored account table and introduce tracking forest ([#1394](https://github.com/0xMiden/node/pull/1394)). - [BREAKING] Re-organized RPC protobuf schema to be independent of internal schema ([#1401](https://github.com/0xMiden/node/pull/1401)). - Removed internal errors from the `miden-network-monitor` ([#1424](https://github.com/0xMiden/node/pull/1424)). -- [BREAKING] Added block signing capabilities to Validator component and updated gensis bootstrap to sign blocks with configured signer ([#1426](https://github.com/0xMiden/node/pull/1426)). +- [BREAKING] Added block signing capabilities to Validator component and updated genesis bootstrap to sign blocks with configured signer ([#1426](https://github.com/0xMiden/node/pull/1426)). - Track network transactions latency in `miden-network-monitor` ([#1430](https://github.com/0xMiden/node/pull/1430)). - Reduced default block interval from `5s` to `2s` ([#1438](https://github.com/0xMiden/node/pull/1438)). - Increased retained account tree history from 33 to 100 blocks to account for the reduced block interval ([#1438](https://github.com/0xMiden/node/pull/1438)). diff --git a/Makefile b/Makefile index 7e7317d3aa..941d199244 100644 --- a/Makefile +++ b/Makefile @@ -11,11 +11,15 @@ STRESS_TEST_DATA_DIR ?= stress-test-store-$(shell date +%Y%m%d-%H%M%S) COMPOSE_FILES = -f docker-compose.yml -f compose/telemetry.yml -f compose/monitor.yml CONFIG_DIR = .config README_FILES = $(shell git ls-files '*README.md') +EXTERNAL_DOCS_MARKDOWN_FILES = $(shell git ls-files 'docs/external/**/*.md') +MARKDOWN_FILES = $(README_FILES) $(EXTERNAL_DOCS_MARKDOWN_FILES) PRETTIER_CONFIG = $(CONFIG_DIR)/prettier.json PRETTIER_LOG_LEVEL = warn PRETTIER_VERSION ?= 3.8.3 MARKDOWNLINT_CONFIG = $(CONFIG_DIR)/markdownlint-cli2.yaml MARKDOWNLINT_CLI2_VERSION ?= 0.22.1 +CSPELL_CONFIG = $(CONFIG_DIR)/cspell.yaml +CSPELL_VERSION ?= 10.0.1 RUSTFMT_CONFIG = $(CONFIG_DIR)/rustfmt.toml TAPLO_CONFIG = $(CONFIG_DIR)/taplo.toml @@ -47,18 +51,23 @@ format-check: markdown-format-check ## Checks rustfmt, README formatting, and co .PHONY: markdown-format -markdown-format: ## Formats README Markdown files - @prettier --config $(PRETTIER_CONFIG) --log-level $(PRETTIER_LOG_LEVEL) --write $(README_FILES) +markdown-format: ## Formats Markdown files + @prettier --config $(PRETTIER_CONFIG) --log-level $(PRETTIER_LOG_LEVEL) --write $(MARKDOWN_FILES) .PHONY: markdown-format-check -markdown-format-check: ## Checks README Markdown formatting - @prettier --config $(PRETTIER_CONFIG) --log-level $(PRETTIER_LOG_LEVEL) --check $(README_FILES) +markdown-format-check: ## Checks Markdown formatting + @prettier --config $(PRETTIER_CONFIG) --log-level $(PRETTIER_LOG_LEVEL) --check $(MARKDOWN_FILES) .PHONY: markdown-lint -markdown-lint: ## Lints README Markdown files - markdownlint-cli2 --config $(MARKDOWNLINT_CONFIG) $(README_FILES) +markdown-lint: ## Lints Markdown files + markdownlint-cli2 --config $(MARKDOWNLINT_CONFIG) $(MARKDOWN_FILES) + + +.PHONY: markdown-spellcheck +markdown-spellcheck: ## Spellchecks Markdown files + cspell --config $(CSPELL_CONFIG) --no-progress --show-suggestions $(MARKDOWN_FILES) .PHONY: shear @@ -85,7 +94,7 @@ workspace-check: ## Runs a check that all packages have `lints.workspace = true` .PHONY: lint -lint: typos-check format markdown-lint fix clippy toml shear ## Runs all linting tasks at once (Clippy, formatting, Markdown, cargo-shear) +lint: typos-check markdown-spellcheck format markdown-lint fix clippy toml shear ## Runs all linting tasks at once (Clippy, formatting, spelling, Markdown, cargo-shear) # --- docs ---------------------------------------------------------------------------------------- @@ -161,16 +170,23 @@ install-network-monitor: ## Installs network monitor binary # --- docker -------------------------------------------------------------------------------------- -.PHONY: compose-up -compose-up: ## Starts all node components, telemetry, and monitor via docker compose +.PHONY: local-network-build +local-network-build: docker-build ## Builds Docker images used by the local development network + +.PHONY: local-network-up +local-network-up: ## Starts the local development network docker compose $(COMPOSE_FILES) up -d -.PHONY: compose-down -compose-down: ## Stops and removes all containers via docker compose +.PHONY: local-network-down +local-network-down: ## Stops the local development network, preserving volumes docker compose $(COMPOSE_FILES) down --remove-orphans -.PHONY: compose-logs -compose-logs: ## Follows logs for all components via docker compose +.PHONY: local-network-delete +local-network-delete: ## Stops the local development network and deletes volumes + docker compose $(COMPOSE_FILES) down -v --remove-orphans + +.PHONY: local-network-logs +local-network-logs: ## Follows logs for the local development network docker compose $(COMPOSE_FILES) logs -f .PHONY: docker-build @@ -249,6 +265,7 @@ check-tools: ## Checks if development tools are installed @command -v npm >/dev/null 2>&1 && echo "[OK] npm is installed" || echo "[MISSING] npm is not installed (run: make install-tools)" @command -v prettier >/dev/null 2>&1 && echo "[OK] prettier is installed" || echo "[MISSING] prettier is not installed (run: make install-tools)" @command -v markdownlint-cli2 >/dev/null 2>&1 && echo "[OK] markdownlint-cli2 is installed" || echo "[MISSING] markdownlint-cli2 is not installed (run: make install-tools)" + @command -v cspell >/dev/null 2>&1 && echo "[OK] cspell is installed" || echo "[MISSING] cspell is not installed (run: make install-tools)" .PHONY: install-tools install-tools: ## Installs tools required by the Makefile @@ -266,5 +283,5 @@ install-tools: ## Installs tools required by the Makefile echo "On Windows: Download from https://nodejs.org/"; \ exit 1; \ fi - npm install --global prettier@$(PRETTIER_VERSION) markdownlint-cli2@$(MARKDOWNLINT_CLI2_VERSION) + npm install --global prettier@$(PRETTIER_VERSION) markdownlint-cli2@$(MARKDOWNLINT_CLI2_VERSION) cspell@$(CSPELL_VERSION) @echo "Development tools installation complete!" diff --git a/README.md b/README.md index f5f1a59c96..752ad45880 100644 --- a/README.md +++ b/README.md @@ -30,11 +30,11 @@ further value from it. If any information is missing from the official documenta ## Developer docs Developers can find repository and onboarding documentation in the [developer docs][developer-docs]. Those docs are more -in-depth but the following sections endeavour to provide a short summary. +in-depth but the following sections endeavor to provide a short summary. -### Workspace organisation +### Workspace organization -The workspace is organised around several binaries, with supplementary crates providing organisation and shared +The workspace is organized around several binaries, with supplementary crates providing organization and shared functionality. These crates are for internal use only; the primary outputs are the binaries and gRPC schema. The former are found under the `bin` directory, the latter in the `proto` directory. diff --git a/compose/monitor.yml b/compose/monitor.yml index 39a0b7a95c..4d5019c205 100644 --- a/compose/monitor.yml +++ b/compose/monitor.yml @@ -14,4 +14,4 @@ services: - MIDEN_MONITOR_NETWORK_NAME=Localhost - OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4317 ports: - - "3001:3001" + - "127.0.0.1:3001:3001" diff --git a/compose/telemetry.yml b/compose/telemetry.yml index 7a23f84971..01c8dc0585 100644 --- a/compose/telemetry.yml +++ b/compose/telemetry.yml @@ -5,8 +5,8 @@ services: - ./compose/tempo/tempo.yml:/etc/tempo.yaml command: ["-config.file=/etc/tempo.yaml"] ports: - - "3200:3200" - - "4317:4317" + - "127.0.0.1:3200:3200" + - "127.0.0.1:4317:4317" grafana: image: grafana/grafana:12.4 @@ -19,7 +19,7 @@ services: - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin - GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH=/var/lib/grafana/dashboards/miden-node.json ports: - - "3000:3000" + - "127.0.0.1:3000:3000" depends_on: - tempo diff --git a/docker-compose.yml b/docker-compose.yml index cfd3fb8b4c..4cde0e11de 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -104,7 +104,7 @@ services: - --ntx-builder.url=http://ntx-builder:50301 - --rpc.network-tx-auth-header-value=secret_value ports: - - "57291:57291" + - "127.0.0.1:57291:57291" validator: image: miden-validator diff --git a/docs/external/docusaurus.config.ts b/docs/external/docusaurus.config.ts index ef8eee7646..3309aa20d5 100644 --- a/docs/external/docusaurus.config.ts +++ b/docs/external/docusaurus.config.ts @@ -2,14 +2,19 @@ import type { Config } from "@docusaurus/types"; import { themes as prismThemes } from "prism-react-renderer"; // If your content lives in docs/src, set DOCS_PATH='src'; else '.' -const DOCS_PATH = - process.env.DOCS_PATH || (require("fs").existsSync("src") ? "src" : "."); +const DOCS_PATH = process.env.DOCS_PATH || (require("fs").existsSync("src") ? "src" : "."); const config: Config = { title: "Docs Dev Preview", url: "http://localhost:3000", baseUrl: "/", trailingSlash: false, + onBrokenLinks: "throw", + markdown: { + hooks: { + onBrokenMarkdownLinks: "throw", + }, + }, // Minimal classic preset: docs only, autogenerated sidebars, same math plugins as prod presets: [ @@ -102,7 +107,7 @@ const config: Config = { prism: { theme: prismThemes.oneLight, darkTheme: prismThemes.oneDark, - additionalLanguages: ["rust", "solidity", "toml", "yaml"], + additionalLanguages: ["bash", "json", "protobuf", "rust", "solidity", "toml", "yaml"], }, navbar: { logo: { diff --git a/docs/external/src/full-node/_category_.yml b/docs/external/src/full-node/_category_.yml new file mode 100644 index 0000000000..20137ef97e --- /dev/null +++ b/docs/external/src/full-node/_category_.yml @@ -0,0 +1,3 @@ +label: "Full Node Guide" +position: 2 +collapsed: true diff --git a/docs/external/src/full-node/bootstrap.md b/docs/external/src/full-node/bootstrap.md new file mode 100644 index 0000000000..92f87e272c --- /dev/null +++ b/docs/external/src/full-node/bootstrap.md @@ -0,0 +1,69 @@ +--- +title: "Bootstrap" +sidebar_position: 3 +--- + + + +import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; + +# Bootstrap + +A full node must perform one-time initialization by bootstrapping its local chain state to the target network's genesis +block. + + + + +For an official network: + +```bash +miden-node bootstrap \ + --data-directory full-node-data \ + --network +``` + +For a local or custom network: + +```bash +miden-node bootstrap \ + --data-directory full-node-data \ + --file genesis.dat +``` + +The data directory must be empty when bootstrapping. + + + + +For an official network: + +```bash +docker run --rm \ + -v miden-full-node-data:/data \ + ghcr.io/0xmiden/miden-node: \ + miden-node bootstrap \ + --data-directory /data \ + --network +``` + +For a local or custom network: + +```bash +docker run --rm \ + -v miden-full-node-data:/data \ + -v "$PWD/genesis.dat:/genesis.dat:ro" \ + ghcr.io/0xmiden/miden-node: \ + miden-node bootstrap \ + --data-directory /data \ + --file /genesis.dat +``` + +The data volume must be empty when bootstrapping. + + + + + + +Use the same node version and genesis source as the upstream network you intend to follow. diff --git a/docs/external/src/full-node/configuration.md b/docs/external/src/full-node/configuration.md new file mode 100644 index 0000000000..2c626268e8 --- /dev/null +++ b/docs/external/src/full-node/configuration.md @@ -0,0 +1,42 @@ +--- +title: "Configuration" +sidebar_position: 7 +--- + +# Configuration + +Required options: + +| Option | Purpose | +| ------------------------- | -------------------------------------------------------- | +| `--data-directory` | Directory containing local node state. | +| `--rpc.listen` | Socket address for the local public RPC API. | +| `--sync.block-source.url` | Upstream RPC URL used for block and proof subscriptions. | + +The rest have sensible default values which should only be tweaked for specific reasons. Use the command help output for +the complete current configuration surface. + +Most options also have environment variable forms, which are useful when running under an orchestrator. + +## OpenTelemetry Traces + +Full nodes can export OpenTelemetry traces using the standard OTLP environment variables. Trace export is enabled when +either of these variables is set to a non-empty value: + +- `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` +- `OTEL_EXPORTER_OTLP_ENDPOINT` + +For example: + +```bash +OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317 \ +OTEL_RESOURCE_ATTRIBUTES=service.instance.id=full-node-1 \ +miden-node full \ + --data-directory full-node-data \ + --rpc.listen 127.0.0.1:57291 \ + --sync.block-source.url http://upstream-node:57291 +``` + +Use `OTEL_RESOURCE_ATTRIBUTES=service.instance.id=` to identify a specific node instance in your tracing +backend. Other standard OpenTelemetry environment variables, such as `OTEL_SERVICE_NAME`, can be used to override the +service name when needed. diff --git a/docs/external/src/full-node/index.md b/docs/external/src/full-node/index.md new file mode 100644 index 0000000000..d9a8702dbd --- /dev/null +++ b/docs/external/src/full-node/index.md @@ -0,0 +1,21 @@ +--- +title: "Full Node Guide" +sidebar_position: 0 +--- + +# Full Node Guide + +Run a full node to synchronize to an existing Miden network. The full node provides the complete gRPC API and can be +used to avoid rate-limiting on official RPC endpoints. This is particularly useful for heavy RPC users and provides a +more robust implementation for explorers and indexers to maintain sync with the network, at the cost of storing the +network data. + +Full nodes can also be daisy-chained to provide horizontal RPC scaling and throughput. + +Use this guide when you want your own RPC endpoint or local replicated state for an existing network. + +The lifecycle pages use the `miden-node` command directly. Choose an installation method first, then follow the quick +start. + +Start with [Installation](/full-node/installation) and [Quick Start](/full-node/quick-start), then use the remaining +pages for detailed bootstrap, operation, RPC, migration, and configuration guidance. diff --git a/docs/external/src/full-node/installation.md b/docs/external/src/full-node/installation.md new file mode 100644 index 0000000000..3ec92631d0 --- /dev/null +++ b/docs/external/src/full-node/installation.md @@ -0,0 +1,71 @@ +--- +title: "Installation" +sidebar_position: 1 +--- + + + +import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; + +# Installation + +The Miden node can be installed as a native binary, or as a Docker image. + + + + +Install the latest node binary from crates.io: + +```bash +cargo install miden-node --locked +``` + +Or install a specific version: + +```bash +cargo install miden-node --version --locked +``` + +Check the installed binary: + +```bash +miden-node --help +``` + +You can also install directly from a repository revision when you need an unreleased version: + +```bash +cargo install miden-node --git https://github.com/0xMiden/node.git --rev --locked +``` + +Create a data directory for node state: + +```bash +mkdir -p full-node-data +``` + + + + +Pull the published image: + +```bash +docker pull ghcr.io/0xmiden/miden-node: +``` + +Check the image: + +```bash +docker run --rm ghcr.io/0xmiden/miden-node: miden-node --help +``` + +Create a Docker volume for node state: + +```bash +docker volume create miden-full-node-data +``` + + + + + diff --git a/docs/external/src/full-node/migrations.md b/docs/external/src/full-node/migrations.md new file mode 100644 index 0000000000..666bf136b5 --- /dev/null +++ b/docs/external/src/full-node/migrations.md @@ -0,0 +1,41 @@ +--- +title: "Migrations" +sidebar_position: 5 +--- + + + +import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; + +# Migrations + +Occasionally, a new node version requires storage schema changes. These can be applied using the `migrate` command after +stopping the node. + + + + +```bash +miden-node migrate --data-directory full-node-data +``` + + + + +```bash +docker run --rm \ + -v miden-full-node-data:/data \ + ghcr.io/0xmiden/miden-node: \ + miden-node migrate --data-directory /data +``` + + + + + + +Backwards migrations are not supported. If a data directory is older than the minimum supported schema version for a +release, migrate forward in stages with older compatible versions first. + +The node will error on startup if any migrations have not been applied. It is safe to run the migration command if all +migrations have already been applied. diff --git a/docs/external/src/full-node/operation.md b/docs/external/src/full-node/operation.md new file mode 100644 index 0000000000..2cca350c5e --- /dev/null +++ b/docs/external/src/full-node/operation.md @@ -0,0 +1,49 @@ +--- +title: "Operation" +sidebar_position: 4 +--- + + + +import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; + +# Operation + +Start a full node with an upstream RPC source: + + + + +```bash +miden-node full \ + --data-directory full-node-data \ + --rpc.listen 127.0.0.1:57291 \ + --sync.block-source.url http://upstream-node:57291 +``` + +Bind `--rpc.listen` to `127.0.0.1` unless the RPC endpoint is intentionally exposed through your own networking layer. + + + + +```bash +docker run --rm --name miden-full-node \ + -v miden-full-node-data:/data \ + -p 127.0.0.1:57291:57291 \ + ghcr.io/0xmiden/miden-node: \ + miden-node full \ + --data-directory /data \ + --rpc.listen 0.0.0.0:57291 \ + --sync.block-source.url http://upstream-node:57291 +``` + +The Docker port publish binds the RPC endpoint to `127.0.0.1` on the host. The node listens on `0.0.0.0` inside the +container so Docker can route the mapped port. + + + + + + +The full node syncs blocks and proofs from the upstream RPC, stores local state, and serves its own RPC API. It does not +produce blocks. diff --git a/docs/external/src/full-node/quick-start.md b/docs/external/src/full-node/quick-start.md new file mode 100644 index 0000000000..cb7e6314ae --- /dev/null +++ b/docs/external/src/full-node/quick-start.md @@ -0,0 +1,78 @@ +--- +title: "Quick Start" +sidebar_position: 2 +--- + + + +import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; + +# Quick Start + +Launch a testnet full node after completing [Installation](/full-node/installation). + + + + +Bootstrap an empty data directory from the official testnet genesis state: + +```bash +miden-node bootstrap \ + --data-directory full-node-data \ + --network testnet +``` + +Start the full node and sync from the official testnet RPC endpoint: + +```bash +miden-node full \ + --data-directory full-node-data \ + --rpc.listen 127.0.0.1:57291 \ + --sync.block-source.url https://rpc.testnet.miden.io +``` + + + + +Bootstrap an empty data volume from the official testnet genesis state: + +```bash +docker run --rm \ + -v miden-full-node-data:/data \ + ghcr.io/0xmiden/miden-node: \ + miden-node bootstrap \ + --data-directory /data \ + --network testnet +``` + +Start the full node and sync from the testnet RPC endpoint: + +```bash +docker run --rm --name miden-full-node \ + -v miden-full-node-data:/data \ + -p 127.0.0.1:57291:57291 \ + ghcr.io/0xmiden/miden-node: \ + miden-node full \ + --data-directory /data \ + --rpc.listen 0.0.0.0:57291 \ + --sync.block-source.url https://rpc.testnet.miden.io +``` + +The Docker port publish binds the RPC endpoint to `127.0.0.1` on the host. The node listens on `0.0.0.0` inside the +container so Docker can route the mapped port. + + + + + + +Check the local RPC endpoint from another terminal: + +```bash +grpcurl -plaintext localhost:57291 rpc.Api/Status +``` + +The `-plaintext` flag is required for the local full node RPC listener because it does not use TLS. + +Replace `testnet`, ``, and `https://rpc.testnet.miden.io` with the network, version, and upstream source +you intend to follow. diff --git a/docs/external/src/full-node/rpc.md b/docs/external/src/full-node/rpc.md new file mode 100644 index 0000000000..ed1c256654 --- /dev/null +++ b/docs/external/src/full-node/rpc.md @@ -0,0 +1,45 @@ +--- +title: "RPC" +sidebar_position: 6 +--- + +# RPC + +A full node serves the public `rpc.Api` service from its local replicated state. Use it as a private or dedicated RPC +endpoint for applications, indexers, explorers, and other infrastructure that should not depend directly on official +public RPC capacity. + +## Local Queries + +Read queries are served from the full node's local state. This includes account, block, note, and sync methods. + +The network-note debugging endpoint, `GetNetworkNoteStatus`, is the exception: it depends on NTX builder state rather +than replicated chain state, so full nodes forward it to the configured upstream RPC source. + +## Transaction Submission + +Full nodes do not sequence transactions. `SubmitProvenTx` and `SubmitProvenTxBatch` are forwarded to the configured +upstream RPC source. If the upstream source is another full node, the request is forwarded again until it reaches the +sequencer. + +This lets clients submit through a nearby full node while preserving the sequencer as the only block-producing node. + +## Scaling Throughput + +Full nodes sync from their upstream source using: + +- `BlockSubscription` for committed signed blocks. +- `ProofSubscription` for block proofs. + +You can daisy-chain full nodes to scale read throughput, and fan out. + +```text + ┌── Full node +Official RPC ── Full node ───┼── Full node + └── Full node +``` + +Each downstream full node subscribes to blocks and proofs from its upstream source, stores local state, and serves its +own read RPC traffic. This can reduce load on the sequencer or official public RPC endpoint. + +See the [RPC subscriptions guide](../rpc/subscriptions) for stream semantics and reconnect behavior. diff --git a/docs/external/src/full-node/troubleshooting.md b/docs/external/src/full-node/troubleshooting.md new file mode 100644 index 0000000000..f37094b80c --- /dev/null +++ b/docs/external/src/full-node/troubleshooting.md @@ -0,0 +1,24 @@ +--- +title: "Troubleshooting" +sidebar_position: 8 +--- + +# Troubleshooting + +## Data Directory Is Empty + +Run `miden-node bootstrap` before starting `miden-node full`. + +## Wrong Genesis + +If the full node was bootstrapped from a different genesis block than its upstream source, recreate the data directory +from the correct trusted genesis source. + +## Subscription Lag + +If the upstream closes a subscription with `DATA_LOSS`, restart sync from the full node's last local tip. Persistent +repeated lag usually means the node or upstream needs more capacity. + +## Port Already In Use + +Change `--rpc.listen` or stop the process already bound to the port. diff --git a/docs/external/src/index.md b/docs/external/src/index.md index b4d1f0afef..f4bc1ae3bc 100644 --- a/docs/external/src/index.md +++ b/docs/external/src/index.md @@ -1,25 +1,17 @@ --- sidebar_position: 0 +title: "Miden Infrastructure Guide" --- -# Introduction +# Miden Infrastructure Guide -Welcome to the Miden node documentation. +This guide covers the infrastructure used to run, sync, and interact with Miden networks. -This book provides two separate guides aimed at node operators and developers looking to contribute to the node -respectively. Each guide is standalone, but developers should also read through the operator guide as it provides some -additional context. +The documentation is roughly organized by audience: -At present, the Miden node is the central hub responsible for receiving user transactions and forming them into new -blocks for a Miden network. As Miden decentralizes, the node will morph into the official reference implementation(s) of -the various components required by a fully p2p network. - -Each Miden network therefore has exactly one node receiving transactions and creating blocks. The node provides a gRPC -interface for users, dApps, wallets and other clients to submit transactions and query the state. - -## Feedback - -Please report any issues, ask questions or leave feedback in the node repository -[here](https://github.com/0xMiden/node/issues/new/choose). - -This includes outdated, misleading, incorrect or just plain confusing information :) +- [gRPC API](./rpc) is the reference for the official Miden RPC API. +- [Local Network Development](./local-network-development) covers spinning up a local network to develop against. +- Check out the [Full Node Guide](./full-node/) to install a node, sync to an official network, serve RPC locally, and + avoid rate limits on official endpoints. +- Use the [Network Operator Guide](./network-operator/) when operating a Miden network's centralized sequencing + infrastructure. diff --git a/docs/external/src/local-network-development.md b/docs/external/src/local-network-development.md new file mode 100644 index 0000000000..ddca71b45e --- /dev/null +++ b/docs/external/src/local-network-development.md @@ -0,0 +1,99 @@ +--- +title: "Local Network Development" +sidebar_position: 1 +--- + +# Local Network Development + +Use this guide to start a disposable Miden network for local development and testing. The provided Docker Compose setup +includes the local network, monitoring, and trace collection, so you can develop against a working environment without +wiring the network services manually. + +The compose files live in the repository: `docker-compose.yml` in the root and supporting files under `compose/`. The +guide uses `make` targets as shorthand for the underlying Docker image builds and Docker Compose commands; check the +`Makefile` when you need the exact command. + +This is not a production deployment guide and it is not the path for independent full node runners on an existing +network. + +## Prerequisites + +- Git +- Docker with Docker Compose support +- `make` + +## Check Out a Version + +Prefer a release tag when testing against released artifacts. Use a branch when developing against the current +repository state. + +```bash +git clone https://github.com/0xMiden/node.git +cd node +git checkout +``` + +## Local Network Commands + +Build the images after checkout or whenever you need fresh local images. The local network stores data in the +`node-data` Docker volume; `local-network-down` keeps that data, while `local-network-delete` removes it. + +```bash +# Build the Docker images used by the local network. +make local-network-build + +# Start the local network. +make local-network-up + +# Follow container logs. +# +# Logs are useful for startup checks; use Tempo traces for request-level debugging. +make local-network-logs + +# Stop the local network, preserving the local chain data volume. +make local-network-down + +# Stop the local network and delete the local chain data volume. +make local-network-delete +``` + +After `make local-network-delete`, run `make local-network-up` to bootstrap a fresh local chain. + +## Exposed Endpoints + +Published ports are bound to `localhost`; the following services are available: + +| Service | URL | Purpose | +| --------------- | ------------------------ | ------------------------------------------------ | +| RPC API | `http://localhost:57291` | Submit transactions and query local chain state. | +| Grafana | `http://localhost:3000` | Inspect dashboards and traces. | +| Network monitor | `http://localhost:3001` | View local network health. | +| Tempo HTTP API | `http://localhost:3200` | Query stored trace data. | +| Tempo OTLP gRPC | `http://localhost:4317` | Receive OpenTelemetry traces from services. | + +## Monitoring and Traces + +The local network exports OpenTelemetry traces to Tempo. Grafana is preconfigured with Tempo as a data source, so use +`http://localhost:3000` to inspect traces when a request fails, stalls, or behaves differently than expected. + +Container logs are still useful for startup failures and quick checks, but traces usually provide a better view of how a +request moved through the local network. + +The network monitor at `http://localhost:3001` provides a compact health view for the running local network. + +## Prover Override + +The default stack spins up an internal prover instance which means proving will happen locally. This can be overridden +to use an external prover by setting `MIDEN_REMOTE_PROVER_URL` when starting the stack. + +## Check the RPC API + +The RPC server exposes gRPC reflection. With `grpcurl` installed, a basic status check looks like: + +```bash +grpcurl -plaintext localhost:57291 rpc.Api/Status +``` + +Note the `-plaintext` flag, the local network does not use TLS. + +Use the [gRPC API](./rpc/) section for the public RPC surface and streaming endpoints. diff --git a/docs/external/src/network-operator/_category_.yml b/docs/external/src/network-operator/_category_.yml new file mode 100644 index 0000000000..e9167fcdfa --- /dev/null +++ b/docs/external/src/network-operator/_category_.yml @@ -0,0 +1,3 @@ +label: "Network Operator Guide" +position: 4 +collapsed: true diff --git a/docs/external/src/network-operator/architecture.md b/docs/external/src/network-operator/architecture.md new file mode 100644 index 0000000000..ddba9ddb65 --- /dev/null +++ b/docs/external/src/network-operator/architecture.md @@ -0,0 +1,44 @@ +--- +title: "Architecture" +sidebar_position: 1 +--- + +# Network Architecture + +A Miden network is operated around one sequencer. The sequencer owns network progression, produces blocks, serves public +RPC, and coordinates with trusted internal services. + +## Example Architecture + +```text +Clients, wallets, applications + | + Load balancer + | + Public RPC full nodes + | + Block/proof subscriptions + | + Sequencer + / | \ + / | \ +Validator NTX builder Remote batch/block provers + | + Remote tx prover + +Network monitor observes RPC, validator, provers, explorer, faucet, and note transport. +``` + +## Components and Roles + +| Component | Binary | Role | Public exposure | +| --------------- | ----------------------- | ------------------------------------------------------------------- | ------------------- | +| Sequencer | `miden-node sequencer` | Produces blocks, owns canonical network progression, and serves RPC | Public RPC only | +| Full node | `miden-node full` | Replicates blocks and proofs and serves local or scaled RPC | Optional public RPC | +| Validator | `miden-validator` | Validates transactions and blocks, then signs blocks | Internal only | +| NTX builder | `miden-ntx-builder` | Builds network transactions from network notes | Internal only | +| Remote prover | `miden-remote-prover` | Offloads transaction, batch, or block proof generation | Internal only | +| Network monitor | `miden-network-monitor` | Provides health checks and an operator dashboard | Operator-facing | + +The repository's Docker Compose setup is useful as a local connectivity reference for these services. Operators should +not treat it as a production deployment model. diff --git a/docs/external/src/network-operator/bootstrap-and-genesis.md b/docs/external/src/network-operator/bootstrap-and-genesis.md new file mode 100644 index 0000000000..fc079c2c91 --- /dev/null +++ b/docs/external/src/network-operator/bootstrap-and-genesis.md @@ -0,0 +1,39 @@ +--- +title: "Bootstrap and Genesis" +sidebar_position: 2 +--- + +# Bootstrap and Genesis + +The validator creates and signs the genesis block. The sequencer node and services that need trusted genesis state are +then initialized from that signed genesis block. + +## Basic Sequence + +Create and sign the genesis block: + +```bash +miden-validator bootstrap \ + --data-directory validator-data \ + --genesis-block-directory genesis-data \ + --accounts-directory accounts +``` + +Initialize the sequencer's node storage from the signed genesis block: + +```bash +miden-node bootstrap \ + --data-directory node-data \ + --file genesis-data/genesis.dat +``` + +Initialize the network transaction builder from the same signed genesis block: + +```bash +miden-ntx-builder bootstrap \ + --data-directory ntx-builder-data \ + --file genesis-data/genesis.dat +``` + +For deployments with external key management, configure the validator key during bootstrap and startup with the +validator's KMS options. The signed genesis block is the trust anchor for every service that joins the network. diff --git a/docs/external/src/network-operator/index.md b/docs/external/src/network-operator/index.md new file mode 100644 index 0000000000..68ed306153 --- /dev/null +++ b/docs/external/src/network-operator/index.md @@ -0,0 +1,11 @@ +--- +title: "Network Operator Guide" +sidebar_position: 0 +--- + +# Network Operator Guide + +Network operators run the centralized services for a Miden network. This includes the sequencer and trusted internal +services such as the validator, network transaction builder, remote provers, and network monitor. + +Start with [Architecture](/network-operator/architecture) for the service roles and a deployment example. diff --git a/docs/external/src/network-operator/monitoring.md b/docs/external/src/network-operator/monitoring.md new file mode 100644 index 0000000000..336e36537d --- /dev/null +++ b/docs/external/src/network-operator/monitoring.md @@ -0,0 +1,27 @@ +--- +title: "Monitoring" +sidebar_position: 7 +--- + +# Monitoring + +Network operators can use `miden-network-monitor` and OpenTelemetry tracing to observe network health, RPC freshness, +validator status, prover status, and related infrastructure. + +## Network Monitor + +`miden-network-monitor` is an observer and test client. It is not required for block production. Depending on +configuration, it can check RPC freshness, validator health, remote prover status, faucet availability, explorer +availability, note transport, and end-to-end network transaction flows. + +Use the binary help output for the current configuration surface: + +```bash +miden-network-monitor start --help +``` + +## Telemetry + +Node services use standard OpenTelemetry environment variables for trace export. The local compose telemetry overlay is +a useful reference for wiring services to an OTLP endpoint, but production deployments should use the operator's own +telemetry backend and retention policy. diff --git a/docs/external/src/network-operator/ntx-builder.md b/docs/external/src/network-operator/ntx-builder.md new file mode 100644 index 0000000000..df389b98e6 --- /dev/null +++ b/docs/external/src/network-operator/ntx-builder.md @@ -0,0 +1,32 @@ +--- +title: "NTX Builder" +sidebar_position: 5 +--- + +# NTX Builder + +The network transaction builder follows committed blocks, tracks network notes, constructs network transactions, proves +them locally or through a remote transaction prover, and submits them through the sequencer RPC. + +## Start + +```bash +miden-ntx-builder start \ + --listen 0.0.0.0:50301 \ + --rpc.url http://sequencer:57291 \ + --data-directory ntx-builder-data +``` + +If a remote transaction prover is available, configure it with: + +```bash +miden-ntx-builder start \ + --listen 0.0.0.0:50301 \ + --rpc.url http://sequencer:57291 \ + --tx-prover.url http://tx-prover:50051 \ + --data-directory ntx-builder-data +``` + +The NTX builder's gRPC API is internal. The sequencer RPC uses it for network-note status queries. + +Use `miden-ntx-builder start --help` for the complete current option list. diff --git a/docs/external/src/network-operator/remote-provers.md b/docs/external/src/network-operator/remote-provers.md new file mode 100644 index 0000000000..0ecada25f0 --- /dev/null +++ b/docs/external/src/network-operator/remote-provers.md @@ -0,0 +1,30 @@ +--- +title: "Remote Provers" +sidebar_position: 6 +--- + +# Remote Provers + +Remote provers offload expensive transaction, batch, or block proof generation to dedicated machines. Each +`miden-remote-prover` instance is configured for one proof type. + +## Start + +Run one prover instance per proof kind: + +```bash +miden-remote-prover --kind transaction --port 50051 +miden-remote-prover --kind batch --port 50052 +miden-remote-prover --kind block --port 50053 +``` + +Connect services to the relevant prover URLs: + +| Consumer | Option | +| ------------------------------- | -------------------- | +| Sequencer batch proving | `--batch-prover.url` | +| Sequencer block proving | `--block-prover.url` | +| NTX builder transaction proving | `--tx-prover.url` | + +Remote provers are internal services. Put load balancing, service discovery, and admission control outside the prover +binary when a deployment needs them. diff --git a/docs/external/src/network-operator/sequencer.md b/docs/external/src/network-operator/sequencer.md new file mode 100644 index 0000000000..5dd367e11e --- /dev/null +++ b/docs/external/src/network-operator/sequencer.md @@ -0,0 +1,36 @@ +--- +title: "Sequencer" +sidebar_position: 3 +--- + +# Sequencer + +The sequencer is centralized network infrastructure operated by the network operator. It runs `miden-node sequencer`, +produces blocks, serves public RPC, and connects to the validator and network transaction builder. + +## Start + +```bash +miden-node sequencer \ + --rpc.listen 0.0.0.0:57291 \ + --data-directory node-data \ + --validator.url http://validator:50101 \ + --ntx-builder.url http://ntx-builder:50301 +``` + +Only the public RPC listener should be externally reachable. The validator, NTX builder, and prover URLs are trusted +internal services. + +## Common Configuration + +| Option | Purpose | +| -------------------- | ------------------------------------------------- | +| `--rpc.listen` | Public RPC socket exposed by the sequencer. | +| `--validator.url` | Internal validator service URL. | +| `--ntx-builder.url` | Internal network transaction builder service URL. | +| `--batch.interval` | Batch production interval. | +| `--block.interval` | Block production interval. | +| `--batch-prover.url` | Optional remote batch prover URL. | +| `--block-prover.url` | Optional remote block prover URL. | + +Use `miden-node sequencer --help` for the complete current option list. diff --git a/docs/external/src/network-operator/upgrades-and-migrations.md b/docs/external/src/network-operator/upgrades-and-migrations.md new file mode 100644 index 0000000000..ef69734a17 --- /dev/null +++ b/docs/external/src/network-operator/upgrades-and-migrations.md @@ -0,0 +1,24 @@ +--- +title: "Upgrades and Migrations" +sidebar_position: 8 +--- + +# Upgrades and Migrations + +Network upgrades may involve binary upgrades, storage migrations, schema changes, and coordinated service restarts. + +## Node Storage Migrations + +Apply pending node storage migrations before starting a newer sequencer or full-node binary: + +```bash +miden-node migrate --data-directory node-data +``` + +Backwards migrations are not supported. If a data directory is older than the minimum supported schema version for the +target binary, migrate forward in stages with older compatible binaries first. + +## Coordination + +Upgrade planning should account for RPC schema compatibility, public client expectations, validator availability, NTX +builder compatibility, prover compatibility, and monitoring coverage before the sequencer is restarted. diff --git a/docs/external/src/network-operator/validator.md b/docs/external/src/network-operator/validator.md new file mode 100644 index 0000000000..4f4d29e5ae --- /dev/null +++ b/docs/external/src/network-operator/validator.md @@ -0,0 +1,22 @@ +--- +title: "Validator" +sidebar_position: 4 +--- + +# Validator + +The validator verifies submitted transactions and proposed blocks before signing blocks for the sequencer. It is an +internal service and should not be exposed publicly. + +## Start + +```bash +miden-validator start \ + --listen 0.0.0.0:50101 \ + --data-directory validator-data +``` + +For local development, the validator can use its default insecure development key. Production deployments should +configure validator signing explicitly, either with a local key or with KMS-backed signing. + +Use `miden-validator start --help` for the complete current option list. diff --git a/docs/external/src/operator/_category_.yml b/docs/external/src/operator/_category_.yml deleted file mode 100644 index 397a6a7e22..0000000000 --- a/docs/external/src/operator/_category_.yml +++ /dev/null @@ -1,4 +0,0 @@ -label: "Node Operator Guide" -# Determines where this documentation section appears relative to other sections in the parent folder -position: 1 -collapsed: true diff --git a/docs/external/src/operator/architecture.md b/docs/external/src/operator/architecture.md deleted file mode 100644 index 2ed5ba9bda..0000000000 --- a/docs/external/src/operator/architecture.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: "Architecture" -sidebar_position: 2 ---- - -# Network architecture - -The network itself consists of five distributed components: store, block-producer, network transaction builder, validator, and RPC. - -The components can be run on separate instances when optimised for performance, but can also be run as a single process -for convenience. At the moment both of Miden's public networks (testnet and devnet) are operating in single process -mode. - -Inter-component communication is done using a gRPC API which is assumed trusted. In other words this _must not_ be -public. External communication is handled by the RPC component with a separate external-only gRPC API. - -The image below shows a rough example of what a network architecture may look like. Only the more important data -flows are pictured to improve clarity. - -[![node architecture](../img/operator_architecture.svg)](../img/operator_architecture.svg) - -## RPC - -The RPC component provides a public gRPC API with which users can submit transactions and query chain state. Queries are -validated and then proxied to the store. Similarly, transaction proofs are verified before submitting them to the -block-producer. This takes a non-trivial amount of load off the block-producer. - -This is the _only_ external facing component and it essentially acts as a shielding proxy that prevents bad requests -from impacting block production. - -It can be trivially scaled horizontally e.g. with a load-balancer in front as shown above. - -## Store - -The store is responsible for persisting the chain state. It is effectively a database which holds the current state of -the chain, wrapped in a gRPC interface which allows querying this state and submitting new blocks. - -It receives new blocks from the block-producer, which it then submits to the validator for signing before it is committed -on chain. It then submits the block to the prover whereafter the block is marked as proven. Blocks therefore undergo -two levels of finalization, `committed` and then `proven`. - -It expects that this gRPC interface is _only_ accessible internally i.e. there is an implicit assumption of trust. - -## Block-producer - -The block-producer is responsible for aggregating received transactions into blocks and submitting them to the store. - -Transactions are placed in a mempool and are periodically sampled to form batches of transactions. These batches are -proved, and then periodically aggregated into a block. This constructed block is sent to the validator, which verifies the -contents of the block before signing the block's commitment and returning the signature to the block-producer. This signed -block is then submitted to the store where it is proven and committed. - -Proof generation in production is typically outsourced to a remote machine with appropriate resources. For convenience, -it is also possible to perform proving in-process. This is useful when running a local node for test purposes. - -## Network transaction builder - -The network transaction builder follows committed blocks for network notes, and creates transactions consuming these. -We call these network transactions and at present this is the only entity that is allowed to create such transactions. -This restriction will be lifted in the future, but for now this component _must_ be enabled to have support for -network transactions. - -Internally, the builder spawns a dedicated actor for each network account that has pending notes. Actors that remain -idle (no notes to consume) for a configurable duration are automatically deactivated to conserve resources, and are -re-activated when new notes arrive. The idle timeout can be tuned with the `--ntx-builder.idle-timeout` CLI -argument (default: 5 minutes). - -Accounts whose actors crash repeatedly (due to database errors) are automatically deactivated after a configurable -number of failures, preventing resource exhaustion. The threshold can be set with -`--ntx-builder.max-account-crashes` (default: 10). - -The builder also exposes an internal gRPC server that the RPC component uses to proxy debugging endpoints such as -`GetNetworkNoteStatus`. In bundled mode this is wired automatically; in distributed mode operators must set -`--ntx-builder.url` (or `MIDEN_NODE_NTX_BUILDER_URL`) on the RPC component. - -## Validator - -The validator is responsible for verifying the integrity of the blockchain by signing new blocks before they can be committed. - -At the moment this is implemented by having all transactions sent here to be re-executed to double-check their integrity. This -also guards against bugs in the proving or execution systems, by backing up the transactions and their private inputs. This -forms part of our training wheels while Miden is maturing. - -The validator signs a new block if: - -- all transactions were previously verified -- block proof is valid -- block delta matches the aggregated transaction deltas -- block header is valid and matches the data -- block builds on the current chain tip diff --git a/docs/external/src/operator/index.md b/docs/external/src/operator/index.md deleted file mode 100644 index f362151a8c..0000000000 --- a/docs/external/src/operator/index.md +++ /dev/null @@ -1,7 +0,0 @@ -# Operator Guide - -Welcome to the `Miden` node operator guide which should cover everything you need to successfully run and maintain a -Miden node. - -You can report any issues, ask questions or leave feedback at our project repo -[here](https://github.com/0xMiden/node/issues/new/choose). diff --git a/docs/external/src/operator/installation.md b/docs/external/src/operator/installation.md deleted file mode 100644 index d7f87fb609..0000000000 --- a/docs/external/src/operator/installation.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -sidebar_position: 3 ---- - -# Installation - -We provide Debian packages for official releases for the node software. Alternatively, it also can be installed from source on most systems using the Rust package manager `cargo`. - -## Debian package - -Official Debian packages are available under our [releases](https://github.com/0xMiden/node/releases) page. -Both `amd64` and `arm64` packages are available. - -Note that the packages include a `systemd` service which is disabled by default. - -To install, download the desired release's `.deb` package and checksum files. Install using - -```sh -sudo dpkg -i $package_name.deb -``` - -You can (and should) verify the checksum prior to installation using a SHA256 utility. This differs from platform to platform, but on most linux distros: - -```sh -sha256sum --check $checksum_file.deb.checksum -``` - -can be used so long as the checksum file and the package file are in the same folder. - -## Install using `cargo` - -Install Rust using the official Rust installation -[instructions](https://www.rust-lang.org/tools/install). - -Depending on the platform, you may need to install additional libraries. For example, on Ubuntu 22.04 the following -command ensures that all required libraries are installed. - -```sh -sudo apt install llvm clang bindgen pkg-config libssl-dev libsqlite3-dev -``` - -On macOS, ensure the Xcode Command Line Tools are installed: - -```sh -xcode-select --install -``` - -If you still see `'cstdint' file not found` errors after installing the Command Line Tools (common after a macOS upgrade), try setting the SDK root explicitly: - -```sh -export SDKROOT="$(xcrun --sdk macosx --show-sdk-path)" -``` - -Install the latest node binary: - -```sh -cargo install miden-node --locked -``` - -This will install the latest official version of the node. You can install a specific version `x.y.z` using - -```sh -cargo install miden-node --locked --version x.y.z -``` - -You can also use `cargo` to compile the node from the source code if for some reason you need a specific git revision. -Note that since these aren't official releases we cannot provide much support for any issues you run into, so consider -this for advanced use only. The incantation is a little different as you'll be targeting our repo instead: - -```sh -# Install from a specific branch -cargo install --locked --git https://github.com/0xMiden/node miden-node --branch - -# Install a specific tag -cargo install --locked --git https://github.com/0xMiden/node miden-node --tag - -# Install a specific git revision -cargo install --locked --git https://github.com/0xMiden/node miden-node --rev -``` - -More information on the various `cargo install` options can be found -[here](https://doc.rust-lang.org/cargo/commands/cargo-install.html#install-options). - -## Updating - -:::warning -We currently have no backwards compatibility guarantees. This means updating your node is destructive - your -existing chain will not work with the new version. This will change as our protocol and database schema mature and -settle. -::: - -Updating the node to a new version is as simple as re-running the install process and repeating the [bootstrapping](./usage#bootstrapping) instructions. diff --git a/docs/external/src/operator/monitoring.md b/docs/external/src/operator/monitoring.md deleted file mode 100644 index 64327e443f..0000000000 --- a/docs/external/src/operator/monitoring.md +++ /dev/null @@ -1,281 +0,0 @@ ---- -title: "Monitoring" -sidebar_position: 5 ---- - -# Monitoring & telemetry - -We provide logging to `stdout` and an optional [OpenTelemetry](https://opentelemetry.io/) exporter for our traces. - -OpenTelemetry exporting can be enabled by specifying `--enable-otel` via the command-line or the -`MIDEN_NODE_ENABLE_OTEL` environment variable when operating the node. - -We do _not_ export OpenTelemetry logs or metrics. Our end goal is to derive these based off of our tracing information. -This approach is known as [wide-events](https://isburmistrov.substack.com/p/all-you-need-is-wide-events-not-metrics), -[structured logs](https://newrelic.com/blog/how-to-relic/structured-logging), and -[Observability 2.0](https://www.honeycomb.io/blog/time-to-version-observability-signs-point-to-yes). - -What we're exporting are `traces` which consist of `spans` (covering a period of time), and `events` (something happened -at a specific instance in time). These are extremely useful to debug distributed systems - even though `miden` is still -centralized, the `node` components are distributed. - -OpenTelemetry provides a -[Span Metrics Converter](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/connector/spanmetricsconnector) -which can be used to convert our traces into more conventional metrics. - -## What gets traced - -We assign a unique trace (aka root span) to each RPC request, batch build, and block build process. - -
- -Span and attribute naming is unstable and should not be relied upon. This also means changes here will not be considered -breaking, however we will do our best to document them. - -
- -### RPC request/response - -Not yet implemented. - -### Block building - -This trace covers the building, proving and submission of a block. - -
- Span tree - -```sh -block_builder.build_block -┝━ block_builder.select_block -│ ┝━ mempool.lock -│ ┕━ mempool.select_block -┝━ block_builder.get_block_inputs -│ ┝━ block_builder.summarize_batches -│ ┕━ store.state.get_block_inputs -│ ┝━ select_note_inclusion_proofs -│ ┕━ select_block_headers -┝━ block_builder.prove_block -│ ┝━ execute_program -│ ┕━ block_builder.simulate_proving -┝━ block_builder.inject_failure -┕━ block_builder.commit_block - ┝━ store.state.apply_block_with_proving_inputs - │ ┕━ apply_block - │ ┝━ select_block_header_by_block_num - │ ┕━ update_in_memory_structs - ┝━ mempool.lock - ┕━ mempool.commit_block - ┕━ mempool.revert_expired_transactions - ┕━ mempool.revert_transactions -``` - -
- -### Batch building - -This trace covers the building and proving of a batch. - -
- Span tree - -```sh -batch_builder.build_batch -┝━ batch_builder.wait_for_available_worker -┝━ batch_builder.select_batch -│ ┝━ mempool.lock -│ ┕━ mempool.select_batch -┝━ batch_builder.get_batch_inputs -│ ┕━ store.state.get_batch_inputs -┝━ batch_builder.propose_batch -┝━ batch_builder.prove_batch -┝━ batch_builder.inject_failure -┕━ batch_builder.commit_batch - ┝━ mempool.lock - ┕━ mempool.commit_batch -``` - -
- -## Verbosity - -We log important spans and events at `info` level or higher, which is also the default log level. - -Changing this level should rarely be required - let us know if you're missing information that should be at `info`. - -The available log levels are `trace`, `debug`, `info` (default), `warn`, `error` which can be configured using the -`RUST_LOG` environment variable e.g. - -```sh -export RUST_LOG=debug -``` - -The verbosity can also be specified by component: - -```sh -export RUST_LOG=warn,block-producer=debug,rpc=error -``` - -The above would set the general level to `warn`, and the `block-producer` and `rpc` components would be overridden to -`debug` and `error` respectively. Though as mentioned, it should be unusual to do this. - -## Configuration - -The OpenTelemetry trace exporter is enabled by adding the `--enable-otel` flag to each component's start command: - -```sh -miden-node store start --enable-otel -miden-node block-producer start --enable-otel -miden-node rpc start --enable-otel -``` - -The exporter can be configured using environment variables as specified in the official -[documents](https://opentelemetry.io/docs/specs/otel/protocol/exporter/). - -
-Not all options are fully supported. We are limited to what the Rust OpenTelemetry implementation supports. If you have any problems please open an issue and we'll do our best to resolve it. - -Note: we only support gRPC as the export protocol. - -
- -#### Example: Honeycomb configuration - -This is based off Honeycomb's OpenTelemetry -[setup guide](https://docs.honeycomb.io/send-data/opentelemetry/#using-the-honeycomb-opentelemetry-endpoint). - -```sh -OTEL_EXPORTER_OTLP_ENDPOINT=https://api.honeycomb.io:443 \ -OTEL_EXPORTER_OTLP_HEADERS="x-honeycomb-team=your-api-key" \ -miden-node store start --enable-otel -``` - -### Honeycomb queries, triggers and board examples - -#### Example Queries - -Here are some useful Honeycomb queries to help monitor your Miden node: - -**Block building performance**: - -```honeycomb -VISUALIZE -HEATMAP(duration_ms) AVG(duration_ms) -WHERE -name = "block_builder.build_block" -GROUP BY block.number -ORDER BY block.number DESC -LIMIT 100 -``` - -**Batch processing latency**: - -```honeycomb -VISUALIZE -HEATMAP(duration_ms) AVG(duration_ms) P95(duration_ms) -WHERE -name = "batch_builder.build_batch" -GROUP BY batch.id -LIMIT 100 -``` - -**Block proving failures**: - -```honeycomb -VISUALIZE -COUNT -WHERE -name = "block_builder.build_block" -AND status = "error" -CALCULATE RATE -``` - -**Transaction volume by block**: - -```honeycomb -VISUALIZE -MAX(transactions.count) -WHERE -name = "block_builder.build_block" -GROUP BY block.number -ORDER BY block.number DESC -LIMIT 100 -``` - -**RPC request rate by endpoint**: - -```honeycomb -VISUALIZE -COUNT -WHERE -name contains "rpc" -GROUP BY name -``` - -**RPC latency by endpoint**: - -```honeycomb -VISUALIZE -AVG(duration_ms) P95(duration_ms) -WHERE -name contains "rpc" -GROUP BY name -``` - -**RPC errors by status code**: - -```honeycomb -VISUALIZE -COUNT -WHERE -name contains "rpc" -GROUP BY status_code -``` - -#### Example Triggers - -Create triggers in Honeycomb to alert you when important thresholds are crossed: - -**Slow block building**: - -- Query: - -```honeycomb -VISUALIZE -AVG(duration_ms) -WHERE -name = "block_builder.build_block" -``` - -- Trigger condition: `AVG(duration_ms) > 30000` (adjust based on your expected block time) -- Description: Alert when blocks take too long to build (more than 30 seconds on average) - -**High failure rate**: - -- Query: - -```honeycomb -VISUALIZE -COUNT -WHERE -name = "block_builder.build_block" AND error = true -``` - -- Trigger condition: `COUNT > 100 WHERE error = true` -- Description: Alert when more than 100 block builds are failing - -#### Advanced investigation with BubbleUp - -To identify the root cause of performance issues or errors, use Honeycomb's BubbleUp feature: - -1. Create a query for a specific issue (e.g., high latency for block building) -2. Click on a specific high-latency point in the visualization -3. Use BubbleUp to see which attributes differ significantly between normal and slow operations -4. Inspect the related spans in the trace to pinpoint the exact step causing problems - -This approach helps identify patterns like: - -- Which types of transactions are causing slow blocks -- Which specific operations within block/batch processing take the most time -- Correlations between resource usage and performance -- Common patterns in error cases diff --git a/docs/external/src/operator/usage.md b/docs/external/src/operator/usage.md deleted file mode 100644 index 2167c88bab..0000000000 --- a/docs/external/src/operator/usage.md +++ /dev/null @@ -1,259 +0,0 @@ ---- -sidebar_position: 4 ---- - -# Configuration and Usage - -As outlined in the [Architecture](./architecture) chapter, the node consists of several components which are run -as separate processes. The recommended way to operate a node locally is using `docker compose`, which starts each -component in its own container and automatically bootstraps on first run. Operating the components without Docker -is also straightforward using the individual CLI subcommands. - -This guide focuses on basic usage. To discover more advanced options we recommend exploring the various help menus -which can be accessed by appending `--help` to any of the commands. - -## Bootstrapping - -The first step in starting a new Miden network is to initialize the genesis block data. This is a -two-step process: first the validator signs and creates the genesis block, then the store initializes -its database from that block. By default the genesis block will contain a single faucet account. - -```sh -# Step 1: Validator bootstrap — create the signed genesis block and account files. -miden-validator bootstrap \ - --genesis-block-directory genesis-data \ - --accounts-directory accounts - -# Step 2: Node bootstrap — initialize the node database from the genesis block. -miden-node bootstrap \ - --data-directory store-data \ - --file genesis-data/genesis.dat -``` - -You can also configure the account and asset data in the genesis block by passing in a toml configuration file. -This is particularly useful for setting up test scenarios without requiring multiple rounds of -transactions to achieve the desired state. Any account secrets will be written to disk inside the -provided `--accounts-directory` path in the process. - -```sh -miden-validator bootstrap \ - --genesis-block-directory genesis-data \ - --accounts-directory accounts \ - --genesis-config-file genesis.toml -``` - -The genesis configuration file should contain fee parameters, optionally a custom native faucet, -optionally other fungible faucets, and also optionally, wallet definitions with assets, for example: - -```toml -# The UNIX timestamp of the genesis block. It will influence the hash of the genesis block. -timestamp = 1717344256 -# Defines the format of the block protocol to use for the genesis block. -version = 1 - -# The native faucet defaults to a MIDEN token (symbol="MIDEN", decimals=6, -# max_supply=100_000_000_000_000_000). To override it with a pre-built account -# file, specify the path: -# -# native_faucet = "path/to/faucet.mac" -# -# The path is relative to this configuration file. - -# The fee parameters to use for the genesis block. -[fee_parameters] -verification_base_fee = 0 - -# Another fungible faucet (optional) to initialize at genesis. -[[fungible_faucet]] -# The token symbol to use for the token -symbol = "FUZZY" -# Number of decimals your token will have, it effectively defines the fixed point accuracy. -decimals = 6 -# Total supply, in _base units_ -# -# e.g. a max supply of `1e15` _base units_ and decimals set to `6`, will yield you a total supply -# of `1e15/1e6 = 1e9` `FUZZY`s. -max_supply = 1_000_000_000_000_000 -# Account type of the faucet account. -account_type = "public" - - -[[wallet]] -# List of all assets the account should hold. Each token type _must_ have a corresponding faucet. -# The number is in _base units_, e.g. specifying `999 FUZZY` at 6 decimals would become -# `999_000_000`. -assets = [{ amount = 999_000_000, symbol = "FUZZY" }] -# Account type of the wallet account. -account_type = "private" -``` - -To include pre-built accounts (e.g. bridge or wrapped-asset faucets) in the genesis block, use -`[[account]]` entries with paths to `.mac` files: - -```toml -[[account]] -path = "bridge.mac" - -[[account]] -path = "eth_faucet.mac" -``` - -## Operation - -### Using docker compose - -Build the Docker image and start the node. Bootstrap happens automatically on first run. -The default `compose-up` target starts all node components along with a telemetry stack -([Tempo](https://grafana.com/oss/tempo/) + [Grafana](https://grafana.com/oss/grafana/)) and -a network monitor: - -```sh -make docker-build -make docker-build-monitor -make compose-genesis -make compose-up -``` - -This starts: - -- All node components (store, validator, block-producer, rpc, ntx-builder) with OpenTelemetry tracing enabled -- **Tempo** — receives OTLP traces from the node on port `4317`, HTTP API on port `3200` -- **Grafana** — pre-configured with a Tempo datasource and a Miden Node dashboard, available at `http://localhost:3000` -- **Network monitor** — monitors the local node, available at `http://localhost:3001` - -Follow logs: - -```sh -make compose-logs -``` - -Stop the node: - -```sh -make compose-down -``` - -Teardown and regenesis: - -```sh -make compose-genesis -``` - -### Running components individually - -A convenience script is provided that bootstraps and starts all components as separate processes: - -```sh -./scripts/run-node.sh -``` - -To avoid genesis and simply restart from a previous run: - -```sh -SKIP_BOOTSTRAP=true scripts/run-node.sh -``` - -Each component can also be started as a standalone process. For example: - -```sh -# Start the store -miden-node store start \ - --rpc.listen 0.0.0.0:50001 \ - --block-producer.listen 0.0.0.0:50003 \ - --data-directory /tmp/store - -# Start the validator -miden-validator start --listen 0.0.0.0:50101 \ - --data-directory /tmp/validator - -# Start the block producer -miden-node block-producer start --listen 0.0.0.0:50201 \ - --store.url http://127.0.0.1:50003 \ - --validator.url http://127.0.0.1:50101 - -# Start the RPC server -miden-node rpc start \ - --listen 0.0.0.0:57291 \ - --store.url http://127.0.0.1:50001 \ - --block-producer.url http://127.0.0.1:50201 \ - --validator.url http://127.0.0.1:50101 - -# Start the network transaction builder -miden-node ntx-builder start \ - --listen 0.0.0.0:50301 \ - --store.url http://127.0.0.1:50001 \ - --block-producer.url http://127.0.0.1:50201 \ - --validator.url http://127.0.0.1:50101 \ - --data-directory /tmp/ntx-builder -``` - -### SQLite pools - -The store, validator, and network transaction builder use SQLite connection pools for database -queries. By default, each pool size is twice the number of available CPU cores. Override it with -`--sqlite.connection_pool_size` or the component-specific environment variable: - -- `MIDEN_NODE_STORE_SQLITE_CONNECTION_POOL_SIZE` -- `MIDEN_NODE_VALIDATOR_SQLITE_CONNECTION_POOL_SIZE` -- `MIDEN_NODE_NTX_BUILDER_SQLITE_CONNECTION_POOL_SIZE` - -### gRPC server limits and timeouts - -The RPC component enforces per-request timeouts, per-IP rate limits, and global concurrency caps. Configure these -settings with the following options: - -- `--grpc.timeout` (default `10s`): Maximum request duration before the server drops the request. -- `--grpc.max_connection_age` (default `30m`): Maximum lifetime of a connection before the server closes it. -- `--grpc.burst_size` (default `128`): Per-IP burst capacity before rate limiting kicks in. -- `--grpc.replenish_per_sec` (default `16`): Per-IP request credits replenished per second. -- `--grpc.max_global_connections` (default `1000`): Maximum concurrent gRPC connections across all clients. - -## Systemd - -Our [Debian packages](./installation.md#debian-package) install a systemd service which operates the node in `bundled` -mode. You'll still need to run the [bootstrapping](#bootstrapping) process before the node can be started. - -You can inspect the service file with `systemctl cat miden-node` or alternatively you can see it in -our repository in the `packaging` folder. For the bootstrapping process be sure to specify the data-directory as -expected by the systemd file. - -## RocksDB tuning - -The store uses RocksDB for the account and nullifier trees, one instance each. The two most impactful knobs per tree -are exposed as CLI flags (also available as environment variables): - -| Flag | Default | Notes | -|---|---|---| -| `--account_tree.rocksdb.max_cache_size` | 2 GiB | Shared LRU block cache. Increase on memory-rich hosts. | -| `--account_tree.rocksdb.max_open_fds` | 64 | Raise to 512+ when `ulimit -n` allows. | -| `--nullifier_tree.rocksdb.max_cache_size` | 2 GiB | Same as above for the nullifier tree. | -| `--nullifier_tree.rocksdb.max_open_fds` | 64 | Same as above for the nullifier tree. | - -Compaction parallelism is set automatically to the number of available CPU cores. - -```sh -miden-node store start \ - --data-directory data \ - --rpc.listen 0.0.0.0:57291 \ - --account_tree.rocksdb.max_cache_size 4294967296 \ - --account_tree.rocksdb.max_open_fds 512 \ - --nullifier_tree.rocksdb.max_cache_size 4294967296 \ - --nullifier_tree.rocksdb.max_open_fds 512 -``` - -## Environment variables - -Most configuration options can also be configured using environment variables as an alternative to providing the values -via the command-line. This is useful for certain deployment options like `docker`, where they can be easier -to define or inject instead of changing the underlying command line options. - -These are especially convenient where multiple different configuration profiles are used. Write the environment -variables to some specific `profile.env` file and load it as part of the node command: - -```sh -source profile.env && miden-node <...> -``` - -This works well on Linux and MacOS, but Windows requires some additional scripting unfortunately. - -See the `.env` files in each of the binary crates' [directories](https://github.com/0xMiden/node/tree/next/bin) for a list of all available environment variables. diff --git a/docs/external/src/operator/versioning.md b/docs/external/src/operator/versioning.md deleted file mode 100644 index d3d6bad943..0000000000 --- a/docs/external/src/operator/versioning.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -sidebar_position: 6 ---- - -# Versioning - -We follow the [semver](https://semver.org/) standard for versioning. - -The following is considered the node's public API, and will therefore be considered as breaking changes. - -- RPC gRPC specification (note that this _excludes_ internal inter-component gRPC schemas). -- Node configuration options. -- Large protocol and behavioral changes. - -We intend to include our OpenTelemetry trace specification in this once it stabilizes. - -We _will_ also call out non-breaking behavioral changes in our changelog and release notes. diff --git a/docs/external/src/rpc.md b/docs/external/src/rpc.md deleted file mode 100644 index c530bd96f2..0000000000 --- a/docs/external/src/rpc.md +++ /dev/null @@ -1,244 +0,0 @@ ---- -title: "Node gRPC Reference" -sidebar_position: 1 ---- - -# gRPC Reference - -This is a reference of the Node's public RPC interface. It consists of a gRPC API which may be used to submit transactions and query the state of the blockchain. - -The gRPC service definition can be found in the Miden node's `proto` [directory](https://github.com/0xMiden/node/tree/main/proto) in the `rpc.proto` file. - - - -- [GetAccount](#getaccount) -- [GetBlockByNumber](#getblockbynumber) -- [GetBlockHeaderByNumber](#getblockheaderbynumber) -- [GetLimits](#getlimits) -- [GetNetworkNoteStatus](#getnetworknotestatus) -- [GetNotesById](#getnotesbyid) -- [GetNoteScriptByRoot](#getnotescriptbyroot) -- [BlockSubscription](#blocksubscription) -- [ProofSubscription](#proofsubscription) -- [Status](#status) -- [SubmitProvenTx](#submitproventx) -- [SyncAccountStorageMaps](#syncaccountstoragemaps) -- [SyncAccountVault](#syncaccountvault) -- [SyncChainMmr](#syncchainmmr) -- [SyncNotes](#syncnotes) -- [SyncNullifiers](#syncnullifiers) -- [SyncTransactions](#synctransactions) - - - -## API Endpoints - -### GetAccount - -Request an account witness (Merkle proof of inclusion in the account tree) and optionally account details. - -The witness proves the account's state commitment in the account tree. If details are requested, the response also includes the account's header, code, vault assets, and storage data. Account details are only available for public accounts. - -If `block_num` is provided, returns the state at that historical block; otherwise, returns the latest state. - -#### Error Codes - -When the request fails, detailed error information is provided through gRPC status details. The following error codes may be returned: - -| Error Code | Value | gRPC Status | Description | -|---------------------------|-------|--------------------|------------------------------------------------------| -| `INTERNAL_ERROR` | 0 | `INTERNAL` | Internal server error occurred | -| `DESERIALIZATION_FAILED` | 1 | `INVALID_ARGUMENT` | Request could not be deserialized | -| `ACCOUNT_NOT_FOUND` | 2 | `INVALID_ARGUMENT` | Account not found at the requested block | -| `ACCOUNT_NOT_PUBLIC` | 3 | `INVALID_ARGUMENT` | Account details requested for a non-public account | -| `UNKNOWN_BLOCK` | 4 | `INVALID_ARGUMENT` | Requested block number is unknown | -| `BLOCK_PRUNED` | 5 | `INVALID_ARGUMENT` | Requested block has been pruned | - -### GetBlockByNumber - -Request the raw data for a specific block. - -### GetBlockHeaderByNumber - -Request a specific block header and its inclusion proof. - -### GetLimits - -Returns the query parameter limits configured for RPC endpoints. - -This endpoint allows clients to discover the maximum number of items that can be requested in a single call for various endpoints. The response contains a map of endpoint names to their parameter limits. - -**Example response structure:** - -```json -{ - "endpoints": { - "SyncNullifiers": { "parameters": { "nullifier": 1000 } }, - "SyncTransactions": { "parameters": { "account_id": 1000 } }, - "SyncAccountVault": { "parameters": { "account_id": 1000 } }, - "SyncAccountStorageMaps": { "parameters": { "account_id": 1000 } }, - "SyncNotes": { "parameters": { "note_tag": 1000 } }, - "GetNotesById": { "parameters": { "note_id": 100 } } - } -} -``` - -### GetNotesById - -Request a set of notes. - -**Limits:** `note_id` (100) - -### GetNetworkNoteStatus - -Returns the current lifecycle status of a network note. The status indicates where the note is in its lifecycle: pending execution, processed (consumed by a transaction in the mempool), or discarded after too many failed attempts. The response also includes the latest execution error, if any. - -This endpoint is only available when the network transaction builder is enabled and connected. If it is not configured, the endpoint returns `UNAVAILABLE`. - -#### Request - -```protobuf -message NoteId { - Digest id = 1; // The note ID -} -``` - -#### Response - -```protobuf -enum NetworkNoteStatus { - NETWORK_NOTE_STATUS_UNSPECIFIED = 0; - NETWORK_NOTE_STATUS_PENDING = 1; // Awaiting execution or being retried - NETWORK_NOTE_STATUS_NULLIFIER_INFLIGHT = 2; // Consumed by a transaction sent to block producer - NETWORK_NOTE_STATUS_DISCARDED = 3; // Exceeded max retries, will not be retried - NETWORK_NOTE_STATUS_NULLIFIER_COMMITTED = 4; // Consuming transaction committed on-chain -} - -message GetNetworkNoteStatusResponse { - NetworkNoteStatus status = 1; // Current lifecycle status - optional string last_error = 2; // The latest error message, if any - uint32 attempt_count = 3; // Number of failed execution attempts - optional fixed32 last_attempt_block_num = 4; // Block number of the last failed attempt, if any -} -``` - -If the note is not found in the network transaction builder's database, the endpoint returns `NOT_FOUND`. - -### GetNoteScriptByRoot - -Request the script for a note by its root. - -### BlockSubscription - -Streams committed blocks starting from `block_from` inclusive. - -Each stream item contains the serialized signed block and the committed chain tip observed when -the item was emitted. - -### ProofSubscription - -Streams block proofs starting from `block_from` inclusive. - -Each stream item contains the block number, serialized block proof, and the proven chain tip -observed when the item was emitted. - -### Status - -Request the status of the node components. The response contains the current version of the RPC component and the connection status of the other components, including their versions and the number of the most recent block in the chain (chain tip). - -### SubmitProvenTx - -Submit a transaction to the network. - -This endpoint accepts a proven transaction and attempts to add it to the mempool for inclusion in future blocks. The transaction must be properly formatted and include a valid execution proof. - -#### Error Codes - -When transaction submission fails, detailed error information is provided through gRPC status details. The following error codes may be returned: - -| Error Code | Value | gRPC Status | Description | -|-----------------------------------------------|-------|--------------------|---------------------------------------------------------------| -| `INTERNAL_ERROR` | 0 | `INTERNAL` | Internal server error occurred | -| `DESERIALIZATION_FAILED` | 1 | `INVALID_ARGUMENT` | Transaction could not be deserialized | -| `INVALID_TRANSACTION_PROOF` | 2 | `INVALID_ARGUMENT` | Transaction execution proof is invalid | -| `INCORRECT_ACCOUNT_INITIAL_COMMITMENT` | 3 | `INVALID_ARGUMENT` | Account's initial state doesn't match current state | -| `INPUT_NOTES_ALREADY_CONSUMED` | 4 | `INVALID_ARGUMENT` | Input notes have already been consumed by another transaction | -| `UNAUTHENTICATED_NOTES_NOT_FOUND` | 5 | `INVALID_ARGUMENT` | Required unauthenticated notes were not found | -| `OUTPUT_NOTES_ALREADY_EXIST` | 6 | `INVALID_ARGUMENT` | Output note IDs are already in use | -| `TRANSACTION_EXPIRED` | 7 | `INVALID_ARGUMENT` | Transaction has exceeded its expiration block height | - -### SyncAccountStorageMaps - -Returns storage map synchronization data for a specified public account within a given block range. This method allows clients to efficiently sync the storage map state of an account by retrieving only the changes that occurred between two blocks. - -Caller specifies the `account_id` of the public account and the block range (`block_from`, `block_to`) for which to retrieve storage updates. The response includes all storage map key-value updates that occurred within that range, along with the last block included in the sync and the current chain tip. - -This endpoint enables clients to maintain an updated view of account storage. - -### SyncAccountVault - -Returns information that allows clients to sync asset values for specific public accounts within a block range. - -For any `[block_from..block_to]` range, the latest known set of assets is returned for the requested account ID. The data can be split and a cutoff block may be selected if there are too many assets to sync. The response contains the chain tip so that the caller knows when it has been reached. - -### SyncChainMmr - -Returns MMR delta information needed to synchronize the chain MMR within a block range. - -Caller specifies the `block_range`, starting from the last block already represented in its local MMR. The response contains the MMR delta for the requested range, but at most to (including) the chain tip. - -### SyncNotes - -Iteratively sync data for a given set of note tags. - -Client specifies the `note_tags` they are interested in, and the block range from which to search for matching notes. The request will then return the next block containing any note matching the provided tags within the specified range. - -The response includes each note's metadata and inclusion proof. - -A basic note sync can be implemented by repeatedly requesting the previous response's block until reaching the tip of the chain. - -**Limits:** `note_tag` (1000) - -### SyncNullifiers - -Returns nullifier synchronization data for a set of prefixes within a given block range. This method allows clients to efficiently track nullifier creation by retrieving only the nullifiers produced between two blocks. - -Caller specifies the `prefix_len` (currently only 16), the list of prefix values (`nullifiers`), and the block range (`block_from`, optional `block_to`). The response includes all matching nullifiers created within that range, the last block included in the response (`block_num`), and the current chain tip (`chain_tip`). - -If the response is chunked (i.e., `block_num < block_to`), continue by issuing another request with `block_from = block_num + 1` to retrieve subsequent updates. - -**Limits:** `nullifier` (1000) - -### SyncTransactions - -Returns transaction records for specific accounts within a block range. - -## Error Handling - -The Miden node uses standard gRPC error reporting mechanisms. When an RPC call fails, a `Status` object is returned containing: - -- **Status Code**: Standard gRPC status codes (`INVALID_ARGUMENT`, `INTERNAL`, etc.). -- **Message**: Human-readable error description. -- **Details**: Additional structured error information (when available). - -For critical operations like transaction submission, detailed error codes are provided in the `Status.details` field to help clients understand the specific failure reason and take appropriate action. - -### Error Details Format - -The `Status.details` field contains the specific error code serialized as raw bytes: - -- **Format**: Single byte containing the numeric error code value -- **Decoding**: Read the first byte to get the error code -- **Mapping**: Map the numeric value to the corresponding error enum - -**Example decoding** (pseudocode): - -``` -if status.details.length > 0: - error_code = status.details[0] // Extract first byte - switch error_code: - case 1: return "INTERNAL_ERROR" - case 2: return "DESERIALIZATION_FAILED" - case 5: return "INPUT_NOTES_ALREADY_CONSUMED" - // ... etc -``` diff --git a/docs/external/src/rpc/_category_.yml b/docs/external/src/rpc/_category_.yml new file mode 100644 index 0000000000..c260a9788b --- /dev/null +++ b/docs/external/src/rpc/_category_.yml @@ -0,0 +1,3 @@ +label: "gRPC API" +position: 3 +collapsed: false diff --git a/docs/external/src/rpc/errors-and-limits.md b/docs/external/src/rpc/errors-and-limits.md new file mode 100644 index 0000000000..12705d832e --- /dev/null +++ b/docs/external/src/rpc/errors-and-limits.md @@ -0,0 +1,90 @@ +--- +title: "Errors and Limits" +sidebar_position: 3 +--- + +# Errors and Limits + +The Miden RPC API uses standard gRPC status codes. Individual methods may also return structured details defined by the +protobuf schema or encoded by the server implementation. + +## Structured Error Details + +Some methods encode a method-specific error enum in addition to the conventional gRPC error code. This error enum is +encoded in the gRPC status `details` field, allowing clients to branch on more detailed error conditions. + +When present, the detail payload contains the method-specific error code as a single raw byte. This byte can be +interpreted as per the per-method tables below. + +```text +if status.details is not empty: + error_code = status.details[0] + # Interpret error_code using the failed method's table. +else: + # Fall back to the gRPC status code and message. +``` + +Only method-specific failures with documented additional codes set the details byte. Other validation errors, including +malformed requests, unsupported content negotiation, missing genesis data, and failed proof checks, return ordinary gRPC +statuses without a Miden error detail code. The error message remains applicable in all cases, but should be considered +unstable and it is not recommended to match on it. + +If you are missing specific error information that could be useful, please open an issue in the +[Node Repository](https://github.com/0xMiden/node). + +## Transaction Submission Errors + +`SubmitProvenTx` and `SubmitProvenTxBatch` may return the following detail codes when a transaction or batch reaches the +sequencer's mempool and is rejected. + +| Error | Value | gRPC status | Meaning | +| ------------------ | ----- | ------------------ | --------------------------- | +| `Internal` | `0` | `INTERNAL` | Internal submission failure | +| `Expired` | `1` | `INVALID_ARGUMENT` | Transaction expired | +| `StateConflict` | `2` | `INVALID_ARGUMENT` | State conflict | +| `CapacityExceeded` | `3` | `INVALID_ARGUMENT` | Mempool capacity exceeded | + +`Expired` means the transaction or batch has expired, or will expire too soon for the sequencer to consider accepting +it. + +`StateConflict` is intentionally coarse. It can represent spent nullifiers, duplicate output notes, missing +unauthenticated input notes, or an account initial commitment mismatch. Use the status message for the specific +conflict, and use the detail byte when a client needs stable branching between broad submission failure classes. + +`CapacityExceeded` means the mempool capacity has been exhausted and is under load. + +## Request Limits + +Use `GetLimits` to discover method-specific request limits before sending large sync requests. Methods such as +`SyncNotes`, `SyncNullifiers`, and `GetNotesById` may reject requests that exceed the configured limit. Split larger +requests into smaller batches. + +The limits are returned in `json` format as follows: + +```json +{ + "endpoints": { + "CheckNullifiers": { "parameters": { "nullifier": 1000 } }, + "SyncNullifiers": { "parameters": { "nullifier": 1000 } }, + "SyncTransactions": { "parameters": { "account_id": 1000 } }, + "SyncAccountVault": { "parameters": { "account_id": 1000 } }, + "SyncAccountStorageMaps": { "parameters": { "account_id": 1000 } }, + "SyncNotes": { "parameters": { "note_tag": 1000 } }, + "GetNotesById": { "parameters": { "note_id": 100 } } + } +} +``` + +## Content Negotiation + +The RPC server checks the `Accept` header for Miden-specific media parameters: + +```text +application/vnd.miden; version=; genesis= +``` + +Both parameters are optional for read requests. Write requests, including `SubmitProvenTx` and `SubmitProvenTxBatch`, +require the `genesis` parameter so the client explicitly targets the intended network. + +The server accepts compatible major/minor RPC versions. Stable versions allow patch flexibility. Pre-release versions +must match the pre-release label and patch version expected by the server. diff --git a/docs/external/src/rpc/index.md b/docs/external/src/rpc/index.md new file mode 100644 index 0000000000..1500d3fd92 --- /dev/null +++ b/docs/external/src/rpc/index.md @@ -0,0 +1,59 @@ +--- +title: "gRPC API" +sidebar_position: 0 +--- + +# gRPC API + +Miden nodes expose a public gRPC API for querying chain state, synchronizing local state, submitting proven +transactions, and subscribing to committed blocks and block proofs. + +The API uses standard gRPC status codes. Some methods also include additional Miden-specific error codes in status +details for stable client-side handling. + +The official networks are served at `https://rpc.testnet.miden.io` and `https://rpc.devnet.miden.io`. + +## Schema + +The safest way to inspect the schema for a deployed network is through gRPC reflection: + +```bash +grpcurl rpc.testnet.miden.io:443 describe rpc.Api +``` + +For a local development network without TLS, use `-plaintext`: + +```bash +grpcurl -plaintext localhost:57291 describe rpc.Api +``` + +For Rust developers, we also ship a Rust crate +[miden_node_proto_build](https://docs.rs/miden-node-proto-build/latest/miden_node_proto_build/) which exposes the gRPC +schemas as file descriptor sets, which can be used to generate the gRPC bindings using [tonic](https://docs.rs/tonic). + +The source schema files are also available in the [Miden node repository](https://github.com/0xMiden/node), in the +`proto/` directory. If you use the repository source instead of reflection, check out the release tag that matches the +network or client version you are targeting. Branches such as `next` describe repository state, not necessarily the +schema deployed on an official network. + +## Protocol Support + +The RPC server supports: + +- gRPC over HTTP/2. +- gRPC-Web. +- gRPC reflection for discovery tools such as `grpcurl`. + +## Endpoint Groups + +| Group | Methods | +| ---------------------- | --------------------------------------------------------------------------------------------------------------- | +| Status and limits | `Status`, `GetLimits` | +| State queries | `GetAccount`, `GetBlockByNumber`, `GetBlockHeaderByNumber`, `GetNotesById`, `GetNoteScriptByRoot` | +| Transaction submission | `SubmitProvenTx`, `SubmitProvenTxBatch` | +| State synchronization | `SyncTransactions`, `SyncNotes`, `SyncNullifiers`, `SyncAccountVault`, `SyncAccountStorageMaps`, `SyncChainMmr` | +| Block streaming | `BlockSubscription`, `ProofSubscription` | +| Network note debugging | `GetNetworkNoteStatus` | + +See [Public RPC](/rpc/public-api) for endpoint summaries, [Subscriptions](/rpc/subscriptions) for stream semantics, and +[Errors and Limits](/rpc/errors-and-limits) for request limits, content negotiation, and method-specific error codes. diff --git a/docs/external/src/rpc/public-api.md b/docs/external/src/rpc/public-api.md new file mode 100644 index 0000000000..efd9ab7b21 --- /dev/null +++ b/docs/external/src/rpc/public-api.md @@ -0,0 +1,82 @@ +--- +title: "Public RPC" +sidebar_position: 1 +--- + +# Public RPC + +This page summarizes the public gRPC `rpc.Api` service. + +As a reminder, you can inspect the exact schema on any deployed network using gRPC reflection: + +```bash +grpcurl rpc.testnet.miden.io:443 describe rpc.Api +``` + +## Status and Limits + +| Method | Purpose | +| ----------- | --------------------------------------------------------------------------------------------------------- | +| `Status` | Returns the node RPC version, genesis commitment, store status, and block producer status when available. | +| `GetLimits` | Returns configured query parameter limits for methods that accept large repeated parameters. | + +## State Queries + +| Method | Purpose | +| ------------------------ | -------------------------------------------------------------------------------- | +| `GetAccount` | Returns account witness data and optional details for public accounts. | +| `GetBlockByNumber` | Returns raw block data for a block number, optionally including the block proof. | +| `GetBlockHeaderByNumber` | Returns a block header and, optionally, MMR authentication data. | +| `GetNotesById` | Returns committed notes matching the requested note IDs. | +| `GetNoteScriptByRoot` | Returns a note script by script root when available. | + +## Transaction Submission + +| Method | Purpose | +| --------------------- | ------------------------------------------------------------------------------------------- | +| `SubmitProvenTx` | Submits one proven transaction and returns the node's current block height. | +| `SubmitProvenTxBatch` | Submits an atomic batch of proven transactions and returns the node's current block height. | + +Write requests must identify the target network with the `genesis` parameter in the `Accept` header: + +```text +application/vnd.miden; genesis= +``` + +Clients may also include a compatible RPC version: + +```text +application/vnd.miden; version=; genesis= +``` + +See [Errors and Limits](./errors-and-limits.md#transaction-submission-errors) for the transaction submission detail +codes returned in gRPC status details. + +## State Synchronization + +| Method | Purpose | +| ------------------------ | --------------------------------------------------------------------------------------- | +| `SyncTransactions` | Returns transaction records for specified accounts within a block range. | +| `SyncNotes` | Returns note metadata and inclusion proofs for matching note tags within a block range. | +| `SyncNullifiers` | Returns nullifiers matching specified 16-bit prefixes within a block range. | +| `SyncAccountVault` | Returns public account vault updates within a block range. | +| `SyncAccountStorageMaps` | Returns public account storage map updates within a block range. | +| `SyncChainMmr` | Returns MMR delta information needed to synchronize the chain MMR. | + +Use `GetLimits` to discover the maximum request sizes accepted by the node before batching large sync requests. + +## Streaming + +| Method | Purpose | +| ------------------- | ------------------------------------------------------------------------------------- | +| `BlockSubscription` | Streams committed blocks from `block_from`, replaying history before live blocks. | +| `ProofSubscription` | Streams block proofs from `block_from`, replaying existing proofs before live proofs. | + +These streams are the primary mechanism full nodes use to replicate chain data from an upstream source. They are also +useful for indexers, explorers, and other services that need an append-only view of network progress. + +## Network Note Debugging + +| Method | Purpose | +| ---------------------- | ------------------------------------------------------------------------------------------ | +| `GetNetworkNoteStatus` | Returns the lifecycle status of a network note tracked by the network transaction builder. | diff --git a/docs/external/src/rpc/subscriptions.md b/docs/external/src/rpc/subscriptions.md new file mode 100644 index 0000000000..6e2fe37eeb --- /dev/null +++ b/docs/external/src/rpc/subscriptions.md @@ -0,0 +1,38 @@ +--- +title: "Subscriptions" +sidebar_position: 2 +--- + +# Subscriptions + +The RPC API exposes two server-streaming methods for consumers that need to follow network progress. + +## BlockSubscription + +`BlockSubscription` streams committed blocks starting from `block_from`, inclusive. The server first replays historical +blocks, then continues streaming live blocks as they are committed. + +Each response includes: + +- `block`: the serialized block. +- `committed_chain_tip`: the current committed chain tip observed when the item was emitted. + +## ProofSubscription + +`ProofSubscription` streams block proofs starting from `block_from`, inclusive. The server first replays existing +proofs, then continues streaming live proofs as they are generated. + +Each response includes: + +- `block_num`: the block number the proof corresponds to. +- `proof`: the serialized block proof. +- `proven_chain_tip`: the proven chain tip observed when the item was emitted. + +## Consumers + +Full nodes use both streams to replicate state from an upstream source. Indexers, explorers, and monitoring services can +also use the streams to ingest block data without repeatedly polling by block number. + +Consumers should persist their local tip before acknowledging work internally. If a stream closes, reconnect from the +last persisted local tip. If the server reports lag with `DATA_LOSS`, reconnect from local state rather than assuming +any missed items were delivered.