checkpoint

package
v0.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2026 License: GPL-3.0 Imports: 19 Imported by: 0

README

Checkpoint Module

Table of Contents

Overview

Heimdall selects the next proposer using Peppermint’s leader selection algorithm.
The multi-stage checkpoint process is crucial due to potential failures when submitting checkpoints on the Ethereum chain caused by factors like gas limit, network traffic, or high gas fees. Each checkpoint has a validator as the proposer.
The outcome of a checkpoint on the Ethereum chain (success or failure) triggers an ack (acknowledgment) or no-ack (no acknowledgment) transaction,
altering the proposer for the next checkpoint on Heimdall.

Checkpoint Flow.png

Flow

Checkpoint Proposal

A checkpoint proposal is initiated by a proposer, a validator with POL tokens staked on the L1 Ethereum root chain.
The checkpointing process is managed by the bridge processor which generates a MsgCheckpoint and broadcasts it as a transaction.

  • The proposer derives the root hash from the Bor chain contract.
  • Due to Bor’s finality time, the root hash may not always reflect the latest Bor tip.
Checkpoint Processing in Heimdall

Once the checkpoint message is included in a Heimdall block, it undergoes processing through the message handling system.
Each validator node independently verifies the checkpoint by checking the Bor root hash provided in the message against its local Bor chain.

ABCI++ Processing Flow for the checkpoint submission on Heimdall
  • Prepare Proposal: During the proposal phase, the checkpoint message MsgCheckpoint is included in the proposed block only if dry-running this tx does not return any errors.
  • Process Proposal: The proposal is validated to ensure correctness.
  • Pre-Commit: As part of the voting process, validators execute a side transaction to verify the checkpoint against their local Bor data. If the checkpoint is valid, validators include a vote extension confirming their approval.
  • Verify Vote: Injected votes are verified.
    Next block - Finalize: In the next block, the finalized votes are processed, and the checkpoint is considered approved if a sufficient majority supports it.
    The preBlocker triggers post-tx handlers performing the Heimdall state changes when the checkpoint is finally saved in the checkpoint buffer as the checkpoint that needs to be further bridged to the Ethereum L1 root chain.
Submission to Ethereum (L1)

Once approved, the checkpoint is added to a checkpoint buffer and an event is emitted. The bridge system, which listens for these events, submits the checkpoint data along with validator signatures to the Ethereum root chain.

Acknowledgment from Ethereum (L1)

After the checkpoint is successfully included on the Ethereum chain, an acknowledgment MsgCpAck is sent back to Heimdall from the bridge processor.
This acknowledgment, once processed through the ABCI++ flow with side and post-tx handlers: updates the state, flushes processed checkpoints from the buffer, and increments the number of ACK counters to track confirmations of checkpoints.
Additionally, the selection of the next checkpoint proposer is adjusted based on the updated state.

Missing Checkpoint Acknowledgment from Ethereum (L1)

The MsgCpNoAck message is broadcast by the bridge processor to indicate that a checkpoint was potentially transferred to the Ethereum chain but has not received an acknowledgment.
A background routine periodically checks for time elapsed and publishes the No-ACK signal. No-ACK is sent if a sufficient amount of time has passed since:

  • the last checkpoint was created on the Heimdall v2 chain and
  • the last No-ACK was issued.
    To conclude, the No-ACKs are triggered only when a checkpoint acknowledgment is overdue, ensuring they are not sent too frequently.
    This message is broadcasted only by the proposer. This entire flow ensures that checkpoints are securely proposed, verified, and finalized across the Heimdall and Ethereum chains in a decentralized manner.

Checkpoint ABCI diagram.png

Messages
MsgCheckpoint

MsgCheckpoint defines a message for creating a checkpoint on the Ethereum chain.

message MsgCheckpoint {
  option (cosmos.msg.v1.signer) = "proposer";
  option (amino.name) = "heimdallv2/checkpoint/MsgCheckpoint";
  option (gogoproto.equal) = true;
  option (gogoproto.goproto_getters) = true;
  string proposer = 1 [
    (amino.dont_omitempty) = true,
    (cosmos_proto.scalar) = "cosmos.AddressString"
  ];
  uint64 start_block = 2 [ (amino.dont_omitempty) = true ];
  uint64 end_block = 3 [ (amino.dont_omitempty) = true ];
  bytes root_hash = 4 [ (amino.dont_omitempty) = true ];
  bytes account_root_hash = 5 [ (amino.dont_omitempty) = true ];
  string bor_chain_id = 6 [ (amino.dont_omitempty) = true ];
}
MsgCpAck

