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
66 changes: 64 additions & 2 deletions .github/actions/setup-go/action.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
name: Setup Go from go.mod
description: Detect the Go toolchain version from go.mod and install it with caching enabled
description: Detect the Go toolchain version from go.mod, install it, and prime the Go module cache
inputs:
version:
description: "Go version to use (overrides go.mod detection)"
required: false
default: ""
download-modules:
description: "Run go mod download and save the module cache immediately"
required: false
default: "true"
module-directories:
description: "Newline-delimited module directories to download"
required: false
default: |
.
tests/systemtests
outputs:
version:
description: Detected Go version
Expand Down Expand Up @@ -42,8 +52,60 @@ runs:

echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Setup Go
- id: setup-go
name: Setup Go
uses: actions/setup-go@v6.2.0
with:
go-version: ${{ steps.determine.outputs.version }}
cache: true
cache-dependency-path: |
go.sum
tests/systemtests/go.sum

- id: go-env
name: Resolve Go cache paths
shell: bash
run: |
set -euo pipefail

echo "gomodcache=$(go env GOMODCACHE)" >> "$GITHUB_OUTPUT"

- id: go-module-cache
name: Restore Go module cache
if: ${{ inputs.download-modules == 'true' && steps.setup-go.outputs.cache-hit != 'true' }}
uses: actions/cache/restore@v4
with:
path: ${{ steps.go-env.outputs.gomodcache }}
key: go-mod-${{ runner.os }}-${{ runner.arch }}-go-${{ steps.determine.outputs.version }}-${{ hashFiles('go.sum', 'tests/systemtests/go.sum') }}
restore-keys: |
go-mod-${{ runner.os }}-${{ runner.arch }}-go-${{ steps.determine.outputs.version }}-
go-mod-${{ runner.os }}-${{ runner.arch }}-

- name: Download Go modules
if: ${{ inputs.download-modules == 'true' }}
shell: bash
env:
MODULE_DIRECTORIES: ${{ inputs.module-directories }}
run: |
set -euo pipefail

while IFS= read -r module_dir || [ -n "$module_dir" ]; do
if [ -z "$module_dir" ]; then
continue
fi
if [ ! -f "$module_dir/go.mod" ]; then
echo "Module directory '$module_dir' does not contain go.mod" >&2
exit 1
fi

echo "Downloading Go modules in $module_dir"
(cd "$module_dir" && go mod download)
done <<< "$MODULE_DIRECTORIES"

