Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ docker-cluster-start: docker-cluster-stop build-docker-node
else \
DETACH_FLAG=""; \
fi; \
DOCKER_PLATFORM=$(DOCKER_PLATFORM) USERID=$(shell id -u) GROUPID=$(shell id -g) GOCACHE=$(shell go env GOCACHE) NUM_ACCOUNTS=10 INVARIANT_CHECK_INTERVAL=${INVARIANT_CHECK_INTERVAL} UPGRADE_VERSION_LIST=${UPGRADE_VERSION_LIST} MOCK_BALANCES=${MOCK_BALANCES} GIGA_EXECUTOR=${GIGA_EXECUTOR} GIGA_OCC=${GIGA_OCC} RECEIPT_BACKEND=${RECEIPT_BACKEND} docker compose up $$DETACH_FLAG
DOCKER_PLATFORM=$(DOCKER_PLATFORM) USERID=$(shell id -u) GROUPID=$(shell id -g) GOCACHE=$(shell go env GOCACHE) NUM_ACCOUNTS=10 INVARIANT_CHECK_INTERVAL=${INVARIANT_CHECK_INTERVAL} UPGRADE_VERSION_LIST=${UPGRADE_VERSION_LIST} MOCK_BALANCES=${MOCK_BALANCES} GIGA_EXECUTOR=${GIGA_EXECUTOR} GIGA_OCC=${GIGA_OCC} RECEIPT_BACKEND=${RECEIPT_BACKEND} AUTOBAHN=${AUTOBAHN} docker compose up $$DETACH_FLAG

.PHONY: localnet-start

Expand Down
4 changes: 4 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ services:
- GIGA_EXECUTOR
- GIGA_OCC
- RECEIPT_BACKEND
- AUTOBAHN
volumes:
- "${PROJECT_HOME}:/sei-protocol/sei-chain:Z"
- "${PROJECT_HOME}/../sei-tendermint:/sei-protocol/sei-tendermint:Z"
Expand Down Expand Up @@ -50,6 +51,7 @@ services:
- GIGA_EXECUTOR
- GIGA_OCC
- RECEIPT_BACKEND
- AUTOBAHN
volumes:
- "${PROJECT_HOME}:/sei-protocol/sei-chain:Z"
- "${PROJECT_HOME}/../sei-tendermint:/sei-protocol/sei-tendermint:Z"
Expand Down Expand Up @@ -77,6 +79,7 @@ services:
- GIGA_EXECUTOR
- GIGA_OCC
- RECEIPT_BACKEND
- AUTOBAHN
ports:
- "26662-26664:26656-26658"
- "9094-9095:9090-9091"
Expand Down Expand Up @@ -108,6 +111,7 @@ services:
- GIGA_EXECUTOR
- GIGA_OCC
- RECEIPT_BACKEND
- AUTOBAHN
ports:
- "26665-26667:26656-26658"
- "9096-9097:9090-9091"
Expand Down
15 changes: 11 additions & 4 deletions docker/localnode/scripts/step1_configure_init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ echo "Configure and initialize environment"
cp build/seid "$GOBIN"/

# Prepare shared folders
NODE_DIR="build/generated/node_${NODE_ID}"
mkdir -p build/generated/gentx/
mkdir -p build/generated/exported_keys/
mkdir -p build/generated/node_"$NODE_ID"
mkdir -p "$NODE_DIR"

# Testing whether seid works or not
seid version # Uncomment the below line if there are any dependency issues
Expand All @@ -22,16 +23,22 @@ MONIKER="sei-node-$NODE_ID"
seid init "$MONIKER" --chain-id sei >/dev/null 2>&1

# Copy configs
APP_CONFIG_FILE="build/generated/node_$NODE_ID/app.toml"
TENDERMINT_CONFIG_FILE="build/generated/node_$NODE_ID/config.toml"
APP_CONFIG_FILE="$NODE_DIR/app.toml"
TENDERMINT_CONFIG_FILE="$NODE_DIR/config.toml"
cp docker/localnode/config/app.toml "$APP_CONFIG_FILE"
cp docker/localnode/config/config.toml "$TENDERMINT_CONFIG_FILE"


# Set up persistent peers
SEI_NODE_ID=$(seid tendermint show-node-id)
NODE_IP=$(hostname -i | awk '{print $1}')
echo "$SEI_NODE_ID@$NODE_IP:26656" >> build/generated/persistent_peers.txt
P2P_PORT=26656 # Must match [p2p] laddr in config.toml
echo "$SEI_NODE_ID@$NODE_IP:$P2P_PORT" >> build/generated/persistent_peers.txt

