chia-blockchain 2.5.8rc1__py3-none-any.whl → 2.6.0rc2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. chia/_tests/blockchain/test_blockchain_transactions.py +5 -2
  2. chia/_tests/conftest.py +8 -2
  3. chia/_tests/core/full_node/test_full_node.py +48 -8
  4. chia/_tests/core/full_node/test_hard_fork_utils.py +92 -0
  5. chia/_tests/core/full_node/test_prev_tx_block.py +6 -6
  6. chia/_tests/core/full_node/test_tx_processing_queue.py +92 -8
  7. chia/_tests/core/mempool/test_mempool.py +27 -15
  8. chia/_tests/core/mempool/test_mempool_manager.py +25 -15
  9. chia/_tests/util/test_replace_str_to_bytes.py +1 -0
  10. chia/_tests/util/test_testnet_overrides.py +3 -3
  11. chia/_tests/wallet/sync/test_wallet_sync.py +20 -13
  12. chia/_tests/wallet/test_new_wallet_protocol.py +14 -12
  13. chia/_tests/wallet/test_wallet_node.py +2 -1
  14. chia/apis/full_node_stub.py +4 -2
  15. chia/consensus/block_header_validation.py +1 -1
  16. chia/consensus/blockchain.py +2 -2
  17. chia/consensus/default_constants.py +3 -0
  18. chia/consensus/get_block_challenge.py +14 -6
  19. chia/consensus/multiprocess_validation.py +2 -2
  20. chia/full_node/full_node.py +3 -1
  21. chia/full_node/full_node_api.py +16 -14
  22. chia/full_node/full_node_rpc_api.py +6 -26
  23. chia/full_node/hard_fork_utils.py +44 -0
  24. chia/full_node/tx_processing_queue.py +101 -38
  25. chia/full_node/weight_proof.py +1 -1
  26. chia/simulator/block_tools.py +3 -3
  27. chia/util/initial-config.yaml +1 -0
  28. chia/util/streamable.py +2 -2
  29. chia/wallet/conditions.py +22 -1
  30. {chia_blockchain-2.5.8rc1.dist-info → chia_blockchain-2.6.0rc2.dist-info}/METADATA +2 -2
  31. {chia_blockchain-2.5.8rc1.dist-info → chia_blockchain-2.6.0rc2.dist-info}/RECORD +34 -32
  32. {chia_blockchain-2.5.8rc1.dist-info → chia_blockchain-2.6.0rc2.dist-info}/WHEEL +0 -0
  33. {chia_blockchain-2.5.8rc1.dist-info → chia_blockchain-2.6.0rc2.dist-info}/entry_points.txt +0 -0
  34. {chia_blockchain-2.5.8rc1.dist-info → chia_blockchain-2.6.0rc2.dist-info}/licenses/LICENSE +0 -0
@@ -28,6 +28,7 @@ from chia_rs.sized_ints import uint8, uint32, uint64
28
28
  from chiabip158 import PyBIP158
29
29
 
30
30
  from chia._tests.conftest import ConsensusMode
31
+ from chia._tests.connection_utils import add_dummy_connection, connect_and_get_peer
31
32
  from chia._tests.util.misc import Marks, datacases, invariant_check_mempool
32
33
  from chia._tests.util.setup_nodes import OldSimulatorsAndWallets, setup_simulators_and_wallets
33
34
  from chia.consensus.condition_costs import ConditionCost
