remove softfork2 logic (#15793)

This commit is contained in:
Arvid Norberg 2023-08-01 18:28:16 +02:00 committed by GitHub
parent c20bf49e28
commit f0cb47baef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 62 additions and 218 deletions

View File

@ -68,7 +68,7 @@ class CostLogger:
program,
INFINITE_COST,
mempool_mode=True,
height=DEFAULT_CONSTANTS.SOFT_FORK2_HEIGHT,
height=DEFAULT_CONSTANTS.SOFT_FORK3_HEIGHT,
constants=DEFAULT_CONSTANTS,
)
self.cost_dict[descriptor] = npc_result.cost

View File

@ -495,17 +495,11 @@ async def validate_block_body(
if npc_result is not None:
assert npc_result.conds is not None
block_timestamp: uint64
if height < constants.SOFT_FORK2_HEIGHT:
block_timestamp = block.foliage_transaction_block.timestamp
else:
block_timestamp = prev_transaction_block_timestamp
error = mempool_check_time_locks(
removal_coin_records,
npc_result.conds,
prev_transaction_block_height,
block_timestamp,
prev_transaction_block_timestamp,
)
if error:
return error, None

View File

@ -844,11 +844,7 @@ def validate_unfinished_header_block(
return None, ValidationError(Err.INVALID_TRANSACTIONS_FILTER_HASH)
# 26a. The timestamp in Foliage Block must not be over 5 minutes in the future
if height >= constants.SOFT_FORK2_HEIGHT:
max_future_time = constants.MAX_FUTURE_TIME2
else:
max_future_time = constants.MAX_FUTURE_TIME
if header_block.foliage_transaction_block.timestamp > int(time.time() + max_future_time):
if header_block.foliage_transaction_block.timestamp > int(time.time() + constants.MAX_FUTURE_TIME2):
return None, ValidationError(Err.TIMESTAMP_TOO_FAR_IN_FUTURE)
if prev_b is not None:

View File

@ -35,7 +35,6 @@ class ConsensusConstants:
MAX_PLOT_SIZE: int
SUB_SLOT_TIME_TARGET: int # The target number of seconds per sub-slot
NUM_SP_INTERVALS_EXTRA: int # The difference between signage point and infusion point (plus required_iters)
MAX_FUTURE_TIME: int # The next block can have a timestamp of at most these many seconds more
MAX_FUTURE_TIME2: int # After soft-fork2, this is the new MAX_FUTURE_TIME
NUMBER_OF_TIMESTAMPS: int # Than the average of the last NUMBER_OF_TIMESTAMPS blocks
# Used as the initial cc rc challenges, as well as first block back pointers, and first SES back pointer
@ -63,9 +62,6 @@ class ConsensusConstants:
MAX_GENERATOR_REF_LIST_SIZE: uint32
POOL_SUB_SLOT_ITERS: uint64
# soft fork initiated in 1.8.0 release
SOFT_FORK2_HEIGHT: uint32
# soft fork initiated in 2.0 release
SOFT_FORK3_HEIGHT: uint32

View File

@ -25,7 +25,6 @@ default_kwargs = {
"MAX_PLOT_SIZE": 50,
"SUB_SLOT_TIME_TARGET": 600, # The target number of seconds per slot, mainnet 600
"NUM_SP_INTERVALS_EXTRA": 3, # The number of sp intervals to add to the signage point
"MAX_FUTURE_TIME": 5 * 60, # The next block can have a timestamp of at most these many seconds in the future
"MAX_FUTURE_TIME2": 2 * 60, # The next block can have a timestamp of at most these many seconds in the future
"NUMBER_OF_TIMESTAMPS": 11, # Than the average of the last NUMBER_OF_TIMESTAMPS blocks
# Used as the initial cc rc challenges, as well as first block back pointers, and first SES back pointer
@ -56,7 +55,6 @@ default_kwargs = {
"MAX_GENERATOR_SIZE": 1000000,
"MAX_GENERATOR_REF_LIST_SIZE": 512, # Number of references allowed in the block generator ref list
"POOL_SUB_SLOT_ITERS": 37600000000, # iters limit * NUM_SPS
"SOFT_FORK2_HEIGHT": 3886635,
# October 23, 2023
"SOFT_FORK3_HEIGHT": 4410000,
# June 2024

View File

@ -55,8 +55,7 @@ def get_name_puzzle_conditions(
if mempool_mode:
flags = flags | MEMPOOL_MODE
if height >= constants.SOFT_FORK2_HEIGHT:
flags = flags | ENABLE_ASSERT_BEFORE | NO_RELATIVE_CONDITIONS_ON_EPHEMERAL
flags = flags | ENABLE_ASSERT_BEFORE | NO_RELATIVE_CONDITIONS_ON_EPHEMERAL
if height >= constants.SOFT_FORK3_HEIGHT:
# the soft-fork initiated with 2.0. To activate end of October 2023

View File

@ -72,8 +72,6 @@ def update_testnet_overrides(network_id: str, overrides: Dict[str, Any]) -> None
return
# activate softforks immediately on testnet
# these numbers are supposed to match initial-config.yaml
if "SOFT_FORK2_HEIGHT" not in overrides:
overrides["SOFT_FORK2_HEIGHT"] = 0
if "SOFT_FORK3_HEIGHT" not in overrides:
overrides["SOFT_FORK3_HEIGHT"] = 2997292
if "HARD_FORK_HEIGHT" not in overrides:

View File

@ -149,8 +149,7 @@ test_constants = DEFAULT_CONSTANTS.replace(
"SUB_SLOT_ITERS_STARTING": 2**10, # Must be a multiple of 64
"NUMBER_ZERO_BITS_PLOT_FILTER": 1, # H(plot signature of the challenge) must start with these many zeroes
# Allows creating blockchains with timestamps up to 10 days in the future, for testing
"MAX_FUTURE_TIME": 3600 * 24 * 10,
"MAX_FUTURE_TIME2": 3600 * 24 * 10, # After the Fork
"MAX_FUTURE_TIME2": 3600 * 24 * 10,
"MEMPOOL_BLOCK_BUFFER": 6,
"UNIQUE_PLOTS_WINDOW": 2,
}

View File

@ -71,7 +71,6 @@ network_overrides: &network_overrides
GENESIS_PRE_FARM_POOL_PUZZLE_HASH: d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc
MEMPOOL_BLOCK_BUFFER: 10
MIN_PLOT_SIZE: 18
SOFT_FORK2_HEIGHT: 0
SOFT_FORK3_HEIGHT: 2997292
# planned 2.0 release is July 26, height 2965036 on testnet
# 1 week later

View File

@ -1503,18 +1503,12 @@ class TestBlockHeaderValidation:
await _validate_and_add_block(empty_blockchain, blocks[-1])
@pytest.mark.asyncio
@pytest.mark.parametrize("with_softfork2", [False, True])
async def test_bad_timestamp(self, bt, with_softfork2):
async def test_bad_timestamp(self, bt):
# 26
if with_softfork2:
# enable softfork2 at height 0, to make it apply to this test
# the test constants set MAX_FUTURE_TIME to 10 days, restore it to
# default for this test
constants = bt.constants.replace(SOFT_FORK2_HEIGHT=0, MAX_FUTURE_TIME=5 * 60, MAX_FUTURE_TIME2=2 * 60)
time_delta = 2 * 60 + 1
else:
constants = bt.constants.replace(MAX_FUTURE_TIME=5 * 60)
time_delta = 5 * 60 + 1
# the test constants set MAX_FUTURE_TIME to 10 days, restore it to
# default for this test
constants = bt.constants.replace(MAX_FUTURE_TIME2=2 * 60)
time_delta = 2 * 60 + 1
blocks = bt.get_consecutive_blocks(1)
@ -1867,7 +1861,6 @@ class TestBodyValidation:
assert state_change.fork_height == 2
@pytest.mark.asyncio
@pytest.mark.parametrize("with_softfork2", [False, True])
@pytest.mark.parametrize(
"opcode,lock_value,expected",
[
@ -1941,35 +1934,8 @@ class TestBodyValidation:
(co.ASSERT_BEFORE_SECONDS_ABSOLUTE, 10032, rbr.NEW_PEAK),
],
)
async def test_timelock_conditions(self, opcode, lock_value, expected, with_softfork2, bt):
if with_softfork2:
# enable softfork2 at height 0, to make it apply to this test
constants = bt.constants.replace(SOFT_FORK2_HEIGHT=0)
else:
constants = bt.constants
# if the softfork is not active in this test, fixup all the
# tests to instead expect NEW_PEAK unconditionally
if opcode in [
ConditionOpcode.ASSERT_MY_BIRTH_HEIGHT,
ConditionOpcode.ASSERT_MY_BIRTH_SECONDS,
ConditionOpcode.ASSERT_BEFORE_SECONDS_RELATIVE,
ConditionOpcode.ASSERT_BEFORE_SECONDS_ABSOLUTE,
ConditionOpcode.ASSERT_BEFORE_HEIGHT_RELATIVE,
ConditionOpcode.ASSERT_BEFORE_HEIGHT_ABSOLUTE,
]:
expected = AddBlockResult.NEW_PEAK
# before soft-fork 2, the timestamp we compared against was the
# current block's timestamp as opposed to the previous tx-block's
# timestamp. These conditions used to be valid, before the soft-fork
if opcode == ConditionOpcode.ASSERT_SECONDS_RELATIVE and lock_value > 0 and lock_value <= 10:
expected = AddBlockResult.NEW_PEAK
if opcode == ConditionOpcode.ASSERT_SECONDS_ABSOLUTE and lock_value > 10020 and lock_value <= 10030:
expected = AddBlockResult.NEW_PEAK
async with make_empty_blockchain(constants) as b:
async def test_timelock_conditions(self, opcode, lock_value, expected, bt):
async with make_empty_blockchain(bt.constants) as b:
blocks = bt.get_consecutive_blocks(
3,
guarantee_transaction_block=True,
@ -2100,7 +2066,6 @@ class TestBodyValidation:
assert (res, error, state_change.fork_height if state_change else None) == expected
@pytest.mark.asyncio
@pytest.mark.parametrize("with_softfork2", [False, True])
@pytest.mark.parametrize("with_garbage", [True, False])
@pytest.mark.parametrize(
"opcode,lock_value,expected",
@ -2165,47 +2130,19 @@ class TestBodyValidation:
(co.ASSERT_BEFORE_SECONDS_ABSOLUTE, 10032, rbr.NEW_PEAK),
],
)
async def test_ephemeral_timelock(self, opcode, lock_value, expected, with_garbage, with_softfork2, bt):
if with_softfork2:
# enable softfork2 at height 0, to make it apply to this test
constants = bt.constants.replace(SOFT_FORK2_HEIGHT=0)
async def test_ephemeral_timelock(self, opcode, lock_value, expected, with_garbage, bt):
# we don't allow any birth assertions, not
# relative time locks on ephemeral coins. This test is only for
# ephemeral coins, so these cases should always fail
if opcode in [
ConditionOpcode.ASSERT_MY_BIRTH_HEIGHT,
ConditionOpcode.ASSERT_MY_BIRTH_SECONDS,
ConditionOpcode.ASSERT_SECONDS_RELATIVE,
ConditionOpcode.ASSERT_HEIGHT_RELATIVE,
]:
expected = AddBlockResult.INVALID_BLOCK
# after the softfork, we don't allow any birth assertions, not
# relative time locks on ephemeral coins. This test is only for
# ephemeral coins, so these cases should always fail
if opcode in [
ConditionOpcode.ASSERT_MY_BIRTH_HEIGHT,
ConditionOpcode.ASSERT_MY_BIRTH_SECONDS,
ConditionOpcode.ASSERT_SECONDS_RELATIVE,
ConditionOpcode.ASSERT_HEIGHT_RELATIVE,
]:
expected = AddBlockResult.INVALID_BLOCK
else:
constants = bt.constants
# if the softfork is not active in this test, fixup all the
# tests to instead expect NEW_PEAK unconditionally
if opcode in [
ConditionOpcode.ASSERT_MY_BIRTH_HEIGHT,
ConditionOpcode.ASSERT_MY_BIRTH_SECONDS,
ConditionOpcode.ASSERT_BEFORE_HEIGHT_RELATIVE,
ConditionOpcode.ASSERT_BEFORE_HEIGHT_ABSOLUTE,
ConditionOpcode.ASSERT_BEFORE_SECONDS_RELATIVE,
ConditionOpcode.ASSERT_BEFORE_SECONDS_ABSOLUTE,
]:
expected = AddBlockResult.NEW_PEAK
# before the softfork, we compared ASSERT_SECONDS_* conditions
# against the current block's timestamp, so we need to
# adjust these test cases
if opcode == co.ASSERT_SECONDS_ABSOLUTE and lock_value > 10020 and lock_value <= 10030:
expected = rbr.NEW_PEAK
if opcode == co.ASSERT_SECONDS_RELATIVE and lock_value > -10 and lock_value <= 0:
expected = rbr.NEW_PEAK
async with make_empty_blockchain(constants) as b:
async with make_empty_blockchain(bt.constants) as b:
blocks = bt.get_consecutive_blocks(
3,
guarantee_transaction_block=True,

View File

@ -890,6 +890,19 @@ class TestBlockchainTransactions:
full_node_1.blockchain, invalid_new_blocks[-1], expected_error=Err.ASSERT_SECONDS_RELATIVE_FAILED
)
# we compare the timestamp against the previous transaction block, so in
# order to progress the timestamp, we need to farm one more block
blocks.extend(
bt.get_consecutive_blocks(
1,
blocks,
farmer_reward_puzzle_hash=coinbase_puzzlehash,
guarantee_transaction_block=True,
time_per_block=301,
)
)
await full_node_api_1.full_node.add_block(blocks[-1])
valid_new_blocks = bt.get_consecutive_blocks(
1,
blocks,
@ -951,6 +964,19 @@ class TestBlockchainTransactions:
full_node_1.blockchain, invalid_new_blocks[-1], expected_error=Err.ASSERT_SECONDS_ABSOLUTE_FAILED
)
# we compare the timestamp against the previous transaction block, so in
# order to progress the timestamp, we need to farm one more block
blocks.extend(
bt.get_consecutive_blocks(
1,
blocks,
farmer_reward_puzzle_hash=coinbase_puzzlehash,
guarantee_transaction_block=True,
time_per_block=30,
)
)
await full_node_api_1.full_node.add_block(blocks[-1])
valid_new_blocks = bt.get_consecutive_blocks(
1,
blocks,

View File

@ -16,7 +16,7 @@ def cost_of_spend_bundle(spend_bundle: SpendBundle) -> int:
program,
INFINITE_COST,
mempool_mode=True,
height=DEFAULT_CONSTANTS.SOFT_FORK2_HEIGHT,
height=DEFAULT_CONSTANTS.SOFT_FORK3_HEIGHT,
constants=DEFAULT_CONSTANTS,
)
return npc_result.cost

View File

@ -169,7 +169,7 @@ def db_version(request) -> int:
return request.param
@pytest.fixture(scope="function", params=[1000000, 3886635, 4410000, 5496000])
@pytest.fixture(scope="function", params=[1000000, 4410000, 5496000])
def softfork_height(request) -> int:
return request.param
@ -540,48 +540,6 @@ async def one_node() -> AsyncIterator[Tuple[List[Service], List[FullNodeSimulato
yield _
@pytest.fixture(scope="function", params=[True, False])
def enable_softfork2(request):
return request.param
@pytest_asyncio.fixture(scope="function")
async def one_node_one_block_with_softfork2(
enable_softfork2,
) -> AsyncIterator[Tuple[Union[FullNodeAPI, FullNodeSimulator], ChiaServer, BlockTools]]:
if enable_softfork2:
constant_replacements = {"SOFT_FORK2_HEIGHT": 0}
else:
constant_replacements = {}
async_gen = setup_simulators_and_wallets(1, 0, constant_replacements)
nodes, _, bt = await async_gen.__anext__()
full_node_1 = nodes[0]
server_1 = full_node_1.full_node.server
wallet_a = bt.get_pool_wallet_tool()
reward_ph = wallet_a.get_new_puzzlehash()
blocks = bt.get_consecutive_blocks(
1,
guarantee_transaction_block=True,
farmer_reward_puzzle_hash=reward_ph,
pool_reward_puzzle_hash=reward_ph,
genesis_timestamp=uint64(10000),
time_per_block=10,
)
assert blocks[0].height == 0
for block in blocks:
await full_node_1.full_node.add_block(block)
await time_out_assert(60, node_height_at_least, True, full_node_1, blocks[-1].height)
yield full_node_1, server_1, bt
async for _ in async_gen:
yield _
@pytest_asyncio.fixture(scope="function")
async def one_node_one_block() -> AsyncIterator[Tuple[Union[FullNodeAPI, FullNodeSimulator], ChiaServer, BlockTools]]:
async_gen = setup_simulators_and_wallets(1, 0, {})

View File

@ -60,19 +60,14 @@ async def check_spend_bundle_validity(
blocks: List[FullBlock],
spend_bundle: SpendBundle,
expected_err: Optional[Err] = None,
softfork2: bool = False,
) -> Tuple[List[CoinRecord], List[CoinRecord], FullBlock]:
"""
This test helper create an extra block after the given blocks that contains the given
`SpendBundle`, and then invokes `add_block` to ensure that it's accepted (if `expected_err=None`)
or fails with the correct error code.
"""
if softfork2:
constants = bt.constants.replace(SOFT_FORK2_HEIGHT=0)
else:
constants = bt.constants
db_wrapper, blockchain = await create_ram_blockchain(constants)
db_wrapper, blockchain = await create_ram_blockchain(bt.constants)
try:
for block in blocks:
await _validate_and_add_block(blockchain, block)
@ -111,7 +106,6 @@ async def check_conditions(
condition_solution: Program,
expected_err: Optional[Err] = None,
spend_reward_index: int = -2,
softfork2: bool = False,
) -> Tuple[List[CoinRecord], List[CoinRecord], FullBlock]:
blocks = await initial_blocks(bt)
coin = list(blocks[spend_reward_index].get_included_reward_coins())[0]
@ -121,7 +115,7 @@ async def check_conditions(
# now let's try to create a block with the spend bundle and ensure that it doesn't validate
return await check_spend_bundle_validity(bt, blocks, spend_bundle, expected_err=expected_err, softfork2=softfork2)
return await check_spend_bundle_validity(bt, blocks, spend_bundle, expected_err=expected_err)
co = ConditionOpcode
@ -195,7 +189,6 @@ class TestConditions:
assert new_block.transactions_info.cost - block_base_cost == expected_cost
@pytest.mark.asyncio
@pytest.mark.parametrize("softfork2", [True, False])
@pytest.mark.parametrize(
"opcode,value,expected",
[
@ -279,32 +272,9 @@ class TestConditions:
(co.ASSERT_BEFORE_SECONDS_ABSOLUTE, 0x100000000, None),
],
)
async def test_condition(self, opcode, value, expected, bt, softfork2):
async def test_condition(self, opcode, value, expected, bt):
conditions = Program.to(assemble(f"(({opcode[0]} {value}))"))
# when soft fork 2 is not active, these conditions are also not active,
# and never constrain the block
if not softfork2 and opcode in [
co.ASSERT_MY_BIRTH_HEIGHT,
co.ASSERT_MY_BIRTH_SECONDS,
co.ASSERT_BEFORE_SECONDS_RELATIVE,
co.ASSERT_BEFORE_SECONDS_ABSOLUTE,
co.ASSERT_BEFORE_HEIGHT_RELATIVE,
co.ASSERT_BEFORE_HEIGHT_ABSOLUTE,
]:
expected = None
if not softfork2:
# before soft-fork 2, the timestamp we compared against was the
# current block's timestamp as opposed to the previous tx-block's
# timestamp. These conditions used to be valid, before the soft-fork
if opcode == ConditionOpcode.ASSERT_SECONDS_RELATIVE and value > 10 and value <= 20:
expected = None
if opcode == ConditionOpcode.ASSERT_SECONDS_ABSOLUTE and value > 10030 and value <= 10040:
expected = None
await check_conditions(bt, conditions, expected_err=expected, softfork2=softfork2)
await check_conditions(bt, conditions, expected_err=expected)
@pytest.mark.asyncio
async def test_invalid_my_id(self, bt):
@ -433,4 +403,4 @@ class TestConditions:
conditions += b"\x80"
conditions_program = Program.from_bytes(conditions)
await check_conditions(bt, conditions_program, expected_err=expect_err, softfork2=True)
await check_conditions(bt, conditions_program, expected_err=expect_err)

View File

@ -410,9 +410,7 @@ class TestMempoolManager:
(co.ASSERT_SECONDS_ABSOLUTE, 10052, mis.FAILED),
],
)
async def test_ephemeral_timelock(
self, one_node_one_block_with_softfork2, enable_softfork2, wallet_a, opcode, lock_value, expected
):
async def test_ephemeral_timelock(self, one_node_one_block, wallet_a, opcode, lock_value, expected):
def test_fun(coin_1: Coin, coin_2: Coin) -> SpendBundle:
conditions = {opcode: [ConditionWithArgs(opcode, [int_to_bytes(lock_value)])]}
tx1 = wallet_a.generate_signed_transaction(uint64(1000000), wallet_a.get_new_puzzlehash(), coin_2)
@ -425,15 +423,10 @@ class TestMempoolManager:
bundle = SpendBundle.aggregate([tx1, tx2])
return bundle
if not enable_softfork2 and opcode in [co.ASSERT_MY_BIRTH_HEIGHT, co.ASSERT_MY_BIRTH_SECONDS]:
expected = MempoolInclusionStatus.FAILED
full_node_1, server_1, bt = one_node_one_block_with_softfork2
full_node_1, server_1, bt = one_node_one_block
_ = await next_block(full_node_1, wallet_a, bt)
_ = await next_block(full_node_1, wallet_a, bt)
blocks, bundle, status, err = await self.condition_tester2(
one_node_one_block_with_softfork2, wallet_a, test_fun
)
blocks, bundle, status, err = await self.condition_tester2(one_node_one_block, wallet_a, test_fun)
mempool_bundle = full_node_1.full_node.mempool_manager.get_spendbundle(bundle.name())
print(f"opcode={opcode} timelock_value={lock_value} expected={expected} status={status}")

View File

@ -558,7 +558,6 @@ mis = MempoolInclusionStatus
@pytest.mark.asyncio
@pytest.mark.parametrize("softfork2", [False, True])
@pytest.mark.parametrize(
"opcode,lock_value,expected_status,expected_error",
[
@ -617,29 +616,14 @@ async def test_ephemeral_timelock(
lock_value: int,
expected_status: MempoolInclusionStatus,
expected_error: Optional[Err],
softfork2: bool,
) -> None:
if softfork2:
constants = DEFAULT_CONSTANTS.replace(SOFT_FORK2_HEIGHT=0)
else:
constants = DEFAULT_CONSTANTS
mempool_manager = await instantiate_mempool_manager(
get_coin_record=get_coin_record_for_test_coins,
block_height=uint32(5),
block_timestamp=uint64(10050),
constants=constants,
constants=DEFAULT_CONSTANTS,
)
if not softfork2 and opcode in [
co.ASSERT_BEFORE_HEIGHT_ABSOLUTE,
co.ASSERT_BEFORE_HEIGHT_RELATIVE,
co.ASSERT_BEFORE_SECONDS_ABSOLUTE,
co.ASSERT_BEFORE_SECONDS_RELATIVE,
]:
expected_error = Err.INVALID_CONDITION
expected_status = MempoolInclusionStatus.FAILED
conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 1]]
created_coin = Coin(TEST_COIN_ID, IDENTITY_PUZZLE_HASH, 1)
sb1 = spend_bundle_from_conditions(conditions)
@ -1017,7 +1001,7 @@ async def test_assert_before_expiration(
get_coin_record,
block_height=uint32(10),
block_timestamp=uint64(10000),
constants=DEFAULT_CONSTANTS.replace(SOFT_FORK2_HEIGHT=0),
constants=DEFAULT_CONSTANTS,
)
bundle = spend_bundle_from_conditions(

View File

@ -9,7 +9,6 @@ def test_testnet10() -> None:
overrides: Dict[str, Any] = {}
update_testnet_overrides("testnet10", overrides)
assert overrides == {
"SOFT_FORK2_HEIGHT": 0,
"SOFT_FORK3_HEIGHT": 2997292,
"HARD_FORK_HEIGHT": 2997292,
"PLOT_FILTER_128_HEIGHT": 3061804,
@ -20,7 +19,6 @@ def test_testnet10() -> None:
def test_testnet10_existing() -> None:
overrides: Dict[str, Any] = {
"SOFT_FORK2_HEIGHT": 42,
"SOFT_FORK3_HEIGHT": 42,
"HARD_FORK_HEIGHT": 42,
"PLOT_FILTER_128_HEIGHT": 42,
@ -29,7 +27,6 @@ def test_testnet10_existing() -> None:
}
update_testnet_overrides("testnet10", overrides)
assert overrides == {
"SOFT_FORK2_HEIGHT": 42,
"SOFT_FORK3_HEIGHT": 42,
"HARD_FORK_HEIGHT": 42,
"PLOT_FILTER_128_HEIGHT": 42,