MsgCpAck defines a message for creating the ack tx of a submitted checkpoint.

message MsgCpAck {
  option (cosmos.msg.v1.signer) = "from";
  option (amino.name) = "heimdallv2/checkpoint/MsgCpAck";
  option (gogoproto.equal) = false;
  option (gogoproto.goproto_getters) = true;
  string from = 1 [
    (amino.dont_omitempty) = true,
    (cosmos_proto.scalar) = "cosmos.AddressString"
  ];
  uint64 number = 2 [ (amino.dont_omitempty) = true ];
  string proposer = 3 [
    (amino.dont_omitempty) = true,
    (cosmos_proto.scalar) = "cosmos.AddressString"
  ];
  uint64 start_block = 4 [ (amino.dont_omitempty) = true ];
  uint64 end_block = 5 [ (amino.dont_omitempty) = true ];
  bytes root_hash = 6 [ (amino.dont_omitempty) = true ];
  bytes tx_hash = 7 [ (amino.dont_omitempty) = true ];
  uint64 log_index = 8 [ (amino.dont_omitempty) = true ];
}

MsgCheckpointNoAck

MsgCpNoAck defines a message for creating the no-ack tx of a checkpoint.

message MsgCpNoAck {
  option (cosmos.msg.v1.signer) = "from";
  option (amino.name) = "heimdallv2/checkpoint/MsgCpNoAck";
  option (gogoproto.equal) = false;
  option (gogoproto.goproto_getters) = true;
  string from = 1 [
    (amino.dont_omitempty) = true,
    (cosmos_proto.scalar) = "cosmos.AddressString"
  ];
}

Interact with the Node

Tx Commands
Send checkpoint
heimdalld tx checkpoint send-checkpoint --proposer=<proposer-address> --start-block=<start-block-number> --end-block=<end-block-number> --root-hash=<root-hash> --account-root=<account-root> --bor-chain-id=<bor-chain-id> --auto-configure=true/false
Send checkpoint ack

With autoconfiguration:

heimdalld tx checkpoint send-ack --auto-configure=true --home /var/lib/heimdall/

Or without autoconfiguration (you need to provide the following parameters):

heimdalld tx checkpoint send-ack --home /var/lib/heimdall/ --tx-hash=<checkpoint-tx-hash> --log-index=<log-index> --header=<header> --proposer=<proposer-address> --auto-configure=false
Send checkpoint no-ack
heimdalld tx checkpoint checkpoint-no-ack --from <from>

CLI Query Commands

One can run the following query commands from the checkpoint module:

  • get-params - Get checkpoint params
  • get-overview - Get checkpoint overview
  • get-ack-count - Get checkpoint ack count
  • get-checkpoint - Get checkpoint based on its number
  • get-checkpoint-latest - Get the latest checkpoint
  • get-checkpoint-buffer - Get the checkpoint buffer
  • get-last-no-ack - Get the last no ack
  • get-next-checkpoint - Get the next checkpoint
  • get-current-proposer - Get the current proposer
  • get-proposers - Get the proposers
  • get-checkpoint-list - Get the list of checkpoints
heimdalld query checkpoint get-params
heimdalld query checkpoint get-overview
heimdalld query checkpoint get-ack-count
heimdalld query checkpoint get-checkpoint
heimdalld query checkpoint get-checkpoint-latest
heimdalld query checkpoint get-checkpoint-buffer
heimdalld query checkpoint get-last-no-ack
heimdalld query checkpoint get-next-checkpoint
heimdalld query checkpoint get-current-proposer
heimdalld query checkpoint get-proposers
heimdalld query checkpoint get-checkpoint-list

GRPC Endpoints

The endpoints and the params are defined in the checkpoint/query.proto file. Please refer to them for more information about the optional params.

grpcurl -plaintext -d '{}' localhost:9090 heimdallv2.checkpoint.Query/GetCheckpointParams
grpcurl -plaintext -d '{}' localhost:9090 heimdallv2.checkpoint.Query/GetCheckpointOverview
grpcurl -plaintext -d '{}' localhost:9090 heimdallv2.checkpoint.Query/GetAckCount
grpcurl -plaintext -d '{}' localhost:9090 heimdallv2.checkpoint.Query/GetCheckpointLatest
grpcurl -plaintext -d '{}' localhost:9090 heimdallv2.checkpoint.Query/GetCheckpointBuffer
grpcurl -plaintext -d '{}' localhost:9090 heimdallv2.checkpoint.Query/GetLastNoAck
grpcurl -plaintext -d '{"bor_chain_id": <>}' localhost:9090 heimdallv2.checkpoint.Query/GetNextCheckpoint
grpcurl -plaintext -d '{}' localhost:9090 heimdallv2.checkpoint.Query/GetCurrentProposer
grpcurl -plaintext -d '{}' localhost:9090 heimdallv2.checkpoint.Query/GetProposers
grpcurl -plaintext -d '{}' localhost:9090 heimdallv2.checkpoint.Query/GetCheckpointList
grpcurl -plaintext -d '{"tx_hash": <>}' localhost:9090 heimdallv2.checkpoint.QueryGetCheckpointSignatures
grpcurl -plaintext -d '{"number": <>}' localhost:9090 heimdallv2.checkpoint.Query/GetCheckpoint