@@ -55,6 +56,7 @@ from chia.full_node.mempool_manager import (
55
56
  from chia.protocols import wallet_protocol
56
57
  from chia.protocols.full_node_protocol import RequestBlock, RespondBlock
57
58
  from chia.protocols.protocol_message_types import ProtocolMessageTypes
59
+ from chia.server.ws_connection import WSChiaConnection
58
60
  from chia.simulator.full_node_simulator import FullNodeSimulator
59
61
  from chia.simulator.simulator_protocol import FarmNewBlockProtocol
60
62
  from chia.simulator.wallet_tools import WalletTool
@@ -67,7 +69,6 @@ from chia.types.condition_opcodes import ConditionOpcode
67
69
  from chia.types.condition_with_args import ConditionWithArgs
68
70
  from chia.types.mempool_inclusion_status import MempoolInclusionStatus
69
71
  from chia.types.mempool_item import BundleCoinSpend, MempoolItem, UnspentLineageInfo
70
- from chia.types.peer_info import PeerInfo
71
72
  from chia.util.casts import int_to_bytes
72
73
  from chia.util.default_root import DEFAULT_ROOT_PATH
73
74
  from chia.util.errors import Err, ValidationError
@@ -1842,9 +1843,13 @@ async def test_identical_spend_aggregation_e2e(
1842
1843
  }
1843
1844
 
1844
1845
  async def send_to_mempool(
1845
- full_node: FullNodeSimulator, spend_bundle: SpendBundle, *, expecting_conflict: bool = False
1846
+ full_node: FullNodeSimulator,
1847
+ wallet_peer: WSChiaConnection,
1848
+ spend_bundle: SpendBundle,
1849
+ *,
1850
+ expecting_conflict: bool = False,
1846
1851
  ) -> None:
1847
- res = await full_node.send_transaction(wallet_protocol.SendTransaction(spend_bundle))
1852
+ res = await full_node.send_transaction(wallet_protocol.SendTransaction(spend_bundle), wallet_peer)
1848
1853
  assert res is not None and ProtocolMessageTypes(res.type) == ProtocolMessageTypes.transaction_ack
1849
1854
  res_parsed = wallet_protocol.TransactionAck.from_bytes(res.data)
1850
1855
  if expecting_conflict:
@@ -1872,7 +1877,7 @@ async def test_identical_spend_aggregation_e2e(
1872
1877
  await wallet.generate_signed_transaction([uint64(200)] * len(phs), phs, action_scope)
1873
1878
  [tx] = action_scope.side_effects.transactions
1874
1879
  assert tx.spend_bundle is not None
1875
- await send_to_mempool(full_node_api, tx.spend_bundle)
1880
+ await send_to_mempool(full_node_api, wallet_peer, tx.spend_bundle)
1876
1881
  await farm_a_block(full_node_api, wallet_node, ph)
1877
1882
  coins = list(await wallet_node.wallet_state_manager.coin_store.get_unspent_coins_for_wallet(1))
1878
1883
  # Two blocks farmed plus 3 transactions
@@ -1881,7 +1886,7 @@ async def test_identical_spend_aggregation_e2e(
1881
1886
 
1882
1887
  [[full_node_api], [[wallet_node, wallet_server]], _] = simulator_and_wallet
1883
1888
  server = full_node_api.full_node.server
1884
- await wallet_server.start_client(PeerInfo(self_hostname, server.get_port()), None)
1889
+ wallet_peer = await connect_and_get_peer(server, wallet_server, self_hostname)
1885
1890
  wallet, coins, ph = await make_setup_and_coins(full_node_api, wallet_node)
1886
1891
 
1887
1892
  # Make sure spending AB then BC would generate a conflict for the latter
@@ -1896,10 +1901,10 @@ async def test_identical_spend_aggregation_e2e(
1896
1901
  assert tx_b.spend_bundle is not None
1897
1902
  assert tx_c.spend_bundle is not None
1898
1903
  ab_bundle = SpendBundle.aggregate([tx_a.spend_bundle, tx_b.spend_bundle])
1899
- await send_to_mempool(full_node_api, ab_bundle)
1904
+ await send_to_mempool(full_node_api, wallet_peer, ab_bundle)
1900
1905
  # BC should conflict here (on B)
1901
1906
  bc_bundle = SpendBundle.aggregate([tx_b.spend_bundle, tx_c.spend_bundle])
1902
- await send_to_mempool(full_node_api, bc_bundle, expecting_conflict=True)
1907
+ await send_to_mempool(full_node_api, wallet_peer, bc_bundle, expecting_conflict=True)
1903
1908
  await farm_a_block(full_node_api, wallet_node, ph)
1904
1909
 
1905
1910
  # Make sure DE and EF would aggregate on E when E is eligible for deduplication
@@ -1913,7 +1918,7 @@ async def test_identical_spend_aggregation_e2e(
1913
1918
  )
1914
1919
  [tx] = action_scope.side_effects.transactions
1915
1920
  assert tx.spend_bundle is not None
1916
- await send_to_mempool(full_node_api, tx.spend_bundle)
1921
+ await send_to_mempool(full_node_api, wallet_peer, tx.spend_bundle)
1917
1922
  await farm_a_block(full_node_api, wallet_node, ph)
1918
1923
  # Grab the coin we created and make an eligible coin out of it
1919
1924
  coins_with_identity_ph = await full_node_api.full_node.coin_store.get_coin_records_by_puzzle_hash(
@@ -1921,7 +1926,7 @@ async def test_identical_spend_aggregation_e2e(
1921
1926
  )
1922
1927
  coin = coins_with_identity_ph[0].coin
1923
1928
  sb = spend_bundle_from_conditions([[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, coin.amount]], coin)
1924
- await send_to_mempool(full_node_api, sb)
1929
+ await send_to_mempool(full_node_api, wallet_peer, sb)
1925
1930
  await farm_a_block(full_node_api, wallet_node, ph)
1926
1931
  # Grab the eligible coin to spend as E in DE and EF transactions
1927
1932
  e_coin = (await full_node_api.full_node.coin_store.get_coin_records_by_puzzle_hash(False, IDENTITY_PUZZLE_HASH))[
@@ -1964,10 +1969,10 @@ async def test_identical_spend_aggregation_e2e(
1964
1969
  # Send DE and EF combinations to the mempool
1965
1970
  sb_de = SpendBundle.aggregate([tx_d.spend_bundle, sb_e])
1966
1971
  sb_de_name = sb_de.name()
1967
- await send_to_mempool(full_node_api, sb_de)
1972
+ await send_to_mempool(full_node_api, wallet_peer, sb_de)
1968
1973
  sb_ef = SpendBundle.aggregate([sb_e, tx_f.spend_bundle])
1969
1974
  sb_ef_name = sb_ef.name()
1970
- await send_to_mempool(full_node_api, sb_ef)
1975
+ await send_to_mempool(full_node_api, wallet_peer, sb_ef)
1971
1976
  # Send also a transaction EG that spends E differently from DE and EF,
1972
1977
  # to ensure it's rejected by the mempool
1973
1978
  conditions = [
@@ -1987,7 +1992,7 @@ async def test_identical_spend_aggregation_e2e(
1987
1992
  [tx_g] = action_scope.side_effects.transactions
1988
1993
  assert tx_g.spend_bundle is not None
1989
1994
  sb_e2g = SpendBundle.aggregate([sb_e2, tx_g.spend_bundle])
1990
- await send_to_mempool(full_node_api, sb_e2g, expecting_conflict=True)
1995
+ await send_to_mempool(full_node_api, wallet_peer, sb_e2g, expecting_conflict=True)
1991
1996
 
1992
1997
  # Make sure our coin IDs to spend bundles mappings are correct
1993
1998
  assert get_sb_names_by_coin_id(full_node_api, coins[4].coin.name()) == {sb_de_name}
@@ -2212,6 +2217,7 @@ async def test_fill_rate_block_validation(
2212
2217
  max_block_clvm_cost: uint64,
2213
2218
  expected_block_items: int,
2214
2219
  expected_block_cost: uint64,
2220
+ self_hostname: str,
2215
2221
  ) -> None:
2216
2222
  """
2217
2223
  This test covers the case where we set the fill rate to 100% and ensure
@@ -2222,8 +2228,10 @@ async def test_fill_rate_block_validation(
2222
2228
  expecting only one of the two test items to get included in the block.
2223
2229
  """
2224
2230
 
2225
- async def send_to_mempool(full_node: FullNodeSimulator, spend_bundle: SpendBundle) -> None:
2226
- res = await full_node.send_transaction(wallet_protocol.SendTransaction(spend_bundle))
2231
+ async def send_to_mempool(
2232
+ full_node: FullNodeSimulator, dummy_peer: WSChiaConnection, spend_bundle: SpendBundle
2233
+ ) -> None:
2234
+ res = await full_node.send_transaction(wallet_protocol.SendTransaction(spend_bundle), dummy_peer)
2227
2235
  assert res is not None and ProtocolMessageTypes(res.type) == ProtocolMessageTypes.transaction_ack
2228
2236
  res_parsed = wallet_protocol.TransactionAck.from_bytes(res.data)
2229
2237
  assert res_parsed.status == MempoolInclusionStatus.SUCCESS.value
@@ -2242,11 +2250,13 @@ async def test_fill_rate_block_validation(
2242
2250
  coin_records = await full_node_api.full_node.coin_store.get_coin_records_by_puzzle_hash(False, ph)
2243
2251
  coin = next(cr.coin for cr in coin_records if cr.coin.amount == 250_000_000_000)
2244
2252
  coins_and_puzzles.append((coin, puzzle))
2253
+ _, dummy_node_id = await add_dummy_connection(full_node_api.server, self_hostname, 12312)
2254
+ dummy_peer = full_node_api.server.all_connections[dummy_node_id]
2245
2255
  sbs_info = []
2246
2256
  for coin, puzzle in coins_and_puzzles:
2247
2257
  coin_spend = make_spend(coin, puzzle, SerializedProgram.to([]))
2248
2258
  sb = SpendBundle([coin_spend], G2Element())
2249
- await send_to_mempool(full_node_api, sb)
2259
+ await send_to_mempool(full_node_api, dummy_peer, sb)
2250
2260
  sbs_info.append((coin.name(), puzzle, sb.name()))
2251
2261
  return sbs_info
2252
2262
 
@@ -59,6 +59,7 @@ test_constants = ConsensusConstants(
59
59
  POOL_SUB_SLOT_ITERS=uint64(37600000000),
60
60
  HARD_FORK_HEIGHT=uint32(5496000),
61
61
  HARD_FORK2_HEIGHT=uint32(0xFFFFFFFF),
62
+ SOFT_FORK8_HEIGHT=uint32(8655000),
62
63
  PLOT_V1_PHASE_OUT_EPOCH_BITS=uint8(8),
63
64
  PLOT_FILTER_128_HEIGHT=uint32(10542000),
64
65
  PLOT_FILTER_64_HEIGHT=uint32(15592000),
@@ -8,19 +8,19 @@ from chia.consensus.default_constants import update_testnet_overrides
8
8
  def test_testnet11() -> None:
9
9
  overrides: dict[str, Any] = {}
10
10
  update_testnet_overrides("testnet11", overrides)
11
- assert overrides == {"PLOT_SIZE_V2": 28}
11
+ assert overrides == {"PLOT_SIZE_V2": 28, "SOFT_FORK8_HEIGHT": 3680000}
12
12
 
13
13
 
14
14
  def test_min_plot_size() -> None:
15
15
  overrides: dict[str, Any] = {"MIN_PLOT_SIZE": 18}
16
16
  update_testnet_overrides("testnet11", overrides)
17
- assert overrides == {"MIN_PLOT_SIZE_V1": 18, "PLOT_SIZE_V2": 28}
17
+ assert overrides == {"MIN_PLOT_SIZE_V1": 18, "PLOT_SIZE_V2": 28, "SOFT_FORK8_HEIGHT": 3680000}
18
18
 
19
19
 
20
20
  def test_max_plot_size() -> None:
21
21
  overrides: dict[str, Any] = {"MAX_PLOT_SIZE": 32}
22
22
  update_testnet_overrides("testnet11", overrides)
23
- assert overrides == {"MAX_PLOT_SIZE_V1": 32, "PLOT_SIZE_V2": 28}
23
+ assert overrides == {"MAX_PLOT_SIZE_V1": 32, "PLOT_SIZE_V2": 28, "SOFT_FORK8_HEIGHT": 3680000}
24
24
 
25
25
 
26
26
  def test_mainnet() -> None:
@@ -25,7 +25,12 @@ from chiabip158 import PyBIP158
25
25
  from colorlog import getLogger
26
26
 
27
27
  from chia._tests.conftest import ConsensusMode
28
- from chia._tests.connection_utils import connect_and_get_peer, disconnect_all, disconnect_all_and_reconnect
28
+ from chia._tests.connection_utils import (
29
+ add_dummy_connection,
30
+ connect_and_get_peer,
31
+ disconnect_all,
32
+ disconnect_all_and_reconnect,
33
+ )
29
34
  from chia._tests.util.blockchain_mock import BlockchainMock
30
35
  from chia._tests.util.misc import patch_request_handler, wallet_height_at_least
31
36
  from chia._tests.util.setup_nodes import OldSimulatorsAndWallets
@@ -676,7 +681,7 @@ async def test_request_additions_success(simulator_and_wallet: OldSimulatorsAndW
676
681
  ph = await action_scope.get_puzzle_hash(wallet.wallet_state_manager)
677
682
 
678
683
  full_node_api = full_nodes[0]
679
- await wallet_server.start_client(PeerInfo(self_hostname, full_node_api.full_node.server.get_port()), None)
684
+ wallet_peer = await connect_and_get_peer(full_node_api.full_node.server, wallet_server, self_hostname)
680
685
 
681
686
  for _ in range(2):
682
687
  await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
@@ -698,7 +703,7 @@ async def test_request_additions_success(simulator_and_wallet: OldSimulatorsAndW
698
703
  )
699
704
  [tx] = action_scope.side_effects.transactions
700
705
  assert tx.spend_bundle is not None
701
- await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
706
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle), wallet_peer)
702
707
  await full_node_api.wait_transaction_records_entered_mempool([tx])
703
708
  await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
704
709
 
@@ -918,7 +923,9 @@ async def test_dusted_wallet(
918
923
  )
919
924
  [tx] = action_scope.side_effects.transactions
920
925
  assert tx.spend_bundle is not None
921
- await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
926
+ _, dummy_node_id = await add_dummy_connection(full_node_api.server, self_hostname, 12312)
927
+ dummy_peer = full_node_api.server.all_connections[dummy_node_id]
928
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle), dummy_peer)
922
929
  await full_node_api.wait_transaction_records_entered_mempool([tx])
923
930
  await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
924
931
  await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
@@ -985,7 +992,7 @@ async def test_dusted_wallet(
985
992
  )
986
993
  [tx] = action_scope.side_effects.transactions
987
994
  assert tx.spend_bundle is not None
988
- await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
995
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle), dummy_peer)
989
996
 
990
997
  # advance the chain and sync both wallets
991
998
  await full_node_api.wait_transaction_records_entered_mempool([tx])
@@ -1008,7 +1015,7 @@ async def test_dusted_wallet(
1008
1015
  )
1009
1016
  [tx] = action_scope.side_effects.transactions
1010
1017
  assert tx.spend_bundle is not None
1011
- await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1018
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle), dummy_peer)
1012
1019
 
1013
1020
  # advance the chain and sync both wallets
1014
1021
  await full_node_api.wait_transaction_records_entered_mempool([tx])
@@ -1061,7 +1068,7 @@ async def test_dusted_wallet(
1061
1068
  )
1062
1069
  [tx] = action_scope.side_effects.transactions
1063
1070
  assert tx.spend_bundle is not None
1064
- await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1071
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle), dummy_peer)
1065
1072
 
1066
1073
  # advance the chain and sync both wallets
1067
1074
  await full_node_api.wait_transaction_records_entered_mempool([tx])
@@ -1105,7 +1112,7 @@ async def test_dusted_wallet(
1105
1112
  )
1106
1113
  [tx] = action_scope.side_effects.transactions
1107
1114
  assert tx.spend_bundle is not None
1108
- await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1115
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle), dummy_peer)
1109
1116
 
