New full node protocol
This commit is contained in:
parent
3baab5c6a7
commit
179ccbb1b7
|
@ -73,8 +73,8 @@ full_node:
|
|||
|
||||
enable_upnp: True
|
||||
# Don't send any more than these number of headers and blocks, in one message
|
||||
max_headers_to_send: 25
|
||||
max_blocks_to_send: 5
|
||||
max_headers_to_send: 1
|
||||
max_blocks_to_send: 1
|
||||
num_sync_batches: 10
|
||||
|
||||
# If node is more than these blocks behind, will do a sync
|
||||
|
|
|
@ -27,7 +27,7 @@ from src.util.ConsensusError import Err
|
|||
from src.util.blockchain_check_conditions import blockchain_check_conditions_dict
|
||||
from src.util.condition_tools import hash_key_pairs_for_conditions_dict
|
||||
from src.util.mempool_check_conditions import get_name_puzzle_conditions
|
||||
from src.util.errors import BlockNotInBlockchain, InvalidGenesisBlock
|
||||
from src.util.errors import InvalidGenesisBlock
|
||||
from src.util.ints import uint32, uint64
|
||||
from src.types.challenge import Challenge
|
||||
|
||||
|
@ -210,38 +210,6 @@ class Blockchain:
|
|||
ret_hashes.append(curr.header_hash)
|
||||
return list(reversed(ret_hashes))
|
||||
|
||||
def get_header_hashes_by_height(
|
||||
self, heights: List[uint32], tip_header_hash: bytes32
|
||||
) -> List[bytes32]:
|
||||
"""
|
||||
Returns a list of header blocks, one for each height requested.
|
||||
"""
|
||||
if len(heights) == 0:
|
||||
return []
|
||||
|
||||
sorted_heights = sorted(
|
||||
[(height, index) for index, height in enumerate(heights)], reverse=True
|
||||
)
|
||||
|
||||
curr_block: Optional[Header] = self.headers.get(tip_header_hash, None)
|
||||
|
||||
if curr_block is None:
|
||||
raise BlockNotInBlockchain(
|
||||
f"Header hash {tip_header_hash} not present in chain."
|
||||
)
|
||||
headers: List[Tuple[int, Header]] = []
|
||||
for height, index in sorted_heights:
|
||||
if height > curr_block.height:
|
||||
raise ValueError("Height is not valid for tip {tip_header_hash}")
|
||||
while height < curr_block.height:
|
||||
curr_block = self.headers.get(curr_block.prev_header_hash, None)
|
||||
if curr_block is None:
|
||||
raise ValueError(f"Do not have header {height}")
|
||||
headers.append((index, curr_block))
|
||||
|
||||
# Return sorted by index (original order)
|
||||
return [b.header_hash for _, b in sorted(headers, key=lambda pair: pair[0])]
|
||||
|
||||
def find_fork_point(self, alternate_chain: List[bytes32]) -> uint32:
|
||||
"""
|
||||
Takes in an alternate blockchain (headers), and compares it to self. Returns the last header
|
||||
|
|
1026
src/full_node.py
1026
src/full_node.py
File diff suppressed because it is too large
Load Diff
|
@ -72,9 +72,22 @@ class MempoolManager:
|
|||
else:
|
||||
return None
|
||||
|
||||
async 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.
|
||||
"""
|
||||
if fees < 0:
|
||||
return False
|
||||
fees_per_cost = fees / cost
|
||||
for pool in self.mempools.values():
|
||||
if not pool.at_full_capacity() or fees_per_cost >= pool.get_min_fee_rate():
|
||||
return True
|
||||
return False
|
||||
|
||||
async def add_spendbundle(
|
||||
self, new_spend: SpendBundle, to_pool: Mempool = None
|
||||
) -> Tuple[bool, Optional[Err]]:
|
||||
) -> Tuple[Optional[uint64], Optional[Err]]:
|
||||
"""
|
||||
Tries to add spendbundle to either self.mempools or to_pool if it's specified.
|
||||
Returns true if it's added in any of pools, Returns error if it fails.
|
||||
|
@ -86,12 +99,12 @@ class MempoolManager:
|
|||
# npc contains names of the coins removed, puzzle_hashes and their spend conditions
|
||||
fail_reason, npc_list, cost = await get_name_puzzle_conditions(program)
|
||||
if fail_reason:
|
||||
return False, fail_reason
|
||||
return None, fail_reason
|
||||
|
||||
fees = new_spend.fees()
|
||||
|
||||
if cost == 0:
|
||||
return False, Err.UNKNOWN
|
||||
return None, Err.UNKNOWN
|
||||
fees_per_cost: float = fees / cost
|
||||
|
||||
# build removal list
|
||||
|
@ -101,13 +114,13 @@ class MempoolManager:
|
|||
# Check additions for max coin amount
|
||||
for coin in additions:
|
||||
if coin.amount >= consensus_constants["MAX_COIN_AMOUNT"]:
|
||||
return False, Err.COIN_AMOUNT_EXCEEDS_MAXIMUM
|
||||
return None, Err.COIN_AMOUNT_EXCEEDS_MAXIMUM
|
||||
|
||||
# Watch out for duplicate outputs
|
||||
addition_counter = collections.Counter(_.name() for _ in additions)
|
||||
for k, v in addition_counter.items():
|
||||
if v > 1:
|
||||
return False, Err.DUPLICATE_OUTPUT
|
||||
return None, Err.DUPLICATE_OUTPUT
|
||||
|
||||
# Spend might be valid for on pool but not for others
|
||||
added_count = 0
|
||||
|
@ -163,7 +176,7 @@ class MempoolManager:
|
|||
for unspent in unspents.values():
|
||||
coin = removals_dic[unspent.coin.name()]
|
||||
if unspent.coin.puzzle_hash != coin.puzzle_hash:
|
||||
return False, Err.WRONG_PUZZLE_HASH
|
||||
return None, Err.WRONG_PUZZLE_HASH
|
||||
|
||||
# Verify conditions, create hash_key list for aggsig check
|
||||
hash_key_pairs = []
|
||||
|
@ -189,7 +202,7 @@ class MempoolManager:
|
|||
|
||||
# Verify aggregated signature
|
||||
if not new_spend.aggregated_signature.validate(hash_key_pairs):
|
||||
return False, Err.BAD_AGGREGATE_SIGNATURE
|
||||
return None, Err.BAD_AGGREGATE_SIGNATURE
|
||||
|
||||
# Remove all conflicting Coins and SpendBundles
|
||||
if fail_reason:
|
||||
|
@ -203,9 +216,9 @@ class MempoolManager:
|
|||
added_count += 1
|
||||
|
||||
if added_count > 0:
|
||||
return True, None
|
||||
return uint64(cost), None
|
||||
else:
|
||||
return False, errors[0]
|
||||
return None, errors[0]
|
||||
|
||||
async def check_removals(
|
||||
self, additions: List[Coin], removals: List[Coin], mempool: Mempool
|
||||
|
|
|
@ -8,7 +8,7 @@ from src.types.peer_info import PeerInfo
|
|||
from src.types.proof_of_time import ProofOfTime
|
||||
from src.types.sized_bytes import bytes32
|
||||
from src.util.cbor_message import cbor_message
|
||||
from src.util.ints import uint32
|
||||
from src.util.ints import uint32, uint64
|
||||
|
||||
|
||||
"""
|
||||
|
@ -18,8 +18,24 @@ Protocol between full nodes.
|
|||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class TransactionId:
|
||||
class NewTip:
|
||||
height: uint32
|
||||
weight: uint64
|
||||
header_hash: bytes32
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RemovingTip:
|
||||
header_hash: bytes32
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class NewTransaction:
|
||||
transaction_id: bytes32
|
||||
cost: uint64
|
||||
fees: uint64
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
@ -30,34 +46,120 @@ class RequestTransaction:
|
|||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class NewTransaction:
|
||||
class RespondTransaction:
|
||||
transaction: SpendBundle
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RejectTransactionRequest:
|
||||
transaction_id: bytes32
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class NewProofOfTime:
|
||||
height: uint32
|
||||
challenge_hash: bytes32
|
||||
number_of_iterations: uint64
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RequestProofOfTime:
|
||||
height: uint32
|
||||
challenge_hash: bytes32
|
||||
number_of_iterations: uint64
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RespondProofOfTime:
|
||||
proof: ProofOfTime
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class UnfinishedBlock:
|
||||
block: FullBlock
|
||||
class RejectProofOfTimeRequest:
|
||||
challenge_hash: bytes32
|
||||
iterations: uint64
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RequestBlock:
|
||||
class NewCompactProofOfTime:
|
||||
height: uint32
|
||||
challenge_hash: bytes32
|
||||
number_of_iterations: uint64
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RequestCompactProofOfTime:
|
||||
height: uint32
|
||||
challenge_hash: bytes32
|
||||
number_of_iterations: uint64
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RespondCompactProofOfTime:
|
||||
proof: ProofOfTime
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RejectCompactProofOfTimeRequest:
|
||||
challenge_hash: bytes32
|
||||
iterations: uint64
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class NewUnfinishedBlock:
|
||||
previous_header_hash: bytes32
|
||||
iterations: uint64
|
||||
new_header_hash: bytes32
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RequestUnfinishedBlock:
|
||||
header_hash: bytes32
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class Block:
|
||||
class RespondUnfinishedBlock:
|
||||
block: FullBlock
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RejectUnfinishedBlockRequest:
|
||||
header_hash: bytes32
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RequestBlock:
|
||||
height: uint32
|
||||
header_hash: bytes32
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RespondBlock:
|
||||
block: FullBlock
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RejectBlockRequest:
|
||||
height: uint32
|
||||
header_hash: bytes32
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RequestPeers:
|
||||
|
@ -86,27 +188,19 @@ class AllHeaderHashes:
|
|||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RequestHeaderBlocks:
|
||||
tip_header_hash: bytes32
|
||||
heights: List[uint32]
|
||||
class RequestHeaderBlock:
|
||||
height: uint32
|
||||
header_hash: bytes32
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class HeaderBlocks:
|
||||
tip_header_hash: bytes32
|
||||
header_blocks: List[HeaderBlock]
|
||||
class RespondHeaderBlock:
|
||||
header_block: HeaderBlock
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class RequestSyncBlocks:
|
||||
tip_header_hash: bytes32
|
||||
heights: List[uint32]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@cbor_message
|
||||
class SyncBlocks:
|
||||
tip_header_hash: bytes32
|
||||
blocks: List[FullBlock]
|
||||
class RejectHeaderBlockRequest:
|
||||
height: uint32
|
||||
header_hash: bytes32
|
||||
|
|
71
src/store.py
71
src/store.py
|
@ -19,6 +19,8 @@ class FullNodeStore:
|
|||
db: aiosqlite.Connection
|
||||
# Whether or not we are syncing
|
||||
sync_mode: bool
|
||||
# Whether we are waiting for tips (at the start of sync) or already syncing
|
||||
waiting_for_tips: bool
|
||||
# Potential new tips that we have received from others.
|
||||
potential_tips: Dict[bytes32, FullBlock]
|
||||
# List of all header hashes up to the tip, download up front
|
||||
|
@ -35,6 +37,8 @@ class FullNodeStore:
|
|||
potential_future_blocks: List[FullBlock]
|
||||
# Current estimate of the speed of the network timelords
|
||||
proof_of_time_estimate_ips: uint64
|
||||
# Proof of time heights
|
||||
proof_of_time_heights: Dict[Tuple[bytes32, uint64], uint32]
|
||||
# Our best unfinished block
|
||||
unfinished_blocks_leader: Tuple[uint32, uint64]
|
||||
# Blocks which we have created, but don't have proof of space yet, old ones are cleared
|
||||
|
@ -45,6 +49,7 @@ class FullNodeStore:
|
|||
seen_unfinished_blocks: set
|
||||
# Blocks which we have received but our blockchain does not reach, old ones are cleared
|
||||
disconnected_blocks: Dict[bytes32, FullBlock]
|
||||
|
||||
# Lock
|
||||
lock: asyncio.Lock
|
||||
|
||||
|
@ -80,6 +85,7 @@ class FullNodeStore:
|
|||
await self.db.commit()
|
||||
|
||||
self.sync_mode = False
|
||||
self.waiting_for_tips = True
|
||||
self.potential_tips = {}
|
||||
self.potential_hashes = []
|
||||
self.potential_headers = {}
|
||||
|
@ -88,6 +94,7 @@ class FullNodeStore:
|
|||
self.potential_blocks_received = {}
|
||||
self.potential_future_blocks = []
|
||||
self.proof_of_time_estimate_ips = uint64(10000)
|
||||
self.proof_of_time_heights = {}
|
||||
self.unfinished_blocks_leader = (
|
||||
uint32(0),
|
||||
uint64((1 << 64) - 1),
|
||||
|
@ -132,6 +139,22 @@ class FullNodeStore:
|
|||
return FullBlock.from_bytes(row[2])
|
||||
return None
|
||||
|
||||
async def get_blocks_at(self, heights: List[uint32]) -> List[FullBlock]:
|
||||
if len(heights) == 0:
|
||||
return []
|
||||
|
||||
heights_db = tuple(heights)
|
||||
formatted_str = (
|
||||
f'SELECT * from blocks WHERE height in ({"?," * (len(heights_db) - 1)}?)'
|
||||
)
|
||||
cursor = await self.db.execute(formatted_str, heights_db)
|
||||
rows = await cursor.fetchall()
|
||||
await cursor.close()
|
||||
blocks: List[FullBlock] = []
|
||||
for row in rows:
|
||||
blocks.append(FullBlock.from_bytes(row[2]))
|
||||
return blocks
|
||||
|
||||
async def get_headers(self) -> List[Header]:
|
||||
cursor = await self.db.execute("SELECT * from headers")
|
||||
rows = await cursor.fetchall()
|
||||
|
@ -181,6 +204,12 @@ class FullNodeStore:
|
|||
def get_sync_mode(self) -> bool:
|
||||
return self.sync_mode
|
||||
|
||||
def set_waiting_for_tips(self, waiting_for_tips: bool) -> None:
|
||||
self.waiting_for_tips = waiting_for_tips
|
||||
|
||||
def get_waiting_for_tips(self) -> bool:
|
||||
return self.waiting_for_tips
|
||||
|
||||
async def clear_sync_info(self):
|
||||
self.potential_tips.clear()
|
||||
self.potential_headers.clear()
|
||||
|
@ -188,6 +217,7 @@ class FullNodeStore:
|
|||
await cursor.close()
|
||||
self.potential_blocks_received.clear()
|
||||
self.potential_future_blocks.clear()
|
||||
self.waiting_for_tips = True
|
||||
|
||||
def get_potential_tips_tuples(self) -> List[Tuple[bytes32, FullBlock]]:
|
||||
return list(self.potential_tips.items())
|
||||
|
@ -256,9 +286,15 @@ class FullNodeStore:
|
|||
return (res[0], res[1], res[2])
|
||||
|
||||
def clear_candidate_blocks_below(self, height: uint32) -> None:
|
||||
for key in list(self.candidate_blocks.keys()):
|
||||
if self.candidate_blocks[key][3] < height:
|
||||
del_keys = []
|
||||
for key, value in self.candidate_blocks.items():
|
||||
if value[3] < height:
|
||||
del_keys.append(key)
|
||||
for key in del_keys:
|
||||
try:
|
||||
del self.candidate_blocks[key]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def add_unfinished_block(
|
||||
self, key: Tuple[bytes32, uint64], block: FullBlock
|
||||
|
@ -281,9 +317,15 @@ class FullNodeStore:
|
|||
return self.unfinished_blocks.copy()
|
||||
|
||||
def clear_unfinished_blocks_below(self, height: uint32) -> None:
|
||||
for key in list(self.unfinished_blocks.keys()):
|
||||
if self.unfinished_blocks[key].height < height:
|
||||
del_keys = []
|
||||
for key, unf in self.unfinished_blocks.items():
|
||||
if unf.height < height:
|
||||
del_keys.append(key)
|
||||
for key in del_keys:
|
||||
try:
|
||||
del self.unfinished_blocks[key]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def set_unfinished_block_leader(self, key: Tuple[bytes32, uint64]) -> None:
|
||||
self.unfinished_blocks_leader = key
|
||||
|
@ -296,3 +338,24 @@ class FullNodeStore:
|
|||
|
||||
def get_proof_of_time_estimate_ips(self) -> uint64:
|
||||
return self.proof_of_time_estimate_ips
|
||||
|
||||
def add_proof_of_time_heights(
|
||||
self, challenge_iters: Tuple[bytes32, uint64], height: uint32
|
||||
) -> None:
|
||||
self.proof_of_time_heights[challenge_iters] = height
|
||||
|
||||
def get_proof_of_time_heights(
|
||||
self, challenge_iters: Tuple[bytes32, uint64]
|
||||
) -> Optional[uint32]:
|
||||
return self.proof_of_time_heights.get(challenge_iters, None)
|
||||
|
||||
def clear_proof_of_time_heights_below(self, height: uint32) -> None:
|
||||
del_keys: List = []
|
||||
for key, value in self.proof_of_time_heights.items():
|
||||
if value < height:
|
||||
del_keys.append(key)
|
||||
for key in del_keys:
|
||||
try:
|
||||
del self.proof_of_time_heights[key]
|
||||
except KeyError:
|
||||
pass
|
||||
|
|
|
@ -34,4 +34,4 @@ class ProofOfSpace(Streamable):
|
|||
|
||||
@staticmethod
|
||||
def calculate_plot_seed(pool_pubkey: PublicKey, plot_pubkey: PublicKey) -> bytes32:
|
||||
return bytes32(std_hash(bytes(pool_pubkey) + bytes(plot_pubkey)).digest())
|
||||
return bytes32(std_hash(bytes(pool_pubkey) + bytes(plot_pubkey)))
|
||||
|
|
|
@ -116,9 +116,7 @@ class BlockTools:
|
|||
block_list.append(FullBlock.from_bytes(test_constants["GENESIS_BLOCK"]))
|
||||
else:
|
||||
block_list.append(
|
||||
self.create_genesis_block(
|
||||
test_constants, std_hash(seed), seed
|
||||
)
|
||||
self.create_genesis_block(test_constants, std_hash(seed), seed)
|
||||
)
|
||||
prev_difficulty = test_constants["DIFFICULTY_STARTING"]
|
||||
curr_difficulty = prev_difficulty
|
||||
|
|
|
@ -15,8 +15,7 @@ from src.types.hashable.Coin import Coin
|
|||
from src.types.header import Header, HeaderData
|
||||
from src.types.proof_of_space import ProofOfSpace
|
||||
from src.coin_store import CoinStore
|
||||
from src.util.ints import uint8, uint32, uint64
|
||||
from src.util.errors import BlockNotInBlockchain
|
||||
from src.util.ints import uint8, uint64
|
||||
from tests.block_tools import BlockTools
|
||||
|
||||
bt = BlockTools()
|
||||
|
@ -52,9 +51,6 @@ class TestGenesisBlock:
|
|||
assert len(bc1.get_current_tips()) == 1
|
||||
genesis_block = bc1.get_current_tips()[0]
|
||||
assert genesis_block.height == 0
|
||||
assert (
|
||||
bc1.get_header_hashes_by_height([uint32(0)], genesis_block.header_hash)
|
||||
)[0] == genesis_block.header_hash
|
||||
assert (
|
||||
bc1.get_next_difficulty(genesis_block.header_hash)
|
||||
) == genesis_block.weight
|
||||
|
@ -83,32 +79,6 @@ class TestBlockValidation:
|
|||
await unspent_store.close()
|
||||
await store.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_header_hashes(self, initial_blockchain):
|
||||
blocks, b = initial_blockchain
|
||||
header_hashes_1 = b.get_header_hashes_by_height(
|
||||
[0, 8, 3], blocks[8].header_hash
|
||||
)
|
||||
assert header_hashes_1 == [
|
||||
blocks[0].header_hash,
|
||||
blocks[8].header_hash,
|
||||
blocks[3].header_hash,
|
||||
]
|
||||
|
||||
try:
|
||||
b.get_header_hashes_by_height([0, 8, 3], blocks[6].header_hash)
|
||||
thrown = False
|
||||
except ValueError:
|
||||
thrown = True
|
||||
assert thrown
|
||||
|
||||
try:
|
||||
b.get_header_hashes_by_height([0, 8, 3], blocks[9].header_hash)
|
||||
thrown_2 = False
|
||||
except BlockNotInBlockchain:
|
||||
thrown_2 = True
|
||||
assert thrown_2
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prev_pointer(self, initial_blockchain):
|
||||
blocks, b = initial_blockchain
|
||||
|
|
|
@ -48,7 +48,9 @@ class TestBlockchainTransactions:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
for block in blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
spent_block = blocks[1]
|
||||
|
@ -58,13 +60,13 @@ class TestBlockchainTransactions:
|
|||
)
|
||||
|
||||
assert spend_bundle is not None
|
||||
tx: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx):
|
||||
async for _ in full_node_1.respond_transaction(tx):
|
||||
outbound: OutboundMessage = _
|
||||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function == "maybe_transaction"
|
||||
assert outbound.message.function == "new_transaction"
|
||||
|
||||
sb = await full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
assert sb is spend_bundle
|
||||
|
@ -84,7 +86,9 @@ class TestBlockchainTransactions:
|
|||
)
|
||||
|
||||
next_block = new_blocks[11]
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(next_block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(next_block)
|
||||
):
|
||||
pass
|
||||
|
||||
tips = full_node_1.blockchain.get_current_tips()
|
||||
|
@ -129,7 +133,9 @@ class TestBlockchainTransactions:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
for block in blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
spent_block = blocks[1]
|
||||
|
@ -172,7 +178,9 @@ class TestBlockchainTransactions:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
for block in blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
spent_block = blocks[1]
|
||||
|
@ -216,7 +224,9 @@ class TestBlockchainTransactions:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
for block in blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
# Coinbase that gets spent
|
||||
|
@ -290,7 +300,9 @@ class TestBlockchainTransactions:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
for block in blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
# Coinbase that gets spent
|
||||
|
@ -371,7 +383,9 @@ class TestBlockchainTransactions:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
for block in blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
# Coinbase that gets spent
|
||||
|
@ -411,7 +425,9 @@ class TestBlockchainTransactions:
|
|||
)
|
||||
|
||||
for block in valid_new_blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
# Try to validate that block at index 12
|
||||
|
@ -439,7 +455,9 @@ class TestBlockchainTransactions:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
for block in blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
# Coinbase that gets spent
|
||||
|
@ -480,7 +498,9 @@ class TestBlockchainTransactions:
|
|||
)
|
||||
|
||||
for block in valid_new_blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
# Try to validate that block at index 12
|
||||
|
@ -508,7 +528,9 @@ class TestBlockchainTransactions:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
for block in blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
# Coinbase that gets spent
|
||||
|
@ -552,7 +574,9 @@ class TestBlockchainTransactions:
|
|||
)
|
||||
|
||||
for block in valid_new_blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
# Try to validate that block after 3 sec have passed
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
# import asyncio
|
||||
|
||||
# import pytest
|
||||
|
||||
# from src.protocols import full_node_protocol
|
||||
# from src.types.peer_info import PeerInfo
|
||||
# from src.util.ints import uint16
|
||||
# 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 TestFullNode:
|
||||
# @pytest.fixture(scope="function")
|
||||
# async def two_nodes(self):
|
||||
# async for _ in setup_two_nodes():
|
||||
# yield _
|
||||
#
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_unfinished_blocks_load(self, two_nodes):
|
||||
# num_blocks = 10
|
||||
# full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
# blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10)
|
||||
|
||||
# for i in range(1, num_blocks - 1):
|
||||
# async for _ in full_node_1.respond_block(
|
||||
# full_node_protocol.RespondBlock(blocks[i])
|
||||
# ):
|
||||
# pass
|
||||
|
||||
# await server_2.start_client(
|
||||
# PeerInfo(server_1._host, uint16(server_1._port)), None
|
||||
# )
|
||||
# await asyncio.sleep(2) # Allow connections to get made
|
|
@ -28,7 +28,9 @@ class TestFullSync:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
for i in range(1, num_blocks):
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(blocks[i])):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(blocks[i])
|
||||
):
|
||||
pass
|
||||
|
||||
await server_2.start_client(
|
||||
|
@ -64,15 +66,21 @@ class TestFullSync:
|
|||
|
||||
# 10 blocks to node_1
|
||||
for i in range(1, num_blocks):
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(blocks[i])):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(blocks[i])
|
||||
):
|
||||
pass
|
||||
# 4 different blocks to node_2
|
||||
for i in range(1, num_blocks_2):
|
||||
async for _ in full_node_2.block(full_node_protocol.Block(blocks_2[i])):
|
||||
async for _ in full_node_2.respond_block(
|
||||
full_node_protocol.RespondBlock(blocks_2[i])
|
||||
):
|
||||
pass
|
||||
|
||||
# 6th block from node_1 to node_2
|
||||
async for _ in full_node_2.block(full_node_protocol.Block(blocks[5])):
|
||||
async for _ in full_node_2.respond_block(
|
||||
full_node_protocol.RespondBlock(blocks[5])
|
||||
):
|
||||
pass
|
||||
|
||||
await server_2.start_client(
|
||||
|
|
|
@ -44,20 +44,22 @@ class TestMempool:
|
|||
|
||||
block = blocks[1]
|
||||
print(f"block coinbase: {block.body.coinbase.name()}")
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
spend_bundle = wallet_a.generate_signed_transaction(
|
||||
1000, receiver_puzzlehash, block.body.coinbase
|
||||
)
|
||||
assert spend_bundle is not None
|
||||
tx: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx):
|
||||
async for _ in full_node_1.respond_transaction(tx):
|
||||
outbound: OutboundMessage = _
|
||||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function == "maybe_transaction"
|
||||
assert outbound.message.function == "new_transaction"
|
||||
|
||||
sb = await full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
assert sb is spend_bundle
|
||||
|
@ -76,21 +78,23 @@ class TestMempool:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes_standard_freeze
|
||||
|
||||
block = blocks[1]
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
spend_bundle = wallet_a.generate_signed_transaction(
|
||||
1000, receiver_puzzlehash, block.body.coinbase
|
||||
)
|
||||
assert spend_bundle is not None
|
||||
tx: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle
|
||||
)
|
||||
|
||||
async for _ in full_node_1.transaction(tx):
|
||||
async for _ in full_node_1.respond_transaction(tx):
|
||||
outbound: OutboundMessage = _
|
||||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function != "maybe_transaction"
|
||||
assert outbound.message.function != "new_transaction"
|
||||
|
||||
sb = await full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
assert sb is None
|
||||
|
@ -100,13 +104,15 @@ class TestMempool:
|
|||
)
|
||||
|
||||
for i in range(1, 201):
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(blocks[i])):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(blocks[i])
|
||||
):
|
||||
pass
|
||||
|
||||
async for _ in full_node_1.transaction(tx):
|
||||
async for _ in full_node_1.respond_transaction(tx):
|
||||
outbound_2: OutboundMessage = _
|
||||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound_2.message.function == "maybe_transaction"
|
||||
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())
|
||||
assert sb is spend_bundle
|
||||
|
@ -125,7 +131,9 @@ class TestMempool:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
block = blocks[1]
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
spend_bundle1 = wallet_a.generate_signed_transaction(
|
||||
|
@ -133,23 +141,23 @@ class TestMempool:
|
|||
)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle1
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx1):
|
||||
async for _ in full_node_1.respond_transaction(tx1):
|
||||
outbound: OutboundMessage = _
|
||||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function == "maybe_transaction"
|
||||
assert outbound.message.function == "new_transaction"
|
||||
|
||||
other_receiver = WalletTool()
|
||||
spend_bundle2 = wallet_a.generate_signed_transaction(
|
||||
1000, other_receiver.get_new_puzzlehash(), block.body.coinbase
|
||||
)
|
||||
assert spend_bundle2 is not None
|
||||
tx2: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle2
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx2):
|
||||
async for _ in full_node_1.respond_transaction(tx2):
|
||||
pass
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
@ -172,30 +180,32 @@ class TestMempool:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
block = blocks[1]
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
spend_bundle1 = wallet_a.generate_signed_transaction(
|
||||
1000, receiver_puzzlehash, block.body.coinbase
|
||||
)
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle1
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx1):
|
||||
async for _ in full_node_1.respond_transaction(tx1):
|
||||
outbound: OutboundMessage = _
|
||||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function == "maybe_transaction"
|
||||
assert outbound.message.function == "new_transaction"
|
||||
|
||||
spend_bundle2 = wallet_a.generate_signed_transaction(
|
||||
1000, receiver_puzzlehash, block.body.coinbase, fee=1
|
||||
)
|
||||
|
||||
assert spend_bundle2 is not None
|
||||
tx2: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle2
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx2):
|
||||
async for _ in full_node_1.respond_transaction(tx2):
|
||||
pass
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
@ -218,7 +228,9 @@ class TestMempool:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
block = blocks[1]
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
cvp = ConditionVarPair(
|
||||
|
@ -233,13 +245,13 @@ class TestMempool:
|
|||
)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle1
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx1):
|
||||
async for _ in full_node_1.respond_transaction(tx1):
|
||||
outbound: OutboundMessage = _
|
||||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function != "maybe_transaction"
|
||||
assert outbound.message.function != "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -259,7 +271,9 @@ class TestMempool:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
block = blocks[1]
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
cvp = ConditionVarPair(
|
||||
|
@ -274,13 +288,13 @@ class TestMempool:
|
|||
)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle1
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx1):
|
||||
async for _ in full_node_1.respond_transaction(tx1):
|
||||
outbound: OutboundMessage = _
|
||||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function == "maybe_transaction"
|
||||
assert outbound.message.function == "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -300,7 +314,9 @@ class TestMempool:
|
|||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
block = blocks[1]
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(block)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(block)
|
||||
):
|
||||
pass
|
||||
|
||||
cvp = ConditionVarPair(
|
||||
|
@ -313,13 +329,13 @@ class TestMempool:
|
|||
)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle1
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx1):
|
||||
async for _ in full_node_1.respond_transaction(tx1):
|
||||
outbound: OutboundMessage = _
|
||||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function != "maybe_transaction"
|
||||
assert outbound.message.function != "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -341,7 +357,9 @@ class TestMempool:
|
|||
block = blocks[1]
|
||||
|
||||
for b in blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(b)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(b)
|
||||
):
|
||||
pass
|
||||
|
||||
cvp = ConditionVarPair(
|
||||
|
@ -354,13 +372,13 @@ class TestMempool:
|
|||
)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle1
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx1):
|
||||
async for _ in full_node_1.respond_transaction(tx1):
|
||||
outbound: OutboundMessage = _
|
||||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function == "maybe_transaction"
|
||||
assert outbound.message.function == "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -382,7 +400,9 @@ class TestMempool:
|
|||
block = blocks[1]
|
||||
|
||||
for b in blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(b)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(b)
|
||||
):
|
||||
pass
|
||||
|
||||
cvp = ConditionVarPair(
|
||||
|
@ -395,13 +415,13 @@ class TestMempool:
|
|||
)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle1
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx1):
|
||||
async for _ in full_node_1.respond_transaction(tx1):
|
||||
outbound: OutboundMessage = _
|
||||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function == "maybe_transaction"
|
||||
assert outbound.message.function == "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -423,7 +443,9 @@ class TestMempool:
|
|||
block = blocks[1]
|
||||
|
||||
for b in blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(b)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(b)
|
||||
):
|
||||
pass
|
||||
|
||||
cvp = ConditionVarPair(
|
||||
|
@ -436,13 +458,13 @@ class TestMempool:
|
|||
)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle1
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx1):
|
||||
async for _ in full_node_1.respond_transaction(tx1):
|
||||
outbound: OutboundMessage = _
|
||||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function != "maybe_transaction"
|
||||
assert outbound.message.function != "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -464,7 +486,9 @@ class TestMempool:
|
|||
block = blocks[1]
|
||||
|
||||
for b in blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(b)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(b)
|
||||
):
|
||||
pass
|
||||
|
||||
time_now = uint64(int(time() * 1000))
|
||||
|
@ -479,13 +503,13 @@ class TestMempool:
|
|||
)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle1
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx1):
|
||||
async for _ in full_node_1.respond_transaction(tx1):
|
||||
outbound: OutboundMessage = _
|
||||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound.message.function == "maybe_transaction"
|
||||
assert outbound.message.function == "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -507,7 +531,9 @@ class TestMempool:
|
|||
block = blocks[1]
|
||||
|
||||
for b in blocks:
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(b)):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(b)
|
||||
):
|
||||
pass
|
||||
|
||||
time_now = uint64(int(time() * 1000))
|
||||
|
@ -525,12 +551,12 @@ class TestMempool:
|
|||
)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle1
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx1):
|
||||
async for _ in full_node_1.respond_transaction(tx1):
|
||||
outbound: OutboundMessage = _
|
||||
assert outbound.message.function != "maybe_transaction"
|
||||
assert outbound.message.function != "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -538,13 +564,13 @@ class TestMempool:
|
|||
# Sleep so that 3 sec passes
|
||||
await asyncio.sleep(3)
|
||||
|
||||
tx2: full_node_protocol.NewTransaction = full_node_protocol.NewTransaction(
|
||||
tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
||||
spend_bundle1
|
||||
)
|
||||
async for _ in full_node_1.transaction(tx2):
|
||||
async for _ in full_node_1.respond_transaction(tx2):
|
||||
outbound_2: OutboundMessage = _
|
||||
# Maybe transaction means that it's accepted in mempool
|
||||
assert outbound_2.message.function == "maybe_transaction"
|
||||
assert outbound_2.message.function == "new_transaction"
|
||||
|
||||
sb1 = await full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
|
|
@ -30,7 +30,9 @@ class TestNodeLoad:
|
|||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10)
|
||||
|
||||
for i in range(1, num_blocks - 1):
|
||||
async for _ in full_node_1.block(full_node_protocol.Block(blocks[i])):
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(blocks[i])
|
||||
):
|
||||
pass
|
||||
|
||||
await server_2.start_client(
|
||||
|
@ -43,14 +45,15 @@ class TestNodeLoad:
|
|||
start_unf = time.time()
|
||||
for i in range(num_unfinished_blocks):
|
||||
msg = Message(
|
||||
"unfinished_block", full_node_protocol.UnfinishedBlock(blocks[9])
|
||||
"respond_unfinished_block",
|
||||
full_node_protocol.RespondUnfinishedBlock(blocks[9]),
|
||||
)
|
||||
server_1.push_message(
|
||||
OutboundMessage(NodeType.FULL_NODE, msg, Delivery.BROADCAST)
|
||||
)
|
||||
|
||||
# Send the whole block ast the end so we can detect when the node is done
|
||||
block_msg = Message("block", full_node_protocol.Block(blocks[9]))
|
||||
block_msg = Message("respond_block", full_node_protocol.RespondBlock(blocks[9]))
|
||||
server_1.push_message(
|
||||
OutboundMessage(NodeType.FULL_NODE, block_msg, Delivery.BROADCAST)
|
||||
)
|
||||
|
@ -82,7 +85,7 @@ class TestNodeLoad:
|
|||
|
||||
start_unf = time.time()
|
||||
for i in range(1, num_blocks):
|
||||
msg = Message("block", full_node_protocol.Block(blocks[i]))
|
||||
msg = Message("respond_block", full_node_protocol.RespondBlock(blocks[i]))
|
||||
server_1.push_message(
|
||||
OutboundMessage(NodeType.FULL_NODE, msg, Delivery.BROADCAST)
|
||||
)
|
||||
|
|
|
@ -17,7 +17,7 @@ def test_1():
|
|||
|
||||
conditions = [
|
||||
make_create_coin_condition(std_hash(bytes(pp)), amount)
|
||||
for pp, amount in [(puzzle_program_1, 1000), (puzzle_program_2, 2000), ]
|
||||
for pp, amount in [(puzzle_program_1, 1000), (puzzle_program_2, 2000),]
|
||||
]
|
||||
|
||||
assert conditions is not None
|
||||
|
|
|
@ -41,6 +41,7 @@ class TestStore:
|
|||
async def test_basic_store(self):
|
||||
assert sqlite3.threadsafety == 1
|
||||
blocks = bt.get_consecutive_blocks(test_constants, 9, [], 9, b"0")
|
||||
blocks_alt = bt.get_consecutive_blocks(test_constants, 3, [], 9, b"1")
|
||||
db_filename = Path("blockchain_test.db")
|
||||
db_filename_2 = Path("blockchain_test_2.db")
|
||||
db_filename_3 = Path("blockchain_test_3.db")
|
||||
|
@ -64,8 +65,11 @@ class TestStore:
|
|||
await db.add_block(block)
|
||||
assert block == await db.get_block(block.header_hash)
|
||||
|
||||
# Get headers
|
||||
assert len(await db.get_headers()) == len(blocks)
|
||||
await db.add_block(blocks_alt[2])
|
||||
assert len(await db.get_blocks_at([1, 2])) == 3
|
||||
|
||||
# Get headers (added alt block also, so +1)
|
||||
assert len(await db.get_headers()) == len(blocks) + 1
|
||||
|
||||
# Save/get sync
|
||||
for sync_mode in (False, True):
|
||||
|
@ -95,6 +99,16 @@ class TestStore:
|
|||
db.clear_candidate_blocks_below(uint32(8))
|
||||
assert db.get_candidate_block(blocks[5].header_hash) is None
|
||||
|
||||
# Proof of time heights
|
||||
chall_iters = (bytes32(bytes([1] * 32)), uint32(32532535))
|
||||
chall_iters_2 = (bytes32(bytes([3] * 32)), uint32(12522535))
|
||||
assert db.get_proof_of_time_heights(chall_iters) is None
|
||||
db.add_proof_of_time_heights(chall_iters, 5)
|
||||
db.add_proof_of_time_heights(chall_iters_2, 7)
|
||||
db.clear_proof_of_time_heights_below(6)
|
||||
assert db.get_proof_of_time_heights(chall_iters) is None
|
||||
assert db.get_proof_of_time_heights(chall_iters_2) is not None
|
||||
|
||||
# Add/get unfinished block
|
||||
i = 1
|
||||
for block in blocks:
|
||||
|
|
Loading…
Reference in New Issue