# Store autobahn-compatible pubkeys and address for config generation
cp ~/.sei/config/validator_pubkey.txt "$NODE_DIR/" || { echo "ERROR: failed to copy validator_pubkey.txt"; exit 1; }
cp ~/.sei/config/node_pubkey.txt "$NODE_DIR/" || { echo "ERROR: failed to copy node_pubkey.txt"; exit 1; }
echo "$NODE_IP:$P2P_PORT" > "$NODE_DIR/autobahn_address.txt"

# Create a new account
ACCOUNT_NAME="node_admin"
Expand Down
25 changes: 25 additions & 0 deletions docker/localnode/scripts/step4_config_override.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
NODE_ID=${ID:-0}
GIGA_EXECUTOR=${GIGA_EXECUTOR:-false}
GIGA_OCC=${GIGA_OCC:-false}
AUTOBAHN=${AUTOBAHN:-false}

APP_CONFIG_FILE="build/generated/node_$NODE_ID/app.toml"
TENDERMINT_CONFIG_FILE="build/generated/node_$NODE_ID/config.toml"
Expand Down Expand Up @@ -59,3 +60,27 @@ if [ -n "$RECEIPT_BACKEND" ]; then
echo "rs-backend = \"$RECEIPT_BACKEND\"" >> ~/.sei/config/app.toml
fi
fi

# Generate Autobahn (GigaRouter) config if requested
if [ "$AUTOBAHN" = "true" ]; then
echo "Generating Autobahn config for node $NODE_ID..."
AUTOBAHN_CONFIG="$HOME/.sei/config/autobahn.json"

# Collect node directories as arguments
NODE_DIRS=""
for i in $(seq 0 $((CLUSTER_SIZE - 1))); do
NODE_DIRS="$NODE_DIRS build/generated/node_${i}"
done

# Generate autobahn config using seid
seid tendermint gen-autobahn-config $NODE_DIRS --output "$AUTOBAHN_CONFIG"

# Inject autobahn config file path into config.toml
# Must be placed before any [section] header so TOML parser reads it as a top-level key.
if grep -q "autobahn-config-file" ~/.sei/config/config.toml; then
sed -i 's|autobahn-config-file = .*|autobahn-config-file = "'"$AUTOBAHN_CONFIG"'"|' ~/.sei/config/config.toml
else
sed -i '1s|^|autobahn-config-file = "'"$AUTOBAHN_CONFIG"'"\n|' ~/.sei/config/config.toml
fi
echo "Autobahn config written to $AUTOBAHN_CONFIG"
fi
1 change: 1 addition & 0 deletions sei-cosmos/server/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ func AddCommands(
ShowValidatorCmd(),
ShowAddressCmd(),
VersionCmd(),
commands.MakeGenAutobahnConfigCommand(),
commands.MakeGenValidatorCommand(),
commands.MakeReindexEventCommand(conf),
commands.MakeLightCommand(conf),
Expand Down
96 changes: 96 additions & 0 deletions sei-tendermint/cmd/tendermint/commands/gen_autobahn_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package commands

import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"time"

"github.com/spf13/cobra"

"github.com/sei-protocol/sei-chain/sei-tendermint/config"
atypes "github.com/sei-protocol/sei-chain/sei-tendermint/internal/autobahn/types"
"github.com/sei-protocol/sei-chain/sei-tendermint/internal/p2p"
"github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils"
"github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils/tcp"
)

// MakeGenAutobahnConfigCommand creates a cobra command that generates an autobahn JSON config file.
// Each node directory must contain validator_pubkey.txt, node_pubkey.txt, and autobahn_address.txt.
func MakeGenAutobahnConfigCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "gen-autobahn-config [node-dirs...]",
Short: "Generate autobahn JSON config from node pubkey files",
Long: `Generate an autobahn JSON config file by reading validator_pubkey.txt,
node_pubkey.txt, and autobahn_address.txt from each node directory.
Output is written to the file specified by --output.`,
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
output, _ := cmd.Flags().GetString("output")
if output == "" {
return fmt.Errorf("--output flag is required")
}