1110
1117
  # advance the chain and sync both wallets
1111
1118
  await full_node_api.wait_transaction_records_entered_mempool([tx])
@@ -1169,7 +1176,7 @@ async def test_dusted_wallet(
1169
1176
  )
1170
1177
  [tx] = action_scope.side_effects.transactions
1171
1178
  assert tx.spend_bundle is not None
1172
- await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1179
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle), dummy_peer)
1173
1180
 
1174
1181
  # advance the chain and sync both wallets
1175
1182
  await full_node_api.wait_transaction_records_entered_mempool([tx])
@@ -1210,7 +1217,7 @@ async def test_dusted_wallet(
1210
1217
  )
1211
1218
  [tx] = action_scope.side_effects.transactions
1212
1219
  assert tx.spend_bundle is not None
1213
- await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1220
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle), dummy_peer)
1214
1221
 
1215
1222
  # advance the chain and sync both wallets
1216
1223
  await full_node_api.wait_transaction_records_entered_mempool([tx])
@@ -1259,7 +1266,7 @@ async def test_dusted_wallet(
1259
1266
  )
1260
1267
  [tx] = action_scope.side_effects.transactions
1261
1268
  assert tx.spend_bundle is not None
1262
- await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1269
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle), dummy_peer)
1263
1270
  await full_node_api.wait_transaction_records_entered_mempool([tx])
