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 .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
timeout-minutes: 240
strategy:
matrix:
tests: [unmarked, ibc, ibc_rly_evm, ibc_rly_gas, ibc_timeout, ibc_update_client, ica, gov, upgrade, slow, gas]
tests: [unmarked, ibc, ibc_rly_evm, ibc_rly_gas, ibc_timeout, ibc_update_client, ica, gov, upgrade, slow, gas, mint]
env:
TESTS_TO_RUN: ${{ matrix.tests }}
steps:
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ require (
replace (
cosmossdk.io/store => github.com/crypto-org-chain/cosmos-sdk/store v0.0.0-20241217090828-cfbca9fe8254
cosmossdk.io/x/tx => github.com/crypto-org-chain/cosmos-sdk/x/tx v0.0.0-20241217090828-cfbca9fe8254
github.com/cosmos/cosmos-sdk => github.com/crypto-org-chain/cosmos-sdk v0.50.6-0.20250424063720-28ea58ae20d8
github.com/cosmos/cosmos-sdk => github.com/crypto-org-chain/cosmos-sdk v0.50.6-0.20251119062431-8d0a31ef043d
)

replace (
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -904,8 +904,8 @@ github.com/crypto-org-chain/btree v0.0.0-20240406140148-2687063b042c h1:MOgfS4+F
github.com/crypto-org-chain/btree v0.0.0-20240406140148-2687063b042c/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
github.com/crypto-org-chain/cometbft v0.0.0-20251014161156-b0e778b18408 h1:7dfWkDRYCsguKrpd0t14nrZ3Xf/9aVHiQrWx5o0DCdo=
github.com/crypto-org-chain/cometbft v0.0.0-20251014161156-b0e778b18408/go.mod h1:khbgmtxbgwJfMqDmnGY4rl2sQpTdzpPb1f9nqnfpy1o=
github.com/crypto-org-chain/cosmos-sdk v0.50.6-0.20250424063720-28ea58ae20d8 h1:Sif0pGNc4C384OLucyQ7P/+KjYiJ6uDn8Cf8wR7MI+c=
github.com/crypto-org-chain/cosmos-sdk v0.50.6-0.20250424063720-28ea58ae20d8/go.mod h1:JwwsMeZldLN20b72mmbWPY0EV9rs+v/12hRu1JFttvY=
github.com/crypto-org-chain/cosmos-sdk v0.50.6-0.20251119062431-8d0a31ef043d h1:ffzsdKbhbSSBIMBAGJGjezjEr60A/JgpznOJhMUMbfE=
github.com/crypto-org-chain/cosmos-sdk v0.50.6-0.20251119062431-8d0a31ef043d/go.mod h1:8/AdT5lF3ILCCl/sDQXyBgzWGtcmD1tInWyhYeREVPA=
github.com/crypto-org-chain/cosmos-sdk/store v0.0.0-20241217090828-cfbca9fe8254 h1:NEgy0r3otU/O+0OAjMdEhbn4VotQlg+98hHbD7M23wU=
github.com/crypto-org-chain/cosmos-sdk/store v0.0.0-20241217090828-cfbca9fe8254/go.mod h1:8DwVTz83/2PSI366FERGbWSH7hL6sB7HbYp8bqksNwM=
github.com/crypto-org-chain/cosmos-sdk/x/tx v0.0.0-20241217090828-cfbca9fe8254 h1:JzLOFRiKsDtLJt5h0M0jkEIPDKvFFyja7VEp7gG6O9U=
Expand Down
4 changes: 2 additions & 2 deletions gomod2nix.toml
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ schema = 3
version = "v1.0.0-beta.5"
hash = "sha256-Fy/PbsOsd6iq0Njy3DVWK6HqWsogI+MkE8QslHGWyVg="
[mod."github.com/cosmos/cosmos-sdk"]
version = "v0.50.6-0.20250424063720-28ea58ae20d8"
hash = "sha256-UCynFh2IangiNqQsgux4dKCk8wuF1vgoINQGA8N59QY="
version = "v0.50.6-0.20251119062431-8d0a31ef043d"
hash = "sha256-VxQus9ynUK8nAZh3ubNXRcxJsITzgndjd7UYYgMt6C0="
replaced = "github.com/crypto-org-chain/cosmos-sdk"
[mod."github.com/cosmos/go-bip39"]
version = "v1.0.0"
Expand Down
1 change: 1 addition & 0 deletions integration_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def pytest_configure(config):
config.addinivalue_line("markers", "ibc_update_client: marks ibc updateclient test")
config.addinivalue_line("markers", "gov: marks gov related tests")
config.addinivalue_line("markers", "gas: marks gas related tests")
config.addinivalue_line("markers", "mint: marks mint module tests")


def pytest_collection_modifyitems(items, config):
Expand Down
256 changes: 256 additions & 0 deletions integration_tests/test_mint_blocks_per_year.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
"""
Integration tests for mint module BlocksPerYear parameter validation.

This test suite validates that the mint module properly handles different values
of the blocks_per_year parameter, including edge cases that could cause overflow
or panic conditions.

Test scenarios:
1. blocks_per_year = 0 (invalid, should be rejected)
2. blocks_per_year = 100 (valid, should succeed)
3. blocks_per_year = MaxInt64 (valid, should succeed)
4. blocks_per_year = MaxInt64 + 1 (overflow case, should be rejected)
5. blocks_per_year = 2^64-1 (UINT64_MAX, overflow case, should be rejected)
"""

import pytest

from .cosmoscli import module_address
from .utils import submit_gov_proposal, wait_for_new_blocks

pytestmark = pytest.mark.mint

MAX_INT64 = (1 << 63) - 1 # 9223372036854775807
UINT64_MAX = (1 << 64) - 1 # 18446744073709551615


def normalize_legacy_dec(value: str) -> str:
"""
Ensure math.LegacyDec strings have an explicit decimal point (scale 18).
This matches the Cosmos SDK's LegacyDec format.
"""
if not value:
return "0.000000000000000000"
if "." in value:
return value
sign = ""
if value[0] == "-":
sign = "-"
value = value[1:]
stripped = value.lstrip("0")
if not stripped:
return "0.000000000000000000"
padded = stripped.rjust(19, "0")
int_part = padded[:-18] or "0"
frac_part = padded[-18:]
return f"{sign}{int_part}.{frac_part}"


def get_mint_params(cli):
"""Query current mint module parameters."""
params = cli.query_params("mint")
return params


def submit_mint_param_update(cronos, blocks_per_year_value):
"""
Submit a governance proposal to update mint module parameters.

Args:
cronos: Cronos cluster instance
blocks_per_year_value: Value to set for blocks_per_year parameter

Returns:
True if proposal passes, False if it fails
"""
cli = cronos.cosmos_cli()

params = get_mint_params(cli)

# Normalize legacy decimal fields
for dec_key in (
"inflation_rate_change",
"inflation_max",
"inflation_min",
"goal_bonded",
):
if dec_key in params and isinstance(params[dec_key], str):
params[dec_key] = normalize_legacy_dec(params[dec_key])

# Update blocks_per_year to the test value
params["blocks_per_year"] = str(blocks_per_year_value)

authority = module_address("gov")
msg = "/cosmos.mint.v1beta1.MsgUpdateParams"

try:
submit_gov_proposal(
cronos,
msg,
messages=[
{
"@type": msg,
"authority": authority,
"params": params,
}
],
)
return True
except (AssertionError, Exception) as e:
print(f"Proposal failed as expected: {e}")
return False


def test_mint_blocks_per_year_zero(cronos):
"""
Test that blocks_per_year = 0 is properly rejected.

Zero is an invalid value because it would cause division by zero
in the minting calculations.
"""
cli = cronos.cosmos_cli()

# Get initial params
initial_params = get_mint_params(cli)
initial_blocks_per_year = initial_params["blocks_per_year"]
print(f"Initial blocks_per_year: {initial_blocks_per_year}")
test_value = 0

# Attempt to update to 0 (should fail)
print(f"Attempting to set blocks_per_year to {test_value}")
success = submit_mint_param_update(cronos, test_value)

assert not success, f"Proposal should fail for blocks_per_year = {test_value}"
wait_for_new_blocks(cli, 1)
current_params = get_mint_params(cli)
assert (
current_params["blocks_per_year"] == initial_blocks_per_year
), "Blocks per year should not change"


def test_mint_blocks_per_year_valid(cronos):
"""
Test that a valid blocks_per_year value (100) works correctly.

This verifies that the parameter update mechanism works for valid values.
"""
cli = cronos.cosmos_cli()

# Get initial params
initial_params = get_mint_params(cli)
initial_blocks_per_year = initial_params["blocks_per_year"]
print(f"Initial blocks_per_year: {initial_blocks_per_year}")

# Update to a valid value (100)
test_value = 100
print(f"Attempting to set blocks_per_year to {test_value}")
success = submit_mint_param_update(cronos, test_value)

# Should succeed
assert (
success
), f"Valid blocks_per_year proposal should succeed with value {test_value}"

# Wait for proposal execution
wait_for_new_blocks(cli, 2)

# Verify the chain is still producing blocks (no panic)
updated_params = get_mint_params(cli)
updated_blocks_per_year = updated_params["blocks_per_year"]
print(f"Updated blocks_per_year: {updated_blocks_per_year}")

# Verify the value was updated correctly
assert updated_blocks_per_year == str(
test_value
), f"blocks_per_year should be {test_value}, got {updated_blocks_per_year}"

# Verify chain continues to produce blocks after the update
# This ensures the BeginBlocker doesn't panic with the new value
wait_for_new_blocks(cli, 3)
print(f"Chain continues to produce blocks with valid blocks_per_year {test_value}")


def test_mint_blocks_per_year_max_int64_boundary(cronos):
"""
Test the boundary case: blocks_per_year = MaxInt64.

This value should be valid as it's the maximum positive value
that fits in an int64.
"""
cli = cronos.cosmos_cli()

# Get initial params
initial_params = get_mint_params(cli)
initial_blocks_per_year = initial_params["blocks_per_year"]
print(f"Initial blocks_per_year: {initial_blocks_per_year}")

# Update to MaxInt64 (should be valid)
test_value = MAX_INT64
print(f"Attempting to set blocks_per_year to {test_value} (MaxInt64)")

success = submit_mint_param_update(cronos, test_value)
assert success, f"Proposal should succeed with blocks_per_year = {test_value}"

wait_for_new_blocks(cli, 2)
updated_params = get_mint_params(cli)
updated_blocks_per_year = updated_params["blocks_per_year"]
print(f"Updated blocks_per_year: {updated_blocks_per_year}")
assert updated_blocks_per_year == str(
test_value
), f"blocks_per_year should be {test_value}, got {updated_blocks_per_year}"

wait_for_new_blocks(cli, 3)
print(f"Chain continues to produce blocks with blocks_per_year = {test_value}")


def test_mint_blocks_per_year_just_over_max_int64(cronos):
"""
Test the edge case: blocks_per_year = MaxInt64 + 1.

This is the smallest value that would overflow int64 and should be rejected.
"""
cli = cronos.cosmos_cli()

# Get initial params
initial_params = get_mint_params(cli)
initial_blocks_per_year = initial_params["blocks_per_year"]
print(f"Initial blocks_per_year: {initial_blocks_per_year}")

# Attempt to update to MaxInt64 + 1 (should fail or be rejected)
overflow_value = MAX_INT64 + 1
print(f"Attempting to set blocks_per_year to {overflow_value}")

success = submit_mint_param_update(cronos, overflow_value)

assert not success, f"Proposal should fail for blocks_per_year = {overflow_value}"
wait_for_new_blocks(cli, 1)
current_params = get_mint_params(cli)
assert (
current_params["blocks_per_year"] == initial_blocks_per_year
), "Blocks per year should not change"


def test_mint_blocks_per_year_uint64_max(cronos):
"""
Test that blocks_per_year = 2^64-1 (UINT64_MAX) is properly rejected.
"""
cli = cronos.cosmos_cli()

# Get initial params
initial_params = get_mint_params(cli)
initial_blocks_per_year = initial_params["blocks_per_year"]
print(f"Initial blocks_per_year: {initial_blocks_per_year}")

# Attempt to update to UINT64_MAX (2^64 - 1)
# This value fits in uint64 but severely overflows int64
overflow_value = UINT64_MAX
print(f"Attempting to set blocks_per_year to {overflow_value} (2^64 - 1)")

success = submit_mint_param_update(cronos, overflow_value)

assert not success, f"Proposal should fail for blocks_per_year = {overflow_value}"
wait_for_new_blocks(cli, 1)
current_params = get_mint_params(cli)
assert (
current_params["blocks_per_year"] == initial_blocks_per_year
), "Blocks per year should not change"
Loading