Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions content/reference/architecture/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,11 @@ Two components connect external blockchains (EVM chains, Cosmos chains, etc.) to

### Outpost contracts

Outpost contracts are deployed on each source chain. They handle two things:
{% admonition(type="info") %}
The outpost contract is not yet deployed on the testnet. On the current testnet, assertions are submitted to ShinzoHub through an admin-key approval flow. The contract-based flow described below is the planned design.
{% end %}

Outpost contracts will be deployed on each source chain. They handle two things:

- Validator assertions: a validator proves their identity using chain-native mechanisms and authorises an operator (delegate) key to act as their Generator. On Ethereum, the validator's withdrawal key signs an EIP-712 message on the outpost contract that names the validator (consensus public key) and the operator pubkey. The contract verifies the signature, checks validator status, and emits an `AssertionSigned` event.
- Payments: Users call `payment()` on the outpost. The contract stores a receipt and emits a `PaymentCreated` event.
Expand All @@ -166,7 +170,7 @@ The outpost design is chain agnostic. Each chain gets its own implementation usi

The EVM relayer is a Go process with two pipelines:

1. The assertion pipeline subscribes to `AssertionSigned` events on the outpost's `GeneratorAssertion` contract via `eth_subscribe`, reads the assertion fields directly from the event, and broadcasts `MsgGeneratorAssertion` to ShinzoHub. No block scanning and no dependency on who built the block.
1. The assertion pipeline (planned, not yet live on testnet) subscribes to `AssertionSigned` events on the outpost's `GeneratorAssertion` contract via `eth_subscribe`, reads the assertion fields directly from the event, and broadcasts `MsgGeneratorAssertion` to ShinzoHub. No block scanning and no dependency on who built the block. On the current testnet, assertions are submitted directly through an admin-key flow, so this pipeline is not in use yet.
1. The payment pipeline subscribes to `PaymentCreated` log events from the outpost, extracts user `DID` and payment amount, and broadcasts `MsgRequestStreamAccess` to ShinzoHub.

The relayer maintains a persistent block cursor so it can resume where it left off after a restart. It has its own wallet on ShinzoHub and needs SHNZ for transaction fees.
Expand Down Expand Up @@ -211,7 +215,28 @@ Snapshots bundle multiple blocks into signed files for faster initial sync. The

### Generator registration

Spans two chains and a relayer. The Generator cannot register on ShinzoHub until the validator has signed an assertion that ties the Generator client's operator key to the validator's identity.
The Generator cannot register on ShinzoHub until the validator has completed an assertion that ties the Generator client's operator key to the validator's identity.

On the current testnet, the assertion is submitted through an admin-key approval flow:

{% mermaid() %}
sequenceDiagram
participant Idx as Generator<br/>(operator key)
participant SH as ShinzoHub<br/>(Generator Registry 0x0212)
participant Source as SourceHub

Idx->>Idx: generate operator/delegate<br/>key locally
Idx->>SH: MsgGeneratorAssertion<br/>(admin-key signed:<br/>consensus key, withdrawal addr,<br/>operator pubkey, source chain)
SH->>SH: store assertion record<br/>emit GeneratorAsserted
Idx->>SH: register() on 0x0212<br/>(signed by operator key)
SH->>SH: derive DID from<br/>operator pubkey
SH->>Source: ICA RegisterObject
Source->>Source: ACP adds DID<br/>to generator group
{% end %}

#### Planned contract-based flow

Once the outpost contract is deployed, the assertion step will run through the outpost and an EVM relayer instead of the admin-key flow:

{% mermaid() %}
sequenceDiagram
Expand Down
36 changes: 28 additions & 8 deletions content/reference/components/outpost/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ title = "Outpost"
mermaid = true
+++

An outpost is a smart contract deployed on an external chain (not ShinzoHub) that does two things: lets validators prove their identity so they can register as Generator, and lets users pay for view access without interacting with ShinzoHub directly.
An outpost is a smart contract deployed on an external chain (not ShinzoHub) that does two things: lets validators prove their identity so they can register as Generators, and lets users pay for view access without interacting with ShinzoHub directly.

Outposts are how external chains connect into the Shinzo network. They handle source chain local logic. [Relayers](../relayer) bridge the results to [ShinzoHub](../shinzohub).

{% admonition(type="info") %}
The outpost contract is not yet deployed on the testnet. On the current testnet, assertions are submitted to ShinzoHub through an admin-key approval flow. The contract-based assertion and payment flows described on this page are the planned design.
{% end %}

## Why outposts exist

ShinzoHub cannot directly verify that a validator on another chain is who they claim to be. Every chain has its own consensus mechanism and key types. The outpost runs on the same chain as the validator, where that chain's native tools can verify identity.
Expand All @@ -16,17 +20,33 @@ Outposts also handle payments. Users on external chains should be able to pay in