1264
1271
  await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1265
1272
  await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
@@ -1278,7 +1285,7 @@ async def test_dusted_wallet(
1278
1285
  )
1279
1286
  [tx] = action_scope.side_effects.transactions
1280
1287
  assert tx.spend_bundle is not None
1281
- await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1288
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle), dummy_peer)
1282
1289
 
1283
1290
  # advance the chain and sync both wallets
1284
1291
  await full_node_api.wait_transaction_records_entered_mempool([tx])
@@ -1313,7 +1320,7 @@ async def test_dusted_wallet(
1313
1320
  )
1314
1321
  [tx] = action_scope.side_effects.transactions
1315
1322
  assert tx.spend_bundle is not None
1316
- await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1323
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle), dummy_peer)
1317
1324
 
1318
1325
  # advance the chain and sync both wallets
1319
1326
  await full_node_api.wait_transaction_records_entered_mempool([tx])
@@ -833,7 +833,7 @@ async def raw_mpu_setup(one_node: OneNode, self_hostname: str, no_capability: bo
833
833
  for coin, hint in new_coins:
834
834
  solution = Program.to([[]])
835
835
  bundle = SpendBundle([CoinSpend(coin, puzzle, solution)], AugSchemeMPL.aggregate([]))
836
- tx_resp = await simulator.send_transaction(wallet_protocol.SendTransaction(bundle))
836
+ tx_resp = await simulator.send_transaction(wallet_protocol.SendTransaction(bundle), peer)
837
837
  assert tx_resp is not None
838
838
 
839
839
  ack = wallet_protocol.TransactionAck.from_bytes(tx_resp.data)
@@ -891,11 +891,13 @@ async def subscribe_puzzle(
891
891
  assert len(response.coin_states) == existing_coin_states
892
892
 
893
893
 
894
- async def spend_coin(simulator: FullNodeSimulator, coin: Coin, solution: Program | None = None) -> bytes32:
894
+ async def spend_coin(
895
+ simulator: FullNodeSimulator, peer: WSChiaConnection, coin: Coin, solution: Program | None = None
896
+ ) -> bytes32:
895
897
  bundle = SpendBundle(
896
898
  [CoinSpend(coin, IDENTITY_PUZZLE, Program.to([]) if solution is None else solution)], AugSchemeMPL.aggregate([])
897
899
  )
898
- tx_resp = await simulator.send_transaction(wallet_protocol.SendTransaction(bundle))
900
+ tx_resp = await simulator.send_transaction(wallet_protocol.SendTransaction(bundle), peer)
899
901
  assert tx_resp is not None
900
902
 
901
903
  ack = wallet_protocol.TransactionAck.from_bytes(tx_resp.data)
@@ -915,7 +917,7 @@ async def test_spent_coin_id_mempool_update(mpu_setup: Mpu) -> None:
915
917
  # Make a coin and spend it
916
918
  coin, _ = await make_coin(simulator.full_node)
917
919
  await subscribe_coin(simulator, coin.name(), peer)
918
- transaction_id = await spend_coin(simulator, coin)
920
+ transaction_id = await spend_coin(simulator, peer, coin)
919
921
 
920
922
  # We should have gotten a mempool update for this transaction
921
923
  await assert_mempool_added(queue, {transaction_id})
@@ -942,7 +944,7 @@ async def test_spent_puzzle_hash_mempool_update(mpu_setup: Mpu) -> None:
942
944
  # Make a coin and spend it
943
945
  coin, _ = await make_coin(simulator.full_node)
944
946
  await subscribe_puzzle(simulator, coin.puzzle_hash, peer)
945
- transaction_id = await spend_coin(simulator, coin)
947
+ transaction_id = await spend_coin(simulator, peer, coin)
946
948
 
947
949
  # We should have gotten a mempool update for this transaction
948
950
  await assert_mempool_added(queue, {transaction_id})
@@ -969,7 +971,7 @@ async def test_spent_hint_mempool_update(mpu_setup: Mpu) -> None:
969
971
  # Make a coin and spend it
970
972
  coin, hint = await make_coin(simulator.full_node)
971
973
  await subscribe_puzzle(simulator, hint, peer)
972
- transaction_id = await spend_coin(simulator, coin)
974
+ transaction_id = await spend_coin(simulator, peer, coin)
973
975
 
974
976
  # We should have gotten a mempool update for this transaction
975
977
  await assert_mempool_added(queue, {transaction_id})
@@ -998,7 +1000,7 @@ async def test_created_coin_id_mempool_update(mpu_setup: Mpu) -> None:
998
1000
  child_coin = Coin(coin.name(), std_hash(b"new puzzle hash"), coin.amount)
999
1001
  await subscribe_coin(simulator, child_coin.name(), peer, existing_coin_states=0)
1000
1002
  transaction_id = await spend_coin(
1001
- simulator, coin, solution=Program.to([[51, child_coin.puzzle_hash, child_coin.amount]])
1003
+ simulator, peer, coin, solution=Program.to([[51, child_coin.puzzle_hash, child_coin.amount]])
1002
1004
  )
1003
1005
 
1004
1006
  # We should have gotten a mempool update for this transaction
@@ -1028,7 +1030,7 @@ async def test_created_puzzle_hash_mempool_update(mpu_setup: Mpu) -> None:
1028
1030
  child_coin = Coin(coin.name(), std_hash(b"new puzzle hash"), coin.amount)
1029
1031
  await subscribe_puzzle(simulator, child_coin.puzzle_hash, peer, existing_coin_states=0)
1030
1032
  transaction_id = await spend_coin(
1031
- simulator, coin, solution=Program.to([[51, child_coin.puzzle_hash, child_coin.amount]])
1033
+ simulator, peer, coin, solution=Program.to([[51, child_coin.puzzle_hash, child_coin.amount]])
1032
1034
  )
1033
1035
 
1034
1036
  # We should have gotten a mempool update for this transaction
@@ -1059,7 +1061,7 @@ async def test_created_hint_mempool_update(mpu_setup: Mpu) -> None:
1059
1061
  hint = std_hash(b"new hint")
1060
1062
  await subscribe_puzzle(simulator, hint, peer, existing_coin_states=0)
1061
1063
  transaction_id = await spend_coin(
1062
- simulator, coin, solution=Program.to([[51, child_coin.puzzle_hash, child_coin.amount, [hint]]])
1064
+ simulator, peer, coin, solution=Program.to([[51, child_coin.puzzle_hash, child_coin.amount, [hint]]])
1063
1065
  )
1064
1066
 
1065
1067
  # We should have gotten a mempool update for this transaction
@@ -1087,7 +1089,7 @@ async def test_missing_capability_coin_id(mpu_setup_no_capability: Mpu) -> None:
1087
1089
  # Make a coin and spend it
1088
1090
  coin, _ = await make_coin(simulator.full_node)
1089
1091
  await subscribe_coin(simulator, coin.name(), peer)
1090
- transaction_id = await spend_coin(simulator, coin)
1092
+ transaction_id = await spend_coin(simulator, peer, coin)
1091
1093
 
1092
1094
  # There is no mempool update for this transaction since the peer doesn't have the capability
1093
1095
  assert queue.empty()
@@ -1112,7 +1114,7 @@ async def test_missing_capability_puzzle_hash(mpu_setup_no_capability: Mpu) -> N
1112
1114
  # Make a coin and spend it
1113
1115
  coin, _ = await make_coin(simulator.full_node)
1114
1116
  await subscribe_puzzle(simulator, coin.puzzle_hash, peer)
1115
- transaction_id = await spend_coin(simulator, coin)
1117
+ transaction_id = await spend_coin(simulator, peer, coin)
1116
1118
 
1117
1119
  # There is no mempool update for this transaction since the peer doesn't have the capability
1118
1120
  assert queue.empty()
@@ -1137,7 +1139,7 @@ async def test_missing_capability_hint(mpu_setup_no_capability: Mpu) -> None:
1137
1139
  # Make a coin and spend it
1138
1140
  coin, hint = await make_coin(simulator.full_node)
1139
1141
  await subscribe_puzzle(simulator, hint, peer)
1140
- transaction_id = await spend_coin(simulator, coin)
1142
+ transaction_id = await spend_coin(simulator, peer, coin)
1141
1143
 
1142
1144
  # There is no mempool update for this transaction since the peer doesn't have the capability
1143
1145
  assert queue.empty()
@@ -19,6 +19,7 @@ from chia.protocols import wallet_protocol
19
19
  from chia.protocols.outbound_message import Message, make_msg
20
20
  from chia.protocols.protocol_message_types import ProtocolMessageTypes
21
21
  from chia.server.api_protocol import Self
22
+ from chia.server.ws_connection import WSChiaConnection
22
23
  from chia.simulator.add_blocks_in_batches import add_blocks_in_batches
23
24
  from chia.simulator.block_tools import test_constants
24
25
  from chia.types.blockchain_format.coin import Coin
@@ -624,7 +625,7 @@ async def test_transaction_send_cache(
624
625
  logged_spends = []
625
626
 
626
627
  async def send_transaction(
627
- self: Self, request: wallet_protocol.SendTransaction, *, test: bool = False
628
+ self: Self, request: wallet_protocol.SendTransaction, peer: WSChiaConnection, *, test: bool = False
628
629
  ) -> Message | None:
629
630
  logged_spends.append(request.transaction.name())
630
631
  return None
@@ -285,8 +285,10 @@ class FullNodeApiStub(ApiProtocol, Protocol):
285
285
  """Handle removals request from wallet."""
286
286
  ...
287
287
 
288
- @metadata.request()
289
- async def send_transaction(self, request: wallet_protocol.SendTransaction, *, test: bool = False) -> Message | None:
288
+ @metadata.request(peer_required=True)
289
+ async def send_transaction(
290
+ self, request: wallet_protocol.SendTransaction, peer: WSChiaConnection, *, test: bool = False
291
+ ) -> Message | None:
290
292
  """Handle transaction send from wallet."""
291
293
  ...
292
294
 
@@ -510,7 +510,7 @@ def validate_unfinished_header_block(
510
510
  blocks=blocks,
511
511
  prev_b_hash=header_block.prev_header_hash,
512
512
  sp_index=header_block.reward_chain_block.signage_point_index,
513
- first_in_sub_slot=len(header_block.finished_sub_slots) > 0,
513
+ finished_sub_slots=len(header_block.finished_sub_slots),
514
514
  ),
515
515
  )
516
516
  if required_iters is None:
@@ -279,7 +279,7 @@ class Blockchain:
279
279
  blocks=self,
280
280
  prev_b_hash=block.prev_header_hash,
281
281
  sp_index=block.reward_chain_block.signage_point_index,
282
- first_in_sub_slot=len(block.finished_sub_slots) > 0,
282
+ finished_sub_slots=len(block.finished_sub_slots),
283
283
  )
284
284
  flags = get_flags_for_height_and_constants(prev_tx_height, self.constants)
285
285
  additions, removals = additions_and_removals(
@@ -715,7 +715,7 @@ class Blockchain:
715
715
  blocks=self,
716
716
  prev_b_hash=block.prev_header_hash,
717
717
  sp_index=block.reward_chain_block.signage_point_index,
718
- first_in_sub_slot=len(block.finished_sub_slots) > 0,
718
+ finished_sub_slots=len(block.finished_sub_slots),
719
719
  )
720
720
 
721
721
  # With hard fork 2 we ban transactions_generator_ref_list.
@@ -81,6 +81,7 @@ DEFAULT_CONSTANTS = ConsensusConstants(
81
81
  HARD_FORK_HEIGHT=uint32(5496000),
82
82
  # TODO: todo_v2_plots finalize fork height
83
83
  HARD_FORK2_HEIGHT=uint32(0xFFFFFFFA),
84
+ SOFT_FORK8_HEIGHT=uint32(8655000),
84
85
  # starting at the hard fork 2 height, v1 plots will gradually be phased out,
85
86
  # and stop working entirely after (1 << this) many epochs
86
87
  PLOT_V1_PHASE_OUT_EPOCH_BITS=uint8(8),
@@ -111,6 +112,8 @@ def update_testnet_overrides(network_id: str, overrides: dict[str, Any]) -> None
111
112
  if network_id in {"testnet11", "testneta"}:
112
113
  if "PLOT_SIZE_V2" not in overrides:
113
114
  overrides["PLOT_SIZE_V2"] = 28
115
+ if "SOFT_FORK8_HEIGHT" not in overrides:
116
+ overrides["SOFT_FORK8_HEIGHT"] = 3680000
114
117
  if network_id == "testneta":
115
118
  if "HARD_FORK_HEIGHT" not in overrides:
116
119
  overrides["HARD_FORK_HEIGHT"] = 3693395
@@ -7,6 +7,7 @@ from chia_rs.sized_bytes import bytes32
7
7
  from chia_rs.sized_ints import uint8, uint32, uint64
8
8
 
9
9
  from chia.consensus.blockchain_interface import BlockRecordsProtocol
10
+ from chia.consensus.pot_iterations import is_overflow_block
10
11
  from chia.types.unfinished_header_block import UnfinishedHeaderBlock
11
12
 
12
13
  log = logging.getLogger(__name__)
@@ -110,17 +111,24 @@ def pre_sp_tx_block(
110
111
  *,
111
112
  prev_b_hash: bytes32,
112
113
  sp_index: uint8,
113
- first_in_sub_slot: bool,
114
+ finished_sub_slots: int,
114
115
  ) -> BlockRecord | None:
115
116
  if prev_b_hash == constants.GENESIS_CHALLENGE:
116
117
  return None
117
118
  curr = blocks.block_record(prev_b_hash)
118
- before_slot = first_in_sub_slot
119
+ # For overflow blocks, the SP is in the previous sub-slot, so we need to cross
120
+ # one extra slot boundary before we're past the SP's slot
121
+ overflow = is_overflow_block(constants, sp_index)
122
+ slots_crossed = finished_sub_slots
119
123
  while curr.height > 0:
120
- if curr.is_transaction_block and (before_slot or curr.signage_point_index < sp_index):
124
+ if not overflow:
125
+ before_sp = curr.signage_point_index < sp_index or slots_crossed > 0
126
+ else:
127
+ before_sp = slots_crossed >= 2 or (slots_crossed == 1 and curr.signage_point_index < sp_index)
128
+ if curr.is_transaction_block and before_sp:
121
129
  break
122
130
  if curr.first_in_sub_slot:
123
- before_slot = True
131
+ slots_crossed += 1
124
132
  curr = blocks.block_record(curr.prev_hash)
125
133
  return curr
126
134
 
@@ -131,14 +139,14 @@ def pre_sp_tx_block_height(
131
139
  *,
132
140
  prev_b_hash: bytes32,
133
141
  sp_index: uint8,
134
- first_in_sub_slot: bool,
142
+ finished_sub_slots: int,
135
143
  ) -> uint32:
136
144
  latest_tx_block = pre_sp_tx_block(
137
145
  constants=constants,
138
146
  blocks=blocks,
139
147
  prev_b_hash=prev_b_hash,
140
148
  sp_index=sp_index,
141
- first_in_sub_slot=first_in_sub_slot,
149
+ finished_sub_slots=finished_sub_slots,
142
150
  )
143
151
  if latest_tx_block is None:
144
152
  return uint32(0)
@@ -120,7 +120,7 @@ def _pre_validate_block(
120
120
  blocks=blockchain,
121
121
  prev_b_hash=block.prev_header_hash,
122
122
  sp_index=block.reward_chain_block.signage_point_index,
123
- first_in_sub_slot=len(block.finished_sub_slots) > 0,
123
+ finished_sub_slots=len(block.finished_sub_slots),
124
124
  )
125
125
  err, conds = _run_block(block, prev_generators, prev_tx_height, constants)
126
126
 
@@ -231,7 +231,7 @@ async def pre_validate_block(
231
231
  blocks=blockchain,
232
232
  prev_b_hash=block.prev_header_hash,
233
233
  sp_index=block.reward_chain_block.signage_point_index,
234
- first_in_sub_slot=len(block.finished_sub_slots) > 0,
234
+ finished_sub_slots=len(block.finished_sub_slots),
235
235
  ),
236
236
  )
237
237
  if required_iters is None:
@@ -286,7 +286,9 @@ class FullNode:
286
286
  single_threaded=single_threaded,
287
287
  ) as self._mempool_manager:
