Full node tests
This commit is contained in:
parent
65d789a999
commit
386f29bce0
|
@ -591,7 +591,6 @@ class FullNode:
|
|||
Requests a full transaction if we haven't seen it previously, and if the fees are enough.
|
||||
"""
|
||||
if self.mempool_manager.seen(transaction.transaction_id):
|
||||
self.log.info(f"tx_id({transaction.transaction_id}) already seen")
|
||||
return
|
||||
elif self.mempool_manager.is_fee_enough(transaction.fees, transaction.cost):
|
||||
requestTX = full_node_protocol.RequestTransaction(
|
||||
|
@ -608,9 +607,7 @@ class FullNode:
|
|||
self, request: full_node_protocol.RequestTransaction
|
||||
) -> OutboundMessageGenerator:
|
||||
""" Peer has requested a full transaction from us. """
|
||||
spend_bundle = await self.mempool_manager.get_spendbundle(
|
||||
request.transaction_id
|
||||
)
|
||||
spend_bundle = self.mempool_manager.get_spendbundle(request.transaction_id)
|
||||
if spend_bundle is None:
|
||||
reject = full_node_protocol.RejectTransactionRequest(request.transaction_id)
|
||||
yield OutboundMessage(
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import collections
|
||||
from typing import Dict, Optional, Tuple, List, Set
|
||||
import logging
|
||||
|
||||
from src.consensus.constants import constants as consensus_constants
|
||||
from src.util.bundle_tools import best_solution_program
|
||||
|
@ -22,6 +23,9 @@ from src.util.ints import uint64, uint32
|
|||
from sortedcontainers import SortedDict
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MempoolManager:
|
||||
def __init__(self, unspent_store: CoinStore, override_constants: Dict = {}):
|
||||
# Allow passing in custom overrides
|
||||
|
@ -72,7 +76,7 @@ class MempoolManager:
|
|||
else:
|
||||
return None
|
||||
|
||||
async def is_fee_enough(self, fees: uint64, cost: uint64) -> bool:
|
||||
def is_fee_enough(self, fees: uint64, cost: uint64) -> bool:
|
||||
"""
|
||||
Determines whether any of the pools can accept a transaction with a given fees
|
||||
and cost.
|
||||
|
@ -162,7 +166,7 @@ class MempoolManager:
|
|||
for item in conflicting_pool_items.values():
|
||||
if item.fee_per_cost >= fees_per_cost:
|
||||
tmp_error = Err.MEMPOOL_CONFLICT
|
||||
await self.add_to_potential_tx_set(new_spend)
|
||||
self.add_to_potential_tx_set(new_spend)
|
||||
break
|
||||
elif fail_reason:
|
||||
errors.append(fail_reason)
|
||||
|
@ -191,7 +195,7 @@ class MempoolManager:
|
|||
error is Err.ASSERT_BLOCK_INDEX_EXCEEDS_FAILED
|
||||
or error is Err.ASSERT_BLOCK_AGE_EXCEEDS_FAILED
|
||||
):
|
||||
await self.add_to_potential_tx_set(new_spend)
|
||||
self.add_to_potential_tx_set(new_spend)
|
||||
break
|
||||
hash_key_pairs.extend(
|
||||
hash_key_pairs_for_conditions_dict(npc.condition_dict)
|
||||
|
@ -245,12 +249,12 @@ class MempoolManager:
|
|||
removal, mempool.header.height + 1, uint32(0), False, False
|
||||
)
|
||||
continue
|
||||
log.warning(f"Getting removal {removal}")
|
||||
# 2. Checks we have it in the unspent_store
|
||||
unspent: Optional[CoinRecord] = await self.unspent_store.get_coin_record(
|
||||
removal.name(), mempool.header
|
||||
)
|
||||
if unspent is None:
|
||||
print(f"unkown unspent {removal.name()}")
|
||||
return Err.UNKNOWN_UNSPENT, {}, []
|
||||
# 3. Checks if it's been spent already
|
||||
if unspent.spent == 1:
|
||||
|
@ -271,7 +275,7 @@ class MempoolManager:
|
|||
# 5. If coins can be spent return list of unspents as we see them in local storage
|
||||
return None, coin_records, []
|
||||
|
||||
async def add_to_potential_tx_set(self, spend: SpendBundle):
|
||||
def add_to_potential_tx_set(self, spend: SpendBundle):
|
||||
"""
|
||||
Adds SpendBundles that have failed to be added to the pool in potential tx set.
|
||||
This is later used to retry to add them.
|
||||
|
@ -282,14 +286,14 @@ class MempoolManager:
|
|||
first_in = list(self.potential_txs.keys())[0]
|
||||
del self.potential_txs[first_in]
|
||||
|
||||
async def seen(self, bundle_hash: bytes32) -> bool:
|
||||
def seen(self, bundle_hash: bytes32) -> bool:
|
||||
""" Return true if we saw this spendbundle before """
|
||||
if bundle_hash in self.seen_bundle_hashes:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
async def get_spendbundle(self, bundle_hash: bytes32) -> Optional[SpendBundle]:
|
||||
def get_spendbundle(self, bundle_hash: bytes32) -> Optional[SpendBundle]:
|
||||
""" Returns a full SpendBundle if it's inside one the mempools"""
|
||||
for pool in self.mempools.values():
|
||||
if bundle_hash in pool.spends:
|
||||
|
|
|
@ -68,7 +68,7 @@ class TestBlockchainTransactions:
|
|||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function == "new_transaction"
|
||||
|
||||
sb = await full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
assert sb is spend_bundle
|
||||
|
||||
last_block = blocks[10]
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import asyncio
|
||||
from secrets import token_bytes
|
||||
|
||||
import pytest
|
||||
|
||||
from src.protocols import full_node_protocol
|
||||
from src.protocols import full_node_protocol as fnp
|
||||
from src.types.peer_info import PeerInfo
|
||||
from src.util.ints import uint16, uint32
|
||||
from src.util.ints import uint16, uint32, uint64
|
||||
from tests.setup_nodes import setup_two_nodes, test_constants, bt
|
||||
from tests.wallet_tools import WalletTool
|
||||
|
||||
|
@ -28,7 +26,9 @@ def wallet_blocks():
|
|||
wallet_a = WalletTool()
|
||||
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
||||
wallet_receiver = WalletTool()
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, coinbase_puzzlehash)
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
test_constants, num_blocks, [], 10, reward_puzzlehash=coinbase_puzzlehash
|
||||
)
|
||||
return wallet_a, wallet_receiver, blocks
|
||||
|
||||
|
||||
|
@ -39,9 +39,7 @@ class TestFullNode:
|
|||
_, _, blocks = wallet_blocks
|
||||
|
||||
for i in range(1, 3):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(blocks[i])
|
||||
):
|
||||
async for _ in full_node_1.respond_block(fnp.RespondBlock(blocks[i])):
|
||||
pass
|
||||
|
||||
await server_2.start_client(
|
||||
|
@ -49,27 +47,56 @@ class TestFullNode:
|
|||
)
|
||||
await asyncio.sleep(2) # Allow connections to get made
|
||||
|
||||
new_tip_1 = full_node_protocol.NewTip(blocks[-1].height, blocks[-1].weight, blocks[-1].header_hash)
|
||||
new_tip_1 = fnp.NewTip(
|
||||
blocks[-1].height, blocks[-1].weight, blocks[-1].header_hash
|
||||
)
|
||||
msgs_1 = [x async for x in full_node_1.new_tip(new_tip_1)]
|
||||
|
||||
assert len(msgs_1) == 1
|
||||
assert msgs_1[0].message.data == full_node_protocol.RequestBlock(uint32(3), blocks[-1].header_hash)
|
||||
assert msgs_1[0].message.data == fnp.RequestBlock(
|
||||
uint32(3), blocks[-1].header_hash
|
||||
)
|
||||
|
||||
new_tip_2 = full_node_protocol.NewTip(blocks[-2].height, blocks[-2].weight, blocks[-2].header_hash)
|
||||
new_tip_2 = fnp.NewTip(
|
||||
blocks[-2].height, blocks[-2].weight, blocks[-2].header_hash
|
||||
)
|
||||
msgs_2 = [x async for x in full_node_1.new_tip(new_tip_2)]
|
||||
assert len(msgs_2) == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_new_transaction(self, two_nodes, wallet_blocks):
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
wallet_a, wallet_receiver, blocks = wallet_blocks
|
||||
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
||||
spent_block = blocks[1]
|
||||
print(spent_block.body.coinbase, receiver_puzzlehash)
|
||||
|
||||
spend_bundle = wallet_a.generate_signed_transaction(
|
||||
1000, receiver_puzzlehash, spent_block.body.coinbase
|
||||
1001, receiver_puzzlehash, spent_block.body.coinbase
|
||||
)
|
||||
assert spend_bundle is not None
|
||||
|
||||
# new_transaction_1 = full_node_protocol.NewTransaction(tx_id, )
|
||||
print("abc1")
|
||||
tx_id_1 = spend_bundle.get_hash()
|
||||
new_transaction_1 = fnp.NewTransaction(tx_id_1, uint64(100), uint64(100))
|
||||
# Not seen
|
||||
msgs_1 = [x async for x in full_node_1.new_transaction(new_transaction_1)]
|
||||
assert len(msgs_1) == 1
|
||||
assert msgs_1[0].message.data == fnp.RequestTransaction(tx_id_1)
|
||||
|
||||
respond_transaction_1 = fnp.RespondTransaction(spend_bundle)
|
||||
[x async for x in full_node_1.respond_transaction(respond_transaction_1)]
|
||||
|
||||
# Already seen
|
||||
msgs_3 = [x async for x in full_node_1.new_transaction(new_transaction_1)]
|
||||
assert len(msgs_3) == 0
|
||||
|
||||
# for _ in range(10):
|
||||
# spend_bundle = wallet_a.generate_signed_transaction(
|
||||
# 1001, receiver_puzzlehash, spent_block.body.coinbase
|
||||
# )
|
||||
# assert spend_bundle is not None
|
||||
# new_transaction_1 = fnp.NewTransaction(
|
||||
# spend_bundle.get_hash(), uint64(100), uint64(100)
|
||||
# )
|
||||
# respond_transaction_2 = fnp.RespondTransaction(spend_bundle)
|
||||
# [x async for x in full_node_1.respond_transaction(respond_transaction_2)]
|
||||
|
|
|
@ -61,7 +61,7 @@ class TestMempool:
|
|||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function == "new_transaction"
|
||||
|
||||
sb = await full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
assert sb is spend_bundle
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
@ -96,7 +96,7 @@ class TestMempool:
|
|||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function != "new_transaction"
|
||||
|
||||
sb = await full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
assert sb is None
|
||||
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
|
@ -114,7 +114,7 @@ class TestMempool:
|
|||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound_2.message.function == "new_transaction"
|
||||
print(blocks[1].body.coinbase.name())
|
||||
sb = await full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
assert sb is spend_bundle
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
@ -160,8 +160,8 @@ class TestMempool:
|
|||
async for _ in full_node_1.respond_transaction(tx2):
|
||||
pass
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb2 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle2.name())
|
||||
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb2 = full_node_1.mempool_manager.get_spendbundle(spend_bundle2.name())
|
||||
|
||||
assert sb1 == spend_bundle1
|
||||
assert sb2 is None
|
||||
|
@ -208,8 +208,8 @@ class TestMempool:
|
|||
async for _ in full_node_1.respond_transaction(tx2):
|
||||
pass
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb2 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle2.name())
|
||||
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb2 = full_node_1.mempool_manager.get_spendbundle(spend_bundle2.name())
|
||||
|
||||
assert sb1 is None
|
||||
assert sb2 == spend_bundle2
|
||||
|
@ -253,7 +253,7 @@ class TestMempool:
|
|||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function != "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
assert sb1 is None
|
||||
|
||||
|
@ -296,7 +296,7 @@ class TestMempool:
|
|||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function == "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
assert sb1 is spend_bundle1
|
||||
|
||||
|
@ -337,7 +337,7 @@ class TestMempool:
|
|||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function != "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
assert sb1 is None
|
||||
|
||||
|
@ -380,7 +380,7 @@ class TestMempool:
|
|||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function == "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
assert sb1 is spend_bundle1
|
||||
|
||||
|
@ -423,7 +423,7 @@ class TestMempool:
|
|||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function == "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
assert sb1 is spend_bundle1
|
||||
|
||||
|
@ -466,7 +466,7 @@ class TestMempool:
|
|||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function != "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
assert sb1 is None
|
||||
|
||||
|
@ -511,7 +511,7 @@ class TestMempool:
|
|||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function == "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
assert sb1 is spend_bundle1
|
||||
|
||||
|
@ -558,7 +558,7 @@ class TestMempool:
|
|||
outbound: OutboundMessage = _
|
||||
assert outbound.message.function != "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
assert sb1 is None
|
||||
# Sleep so that 3 sec passes
|
||||
|
@ -572,6 +572,6 @@ class TestMempool:
|
|||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound_2.message.function == "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
assert sb1 is spend_bundle1
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import asyncio
|
||||
from os import urandom
|
||||
|
||||
import pytest
|
||||
from blspy import ExtendedPrivateKey
|
||||
|
|
|
@ -47,7 +47,6 @@ class WalletTool:
|
|||
pubkey = self.extended_secret_key.public_child(
|
||||
self.next_address
|
||||
).get_public_key()
|
||||
print("Signing with pubkey", pubkey, self.next_address)
|
||||
self.pubkey_num_lookup[pubkey.serialize()] = self.next_address
|
||||
self.next_address = self.next_address + 1
|
||||
return pubkey
|
||||
|
@ -71,9 +70,6 @@ class WalletTool:
|
|||
def get_keys(self, puzzle_hash):
|
||||
for child in range(self.next_address):
|
||||
pubkey = self.extended_secret_key.public_child(child).get_public_key()
|
||||
print("PK", pubkey, child)
|
||||
print("Hash", puzzle_hash, puzzle_for_pk(pubkey.serialize()).get_hash())
|
||||
print("GET puzzle:", puzzle_for_pk(pubkey.serialize()))
|
||||
if puzzle_hash == puzzle_for_pk(pubkey.serialize()).get_hash():
|
||||
return (
|
||||
pubkey,
|
||||
|
@ -91,9 +87,7 @@ class WalletTool:
|
|||
|
||||
def get_new_puzzlehash(self):
|
||||
puzzle = self.get_new_puzzle()
|
||||
print("Puzzle", puzzle)
|
||||
puzzlehash = puzzle.get_hash()
|
||||
print("Puzzle hash:", puzzlehash)
|
||||
return puzzlehash
|
||||
|
||||
def sign(self, value, pubkey):
|
||||
|
|
Loading…
Reference in New Issue