chia-blockchain 2.5.1rc3__py3-none-any.whl → 2.5.2rc1__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.
- chia/_tests/core/mempool/test_mempool_fee_estimator.py +3 -1
- chia/_tests/core/mempool/test_mempool_manager.py +14 -5
- chia/_tests/core/mempool/test_singleton_fast_forward.py +181 -5
- chia/_tests/util/spend_sim.py +3 -1
- chia/full_node/full_node.py +1 -0
- chia/full_node/mempool.py +3 -3
- chia/full_node/mempool_manager.py +22 -5
- chia/types/eligible_coin_spends.py +30 -26
- chia/types/internal_mempool_item.py +1 -1
- {chia_blockchain-2.5.1rc3.dist-info → chia_blockchain-2.5.2rc1.dist-info}/METADATA +1 -1
- {chia_blockchain-2.5.1rc3.dist-info → chia_blockchain-2.5.2rc1.dist-info}/RECORD +14 -14
- {chia_blockchain-2.5.1rc3.dist-info → chia_blockchain-2.5.2rc1.dist-info}/WHEEL +1 -1
- {chia_blockchain-2.5.1rc3.dist-info → chia_blockchain-2.5.2rc1.dist-info}/LICENSE +0 -0
- {chia_blockchain-2.5.1rc3.dist-info → chia_blockchain-2.5.2rc1.dist-info}/entry_points.txt +0 -0
|
@@ -63,7 +63,9 @@ async def test_basics() -> None:
|
|
|
63
63
|
async def test_fee_increase() -> None:
|
|
64
64
|
async with DBConnection(db_version=2) as db_wrapper:
|
|
65
65
|
coin_store = await CoinStore.create(db_wrapper)
|
|
66
|
-
mempool_manager = MempoolManager(
|
|
66
|
+
mempool_manager = MempoolManager(
|
|
67
|
+
coin_store.get_coin_records, coin_store.get_unspent_lineage_info_for_puzzle_hash, test_constants
|
|
68
|
+
)
|
|
67
69
|
assert test_constants.MAX_BLOCK_COST_CLVM == mempool_manager.constants.MAX_BLOCK_COST_CLVM
|
|
68
70
|
btc_fee_estimator: BitcoinFeeEstimator = mempool_manager.mempool.fee_estimator # type: ignore
|
|
69
71
|
fee_tracker = btc_fee_estimator.get_tracker()
|
|
@@ -103,6 +103,10 @@ async def zero_calls_get_coin_records(coin_ids: Collection[bytes32]) -> list[Coi
|
|
|
103
103
|
return []
|
|
104
104
|
|
|
105
105
|
|
|
106
|
+
async def zero_calls_get_unspent_lineage_info_for_puzzle_hash(_puzzle_hash: bytes32) -> Optional[UnspentLineageInfo]:
|
|
107
|
+
assert False # pragma no cover
|
|
108
|
+
|
|
109
|
+
|
|
106
110
|
async def get_coin_records_for_test_coins(coin_ids: Collection[bytes32]) -> list[CoinRecord]:
|
|
107
111
|
test_coin_records = {
|
|
108
112
|
TEST_COIN_ID: TEST_COIN_RECORD,
|
|
@@ -140,7 +144,12 @@ async def instantiate_mempool_manager(
|
|
|
140
144
|
constants: ConsensusConstants = DEFAULT_CONSTANTS,
|
|
141
145
|
max_tx_clvm_cost: Optional[uint64] = None,
|
|
142
146
|
) -> MempoolManager:
|
|
143
|
-
mempool_manager = MempoolManager(
|
|
147
|
+
mempool_manager = MempoolManager(
|
|
148
|
+
get_coin_records,
|
|
149
|
+
zero_calls_get_unspent_lineage_info_for_puzzle_hash,
|
|
150
|
+
constants,
|
|
151
|
+
max_tx_clvm_cost=max_tx_clvm_cost,
|
|
152
|
+
)
|
|
144
153
|
test_block_record = create_test_block_record(height=block_height, timestamp=block_timestamp)
|
|
145
154
|
await mempool_manager.new_peak(test_block_record, None)
|
|
146
155
|
invariant_check_mempool(mempool_manager.mempool)
|
|
@@ -427,18 +436,18 @@ def make_bundle_spends_map_and_fee(
|
|
|
427
436
|
eligibility_and_additions[coin_id] = EligibilityAndAdditions(
|
|
428
437
|
is_eligible_for_dedup=bool(spend.flags & ELIGIBLE_FOR_DEDUP),
|
|
429
438
|
spend_additions=spend_additions,
|
|
430
|
-
|
|
439
|
+
ff_puzzle_hash=bytes32(spend.puzzle_hash) if bool(spend.flags & ELIGIBLE_FOR_FF) else None,
|
|
431
440
|
)
|
|
432
441
|
for coin_spend in spend_bundle.coin_spends:
|
|
433
442
|
coin_id = coin_spend.coin.name()
|
|
434
443
|
removals_amount += coin_spend.coin.amount
|
|
435
444
|
eligibility_info = eligibility_and_additions.get(
|
|
436
|
-
coin_id, EligibilityAndAdditions(is_eligible_for_dedup=False, spend_additions=[],
|
|
445
|
+
coin_id, EligibilityAndAdditions(is_eligible_for_dedup=False, spend_additions=[], ff_puzzle_hash=None)
|
|
437
446
|
)
|
|
438
447
|
bundle_coin_spends[coin_id] = BundleCoinSpend(
|
|
439
448
|
coin_spend=coin_spend,
|
|
440
449
|
eligible_for_dedup=eligibility_info.is_eligible_for_dedup,
|
|
441
|
-
eligible_for_fast_forward=eligibility_info.
|
|
450
|
+
eligible_for_fast_forward=eligibility_info.ff_puzzle_hash is not None,
|
|
442
451
|
additions=eligibility_info.spend_additions,
|
|
443
452
|
)
|
|
444
453
|
fee = uint64(removals_amount - additions_amount)
|
|
@@ -1137,7 +1146,7 @@ async def test_create_bundle_from_mempool_on_max_cost(num_skipped_items: int, ca
|
|
|
1137
1146
|
skipped_due_to_eligible_coins = sum(
|
|
1138
1147
|
1
|
|
1139
1148
|
for line in caplog.text.split("\n")
|
|
1140
|
-
if "
|
|
1149
|
+
if "Exception while checking a mempool item for deduplication: Skipping transaction with eligible coin(s)"
|
|
1141
1150
|
in line
|
|
1142
1151
|
)
|
|
1143
1152
|
if num_skipped_items == PRIORITY_TX_THRESHOLD:
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import copy
|
|
3
4
|
import dataclasses
|
|
4
5
|
from typing import Any, Optional
|
|
5
6
|
|
|
6
7
|
import pytest
|
|
7
8
|
from chia_rs import AugSchemeMPL, G1Element, G2Element, PrivateKey
|
|
9
|
+
from chiabip158 import PyBIP158
|
|
8
10
|
|
|
9
11
|
from chia._tests.clvm.test_puzzles import public_key_for_index, secret_exponent_for_index
|
|
10
12
|
from chia._tests.core.mempool.test_mempool_manager import (
|
|
@@ -57,14 +59,14 @@ async def test_process_fast_forward_spends_nothing_to_do() -> None:
|
|
|
57
59
|
internal_mempool_item = InternalMempoolItem(sb, item.conds, item.height_added_to_mempool, item.bundle_coin_spends)
|
|
58
60
|
original_version = dataclasses.replace(internal_mempool_item)
|
|
59
61
|
eligible_coin_spends = EligibleCoinSpends()
|
|
60
|
-
await eligible_coin_spends.process_fast_forward_spends(
|
|
62
|
+
bundle_coin_spends = await eligible_coin_spends.process_fast_forward_spends(
|
|
61
63
|
mempool_item=internal_mempool_item,
|
|
62
64
|
get_unspent_lineage_info_for_puzzle_hash=get_unspent_lineage_info_for_puzzle_hash,
|
|
63
65
|
height=TEST_HEIGHT,
|
|
64
66
|
constants=DEFAULT_CONSTANTS,
|
|
65
67
|
)
|
|
66
68
|
assert eligible_coin_spends == EligibleCoinSpends()
|
|
67
|
-
assert
|
|
69
|
+
assert bundle_coin_spends == original_version.bundle_coin_spends
|
|
68
70
|
|
|
69
71
|
|
|
70
72
|
@pytest.mark.anyio
|
|
@@ -130,7 +132,7 @@ async def test_process_fast_forward_spends_latest_unspent() -> None:
|
|
|
130
132
|
internal_mempool_item = InternalMempoolItem(sb, item.conds, item.height_added_to_mempool, item.bundle_coin_spends)
|
|
131
133
|
original_version = dataclasses.replace(internal_mempool_item)
|
|
132
134
|
eligible_coin_spends = EligibleCoinSpends()
|
|
133
|
-
await eligible_coin_spends.process_fast_forward_spends(
|
|
135
|
+
bundle_coin_spends = await eligible_coin_spends.process_fast_forward_spends(
|
|
134
136
|
mempool_item=internal_mempool_item,
|
|
135
137
|
get_unspent_lineage_info_for_puzzle_hash=get_unspent_lineage_info_for_puzzle_hash,
|
|
136
138
|
height=TEST_HEIGHT,
|
|
@@ -149,7 +151,7 @@ async def test_process_fast_forward_spends_latest_unspent() -> None:
|
|
|
149
151
|
# We have set the next version from our additions to chain ff spends
|
|
150
152
|
assert eligible_coin_spends.fast_forward_spends == expected_fast_forward_spends
|
|
151
153
|
# We didn't need to fast forward the item so it stays as is
|
|
152
|
-
assert
|
|
154
|
+
assert bundle_coin_spends == original_version.bundle_coin_spends
|
|
153
155
|
|
|
154
156
|
|
|
155
157
|
def test_perform_the_fast_forward() -> None:
|
|
@@ -381,6 +383,47 @@ async def prepare_and_test_singleton(
|
|
|
381
383
|
return singleton, eve_coin_spend, inner_puzzle, remaining_coin
|
|
382
384
|
|
|
383
385
|
|
|
386
|
+
@pytest.mark.anyio
|
|
387
|
+
async def test_singleton_fast_forward_solo() -> None:
|
|
388
|
+
"""
|
|
389
|
+
We don't allow a spend bundle with *only* fast forward spends, since those
|
|
390
|
+
are difficult to evict from the mempool. They would always be valid as long as
|
|
391
|
+
the singleton exists.
|
|
392
|
+
"""
|
|
393
|
+
SINGLETON_AMOUNT = uint64(1337)
|
|
394
|
+
async with sim_and_client() as (sim, sim_client):
|
|
395
|
+
singleton, eve_coin_spend, inner_puzzle, _ = await prepare_and_test_singleton(
|
|
396
|
+
sim, sim_client, True, SINGLETON_AMOUNT, SINGLETON_AMOUNT
|
|
397
|
+
)
|
|
398
|
+
singleton_puzzle_hash = eve_coin_spend.coin.puzzle_hash
|
|
399
|
+
inner_puzzle_hash = inner_puzzle.get_tree_hash()
|
|
400
|
+
inner_conditions: list[list[Any]] = [
|
|
401
|
+
[ConditionOpcode.CREATE_COIN, inner_puzzle_hash, SINGLETON_AMOUNT],
|
|
402
|
+
]
|
|
403
|
+
singleton_coin_spend, _ = make_singleton_coin_spend(eve_coin_spend, singleton, inner_puzzle, inner_conditions)
|
|
404
|
+
# spending the eve coin is not eligible for fast forward, so we need to make this spend first, to test FF
|
|
405
|
+
await make_and_send_spend_bundle(sim, sim_client, [singleton_coin_spend], aggsig=G2Element())
|
|
406
|
+
unspent_lineage_info = await sim_client.service.coin_store.get_unspent_lineage_info_for_puzzle_hash(
|
|
407
|
+
singleton_puzzle_hash
|
|
408
|
+
)
|
|
409
|
+
singleton_child, _ = await get_singleton_and_remaining_coins(sim)
|
|
410
|
+
assert singleton_child.amount == SINGLETON_AMOUNT
|
|
411
|
+
assert unspent_lineage_info == UnspentLineageInfo(
|
|
412
|
+
coin_id=singleton_child.name(),
|
|
413
|
+
coin_amount=singleton_child.amount,
|
|
414
|
+
parent_id=eve_coin_spend.coin.name(),
|
|
415
|
+
parent_amount=singleton.amount,
|
|
416
|
+
parent_parent_id=eve_coin_spend.coin.parent_coin_info,
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
inner_conditions = [[ConditionOpcode.CREATE_COIN, inner_puzzle_hash, 21]]
|
|
420
|
+
# this is a FF spend that isn't combined with any other spend. It's not allowed
|
|
421
|
+
singleton_coin_spend, _ = make_singleton_coin_spend(eve_coin_spend, singleton, inner_puzzle, inner_conditions)
|
|
422
|
+
status, error = await sim_client.push_tx(SpendBundle([singleton_coin_spend], G2Element()))
|
|
423
|
+
assert error is Err.INVALID_SPEND_BUNDLE
|
|
424
|
+
assert status == MempoolInclusionStatus.FAILED
|
|
425
|
+
|
|
426
|
+
|
|
384
427
|
@pytest.mark.anyio
|
|
385
428
|
@pytest.mark.parametrize("is_eligible_for_ff", [True, False])
|
|
386
429
|
async def test_singleton_fast_forward_different_block(is_eligible_for_ff: bool) -> None:
|
|
@@ -544,7 +587,8 @@ async def test_singleton_fast_forward_same_block() -> None:
|
|
|
544
587
|
singleton_coin_spend, _ = make_singleton_coin_spend(
|
|
545
588
|
eve_coin_spend, singleton, inner_puzzle, inner_conditions
|
|
546
589
|
)
|
|
547
|
-
|
|
590
|
+
remaining_coin_spend = CoinSpend(remaining_coin, IDENTITY_PUZZLE, remaining_spend_solution)
|
|
591
|
+
status, error = await sim_client.push_tx(SpendBundle([singleton_coin_spend, remaining_coin_spend], aggsig))
|
|
548
592
|
assert error is None
|
|
549
593
|
assert status == MempoolInclusionStatus.SUCCESS
|
|
550
594
|
|
|
@@ -565,3 +609,135 @@ async def test_singleton_fast_forward_same_block() -> None:
|
|
|
565
609
|
assert unspent_lineage_info.parent_id == latest_singleton.parent_coin_info
|
|
566
610
|
# The one before it should have the second last random amount
|
|
567
611
|
assert unspent_lineage_info.parent_amount == random_amounts[-2]
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
@pytest.mark.anyio
|
|
615
|
+
async def test_mempool_items_immutability_on_ff() -> None:
|
|
616
|
+
"""
|
|
617
|
+
This tests processing singleton fast forward spends for mempool items using
|
|
618
|
+
modified copies, without altering those original mempool items.
|
|
619
|
+
"""
|
|
620
|
+
SINGLETON_AMOUNT = uint64(1337)
|
|
621
|
+
async with sim_and_client() as (sim, sim_client):
|
|
622
|
+
singleton, eve_coin_spend, inner_puzzle, remaining_coin = await prepare_and_test_singleton(
|
|
623
|
+
sim, sim_client, True, SINGLETON_AMOUNT, SINGLETON_AMOUNT
|
|
624
|
+
)
|
|
625
|
+
singleton_name = singleton.name()
|
|
626
|
+
singleton_puzzle_hash = eve_coin_spend.coin.puzzle_hash
|
|
627
|
+
inner_puzzle_hash = inner_puzzle.get_tree_hash()
|
|
628
|
+
sk = AugSchemeMPL.key_gen(b"1" * 32)
|
|
629
|
+
g1 = sk.get_g1()
|
|
630
|
+
sig = AugSchemeMPL.sign(sk, b"foobar", g1)
|
|
631
|
+
inner_conditions: list[list[Any]] = [
|
|
632
|
+
[ConditionOpcode.AGG_SIG_UNSAFE, bytes(g1), b"foobar"],
|
|
633
|
+
[ConditionOpcode.CREATE_COIN, inner_puzzle_hash, SINGLETON_AMOUNT],
|
|
634
|
+
]
|
|
635
|
+
singleton_coin_spend, singleton_signing_puzzle = make_singleton_coin_spend(
|
|
636
|
+
eve_coin_spend, singleton, inner_puzzle, inner_conditions
|
|
637
|
+
)
|
|
638
|
+
remaining_spend_solution = SerializedProgram.from_program(
|
|
639
|
+
Program.to([[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, remaining_coin.amount]])
|
|
640
|
+
)
|
|
641
|
+
remaining_coin_spend = CoinSpend(remaining_coin, IDENTITY_PUZZLE, remaining_spend_solution)
|
|
642
|
+
await make_and_send_spend_bundle(
|
|
643
|
+
sim,
|
|
644
|
+
sim_client,
|
|
645
|
+
[remaining_coin_spend, singleton_coin_spend],
|
|
646
|
+
signing_puzzle=singleton_signing_puzzle,
|
|
647
|
+
signing_coin=singleton,
|
|
648
|
+
aggsig=sig,
|
|
649
|
+
)
|
|
650
|
+
unspent_lineage_info = await sim_client.service.coin_store.get_unspent_lineage_info_for_puzzle_hash(
|
|
651
|
+
singleton_puzzle_hash
|
|
652
|
+
)
|
|
653
|
+
singleton_child, [remaining_coin] = await get_singleton_and_remaining_coins(sim)
|
|
654
|
+
singleton_child_name = singleton_child.name()
|
|
655
|
+
assert singleton_child.amount == SINGLETON_AMOUNT
|
|
656
|
+
assert unspent_lineage_info == UnspentLineageInfo(
|
|
657
|
+
coin_id=singleton_child_name,
|
|
658
|
+
coin_amount=singleton_child.amount,
|
|
659
|
+
parent_id=singleton_name,
|
|
660
|
+
parent_amount=singleton.amount,
|
|
661
|
+
parent_parent_id=eve_coin_spend.coin.name(),
|
|
662
|
+
)
|
|
663
|
+
# Now let's spend the first version again (despite being already spent
|
|
664
|
+
# by now) to exercise its fast forward.
|
|
665
|
+
remaining_spend_solution = SerializedProgram.from_program(
|
|
666
|
+
Program.to([[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, remaining_coin.amount]])
|
|
667
|
+
)
|
|
668
|
+
remaining_coin_spend = CoinSpend(remaining_coin, IDENTITY_PUZZLE, remaining_spend_solution)
|
|
669
|
+
sb = SpendBundle([remaining_coin_spend, singleton_coin_spend], sig)
|
|
670
|
+
sb_name = sb.name()
|
|
671
|
+
status, error = await sim_client.push_tx(sb)
|
|
672
|
+
assert status == MempoolInclusionStatus.SUCCESS
|
|
673
|
+
assert error is None
|
|
674
|
+
original_item = copy.copy(sim_client.service.mempool_manager.get_mempool_item(sb_name))
|
|
675
|
+
original_filter = sim_client.service.mempool_manager.get_filter()
|
|
676
|
+
# Let's trigger the fast forward by creating a mempool bundle
|
|
677
|
+
result = await sim.mempool_manager.create_bundle_from_mempool(
|
|
678
|
+
sim_client.service.block_records[-1].header_hash,
|
|
679
|
+
sim_client.service.coin_store.get_unspent_lineage_info_for_puzzle_hash,
|
|
680
|
+
)
|
|
681
|
+
assert result is not None
|
|
682
|
+
bundle, _ = result
|
|
683
|
+
# Make sure the mempool bundle we created contains the result of our
|
|
684
|
+
# fast forward, instead of our original spend.
|
|
685
|
+
assert any(cs.coin.name() == singleton_child_name for cs in bundle.coin_spends)
|
|
686
|
+
assert not any(cs.coin.name() == singleton_name for cs in bundle.coin_spends)
|
|
687
|
+
# We should have processed our item without modifying it in-place
|
|
688
|
+
new_item = copy.copy(sim_client.service.mempool_manager.get_mempool_item(sb_name))
|
|
689
|
+
new_filter = sim_client.service.mempool_manager.get_filter()
|
|
690
|
+
assert new_item == original_item
|
|
691
|
+
assert new_filter == original_filter
|
|
692
|
+
sb_filter = PyBIP158(bytearray(original_filter))
|
|
693
|
+
items_not_in_sb_filter = sim_client.service.mempool_manager.get_items_not_in_filter(sb_filter)
|
|
694
|
+
assert len(items_not_in_sb_filter) == 0
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
@pytest.mark.anyio
|
|
698
|
+
async def test_double_spend_ff_spend_no_latest_unspent() -> None:
|
|
699
|
+
"""
|
|
700
|
+
This test covers the scenario where we receive a spend bundle with a
|
|
701
|
+
singleton fast forward spend that has currently no unspent coin.
|
|
702
|
+
"""
|
|
703
|
+
test_amount = uint64(1337)
|
|
704
|
+
async with sim_and_client() as (sim, sim_client):
|
|
705
|
+
# Prepare a singleton spend
|
|
706
|
+
singleton, eve_coin_spend, inner_puzzle, _ = await prepare_and_test_singleton(
|
|
707
|
+
sim, sim_client, True, start_amount=test_amount, singleton_amount=test_amount
|
|
708
|
+
)
|
|
709
|
+
singleton_name = singleton.name()
|
|
710
|
+
singleton_puzzle_hash = eve_coin_spend.coin.puzzle_hash
|
|
711
|
+
inner_puzzle_hash = inner_puzzle.get_tree_hash()
|
|
712
|
+
sk = AugSchemeMPL.key_gen(b"9" * 32)
|
|
713
|
+
g1 = sk.get_g1()
|
|
714
|
+
sig = AugSchemeMPL.sign(sk, b"foobar", g1)
|
|
715
|
+
inner_conditions: list[list[Any]] = [
|
|
716
|
+
[ConditionOpcode.AGG_SIG_UNSAFE, bytes(g1), b"foobar"],
|
|
717
|
+
[ConditionOpcode.CREATE_COIN, inner_puzzle_hash, test_amount],
|
|
718
|
+
]
|
|
719
|
+
singleton_coin_spend, _ = make_singleton_coin_spend(eve_coin_spend, singleton, inner_puzzle, inner_conditions)
|
|
720
|
+
# Get its current latest unspent info
|
|
721
|
+
unspent_lineage_info = await sim_client.service.coin_store.get_unspent_lineage_info_for_puzzle_hash(
|
|
722
|
+
singleton_puzzle_hash
|
|
723
|
+
)
|
|
724
|
+
assert unspent_lineage_info == UnspentLineageInfo(
|
|
725
|
+
coin_id=singleton_name,
|
|
726
|
+
coin_amount=test_amount,
|
|
727
|
+
parent_id=eve_coin_spend.coin.name(),
|
|
728
|
+
parent_amount=eve_coin_spend.coin.amount,
|
|
729
|
+
parent_parent_id=eve_coin_spend.coin.parent_coin_info,
|
|
730
|
+
)
|
|
731
|
+
# Let's remove this latest unspent coin from the coin store
|
|
732
|
+
async with sim_client.service.coin_store.db_wrapper.writer_maybe_transaction() as conn:
|
|
733
|
+
await conn.execute("DELETE FROM coin_record WHERE coin_name = ?", (unspent_lineage_info.coin_id,))
|
|
734
|
+
# This singleton no longer has a latest unspent coin
|
|
735
|
+
unspent_lineage_info = await sim_client.service.coin_store.get_unspent_lineage_info_for_puzzle_hash(
|
|
736
|
+
singleton_puzzle_hash
|
|
737
|
+
)
|
|
738
|
+
assert unspent_lineage_info is None
|
|
739
|
+
# Let's attempt to spend this singleton and get get it fast forwarded
|
|
740
|
+
status, error = await make_and_send_spend_bundle(sim, sim_client, [singleton_coin_spend], aggsig=sig)
|
|
741
|
+
# It fails validation because it doesn't currently have a latest unspent
|
|
742
|
+
assert status == MempoolInclusionStatus.FAILED
|
|
743
|
+
assert error == Err.DOUBLE_SPEND
|
chia/_tests/util/spend_sim.py
CHANGED
|
@@ -165,7 +165,9 @@ class SpendSim:
|
|
|
165
165
|
async with DBWrapper2.managed(database=uri, uri=True, reader_count=1, db_version=2) as self.db_wrapper:
|
|
166
166
|
self.coin_store = await CoinStore.create(self.db_wrapper)
|
|
167
167
|
self.hint_store = await HintStore.create(self.db_wrapper)
|
|
168
|
-
self.mempool_manager = MempoolManager(
|
|
168
|
+
self.mempool_manager = MempoolManager(
|
|
169
|
+
self.coin_store.get_coin_records, self.coin_store.get_unspent_lineage_info_for_puzzle_hash, defaults
|
|
170
|
+
)
|
|
169
171
|
self.defaults = defaults
|
|
170
172
|
|
|
171
173
|
# Load the next data if there is any
|
chia/full_node/full_node.py
CHANGED
|
@@ -274,6 +274,7 @@ class FullNode:
|
|
|
274
274
|
|
|
275
275
|
self._mempool_manager = MempoolManager(
|
|
276
276
|
get_coin_records=self.coin_store.get_coin_records,
|
|
277
|
+
get_unspent_lineage_info_for_puzzle_hash=self.coin_store.get_unspent_lineage_info_for_puzzle_hash,
|
|
277
278
|
consensus_constants=self.constants,
|
|
278
279
|
single_threaded=single_threaded,
|
|
279
280
|
)
|
chia/full_node/mempool.py
CHANGED
|
@@ -526,14 +526,14 @@ class Mempool:
|
|
|
526
526
|
unique_additions.extend(spend_data.additions)
|
|
527
527
|
cost_saving = 0
|
|
528
528
|
else:
|
|
529
|
-
await eligible_coin_spends.process_fast_forward_spends(
|
|
529
|
+
bundle_coin_spends = await eligible_coin_spends.process_fast_forward_spends(
|
|
530
530
|
mempool_item=item,
|
|
531
531
|
get_unspent_lineage_info_for_puzzle_hash=get_unspent_lineage_info_for_puzzle_hash,
|
|
532
532
|
height=height,
|
|
533
533
|
constants=constants,
|
|
534
534
|
)
|
|
535
535
|
unique_coin_spends, cost_saving, unique_additions = eligible_coin_spends.get_deduplication_info(
|
|
536
|
-
bundle_coin_spends=
|
|
536
|
+
bundle_coin_spends=bundle_coin_spends, max_cost=cost
|
|
537
537
|
)
|
|
538
538
|
item_cost = cost - cost_saving
|
|
539
539
|
log.info(
|
|
@@ -570,7 +570,7 @@ class Mempool:
|
|
|
570
570
|
if self.mempool_info.max_block_clvm_cost - cost_sum < MIN_COST_THRESHOLD:
|
|
571
571
|
break
|
|
572
572
|
except Exception as e:
|
|
573
|
-
log.
|
|
573
|
+
log.info(f"Exception while checking a mempool item for deduplication: {e}")
|
|
574
574
|
continue
|
|
575
575
|
if processed_spend_bundles == 0:
|
|
576
576
|
return None
|
|
@@ -129,6 +129,7 @@ class MempoolManager:
|
|
|
129
129
|
constants: ConsensusConstants
|
|
130
130
|
seen_bundle_hashes: dict[bytes32, bytes32]
|
|
131
131
|
get_coin_records: Callable[[Collection[bytes32]], Awaitable[list[CoinRecord]]]
|
|
132
|
+
get_unspent_lineage_info_for_puzzle_hash: Callable[[bytes32], Awaitable[Optional[UnspentLineageInfo]]]
|
|
132
133
|
nonzero_fee_minimum_fpc: int
|
|
133
134
|
mempool_max_total_cost: int
|
|
134
135
|
# a cache of MempoolItems that conflict with existing items in the pool
|
|
@@ -145,6 +146,7 @@ class MempoolManager:
|
|
|
145
146
|
def __init__(
|
|
146
147
|
self,
|
|
147
148
|
get_coin_records: Callable[[Collection[bytes32]], Awaitable[list[CoinRecord]]],
|
|
149
|
+
get_unspent_lineage_info_for_puzzle_hash: Callable[[bytes32], Awaitable[Optional[UnspentLineageInfo]]],
|
|
148
150
|
consensus_constants: ConsensusConstants,
|
|
149
151
|
*,
|
|
150
152
|
single_threaded: bool = False,
|
|
@@ -156,6 +158,7 @@ class MempoolManager:
|
|
|
156
158
|
self.seen_bundle_hashes: dict[bytes32, bytes32] = {}
|
|
157
159
|
|
|
158
160
|
self.get_coin_records = get_coin_records
|
|
161
|
+
self.get_unspent_lineage_info_for_puzzle_hash = get_unspent_lineage_info_for_puzzle_hash
|
|
159
162
|
|
|
160
163
|
# The fee per cost must be above this amount to consider the fee "nonzero", and thus able to kick out other
|
|
161
164
|
# transactions. This prevents spam. This is equivalent to 0.055 XCH per block, or about 0.00005 XCH for two
|
|
@@ -349,6 +352,7 @@ class MempoolManager:
|
|
|
349
352
|
spend_name,
|
|
350
353
|
first_added_height,
|
|
351
354
|
get_coin_records,
|
|
355
|
+
self.get_unspent_lineage_info_for_puzzle_hash,
|
|
352
356
|
)
|
|
353
357
|
if err is None:
|
|
354
358
|
# No error, immediately add to mempool, after removing conflicting TXs.
|
|
@@ -379,6 +383,7 @@ class MempoolManager:
|
|
|
379
383
|
spend_name: bytes32,
|
|
380
384
|
first_added_height: uint32,
|
|
381
385
|
get_coin_records: Callable[[Collection[bytes32]], Awaitable[list[CoinRecord]]],
|
|
386
|
+
get_unspent_lineage_info_for_puzzle_hash: Callable[[bytes32], Awaitable[Optional[UnspentLineageInfo]]],
|
|
382
387
|
) -> tuple[Optional[Err], Optional[MempoolItem], list[bytes32]]:
|
|
383
388
|
"""
|
|
384
389
|
Validates new_spend with the given NPCResult, and spend_name, and the current mempool. The mempool should
|
|
@@ -423,7 +428,7 @@ class MempoolManager:
|
|
|
423
428
|
eligibility_and_additions[coin_id] = EligibilityAndAdditions(
|
|
424
429
|
is_eligible_for_dedup=is_eligible_for_dedup,
|
|
425
430
|
spend_additions=spend_additions,
|
|
426
|
-
|
|
431
|
+
ff_puzzle_hash=bytes32(spend.puzzle_hash) if is_eligible_for_ff else None,
|
|
427
432
|
)
|
|
428
433
|
removal_names_from_coin_spends: set[bytes32] = set()
|
|
429
434
|
fast_forward_coin_ids: set[bytes32] = set()
|
|
@@ -433,14 +438,20 @@ class MempoolManager:
|
|
|
433
438
|
removal_names_from_coin_spends.add(coin_id)
|
|
434
439
|
eligibility_info = eligibility_and_additions.get(
|
|
435
440
|
coin_id,
|
|
436
|
-
EligibilityAndAdditions(is_eligible_for_dedup=False, spend_additions=[],
|
|
441
|
+
EligibilityAndAdditions(is_eligible_for_dedup=False, spend_additions=[], ff_puzzle_hash=None),
|
|
437
442
|
)
|
|
438
|
-
mark_as_fast_forward = eligibility_info.
|
|
443
|
+
mark_as_fast_forward = eligibility_info.ff_puzzle_hash is not None and supports_fast_forward(coin_spend)
|
|
444
|
+
if mark_as_fast_forward:
|
|
445
|
+
# Make sure the fast forward spend still has a version that is
|
|
446
|
+
# still unspent, because if the singleton has been melted, the
|
|
447
|
+
# fast forward spend will never become valid.
|
|
448
|
+
assert eligibility_info.ff_puzzle_hash is not None
|
|
449
|
+
if await get_unspent_lineage_info_for_puzzle_hash(eligibility_info.ff_puzzle_hash) is None:
|
|
450
|
+
return Err.DOUBLE_SPEND, None, []
|
|
451
|
+
fast_forward_coin_ids.add(coin_id)
|
|
439
452
|
# We are now able to check eligibility of both dedup and fast forward
|
|
440
453
|
if not (eligibility_info.is_eligible_for_dedup or mark_as_fast_forward):
|
|
441
454
|
non_eligible_coin_ids.append(coin_id)
|
|
442
|
-
if mark_as_fast_forward:
|
|
443
|
-
fast_forward_coin_ids.add(coin_id)
|
|
444
455
|
bundle_coin_spends[coin_id] = BundleCoinSpend(
|
|
445
456
|
coin_spend=coin_spend,
|
|
446
457
|
eligible_for_dedup=eligibility_info.is_eligible_for_dedup,
|
|
@@ -452,6 +463,12 @@ class MempoolManager:
|
|
|
452
463
|
# If you reach here it's probably because your program reveal doesn't match the coin's puzzle hash
|
|
453
464
|
return Err.INVALID_SPEND_BUNDLE, None, []
|
|
454
465
|
|
|
466
|
+
# fast forward spends are only allowed when bundled with other, non-FF, spends
|
|
467
|
+
# in order to evict an FF spend, it must be associated with a normal
|
|
468
|
+
# spend that can be included in a block or invalidated some other way
|
|
469
|
+
if all([s.eligible_for_fast_forward for s in bundle_coin_spends.values()]):
|
|
470
|
+
return Err.INVALID_SPEND_BUNDLE, None, []
|
|
471
|
+
|
|
455
472
|
removal_record_dict: dict[bytes32, CoinRecord] = {}
|
|
456
473
|
removal_amount: int = 0
|
|
457
474
|
removal_records = await get_coin_records(removal_names)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import copy
|
|
3
4
|
import dataclasses
|
|
4
5
|
from collections.abc import Awaitable
|
|
5
6
|
from typing import Callable, Optional
|
|
@@ -23,7 +24,10 @@ from chia.util.ints import uint32, uint64
|
|
|
23
24
|
class EligibilityAndAdditions:
|
|
24
25
|
is_eligible_for_dedup: bool
|
|
25
26
|
spend_additions: list[Coin]
|
|
26
|
-
|
|
27
|
+
# This is the spend puzzle hash. It's set to `None` if the spend is not
|
|
28
|
+
# eligible for fast forward. When the spend is eligible, we use its puzzle
|
|
29
|
+
# hash to check if the singleton has an unspent coin or not.
|
|
30
|
+
ff_puzzle_hash: Optional[bytes32] = None
|
|
27
31
|
|
|
28
32
|
|
|
29
33
|
def run_for_cost(
|
|
@@ -233,26 +237,36 @@ class EligibleCoinSpends:
|
|
|
233
237
|
get_unspent_lineage_info_for_puzzle_hash: Callable[[bytes32], Awaitable[Optional[UnspentLineageInfo]]],
|
|
234
238
|
height: uint32,
|
|
235
239
|
constants: ConsensusConstants,
|
|
236
|
-
) ->
|
|
240
|
+
) -> dict[bytes32, BundleCoinSpend]:
|
|
237
241
|
"""
|
|
238
|
-
Provides the caller with
|
|
239
|
-
|
|
242
|
+
Provides the caller with a `bundle_coin_spends` map that has a proper
|
|
243
|
+
state of fast forwarded coin spends and additions starting from
|
|
240
244
|
the most recent unspent versions of the related singleton spends.
|
|
241
245
|
|
|
242
246
|
Args:
|
|
243
|
-
mempool_item:
|
|
247
|
+
mempool_item: The internal mempool item to process
|
|
244
248
|
get_unspent_lineage_info_for_puzzle_hash: to lookup the most recent
|
|
245
249
|
version of the singleton from the coin store
|
|
246
250
|
constants: needed in order to refresh the mempool item if needed
|
|
247
251
|
height: needed in order to refresh the mempool item if needed
|
|
248
252
|
|
|
253
|
+
Returns:
|
|
254
|
+
The resulting `bundle_coin_spends` map of coin IDs to coin spends
|
|
255
|
+
and metadata, after fast forwarding
|
|
256
|
+
|
|
249
257
|
Raises:
|
|
250
258
|
If a fast forward cannot proceed, to prevent potential double spends
|
|
251
259
|
"""
|
|
260
|
+
|
|
261
|
+
# Let's first create a copy of the mempool item's `bundle_coin_spends`
|
|
262
|
+
# map to work on and return. This way we avoid the possibility of
|
|
263
|
+
# propagating a modified version of this item through the network.
|
|
264
|
+
bundle_coin_spends = copy.copy(mempool_item.bundle_coin_spends)
|
|
252
265
|
new_coin_spends = []
|
|
266
|
+
# Map of rebased singleton coin ID to coin spend and metadata
|
|
253
267
|
ff_bundle_coin_spends = {}
|
|
254
268
|
replaced_coin_ids = []
|
|
255
|
-
for coin_id, spend_data in
|
|
269
|
+
for coin_id, spend_data in bundle_coin_spends.items():
|
|
256
270
|
if not spend_data.eligible_for_fast_forward:
|
|
257
271
|
# Nothing to do for this spend, moving on
|
|
258
272
|
new_coin_spends.append(spend_data.coin_spend)
|
|
@@ -326,21 +340,17 @@ class EligibleCoinSpends:
|
|
|
326
340
|
new_coin_spends.append(new_coin_spend)
|
|
327
341
|
if len(ff_bundle_coin_spends) == 0:
|
|
328
342
|
# This item doesn't have any fast forward coins, nothing to do here
|
|
329
|
-
return
|
|
343
|
+
return bundle_coin_spends
|
|
330
344
|
# Update the mempool item after validating the new spend bundle
|
|
331
345
|
new_sb = SpendBundle(
|
|
332
346
|
coin_spends=new_coin_spends, aggregated_signature=mempool_item.spend_bundle.aggregated_signature
|
|
333
347
|
)
|
|
334
|
-
# We need to run the new spend bundle to make sure it remains valid
|
|
335
348
|
assert mempool_item.conds is not None
|
|
336
349
|
try:
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
height,
|
|
342
|
-
)
|
|
343
|
-
# validate_clvm_and_signature raises a TypeError with an error code
|
|
350
|
+
# Run the new spend bundle to make sure it remains valid. What we
|
|
351
|
+
# care about here is whether this call throws or not.
|
|
352
|
+
get_conditions_from_spendbundle(new_sb, mempool_item.conds.cost, constants, height)
|
|
353
|
+
# get_conditions_from_spendbundle raises a TypeError with an error code
|
|
344
354
|
except TypeError as e:
|
|
345
355
|
# Convert that to a ValidationError
|
|
346
356
|
if len(e.args) > 0:
|
|
@@ -351,15 +361,9 @@ class EligibleCoinSpends:
|
|
|
351
361
|
"Mempool item became invalid after singleton fast forward with an unspecified error."
|
|
352
362
|
) # pragma: no cover
|
|
353
363
|
|
|
354
|
-
# Update bundle_coin_spends using the
|
|
364
|
+
# Update bundle_coin_spends using the map of rebased singleton coin ID
|
|
365
|
+
# to coin spend and metadata.
|
|
355
366
|
for coin_id in replaced_coin_ids:
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
# NOTE: From this point on, in `create_bundle_from_mempool_items`, we rely
|
|
360
|
-
# on `bundle_coin_spends` and we don't use this updated spend bundle
|
|
361
|
-
# information, as we'll only need `aggregated_signature` which doesn't
|
|
362
|
-
# change. Still, it's good form to update the spend bundle with the
|
|
363
|
-
# new coin spends
|
|
364
|
-
mempool_item.spend_bundle = new_sb
|
|
365
|
-
mempool_item.conds = new_conditions
|
|
367
|
+
bundle_coin_spends.pop(coin_id, None)
|
|
368
|
+
bundle_coin_spends.update(ff_bundle_coin_spends)
|
|
369
|
+
return bundle_coin_spends
|
|
@@ -121,12 +121,12 @@ chia/_tests/core/make_block_generator.py,sha256=m9Uq39ZMuAkwSV5cPQt5jE8ysaSEJwqG
|
|
|
121
121
|
chia/_tests/core/mempool/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
122
122
|
chia/_tests/core/mempool/config.py,sha256=-GncDnWBQwvk5MHfOhjQ4DnUD3VlxrD8lLrt8Gd2D5c,86
|
|
123
123
|
chia/_tests/core/mempool/test_mempool.py,sha256=HlrEIAk70dGvNodQm_pHmSDYez6rF2fgS_BVK3Ezzd4,141045
|
|
124
|
-
chia/_tests/core/mempool/test_mempool_fee_estimator.py,sha256=
|
|
124
|
+
chia/_tests/core/mempool/test_mempool_fee_estimator.py,sha256=SSzCp4Tw4LMp2yYzEjzyf6UHejWKm_dDpMkpyas6MZs,3710
|
|
125
125
|
chia/_tests/core/mempool/test_mempool_fee_protocol.py,sha256=iD8R9S8falpF4WRxBeNSF8fpeoAY3e8K5FT4DYWSDDw,2161
|
|
126
126
|
chia/_tests/core/mempool/test_mempool_item_queries.py,sha256=BESoQXx8XG2jSJiE12nslC3y_vPWrfCWPCrv4tGl3Js,7027
|
|
127
|
-
chia/_tests/core/mempool/test_mempool_manager.py,sha256=
|
|
127
|
+
chia/_tests/core/mempool/test_mempool_manager.py,sha256=zRxgq74FRmxDm8KbhunW40f3aWZzVEQp3-qtgIw1S00,97083
|
|
128
128
|
chia/_tests/core/mempool/test_mempool_performance.py,sha256=EJ5cZkSOoQDSmt68GMAiYdmFWNOtJq0AnROJManU184,2800
|
|
129
|
-
chia/_tests/core/mempool/test_singleton_fast_forward.py,sha256=
|
|
129
|
+
chia/_tests/core/mempool/test_singleton_fast_forward.py,sha256=qySBET8zAXbQwx3xxedj0wUEIv73hwHE93OliHZ3W1g,38572
|
|
130
130
|
chia/_tests/core/node_height.py,sha256=MHC8fEZXvDCU-7zCWXwnSaWx-iECEvyl51OpitIMQIE,912
|
|
131
131
|
chia/_tests/core/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
132
132
|
chia/_tests/core/server/config.py,sha256=fTDhByaME5cEDbtyTKCWUf69F4kajs75aTQewZMjxak,69
|
|
@@ -277,7 +277,7 @@ chia/_tests/util/protocol_messages_json.py,sha256=7c8bq0PSnyyX80guTe3VB_tAqkeAv1
|
|
|
277
277
|
chia/_tests/util/rpc.py,sha256=g-vf7Nnp9Myr588lR2uyRs12eeQ1FIJ73h4FTFqiUeo,825
|
|
278
278
|
chia/_tests/util/run_block.py,sha256=qkjF45klRj0KXkHf9z6k2aY8SUJmUT8cJVg_NoTjE9Y,6006
|
|
279
279
|
chia/_tests/util/setup_nodes.py,sha256=DKKa_aZVXEfg7sd7dqWE2DDrGLvI6dB7SCslJbN2QA8,18407
|
|
280
|
-
chia/_tests/util/spend_sim.py,sha256=
|
|
280
|
+
chia/_tests/util/spend_sim.py,sha256=OTlZslTN24PQ2Q3bGWKvG7JoXQ3RhhWkGzbqq59N29k,21064
|
|
281
281
|
chia/_tests/util/split_managers.py,sha256=n7y0gvtkpOyGvMNAd1iYzeSrwXhlwcKcaRZfBE1FMPw,3069
|
|
282
282
|
chia/_tests/util/temp_file.py,sha256=tQnufsTZahaxYBQrRvArmwB0ZF3Q4-8ZxauQJ4-dKr4,306
|
|
283
283
|
chia/_tests/util/test_action_scope.py,sha256=0xJyAPL4NmJpWWJ6_QA6v-RpAh4RQeFRH1DrJGk9Biw,5220
|
|
@@ -524,14 +524,14 @@ chia/full_node/fee_estimator_constants.py,sha256=GsQfI9Z7YzPWGEe6ghJeYvzbG87C86K
|
|
|
524
524
|
chia/full_node/fee_estimator_interface.py,sha256=GoeD5RVmIsb4_qW-9AGttglwcDIpdIxFrEhqLUXp-Mw,1606
|
|
525
525
|
chia/full_node/fee_history.py,sha256=MniggGft1CVGHOJR7HI9YqGBP4er2dwL7Xzmm2E9JxU,586
|
|
526
526
|
chia/full_node/fee_tracker.py,sha256=HH8ZVxU9Md6oHobP1O2_q1bBu-o75nicQ2BeETGQxi0,22621
|
|
527
|
-
chia/full_node/full_node.py,sha256=
|
|
527
|
+
chia/full_node/full_node.py,sha256=l2Xgx0kTSzhOvynY6ZNHA9Izp1HsPk4M8Sm-0qWJ3NQ,166022
|
|
528
528
|
chia/full_node/full_node_api.py,sha256=JEkwf5mc9W1kokbR-P3vJntSU83Kf5R3nUic_XAICPw,98371
|
|
529
529
|
chia/full_node/full_node_store.py,sha256=1NIj4TWwFjrVHtnAl3F5i1dFPEW2QA5pwTNM4xN3Vbs,47402
|
|
530
530
|
chia/full_node/hint_management.py,sha256=P-NbUWOEoRyIp-_rUkIUm2lP7KrN9N5on57QIQio9mU,2305
|
|
531
531
|
chia/full_node/hint_store.py,sha256=Lr8oR1ptmEJE3H7VghEJrhHXtX8YIXr3cNTnsJZLgk0,3687
|
|
532
|
-
chia/full_node/mempool.py,sha256=
|
|
532
|
+
chia/full_node/mempool.py,sha256=kk6r-zCCZelnyx7DoJl0FydUSynudbB6DQToSYy4Ozo,25095
|
|
533
533
|
chia/full_node/mempool_check_conditions.py,sha256=AeTVTkrg4mK2kbdYOgmr1QcBDXUF3B3X-SSoshwgvgY,5751
|
|
534
|
-
chia/full_node/mempool_manager.py,sha256=
|
|
534
|
+
chia/full_node/mempool_manager.py,sha256=kwz8hPqniRiBVzQexfGVdEIv-VTvuhffkfZD9DOWk5Y,39833
|
|
535
535
|
chia/full_node/pending_tx_cache.py,sha256=wKy-7KSOMIPAb7Y1nQcK7HHIFCNaFeMiIxBEP5U4T6Q,3674
|
|
536
536
|
chia/full_node/puzzles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
537
537
|
chia/full_node/puzzles/block_program_zero.clsp,sha256=VeDPXnkPB2_1xH94Kzx4ntgk20fRI7AiWHCWaB95aJc,642
|
|
@@ -705,13 +705,13 @@ chia/types/coin_record.py,sha256=BEutj_kc5DzzRxlhv37TWhsjLMwwQ63z5cQIVmVSnoI,128
|
|
|
705
705
|
chia/types/coin_spend.py,sha256=Q_U4DqHJo6kvx36ON__c3LZ_9NC1qK-jZFjuHE51ozI,4130
|
|
706
706
|
chia/types/condition_opcodes.py,sha256=nFibKuhiR0FwXUB0hqDQbv0Ngfb-BezNKTfDzoa3vII,2213
|
|
707
707
|
chia/types/condition_with_args.py,sha256=N5f6V0ok1cLSTG-4YqAGOISYyhixC8745LGYqvu0Y58,389
|
|
708
|
-
chia/types/eligible_coin_spends.py,sha256=
|
|
708
|
+
chia/types/eligible_coin_spends.py,sha256=jyBVuuj64eKwUN6u9fRHchgMwkawZCNMV2pVnVF9UTI,18071
|
|
709
709
|
chia/types/end_of_slot_bundle.py,sha256=l6Oqhk4cnZgfmAKAToSMwsUnK2m9wpw5AJauwn-19WY,100
|
|
710
710
|
chia/types/fee_rate.py,sha256=rtCF9o5sI-6fVzRjRsBl0b3mYHB7Ik1p9IkQtbrGQAw,854
|
|
711
711
|
chia/types/full_block.py,sha256=2WqaqUwiJImjKJTE59C3zZdYPFdN5ZNfpn8AQiCVAGw,82
|
|
712
712
|
chia/types/generator_types.py,sha256=U2qtssNjKRnfSoidf-ziiB0r4iFzkV0-MYy-Bj2N-n0,340
|
|
713
713
|
chia/types/header_block.py,sha256=sTLOSI-Jpg1dwOJfKjHVFvauWK95AdpHReKmaes_cMs,86
|
|
714
|
-
chia/types/internal_mempool_item.py,sha256=
|
|
714
|
+
chia/types/internal_mempool_item.py,sha256=3UxMtcHm6mbg_54aT3GBtWS39arhu7NfINjlLKHCfck,619
|
|
715
715
|
chia/types/mempool_inclusion_status.py,sha256=iduTqYGvOMyVkDfiHmqESjHvbzP_6ZsawTIkKV8DXQc,260
|
|
716
716
|
chia/types/mempool_item.py,sha256=v9KJLaN_4_N02xY2eDIMj_knBJ-WNJGSvRtGKlwgxDk,2820
|
|
717
717
|
chia/types/mempool_submission_status.py,sha256=Q8aaZ7UQp0FyJt9CnAto63s-_RJOVoN2OpZ5h4fB01g,1049
|
|
@@ -1035,8 +1035,8 @@ chia/wallet/wallet_transaction_store.py,sha256=thFNbDkOEXbwYyToZB5uafnaj4VqDteHq
|
|
|
1035
1035
|
chia/wallet/wallet_user_store.py,sha256=lVJyOKPO6zB66EIHZA7rG9u-5V_MC0AtiEuDubU8RBk,4084
|
|
1036
1036
|
chia/wallet/wallet_weight_proof_handler.py,sha256=LKfnVR2HM1-7vdkSwoIVFUc7QIUvnhQPscZZCSKFvl0,4926
|
|
1037
1037
|
mozilla-ca/cacert.pem,sha256=o_Mowh453dHyvhzqQ6wN7IGeqiCpBCXX2pAaEVMbOqU,231212
|
|
1038
|
-
chia_blockchain-2.5.
|
|
1039
|
-
chia_blockchain-2.5.
|
|
1040
|
-
chia_blockchain-2.5.
|
|
1041
|
-
chia_blockchain-2.5.
|
|
1042
|
-
chia_blockchain-2.5.
|
|
1038
|
+
chia_blockchain-2.5.2rc1.dist-info/LICENSE,sha256=0tuU-jTzeRDJJaxF2YCEpBwbywgpbrVSXq1i6fJq63U,11347
|
|
1039
|
+
chia_blockchain-2.5.2rc1.dist-info/METADATA,sha256=anievx9tDspq_YHuwSU-xpQbiolfbLZSdkIVQAdczrw,10631
|
|
1040
|
+
chia_blockchain-2.5.2rc1.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
|
1041
|
+
chia_blockchain-2.5.2rc1.dist-info/entry_points.txt,sha256=GL2-UvicPVdKz72IP4shnmV3XImfoD5pMzoURfoAYk4,742
|
|
1042
|
+
chia_blockchain-2.5.2rc1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|