288
288
  # Transactions go into this queue from the server, and get sent to respond_transaction
289
- self._transaction_queue = TransactionQueue(1000, self.log)
289
+ self._transaction_queue = TransactionQueue(
290
+ 1000, self.log, max_tx_clvm_cost=uint64(self.constants.MAX_BLOCK_COST_CLVM // 2)
291
+ )
290
292
  self._transaction_queue_task: asyncio.Task[None] = create_referenced_task(self._handle_transactions())
291
293
 
292
294
  self._init_weight_proof = create_referenced_task(self.initialize_weight_proof())
@@ -38,13 +38,13 @@ from chiabip158 import PyBIP158
38
38
  from chia.consensus.block_creation import create_unfinished_block
39
39
  from chia.consensus.blockchain import BlockchainMutexPriority
40
40
  from chia.consensus.generator_tools import get_block_header
41
- from chia.consensus.get_block_challenge import pre_sp_tx_block_height
42
41
  from chia.consensus.get_block_generator import get_block_generator
43
42
  from chia.consensus.pot_iterations import calculate_ip_iters, calculate_iterations_quality, calculate_sp_iters
44
43
  from chia.consensus.signage_point import SignagePoint
45
44
  from chia.full_node.coin_store import CoinStore
46
45
  from chia.full_node.fee_estimator_interface import FeeEstimatorInterface
47
46
  from chia.full_node.full_block_utils import get_height_and_tx_status_from_block, header_block_from_block
47
+ from chia.full_node.hard_fork_utils import get_flags
48
48
  from chia.full_node.tx_processing_queue import PeerWithTx, TransactionQueueEntry, TransactionQueueFull
49
49
  from chia.protocols import farmer_protocol, full_node_protocol, introducer_protocol, timelord_protocol, wallet_protocol
50
50
  from chia.protocols.fee_estimate import FeeEstimate, FeeEstimateGroup, fee_rate_v2_to_v1
@@ -1270,15 +1270,7 @@ class FullNodeAPI:
1270
1270
  # in this case we've already made sure `block` does have a
1271
1271
  # transactions_generator, so the block_generator should always be set
1272
1272
  assert block_generator is not None, "failed to get block_generator for tx-block"
1273
-
1274
- prev_tx_height = pre_sp_tx_block_height(
1275
- constants=self.full_node.constants,
1276
- blocks=self.full_node.blockchain,
1277
- prev_b_hash=block.prev_header_hash,
1278
- sp_index=block.reward_chain_block.signage_point_index,
1279
- first_in_sub_slot=len(block.finished_sub_slots) > 0,
1280
- )
1281
- flags = get_flags_for_height_and_constants(prev_tx_height, self.full_node.constants)
1273
+ flags = await get_flags(constants=self.full_node.constants, blocks=self.full_node.blockchain, block=block)
1282
1274
  additions, removals = await asyncio.get_running_loop().run_in_executor(
1283
1275
  self.executor,
1284
1276
  additions_and_removals,
@@ -1424,16 +1416,26 @@ class FullNodeAPI:
1424
1416
  msg = make_msg(ProtocolMessageTypes.respond_removals, response)
1425
1417
  return msg
1426
1418
 
1427
- @metadata.request()
1428
- async def send_transaction(self, request: wallet_protocol.SendTransaction, *, test: bool = False) -> Message | None:
1419
+ @metadata.request(peer_required=True)
1420
+ async def send_transaction(
1421
+ self, request: wallet_protocol.SendTransaction, peer: WSChiaConnection, *, test: bool = False
1422
+ ) -> Message | None:
1429
1423
  spend_name = request.transaction.name()
1430
1424
  if self.full_node.mempool_manager.get_spendbundle(spend_name) is not None:
1431
1425
  self.full_node.mempool_manager.remove_seen(spend_name)
1432
1426
  response = wallet_protocol.TransactionAck(spend_name, uint8(MempoolInclusionStatus.SUCCESS), None)
1433
1427
  return make_msg(ProtocolMessageTypes.transaction_ack, response)
1434
-
1428
+ high_priority = self.is_trusted(peer)
1435
1429
  queue_entry = TransactionQueueEntry(request.transaction, None, spend_name, None, test)
1436
- self.full_node.transaction_queue.put(queue_entry, peer_id=None, high_priority=True)
1430
+ try:
1431
+ self.full_node.transaction_queue.put(queue_entry, peer_id=peer.peer_node_id, high_priority=high_priority)
1432
+ except TransactionQueueFull:
1433
+ return make_msg(
1434
+ ProtocolMessageTypes.transaction_ack,
1435
+ wallet_protocol.TransactionAck(
1436
+ spend_name, uint8(MempoolInclusionStatus.FAILED), "Transaction queue full"
1437
+ ),
1438
+ )
1437
1439
  try:
1438
1440
  with anyio.fail_after(delay=45):
1439
1441
  status, error = await queue_entry.done.wait()