REST Endpoints

The endpoints and the params are defined in the checkpoint/query.proto file. Please refer to them for more information about the optional params.

curl localhost:1317/checkpoints/params
curl localhost:1317/checkpoints/overview
curl localhost:1317/checkpoints/count
curl localhost:1317/checkpoints/latest
curl localhost:1317/checkpoints/buffer
curl localhost:1317/checkpoints/last-no-ack
curl localhost:1317/checkpoints/prepare-next
# /checkpoints/list requires Cosmos-style pagination — a bare call returns
# HTTP 400 ("pagination request is empty"). Pass at least one of
# pagination.limit, pagination.offset, or pagination.key.
curl "localhost:1317/checkpoints/list?pagination.limit=10"
# tx_hash is the L1 (Ethereum) tx hash of the checkpoint submission,
# not a Heimdall tx hash. Returns 404 until the L1 submission is registered.
curl localhost:1317/checkpoints/signatures/{tx_hash}
curl localhost:1317/checkpoints/{number}

Documentation

Index

Constants

View Source
const ConsensusVersion = 1

ConsensusVersion defines the current x/checkpoint module consensus version.

Variables

This section is empty.

Functions

This section is empty.

Types

type AppModule

type AppModule struct {
	// contains filtered or unexported fields
}

AppModule implements an application module for the checkpoint module.

func NewAppModule

func NewAppModule(
	keeper *keeper.Keeper,
) AppModule

NewAppModule creates a new AppModule object

func (AppModule) AutoCLIOptions

func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions

AutoCLIOptions returns the auto cli options for the module (query and tx)

func (AppModule) ConsensusVersion

func (AppModule) ConsensusVersion() uint64

ConsensusVersion implements AppModule/ConsensusVersion.

func (AppModule) DefaultGenesis

func (AppModule) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage

DefaultGenesis returns default genesis state as raw bytes for the checkpoint module.

func (AppModule) ExportGenesis

func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage

ExportGenesis returns the exported genesis state as raw bytes for the checkpoint module.

func (AppModule) GetTxCmd

func (am AppModule) GetTxCmd() *cobra.Command

GetTxCmd returns the root tx command for the bor module.

func (AppModule) InitGenesis

func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage)

InitGenesis performs genesis initialization for the checkpoint module.

func (AppModule) IsAppModule

func (am AppModule) IsAppModule()

IsAppModule implements the appmodule.AppModule interface.

func (AppModule) IsOnePerModuleType

func (am AppModule) IsOnePerModuleType()

IsOnePerModuleType implements the depinject.OnePerModuleType interface.

func (AppModule) Name

func (AppModule) Name() string

Name returns the checkpoint module's name.

func (AppModule) QuerierRoute

func (AppModule) QuerierRoute() string

QuerierRoute returns the checkpoint module's querier route name.

func (AppModule) RegisterGRPCGatewayRoutes

func (AppModule) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *gwruntime.ServeMux)

RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the checkpoint module.

func (AppModule) RegisterInterfaces

func (AppModule) RegisterInterfaces(registry cdctypes.InterfaceRegistry)

RegisterInterfaces registers the module's interface types

func (AppModule) RegisterLegacyAminoCodec

func (AppModule) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino)

RegisterLegacyAminoCodec registers the checkpoint module's types on the given LegacyAmino codec.

func (AppModule) RegisterServices

func (am AppModule) RegisterServices(cfg module.Configurator)

RegisterServices registers module services.

func (AppModule) RegisterSideMsgServices

func (am AppModule) RegisterSideMsgServices(sideCfg sidetxs.SideTxConfigurator)

RegisterSideMsgServices registers side handler module services.

func (AppModule) ValidateGenesis

func (AppModule) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error

ValidateGenesis performs genesis state validation for the checkpoint module.

Directories

Path Synopsis
client
cli
Package testutil is a generated GoMock package.
Package testutil is a generated GoMock package.
Package types is a reverse proxy.
Package types is a reverse proxy.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL