diff --git a/scripts/generate-mainnet-genesis.sh b/scripts/generate-mainnet-genesis.sh index a85ecf2..a2ddc8e 100755 --- a/scripts/generate-mainnet-genesis.sh +++ b/scripts/generate-mainnet-genesis.sh @@ -12,9 +12,11 @@ fi TESTNET_STATE_FILE="$1" MAINNET_GENESIS_DIR=mainnet-genesis +OUTPUT_DIR=output -# Create a temporary target directory +# Create a required target directories mkdir -p $MAINNET_GENESIS_DIR +mkdir -p $OUTPUT_DIR # -------- @@ -34,6 +36,10 @@ docker run \ # -------- +# Install required bech32 dependency +# TODO: Avoid installing bech32 system-wide +python -m pip install bech32 --break-system-packages + # Carry over state from testnet to mainnet echo "Carrying over state from testnet state to mainnet genesis..." python3 $script_dir/transfer-state.py diff --git a/scripts/genesis.sh b/scripts/genesis.sh index 72c8f55..301fa90 100755 --- a/scripts/genesis.sh +++ b/scripts/genesis.sh @@ -29,7 +29,7 @@ mainnet_genesis_file="$NODE_HOME/config/genesis.json" # Update any module params if required here # Perform alps allocations -laconicd genesis add-genesis-account $EARLY_SUPPORTS_ACC_ADDRESS $EARLY_SUPPORTS_ALLOC$LPS_DENOM --keyring-backend $KEYRING +laconicd genesis add-genesis-account $EARLY_SUPPORTS_ACC_ADDRESS $EARLY_SUPPORTS_ALLOC$LPS_DENOM --keyring-backend $KEYRING --append # Use zero address to add an account for lps_lockup zero_address="laconic1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqklcls0" diff --git a/scripts/transfer-state.py b/scripts/transfer-state.py index 5d67b54..a8081f7 100644 --- a/scripts/transfer-state.py +++ b/scripts/transfer-state.py @@ -2,10 +2,56 @@ import json from decimal import Decimal from collections import defaultdict +from bech32 import bech32_decode, bech32_encode, convertbits + +#------ + +# Helper methods + +def valoper_to_account_address(valoper_addr: str, new_prefix = "laconic") -> str: + hrp, data = bech32_decode(valoper_addr) + if hrp is None or data is None: + raise ValueError("Invalid bech32 address") + + # Convert back from 5-bit to 8-bit + decoded = convertbits(data, 5, 8, False) + if decoded is None: + raise ValueError("Failed to convert bits") + + # Re-encode with new prefix + converted_data = convertbits(decoded, 8, 5, True) + return bech32_encode(new_prefix, converted_data) + +def get_min_delegation_share(state): + validators = state["app_state"]["staking"]["validators"] + delegations = state["app_state"]["staking"]["delegations"] + + shares_list = [] + + for val in validators: + valoper_addr = val["operator_address"] + orig_delegator_addr = valoper_to_account_address(valoper_addr) + + # Find delegations where the delegator is the original delegator and delegated to their validator + for delegation in delegations: + if (delegation["delegator_address"] == orig_delegator_addr and + delegation["validator_address"] == valoper_addr): + shares = int(Decimal(delegation["shares"])) + shares_list.append(shares) + + break + + # Find minimum + return min(shares_list) + +#------ + +# Read testnet and mainnet states mainnet_genesis_dir="mainnet-genesis" testnet_state_file=f"{mainnet_genesis_dir}/testnet-state.json" mainnet_genesis_file=f"{mainnet_genesis_dir}/config/genesis.json" +staking_amount_file=f"output/staking-amount.json" with open(testnet_state_file) as f: testnet_state = json.load(f) @@ -107,6 +153,13 @@ mainnet_state["app_state"]["bank"]["supply"] = new_supply #------ +# Find minimum delegation share for common staking amount + +min_delegation_share = get_min_delegation_share(testnet_state) +with open(staking_amount_file, "w") as f: + json.dump({"common_staking_amount": min_delegation_share}, f, indent=2) +print(f"Staking amount written to {staking_amount_file}") + # Write back modified state with open(mainnet_genesis_file, "w") as f: - json.dump(mainnet_state, f, indent=2) + json.dump(mainnet_state, f, indent=2)