## Validator assertions

An assertion is a cryptographic proof that a validator on an external chain is who they claim to be. This is a prerequisite for becoming a Generator. A validator cannot register a Generator client directly on ShinzoHub; they must go through the assertion process on their source chain first.
An assertion ties a validator's identity to an operator (delegate) key, so the operator can register and run a Generator on ShinzoHub on the validator's behalf. A validator cannot register a Generator client directly on ShinzoHub; they must go through the assertion process first.

### Current testnet flow

On the current testnet, the outpost contract is not yet deployed. Assertions use a simplified admin-key approval flow:

1. The Generator client generates an operator (delegate) key locally.
1. The operator provides their validator's consensus public key, withdrawal address, and source chain through the Technical Registry.
1. The assertion is submitted to ShinzoHub as a `MsgGeneratorAssertion` message, signed by a server-side admin key and broadcast directly to ShinzoHub. No outpost contract, withdrawal-key signature, or on-chain validator-status check is involved.
1. ShinzoHub stores the assertion record and emits a `GeneratorAsserted` event.
1. Once the assertion record exists on-chain, the operator can register in the Generator Registry (`0x0212`), signing the registration with their operator key.

The requirement to participate with an active, bonded validator on your source chain still applies. What differs on the testnet is the enforcement mechanism: the admin-key flow approves assertions rather than an on-chain contract verifying validator status.

### Planned contract-based assertion flow

The full assertion flow runs through the outpost contract once it is deployed. The contract handles identity verification on the source chain, and a relayer bridges the result to ShinzoHub.

The flow:
The planned flow:

1. The Generator client generates an operator (delegate) key locally.
1. The validator's withdrawal key calls the outpost, providing their consensus public key and the operator pubkey, and signs the assertion digest.
1. Outpost verifies the validator using the chain's native mechanism, stores the signed assertion, and emits an `AssertionSigned` event.
1. The outpost verifies the validator using the chain's native mechanism, stores the signed assertion, and emits an `AssertionSigned` event.
1. A [relayer](../relayer) picks up the event and broadcasts `MsgGeneratorAssertion` to ShinzoHub.
1. ShinzoHub verifies the assertion and records a slip for the operator pubkey. The Generator can now register in the Generator Registry (`0x0212`), signing the registration with its operator key.

### Consensus public key
#### Consensus public key

The consensus public key (sometimes just called the consensus key) is the validator's identity on a chain's consensus layer. The outpost reads it from the assertion to know which validator is asserting, then asks the chain to confirm that validator is active and bonded. It is not the same as the withdrawal key: the withdrawal key signs the assertion to prove control of the validator's stake, while the consensus public key names the validator being asserted.

Expand All @@ -36,13 +56,13 @@ The key type, format, and lookup tooling are all chain-specific. Each outpost im
- **Cosmos SDK chains.** Typically an Ed25519 CometBFT pubkey. On the validator node, `<chaind> tendermint show-validator` prints it in the chain's `valconspub...` bech32 form. It can also be read from `<chaind> query staking validator <valoper-addr>` under `consensus_pubkey`.
- **Other chains.** Each future outpost will define its own consensus key type and the corresponding lookup procedure.

### The digest
#### The digest

The outpost generates a hash that both parties must sign. The digest includes the assertion ID, withdrawal address, delegate key, consensus key hash, creation time, and signature deadline.

How the digest is computed depends on the implementation. Different chains have different hashing and signing conventions. The requirement is that the digest is deterministic and includes enough context to prevent replay attacks across chains.

### EVM implementation
#### EVM implementation

On EVM chains, the outpost contract (`GeneratorAssertion`) uses EIP-712 typed data signatures. The validator opens an assertion with `createAssertion`, then submits the withdrawal-key signature with `submitAssertionSignature`. The contract emits `AssertionSigned`, which the relayer subscribes to:

Expand All @@ -61,7 +81,7 @@ sequenceDiagram

The relayer reads the assertion fields from the event log and forwards them to ShinzoHub. There is no `extraData` tagging and no dependency on who built the block, which matters on mainnet where MEV-boost builders construct the block header (including `extraData`) on the validator's behalf.

### Chain-specific verification
#### Chain-specific verification

The verification step is what makes each outpost implementation different. The concept is always the same (prove you are a validator), but the proof mechanism depends on the chain.

Expand Down
4 changes: 4 additions & 0 deletions content/reference/components/relayer/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ This is the EVM relayer, which bridges EVM chains to ShinzoHub. It is a complete

## Assertion relay

