diff --git a/src/mempool.py b/src/mempool.py index c871aa9f..cd3ad72c 100644 --- a/src/mempool.py +++ b/src/mempool.py @@ -1,18 +1,15 @@ import collections -from dataclasses import dataclass from typing import Dict, Optional, Tuple, List from src.consensus.constants import constants as consensus_constants from src.farming.farming_tools import best_solution_program from src.types.full_block import FullBlock from src.types.hashable import SpendBundle, CoinName, Coin, Unspent -from src.types.hashable.SpendBundle import BundleHash from src.types.header_block import HeaderBlock from src.types.mempool_item import MempoolItem from src.types.pool import Pool from src.types.sized_bytes import bytes32 from src.unspent_store import UnspentStore -from src.util.Conditions import ConditionOpcode, ConditionVarPair from src.util.ConsensusError import Err from src.util.mempool_check_conditions import get_name_puzzle_conditions, mempool_check_conditions_dict from src.util.consensus import hash_key_pairs_for_conditions_dict @@ -189,7 +186,8 @@ class Mempool: new_item = MempoolItem(new_spend, fees_per_cost, uint64(fees), cost) pool.add_to_pool(new_item, additions, removals_dic) - self.allSpend[new_spend.name] = new_spend + + self.allSpend[new_spend.name()] = new_spend added_count += 1 return added_count > 0, None @@ -205,7 +203,7 @@ class Mempool: conflicts: List[Coin] = [] for removal in removals: # 0. Checks for double spend inside same spend_bundle - if not removals_counter[removal.name()]: + if not removal.name() in removals_counter: removals_counter[removal.name()] = 1 else: return Err.DOUBLE_SPEND, {}, None @@ -234,7 +232,7 @@ class Mempool: return None, unspents, None async def add_to_potential_tx_set(self, spend: SpendBundle): - self.potential_txs[spend.name] = spend + self.potential_txs[spend.name()] = spend while len(self.potential_txs) > self.potential_cache_size: first_in = self.potential_txs.keys()[0] diff --git a/tests/test_mempool.py b/tests/test_mempool.py index e69de29b..f4704514 100644 --- a/tests/test_mempool.py +++ b/tests/test_mempool.py @@ -0,0 +1,75 @@ +import asyncio +import pytest +from src.server.outbound_message import OutboundMessage +from src.protocols import peer_protocol +from src.wallet.wallets.standard_wallet.wallet import Wallet +from tests.setup_nodes import setup_two_nodes, test_constants, bt + + +@pytest.fixture(scope="module") +def event_loop(): + loop = asyncio.get_event_loop() + yield loop + + +class TestMempool: + @pytest.fixture(scope="function") + async def two_nodes(self): + async for _ in setup_two_nodes(): + yield _ + + @pytest.mark.asyncio + async def test_basic_mempool(self, two_nodes): + num_blocks = 3 + wallet_a = Wallet() + coinbase_puzzlehash = wallet_a.get_new_puzzlehash() + wallet_receiver = Wallet() + receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() + + blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash) + full_node_1, full_node_2, server_1, server_2 = two_nodes + + block = blocks[1] + async for _ in full_node_1.block(peer_protocol.Block(block)): + wallet_a.notify([block.body.coinbase], []) + spend_bundle = wallet_a.generate_signed_transaction(1000, receiver_puzzlehash) + tx: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle) + async for _ in full_node_1.transaction(tx): + outbound: OutboundMessage = _ + # Maybe transaction means that it's accepted in mempool + assert outbound.message.function == "maybe_transaction" + + @pytest.mark.asyncio + async def test_double_spend(self, two_nodes): + num_blocks = 3 + wallet_a = Wallet() + coinbase_puzzlehash = wallet_a.get_new_puzzlehash() + wallet_receiver = Wallet() + receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() + + blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash) + full_node_1, full_node_2, server_1, server_2 = two_nodes + + block = blocks[1] + async for _ in full_node_1.block(peer_protocol.Block(block)): + pass + + wallet_a.notify([block.body.coinbase], []) + spend_bundle1 = wallet_a.generate_signed_transaction(1000, receiver_puzzlehash) + tx1: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle1) + async for _ in full_node_1.transaction(tx1): + outbound: OutboundMessage = _ + # Maybe transaction means that it's accepted in mempool + assert outbound.message.function == "maybe_transaction" + + spend_bundle2 = wallet_a.generate_signed_transaction(2000, receiver_puzzlehash) + tx2: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle2) + async for _ in full_node_1.transaction(tx2): + pass + + sb1 = await full_node_1.mempool.get_spendbundle(spend_bundle1.name()) + sb2 = await full_node_1.mempool.get_spendbundle(spend_bundle2.name()) + + assert sb1 == spend_bundle1 + assert sb2 is None +