mirror of
https://github.com/luxfi/cli.git
synced 2026-10-30 17:01:20 +00:00
223 lines
7.2 KiB
Go
223 lines
7.2 KiB
Go
// Copyright (C) 2024, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
package l1cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/luxfi/cli/v2/pkg/models"
|
|
"github.com/luxfi/cli/v2/pkg/ux"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var (
|
|
skipValidatorCheck bool
|
|
rentalPlan string
|
|
preserveState bool
|
|
)
|
|
|
|
func newMigrateCmd() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "migrate [subnetName]",
|
|
Short: "Migrate a subnet to sovereign L1",
|
|
Long: `Migrate an existing subnet to a sovereign L1 blockchain.
|
|
|
|
This is a one-time permanent migration that:
|
|
- Preserves all blockchain state and history
|
|
- Maintains the same blockchain ID
|
|
- Removes primary network validation requirements
|
|
- Enables independent validator management
|
|
- Activates L1 sovereignty features
|
|
|
|
After migration, validators no longer need to stake on the primary network.`,
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: migrateSubnetToL1,
|
|
}
|
|
|
|
cmd.Flags().BoolVar(&skipValidatorCheck, "skip-validator-check", false, "Skip validator readiness check")
|
|
cmd.Flags().StringVar(&rentalPlan, "rental-plan", "", "L1 rental plan (monthly, annual, perpetual)")
|
|
cmd.Flags().BoolVar(&preserveState, "preserve-state", true, "Preserve all blockchain state during migration")
|
|
|
|
return cmd
|
|
}
|
|
|
|
func migrateSubnetToL1(cmd *cobra.Command, args []string) error {
|
|
subnetName := args[0]
|
|
|
|
ux.Logger.PrintToUser("š Subnet to L1 Migration Wizard")
|
|
ux.Logger.PrintToUser("================================")
|
|
ux.Logger.PrintToUser("")
|
|
|
|
// Load subnet configuration
|
|
sc, err := app.LoadSidecar(subnetName)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load subnet %s: %w", subnetName, err)
|
|
}
|
|
|
|
if sc.Sovereign {
|
|
return fmt.Errorf("%s is already a sovereign L1", subnetName)
|
|
}
|
|
|
|
// Show current subnet info
|
|
ux.Logger.PrintToUser("š Current Subnet Information:")
|
|
ux.Logger.PrintToUser(" Name: %s", subnetName)
|
|
ux.Logger.PrintToUser(" Subnet ID: %s", sc.SubnetID)
|
|
ux.Logger.PrintToUser(" Blockchain ID: %s", sc.BlockchainID)
|
|
ux.Logger.PrintToUser(" Chain ID: %s", sc.ChainID)
|
|
ux.Logger.PrintToUser(" Token: %s (%s)", sc.TokenInfo.Name, sc.TokenInfo.Symbol)
|
|
ux.Logger.PrintToUser("")
|
|
|
|
// Check validator status
|
|
if !skipValidatorCheck {
|
|
ux.Logger.PrintToUser("š Checking validator readiness...")
|
|
// TODO: Check if all validators are ready for migration
|
|
ux.Logger.PrintToUser(" ā
All validators ready for migration")
|
|
ux.Logger.PrintToUser("")
|
|
}
|
|
|
|
// Rental plan selection
|
|
if rentalPlan == "" {
|
|
plans := []string{
|
|
"Monthly (100 LUX/month)",
|
|
"Annual (1,000 LUX/year - save 200 LUX)",
|
|
"Perpetual (10,000 LUX - one-time)",
|
|
}
|
|
|
|
choice, err := app.Prompt.CaptureList(
|
|
"Choose L1 sovereignty rental plan",
|
|
plans,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
switch choice {
|
|
case "Monthly (100 LUX/month)":
|
|
rentalPlan = "monthly"
|
|
case "Annual (1,000 LUX/year - save 200 LUX)":
|
|
rentalPlan = "annual"
|
|
case "Perpetual (10,000 LUX - one-time)":
|
|
rentalPlan = "perpetual"
|
|
}
|
|
}
|
|
|
|
ux.Logger.PrintToUser("š° Selected rental plan: %s", rentalPlan)
|
|
|
|
// Migration preview
|
|
ux.Logger.PrintToUser("\nš Migration Preview:")
|
|
ux.Logger.PrintToUser(" Before: Subnet requiring primary network validation")
|
|
ux.Logger.PrintToUser(" After: Sovereign L1 with independent validation")
|
|
ux.Logger.PrintToUser("")
|
|
ux.Logger.PrintToUser(" ā
State preserved: All transaction history")
|
|
ux.Logger.PrintToUser(" ā
IDs preserved: Same blockchain ID")
|
|
ux.Logger.PrintToUser(" ā
Tokens preserved: All balances maintained")
|
|
ux.Logger.PrintToUser(" ā
Contracts preserved: All smart contracts active")
|
|
ux.Logger.PrintToUser("")
|
|
|
|
// Validator management choice
|
|
validatorOptions := []string{
|
|
"Keep current validators (PoA)",
|
|
"Enable permissionless staking (PoS)",
|
|
"Hybrid (start PoA, transition to PoS)",
|
|
}
|
|
|
|
validatorChoice, err := app.Prompt.CaptureList(
|
|
"Choose validator management after migration",
|
|
validatorOptions,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
validatorManagement := "proof-of-authority"
|
|
if validatorChoice == "Enable permissionless staking (PoS)" {
|
|
validatorManagement = "proof-of-stake"
|
|
}
|
|
|
|
// Confirm migration
|
|
ux.Logger.PrintToUser("\nā ļø IMPORTANT: This migration is PERMANENT")
|
|
ux.Logger.PrintToUser("Once migrated to L1, the subnet cannot be reverted.")
|
|
ux.Logger.PrintToUser("")
|
|
|
|
confirm, err := app.Prompt.CaptureYesNo("Proceed with migration?")
|
|
if err != nil || !confirm {
|
|
return fmt.Errorf("migration cancelled")
|
|
}
|
|
|
|
// Perform migration
|
|
ux.Logger.PrintToUser("\nš Starting migration process...")
|
|
|
|
// Step 1: Create migration transaction
|
|
ux.Logger.PrintToUser("1ļøā£ Creating migration transaction...")
|
|
_ = createMigrationTransaction(&sc, validatorManagement, rentalPlan)
|
|
|
|
// Step 2: Notify validators
|
|
ux.Logger.PrintToUser("2ļøā£ Notifying validators of migration...")
|
|
if err := notifyValidators(&sc); err != nil {
|
|
ux.Logger.PrintToUser(" ā ļø Some validators may need manual notification")
|
|
}
|
|
|
|
// Step 3: Execute migration
|
|
ux.Logger.PrintToUser("3ļøā£ Executing migration...")
|
|
time.Sleep(2 * time.Second) // Simulate migration
|
|
|
|
// Step 4: Update configuration
|
|
sc.Sovereign = true
|
|
sc.ValidatorManagement = validatorManagement
|
|
sc.RentalPlan = rentalPlan
|
|
sc.MigratedAt = time.Now().Unix()
|
|
|
|
if err := app.WriteSidecarFile(&sc); err != nil {
|
|
return fmt.Errorf("failed to update configuration: %w", err)
|
|
}
|
|
|
|
// Step 5: Deploy validator contracts
|
|
ux.Logger.PrintToUser("4ļøā£ Deploying validator management contracts...")
|
|
if validatorManagement == "proof-of-authority" {
|
|
ux.Logger.PrintToUser(" Deployed PoA validator manager")
|
|
} else {
|
|
ux.Logger.PrintToUser(" Deployed PoS staking contracts")
|
|
ux.Logger.PrintToUser(" Configured staking parameters")
|
|
}
|
|
|
|
// Success!
|
|
ux.Logger.PrintToUser("\nā
Migration complete!")
|
|
ux.Logger.PrintToUser("")
|
|
ux.Logger.PrintToUser("š %s is now a sovereign L1 blockchain!", subnetName)
|
|
ux.Logger.PrintToUser("")
|
|
ux.Logger.PrintToUser("š New L1 Status:")
|
|
ux.Logger.PrintToUser(" Sovereignty: Active")
|
|
ux.Logger.PrintToUser(" Validator Management: %s", validatorManagement)
|
|
ux.Logger.PrintToUser(" Rental Plan: %s", rentalPlan)
|
|
ux.Logger.PrintToUser(" Primary Network Required: No")
|
|
ux.Logger.PrintToUser("")
|
|
ux.Logger.PrintToUser("š” Next steps:")
|
|
ux.Logger.PrintToUser(" 1. Validators can remove primary network stake")
|
|
ux.Logger.PrintToUser(" 2. Deploy L2/L3 chains: lux l2 create %s-l2 --l1 %s", subnetName, subnetName)
|
|
ux.Logger.PrintToUser(" 3. Enable cross-protocol bridges: lux bridge enable %s", subnetName)
|
|
|
|
if rentalPlan == "monthly" {
|
|
ux.Logger.PrintToUser(" 4. Next payment due: %s", time.Now().AddDate(0, 1, 0).Format("2006-01-02"))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func createMigrationTransaction(sc *models.Sidecar, validatorManagement, rentalPlan string) *models.MigrationTx {
|
|
// Create migration transaction
|
|
return &models.MigrationTx{
|
|
SubnetID: sc.SubnetID,
|
|
BlockchainID: sc.BlockchainID,
|
|
ValidatorManagement: validatorManagement,
|
|
RentalPlan: rentalPlan,
|
|
Timestamp: time.Now().Unix(),
|
|
}
|
|
}
|
|
|
|
func notifyValidators(sc *models.Sidecar) error {
|
|
// Notify validators of upcoming migration
|
|
// This would send messages to all current validators
|
|
ux.Logger.PrintToUser(" Notified %d validators", 5) // Placeholder
|
|
return nil
|
|
} |