Skip to content

Commit 4d188e0

Browse files
authored
catchup: into long_lived/datalayer_merkle_blob from main @ dac837e (#19808)
Source hash: dac837e Remaining commits: 0
2 parents e862431 + fb8de7a commit 4d188e0

File tree

133 files changed

+5757
-3314
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

133 files changed

+5757
-3314
lines changed

Install.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ foreach ($extra in $extras)
105105
./Setup-poetry.ps1 -pythonVersion "$pythonVersion"
106106

107107
.penv/Scripts/poetry env use $(py -"$pythonVersion" -c 'import sys; print(sys.executable)')
108-
.penv/Scripts/poetry install @extras_cli
108+
.penv/Scripts/poetry sync @extras_cli
109109

110110
if ($i)
111111
{

benchmarks/coin_store.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@ def make_coin() -> Coin:
2828
return Coin(rand_hash(), rand_hash(), uint64(1))
2929

3030

31-
def make_coins(num: int) -> tuple[list[Coin], list[bytes32]]:
32-
additions: list[Coin] = []
31+
def make_coins(num: int) -> tuple[list[tuple[bytes32, Coin, bool]], list[bytes32]]:
32+
additions: list[tuple[bytes32, Coin, bool]] = []
3333
hashes: list[bytes32] = []
3434
for i in range(num):
3535
c = make_coin()
36-
additions.append(c)
37-
hashes.append(c.name())
36+
coin_id = c.name()
37+
additions.append((coin_id, c, False))
38+
hashes.append(coin_id)
3839

3940
return additions, hashes
4041

@@ -145,7 +146,7 @@ async def run_new_block_benchmark(version: int) -> None:
145146
# add one new coins
146147
c = make_coin()
147148
coin_id = c.name()
148-
additions.append(c)
149+
additions.append((coin_id, c, False))
149150
total_add += 1
150151

151152
farmer_coin, pool_coin = rewards(uint32(height))

benchmarks/mempool-long-lived.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from chia_rs import CoinSpend, G2Element, SpendBundle
1010
from chia_rs.sized_bytes import bytes32
1111
from chia_rs.sized_ints import uint32, uint64
12-
from clvm.casts import int_to_bytes
1312

1413
from chia.consensus.default_constants import DEFAULT_CONSTANTS
1514
from chia.full_node.mempool_manager import MempoolManager
@@ -18,6 +17,7 @@
1817
from chia.types.coin_record import CoinRecord
1918
from chia.types.condition_opcodes import ConditionOpcode
2019
from chia.types.mempool_item import UnspentLineageInfo
20+
from chia.util.casts import int_to_bytes
2121

2222
# this is one week worth of blocks
2323
NUM_ITERS = 32256

chia/_tests/blockchain/test_blockchain.py

Lines changed: 214 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
from __future__ import annotations
22

33
import asyncio
4+
import copy
45
import logging
56
import random
67
import time
78
from collections.abc import AsyncIterator, Awaitable
89
from contextlib import asynccontextmanager
9-
from dataclasses import replace
10+
from dataclasses import dataclass, replace
1011
from typing import Optional
1112

1213
import pytest
@@ -20,12 +21,14 @@
2021
InfusedChallengeChainSubSlot,
2122
MerkleSet,
2223
SpendBundle,
24+
SpendBundleConditions,
25+
SpendConditions,
2326
TransactionsInfo,
2427
UnfinishedBlock,
28+
is_canonical_serialization,
2529
)
2630
from chia_rs.sized_bytes import bytes32
2731
from chia_rs.sized_ints import uint8, uint32, uint64
28-
from clvm.casts import int_to_bytes
2932

3033
from chia._tests.blockchain.blockchain_test_utils import (
3134
_validate_and_add_block,
@@ -38,7 +41,7 @@
3841
from chia._tests.util.blockchain import create_blockchain
3942
from chia._tests.util.get_name_puzzle_conditions import get_name_puzzle_conditions
4043
from chia.consensus.augmented_chain import AugmentedBlockchain
41-
from chia.consensus.block_body_validation import ForkInfo
44+
from chia.consensus.block_body_validation import ForkAdd, ForkInfo
4245
from chia.consensus.block_header_validation import validate_finished_header_block
4346
from chia.consensus.block_rewards import calculate_base_farmer_reward
4447
from chia.consensus.blockchain import AddBlockResult, Blockchain
@@ -61,6 +64,7 @@
6164
from chia.types.condition_with_args import ConditionWithArgs
6265
from chia.types.generator_types import BlockGenerator
6366
from chia.types.validation_state import ValidationState
67+
from chia.util.casts import int_to_bytes
6468
from chia.util.errors import Err
6569
from chia.util.hash import std_hash
6670
from chia.util.keychain import Keychain
@@ -3648,6 +3652,41 @@ async def test_get_blocks_at(self, empty_blockchain: Blockchain, default_1000_bl
36483652
assert len(blocks) == 200
36493653
assert blocks[-1].height == 199
36503654

3655+
@pytest.mark.anyio
3656+
async def test_overlong_generator_encoding(
3657+
self, empty_blockchain: Blockchain, bt: BlockTools, consensus_mode: ConsensusMode
3658+
) -> None:
3659+
# add enough blocks to pass the hard fork
3660+
blocks = bt.get_consecutive_blocks(10)
3661+
for b in blocks[:-1]:
3662+
await _validate_and_add_block(empty_blockchain, b)
3663+
3664+
while not blocks[-1].is_transaction_block():
3665+
await _validate_and_add_block(empty_blockchain, blocks[-1])
3666+
blocks = bt.get_consecutive_blocks(1, block_list_input=blocks)
3667+
original_block: FullBlock = blocks[-1]
3668+
3669+
# overlong encoding
3670+
generator = SerializedProgram.fromhex("c00101")
3671+
assert not is_canonical_serialization(bytes(generator))
3672+
3673+
block = recursive_replace(original_block, "transactions_generator", generator)
3674+
block = recursive_replace(block, "transactions_info.generator_root", std_hash(bytes(generator)))
3675+
block = recursive_replace(
3676+
block, "foliage_transaction_block.transactions_info_hash", std_hash(bytes(block.transactions_info))
3677+
)
3678+
block = recursive_replace(
3679+
block, "foliage.foliage_transaction_block_hash", std_hash(bytes(block.foliage_transaction_block))
3680+
)
3681+
3682+
# overlong encoding became invalid in the 3.0 hard fork
3683+
if consensus_mode == ConsensusMode.HARD_FORK_3_0:
3684+
expected_error = Err.INVALID_TRANSACTIONS_GENERATOR_ENCODING
3685+
else:
3686+
expected_error = None
3687+
3688+
await _validate_and_add_block(empty_blockchain, block, expected_error=expected_error, skip_prevalidation=True)
3689+
36513690

36523691
@pytest.mark.anyio
36533692
async def test_reorg_new_ref(empty_blockchain: Blockchain, bt: BlockTools) -> None:
@@ -4199,3 +4238,175 @@ async def test_get_header_blocks_in_range_tx_filter_non_tx_block(empty_blockchai
41994238
blocks_with_filter = await b.get_header_blocks_in_range(0, 42, tx_filter=True)
42004239
empty_tx_filter = b"\x00"
42014240
assert blocks_with_filter[non_tx_block.header_hash].transactions_filter == empty_tx_filter
4241+
4242+
4243+
@dataclass(frozen=True)
4244+
class ForkInfoTestSetup:
4245+
fork_info: ForkInfo
4246+
initial_additions_since_fork: dict[bytes32, ForkAdd]
4247+
test_block: FullBlock
4248+
coin: Coin
4249+
child_coin: Coin
4250+
4251+
@classmethod
4252+
def create(cls, same_ph_as_parent: bool, same_amount_as_parent: bool) -> ForkInfoTestSetup:
4253+
from chia._tests.util.network_protocol_data import full_block as test_block
4254+
4255+
unrelated_coin = Coin(bytes32([0] * 32), bytes32([1] * 32), uint64(42))
4256+
# We add this initial state with an unrelated addition, to create a
4257+
# difference between the `rollback` state and the completely empty
4258+
# `reset` state.
4259+
initial_additions_since_fork = {
4260+
unrelated_coin.name(): ForkAdd(
4261+
coin=unrelated_coin,
4262+
confirmed_height=uint32(1),
4263+
timestamp=uint64(0),
4264+
hint=None,
4265+
is_coinbase=False,
4266+
same_as_parent=False,
4267+
)
4268+
}
4269+
fork_info = ForkInfo(
4270+
test_block.height - 1,
4271+
test_block.height - 1,
4272+
test_block.prev_header_hash,
4273+
additions_since_fork=copy.copy(initial_additions_since_fork),
4274+
)
4275+
puzzle_hash = bytes32([2] * 32)
4276+
amount = uint64(1337)
4277+
coin = Coin(bytes32([3] * 32), puzzle_hash, amount)
4278+
child_coin_ph = puzzle_hash if same_ph_as_parent else bytes32([4] * 32)
4279+
child_coin_amount = amount if same_amount_as_parent else uint64(0)
4280+
child_coin = Coin(coin.name(), child_coin_ph, child_coin_amount)
4281+
return cls(
4282+
fork_info=fork_info,
4283+
initial_additions_since_fork=initial_additions_since_fork,
4284+
test_block=test_block,
4285+
coin=coin,
4286+
child_coin=child_coin,
4287+
)
4288+
4289+
def check_additions(self, expected_same_parent_additions: set[bytes32]) -> None:
4290+
assert all(
4291+
a in self.fork_info.additions_since_fork and self.fork_info.additions_since_fork[a].same_as_parent
4292+
for a in expected_same_parent_additions
4293+
)
4294+
remaining_additions = set(self.fork_info.additions_since_fork) - expected_same_parent_additions
4295+
assert not any(self.fork_info.additions_since_fork[a].same_as_parent for a in remaining_additions)
4296+
4297+
4298+
@pytest.mark.parametrize("same_ph_as_parent", [True, False])
4299+
@pytest.mark.parametrize("same_amount_as_parent", [True, False])
4300+
@pytest.mark.parametrize("rollback", [True, False])
4301+
@pytest.mark.parametrize("reset", [True, False])
4302+
@pytest.mark.anyio
4303+
async def test_include_spends_same_as_parent(
4304+
same_ph_as_parent: bool, same_amount_as_parent: bool, rollback: bool, reset: bool
4305+
) -> None:
4306+
"""
4307+
Tests that `ForkInfo` properly tracks same-as-parent created coins.
4308+
A created coin is tracked as such if its puzzle hash and amount match the
4309+
parent. We're covering here `include_spends`, `rollback` and `reset` in the
4310+
context of same-as-parent coins.
4311+
"""
4312+
test_setup = ForkInfoTestSetup.create(same_ph_as_parent, same_amount_as_parent)
4313+
# Now let's prepare the test spend bundle conditions
4314+
create_coin = [(test_setup.child_coin.puzzle_hash, test_setup.child_coin.amount, None)]
4315+
conds = SpendBundleConditions(
4316+
[
4317+
SpendConditions(
4318+
test_setup.coin.name(),
4319+
test_setup.coin.parent_coin_info,
4320+
test_setup.coin.puzzle_hash,
4321+
test_setup.coin.amount,
4322+
None,
4323+
None,
4324+
None,
4325+
None,
4326+
None,
4327+
None,
4328+
create_coin,
4329+
[],
4330+
[],
4331+
[],
4332+
[],
4333+
[],
4334+
[],
4335+
[],
4336+
0,
4337+
0,
4338+
0,
4339+
)
4340+
],
4341+
0,
4342+
0,
4343+
0,
4344+
None,
4345+
None,
4346+
[],
4347+
0,
4348+
0,
4349+
0,
4350+
True,
4351+
0,
4352+
0,
4353+
)
4354+
# Now let's run the test
4355+
test_setup.fork_info.include_spends(conds, test_setup.test_block, test_setup.test_block.header_hash)
4356+
# Let's make sure the results are as expected
4357+
expected_same_parent_additions = (
4358+
{test_setup.child_coin.name()} if same_ph_as_parent and same_amount_as_parent else set()
4359+
)
4360+
test_setup.check_additions(expected_same_parent_additions)
4361+
if rollback:
4362+
# Now we rollback before the spend that belongs to the test conditions
4363+
test_setup.fork_info.rollback(test_setup.test_block.prev_header_hash, test_setup.test_block.height - 1)
4364+
# That should leave only the initial additions we started with, which
4365+
# are unrelated to the test conditions. We added this initial state to
4366+
# create a difference between `rollback` state and the completely empty
4367+
# `reset` state.
4368+
assert test_setup.fork_info.additions_since_fork == test_setup.initial_additions_since_fork
4369+
if reset:
4370+
# Now we reset to a test height and header hash
4371+
test_setup.fork_info.reset(1, bytes32([0] * 32))
4372+
# That should leave this empty
4373+
assert test_setup.fork_info.additions_since_fork == {}
4374+
4375+
4376+
@pytest.mark.parametrize("same_ph_as_parent", [True, False])
4377+
@pytest.mark.parametrize("same_amount_as_parent", [True, False])
4378+
@pytest.mark.parametrize("rollback", [True, False])
4379+
@pytest.mark.parametrize("reset", [True, False])
4380+
@pytest.mark.anyio
4381+
async def test_include_block_same_as_parent_coins(
4382+
same_ph_as_parent: bool, same_amount_as_parent: bool, rollback: bool, reset: bool
4383+
) -> None:
4384+
"""
4385+
Tests that `ForkInfo` properly tracks same-as-parent created coins.
4386+
A created coin is tracked as such if its puzzle hash and amount match the
4387+
parent. We're covering here `include_block`, `rollback` and `reset` in the
4388+
context of such coins.
4389+
"""
4390+
test_setup = ForkInfoTestSetup.create(same_ph_as_parent, same_amount_as_parent)
4391+
# Now let's run the test
4392+
test_setup.fork_info.include_block(
4393+
[(test_setup.child_coin, None)],
4394+
[(test_setup.coin.name(), test_setup.coin)],
4395+
test_setup.test_block,
4396+
test_setup.test_block.header_hash,
4397+
)
4398+
# Let's make sure the results are as expected
4399+
expected_same_as_parent_additions = (
4400+
{test_setup.child_coin.name()} if same_ph_as_parent and same_amount_as_parent else set()
4401+
)
4402+
test_setup.check_additions(expected_same_as_parent_additions)
4403+
if rollback:
4404+
# Now we rollback before the spend that belongs to the test conditions
4405+
test_setup.fork_info.rollback(test_setup.test_block.prev_header_hash, test_setup.test_block.height - 1)
4406+
# That should leave only the initial additions we started with
4407+
assert test_setup.fork_info.additions_since_fork == test_setup.initial_additions_since_fork
4408+
if reset:
4409+
# Now we reset to a test height and header hash
4410+
test_setup.fork_info.reset(1, bytes32([0] * 32))
4411+
# That should leave this empty
4412+
assert test_setup.fork_info.additions_since_fork == {}

chia/_tests/blockchain/test_blockchain_transactions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from chia_rs import SpendBundle
77
from chia_rs.sized_bytes import bytes32
88
from chia_rs.sized_ints import uint32, uint64
9-
from clvm.casts import int_to_bytes
109

1110
from chia._tests.blockchain.blockchain_test_utils import _validate_and_add_block
1211
from chia._tests.util.generator_tools_testing import run_and_get_removals_and_additions
@@ -19,6 +18,7 @@
1918
from chia.simulator.wallet_tools import WalletTool
2019
from chia.types.condition_opcodes import ConditionOpcode
2120
from chia.types.condition_with_args import ConditionWithArgs
21+
from chia.util.casts import int_to_bytes
2222
from chia.util.errors import Err
2323
from chia.wallet.conditions import AssertCoinAnnouncement, AssertPuzzleAnnouncement
2424
from chia.wallet.estimate_fees import estimate_fees

chia/_tests/blockchain/test_build_chains.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def validate_coins(constants: ConsensusConstants, blocks: list[FullBlock]) -> No
7777
constants,
7878
)
7979

80-
for rem in removals:
80+
for _, rem in removals:
8181
try:
8282
unspent_coins.remove(rem)
8383
except KeyError: # pragma: no cover

chia/_tests/blockchain/test_get_block_generator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
import pytest
77
from chia_rs.sized_bytes import bytes32
88
from chia_rs.sized_ints import uint32
9-
from clvm.casts import int_to_bytes
109

1110
from chia.consensus.get_block_generator import get_block_generator
1211
from chia.types.blockchain_format.serialized_program import SerializedProgram
1312
from chia.types.generator_types import BlockGenerator
13+
from chia.util.casts import int_to_bytes
1414

1515

1616
@dataclass(frozen=True)

0 commit comments

Comments
 (0)