var validators []config.AutobahnValidator
for _, dir := range args {
valKeyRaw, err := os.ReadFile(filepath.Clean(filepath.Join(dir, "validator_pubkey.txt")))
if err != nil {
return fmt.Errorf("reading validator_pubkey.txt from %s: %w", dir, err)
}
var valKey atypes.PublicKey
if err := valKey.UnmarshalText([]byte(strings.TrimSpace(string(valKeyRaw)))); err != nil {
return fmt.Errorf("parsing validator key from %s: %w", dir, err)
}

nodeKeyRaw, err := os.ReadFile(filepath.Clean(filepath.Join(dir, "node_pubkey.txt")))
if err != nil {
return fmt.Errorf("reading node_pubkey.txt from %s: %w", dir, err)
}
var nodeKey p2p.NodePublicKey
if err := nodeKey.UnmarshalText([]byte(strings.TrimSpace(string(nodeKeyRaw)))); err != nil {
return fmt.Errorf("parsing node key from %s: %w", dir, err)
}

addrRaw, err := os.ReadFile(filepath.Clean(filepath.Join(dir, "autobahn_address.txt")))
if err != nil {
return fmt.Errorf("reading autobahn_address.txt from %s: %w", dir, err)
}
addr, err := tcp.ParseHostPort(strings.TrimSpace(string(addrRaw)))
if err != nil {
return fmt.Errorf("parsing address from %s: %w", dir, err)
}

validators = append(validators, config.AutobahnValidator{
ValidatorKey: valKey,
NodeKey: nodeKey,
Address: addr,
})
}

cfg := config.AutobahnFileConfig{
Validators: validators,
MaxGasPerBlock: 50_000_000,
MaxTxsPerBlock: 5_000,
MempoolSize: 5_000,
BlockInterval: utils.Duration(400 * time.Millisecond),
AllowEmptyBlocks: false,
ViewTimeout: utils.Duration(1500 * time.Millisecond),
DialInterval: utils.Duration(10 * time.Second),
}

data, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
return fmt.Errorf("marshaling config: %w", err)
}
if err := os.WriteFile(output, data, 0600); err != nil {
return fmt.Errorf("writing config to %s: %w", output, err)
}
fmt.Printf("Autobahn config written to %s\n", output)
return nil
},
}
cmd.Flags().StringP("output", "o", "", "output file path for the autobahn config")
return cmd
}
57 changes: 57 additions & 0 deletions sei-tendermint/config/autobahn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package config

import (
"errors"

atypes "github.com/sei-protocol/sei-chain/sei-tendermint/internal/autobahn/types"
"github.com/sei-protocol/sei-chain/sei-tendermint/internal/p2p"
"github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils"
"github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils/tcp"
)

// AutobahnValidator represents a validator entry in the autobahn config file.
type AutobahnValidator struct {
ValidatorKey atypes.PublicKey `json:"validator_key"`
NodeKey p2p.NodePublicKey `json:"node_key"`
Address tcp.HostPort `json:"address"`
}

// AutobahnFileConfig is the JSON structure of the autobahn config file.
type AutobahnFileConfig struct {
Validators []AutobahnValidator `json:"validators"`
MaxGasPerBlock uint64 `json:"max_gas_per_block"`
MaxTxsPerBlock uint64 `json:"max_txs_per_block"`
MaxTxsPerSecond utils.Option[uint64] `json:"max_txs_per_second"`
MempoolSize uint64 `json:"mempool_size"`
BlockInterval utils.Duration `json:"block_interval"`
AllowEmptyBlocks bool `json:"allow_empty_blocks"`
ViewTimeout utils.Duration `json:"view_timeout"`
PersistentStateDir utils.Option[string] `json:"persistent_state_dir"`
DialInterval utils.Duration `json:"dial_interval"`
}