- name: Save Go module cache
if: ${{ inputs.download-modules == 'true' && steps.setup-go.outputs.cache-hit != 'true' && steps.go-module-cache.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v4
continue-on-error: true
with:
path: ${{ steps.go-env.outputs.gomodcache }}
key: ${{ steps.go-module-cache.outputs.cache-primary-key }}
6 changes: 0 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ jobs:
- name: Set up Go
uses: ./.github/actions/setup-go

- name: Install dependencies
run: go mod download

- name: Run unit tests
run: make unit-tests

Expand All @@ -49,9 +46,6 @@ jobs:
- name: Set up Go
uses: ./.github/actions/setup-go

- name: Install dependencies
run: go mod download

- name: Run integration tests
run: make integration-tests

Expand Down
12 changes: 0 additions & 12 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ jobs:
- name: Set up Go
uses: ./.github/actions/setup-go

Comment thread
akobrin1 marked this conversation as resolved.
- name: Install dependencies
run: go mod download

- name: Run unit tests
run: make unit-tests

Expand All @@ -42,9 +39,6 @@ jobs:
- name: Set up Go
uses: ./.github/actions/setup-go

- name: Install dependencies
run: go mod download

- name: Build lumerad
run: go build -o ./build/lumerad ./cmd/lumera

Expand All @@ -62,9 +56,6 @@ jobs:
- name: Set up Go
uses: ./.github/actions/setup-go

- name: Install dependencies
run: go mod download

- name: Run integration tests
run: make integration-tests

Expand All @@ -80,8 +71,5 @@ jobs:
- name: Set up Go
uses: ./.github/actions/setup-go

- name: Install dependencies
run: go mod download

- name: Run simulation benchmark
run: make simulation-bench
1 change: 1 addition & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@ func (app *App) setupUpgrades() {
FeeMarketKeeper: &app.FeeMarketKeeper,
Erc20Keeper: &app.Erc20Keeper,
Erc20StoreKey: app.GetKey(erc20types.StoreKey),
EvmigrationKeeper: &app.EvmigrationKeeper,
}

allUpgrades := upgrades.AllUpgrades(params)
Expand Down
16 changes: 7 additions & 9 deletions app/upgrades/chain_id.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
package upgrades

import "strings"
import lcfg "github.com/LumeraProtocol/lumera/config"

const (
chainPrefixMainnet = "lumera-mainnet"
chainPrefixTestnet = "lumera-testnet"
chainPrefixDevnet = "lumera-devnet"
)
// These thin wrappers delegate to the canonical chain-ID detection in the
// config package so the prefixes live in a single leaf package that upgrade
// version subpackages (e.g. v1_20_0) can import without an import cycle.

// IsMainnet returns true if the chain ID corresponds to mainnet.
func IsMainnet(chainID string) bool {
return strings.HasPrefix(chainID, chainPrefixMainnet)
return lcfg.IsMainnetChainID(chainID)
}

// IsTestnet returns true if the chain ID corresponds to testnet.
func IsTestnet(chainID string) bool {
return strings.HasPrefix(chainID, chainPrefixTestnet)
return lcfg.IsTestnetChainID(chainID)
}

// IsDevnet returns true if the chain ID corresponds to devnet.
func IsDevnet(chainID string) bool {
return strings.HasPrefix(chainID, chainPrefixDevnet)
return lcfg.IsDevnetChainID(chainID)
}
2 changes: 2 additions & 0 deletions app/upgrades/params/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

actionmodulekeeper "github.com/LumeraProtocol/lumera/x/action/v1/keeper"
auditmodulekeeper "github.com/LumeraProtocol/lumera/x/audit/v1/keeper"
evmigrationmodulekeeper "github.com/LumeraProtocol/lumera/x/evmigration/keeper"
sntypes "github.com/LumeraProtocol/lumera/x/supernode/v1/types"
)

Expand All @@ -36,4 +37,5 @@ type AppUpgradeParams struct {
FeeMarketKeeper *feemarketkeeper.Keeper
Erc20Keeper *erc20keeper.Keeper
Erc20StoreKey *storetypes.KVStoreKey
EvmigrationKeeper *evmigrationmodulekeeper.Keeper
}
50 changes: 50 additions & 0 deletions app/upgrades/v1_20_0/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package v1_20_0
import (
"context"
"fmt"
"time"

"cosmossdk.io/store/prefix"
storetypes "cosmossdk.io/store/types"
Expand All @@ -25,6 +26,29 @@ import (
// UpgradeName is the on-chain name used for this upgrade.
const UpgradeName = "v1.20.0"

// Devnet and testnet derive a finite migration_end_time automatically from the
// upgrade block time so rehearsals and public testnet exercise a real deadline.
// Mainnet instead receives a specific absolute migration_end_time chosen near
// its own upgrade (the handler leaves it at the default 0).
const (
devnetMigrationWindow = 2 * 24 * time.Hour
testnetMigrationWindow = 7 * 24 * time.Hour
)

// autoMigrationWindow returns the migration window to auto-apply for the given
// chain ID, or 0 if the deadline should be left to a manually chosen timestamp
// (mainnet and any unrecognized chain ID).
func autoMigrationWindow(chainID string) time.Duration {
switch {
case lcfg.IsDevnetChainID(chainID):
return devnetMigrationWindow
case lcfg.IsTestnetChainID(chainID):
return testnetMigrationWindow
default:
return 0
}
}

// StoreUpgrades declares store additions for this upgrade.
var StoreUpgrades = storetypes.StoreUpgrades{
Added: []string{
Expand Down Expand Up @@ -129,6 +153,32 @@ func CreateUpgradeHandler(p appParams.AppUpgradeParams) upgradetypes.UpgradeHand
}
}

// On devnet and testnet, derive a finite migration_end_time from the
// upgrade block time so those networks run against a real deadline without
// hardcoding an absolute timestamp. RunMigrations already seeded the
// evmigration module with default params (enable_migration=true,
// migration_end_time=0); here we only override the deadline. Mainnet keeps
// the default 0 at upgrade and receives a specific migration_end_time
// chosen separately near launch.
if window := autoMigrationWindow(p.ChainID); window > 0 {
if p.EvmigrationKeeper == nil {
return nil, fmt.Errorf("%s upgrade requires evmigration keeper to be wired", UpgradeName)
}
emParams, err := p.EvmigrationKeeper.Params.Get(ctx)
if err != nil {
return nil, fmt.Errorf("get evmigration params: %w", err)
}
emParams.MigrationEndTime = ctx.BlockTime().Add(window).Unix()
if err := p.EvmigrationKeeper.Params.Set(ctx, emParams); err != nil {
return nil, fmt.Errorf("set evmigration migration_end_time: %w", err)
}
p.Logger.Info("Set migration_end_time from upgrade block time",
"chain_id", p.ChainID,
"migration_end_time", emParams.MigrationEndTime,
"window", window.String(),
)
}

p.Logger.Info(fmt.Sprintf("Successfully completed upgrade %s", UpgradeName))
return newVM, nil
}
Expand Down
78 changes: 78 additions & 0 deletions app/upgrades/v1_20_0/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package v1_20_0_test

import (
"testing"
"time"

"cosmossdk.io/log"
"cosmossdk.io/store/prefix"
Expand All @@ -18,6 +19,83 @@ import (
erc20policytypes "github.com/LumeraProtocol/lumera/x/erc20policy/types"
)

// upgradeParamsForChain returns AppUpgradeParams wired with the app keepers the
// v1.20.0 handler needs, for the given chain ID.
func upgradeParamsForChain(app *lumeraapp.App, chainID string) appParams.AppUpgradeParams {
return appParams.AppUpgradeParams{
ChainID: chainID,
Logger: log.NewNopLogger(),
ModuleManager: module.NewManager(),
Configurator: module.NewConfigurator(nil, nil, nil),
BankKeeper: app.BankKeeper,
EVMKeeper: app.EVMKeeper,
FeeMarketKeeper: &app.FeeMarketKeeper,
Erc20Keeper: &app.Erc20Keeper,
Erc20StoreKey: app.GetKey(erc20types.StoreKey),
EvmigrationKeeper: &app.EvmigrationKeeper,
}
}

// On devnet the handler derives a finite migration_end_time from the upgrade
// block time (block time + 2 days) so rehearsals run against a real deadline.
func TestV1200SetsDevnetMigrationEndTime(t *testing.T) {
app := lumeraapp.Setup(t)
ctx := app.BaseApp.NewContext(false)

// Default genesis params seed migration with no deadline.
before, err := app.EvmigrationKeeper.Params.Get(ctx)
require.NoError(t, err)
require.Equal(t, int64(0), before.MigrationEndTime)

want := ctx.BlockTime().Add(2 * 24 * time.Hour).Unix()

handler := upgradev1200.CreateUpgradeHandler(upgradeParamsForChain(app, "lumera-devnet-1"))
_, err = handler(sdk.WrapSDKContext(ctx), upgradetypes.Plan{}, module.VersionMap{})
require.NoError(t, err)

after, err := app.EvmigrationKeeper.Params.Get(ctx)
require.NoError(t, err)
require.Equal(t, want, after.MigrationEndTime,
"devnet upgrade should set migration_end_time to upgrade block time + 2 days")
require.True(t, after.EnableMigration, "enable_migration should remain true (immediate-open)")
require.Equal(t, uint64(2500), after.MaxValidatorDelegations,
"max_validator_delegations default should be 2500")
}

// On testnet the handler derives a 7-day migration window from the upgrade
// block time.
func TestV1200SetsTestnetMigrationEndTime(t *testing.T) {
app := lumeraapp.Setup(t)
ctx := app.BaseApp.NewContext(false)

want := ctx.BlockTime().Add(7 * 24 * time.Hour).Unix()

handler := upgradev1200.CreateUpgradeHandler(upgradeParamsForChain(app, "lumera-testnet-1"))
_, err := handler(sdk.WrapSDKContext(ctx), upgradetypes.Plan{}, module.VersionMap{})
require.NoError(t, err)

after, err := app.EvmigrationKeeper.Params.Get(ctx)
require.NoError(t, err)
require.Equal(t, want, after.MigrationEndTime,
"testnet upgrade should set migration_end_time to upgrade block time + 7 days")
}

// Mainnet keeps migration_end_time at the default 0 at upgrade; a specific
// absolute timestamp is chosen and applied separately near launch.
func TestV1200LeavesMigrationEndTimeZeroOnMainnet(t *testing.T) {
app := lumeraapp.Setup(t)
ctx := app.BaseApp.NewContext(false)

handler := upgradev1200.CreateUpgradeHandler(upgradeParamsForChain(app, "lumera-mainnet-1"))
_, err := handler(sdk.WrapSDKContext(ctx), upgradetypes.Plan{}, module.VersionMap{})
require.NoError(t, err)

after, err := app.EvmigrationKeeper.Params.Get(ctx)
require.NoError(t, err)
require.Equal(t, int64(0), after.MigrationEndTime,
"mainnet upgrade must leave migration_end_time at the default 0")
}

func TestV1200InitializesERC20ParamsWhenInitGenesisIsSkipped(t *testing.T) {
app := lumeraapp.Setup(t)
ctx := app.BaseApp.NewContext(false)
Expand Down
25 changes: 25 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
package config

import (
"strings"

sdk "github.com/cosmos/cosmos-sdk/types"
)

// Chain-ID prefixes identifying each Lumera network. Chain IDs are of the form
// "<prefix>-<n>" (e.g. "lumera-mainnet-1", "lumera-devnet-3").
const (
MainnetChainIDPrefix = "lumera-mainnet"
TestnetChainIDPrefix = "lumera-testnet"
DevnetChainIDPrefix = "lumera-devnet"
)

// IsMainnetChainID reports whether chainID belongs to a Lumera mainnet network.
func IsMainnetChainID(chainID string) bool {
return strings.HasPrefix(chainID, MainnetChainIDPrefix)
}

// IsTestnetChainID reports whether chainID belongs to a Lumera testnet network.
func IsTestnetChainID(chainID string) bool {
return strings.HasPrefix(chainID, TestnetChainIDPrefix)
}

// IsDevnetChainID reports whether chainID belongs to a Lumera devnet network.
func IsDevnetChainID(chainID string) bool {
return strings.HasPrefix(chainID, DevnetChainIDPrefix)
}

const (
// DefaultMaxIBCCallbackGas is the default value of maximum gas that an IBC callback can use.
// If the callback uses more gas, it will be out of gas and the contract state changes will be reverted,
Expand Down
Loading
Loading