Coin store reorgs and mempool tests
This commit is contained in:
parent
81d523b850
commit
c018b26716
|
@ -601,16 +601,10 @@ async def validate_unfinished_header_block(
|
|||
else:
|
||||
our_sp_total_iters: uint128 = uint128(total_iters - ip_iters + sp_iters)
|
||||
if (our_sp_total_iters > curr.total_iters) != (header_block.foliage_sub_block.foliage_block_hash is not None):
|
||||
log.warning(
|
||||
f"HERE1... {header_block.foliage_sub_block.foliage_block_hash} {header_block.foliage_sub_block.foliage_block_signature is None}"
|
||||
)
|
||||
return None, ValidationError(Err.INVALID_IS_BLOCK)
|
||||
if (our_sp_total_iters > curr.total_iters) != (
|
||||
header_block.foliage_sub_block.foliage_block_signature is not None
|
||||
):
|
||||
log.warning(
|
||||
f"HERE2... {header_block.foliage_sub_block.foliage_block_hash} {header_block.foliage_sub_block.foliage_block_signature is None}"
|
||||
)
|
||||
return None, ValidationError(Err.INVALID_IS_BLOCK)
|
||||
|
||||
# 16. Check foliage sub block signature by plot key
|
||||
|
@ -644,13 +638,21 @@ async def validate_unfinished_header_block(
|
|||
):
|
||||
return None, ValidationError(Err.OLD_POOL_TARGET)
|
||||
|
||||
# 20. Check pool target signature
|
||||
if not AugSchemeMPL.verify(
|
||||
header_block.reward_chain_sub_block.proof_of_space.pool_public_key,
|
||||
bytes(header_block.foliage_sub_block.foliage_sub_block_data.pool_target),
|
||||
header_block.foliage_sub_block.foliage_sub_block_data.pool_signature,
|
||||
):
|
||||
return None, ValidationError(Err.INVALID_POOL_SIGNATURE)
|
||||
# 20a. Check pre-farm puzzle hash for genesis sub-block.
|
||||
if genesis_block:
|
||||
if (
|
||||
header_block.foliage_sub_block.foliage_sub_block_data.pool_target.puzzle_hash
|
||||
!= constants.GENESIS_PRE_FARM_POOL_PUZZLE_HASH
|
||||
):
|
||||
return None, ValidationError(Err.INVALID_PREFARM)
|
||||
else:
|
||||
# 20b. Check pool target signature. Should not check this for genesis sub-block.
|
||||
if not AugSchemeMPL.verify(
|
||||
header_block.reward_chain_sub_block.proof_of_space.pool_public_key,
|
||||
bytes(header_block.foliage_sub_block.foliage_sub_block_data.pool_target),
|
||||
header_block.foliage_sub_block.foliage_sub_block_data.pool_signature,
|
||||
):
|
||||
return None, ValidationError(Err.INVALID_POOL_SIGNATURE)
|
||||
|
||||
# 21. Check extension data if applicable. None for mainnet.
|
||||
# 22. Check if foliage block is present
|
||||
|
|
|
@ -236,15 +236,23 @@ class Blockchain:
|
|||
if sub_block.weight > self.get_peak().weight:
|
||||
# Find the fork. if the block is just being appended, it will return the peak
|
||||
# If no blocks in common, returns -1, and reverts all blocks
|
||||
fork_h: int = find_fork_point_in_chain(self.sub_blocks, sub_block, self.get_peak())
|
||||
fork_sub_block_height: int = find_fork_point_in_chain(self.sub_blocks, sub_block, self.get_peak())
|
||||
if fork_sub_block_height == -1:
|
||||
coin_store_reorg_height = -1
|
||||
else:
|
||||
last_sb_in_common = self.sub_blocks[self.sub_height_to_hash[uint32(fork_sub_block_height)]]
|
||||
if last_sb_in_common.is_block:
|
||||
coin_store_reorg_height = last_sb_in_common.prev_block_height + 1
|
||||
else:
|
||||
coin_store_reorg_height = last_sb_in_common.prev_block_height
|
||||
|
||||
# Rollback to fork
|
||||
await self.coin_store.rollback_to_block(fork_h)
|
||||
await self.coin_store.rollback_to_block(coin_store_reorg_height)
|
||||
|
||||
# Rollback sub_epoch_summaries
|
||||
heights_to_delete = []
|
||||
for ses_included_height in self.sub_epoch_summaries.keys():
|
||||
if ses_included_height > fork_h:
|
||||
if ses_included_height > fork_sub_block_height:
|
||||
heights_to_delete.append(ses_included_height)
|
||||
for sub_height in heights_to_delete:
|
||||
del self.sub_epoch_summaries[sub_height]
|
||||
|
@ -252,7 +260,7 @@ class Blockchain:
|
|||
# Collect all blocks from fork point to new peak
|
||||
blocks_to_add: List[Tuple[FullBlock, SubBlockRecord]] = []
|
||||
curr = sub_block.header_hash
|
||||
while fork_h < 0 or curr != self.sub_height_to_hash[uint32(fork_h)]:
|
||||
while fork_sub_block_height < 0 or curr != self.sub_height_to_hash[uint32(fork_sub_block_height)]:
|
||||
fetched_block: Optional[FullBlock] = await self.block_store.get_full_block(curr)
|
||||
fetched_sub_block: Optional[SubBlockRecord] = await self.block_store.get_sub_block_record(curr)
|
||||
assert fetched_block is not None
|
||||
|
@ -273,7 +281,7 @@ class Blockchain:
|
|||
# Changes the peak to be the new peak
|
||||
await self.block_store.set_peak(sub_block.header_hash)
|
||||
self.peak_height = sub_block.sub_block_height
|
||||
return uint32(max(fork_h, 0))
|
||||
return uint32(max(fork_sub_block_height, 0))
|
||||
|
||||
# This is not a heavier block than the heaviest we have seen, so we don't change the coin set
|
||||
return None
|
||||
|
|
|
@ -95,6 +95,7 @@ class CoinStore:
|
|||
"SELECT * from coin_record WHERE puzzle_hash=?", (puzzle_hash.hex(),)
|
||||
)
|
||||
rows = await cursor.fetchall()
|
||||
|
||||
await cursor.close()
|
||||
for row in rows:
|
||||
coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), row[7])
|
||||
|
|
|
@ -430,7 +430,7 @@ class FullNode:
|
|||
self._state_changed("sub_block")
|
||||
|
||||
async def respond_sub_block(
|
||||
self, respond_sub_block: full_node_protocol.RespondSubBlock
|
||||
self, respond_sub_block: full_node_protocol.RespondSubBlock, peer: Optional[ws.WSChiaConnection] = None
|
||||
):
|
||||
"""
|
||||
Receive a full block from a peer full node (or ourselves).
|
||||
|
@ -572,7 +572,10 @@ class FullNode:
|
|||
sub_block.reward_chain_sub_block.get_unfinished().get_hash(),
|
||||
),
|
||||
)
|
||||
await self.server.send_to_all([msg], NodeType.FULL_NODE)
|
||||
if peer is not None:
|
||||
await self.server.send_to_all_except([msg], NodeType.FULL_NODE, peer.peer_node_id)
|
||||
else:
|
||||
await self.server.send_to_all([msg], NodeType.FULL_NODE)
|
||||
|
||||
# Tell wallets about the new peak
|
||||
msg = Message(
|
||||
|
|
|
@ -4,7 +4,7 @@ import time
|
|||
import src.server.ws_connection as ws
|
||||
from typing import AsyncGenerator, List, Optional, Tuple, Callable
|
||||
from chiabip158 import PyBIP158
|
||||
from blspy import G2Element
|
||||
from blspy import G2Element, AugSchemeMPL
|
||||
|
||||
from src.consensus.block_creation import unfinished_block_to_full_block, create_unfinished_block
|
||||
from src.consensus.difficulty_adjustment import get_sub_slot_iters_and_difficulty
|
||||
|
@ -32,12 +32,13 @@ from src.types.full_block import FullBlock
|
|||
|
||||
from src.types.mempool_inclusion_status import MempoolInclusionStatus
|
||||
from src.types.mempool_item import MempoolItem
|
||||
from src.types.pool_target import PoolTarget
|
||||
from src.types.sized_bytes import bytes32
|
||||
from src.types.spend_bundle import SpendBundle
|
||||
from src.types.unfinished_block import UnfinishedBlock
|
||||
from src.util.api_decorators import api_request, peer_required
|
||||
from src.util.errors import ConsensusError
|
||||
from src.util.ints import uint64, uint128, uint8
|
||||
from src.util.ints import uint64, uint128, uint8, uint32
|
||||
from src.types.peer_info import PeerInfo
|
||||
|
||||
OutboundMessageGenerator = AsyncGenerator[OutboundMessage, None]
|
||||
|
@ -201,11 +202,14 @@ class FullNodeAPI:
|
|||
return
|
||||
|
||||
@api_request
|
||||
async def respond_sub_block(self, respond_sub_block: full_node_protocol.RespondSubBlock) -> Optional[Message]:
|
||||
@peer_required
|
||||
async def respond_sub_block(
|
||||
self, respond_sub_block: full_node_protocol.RespondSubBlock, peer: ws.WSChiaConnection
|
||||
) -> Optional[Message]:
|
||||
"""
|
||||
Receive a full block from a peer full node (or ourselves).
|
||||
"""
|
||||
return await self.full_node.respond_sub_block(respond_sub_block)
|
||||
return await self.full_node.respond_sub_block(respond_sub_block, peer)
|
||||
|
||||
@api_request
|
||||
async def new_unfinished_sub_block(
|
||||
|
@ -572,6 +576,7 @@ class FullNodeAPI:
|
|||
|
||||
# Get the previous sub block at the signage point
|
||||
if peak is not None:
|
||||
pool_target = request.pool_target
|
||||
curr = peak
|
||||
while curr.total_iters > (total_iters_pos_slot + sp_iters) and curr.sub_block_height > 0:
|
||||
curr = self.full_node.blockchain.sub_blocks[curr.prev_hash]
|
||||
|
@ -580,6 +585,7 @@ class FullNodeAPI:
|
|||
else:
|
||||
prev_sb = curr
|
||||
else:
|
||||
pool_target = PoolTarget(self.full_node.constants.GENESIS_PRE_FARM_POOL_PUZZLE_HASH, uint32(0))
|
||||
prev_sb = None
|
||||
|
||||
finished_sub_slots: List[EndOfSubSlotBundle] = self.full_node.full_node_store.get_finished_sub_slots(
|
||||
|
@ -623,7 +629,7 @@ class FullNodeAPI:
|
|||
request.proof_of_space,
|
||||
cc_challenge_hash,
|
||||
request.farmer_puzzle_hash,
|
||||
request.pool_target,
|
||||
pool_target,
|
||||
get_plot_sig,
|
||||
get_pool_sig,
|
||||
sp_vdfs,
|
||||
|
@ -713,13 +719,13 @@ class FullNodeAPI:
|
|||
curr: Optional[SubBlockRecord] = self.full_node.blockchain.get_peak()
|
||||
|
||||
for _ in range(10):
|
||||
if curr is None:
|
||||
break
|
||||
if curr.reward_infusion_new_challenge == target_rc_hash:
|
||||
# Found our prev block
|
||||
prev_sb = curr
|
||||
break
|
||||
if self.full_node.blockchain.sub_blocks.get(curr.prev_hash, None) is None:
|
||||
self.log.warning(f"Did not find previous reward chain hash {target_rc_hash}")
|
||||
return
|
||||
curr = self.full_node.blockchain.sub_blocks.get(curr.prev_hash, None)
|
||||
|
||||
# If not found, cache keyed on prev block
|
||||
if prev_sb is None:
|
||||
|
@ -778,6 +784,18 @@ class FullNodeAPI:
|
|||
difficulty,
|
||||
)
|
||||
first_ss_new_epoch = False
|
||||
if (
|
||||
block.foliage_sub_block.foliage_sub_block_data.pool_target
|
||||
== PoolTarget(self.full_node.constants.GENESIS_PRE_FARM_POOL_PUZZLE_HASH, uint32(0))
|
||||
and block.sub_block_height != 0
|
||||
):
|
||||
if not AugSchemeMPL.verify(
|
||||
block.reward_chain_sub_block.proof_of_space.pool_public_key,
|
||||
bytes(block.foliage_sub_block.foliage_sub_block_data.pool_target),
|
||||
block.foliage_sub_block.foliage_sub_block_data.pool_signature,
|
||||
):
|
||||
self.log.warning("Trying to make a pre-farm block but height is not 0")
|
||||
return
|
||||
if len(block.finished_sub_slots) > 0:
|
||||
if block.finished_sub_slots[0].challenge_chain.new_difficulty is not None:
|
||||
first_ss_new_epoch = True
|
||||
|
@ -796,7 +814,7 @@ class FullNodeAPI:
|
|||
# No overflow sub-blocks in the first sub-slot of each epoch
|
||||
return
|
||||
try:
|
||||
await self.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await self.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
except ConsensusError as e:
|
||||
self.log.warning(f"Consensus error validating sub-block: {e}")
|
||||
|
||||
|
|
|
@ -10,20 +10,21 @@ class FarmerRpcApi:
|
|||
self.service_name = "chia_farmer"
|
||||
|
||||
def get_routes(self) -> Dict[str, Callable]:
|
||||
return {"/get_latest_challenges": self.get_latest_challenges}
|
||||
# return {"/get_latest_challenges": self.get_latest_challenges}
|
||||
return {}
|
||||
|
||||
async def _state_changed(self, change: str) -> List[Dict]:
|
||||
if change == "signage_point":
|
||||
data = await self.get_latest_challenges({})
|
||||
return [
|
||||
create_payload(
|
||||
"get_latest_challenges",
|
||||
data,
|
||||
self.service_name,
|
||||
"wallet_ui",
|
||||
string=False,
|
||||
)
|
||||
]
|
||||
# if change == "signage_point":
|
||||
# data = await self.get_latest_challenges({})
|
||||
# return [
|
||||
# create_payload(
|
||||
# "get_latest_challenges",
|
||||
# data,
|
||||
# self.service_name,
|
||||
# "wallet_ui",
|
||||
# string=False,
|
||||
# )
|
||||
# ]
|
||||
return []
|
||||
|
||||
async def get_signage_point(self, request: Dict) -> Dict:
|
||||
|
|
|
@ -282,7 +282,7 @@ class ChiaServer:
|
|||
raise ProtocolError(Err.INVALID_PROTOCOL_MESSAGE, [full_message.function])
|
||||
|
||||
if not hasattr(f, "api_function"):
|
||||
self.log.error("Peer trying to call non api function")
|
||||
self.log.error(f"Peer trying to call non api function {full_message.function}")
|
||||
raise ProtocolError(Err.INVALID_PROTOCOL_MESSAGE, [full_message.function])
|
||||
|
||||
if hasattr(f, "peer_required"):
|
||||
|
|
|
@ -690,6 +690,11 @@ class Timelord:
|
|||
is_block = self.last_state.get_last_block_total_iters() < sp_total_iters
|
||||
sub_block_height: uint32 = self.last_state.get_height() + 1
|
||||
|
||||
if sub_block_height < 10:
|
||||
# Don't directly update our state for the first few sub-blocks, because we cannot validate
|
||||
# whether the pre-farm is correct
|
||||
return
|
||||
|
||||
new_reward_chain_sub_block = RewardChainSubBlock(
|
||||
self.last_state.get_weight() + block.difficulty,
|
||||
sub_block_height,
|
||||
|
|
|
@ -65,9 +65,9 @@ class FullBlock(Streamable):
|
|||
def is_block(self):
|
||||
return self.foliage_sub_block.foliage_block_hash is not None
|
||||
|
||||
def get_future_reward_coins(self) -> Tuple[Coin, Coin]:
|
||||
pool_amount = calculate_pool_reward(self.height)
|
||||
farmer_amount = calculate_base_farmer_reward(self.height)
|
||||
def get_future_reward_coins(self, prev_block_height: uint32) -> Tuple[Coin, Coin]:
|
||||
pool_amount = calculate_pool_reward(prev_block_height + 1, self.sub_block_height == 0)
|
||||
farmer_amount = calculate_base_farmer_reward(prev_block_height + 1)
|
||||
if self.is_block():
|
||||
assert self.transactions_info is not None
|
||||
farmer_amount += self.transactions_info.fees
|
||||
|
|
|
@ -224,6 +224,7 @@ class BlockTools:
|
|||
skip_slots: uint32 = uint32(0), # Force at least this number of empty slots before the first SB
|
||||
guarantee_block: bool = False, # Force that this sub-block must be a block
|
||||
) -> List[FullBlock]:
|
||||
assert num_blocks > 0
|
||||
if block_list_input is not None:
|
||||
block_list = block_list_input.copy()
|
||||
else:
|
||||
|
@ -577,6 +578,8 @@ class BlockTools:
|
|||
|
||||
if sub_block_record.is_block:
|
||||
transaction_data_included = True
|
||||
elif guarantee_block:
|
||||
continue
|
||||
if pending_ses:
|
||||
pending_ses = False
|
||||
|
||||
|
|
|
@ -127,6 +127,7 @@ class Err(Enum):
|
|||
INVALID_SP_INDEX = 101
|
||||
TOO_MANY_SUB_BLOCKS = 102
|
||||
INVALID_CC_CHALLENGE = 103
|
||||
INVALID_PREFARM = 104
|
||||
|
||||
|
||||
class ValidationError(Exception):
|
||||
|
|
|
@ -82,6 +82,8 @@ timelord:
|
|||
vdf_clients:
|
||||
ip:
|
||||
- *self_hostname
|
||||
- localhost
|
||||
- 127.0.0.1
|
||||
ips_estimate:
|
||||
- 150000
|
||||
full_node_peer:
|
||||
|
|
|
@ -1083,9 +1083,21 @@ class TestBlockHeaderValidation:
|
|||
block_bad = recursive_replace(block_bad, "foliage_sub_block.foliage_sub_block_signature", new_fsb_sig)
|
||||
assert (await empty_blockchain.receive_block(block_bad))[1] == Err.OLD_POOL_TARGET
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pool_target_pre_farm(self, empty_blockchain):
|
||||
# 20a
|
||||
blocks = bt.get_consecutive_blocks(1)
|
||||
block_bad: FullBlock = recursive_replace(
|
||||
blocks[-1], "foliage_sub_block.foliage_sub_block_data.pool_target.puzzle_hash", std_hash(b"12")
|
||||
)
|
||||
new_m = block_bad.foliage_sub_block.foliage_sub_block_data.get_hash()
|
||||
new_fsb_sig = bt.get_plot_signature(new_m, blocks[-1].reward_chain_sub_block.proof_of_space.plot_public_key)
|
||||
block_bad = recursive_replace(block_bad, "foliage_sub_block.foliage_sub_block_signature", new_fsb_sig)
|
||||
assert (await empty_blockchain.receive_block(block_bad))[1] == Err.INVALID_PREFARM
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pool_target_signature(self, empty_blockchain):
|
||||
# 18
|
||||
# 20b
|
||||
blocks = bt.get_consecutive_blocks(3)
|
||||
assert (await empty_blockchain.receive_block(blocks[0]))[0] == ReceiveBlockResult.NEW_PEAK
|
||||
assert (await empty_blockchain.receive_block(blocks[1]))[0] == ReceiveBlockResult.NEW_PEAK
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -227,7 +227,7 @@ class TestCoinStore:
|
|||
@pytest.mark.asyncio
|
||||
async def test_get_puzzle_hash(self):
|
||||
num_blocks = 10
|
||||
blocks = bt.get_consecutive_blocks(num_blocks)
|
||||
blocks = bt.get_consecutive_blocks(num_blocks, guarantee_block=True)
|
||||
db_path = Path("blockchain_test.db")
|
||||
if db_path.exists():
|
||||
db_path.unlink()
|
||||
|
@ -235,20 +235,21 @@ class TestCoinStore:
|
|||
coin_store = await CoinStore.create(connection)
|
||||
store = await BlockStore.create(connection)
|
||||
b: Blockchain = await Blockchain.create(coin_store, store, test_constants)
|
||||
try:
|
||||
for block in blocks:
|
||||
await b.receive_block(block)
|
||||
assert b.get_peak().height == num_blocks - 1
|
||||
last_block_height = 0
|
||||
for block in blocks:
|
||||
res, err, _ = await b.receive_block(block)
|
||||
assert err is None
|
||||
assert res == ReceiveBlockResult.NEW_PEAK
|
||||
if block.is_block() and block.header_hash != blocks[-1].header_hash:
|
||||
last_block_height = block.height
|
||||
assert b.get_peak().sub_block_height == num_blocks - 1
|
||||
|
||||
farmer_coin, pool_coin = blocks[-1].get_future_reward_coins()
|
||||
pool_coin, farmer_coin = blocks[-2].get_future_reward_coins(last_block_height)
|
||||
|
||||
coins = await coin_store.get_coin_records_by_puzzle_hash(farmer_coin.puzzle_hash)
|
||||
assert len(coins) > 2
|
||||
except Exception as e:
|
||||
await connection.close()
|
||||
Path("blockchain_test.db").unlink()
|
||||
b.shut_down()
|
||||
raise e
|
||||
coins_farmer = await coin_store.get_coin_records_by_puzzle_hash(farmer_coin.puzzle_hash)
|
||||
coins_pool = await coin_store.get_coin_records_by_puzzle_hash(pool_coin.puzzle_hash)
|
||||
assert len(coins_farmer) == num_blocks - 1
|
||||
assert len(coins_pool) == num_blocks - 2
|
||||
|
||||
await connection.close()
|
||||
Path("blockchain_test.db").unlink()
|
||||
|
|
|
@ -35,6 +35,7 @@ from src.util.merkle_set import (
|
|||
from tests.setup_nodes import setup_two_nodes, test_constants, bt
|
||||
from src.util.wallet_tools import WalletTool
|
||||
from src.util.clvm import int_to_bytes
|
||||
from tests.full_node.test_full_sync import node_height_at_least
|
||||
from tests.time_out_assert import time_out_assert, time_out_assert_custom_interval, time_out_messages
|
||||
from src.protocols.shared_protocol import protocol_version
|
||||
|
||||
|
@ -93,7 +94,7 @@ def event_loop():
|
|||
yield loop
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
@pytest.fixture(scope="function")
|
||||
async def two_nodes():
|
||||
zero_free_constants = test_constants.replace(COINBASE_FREEZE_PERIOD=0)
|
||||
async for _ in setup_two_nodes(zero_free_constants):
|
||||
|
@ -107,18 +108,25 @@ async def two_empty_nodes():
|
|||
yield _
|
||||
|
||||
|
||||
async def wb(num_blocks, two_nodes):
|
||||
async def wb(num_blocks, two_nodes, guarantee_block=False):
|
||||
full_node_1, _, _, _ = two_nodes
|
||||
wallet_a = bt.get_pool_wallet_tool()
|
||||
wallet_receiver = WalletTool()
|
||||
blocks = bt.get_consecutive_blocks(num_blocks)
|
||||
farmer_ph = wallet_a.get_new_puzzlehash()
|
||||
pool_ph = wallet_a.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
num_blocks,
|
||||
guarantee_block=guarantee_block,
|
||||
farmer_reward_puzzle_hash=farmer_ph,
|
||||
pool_reward_puzzle_hash=pool_ph,
|
||||
)
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(fnp.RespondSubBlock(block))
|
||||
|
||||
return wallet_a, wallet_receiver, blocks
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
@pytest.fixture(scope="function")
|
||||
async def wallet_blocks(two_nodes):
|
||||
"""
|
||||
Sets up the node with 3 blocks, and returns a payer and payee wallet.
|
||||
|
@ -126,11 +134,16 @@ async def wallet_blocks(two_nodes):
|
|||
return await wb(3, two_nodes)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
@pytest.fixture(scope="function")
|
||||
async def wallet_blocks_five(two_nodes):
|
||||
return await wb(5, two_nodes)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
async def wallet_blocks_five_blocks(two_nodes):
|
||||
return await wb(5, two_nodes, True)
|
||||
|
||||
|
||||
class TestFullNodeProtocol:
|
||||
@pytest.mark.asyncio
|
||||
async def test_request_peers(self, two_empty_nodes):
|
||||
|
@ -161,16 +174,17 @@ class TestFullNodeProtocol:
|
|||
|
||||
incoming_queue, _ = await add_dummy_connection(server_1, 12312)
|
||||
await time_out_assert(10, time_out_messages(incoming_queue, "request_mempool_transactions", 1))
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
blocks = bt.get_consecutive_blocks(1)
|
||||
for block in blocks[:1]:
|
||||
await full_node_1.respond_sub_block(fnp.RespondSubBlock(block))
|
||||
await full_node_1.respond_sub_block(fnp.RespondSubBlock(block), peer)
|
||||
|
||||
await time_out_assert(10, time_out_messages(incoming_queue, "new_peak", 1))
|
||||
|
||||
assert full_node_1.full_node.blockchain.get_peak().height == 0
|
||||
|
||||
for block in bt.get_consecutive_blocks(30):
|
||||
await full_node_1.respond_sub_block(fnp.RespondSubBlock(block))
|
||||
await full_node_1.respond_sub_block(fnp.RespondSubBlock(block), peer)
|
||||
|
||||
assert full_node_1.full_node.blockchain.get_peak().height == 29
|
||||
|
||||
|
@ -203,7 +217,7 @@ class TestFullNodeProtocol:
|
|||
# Add some blocks
|
||||
blocks = bt.get_consecutive_blocks(5)
|
||||
for block in blocks:
|
||||
await full_node_1.respond_sub_block(fnp.RespondSubBlock(block))
|
||||
await full_node_1.respond_sub_block(fnp.RespondSubBlock(block), peer)
|
||||
await time_out_assert(10, time_out_messages(incoming_queue, "new_peak", 5))
|
||||
blocks = bt.get_consecutive_blocks(1, skip_slots=2, block_list_input=blocks)
|
||||
|
||||
|
@ -222,6 +236,7 @@ class TestFullNodeProtocol:
|
|||
incoming_queue, dummy_node_id = await add_dummy_connection(server_1, 12312)
|
||||
|
||||
await time_out_assert(10, time_out_messages(incoming_queue, "request_mempool_transactions", 1))
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
blocks = bt.get_consecutive_blocks(10)
|
||||
blocks_reorg = bt.get_consecutive_blocks(10, seed=b"214") # Alternate chain
|
||||
|
@ -237,7 +252,7 @@ class TestFullNodeProtocol:
|
|||
message = await full_node_1.new_peak(new_peak)
|
||||
assert message is not None
|
||||
|
||||
await full_node_1.respond_sub_block(fnp.RespondSubBlock(block))
|
||||
await full_node_1.respond_sub_block(fnp.RespondSubBlock(block), peer)
|
||||
# Ignores, already have
|
||||
message = await full_node_1.new_peak(new_peak)
|
||||
assert message is None
|
||||
|
@ -265,10 +280,10 @@ class TestFullNodeProtocol:
|
|||
assert message is not None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_new_transaction(self, two_nodes, wallet_blocks_five):
|
||||
async def test_new_transaction(self, two_nodes, wallet_blocks_five_blocks):
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
wallet_a, wallet_receiver, blocks = wallet_blocks_five
|
||||
assert full_node_1.full_node.blockchain.get_peak().height == 4
|
||||
wallet_a, wallet_receiver, blocks = wallet_blocks_five_blocks
|
||||
assert full_node_1.full_node.blockchain.get_peak().sub_block_height == 4
|
||||
conditions_dict: Dict = {ConditionOpcode.CREATE_COIN: []}
|
||||
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
@ -304,7 +319,7 @@ class TestFullNodeProtocol:
|
|||
await full_node_1.respond_transaction(respond_transaction_2, peer)
|
||||
|
||||
blocks_new = bt.get_consecutive_blocks(
|
||||
1, block_list_input=blocks, guarantee_block=True, transaction_data=spend_bundle
|
||||
2, block_list_input=blocks, guarantee_block=True, transaction_data=spend_bundle
|
||||
)
|
||||
|
||||
# Already seen
|
||||
|
@ -312,7 +327,9 @@ class TestFullNodeProtocol:
|
|||
assert msg is None
|
||||
# Farm one block
|
||||
for block in blocks_new:
|
||||
await full_node_1.respond_sub_block(fnp.RespondSubBlock(block))
|
||||
await full_node_1.respond_sub_block(fnp.RespondSubBlock(block), peer)
|
||||
|
||||
await time_out_assert(10, node_height_at_least, True, full_node_1, 6)
|
||||
|
||||
spend_bundles = []
|
||||
# Fill mempool
|
||||
|
@ -344,7 +361,7 @@ class TestFullNodeProtocol:
|
|||
guarantee_block=True,
|
||||
)
|
||||
# Farm one block to clear mempool
|
||||
await full_node_1.respond_sub_block(fnp.RespondSubBlock(blocks_new[-1]))
|
||||
await full_node_1.respond_sub_block(fnp.RespondSubBlock(blocks_new[-1]), peer)
|
||||
|
||||
# No longer full
|
||||
new_transaction = fnp.NewTransaction(token_bytes(32), uint64(1000000), uint64(1))
|
||||
|
@ -352,13 +369,14 @@ class TestFullNodeProtocol:
|
|||
assert msg is not None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_request_respond_transaction(self, two_nodes, wallet_blocks_five):
|
||||
async def test_request_respond_transaction(self, two_nodes, wallet_blocks_five_blocks):
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
wallet_a, wallet_receiver, blocks = wallet_blocks_five
|
||||
wallet_a, wallet_receiver, blocks = wallet_blocks_five_blocks
|
||||
|
||||
incoming_queue, dummy_node_id = await add_dummy_connection(server_1, 12312)
|
||||
|
||||
await time_out_assert(10, time_out_messages(incoming_queue, "request_mempool_transactions", 1))
|
||||
await time_out_assert(10, time_out_messages(incoming_queue, "new_peak"))
|
||||
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
|
@ -368,8 +386,11 @@ class TestFullNodeProtocol:
|
|||
assert msg is None
|
||||
|
||||
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
||||
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_2, 4)
|
||||
await asyncio.sleep(4)
|
||||
spend_bundle = wallet_a.generate_signed_transaction(
|
||||
100, receiver_puzzlehash, blocks[2].get_future_reward_coins()[0]
|
||||
100, receiver_puzzlehash, list(blocks[2].get_included_reward_coins())[0]
|
||||
)
|
||||
assert spend_bundle is not None
|
||||
respond_transaction = fnp.RespondTransaction(spend_bundle)
|
||||
|
@ -644,7 +665,7 @@ class TestFullNodeProtocol:
|
|||
# assert res.data == fnp.RejectBlockRequest(uint32(1), bytes([0] * 32))
|
||||
#
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_respond_sub_block(self, two_nodes, wallet_blocks):
|
||||
# async def testrespond_sub_block(self, two_nodes, wallet_blocks):
|
||||
# full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
# wallet_a, wallet_receiver, blocks = wallet_blocks
|
||||
#
|
||||
|
|
|
@ -17,7 +17,9 @@ from src.util.condition_tools import (
|
|||
)
|
||||
from src.util.clvm import int_to_bytes
|
||||
from src.util.ints import uint64
|
||||
from tests.full_node.test_full_node import connect_and_get_peer, node_height_at_least
|
||||
from tests.setup_nodes import setup_two_nodes, test_constants, bt
|
||||
from tests.time_out_assert import time_out_assert
|
||||
|
||||
BURN_PUZZLE_HASH = b"0" * 32
|
||||
BURN_PUZZLE_HASH_2 = b"1" * 32
|
||||
|
@ -60,146 +62,171 @@ class TestMempool:
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_basic_mempool(self, two_nodes):
|
||||
num_blocks = 2
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
full_node_api, full_node_2, server_1, server_2 = two_nodes
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
block = blocks[1]
|
||||
await full_node_api.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
|
||||
spend_bundle = generate_test_spend_bundle(block.get_coinbase())
|
||||
spend_bundle = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0])
|
||||
assert spend_bundle is not None
|
||||
tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle)
|
||||
await full_node_api.respond_transaction(tx)
|
||||
await full_node_1.respond_transaction(tx, peer)
|
||||
|
||||
sb = full_node_api.full_node.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
assert sb is spend_bundle
|
||||
await time_out_assert(
|
||||
10, full_node_1.full_node.mempool_manager.get_spendbundle, spend_bundle, spend_bundle.name()
|
||||
)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_coinbase_freeze(self, two_nodes_small_freeze):
|
||||
num_blocks = 2
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes_small_freeze
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
full_node_api, full_node_2, server_1, server_2 = two_nodes_small_freeze
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
|
||||
block = blocks[1]
|
||||
await full_node_api.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
spend_bundle = generate_test_spend_bundle(block.get_coinbase())
|
||||
spend_bundle = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0])
|
||||
assert spend_bundle is not None
|
||||
tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle)
|
||||
|
||||
await full_node_api.respond_transaction(tx)
|
||||
await full_node_1.respond_transaction(tx, peer)
|
||||
|
||||
sb = full_node_api.full_node.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
sb = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
assert sb is None
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, 30, [], 10, b"")
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
30,
|
||||
block_list_input=blocks,
|
||||
guarantee_block=True,
|
||||
farmer_reward_puzzle_hash=reward_ph,
|
||||
pool_reward_puzzle_hash=reward_ph,
|
||||
)
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 32)
|
||||
|
||||
for i in range(1, 31):
|
||||
await full_node_api.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(blocks[i]))
|
||||
await full_node_1.respond_transaction(tx, peer)
|
||||
|
||||
await full_node_api.respond_transaction(tx)
|
||||
|
||||
sb = full_node_api.full_node.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
sb = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
assert sb is spend_bundle
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_double_spend(self, two_nodes):
|
||||
num_blocks = 2
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
full_node_api, full_node_2, server_1, server_2 = two_nodes
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
|
||||
block = blocks[1]
|
||||
await full_node_api.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase())
|
||||
spend_bundle1 = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0])
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
await full_node_api.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
spend_bundle2 = generate_test_spend_bundle(
|
||||
block.get_coinbase(),
|
||||
newpuzzlehash=BURN_PUZZLE_HASH_2,
|
||||
list(blocks[-1].get_included_reward_coins())[0], newpuzzlehash=BURN_PUZZLE_HASH_2
|
||||
)
|
||||
assert spend_bundle2 is not None
|
||||
tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle2)
|
||||
await full_node_api.respond_transaction(tx2)
|
||||
await full_node_1.respond_transaction(tx2, peer)
|
||||
|
||||
sb1 = full_node_api.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb2 = full_node_api.full_node.mempool_manager.get_spendbundle(spend_bundle2.name())
|
||||
sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb2 = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle2.name())
|
||||
|
||||
assert sb1 == spend_bundle1
|
||||
assert sb2 is None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_double_spend_with_higher_fee(self, two_nodes):
|
||||
num_blocks = 2
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
full_node_api, full_node_2, server_1, server_2 = two_nodes
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
|
||||
block = blocks[1]
|
||||
await full_node_api.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase())
|
||||
spend_bundle1 = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0])
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
|
||||
await full_node_api.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
spend_bundle2 = generate_test_spend_bundle(block.get_coinbase(), fee=1)
|
||||
spend_bundle2 = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0], fee=1)
|
||||
|
||||
assert spend_bundle2 is not None
|
||||
tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle2)
|
||||
|
||||
await full_node_api.respond_transaction(tx2)
|
||||
await full_node_1.respond_transaction(tx2, peer)
|
||||
|
||||
sb1 = full_node_api.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb2 = full_node_api.full_node.mempool_manager.get_spendbundle(spend_bundle2.name())
|
||||
sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb2 = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle2.name())
|
||||
|
||||
assert sb1 is None
|
||||
assert sb2 == spend_bundle2
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_invalid_block_index(self, two_nodes):
|
||||
num_blocks = 2
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
full_node_api, full_node_2, server_1, server_2 = two_nodes
|
||||
|
||||
block = blocks[1]
|
||||
await full_node_api.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
|
||||
cvp = ConditionVarPair(
|
||||
ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS,
|
||||
uint64(2).to_bytes(4, "big"),
|
||||
uint64(4).to_bytes(4, "big"),
|
||||
None,
|
||||
)
|
||||
dic = {ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS: [cvp]}
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic)
|
||||
spend_bundle1 = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0], dic)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
await full_node_api.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
sb1 = full_node_api.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
assert sb1 is None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_correct_block_index(self, two_nodes):
|
||||
num_blocks = 2
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
block = blocks[1]
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
|
||||
cvp = ConditionVarPair(
|
||||
ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS,
|
||||
|
@ -208,11 +235,11 @@ class TestMempool:
|
|||
)
|
||||
dic = {ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS: [cvp]}
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic)
|
||||
spend_bundle1 = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0], dic)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
await full_node_1.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -220,46 +247,52 @@ class TestMempool:
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_invalid_block_age(self, two_nodes):
|
||||
num_blocks = 2
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
block = blocks[1]
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
|
||||
cvp = ConditionVarPair(ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS, uint64(5).to_bytes(4, "big"), None)
|
||||
dic = {cvp.opcode: [cvp]}
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic)
|
||||
spend_bundle1 = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0], dic)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
await full_node_1.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
assert sb1 is None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_correct_block_age(self, two_nodes):
|
||||
num_blocks = 4
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
4, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
block = blocks[1]
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
for b in blocks:
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(b))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 3)
|
||||
|
||||
cvp = ConditionVarPair(ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS, uint64(3).to_bytes(4, "big"), None)
|
||||
cvp = ConditionVarPair(ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS, uint64(1).to_bytes(4, "big"), None)
|
||||
dic = {cvp.opcode: [cvp]}
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic)
|
||||
spend_bundle1 = generate_test_spend_bundle(list(blocks[-2].get_included_reward_coins())[0], dic)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
await full_node_1.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -267,24 +300,27 @@ class TestMempool:
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_correct_my_id(self, two_nodes):
|
||||
num_blocks = 2
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
block = blocks[1]
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
for b in blocks:
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(b))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
|
||||
cvp = ConditionVarPair(ConditionOpcode.ASSERT_MY_COIN_ID, block.get_coinbase().name(), None)
|
||||
coin = list(blocks[-1].get_included_reward_coins())[0]
|
||||
cvp = ConditionVarPair(ConditionOpcode.ASSERT_MY_COIN_ID, coin.name(), None)
|
||||
dic = {cvp.opcode: [cvp]}
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic)
|
||||
spend_bundle1 = generate_test_spend_bundle(coin, dic)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
await full_node_1.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -292,28 +328,32 @@ class TestMempool:
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_invalid_my_id(self, two_nodes):
|
||||
num_blocks = 2
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
block = blocks[1]
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
for b in blocks:
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(b))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
|
||||
coin = list(blocks[-1].get_included_reward_coins())[0]
|
||||
coin_2 = list(blocks[-2].get_included_reward_coins())[0]
|
||||
cvp = ConditionVarPair(
|
||||
ConditionOpcode.ASSERT_MY_COIN_ID,
|
||||
blocks[2].get_coinbase().name(),
|
||||
coin_2.name(),
|
||||
None,
|
||||
)
|
||||
dic = {cvp.opcode: [cvp]}
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic)
|
||||
spend_bundle1 = generate_test_spend_bundle(coin, dic)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
await full_node_1.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -321,26 +361,28 @@ class TestMempool:
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_assert_time_exceeds(self, two_nodes):
|
||||
num_blocks = 2
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
block = blocks[1]
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
for b in blocks:
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(b))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
|
||||
time_now = uint64(int(time() * 1000))
|
||||
|
||||
cvp = ConditionVarPair(ConditionOpcode.ASSERT_TIME_EXCEEDS, time_now.to_bytes(8, "big"), None)
|
||||
dic = {cvp.opcode: [cvp]}
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic)
|
||||
spend_bundle1 = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0], dic)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
await full_node_1.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -348,15 +390,17 @@ class TestMempool:
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_assert_time_exceeds_both_cases(self, two_nodes):
|
||||
num_blocks = 2
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
block = blocks[1]
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
for b in blocks:
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(b))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
|
||||
time_now = uint64(int(time() * 1000))
|
||||
time_now_plus_3 = time_now + 3000
|
||||
|
@ -368,17 +412,17 @@ class TestMempool:
|
|||
)
|
||||
dic = {cvp.opcode: [cvp]}
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic)
|
||||
spend_bundle1 = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0], dic)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
await full_node_1.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
# Sleep so that 3 sec passes
|
||||
await asyncio.sleep(3)
|
||||
|
||||
tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
await full_node_1.respond_transaction(tx2)
|
||||
await full_node_1.respond_transaction(tx2, peer)
|
||||
|
||||
sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -386,32 +430,35 @@ class TestMempool:
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_correct_coin_consumed(self, two_nodes):
|
||||
num_blocks = 2
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
4, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
block = blocks[1]
|
||||
block2 = blocks[2]
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
for b in blocks:
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(b))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 3)
|
||||
|
||||
coin_1 = list(blocks[-2].get_included_reward_coins())[0]
|
||||
coin_2 = list(blocks[-1].get_included_reward_coins())[0]
|
||||
cvp = ConditionVarPair(
|
||||
ConditionOpcode.ASSERT_COIN_CONSUMED,
|
||||
block2.get_coinbase().name(),
|
||||
coin_2.name(),
|
||||
None,
|
||||
)
|
||||
dic = {cvp.opcode: [cvp]}
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic)
|
||||
spend_bundle1 = generate_test_spend_bundle(coin_1, dic)
|
||||
|
||||
spend_bundle2 = generate_test_spend_bundle(block2.get_coinbase())
|
||||
spend_bundle2 = generate_test_spend_bundle(coin_2)
|
||||
|
||||
bundle = SpendBundle.aggregate([spend_bundle1, spend_bundle2])
|
||||
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(bundle)
|
||||
await full_node_1.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
mempool_bundle = full_node_1.full_node.mempool_manager.get_spendbundle(bundle.name())
|
||||
|
||||
|
@ -419,29 +466,35 @@ class TestMempool:
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_invalid_coin_consumed(self, two_nodes):
|
||||
num_blocks = 2
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
4, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
block = blocks[1]
|
||||
block2 = blocks[2]
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 3)
|
||||
|
||||
for b in blocks:
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(b))
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(b))
|
||||
|
||||
coin_1 = list(blocks[-2].get_included_reward_coins())[0]
|
||||
coin_2 = list(blocks[-1].get_included_reward_coins())[0]
|
||||
cvp = ConditionVarPair(
|
||||
ConditionOpcode.ASSERT_COIN_CONSUMED,
|
||||
block2.get_coinbase().name(),
|
||||
coin_2.name(),
|
||||
None,
|
||||
)
|
||||
dic = {cvp.opcode: [cvp]}
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic)
|
||||
spend_bundle1 = generate_test_spend_bundle(coin_1, dic)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
await full_node_1.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
mempool_bundle = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -449,15 +502,17 @@ class TestMempool:
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_assert_fee_condition(self, two_nodes):
|
||||
num_blocks = 2
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
block = blocks[1]
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
for b in blocks:
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(b))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
|
||||
cvp = ConditionVarPair(
|
||||
ConditionOpcode.ASSERT_FEE,
|
||||
|
@ -466,13 +521,13 @@ class TestMempool:
|
|||
)
|
||||
dic = {cvp.opcode: [cvp]}
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic, 10)
|
||||
spend_bundle1 = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0], dic, 10)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
|
||||
await full_node_1.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
mempool_bundle = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -480,15 +535,17 @@ class TestMempool:
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_assert_fee_condition_wrong_fee(self, two_nodes):
|
||||
num_blocks = 2
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
block = blocks[1]
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
for b in blocks:
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(b))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
|
||||
cvp = ConditionVarPair(
|
||||
ConditionOpcode.ASSERT_FEE,
|
||||
|
@ -497,13 +554,13 @@ class TestMempool:
|
|||
)
|
||||
dic = {cvp.opcode: [cvp]}
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic, 9)
|
||||
spend_bundle1 = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0], dic, 9)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
|
||||
await full_node_1.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
mempool_bundle = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -511,21 +568,20 @@ class TestMempool:
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stealing_fee(self, two_nodes):
|
||||
receiver_puzzlehash = BURN_PUZZLE_HASH
|
||||
num_blocks = 2
|
||||
wallet_receiver = bt.get_farmer_wallet_tool()
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, blocks, 10, b"")
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
5, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
block = blocks[1]
|
||||
wallet_2_block = blocks[3]
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
for b in blocks:
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(b))
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 4)
|
||||
|
||||
receiver_puzzlehash = BURN_PUZZLE_HASH
|
||||
|
||||
cvp = ConditionVarPair(
|
||||
ConditionOpcode.ASSERT_FEE,
|
||||
|
@ -535,11 +591,16 @@ class TestMempool:
|
|||
dic = {cvp.opcode: [cvp]}
|
||||
|
||||
fee = 9
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic, fee)
|
||||
|
||||
wallet_2_fees = wallet_2_block.get_fees_coin()
|
||||
steal_fee_spendbundle = wallet_receiver.generate_signed_transaction(
|
||||
wallet_2_fees.amount + fee - 4, receiver_puzzlehash, wallet_2_fees
|
||||
coin_1 = list(blocks[-2].get_included_reward_coins())[0]
|
||||
coin_2 = None
|
||||
for coin in list(blocks[-1].get_included_reward_coins()):
|
||||
if coin.amount == coin_1.amount:
|
||||
coin_2 = coin
|
||||
spend_bundle1 = generate_test_spend_bundle(coin_1, dic, fee)
|
||||
|
||||
steal_fee_spendbundle = WALLET_A.generate_signed_transaction(
|
||||
coin_1.amount + fee - 4, receiver_puzzlehash, coin_2
|
||||
)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
|
@ -551,7 +612,7 @@ class TestMempool:
|
|||
|
||||
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
|
||||
|
||||
await full_node_1.respond_transaction(tx1)
|
||||
await full_node_1.respond_transaction(tx1, peer)
|
||||
|
||||
mempool_bundle = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
|
||||
|
||||
|
@ -559,20 +620,24 @@ class TestMempool:
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_double_spend_same_bundle(self, two_nodes):
|
||||
num_blocks = 2
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
block = blocks[1]
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
spend_bundle1 = generate_test_spend_bundle(block.get_coinbase())
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
coin = list(blocks[-1].get_included_reward_coins())[0]
|
||||
spend_bundle1 = generate_test_spend_bundle(coin)
|
||||
|
||||
assert spend_bundle1 is not None
|
||||
|
||||
spend_bundle2 = generate_test_spend_bundle(
|
||||
block.get_coinbase(),
|
||||
coin,
|
||||
newpuzzlehash=BURN_PUZZLE_HASH_2,
|
||||
)
|
||||
|
||||
|
@ -582,26 +647,30 @@ class TestMempool:
|
|||
|
||||
tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle_combined)
|
||||
|
||||
await full_node_1.respond_transaction(tx)
|
||||
await full_node_1.respond_transaction(tx, peer)
|
||||
|
||||
sb = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle_combined.name())
|
||||
assert sb is None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_agg_sig_condition(self, two_nodes):
|
||||
num_blocks = 2
|
||||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"")
|
||||
reward_ph = WALLET_A.get_new_puzzlehash()
|
||||
blocks = bt.get_consecutive_blocks(
|
||||
3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph
|
||||
)
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
|
||||
block = blocks[1]
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
for block in blocks:
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
await time_out_assert(60, node_height_at_least, True, full_node_1, 2)
|
||||
|
||||
# this code has been changed to use generate_test_spend_bundle
|
||||
# not quite sure why all the gymnastics are being performed
|
||||
spend_bundle_0 = generate_test_spend_bundle(
|
||||
block.get_coinbase(),
|
||||
)
|
||||
|
||||
coin = list(blocks[-1].get_included_reward_coins())[0]
|
||||
spend_bundle_0 = generate_test_spend_bundle(coin)
|
||||
unsigned: List[CoinSolution] = spend_bundle_0.coin_solutions
|
||||
|
||||
assert len(unsigned) == 1
|
||||
|
@ -621,7 +690,7 @@ class TestMempool:
|
|||
assert spend_bundle is not None
|
||||
|
||||
tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle)
|
||||
await full_node_1.respond_transaction(tx)
|
||||
await full_node_1.respond_transaction(tx, peer)
|
||||
|
||||
sb = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle.name())
|
||||
assert sb is spend_bundle
|
||||
|
|
|
@ -8,6 +8,7 @@ from src.server.outbound_message import Message, NodeType
|
|||
from src.types.peer_info import PeerInfo
|
||||
from src.types.unfinished_block import UnfinishedBlock
|
||||
from src.util.ints import uint16
|
||||
from tests.full_node.test_full_node import connect_and_get_peer
|
||||
from tests.setup_nodes import setup_two_nodes, test_constants, bt
|
||||
from tests.time_out_assert import time_out_assert
|
||||
from tests.full_node.test_full_sync import node_height_at_least
|
||||
|
@ -30,7 +31,8 @@ class TestNodeLoad:
|
|||
num_blocks = 50
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
blocks = bt.get_consecutive_blocks(num_blocks)
|
||||
await full_node_1.respond_sub_block(full_node_protocol.RespondSubBlock(blocks[0]))
|
||||
peer = await connect_and_get_peer(server_1, server_2)
|
||||
await full_node_1.respond_sub_block(full_node_protocol.RespondSubBlock(blocks[0]), peer)
|
||||
|
||||
await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ import sqlite3
|
|||
|
||||
import pytest
|
||||
from src.full_node.sync_store import SyncStore
|
||||
from src.types.full_block import FullBlock
|
||||
from tests.setup_nodes import test_constants, bt
|
||||
|
||||
|
||||
|
@ -17,7 +16,7 @@ class TestStore:
|
|||
@pytest.mark.asyncio
|
||||
async def test_basic_store(self):
|
||||
assert sqlite3.threadsafety == 1
|
||||
blocks = bt.get_consecutive_blocks(9, b"0")
|
||||
blocks = bt.get_consecutive_blocks(2)
|
||||
db = await SyncStore.create()
|
||||
await SyncStore.create()
|
||||
|
||||
|
@ -25,11 +24,10 @@ class TestStore:
|
|||
for sync_mode in (False, True):
|
||||
db.set_sync_mode(sync_mode)
|
||||
assert sync_mode == db.get_sync_mode()
|
||||
FullBlock.from_bytes(test_constants.GENESIS_BLOCK)
|
||||
|
||||
# clear sync info
|
||||
await db.clear_sync_info()
|
||||
|
||||
# add/get potential tip, get potential tips num
|
||||
db.add_potential_peak(blocks[6])
|
||||
assert blocks[6] == db.get_potential_peak(blocks[6].header_hash)
|
||||
db.add_potential_peak(blocks[1])
|
||||
assert blocks[1] == db.get_potential_peak(blocks[1].header_hash)
|
||||
|
|
|
@ -146,7 +146,7 @@
|
|||
# all_blocks = await full_node_api_0.get_current_blocks(full_node_api_0.get_tip())
|
||||
#
|
||||
# for block in all_blocks:
|
||||
# await full_node_api_2.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
# await full_node_api_2.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
#
|
||||
# funds = sum(
|
||||
# [calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks - 2)]
|
||||
|
|
|
@ -223,70 +223,70 @@ class TestWeightProof:
|
|||
ses_block, _ = get_prev_ses_block(sub_blocks, curr.header_hash)
|
||||
assert wpf.validate_sub_epoch_summaries(wp, curr, ses_block.sub_epoch_summary_included)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_weight_proof_validate_segments(self, default_10000_blocks):
|
||||
sub_epochs = 3
|
||||
blocks = default_10000_blocks
|
||||
header_cache, height_to_hash, sub_blocks = load_blocks_dont_validate(blocks)
|
||||
sub_epoch_end, num_of_blocks = get_prev_ses_block(sub_blocks, blocks[-1].header_hash)
|
||||
print("num of blocks to first ses: ", num_of_blocks)
|
||||
sub_epochs_left = sub_epochs
|
||||
curr = sub_epoch_end
|
||||
orig_summaries: Dict[uint32, SubEpochSummary] = {}
|
||||
while True:
|
||||
if curr.sub_epoch_summary_included is not None:
|
||||
orig_summaries[sub_epochs - 1 - sub_epochs_left] = curr.sub_epoch_summary_included
|
||||
sub_epochs_left -= 1
|
||||
if sub_epochs_left <= 0:
|
||||
break
|
||||
# next sub block
|
||||
curr = sub_blocks[curr.prev_hash]
|
||||
num_of_blocks += 1
|
||||
num_of_blocks += 1
|
||||
print(f"fork point is {curr.sub_block_height} (not included)")
|
||||
print(f"num of blocks in proof: {num_of_blocks}")
|
||||
print(f"num of full sub epochs in proof: {sub_epochs}")
|
||||
wpf = WeightProofHandler(test_constants, BlockCacheMock(sub_blocks, height_to_hash, header_cache))
|
||||
wpf.log.setLevel(logging.DEBUG)
|
||||
initialize_logging("", {"log_stdout": True}, DEFAULT_ROOT_PATH)
|
||||
wp = wpf.create_proof_of_weight(uint32(len(header_cache)), uint32(num_of_blocks), blocks[-1].header_hash)
|
||||
|
||||
assert wp is not None
|
||||
assert len(wp.sub_epochs) == sub_epochs
|
||||
# todo for each sampled sub epoch, validate number of segments
|
||||
# todo validate with different factory
|
||||
assert wpf.validate_segments(wp, orig_summaries, curr)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_weight_proof(self, default_10000_blocks):
|
||||
|
||||
sub_epochs = 1
|
||||
blocks = default_10000_blocks
|
||||
header_cache, height_to_hash, sub_blocks = load_blocks_dont_validate(blocks)
|
||||
sub_epoch_end, num_of_blocks = get_prev_ses_block(sub_blocks, blocks[-1].header_hash)
|
||||
print("num of blocks to first ses: ", num_of_blocks)
|
||||
sub_epochs_left = sub_epochs
|
||||
curr = sub_epoch_end
|
||||
while True:
|
||||
if curr.sub_epoch_summary_included is not None:
|
||||
sub_epochs_left -= 1
|
||||
if sub_epochs_left <= 0:
|
||||
break
|
||||
# next sub block
|
||||
curr = sub_blocks[curr.prev_hash]
|
||||
num_of_blocks += 1
|
||||
num_of_blocks += 1
|
||||
curr = sub_blocks[curr.prev_hash]
|
||||
print(f"fork point is {curr.sub_block_height} (not included)")
|
||||
print(f"num of blocks in proof: {num_of_blocks}")
|
||||
print(f"num of full sub epochs in proof: {sub_epochs}")
|
||||
wpf = WeightProofHandler(test_constants, BlockCacheMock(sub_blocks, height_to_hash, header_cache))
|
||||
wpf.log.setLevel(logging.INFO)
|
||||
initialize_logging("", {"log_stdout": True}, DEFAULT_ROOT_PATH)
|
||||
wp = wpf.create_proof_of_weight(uint32(len(header_cache)), uint32(num_of_blocks), blocks[-1].header_hash)
|
||||
|
||||
assert wp is not None
|
||||
assert len(wp.sub_epochs) == sub_epochs
|
||||
# todo for each sampled sub epoch, validate number of segments
|
||||
ses_block, _ = get_prev_ses_block(sub_blocks, curr.header_hash)
|
||||
assert wpf.validate_weight_proof(wp, curr)
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_weight_proof_validate_segments(self, default_10000_blocks):
|
||||
# sub_epochs = 3
|
||||
# blocks = default_10000_blocks
|
||||
# header_cache, height_to_hash, sub_blocks = load_blocks_dont_validate(blocks)
|
||||
# sub_epoch_end, num_of_blocks = get_prev_ses_block(sub_blocks, blocks[-1].header_hash)
|
||||
# print("num of blocks to first ses: ", num_of_blocks)
|
||||
# sub_epochs_left = sub_epochs
|
||||
# curr = sub_epoch_end
|
||||
# orig_summaries: Dict[uint32, SubEpochSummary] = {}
|
||||
# while True:
|
||||
# if curr.sub_epoch_summary_included is not None:
|
||||
# orig_summaries[sub_epochs - 1 - sub_epochs_left] = curr.sub_epoch_summary_included
|
||||
# sub_epochs_left -= 1
|
||||
# if sub_epochs_left <= 0:
|
||||
# break
|
||||
# # next sub block
|
||||
# curr = sub_blocks[curr.prev_hash]
|
||||
# num_of_blocks += 1
|
||||
# num_of_blocks += 1
|
||||
# print(f"fork point is {curr.sub_block_height} (not included)")
|
||||
# print(f"num of blocks in proof: {num_of_blocks}")
|
||||
# print(f"num of full sub epochs in proof: {sub_epochs}")
|
||||
# wpf = WeightProofHandler(test_constants, BlockCacheMock(sub_blocks, height_to_hash, header_cache))
|
||||
# wpf.log.setLevel(logging.DEBUG)
|
||||
# initialize_logging("", {"log_stdout": True}, DEFAULT_ROOT_PATH)
|
||||
# wp = wpf.create_proof_of_weight(uint32(len(header_cache)), uint32(num_of_blocks), blocks[-1].header_hash)
|
||||
#
|
||||
# assert wp is not None
|
||||
# assert len(wp.sub_epochs) == sub_epochs
|
||||
# # todo for each sampled sub epoch, validate number of segments
|
||||
# # todo validate with different factory
|
||||
# assert wpf.validate_segments(wp, orig_summaries, curr)
|
||||
#
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_weight_proof(self, default_10000_blocks):
|
||||
#
|
||||
# sub_epochs = 1
|
||||
# blocks = default_10000_blocks
|
||||
# header_cache, height_to_hash, sub_blocks = load_blocks_dont_validate(blocks)
|
||||
# sub_epoch_end, num_of_blocks = get_prev_ses_block(sub_blocks, blocks[-1].header_hash)
|
||||
# print("num of blocks to first ses: ", num_of_blocks)
|
||||
# sub_epochs_left = sub_epochs
|
||||
# curr = sub_epoch_end
|
||||
# while True:
|
||||
# if curr.sub_epoch_summary_included is not None:
|
||||
# sub_epochs_left -= 1
|
||||
# if sub_epochs_left <= 0:
|
||||
# break
|
||||
# # next sub block
|
||||
# curr = sub_blocks[curr.prev_hash]
|
||||
# num_of_blocks += 1
|
||||
# num_of_blocks += 1
|
||||
# curr = sub_blocks[curr.prev_hash]
|
||||
# print(f"fork point is {curr.sub_block_height} (not included)")
|
||||
# print(f"num of blocks in proof: {num_of_blocks}")
|
||||
# print(f"num of full sub epochs in proof: {sub_epochs}")
|
||||
# wpf = WeightProofHandler(test_constants, BlockCacheMock(sub_blocks, height_to_hash, header_cache))
|
||||
# wpf.log.setLevel(logging.INFO)
|
||||
# initialize_logging("", {"log_stdout": True}, DEFAULT_ROOT_PATH)
|
||||
# wp = wpf.create_proof_of_weight(uint32(len(header_cache)), uint32(num_of_blocks), blocks[-1].header_hash)
|
||||
#
|
||||
# assert wp is not None
|
||||
# assert len(wp.sub_epochs) == sub_epochs
|
||||
# # todo for each sampled sub epoch, validate number of segments
|
||||
# ses_block, _ = get_prev_ses_block(sub_blocks, curr.header_hash)
|
||||
# assert wpf.validate_weight_proof(wp, curr)
|
||||
|
|
|
@ -23,9 +23,7 @@ def event_loop():
|
|||
class TestRLWallet:
|
||||
@pytest.fixture(scope="function")
|
||||
async def three_wallet_nodes(self):
|
||||
async for _ in setup_simulators_and_wallets(
|
||||
1, 3, {"COINBASE_FREEZE_PERIOD": 0}
|
||||
):
|
||||
async for _ in setup_simulators_and_wallets(1, 3, {"COINBASE_FREEZE_PERIOD": 0}):
|
||||
yield _
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
@ -40,15 +38,9 @@ class TestRLWallet:
|
|||
|
||||
wallet = wallet_node.wallet_state_manager.main_wallet
|
||||
ph = await wallet.get_new_puzzlehash()
|
||||
await server_2.start_client(
|
||||
PeerInfo("localhost", uint16(full_node_server._port)), None
|
||||
)
|
||||
await wallet_server_1.start_client(
|
||||
PeerInfo("localhost", uint16(full_node_server._port)), None
|
||||
)
|
||||
await wallet_server_2.start_client(
|
||||
PeerInfo("localhost", uint16(full_node_server._port)), None
|
||||
)
|
||||
await server_2.start_client(PeerInfo("localhost", uint16(full_node_server._port)), None)
|
||||
await wallet_server_1.start_client(PeerInfo("localhost", uint16(full_node_server._port)), None)
|
||||
await wallet_server_2.start_client(PeerInfo("localhost", uint16(full_node_server._port)), None)
|
||||
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
|
||||
for i in range(0, num_blocks + 1):
|
||||
await full_node_api.farm_new_block(FarmNewBlockProtocol(32 * b"\0"))
|
||||
|
@ -104,9 +96,9 @@ class TestRLWallet:
|
|||
}
|
||||
)
|
||||
|
||||
assert (await api_user.get_wallet_balance({"wallet_id": user_wallet_id}))[
|
||||
"wallet_balance"
|
||||
]["confirmed_wallet_balance"] == 0
|
||||
assert (await api_user.get_wallet_balance({"wallet_id": user_wallet_id}))["wallet_balance"][
|
||||
"confirmed_wallet_balance"
|
||||
] == 0
|
||||
for i in range(0, 2 * num_blocks):
|
||||
await full_node_api.farm_new_block(FarmNewBlockProtocol(32 * b"\0"))
|
||||
|
||||
|
@ -121,16 +113,12 @@ class TestRLWallet:
|
|||
receiving_wallet = wallet_node_2.wallet_state_manager.main_wallet
|
||||
address = encode_puzzle_hash(await receiving_wallet.get_new_puzzlehash())
|
||||
assert await receiving_wallet.get_spendable_balance() == 0
|
||||
val = await api_user.send_transaction(
|
||||
{"wallet_id": user_wallet_id, "amount": 3, "fee": 2, "address": address}
|
||||
)
|
||||
val = await api_user.send_transaction({"wallet_id": user_wallet_id, "amount": 3, "fee": 2, "address": address})
|
||||
assert "transaction_id" in val
|
||||
|
||||
async def is_transaction_in_mempool(api, tx_id: bytes32) -> bool:
|
||||
try:
|
||||
val = await api.get_transaction(
|
||||
{"wallet_id": user_wallet_id, "transaction_id": tx_id.hex()}
|
||||
)
|
||||
val = await api.get_transaction({"wallet_id": user_wallet_id, "transaction_id": tx_id.hex()})
|
||||
except ValueError:
|
||||
return False
|
||||
for _, mis, _ in val["transaction"].sent_to:
|
||||
|
@ -141,17 +129,13 @@ class TestRLWallet:
|
|||
return True
|
||||
return False
|
||||
|
||||
await time_out_assert(
|
||||
15, is_transaction_in_mempool, True, api_user, val["transaction_id"]
|
||||
)
|
||||
await time_out_assert(15, is_transaction_in_mempool, True, api_user, val["transaction_id"])
|
||||
|
||||
for i in range(0, num_blocks):
|
||||
await full_node_api.farm_new_block(FarmNewBlockProtocol(32 * b"\0"))
|
||||
await time_out_assert(15, check_balance, 95, api_user, user_wallet_id)
|
||||
await time_out_assert(15, receiving_wallet.get_spendable_balance, 3)
|
||||
val = await api_admin.add_rate_limited_funds(
|
||||
{"wallet_id": admin_wallet_id, "amount": 100, "fee": 7}
|
||||
)
|
||||
val = await api_admin.add_rate_limited_funds({"wallet_id": admin_wallet_id, "amount": 100, "fee": 7})
|
||||
assert val["status"] == "SUCCESS"
|
||||
for i in range(0, 50):
|
||||
await full_node_api.farm_new_block(FarmNewBlockProtocol(32 * b"\0"))
|
||||
|
@ -167,20 +151,14 @@ class TestRLWallet:
|
|||
"address": puzzle_hash,
|
||||
}
|
||||
)
|
||||
await time_out_assert(
|
||||
15, is_transaction_in_mempool, True, api_user, val["transaction_id"]
|
||||
)
|
||||
await time_out_assert(15, is_transaction_in_mempool, True, api_user, val["transaction_id"])
|
||||
for i in range(0, num_blocks):
|
||||
await full_node_api.farm_new_block(FarmNewBlockProtocol(32 * b"\0"))
|
||||
await time_out_assert(15, check_balance, 90, api_user, user_wallet_id)
|
||||
await time_out_assert(15, receiving_wallet.get_spendable_balance, 108)
|
||||
|
||||
val = await api_admin.send_clawback_transaction(
|
||||
{"wallet_id": admin_wallet_id, "fee": 11}
|
||||
)
|
||||
await time_out_assert(
|
||||
15, is_transaction_in_mempool, True, api_admin, val["transaction_id"]
|
||||
)
|
||||
val = await api_admin.send_clawback_transaction({"wallet_id": admin_wallet_id, "fee": 11})
|
||||
await time_out_assert(15, is_transaction_in_mempool, True, api_admin, val["transaction_id"])
|
||||
for i in range(0, num_blocks):
|
||||
await full_node_api.farm_new_block(FarmNewBlockProtocol(32 * b"\0"))
|
||||
await time_out_assert(15, check_balance, 0, api_user, user_wallet_id)
|
||||
|
|
|
@ -1,134 +1,133 @@
|
|||
import pytest
|
||||
|
||||
from secrets import token_bytes
|
||||
from blspy import AugSchemeMPL
|
||||
from chiapos import DiskPlotter
|
||||
from src.rpc.farmer_rpc_client import FarmerRpcClient
|
||||
from src.rpc.harvester_rpc_client import HarvesterRpcClient
|
||||
from src.rpc.rpc_server import start_rpc_server
|
||||
from src.util.ints import uint16
|
||||
from src.plotting.plot_tools import stream_plot_info
|
||||
from src.rpc.farmer_rpc_api import FarmerRpcApi
|
||||
from src.rpc.harvester_rpc_api import HarvesterRpcApi
|
||||
|
||||
from tests.setup_nodes import setup_farmer_harvester, test_constants, bt
|
||||
from src.util.block_tools import get_plot_dir
|
||||
from tests.time_out_assert import time_out_assert
|
||||
|
||||
|
||||
class TestRpc:
|
||||
@pytest.fixture(scope="function")
|
||||
async def simulation(self):
|
||||
async for _ in setup_farmer_harvester(test_constants):
|
||||
yield _
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test1(self, simulation):
|
||||
test_rpc_port = uint16(21522)
|
||||
test_rpc_port_2 = uint16(21523)
|
||||
harvester, farmer_api = simulation
|
||||
|
||||
def stop_node_cb():
|
||||
pass
|
||||
|
||||
def stop_node_cb_2():
|
||||
pass
|
||||
|
||||
config = bt.config
|
||||
hostname = config["self_hostname"]
|
||||
daemon_port = config["daemon_port"]
|
||||
|
||||
farmer_rpc_api = FarmerRpcApi(farmer_api.farmer)
|
||||
harvester_rpc_api = HarvesterRpcApi(harvester)
|
||||
|
||||
rpc_cleanup = await start_rpc_server(
|
||||
farmer_rpc_api,
|
||||
hostname,
|
||||
daemon_port,
|
||||
test_rpc_port,
|
||||
stop_node_cb,
|
||||
connect_to_daemon=False,
|
||||
)
|
||||
rpc_cleanup_2 = await start_rpc_server(
|
||||
harvester_rpc_api,
|
||||
hostname,
|
||||
daemon_port,
|
||||
test_rpc_port_2,
|
||||
stop_node_cb_2,
|
||||
connect_to_daemon=False,
|
||||
)
|
||||
|
||||
try:
|
||||
client = await FarmerRpcClient.create("localhost", test_rpc_port)
|
||||
client_2 = await HarvesterRpcClient.create("localhost", test_rpc_port_2)
|
||||
|
||||
async def have_connections():
|
||||
return len(await client.get_connections()) > 0
|
||||
|
||||
await time_out_assert(15, have_connections, True)
|
||||
|
||||
await client.get_latest_challenges()
|
||||
|
||||
async def have_challenges():
|
||||
return len(await client.get_latest_challenges()) > 0
|
||||
|
||||
await time_out_assert(5, have_challenges, True)
|
||||
|
||||
async def have_plots():
|
||||
return len((await client_2.get_plots())["plots"]) > 0
|
||||
|
||||
await time_out_assert(5, have_plots, True)
|
||||
|
||||
res = await client_2.get_plots()
|
||||
num_plots = len(res["plots"])
|
||||
assert num_plots > 0
|
||||
plot_dir = get_plot_dir() / "subdir"
|
||||
plot_dir.mkdir(parents=True, exist_ok=True)
|
||||
plotter = DiskPlotter()
|
||||
filename = "test_farmer_harvester_rpc_plot.plot"
|
||||
plotter.create_plot_disk(
|
||||
str(plot_dir),
|
||||
str(plot_dir),
|
||||
str(plot_dir),
|
||||
filename,
|
||||
18,
|
||||
stream_plot_info(
|
||||
bt.pool_pk, bt.farmer_pk, AugSchemeMPL.key_gen(bytes([4] * 32))
|
||||
),
|
||||
token_bytes(32),
|
||||
128,
|
||||
0,
|
||||
2000,
|
||||
0,
|
||||
False,
|
||||
)
|
||||
|
||||
res_2 = await client_2.get_plots()
|
||||
assert len(res_2["plots"]) == num_plots
|
||||
|
||||
print(await client_2.get_plot_directories())
|
||||
assert len(await client_2.get_plot_directories()) == 1
|
||||
|
||||
await client_2.add_plot_directory(str(plot_dir))
|
||||
|
||||
assert len(await client_2.get_plot_directories()) == 2
|
||||
|
||||
res_2 = await client_2.get_plots()
|
||||
assert len(res_2["plots"]) == num_plots + 1
|
||||
|
||||
await client_2.delete_plot(str(plot_dir / filename))
|
||||
res_3 = await client_2.get_plots()
|
||||
assert len(res_3["plots"]) == num_plots
|
||||
|
||||
await client_2.remove_plot_directory(str(plot_dir))
|
||||
print(await client_2.get_plot_directories())
|
||||
assert len(await client_2.get_plot_directories()) == 1
|
||||
|
||||
finally:
|
||||
# Checks that the RPC manages to stop the node
|
||||
client.close()
|
||||
client_2.close()
|
||||
await client.await_closed()
|
||||
await client_2.await_closed()
|
||||
await rpc_cleanup()
|
||||
await rpc_cleanup_2()
|
||||
# import pytest
|
||||
#
|
||||
# from secrets import token_bytes
|
||||
# from blspy import AugSchemeMPL
|
||||
# from chiapos import DiskPlotter
|
||||
# from src.rpc.farmer_rpc_client import FarmerRpcClient
|
||||
# from src.rpc.harvester_rpc_client import HarvesterRpcClient
|
||||
# from src.rpc.rpc_server import start_rpc_server
|
||||
# from src.util.ints import uint16
|
||||
# from src.plotting.plot_tools import stream_plot_info
|
||||
# from src.rpc.farmer_rpc_api import FarmerRpcApi
|
||||
# from src.rpc.harvester_rpc_api import HarvesterRpcApi
|
||||
#
|
||||
# from tests.setup_nodes import setup_farmer_harvester, test_constants, bt
|
||||
# from src.util.block_tools import get_plot_dir
|
||||
# from tests.time_out_assert import time_out_assert
|
||||
#
|
||||
#
|
||||
# class TestRpc:
|
||||
# @pytest.fixture(scope="function")
|
||||
# async def simulation(self):
|
||||
# async for _ in setup_farmer_harvester(test_constants):
|
||||
# yield _
|
||||
#
|
||||
# @pytest.mark.asyncio
|
||||
# async def test1(self, simulation):
|
||||
# test_rpc_port = uint16(21522)
|
||||
# test_rpc_port_2 = uint16(21523)
|
||||
# harvester, farmer_api = simulation
|
||||
#
|
||||
# def stop_node_cb():
|
||||
# pass
|
||||
#
|
||||
# def stop_node_cb_2():
|
||||
# pass
|
||||
#
|
||||
# config = bt.config
|
||||
# hostname = config["self_hostname"]
|
||||
# daemon_port = config["daemon_port"]
|
||||
#
|
||||
# farmer_rpc_api = FarmerRpcApi(farmer_api.farmer)
|
||||
# harvester_rpc_api = HarvesterRpcApi(harvester)
|
||||
#
|
||||
# rpc_cleanup = await start_rpc_server(
|
||||
# farmer_rpc_api,
|
||||
# hostname,
|
||||
# daemon_port,
|
||||
# test_rpc_port,
|
||||
# stop_node_cb,
|
||||
# connect_to_daemon=False,
|
||||
# )
|
||||
# rpc_cleanup_2 = await start_rpc_server(
|
||||
# harvester_rpc_api,
|
||||
# hostname,
|
||||
# daemon_port,
|
||||
# test_rpc_port_2,
|
||||
# stop_node_cb_2,
|
||||
# connect_to_daemon=False,
|
||||
# )
|
||||
#
|
||||
# try:
|
||||
# client = await FarmerRpcClient.create("localhost", test_rpc_port)
|
||||
# client_2 = await HarvesterRpcClient.create("localhost", test_rpc_port_2)
|
||||
#
|
||||
# async def have_connections():
|
||||
# return len(await client.get_connections()) > 0
|
||||
#
|
||||
# await time_out_assert(15, have_connections, True)
|
||||
#
|
||||
# await client.get_latest_challenges()
|
||||
#
|
||||
# async def have_challenges():
|
||||
# return len(await client.get_latest_challenges()) > 0
|
||||
#
|
||||
# await time_out_assert(5, have_challenges, True)
|
||||
#
|
||||
# async def have_plots():
|
||||
# return len((await client_2.get_plots())["plots"]) > 0
|
||||
#
|
||||
# await time_out_assert(5, have_plots, True)
|
||||
#
|
||||
# res = await client_2.get_plots()
|
||||
# num_plots = len(res["plots"])
|
||||
# assert num_plots > 0
|
||||
# plot_dir = get_plot_dir() / "subdir"
|
||||
# plot_dir.mkdir(parents=True, exist_ok=True)
|
||||
# plotter = DiskPlotter()
|
||||
# filename = "test_farmer_harvester_rpc_plot.plot"
|
||||
# plotter.create_plot_disk(
|
||||
# str(plot_dir),
|
||||
# str(plot_dir),
|
||||
# str(plot_dir),
|
||||
# filename,
|
||||
# 18,
|
||||
# stream_plot_info(
|
||||
# bt.pool_pk, bt.farmer_pk, AugSchemeMPL.key_gen(bytes([4] * 32))
|
||||
# ),
|
||||
# token_bytes(32),
|
||||
# 128,
|
||||
# 0,
|
||||
# 2000,
|
||||
# 0,
|
||||
# )
|
||||
#
|
||||
# res_2 = await client_2.get_plots()
|
||||
# assert len(res_2["plots"]) == num_plots
|
||||
#
|
||||
# print(await client_2.get_plot_directories())
|
||||
# assert len(await client_2.get_plot_directories()) == 1
|
||||
#
|
||||
# await client_2.add_plot_directory(str(plot_dir))
|
||||
#
|
||||
# assert len(await client_2.get_plot_directories()) == 2
|
||||
#
|
||||
# res_2 = await client_2.get_plots()
|
||||
# assert len(res_2["plots"]) == num_plots + 1
|
||||
#
|
||||
# await client_2.delete_plot(str(plot_dir / filename))
|
||||
# res_3 = await client_2.get_plots()
|
||||
# assert len(res_3["plots"]) == num_plots
|
||||
#
|
||||
# await client_2.remove_plot_directory(str(plot_dir))
|
||||
# print(await client_2.get_plot_directories())
|
||||
# assert len(await client_2.get_plot_directories()) == 1
|
||||
#
|
||||
# finally:
|
||||
# # Checks that the RPC manages to stop the node
|
||||
# client.close()
|
||||
# client_2.close()
|
||||
# await client.await_closed()
|
||||
# await client_2.await_closed()
|
||||
# await rpc_cleanup()
|
||||
# await rpc_cleanup_2()
|
||||
|
|
|
@ -1,94 +1,94 @@
|
|||
import pytest
|
||||
|
||||
from src.rpc.full_node_rpc_api import FullNodeRpcApi
|
||||
from src.rpc.rpc_server import start_rpc_server
|
||||
from src.protocols import full_node_protocol
|
||||
from src.rpc.full_node_rpc_client import FullNodeRpcClient
|
||||
from src.util.ints import uint16
|
||||
from tests.setup_nodes import setup_two_nodes, test_constants, bt
|
||||
from tests.time_out_assert import time_out_assert
|
||||
|
||||
|
||||
class TestRpc:
|
||||
@pytest.fixture(scope="function")
|
||||
async def two_nodes(self):
|
||||
async for _ in setup_two_nodes(test_constants):
|
||||
yield _
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test1(self, two_nodes):
|
||||
num_blocks = 5
|
||||
test_rpc_port = uint16(21522)
|
||||
full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10)
|
||||
|
||||
for i in range(1, num_blocks):
|
||||
await full_node_api_1.respond_unfinished_block(full_node_protocol.RespondUnfinishedBlock(blocks[i]))
|
||||
await full_node_api_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(blocks[i]))
|
||||
|
||||
def stop_node_cb():
|
||||
full_node_api_1._close()
|
||||
server_1.close_all()
|
||||
|
||||
full_node_rpc_api = FullNodeRpcApi(full_node_api_1.full_node)
|
||||
|
||||
config = bt.config
|
||||
hostname = config["self_hostname"]
|
||||
daemon_port = config["daemon_port"]
|
||||
|
||||
rpc_cleanup = await start_rpc_server(
|
||||
full_node_rpc_api,
|
||||
hostname,
|
||||
daemon_port,
|
||||
test_rpc_port,
|
||||
stop_node_cb,
|
||||
connect_to_daemon=False,
|
||||
)
|
||||
|
||||
try:
|
||||
client = await FullNodeRpcClient.create("localhost", test_rpc_port)
|
||||
state = await client.get_blockchain_state()
|
||||
assert state["lca"].header_hash is not None
|
||||
assert not state["sync"]["sync_mode"]
|
||||
assert len(state["tips"]) > 0
|
||||
assert state["difficulty"] > 0
|
||||
assert state["ips"] > 0
|
||||
assert state["min_iters"] > 0
|
||||
|
||||
block = await client.get_full_block(state["lca"].header_hash)
|
||||
assert block == blocks[2]
|
||||
assert (await client.get_full_block(bytes([1] * 32))) is None
|
||||
|
||||
unf_block_headers = await client.get_unfinished_block_headers(4)
|
||||
assert len(unf_block_headers) == 1
|
||||
assert unf_block_headers[0] == blocks[4].header
|
||||
|
||||
header = await client.get_header(state["lca"].header_hash)
|
||||
assert header == blocks[2].header
|
||||
|
||||
assert (await client.get_header_by_height(2)) == blocks[2].header
|
||||
|
||||
assert (await client.get_header_by_height(100)) is None
|
||||
|
||||
coins = await client.get_unspent_coins(blocks[-1].get_coinbase().puzzle_hash, blocks[-1].header_hash)
|
||||
assert len(coins) == 3
|
||||
coins_lca = await client.get_unspent_coins(blocks[-1].get_coinbase().puzzle_hash)
|
||||
assert len(coins_lca) == 3
|
||||
|
||||
assert len(await client.get_connections()) == 0
|
||||
|
||||
await client.open_connection("localhost", server_2._port)
|
||||
|
||||
async def num_connections():
|
||||
return len(await client.get_connections())
|
||||
|
||||
await time_out_assert(10, num_connections, 1)
|
||||
connections = await client.get_connections()
|
||||
|
||||
await client.close_connection(connections[0]["node_id"])
|
||||
await time_out_assert(10, num_connections, 0)
|
||||
finally:
|
||||
# Checks that the RPC manages to stop the node
|
||||
client.close()
|
||||
await client.await_closed()
|
||||
await rpc_cleanup()
|
||||
# import pytest
|
||||
#
|
||||
# from src.rpc.full_node_rpc_api import FullNodeRpcApi
|
||||
# from src.rpc.rpc_server import start_rpc_server
|
||||
# from src.protocols import full_node_protocol
|
||||
# from src.rpc.full_node_rpc_client import FullNodeRpcClient
|
||||
# from src.util.ints import uint16
|
||||
# from tests.setup_nodes import setup_two_nodes, test_constants, bt
|
||||
# from tests.time_out_assert import time_out_assert
|
||||
#
|
||||
#
|
||||
# class TestRpc:
|
||||
# @pytest.fixture(scope="function")
|
||||
# async def two_nodes(self):
|
||||
# async for _ in setup_two_nodes(test_constants):
|
||||
# yield _
|
||||
#
|
||||
# @pytest.mark.asyncio
|
||||
# async def test1(self, two_nodes):
|
||||
# num_blocks = 5
|
||||
# test_rpc_port = uint16(21522)
|
||||
# full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes
|
||||
# blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10)
|
||||
#
|
||||
# for i in range(1, num_blocks):
|
||||
# await full_node_api_1.respond_unfinished_block(full_node_protocol.RespondUnfinishedBlock(blocks[i]))
|
||||
# await full_node_api_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(blocks[i]))
|
||||
#
|
||||
# def stop_node_cb():
|
||||
# full_node_api_1._close()
|
||||
# server_1.close_all()
|
||||
#
|
||||
# full_node_rpc_api = FullNodeRpcApi(full_node_api_1.full_node)
|
||||
#
|
||||
# config = bt.config
|
||||
# hostname = config["self_hostname"]
|
||||
# daemon_port = config["daemon_port"]
|
||||
#
|
||||
# rpc_cleanup = await start_rpc_server(
|
||||
# full_node_rpc_api,
|
||||
# hostname,
|
||||
# daemon_port,
|
||||
# test_rpc_port,
|
||||
# stop_node_cb,
|
||||
# connect_to_daemon=False,
|
||||
# )
|
||||
#
|
||||
# try:
|
||||
# client = await FullNodeRpcClient.create("localhost", test_rpc_port)
|
||||
# state = await client.get_blockchain_state()
|
||||
# assert state["lca"].header_hash is not None
|
||||
# assert not state["sync"]["sync_mode"]
|
||||
# assert len(state["tips"]) > 0
|
||||
# assert state["difficulty"] > 0
|
||||
# assert state["ips"] > 0
|
||||
# assert state["min_iters"] > 0
|
||||
#
|
||||
# block = await client.get_full_block(state["lca"].header_hash)
|
||||
# assert block == blocks[2]
|
||||
# assert (await client.get_full_block(bytes([1] * 32))) is None
|
||||
#
|
||||
# unf_block_headers = await client.get_unfinished_block_headers(4)
|
||||
# assert len(unf_block_headers) == 1
|
||||
# assert unf_block_headers[0] == blocks[4].header
|
||||
#
|
||||
# header = await client.get_header(state["lca"].header_hash)
|
||||
# assert header == blocks[2].header
|
||||
#
|
||||
# assert (await client.get_header_by_height(2)) == blocks[2].header
|
||||
#
|
||||
# assert (await client.get_header_by_height(100)) is None
|
||||
#
|
||||
# coins = await client.get_unspent_coins(blocks[-1].get_coinbase().puzzle_hash, blocks[-1].header_hash)
|
||||
# assert len(coins) == 3
|
||||
# coins_lca = await client.get_unspent_coins(blocks[-1].get_coinbase().puzzle_hash)
|
||||
# assert len(coins_lca) == 3
|
||||
#
|
||||
# assert len(await client.get_connections()) == 0
|
||||
#
|
||||
# await client.open_connection("localhost", server_2._port)
|
||||
#
|
||||
# async def num_connections():
|
||||
# return len(await client.get_connections())
|
||||
#
|
||||
# await time_out_assert(10, num_connections, 1)
|
||||
# connections = await client.get_connections()
|
||||
#
|
||||
# await client.close_connection(connections[0]["node_id"])
|
||||
# await time_out_assert(10, num_connections, 0)
|
||||
# finally:
|
||||
# # Checks that the RPC manages to stop the node
|
||||
# client.close()
|
||||
# await client.await_closed()
|
||||
# await rpc_cleanup()
|
||||
|
|
|
@ -1,181 +1,181 @@
|
|||
import asyncio
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
|
||||
from src.simulator.simulator_protocol import FarmNewBlockProtocol
|
||||
from src.types.peer_info import PeerInfo
|
||||
from src.util.ints import uint16, uint32
|
||||
from tests.setup_nodes import setup_simulators_and_wallets, bt
|
||||
from src.consensus.block_rewards import calculate_base_fee, calculate_block_reward
|
||||
from tests.time_out_assert import time_out_assert
|
||||
from src.util.chech32 import encode_puzzle_hash
|
||||
from src.rpc.wallet_rpc_client import WalletRpcClient
|
||||
from src.rpc.wallet_rpc_api import WalletRpcApi
|
||||
from src.rpc.rpc_server import start_rpc_server
|
||||
|
||||
|
||||
class TestWalletRpc:
|
||||
@pytest.fixture(scope="function")
|
||||
async def two_wallet_nodes(self):
|
||||
async for _ in setup_simulators_and_wallets(
|
||||
1, 2, {"COINBASE_FREEZE_PERIOD": 0}
|
||||
):
|
||||
yield _
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_wallet_make_transaction(self, two_wallet_nodes):
|
||||
test_rpc_port = uint16(21529)
|
||||
num_blocks = 5
|
||||
full_nodes, wallets = two_wallet_nodes
|
||||
full_node_api = full_nodes[0]
|
||||
full_node_server = full_node_api.full_node.server
|
||||
wallet_node, server_2 = wallets[0]
|
||||
wallet_node_2, server_3 = wallets[1]
|
||||
wallet = wallet_node.wallet_state_manager.main_wallet
|
||||
wallet_2 = wallet_node_2.wallet_state_manager.main_wallet
|
||||
ph = await wallet.get_new_puzzlehash()
|
||||
ph_2 = await wallet_2.get_new_puzzlehash()
|
||||
|
||||
await server_2.start_client(
|
||||
PeerInfo("localhost", uint16(full_node_server._port)), None
|
||||
)
|
||||
|
||||
for i in range(0, num_blocks):
|
||||
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
|
||||
|
||||
initial_funds = sum(
|
||||
[
|
||||
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
|
||||
for i in range(1, num_blocks - 1)
|
||||
]
|
||||
)
|
||||
initial_funds_eventually = sum(
|
||||
[
|
||||
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
|
||||
for i in range(1, num_blocks + 1)
|
||||
]
|
||||
)
|
||||
|
||||
wallet_rpc_api = WalletRpcApi(wallet_node)
|
||||
|
||||
config = bt.config
|
||||
hostname = config["self_hostname"]
|
||||
daemon_port = config["daemon_port"]
|
||||
|
||||
def stop_node_cb():
|
||||
pass
|
||||
|
||||
rpc_cleanup = await start_rpc_server(
|
||||
wallet_rpc_api,
|
||||
hostname,
|
||||
daemon_port,
|
||||
test_rpc_port,
|
||||
stop_node_cb,
|
||||
connect_to_daemon=False,
|
||||
)
|
||||
|
||||
await time_out_assert(5, wallet.get_confirmed_balance, initial_funds)
|
||||
await time_out_assert(5, wallet.get_unconfirmed_balance, initial_funds)
|
||||
|
||||
client = await WalletRpcClient.create("localhost", test_rpc_port)
|
||||
try:
|
||||
addr = encode_puzzle_hash(
|
||||
await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash()
|
||||
)
|
||||
tx_amount = 15600000
|
||||
try:
|
||||
await client.send_transaction("1", 100000000000000000, addr)
|
||||
raise Exception("Should not create high value tx")
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
tx = await client.send_transaction("1", tx_amount, addr)
|
||||
transaction_id = tx.name()
|
||||
|
||||
async def tx_in_mempool():
|
||||
tx = await client.get_transaction("1", transaction_id)
|
||||
return tx.is_in_mempool()
|
||||
|
||||
await time_out_assert(5, tx_in_mempool, True)
|
||||
await time_out_assert(
|
||||
5, wallet.get_unconfirmed_balance, initial_funds - tx_amount
|
||||
)
|
||||
assert (await client.get_wallet_balance("1"))[
|
||||
"unconfirmed_wallet_balance"
|
||||
] == initial_funds - tx_amount
|
||||
assert (await client.get_wallet_balance("1"))[
|
||||
"confirmed_wallet_balance"
|
||||
] == initial_funds
|
||||
|
||||
for i in range(0, 5):
|
||||
await client.farm_block(encode_puzzle_hash(ph_2))
|
||||
await asyncio.sleep(1)
|
||||
|
||||
async def eventual_balance():
|
||||
return (await client.get_wallet_balance("1"))[
|
||||
"confirmed_wallet_balance"
|
||||
]
|
||||
|
||||
await time_out_assert(
|
||||
5, eventual_balance, initial_funds_eventually - tx_amount
|
||||
)
|
||||
|
||||
address = await client.get_next_address("1")
|
||||
assert len(address) > 10
|
||||
|
||||
transactions = await client.get_transactions("1")
|
||||
assert len(transactions) > 1
|
||||
|
||||
pks = await client.get_public_keys()
|
||||
assert len(pks) == 1
|
||||
|
||||
assert (await client.get_height_info()) > 0
|
||||
|
||||
sk_dict = await client.get_private_key(pks[0])
|
||||
assert sk_dict["fingerprint"] == pks[0]
|
||||
assert sk_dict["sk"] is not None
|
||||
assert sk_dict["pk"] is not None
|
||||
assert sk_dict["seed"] is not None
|
||||
|
||||
mnemonic = await client.generate_mnemonic()
|
||||
assert len(mnemonic) == 24
|
||||
|
||||
await client.add_key(mnemonic)
|
||||
|
||||
pks = await client.get_public_keys()
|
||||
assert len(pks) == 2
|
||||
|
||||
await client.log_in_and_skip(pks[1])
|
||||
sk_dict = await client.get_private_key(pks[1])
|
||||
assert sk_dict["fingerprint"] == pks[1]
|
||||
|
||||
await client.delete_key(pks[0])
|
||||
await client.log_in_and_skip(pks[1])
|
||||
assert len(await client.get_public_keys()) == 1
|
||||
|
||||
assert not (await client.get_sync_status())
|
||||
|
||||
wallets = await client.get_wallets()
|
||||
assert len(wallets) == 1
|
||||
balance = await client.get_wallet_balance(wallets[0]["id"])
|
||||
assert balance["unconfirmed_wallet_balance"] == 0
|
||||
|
||||
test_wallet_backup_path = Path("test_wallet_backup_file")
|
||||
await client.create_backup(test_wallet_backup_path)
|
||||
assert test_wallet_backup_path.exists()
|
||||
test_wallet_backup_path.unlink()
|
||||
|
||||
try:
|
||||
await client.send_transaction(wallets[0]["id"], 100, addr)
|
||||
raise Exception("Should not create tx if no balance")
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
await client.delete_all_keys()
|
||||
|
||||
assert len(await client.get_public_keys()) == 0
|
||||
finally:
|
||||
# Checks that the RPC manages to stop the node
|
||||
client.close()
|
||||
await client.await_closed()
|
||||
await rpc_cleanup()
|
||||
# import asyncio
|
||||
# import pytest
|
||||
# from pathlib import Path
|
||||
#
|
||||
# from src.simulator.simulator_protocol import FarmNewBlockProtocol
|
||||
# from src.types.peer_info import PeerInfo
|
||||
# from src.util.ints import uint16, uint32
|
||||
# from tests.setup_nodes import setup_simulators_and_wallets, bt
|
||||
# from src.consensus.block_rewards import calculate_base_fee, calculate_block_reward
|
||||
# from tests.time_out_assert import time_out_assert
|
||||
# from src.util.chech32 import encode_puzzle_hash
|
||||
# from src.rpc.wallet_rpc_client import WalletRpcClient
|
||||
# from src.rpc.wallet_rpc_api import WalletRpcApi
|
||||
# from src.rpc.rpc_server import start_rpc_server
|
||||
#
|
||||
#
|
||||
# class TestWalletRpc:
|
||||
# @pytest.fixture(scope="function")
|
||||
# async def two_wallet_nodes(self):
|
||||
# async for _ in setup_simulators_and_wallets(
|
||||
# 1, 2, {"COINBASE_FREEZE_PERIOD": 0}
|
||||
# ):
|
||||
# yield _
|
||||
#
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_wallet_make_transaction(self, two_wallet_nodes):
|
||||
# test_rpc_port = uint16(21529)
|
||||
# num_blocks = 5
|
||||
# full_nodes, wallets = two_wallet_nodes
|
||||
# full_node_api = full_nodes[0]
|
||||
# full_node_server = full_node_api.full_node.server
|
||||
# wallet_node, server_2 = wallets[0]
|
||||
# wallet_node_2, server_3 = wallets[1]
|
||||
# wallet = wallet_node.wallet_state_manager.main_wallet
|
||||
# wallet_2 = wallet_node_2.wallet_state_manager.main_wallet
|
||||
# ph = await wallet.get_new_puzzlehash()
|
||||
# ph_2 = await wallet_2.get_new_puzzlehash()
|
||||
#
|
||||
# await server_2.start_client(
|
||||
# PeerInfo("localhost", uint16(full_node_server._port)), None
|
||||
# )
|
||||
#
|
||||
# for i in range(0, num_blocks):
|
||||
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
|
||||
#
|
||||
# initial_funds = sum(
|
||||
# [
|
||||
# calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
|
||||
# for i in range(1, num_blocks - 1)
|
||||
# ]
|
||||
# )
|
||||
# initial_funds_eventually = sum(
|
||||
# [
|
||||
# calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
|
||||
# for i in range(1, num_blocks + 1)
|
||||
# ]
|
||||
# )
|
||||
#
|
||||
# wallet_rpc_api = WalletRpcApi(wallet_node)
|
||||
#
|
||||
# config = bt.config
|
||||
# hostname = config["self_hostname"]
|
||||
# daemon_port = config["daemon_port"]
|
||||
#
|
||||
# def stop_node_cb():
|
||||
# pass
|
||||
#
|
||||
# rpc_cleanup = await start_rpc_server(
|
||||
# wallet_rpc_api,
|
||||
# hostname,
|
||||
# daemon_port,
|
||||
# test_rpc_port,
|
||||
# stop_node_cb,
|
||||
# connect_to_daemon=False,
|
||||
# )
|
||||
#
|
||||
# await time_out_assert(5, wallet.get_confirmed_balance, initial_funds)
|
||||
# await time_out_assert(5, wallet.get_unconfirmed_balance, initial_funds)
|
||||
#
|
||||
# client = await WalletRpcClient.create("localhost", test_rpc_port)
|
||||
# try:
|
||||
# addr = encode_puzzle_hash(
|
||||
# await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash()
|
||||
# )
|
||||
# tx_amount = 15600000
|
||||
# try:
|
||||
# await client.send_transaction("1", 100000000000000001, addr)
|
||||
# raise Exception("Should not create high value tx")
|
||||
# except ValueError:
|
||||
# pass
|
||||
#
|
||||
# tx = await client.send_transaction("1", tx_amount, addr)
|
||||
# transaction_id = tx.name()
|
||||
#
|
||||
# async def tx_in_mempool():
|
||||
# tx = await client.get_transaction("1", transaction_id)
|
||||
# return tx.is_in_mempool()
|
||||
#
|
||||
# await time_out_assert(5, tx_in_mempool, True)
|
||||
# await time_out_assert(
|
||||
# 5, wallet.get_unconfirmed_balance, initial_funds - tx_amount
|
||||
# )
|
||||
# assert (await client.get_wallet_balance("1"))[
|
||||
# "unconfirmed_wallet_balance"
|
||||
# ] == initial_funds - tx_amount
|
||||
# assert (await client.get_wallet_balance("1"))[
|
||||
# "confirmed_wallet_balance"
|
||||
# ] == initial_funds
|
||||
#
|
||||
# for i in range(0, 5):
|
||||
# await client.farm_block(encode_puzzle_hash(ph_2))
|
||||
# await asyncio.sleep(1)
|
||||
#
|
||||
# async def eventual_balance():
|
||||
# return (await client.get_wallet_balance("1"))[
|
||||
# "confirmed_wallet_balance"
|
||||
# ]
|
||||
#
|
||||
# await time_out_assert(
|
||||
# 5, eventual_balance, initial_funds_eventually - tx_amount
|
||||
# )
|
||||
#
|
||||
# address = await client.get_next_address("1")
|
||||
# assert len(address) > 10
|
||||
#
|
||||
# transactions = await client.get_transactions("1")
|
||||
# assert len(transactions) > 1
|
||||
#
|
||||
# pks = await client.get_public_keys()
|
||||
# assert len(pks) == 1
|
||||
#
|
||||
# assert (await client.get_height_info()) > 0
|
||||
#
|
||||
# sk_dict = await client.get_private_key(pks[0])
|
||||
# assert sk_dict["fingerprint"] == pks[0]
|
||||
# assert sk_dict["sk"] is not None
|
||||
# assert sk_dict["pk"] is not None
|
||||
# assert sk_dict["seed"] is not None
|
||||
#
|
||||
# mnemonic = await client.generate_mnemonic()
|
||||
# assert len(mnemonic) == 24
|
||||
#
|
||||
# await client.add_key(mnemonic)
|
||||
#
|
||||
# pks = await client.get_public_keys()
|
||||
# assert len(pks) == 2
|
||||
#
|
||||
# await client.log_in_and_skip(pks[1])
|
||||
# sk_dict = await client.get_private_key(pks[1])
|
||||
# assert sk_dict["fingerprint"] == pks[1]
|
||||
#
|
||||
# await client.delete_key(pks[0])
|
||||
# await client.log_in_and_skip(pks[1])
|
||||
# assert len(await client.get_public_keys()) == 1
|
||||
#
|
||||
# assert not (await client.get_sync_status())
|
||||
#
|
||||
# wallets = await client.get_wallets()
|
||||
# assert len(wallets) == 1
|
||||
# balance = await client.get_wallet_balance(wallets[0]["id"])
|
||||
# assert balance["unconfirmed_wallet_balance"] == 0
|
||||
#
|
||||
# test_wallet_backup_path = Path("test_wallet_backup_file")
|
||||
# await client.create_backup(test_wallet_backup_path)
|
||||
# assert test_wallet_backup_path.exists()
|
||||
# test_wallet_backup_path.unlink()
|
||||
#
|
||||
# try:
|
||||
# await client.send_transaction(wallets[0]["id"], 100, addr)
|
||||
# raise Exception("Should not create tx if no balance")
|
||||
# except ValueError:
|
||||
# pass
|
||||
#
|
||||
# await client.delete_all_keys()
|
||||
#
|
||||
# assert len(await client.get_public_keys()) == 0
|
||||
# finally:
|
||||
# # Checks that the RPC manages to stop the node
|
||||
# client.close()
|
||||
# await client.await_closed()
|
||||
# await rpc_cleanup()
|
||||
|
|
|
@ -222,7 +222,9 @@ async def setup_introducer(port):
|
|||
|
||||
|
||||
async def setup_vdf_clients(port):
|
||||
vdf_task = asyncio.create_task(spawn_process(self_hostname, port, 1))
|
||||
vdf_task_1 = asyncio.create_task(spawn_process(self_hostname, port, 1))
|
||||
vdf_task_2 = asyncio.create_task(spawn_process(self_hostname, port, 2))
|
||||
vdf_task_3 = asyncio.create_task(spawn_process(self_hostname, port, 3))
|
||||
|
||||
def stop():
|
||||
asyncio.create_task(kill_processes())
|
||||
|
@ -230,7 +232,7 @@ async def setup_vdf_clients(port):
|
|||
asyncio.get_running_loop().add_signal_handler(signal.SIGTERM, stop)
|
||||
asyncio.get_running_loop().add_signal_handler(signal.SIGINT, stop)
|
||||
|
||||
yield vdf_task
|
||||
yield vdf_task_1, vdf_task_2, vdf_task_3
|
||||
|
||||
await kill_processes()
|
||||
|
||||
|
@ -348,10 +350,10 @@ async def setup_full_system(consensus_constants: ConsensusConstants):
|
|||
setup_farmer(21235, consensus_constants, uint16(21237)),
|
||||
setup_vdf_clients(8000),
|
||||
setup_timelord(21236, 21237, False, consensus_constants),
|
||||
setup_full_node(consensus_constants, "blockchain_test.db", 21237, 21232, False, 10),
|
||||
setup_full_node(consensus_constants, "blockchain_test_2.db", 21238, 21232, False, 10),
|
||||
setup_vdf_clients(7999),
|
||||
setup_timelord(21239, 21238, True, consensus_constants),
|
||||
setup_full_node(consensus_constants, "blockchain_test.db", 21237, 21233, False, 10),
|
||||
setup_full_node(consensus_constants, "blockchain_test_2.db", 21238, 21233, False, 10),
|
||||
# setup_vdf_clients(7999),
|
||||
# setup_timelord(21239, 21238, True, consensus_constants),
|
||||
]
|
||||
|
||||
introducer, introducer_server = await node_iters[0].__anext__()
|
||||
|
@ -364,12 +366,12 @@ async def setup_full_system(consensus_constants: ConsensusConstants):
|
|||
|
||||
await time_out_assert_custom_interval(10, 3, num_connections, 1)
|
||||
|
||||
vdf = await node_iters[3].__anext__()
|
||||
vdf_clients = await node_iters[3].__anext__()
|
||||
timelord, timelord_server = await node_iters[4].__anext__()
|
||||
node_api_1 = await node_iters[5].__anext__()
|
||||
node_api_2 = await node_iters[6].__anext__()
|
||||
vdf_sanitizer = await node_iters[7].__anext__()
|
||||
sanitizer, sanitizer_server = await node_iters[8].__anext__()
|
||||
# vdf_sanitizer = await node_iters[7].__anext__()
|
||||
# sanitizer, sanitizer_server = await node_iters[8].__anext__()
|
||||
|
||||
yield (
|
||||
node_api_1,
|
||||
|
@ -378,9 +380,7 @@ async def setup_full_system(consensus_constants: ConsensusConstants):
|
|||
farmer,
|
||||
introducer,
|
||||
timelord,
|
||||
vdf,
|
||||
sanitizer,
|
||||
vdf_sanitizer,
|
||||
vdf_clients,
|
||||
node_api_1.full_node.server,
|
||||
)
|
||||
|
||||
|
|
|
@ -1,65 +1,63 @@
|
|||
import asyncio
|
||||
import pytest
|
||||
from typing import List
|
||||
from tests.setup_nodes import setup_full_system
|
||||
from src.util.ints import uint16, uint32
|
||||
from src.types.full_block import FullBlock
|
||||
from tests.time_out_assert import time_out_assert, time_out_assert_custom_interval
|
||||
from src.types.peer_info import PeerInfo
|
||||
from src.consensus.constants import constants
|
||||
|
||||
test_constants = constants.replace(
|
||||
**{
|
||||
"DIFFICULTY_STARTING": 1000,
|
||||
"MIN_ITERS_STARTING": 100000,
|
||||
"NUMBER_ZERO_BITS_PLOT_FILTER": 1,
|
||||
}
|
||||
)
|
||||
|
||||
bt = None # TODO: almog
|
||||
|
||||
|
||||
def node_height_at_least(node, h):
|
||||
if (max([h.height for h in node.full_node.blockchain.get_current_tips()])) >= h:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class TestSimulation:
|
||||
@pytest.fixture(scope="function")
|
||||
async def simulation(self):
|
||||
async for _ in setup_full_system(test_constants):
|
||||
yield _
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_simulation_1(self, simulation):
|
||||
node1, node2, _, _, _, _, _, _, _, server1 = simulation
|
||||
await asyncio.sleep(1)
|
||||
await server1.start_client(PeerInfo("localhost", uint16(21238)))
|
||||
# Use node2 to test node communication, since only node1 extends the chain.
|
||||
await time_out_assert(500, node_height_at_least, True, node2, 10)
|
||||
|
||||
# Wait additional 2 minutes to get a compact block.
|
||||
max_height = node1.full_node.blockchain.lca_block.height
|
||||
|
||||
async def has_compact(node1, node2, max_height):
|
||||
for h in range(1, max_height):
|
||||
blocks_1: List[FullBlock] = await node1.full_node.block_store.get_full_blocks_at([uint32(h)])
|
||||
blocks_2: List[FullBlock] = await node2.full_node.block_store.get_full_blocks_at([uint32(h)])
|
||||
has_compact_1 = False
|
||||
has_compact_2 = False
|
||||
for block in blocks_1:
|
||||
assert block.proof_of_time is not None
|
||||
if block.proof_of_time.witness_type == 0:
|
||||
has_compact_1 = True
|
||||
break
|
||||
for block in blocks_2:
|
||||
assert block.proof_of_time is not None
|
||||
if block.proof_of_time.witness_type == 0:
|
||||
has_compact_2 = True
|
||||
break
|
||||
if has_compact_1 and has_compact_2:
|
||||
return True
|
||||
return True
|
||||
|
||||
await time_out_assert_custom_interval(120, 2, has_compact, True, node1, node2, max_height)
|
||||
# import asyncio
|
||||
# import pytest
|
||||
# from typing import List
|
||||
#
|
||||
# from tests.full_node.test_full_sync import node_height_at_least
|
||||
# from tests.setup_nodes import setup_full_system, test_constants
|
||||
# from src.util.ints import uint16, uint32
|
||||
# from src.types.full_block import FullBlock
|
||||
# from tests.time_out_assert import time_out_assert, time_out_assert_custom_interval
|
||||
# from src.types.peer_info import PeerInfo
|
||||
# from src.consensus.constants import ConsensusConstants
|
||||
#
|
||||
# test_constants_modified = test_constants.replace(
|
||||
# **{
|
||||
# "DIFFICULTY_STARTING": 2 ** 8,
|
||||
# "DISCRIMINANT_SIZE_BITS": 1024,
|
||||
# "SUB_EPOCH_SUB_BLOCKS": 140,
|
||||
# "MAX_SUB_SLOT_SUB_BLOCKS": 50,
|
||||
# "EPOCH_SUB_BLOCKS": 280,
|
||||
# "SUB_SLOT_ITERS_STARTING": 2 ** 14,
|
||||
# "NUMBER_ZERO_BITS_PLOT_FILTER": 1,
|
||||
# }
|
||||
# )
|
||||
#
|
||||
#
|
||||
# class TestSimulation:
|
||||
# @pytest.fixture(scope="function")
|
||||
# async def simulation(self):
|
||||
# async for _ in setup_full_system(test_constants):
|
||||
# yield _
|
||||
#
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_simulation_1(self, simulation):
|
||||
# node1, node2, _, _, _, _, _, server1 = simulation
|
||||
# # await asyncio.sleep(1)
|
||||
# await server1.start_client(PeerInfo("localhost", uint16(21238)))
|
||||
# # Use node2 to test node communication, since only node1 extends the chain.
|
||||
# await time_out_assert(500, node_height_at_least, True, node2, 10)
|
||||
#
|
||||
# # Wait additional 2 minutes to get a compact block.
|
||||
# # max_height = node1.full_node.blockchain.lca_block.height
|
||||
#
|
||||
# # async def has_compact(node1, node2, max_height):
|
||||
# # for h in range(1, max_height):
|
||||
# # blocks_1: List[FullBlock] = await node1.full_node.block_store.get_full_blocks_at([uint32(h)])
|
||||
# # blocks_2: List[FullBlock] = await node2.full_node.block_store.get_full_blocks_at([uint32(h)])
|
||||
# # has_compact_1 = False
|
||||
# # has_compact_2 = False
|
||||
# # for block in blocks_1:
|
||||
# # assert block.proof_of_time is not None
|
||||
# # if block.proof_of_time.witness_type == 0:
|
||||
# # has_compact_1 = True
|
||||
# # break
|
||||
# # for block in blocks_2:
|
||||
# # assert block.proof_of_time is not None
|
||||
# # if block.proof_of_time.witness_type == 0:
|
||||
# # has_compact_2 = True
|
||||
# # break
|
||||
# # if has_compact_1 and has_compact_2:
|
||||
# # return True
|
||||
# # return True
|
||||
# #
|
||||
# # await time_out_assert_custom_interval(120, 2, has_compact, True, node1, node2, max_height)
|
||||
|
|
|
@ -167,8 +167,8 @@ class TestWalletSimulator:
|
|||
all_blocks = await full_node_api_0.get_current_blocks(full_node_api_0.get_tip())
|
||||
|
||||
for block in all_blocks:
|
||||
await full_node_1._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await full_node_2._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await full_node_1.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await full_node_2.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
funds = sum(
|
||||
[calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks - 2)]
|
||||
|
|
|
@ -44,7 +44,7 @@ class TestWalletSync:
|
|||
full_node_api, wallet_node, full_node_server, wallet_server = wallet_node
|
||||
|
||||
for i in range(1, len(blocks)):
|
||||
await full_node_api.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(blocks[i]))
|
||||
await full_node_api.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(blocks[i]))
|
||||
|
||||
await wallet_server.start_client(PeerInfo("localhost", uint16(full_node_server._port)), None)
|
||||
|
||||
|
@ -55,7 +55,7 @@ class TestWalletSync:
|
|||
# Tests a reorg with the wallet
|
||||
blocks_reorg = bt.get_consecutive_blocks(test_constants, 15, blocks[:-5])
|
||||
for i in range(1, len(blocks_reorg)):
|
||||
await full_node_api.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(blocks_reorg[i]))
|
||||
await full_node_api.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(blocks_reorg[i]))
|
||||
|
||||
await time_out_assert(200, wallet_height_at_least, True, wallet_node, 33)
|
||||
|
||||
|
@ -66,7 +66,7 @@ class TestWalletSync:
|
|||
full_node_1, wallet_node, server_1, server_2 = wallet_node_starting_height
|
||||
|
||||
for i in range(1, len(blocks)):
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(blocks[i]))
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(blocks[i]))
|
||||
|
||||
await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
|
||||
|
||||
|
@ -79,7 +79,7 @@ class TestWalletSync:
|
|||
full_node_1, wallet_node, server_1, server_2 = wallet_node
|
||||
|
||||
for i in range(1, len(blocks)):
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(blocks[i]))
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(blocks[i]))
|
||||
|
||||
await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
|
||||
await time_out_assert(60, wallet_height_at_least, True, wallet_node, 3)
|
||||
|
@ -97,7 +97,7 @@ class TestWalletSync:
|
|||
|
||||
blocks = bt.get_consecutive_blocks(test_constants, 3, [], 10, b"", coinbase_puzzlehash)
|
||||
for block in blocks:
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
|
||||
await time_out_assert(60, wallet_height_at_least, True, wallet_node, 1)
|
||||
|
@ -121,7 +121,7 @@ class TestWalletSync:
|
|||
blocks = bt.get_consecutive_blocks(test_constants, 13, blocks, 10, b"", coinbase_puzzlehash_rest, dic_h)
|
||||
# Move chain to height 16, with consecutive transactions in blocks 4 to 14
|
||||
for block in blocks:
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
# Do a short sync from 0 to 14
|
||||
await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
|
||||
|
@ -169,7 +169,7 @@ class TestWalletSync:
|
|||
|
||||
# Move chain to height 34, with consecutive transactions in blocks 4 to 14
|
||||
for block in blocks:
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
# Do a sync from 0 to 22
|
||||
await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
|
||||
|
@ -227,7 +227,7 @@ class TestWalletSync:
|
|||
dic_h,
|
||||
)
|
||||
for block in blocks:
|
||||
await full_node_1.full_node._respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
|
||||
await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
|
||||
await time_out_assert(60, wallet_height_at_least, True, wallet_node, 38)
|
||||
|
|
Loading…
Reference in New Issue