// Validate performs basic validation of the autobahn file config.
func (fc *AutobahnFileConfig) Validate() error {
if len(fc.Validators) == 0 {
return errors.New("validators must not be empty")
}
if fc.MaxGasPerBlock == 0 {
return errors.New("max_gas_per_block must be > 0")
}
if fc.MaxTxsPerBlock == 0 {
return errors.New("max_txs_per_block must be > 0")
}
if fc.MempoolSize == 0 {
return errors.New("mempool_size must be > 0")
}
if fc.BlockInterval <= 0 {
return errors.New("block_interval must be > 0")
}
if fc.ViewTimeout <= 0 {
return errors.New("view_timeout must be > 0")
}
if fc.DialInterval <= 0 {
return errors.New("dial_interval must be > 0")
}
return nil
}
1 change: 1 addition & 0 deletions sei-tendermint/internal/p2p/giga_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func NewGigaRouter(cfg *GigaRouterConfig, key NodeSecretKey) (*GigaRouter, error
return nil, fmt.Errorf("consensus.NewState(): %w", err)
}
producerState := producer.NewState(cfg.Producer, consensusState)
logger.Info("GigaRouter initialized", "validators", len(cfg.ValidatorAddrs), "dial_interval", cfg.DialInterval)
return &GigaRouter{
cfg: cfg,
key: key,
Expand Down
55 changes: 5 additions & 50 deletions sei-tendermint/node/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import (
tmnet "github.com/sei-protocol/sei-chain/sei-tendermint/libs/net"
tmstrings "github.com/sei-protocol/sei-chain/sei-tendermint/libs/strings"
"github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils"
"github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils/tcp"
"github.com/sei-protocol/sei-chain/sei-tendermint/privval"
tmgrpc "github.com/sei-protocol/sei-chain/sei-tendermint/privval/grpc"
"github.com/sei-protocol/sei-chain/sei-tendermint/types"
Expand Down Expand Up @@ -198,62 +197,16 @@ func createEvidenceReactor(
return evidenceReactor, evidencePool, evidenceDB.Close, nil
}

// autobahnValidator represents a validator entry in the autobahn config file.
type autobahnValidator struct {
ValidatorKey atypes.PublicKey `json:"validator_key"` // autobahn validator public key
NodeKey p2p.NodePublicKey `json:"node_key"` // p2p node public key
Address tcp.HostPort `json:"address"` // network address (host:port)
}

// autobahnFileConfig is the JSON structure of the autobahn config file.
type autobahnFileConfig struct {
Validators []autobahnValidator `json:"validators"`
MaxGasPerBlock uint64 `json:"max_gas_per_block"`
MaxTxsPerBlock uint64 `json:"max_txs_per_block"`
MaxTxsPerSecond utils.Option[uint64] `json:"max_txs_per_second"`
MempoolSize uint64 `json:"mempool_size"`
BlockInterval utils.Duration `json:"block_interval"`
AllowEmptyBlocks bool `json:"allow_empty_blocks"`
ViewTimeout utils.Duration `json:"view_timeout"`
PersistentStateDir utils.Option[string] `json:"persistent_state_dir"`
DialInterval utils.Duration `json:"dial_interval"`
}

func (fc *autobahnFileConfig) validate() error {
if len(fc.Validators) == 0 {
return errors.New("validators must not be empty")
}
if fc.MaxGasPerBlock == 0 {
return errors.New("max_gas_per_block must be > 0")
}
if fc.MaxTxsPerBlock == 0 {
return errors.New("max_txs_per_block must be > 0")
}
if fc.MempoolSize == 0 {
return errors.New("mempool_size must be > 0")
}
if fc.BlockInterval <= 0 {
return errors.New("block_interval must be > 0")
}
if fc.ViewTimeout <= 0 {
return errors.New("view_timeout must be > 0")
}
if fc.DialInterval <= 0 {
return errors.New("dial_interval must be > 0")
}
return nil
}

func loadAutobahnFileConfig(path string) (*autobahnFileConfig, error) {
func loadAutobahnFileConfig(path string) (*config.AutobahnFileConfig, error) {
data, err := os.ReadFile(path) //nolint:gosec // G304: path is from operator-controlled config
if err != nil {
return nil, err
}
var fc autobahnFileConfig
var fc config.AutobahnFileConfig
if err := json.Unmarshal(data, &fc); err != nil {
return nil, err
}
if err := fc.validate(); err != nil {
if err := fc.Validate(); err != nil {
return nil, err
}
return &fc, nil
Expand Down Expand Up @@ -415,6 +368,7 @@ func createRouter(
}
// Wire up Autobahn (GigaRouter) if enabled.
if cfg.AutobahnConfigFile != "" {
logger.Info("Autobahn config enabled", "config_file", cfg.AutobahnConfigFile)
// TODO: add support for autobahn non-validator (observer) nodes that don't need a signing key.
valKey, ok := validatorKey.Get()
if !ok {
Expand All @@ -424,6 +378,7 @@ func createRouter(
if err != nil {
return nil, closer, fmt.Errorf("buildGigaConfig: %w", err)
}
logger.Info("Autobahn config loaded", "validators", len(gigaCfg.ValidatorAddrs))
options.Giga = utils.Some(gigaCfg)
}

Expand Down
Loading
Loading