{% admonition(type="info") %}
The assertion relay is not yet live on the testnet. On the current testnet, assertions are submitted to ShinzoHub through an admin-key approval flow, so the relayer's assertion pipeline is not in use. The description below covers the planned design.
{% end %}

When a signed assertion is detected on the source chain, the relayer:

1. Extracts the assertion data (consensus key, delegate signature, digest, etc.).
Expand Down
7 changes: 4 additions & 3 deletions content/reference/components/shinzohub/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,14 @@ Key files: `app/precompiles/hostregistry/methods.go`

### Generator Registry (0x0212)

Generators cannot self-register. They must go through the outpost + relayer assertion flow first:
Generators cannot self-register. They must complete an assertion first:

1. Validator proves identity on source chain via outpost contract.
1. Relayer delivers `MsgGeneratorAssertion` to ShinzoHub.
1. On the current testnet, the assertion is submitted to ShinzoHub as a `MsgGeneratorAssertion` message signed by an admin key. No outpost contract or relayer is involved.
1. ShinzoHub's Generator module stores the assertion.
1. Operator calls `register()`, registry verifies stored assertion, derives DID/PID, sends ICA to SourceHub.

The planned flow uses an outpost contract on the source chain and a relayer to deliver the assertion to ShinzoHub. See [Outpost](../outpost#validator-assertions) for the full planned design.

Key files: `app/precompiles/generatorregistry/methods.go`

## Event names
Expand Down
15 changes: 8 additions & 7 deletions content/run/run-a-generator/register/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ To participate in the Shinzo Network, you must register your node. Registration

## Prerequisites

Running the Generator client only requires an execution node (see [Install](../install)). To register a Generator client, however, you must be an active, bonded chain validator. Registration includes an [assertion](/reference/components/outpost#validator-assertions) step in which you prove control of a validator on your source chain. If you are not a validator, you can still run the client, but your node will not be recognized by the network.
Running the Generator client only requires an execution node (see [Install](../install)). To register a Generator client, however, you must be an active, bonded chain validator. Registration includes an [assertion](/reference/components/outpost#validator-assertions) step that ties your generator's operator key to your validator identity. If you are not a validator, you can still run the client, but your node will not be recognized by the network.

Before you start, have the following ready:

1. **An active, bonded chain validator.** The outpost checks that the validator named in your assertion is active and bonded on the source chain.
1. **An active, bonded chain validator.** On the current testnet, the assertion is approved through an admin-key flow rather than an on-chain contract check. The planned outpost contract will verify validator status on-chain once deployed.
1. **Your validator's consensus public key.** The key type, format, and lookup tooling are chain-specific. See [Consensus public key](/reference/components/outpost#consensus-public-key) for how to retrieve it on your chain. It is not your withdrawal address or an EVM address.
1. **Access to your validator's withdrawal key.** The assertion is signed with the withdrawal key to prove control of the validator's stake, and the withdrawal address is included in the assertion. See [Validator assertions](/reference/components/outpost#validator-assertions) for the full flow.
1. **Your validator's withdrawal address.** This is included in the assertion to identify your validator. On the current testnet you only need the address itself (the assertion is admin-key-approved). The planned contract-based flow will require the withdrawal key to sign the assertion. See [Validator assertions](/reference/components/outpost#validator-assertions) for the full flow.
1. **A browser wallet** to sign the on-chain registration transaction.

## Register your Generator
Expand All @@ -36,14 +36,15 @@ Before you start, have the following ready:

### Assertion

The Assertion step verifies that you control the validator you are registering as a Generator. You'll need to provide:
The Assertion step ties your validator identity to your generator's operator key so ShinzoHub knows who you are. You'll need to provide:

- **Consensus public key**: The consensus public key of the validator you are registering (see [Consensus public key](/reference/components/outpost#consensus-public-key)).
- **Consensus public key**: The consensus public key of the validator you're registering (see [Consensus public key](/reference/components/outpost#consensus-public-key)).
- **Withdrawal address**: The withdrawal address for your validator on the source chain.
- **Source chain**: The blockchain your generator monitors (see [shinzo.network/chains](https://shinzo.network/chains) for supported chains).

The assertion is authorized by your validator's withdrawal key, which proves control of the validator's stake. See [Validator assertions](/reference/components/outpost#validator-assertions) for how this works end to end.
On the current testnet, the assertion goes through an admin-key approval flow rather than a smart contract. Your connected wallet address gets recorded as the generator's operator and payout address. The withdrawal-key signature and on-chain validator-status check described in [Validator assertions](/reference/components/outpost#validator-assertions) are part of the planned contract-based flow and aren't live on testnet yet.

Click **Sign & Submit** to sign a message with your wallet, proving ownership of the generator's identity.
Click **Sign & Submit** to submit the assertion.

### Registration (register on-chain)

Expand Down
Loading
Loading