DocsSettlement & BridgingSettlement

L1 Settlement

Since applications built with protokit will in most cases operate as a zk-rollup, one integral part of that security model is the process of “settlement”.

Settlement is the process of validating the integrity and correctness of the off-chain computation, proven to be valid via the so-called “Settlement Proof”, by posting that proof on a underlying blockchain, often called the Layer-1 (L1) of baselayer. In settlement, the entirety of the proofs generated by executing transactions on the protokit appchain are merged and bundled into one Mina transaction. After that transaction is included in a Mina block and verified by the whole Mina network, all transactions that occured on the L2 can be considered valid and final.

Trustless bridging between the L1 and L2 is also possible through settlement. More on that in Bridging

Settlement in protokit

The starter-kit already configures settlement out-of-the-box for development and sovereign environments

The settlement functionality is implemented via a set of modules shipped with the protokit sequencer.

Configuring settlement to protokit is very easy, it consists of three components:

  • Settlement Contract (zkapp): Is the smart contract code that verifies settlement
  • Base Layer: Configured module that tells the sequencer what the settlement layer is and where to find it
  • Settlement Module: The central module coordinating the process from finished BlockProof to the same ending up finalized on the L1

Supported Networks

Protokit supports multiple types of networks: Local, Lightnet and Remote.

  • Local runs in-memory and mainly used for unit-testing zkapps - its of little use for the protokit app development cycle.
  • Lightnet is a locally run mina node that has faster block times, instant finality and pre-funded accounts and is therefore very useful for testing protokit apps and their settlement and bridging capability. It features all features a normal node has, including graphql APIs and an archive node
  • Remote networks are used for devnet and mainnet, which are used for deploying testnets and launching your app on mainnet.

Setup

Modules

You can configure them by appending the configuration of your AppChain like:

const appChain = AppChain.from({
  Runtime: Runtime.from({
    Balances,
  }),
  Protocol: Protocol.from({
    ...Protocol.defaultModules(),
    SettlementContractModule: SettlementContractModule.from(
      SettlementContractModule.settlementOnly()
    ),
  }),
  Sequencer: Sequencer.from({
    BlockTrigger: TimedBlockTrigger,
    // ...
    BaseLayer: MinaBaseLayer,
    FeeStrategy: ConstantFeeStrategy,
    SettlementModule,
    SettlementSigner: InMemoryMinaSigner,
  }),
});

Protocol configuration

First, we have to change the Protocol’s configuration to account for the settlement contract we defined.

  Protocol: {
    ...Protocol.defaultConfig(),
    SettlementContractModule: {
      SettlementContract: {},
    },
  },

Network configuration

Configuring a network is done via the BaseLayer module (in this case MinaBaseLayer).

    BaseLayer: {
      network: {
        type: "lightnet", // Could be "local" | "lightnet" | "remote"
        graphql: "http://localhost:8083/graphql",
        archive: "http://localhost:8085",
        accountManager: "http://localhost:8084",
      },
    },

Address & Key configuration

We also have to specify the contract address protokit should use, and since we specified a InMemoryMinaSigner, we also have to provide that module with the private keys for that contract.

    SettlementModule: {
      addresses: {
        SettlementContract: PublicKey.fromBase58(""),
      },
    },
    SettlementSigner: {
      feepayer: PrivateKey.fromBase58(""),
      contractKeys: [
        // Contract private keys go here
      ],
    },

Fee configuration

We can specify the fee amount that protokit should use for L1 transactions. The used ConstantFeeStrategy sends every transaction with the same fee amount.

    FeeStrategy: {
      fee: 0.1 * 1e9, // 0.1 MINA
    },

Settlement interval configuration

Last, we need to specify how often protokit should attempt to settle to the L1.

    BlockTrigger: {
      blockInterval: 20000,
      settlementInterval: 600000, // 10 minutes
      settlementTokenConfig: {}, // Necessary for custom token bridging
    },

Deploying L1 contracts

For deploying, we have two options: Using the CLI or programmatically. Most users will use the CLI for this, but for advanced use cases and testing, programmatic deployment can be useful.

Devnet

Inside starter-kit, run:

pnpm protokit settlement deploy --env <environment>

Lightnet

  • pnpm env:environment lightnet:start -d
  • pnpm protokit lightnet initialize --env <environment>

The second command does a few things together:

  1. Waits for lightnet to be started & ready
  2. Uses the lightnet faucet to fund the sequencer account
  3. Deploys all settlement & bridging contracts and initializes them

Local

Unfortunately, local-network testing is only useful for unit-testing settlement, not for developing your app. In this case, lightnet should be your tool of choice.

That’s it, now start your appchain and settlement should automatically commence in the interval you configured.

Conclusion

One of the most important requirements is that a Balances runtime module has to exist in the configured runtime. L1 Deposits and Withdrawals go through that module (see configuration below).

Additionally, the Withdrawals runtime module has to be set. As with the default Balances module, it has no callable functions by default, therefore relies on user code to be called.

The responsibilities of the services configured above is the following:

ServiceResponsibilities
SettlementContractModuleContains the provable L1 zkapp contracts that facilitate the settlement and trustless bridging
BaseLayerService to communicate with the Mina node endpoints (send transactions, query account states, …)
SettlementModuleUses all of the above to coordinate the settlement process and ensure the correct proof orchestration
FeeStrategyIs queried by the SettlementModule to obtain a fee amount used for L1 transactions
SettlementSignerHolds the keys (or connection to a key service) for signing deployment (or signed settlement) L1 transactions