Got simulation test to pass

This commit is contained in:
Mariano Sorgente 2020-12-09 23:54:15 +09:00 committed by Yostra
parent 1ccd1632ef
commit fff9ccb026
27 changed files with 2076 additions and 2081 deletions

View File

@ -126,7 +126,7 @@ async def validate_block_body(
pool_coin = create_pool_coin(
curr_sb.height,
curr_sb.pool_puzzle_hash,
calculate_pool_reward(height, curr_sb.sub_block_height == 0),
calculate_pool_reward(height),
)
farmer_coin = create_farmer_coin(
curr_sb.sub_block_height,
@ -140,19 +140,20 @@ async def validate_block_body(
# For the second block in the chain, don't go back further
if curr_sb.height > 0:
curr_sb = sub_blocks[curr_sb.prev_hash]
curr_height = curr_sb.height
while not curr_sb.is_block:
expected_reward_coins.add(
create_pool_coin(
curr_sb.sub_block_height,
curr_sb.pool_puzzle_hash,
calculate_pool_reward(block.height, sub_height == 0),
calculate_pool_reward(curr_height),
)
)
expected_reward_coins.add(
create_farmer_coin(
curr_sb.sub_block_height,
curr_sb.farmer_puzzle_hash,
calculate_base_farmer_reward(block.height),
calculate_base_farmer_reward(curr_height),
)
)
curr_sb = sub_blocks[curr_sb.prev_hash]
@ -267,7 +268,9 @@ async def validate_block_body(
if rem in additions_dic:
# Ephemeral coin
rem_coin: Coin = additions_dic[rem]
new_unspent: CoinRecord = CoinRecord(rem_coin, sub_height, uint32(0), False, False, block.foliage_block.timestamp)
new_unspent: CoinRecord = CoinRecord(
rem_coin, sub_height, uint32(0), False, False, block.foliage_block.timestamp
)
removal_coin_records[new_unspent.name] = new_unspent
else:
unspent = await coin_store.get_coin_record(rem)
@ -299,7 +302,7 @@ async def validate_block_body(
uint32(0),
False,
(rem in coinbases_since_fork),
block.foliage_block.timestamp
block.foliage_block.timestamp,
)
removal_coin_records[new_coin_record.name] = new_coin_record
@ -351,11 +354,7 @@ async def validate_block_body(
for npc in npc_list:
unspent = removal_coin_records[npc.coin_name]
error = blockchain_check_conditions_dict(
unspent,
removal_coin_records,
npc.condition_dict,
height,
block.foliage_block.timestamp
unspent, removal_coin_records, npc.condition_dict, height, block.foliage_block.timestamp
)
if error:
return error

View File

@ -93,7 +93,6 @@ def create_foliage(
else:
height: uint32 = uint32(prev_block.height)
# Create filter
byte_array_tx: List[bytes32] = []
tx_additions: List[Coin] = []
@ -142,22 +141,19 @@ def create_foliage(
reward_claims_incorporated = [pool_coin, farmer_coin]
if sub_block_height > 0:
curr: SubBlockRecord = prev_sub_block
if curr.is_block and curr.prev_hash != constants.GENESIS_PREV_HASH:
block_height = curr.height + 1
else:
block_height = curr.height
while not curr.is_block:
curr = sub_blocks[curr.prev_hash]
pool_coin = create_pool_coin(
curr.sub_block_height,
curr.pool_puzzle_hash,
calculate_pool_reward(block_height, curr.prev_hash == constants.GENESIS_PREV_HASH),
calculate_pool_reward(curr.height),
)
farmer_coin = create_farmer_coin(
curr.sub_block_height,
curr.farmer_puzzle_hash,
calculate_base_farmer_reward(block_height) + curr.fees,
calculate_base_farmer_reward(curr.height) + curr.fees,
)
assert curr.header_hash == prev_block.header_hash
reward_claims_incorporated += [pool_coin, farmer_coin]
@ -169,7 +165,7 @@ def create_foliage(
pool_coin = create_pool_coin(
curr.sub_block_height,
curr.pool_puzzle_hash,
calculate_pool_reward(curr.height, False),
calculate_pool_reward(curr.height),
)
farmer_coin = create_farmer_coin(
curr.sub_block_height,

View File

@ -644,6 +644,7 @@ async def validate_unfinished_header_block(
header_block.foliage_sub_block.foliage_sub_block_data.pool_target.puzzle_hash
!= constants.GENESIS_PRE_FARM_POOL_PUZZLE_HASH
):
log.error(f"Pool target {header_block.foliage_sub_block.foliage_sub_block_data.pool_target}")
return None, ValidationError(Err.INVALID_PREFARM)
else:
# 20b. Check pool target signature. Should not check this for genesis sub-block.
@ -805,6 +806,12 @@ async def validate_finished_header_block(
cc_target_vdf_info,
number_of_iterations=ip_iters,
):
expected = dataclasses.replace(
cc_target_vdf_info,
number_of_iterations=ip_iters,
)
log.error(f"{header_block.reward_chain_sub_block.challenge_chain_ip_vdf }. expected {expected}")
log.error(f"Block: {header_block}")
return None, ValidationError(Err.INVALID_CC_IP_VDF)
if not header_block.challenge_chain_ip_proof.is_valid(
constants,
@ -812,6 +819,8 @@ async def validate_finished_header_block(
cc_target_vdf_info,
None,
):
log.error(f"Did not validate, output {cc_vdf_output}")
log.error(f"Block: {header_block}")
return None, ValidationError(Err.INVALID_CC_IP_VDF)
# 30. Check reward chain infusion point VDF

View File

@ -237,9 +237,9 @@ class Blockchain:
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
coin_store_reorg_height = last_sb_in_common.height
else:
coin_store_reorg_height = last_sb_in_common.prev_block_height
coin_store_reorg_height = last_sb_in_common.height - 1
# Rollback to fork
await self.coin_store.rollback_to_block(coin_store_reorg_height)

View File

@ -57,6 +57,10 @@ class Farmer:
self.keychain = keychain
self.state_changed_callback: Optional[Callable] = None
self.log = log
all_sks = self.keychain.get_all_private_keys()
self._private_keys = [master_sk_to_farmer_sk(sk) for sk, _ in all_sks] + [
master_sk_to_pool_sk(sk) for sk, _ in all_sks
]
if len(self.get_public_keys()) == 0:
error_str = "No keys exist. Please run 'chia keys generate' or open the UI."
@ -108,11 +112,10 @@ class Farmer:
self.state_changed_callback(change)
def get_public_keys(self):
return [child_sk.get_g1() for child_sk in self.get_private_keys()]
return [child_sk.get_g1() for child_sk in self._private_keys]
def get_private_keys(self):
all_sks = self.keychain.get_all_private_keys()
return [master_sk_to_farmer_sk(sk) for sk, _ in all_sks] + [master_sk_to_pool_sk(sk) for sk, _ in all_sks]
return self._private_keys
async def _periodically_clear_cache_task(self):
time_slept: uint64 = uint64(0)

View File

@ -102,6 +102,9 @@ class FarmerAPI:
"""
There are two cases: receiving signatures for sps, or receiving signatures for the block.
"""
import time
start = time.time()
if response.sp_hash not in self.farmer.sps:
self.farmer.log.warning(f"Do not have challenge hash {response.challenge_hash}")
return

View File

@ -76,7 +76,9 @@ class CoinStore:
assert len(included_reward_coins) >= 2
for coin in included_reward_coins:
reward_coin_r: CoinRecord = CoinRecord(coin, block.height, uint32(0), False, True, block.foliage_block.timestamp)
reward_coin_r: CoinRecord = CoinRecord(
coin, block.height, uint32(0), False, True, block.foliage_block.timestamp
)
await self._add_coin_record(reward_coin_r)
# Checks DB and DiffStores for CoinRecord with coin_name and returns it
@ -119,6 +121,7 @@ class CoinStore:
coin_record.spent_block_index,
False,
coin_record.coinbase,
coin_record.timestamp,
)
self.coin_record_cache[coin_record.coin.name().hex()] = new_record
if int(coin_record.confirmed_block_index) > block_index:
@ -160,7 +163,7 @@ class CoinStore:
str(record.coin.puzzle_hash.hex()),
str(record.coin.parent_coin_info.hex()),
record.coin.amount,
record.timestamp
record.timestamp,
),
)
await cursor.close()
@ -177,11 +180,6 @@ class CoinStore:
if current is None:
return
spent: CoinRecord = CoinRecord(
current.coin,
current.confirmed_block_index,
index,
True,
current.coinbase,
current.timestamp
current.coin, current.confirmed_block_index, index, True, current.coinbase, current.timestamp
) # type: ignore # noqa
await self._add_coin_record(spent)

View File

@ -4,9 +4,10 @@ import logging
import time
import traceback
from pathlib import Path
from typing import AsyncGenerator, Optional, Dict, Callable, List, Tuple, Any
from typing import AsyncGenerator, Optional, Dict, Callable, List, Tuple, Any, Union
import aiosqlite
from blspy import AugSchemeMPL
import src.server.ws_connection as ws
from src.consensus.blockchain import Blockchain, ReceiveBlockResult
@ -34,6 +35,7 @@ from src.server.outbound_message import Message, NodeType, OutboundMessage
from src.server.server import ChiaServer
from src.server.ws_connection import WSChiaConnection
from src.types.full_block import FullBlock
from src.types.pool_target import PoolTarget
from src.types.sized_bytes import bytes32
from src.types.sub_epoch_summary import SubEpochSummary
from src.types.unfinished_block import UnfinishedBlock
@ -435,6 +437,20 @@ class FullNode:
await self.server.send_to_all([msg], NodeType.WALLET)
self._state_changed("sub_block")
def has_valid_pool_sig(self, block: Union[UnfinishedBlock, FullBlock]):
if (
block.foliage_sub_block.foliage_sub_block_data.pool_target
== PoolTarget(self.constants.GENESIS_PRE_FARM_POOL_PUZZLE_HASH, uint32(0))
and block.foliage_sub_block.prev_sub_block_hash != self.constants.GENESIS_PREV_HASH
):
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,
):
return False
return True
async def respond_sub_block(
self, respond_sub_block: full_node_protocol.RespondSubBlock, peer: Optional[ws.WSChiaConnection] = None
):
@ -734,7 +750,9 @@ class FullNode:
if block.reward_chain_sub_block.signage_point_index == 0:
res = self.full_node_store.get_sub_slot(block.reward_chain_sub_block.pos_ss_cc_challenge_hash)
assert res is not None
if res is None:
self.log.warning(f"Do not have sub slot {block.reward_chain_sub_block.pos_ss_cc_challenge_hash}")
return
rc_prev = res[0].reward_chain.get_hash()
else:
rc_prev = block.reward_chain_sub_block.reward_chain_sp_vdf.challenge

View File

@ -213,7 +213,8 @@ class FullNodeAPI:
"""
Receive a full block from a peer full node (or ourselves).
"""
return await self.full_node.respond_sub_block(respond_sub_block, peer)
async with self.full_node.timelord_lock:
return await self.full_node.respond_sub_block(respond_sub_block, peer)
@api_request
async def new_unfinished_sub_block(
@ -409,68 +410,70 @@ class FullNodeAPI:
async def respond_end_of_sub_slot(
self, request: full_node_protocol.RespondEndOfSubSlot, peer: ws.WSChiaConnection
) -> Optional[Message]:
fetched_ss = self.full_node.full_node_store.get_sub_slot(
request.end_of_slot_bundle.challenge_chain.challenge_chain_end_of_slot_vdf.challenge
)
if (
(fetched_ss is None)
and request.end_of_slot_bundle.challenge_chain.challenge_chain_end_of_slot_vdf.challenge
!= self.full_node.constants.FIRST_CC_CHALLENGE
):
# If we don't have the prev, request the prev instead
full_node_request = full_node_protocol.RequestSignagePointOrEndOfSubSlot(
request.end_of_slot_bundle.challenge_chain.challenge_chain_end_of_slot_vdf.challenge,
uint8(0),
bytes([0] * 32),
)
return Message("request_signage_point_or_end_of_sub_slot", full_node_request)
peak = self.full_node.blockchain.get_peak()
if peak is not None and peak.sub_block_height > 2:
next_sub_slot_iters = self.full_node.blockchain.get_next_slot_iters(peak.header_hash, True)
next_difficulty = self.full_node.blockchain.get_next_difficulty(peak.header_hash, True)
else:
next_sub_slot_iters = self.full_node.constants.SUB_SLOT_ITERS_STARTING
next_difficulty = self.full_node.constants.DIFFICULTY_STARTING
# Adds the sub slot and potentially get new infusions
new_infusions = self.full_node.full_node_store.new_finished_sub_slot(
request.end_of_slot_bundle, self.full_node.blockchain.sub_blocks, self.full_node.blockchain.get_peak()
)
# It may be an empty list, even if it's not None. Not None means added successfully
if new_infusions is not None:
self.log.info(
f"⏲️ Finished sub slot {request.end_of_slot_bundle.challenge_chain.get_hash()}, number of sub-slots: "
f"{len(self.full_node.full_node_store.finished_sub_slots)}, "
f"RC hash: {request.end_of_slot_bundle.reward_chain.get_hash()}, "
f"Deficit {request.end_of_slot_bundle.reward_chain.deficit}"
async with self.full_node.timelord_lock:
fetched_ss = self.full_node.full_node_store.get_sub_slot(
request.end_of_slot_bundle.challenge_chain.challenge_chain_end_of_slot_vdf.challenge
)
# Notify full nodes of the new sub-slot
broadcast = full_node_protocol.NewSignagePointOrEndOfSubSlot(
request.end_of_slot_bundle.challenge_chain.challenge_chain_end_of_slot_vdf.challenge,
request.end_of_slot_bundle.challenge_chain.get_hash(),
uint8(0),
request.end_of_slot_bundle.reward_chain.end_of_slot_vdf.challenge,
)
msg = Message("new_signage_point_or_end_of_sub_slot", broadcast)
await self.server.send_to_all_except([msg], NodeType.FULL_NODE, peer.peer_node_id)
if (
(fetched_ss is None)
and request.end_of_slot_bundle.challenge_chain.challenge_chain_end_of_slot_vdf.challenge
!= self.full_node.constants.FIRST_CC_CHALLENGE
):
# If we don't have the prev, request the prev instead
full_node_request = full_node_protocol.RequestSignagePointOrEndOfSubSlot(
request.end_of_slot_bundle.challenge_chain.challenge_chain_end_of_slot_vdf.challenge,
uint8(0),
bytes([0] * 32),
)
return Message("request_signage_point_or_end_of_sub_slot", full_node_request)
for infusion in new_infusions:
await self.new_infusion_point_vdf(infusion)
peak = self.full_node.blockchain.get_peak()
if peak is not None and peak.sub_block_height > 2:
next_sub_slot_iters = self.full_node.blockchain.get_next_slot_iters(peak.header_hash, True)
next_difficulty = self.full_node.blockchain.get_next_difficulty(peak.header_hash, True)
else:
next_sub_slot_iters = self.full_node.constants.SUB_SLOT_ITERS_STARTING
next_difficulty = self.full_node.constants.DIFFICULTY_STARTING
# Notify farmers of the new sub-slot
broadcast_farmer = farmer_protocol.NewSignagePoint(
request.end_of_slot_bundle.challenge_chain.get_hash(),
request.end_of_slot_bundle.challenge_chain.get_hash(),
request.end_of_slot_bundle.reward_chain.get_hash(),
next_difficulty,
next_sub_slot_iters,
uint8(0),
# Adds the sub slot and potentially get new infusions
new_infusions = self.full_node.full_node_store.new_finished_sub_slot(
request.end_of_slot_bundle, self.full_node.blockchain.sub_blocks, self.full_node.blockchain.get_peak()
)
msg = Message("new_signage_point", broadcast_farmer)
await self.server.send_to_all([msg], NodeType.FARMER)
else:
self.log.warning(f"End of slot not added {request}")
# It may be an empty list, even if it's not None. Not None means added successfully
if new_infusions is not None:
self.log.info(
f"⏲️ Finished sub slot {request.end_of_slot_bundle.challenge_chain.get_hash()}, number of sub-slots: "
f"{len(self.full_node.full_node_store.finished_sub_slots)}, "
f"RC hash: {request.end_of_slot_bundle.reward_chain.get_hash()}, "
f"Deficit {request.end_of_slot_bundle.reward_chain.deficit}"
)
# Notify full nodes of the new sub-slot
broadcast = full_node_protocol.NewSignagePointOrEndOfSubSlot(
request.end_of_slot_bundle.challenge_chain.challenge_chain_end_of_slot_vdf.challenge,
request.end_of_slot_bundle.challenge_chain.get_hash(),
uint8(0),
request.end_of_slot_bundle.reward_chain.end_of_slot_vdf.challenge,
)
msg = Message("new_signage_point_or_end_of_sub_slot", broadcast)
await self.server.send_to_all_except([msg], NodeType.FULL_NODE, peer.peer_node_id)
for infusion in new_infusions:
await self.new_infusion_point_vdf(infusion)
# Notify farmers of the new sub-slot
broadcast_farmer = farmer_protocol.NewSignagePoint(
request.end_of_slot_bundle.challenge_chain.get_hash(),
request.end_of_slot_bundle.challenge_chain.get_hash(),
request.end_of_slot_bundle.reward_chain.get_hash(),
next_difficulty,
next_sub_slot_iters,
uint8(0),
)
msg = Message("new_signage_point", broadcast_farmer)
await self.server.send_to_all([msg], NodeType.FARMER)
else:
self.log.warning(f"End of slot not added {request}")
@peer_required
@api_request
@ -494,174 +497,182 @@ class FullNodeAPI:
Creates a block body and header, with the proof of space, coinbase, and fee targets provided
by the farmer, and sends the hash of the header data back to the farmer.
"""
if request.pool_target is None or request.pool_signature is None:
raise ValueError("Adaptable pool protocol not yet available.")
async with self.full_node.timelord_lock:
if request.pool_target is None or request.pool_signature is None:
raise ValueError("Adaptable pool protocol not yet available.")
sp_vdfs: Optional[SignagePoint] = self.full_node.full_node_store.get_signage_point(request.challenge_chain_sp)
if sp_vdfs is None:
self.log.warning(f"Received proof of space for an unknown signage point {request.challenge_chain_sp}")
return
if request.signage_point_index > 0 and sp_vdfs.rc_vdf.output.get_hash() != request.reward_chain_sp:
self.log.info(
f"Received proof of space for a potentially old signage point {request.challenge_chain_sp}. Current sp: {sp_vdfs.rc_vdf.output.get_hash()}"
sp_vdfs: Optional[SignagePoint] = self.full_node.full_node_store.get_signage_point(
request.challenge_chain_sp
)
return
if request.signage_point_index == 0:
cc_challenge_hash: bytes32 = request.challenge_chain_sp
else:
cc_challenge_hash: bytes32 = sp_vdfs.cc_vdf.challenge
pos_sub_slot: Optional[Tuple[EndOfSubSlotBundle, int]] = None
if request.challenge_hash != self.full_node.constants.FIRST_CC_CHALLENGE:
# Checks that the proof of space is a response to a recent challenge and valid SP
pos_sub_slot = self.full_node.full_node_store.get_sub_slot(cc_challenge_hash)
if pos_sub_slot is None:
self.log.warning(f"Received proof of space for an unknown sub slot: {request}")
if sp_vdfs is None:
self.log.warning(f"Received proof of space for an unknown signage point {request.challenge_chain_sp}")
return
total_iters_pos_slot: uint128 = pos_sub_slot[2]
else:
total_iters_pos_slot: uint128 = uint128(0)
assert cc_challenge_hash == request.challenge_hash
# Now we know that the proof of space has a signage point either:
# 1. In the previous sub-slot of the peak (overflow)
# 2. In the same sub-slot as the peak
# 3. In a future sub-slot that we already know of
# Checks that the proof of space is valid
quality_string: Optional[bytes32] = request.proof_of_space.verify_and_get_quality_string(
self.full_node.constants, cc_challenge_hash, request.challenge_chain_sp
)
assert quality_string is not None and len(quality_string) == 32
# Grab best transactions from Mempool for given tip target
async with self.full_node.blockchain.lock:
peak: Optional[SubBlockRecord] = self.full_node.blockchain.get_peak()
if peak is None:
spend_bundle: Optional[SpendBundle] = None
else:
spend_bundle: Optional[SpendBundle] = await self.full_node.mempool_manager.create_bundle_from_mempool(
peak.header_hash
if request.signage_point_index > 0 and sp_vdfs.rc_vdf.output.get_hash() != request.reward_chain_sp:
self.log.info(
f"Received proof of space for a potentially old signage point {request.challenge_chain_sp}. "
f"Current sp: {sp_vdfs.rc_vdf.output.get_hash()}"
)
if peak is None or peak.sub_block_height <= self.full_node.constants.MAX_SUB_SLOT_SUB_BLOCKS:
difficulty = self.full_node.constants.DIFFICULTY_STARTING
sub_slot_iters = self.full_node.constants.SUB_SLOT_ITERS_STARTING
else:
assert pos_sub_slot is not None
if pos_sub_slot[0].challenge_chain.new_difficulty is not None:
difficulty = pos_sub_slot[0].challenge_chain.new_difficulty
sub_slot_iters = pos_sub_slot[0].challenge_chain.new_sub_slot_iters
return
if request.signage_point_index == 0:
cc_challenge_hash: bytes32 = request.challenge_chain_sp
else:
difficulty = uint64(peak.weight - self.full_node.blockchain.sub_blocks[peak.prev_hash].weight)
sub_slot_iters = peak.sub_slot_iters
cc_challenge_hash: bytes32 = sp_vdfs.cc_vdf.challenge
required_iters: uint64 = calculate_iterations_quality(
quality_string,
request.proof_of_space.size,
difficulty,
request.challenge_chain_sp,
)
sp_iters: uint64 = calculate_sp_iters(self.full_node.constants, sub_slot_iters, request.signage_point_index)
ip_iters: uint64 = calculate_ip_iters(
self.full_node.constants, sub_slot_iters, request.signage_point_index, required_iters
)
def get_plot_sig(to_sign, _) -> G2Element:
if to_sign == request.challenge_chain_sp:
return request.challenge_chain_sp_signature
elif to_sign == request.reward_chain_sp:
return request.reward_chain_sp_signature
return G2Element.infinity()
def get_pool_sig(to_sign, _) -> G2Element:
return request.pool_signature
# 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]
if curr.total_iters > (total_iters_pos_slot + sp_iters):
prev_sb = None
pos_sub_slot: Optional[Tuple[EndOfSubSlotBundle, int]] = None
if request.challenge_hash != self.full_node.constants.FIRST_CC_CHALLENGE:
# Checks that the proof of space is a response to a recent challenge and valid SP
pos_sub_slot = self.full_node.full_node_store.get_sub_slot(cc_challenge_hash)
if pos_sub_slot is None:
self.log.warning(f"Received proof of space for an unknown sub slot: {request}")
return
total_iters_pos_slot: uint128 = pos_sub_slot[2]
else:
prev_sb = curr
else:
pool_target = PoolTarget(self.full_node.constants.GENESIS_PRE_FARM_POOL_PUZZLE_HASH, uint32(0))
prev_sb = None
total_iters_pos_slot: uint128 = uint128(0)
assert cc_challenge_hash == request.challenge_hash
finished_sub_slots: List[EndOfSubSlotBundle] = self.full_node.full_node_store.get_finished_sub_slots(
prev_sb, self.full_node.blockchain.sub_blocks, cc_challenge_hash
)
if len(finished_sub_slots) == 0:
if prev_sb is not None:
if request.signage_point_index == 0:
# No need to get correct block since SP RC is not validated for this sub block
pass
# Now we know that the proof of space has a signage point either:
# 1. In the previous sub-slot of the peak (overflow)
# 2. In the same sub-slot as the peak
# 3. In a future sub-slot that we already know of
# Checks that the proof of space is valid
quality_string: Optional[bytes32] = request.proof_of_space.verify_and_get_quality_string(
self.full_node.constants, cc_challenge_hash, request.challenge_chain_sp
)
assert quality_string is not None and len(quality_string) == 32
# Grab best transactions from Mempool for given tip target
async with self.full_node.blockchain.lock:
peak: Optional[SubBlockRecord] = self.full_node.blockchain.get_peak()
if peak is None:
spend_bundle: Optional[SpendBundle] = None
else:
found = False
attempts = 0
while prev_sb is not None and attempts < 10:
if prev_sb.reward_infusion_new_challenge == sp_vdfs.rc_vdf.challenge:
found = True
break
if (
prev_sb.finished_reward_slot_hashes is not None
and len(prev_sb.finished_reward_slot_hashes) > 0
):
if prev_sb.finished_reward_slot_hashes[-1] == sp_vdfs.rc_vdf.challenge:
prev_sb = self.full_node.blockchain.sub_blocks.get(prev_sb.prev_hash, None)
spend_bundle: Optional[
SpendBundle
] = await self.full_node.mempool_manager.create_bundle_from_mempool(peak.header_hash)
if peak is None or peak.sub_block_height <= self.full_node.constants.MAX_SUB_SLOT_SUB_BLOCKS:
difficulty = self.full_node.constants.DIFFICULTY_STARTING
sub_slot_iters = self.full_node.constants.SUB_SLOT_ITERS_STARTING
else:
assert pos_sub_slot is not None
if pos_sub_slot[0].challenge_chain.new_difficulty is not None:
difficulty = pos_sub_slot[0].challenge_chain.new_difficulty
sub_slot_iters = pos_sub_slot[0].challenge_chain.new_sub_slot_iters
else:
difficulty = uint64(peak.weight - self.full_node.blockchain.sub_blocks[peak.prev_hash].weight)
sub_slot_iters = peak.sub_slot_iters
required_iters: uint64 = calculate_iterations_quality(
quality_string,
request.proof_of_space.size,
difficulty,
request.challenge_chain_sp,
)
sp_iters: uint64 = calculate_sp_iters(self.full_node.constants, sub_slot_iters, request.signage_point_index)
ip_iters: uint64 = calculate_ip_iters(
self.full_node.constants, sub_slot_iters, request.signage_point_index, required_iters
)
def get_plot_sig(to_sign, _) -> G2Element:
if to_sign == request.challenge_chain_sp:
return request.challenge_chain_sp_signature
elif to_sign == request.reward_chain_sp:
return request.reward_chain_sp_signature
return G2Element.infinity()
def get_pool_sig(to_sign, _) -> G2Element:
return request.pool_signature
# Get the previous sub block at the signage point
if peak is not None:
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]
if curr.total_iters > (total_iters_pos_slot + sp_iters):
pool_target = PoolTarget(self.full_node.constants.GENESIS_PRE_FARM_POOL_PUZZLE_HASH, uint32(0))
prev_sb = None
else:
pool_target = request.pool_target
prev_sb = curr
else:
pool_target = PoolTarget(self.full_node.constants.GENESIS_PRE_FARM_POOL_PUZZLE_HASH, uint32(0))
prev_sb = None
try:
finished_sub_slots: List[EndOfSubSlotBundle] = self.full_node.full_node_store.get_finished_sub_slots(
prev_sb, self.full_node.blockchain.sub_blocks, cc_challenge_hash
)
except ValueError as e:
self.log.warning(f"Value Error: {e}")
return
if len(finished_sub_slots) == 0:
if prev_sb is not None:
if request.signage_point_index == 0:
# No need to get correct block since SP RC is not validated for this sub block
pass
else:
found = False
attempts = 0
while prev_sb is not None and attempts < 10:
if prev_sb.reward_infusion_new_challenge == sp_vdfs.rc_vdf.challenge:
found = True
break
prev_sb = self.full_node.blockchain.sub_blocks.get(prev_sb.prev_hash, None)
attempts += 1
if not found:
self.log.info("Did not find a previous block with the correct reward chain hash")
return
elif request.signage_point_index > 0:
assert finished_sub_slots[-1].reward_chain.get_hash() == sp_vdfs.rc_vdf.challenge
if (
prev_sb.finished_reward_slot_hashes is not None
and len(prev_sb.finished_reward_slot_hashes) > 0
):
if prev_sb.finished_reward_slot_hashes[-1] == sp_vdfs.rc_vdf.challenge:
prev_sb = self.full_node.blockchain.sub_blocks.get(prev_sb.prev_hash, None)
found = True
break
prev_sb = self.full_node.blockchain.sub_blocks.get(prev_sb.prev_hash, None)
attempts += 1
if not found:
self.log.info("Did not find a previous block with the correct reward chain hash")
return
elif request.signage_point_index > 0:
assert finished_sub_slots[-1].reward_chain.get_hash() == sp_vdfs.rc_vdf.challenge
unfinished_block: Optional[UnfinishedBlock] = create_unfinished_block(
self.full_node.constants,
total_iters_pos_slot,
sub_slot_iters,
request.signage_point_index,
sp_iters,
ip_iters,
request.proof_of_space,
cc_challenge_hash,
request.farmer_puzzle_hash,
pool_target,
get_plot_sig,
get_pool_sig,
sp_vdfs,
uint64(int(time.time())),
b"",
spend_bundle,
prev_sb,
self.full_node.blockchain.sub_blocks,
finished_sub_slots,
)
if prev_sb is not None:
height = prev_sb.sub_block_height + 1
else:
height = 0
self.full_node.full_node_store.add_candidate_block(quality_string, height, unfinished_block)
unfinished_block: Optional[UnfinishedBlock] = create_unfinished_block(
self.full_node.constants,
total_iters_pos_slot,
sub_slot_iters,
request.signage_point_index,
sp_iters,
ip_iters,
request.proof_of_space,
cc_challenge_hash,
request.farmer_puzzle_hash,
pool_target,
get_plot_sig,
get_pool_sig,
sp_vdfs,
uint64(int(time.time())),
b"",
spend_bundle,
prev_sb,
self.full_node.blockchain.sub_blocks,
finished_sub_slots,
)
if prev_sb is not None:
height = prev_sb.sub_block_height + 1
else:
height = 0
self.full_node.full_node_store.add_candidate_block(quality_string, height, unfinished_block)
foliage_sb_data_hash = unfinished_block.foliage_sub_block.foliage_sub_block_data.get_hash()
if unfinished_block.is_block():
foliage_block_hash = unfinished_block.foliage_sub_block.foliage_block_hash
else:
foliage_block_hash = bytes([0] * 32)
foliage_sb_data_hash = unfinished_block.foliage_sub_block.foliage_sub_block_data.get_hash()
if unfinished_block.is_block():
foliage_block_hash = unfinished_block.foliage_sub_block.foliage_block_hash
else:
foliage_block_hash = bytes([0] * 32)
message = farmer_protocol.RequestSignedValues(
quality_string,
foliage_sb_data_hash,
foliage_block_hash,
)
return Message("request_signed_values", message)
message = farmer_protocol.RequestSignedValues(
quality_string,
foliage_sb_data_hash,
foliage_block_hash,
)
return Message("request_signed_values", message)
@api_request
async def signed_values(self, farmer_request: farmer_protocol.SignedValues) -> Optional[Message]:
@ -678,6 +689,14 @@ class FullNodeAPI:
self.log.warning(f"Quality string {farmer_request.quality_string} not found in database")
return
if not AugSchemeMPL.verify(
candidate.reward_chain_sub_block.proof_of_space.plot_public_key,
candidate.foliage_sub_block.foliage_sub_block_data.get_hash(),
farmer_request.foliage_sub_block_signature,
):
self.log.warning("Signature not valid. There might be a collision in plots. Ignore this during tests.")
return
fsb2 = dataclasses.replace(
candidate.foliage_sub_block,
foliage_sub_block_signature=farmer_request.foliage_sub_block_signature,
@ -686,6 +705,9 @@ class FullNodeAPI:
fsb2 = dataclasses.replace(fsb2, foliage_block_signature=farmer_request.foliage_block_signature)
new_candidate = dataclasses.replace(candidate, foliage_sub_block=fsb2)
if not self.full_node.has_valid_pool_sig(new_candidate):
self.log.warning("Trying to make a pre-farm block but height is not 0")
return
# Propagate to ourselves (which validates and does further propagations)
request = full_node_protocol.RespondUnfinishedSubBlock(new_candidate)
@ -788,18 +810,9 @@ 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 not self.full_node.has_valid_pool_sig(block):
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
@ -861,17 +874,13 @@ class FullNodeAPI:
@api_request
async def request_additions(self, request: wallet_protocol.RequestAdditions) -> Optional[Message]:
block: Optional[FullBlock] = await self.full_node.block_store.get_full_block(
request.header_hash
)
block: Optional[FullBlock] = await self.full_node.block_store.get_full_block(request.header_hash)
if (
block is None
or block.is_block() is False
or block.sub_block_height not in self.full_node.blockchain.sub_height_to_hash
block is None
or block.is_block() is False
or block.sub_block_height not in self.full_node.blockchain.sub_height_to_hash
):
reject = wallet_protocol.RejectAdditionsRequest(
request.height, request.header_hash
)
reject = wallet_protocol.RejectAdditionsRequest(request.height, request.header_hash)
msg = Message("reject_additions_request", reject)
return msg
@ -891,9 +900,7 @@ class FullNodeAPI:
if request.puzzle_hashes is None:
for puzzle_hash, coins in puzzlehash_coins_map.items():
coins_map.append((puzzle_hash, coins))
response = wallet_protocol.RespondAdditions(
block.sub_block_height, block.header_hash, coins_map, None
)
response = wallet_protocol.RespondAdditions(block.sub_block_height, block.header_hash, coins_map, None)
else:
# Create addition Merkle set
addition_merkle_set = MerkleSet()
@ -904,15 +911,11 @@ class FullNodeAPI:
assert addition_merkle_set.get_root() == block.foliage_block.additions_root
for puzzle_hash in request.puzzle_hashes:
result, proof = addition_merkle_set.is_included_already_hashed(
puzzle_hash
)
result, proof = addition_merkle_set.is_included_already_hashed(puzzle_hash)
if puzzle_hash in puzzlehash_coins_map:
coins_map.append((puzzle_hash, puzzlehash_coins_map[puzzle_hash]))
hash_coin_str = hash_coin_list(puzzlehash_coins_map[puzzle_hash])
result_2, proof_2 = addition_merkle_set.is_included_already_hashed(
hash_coin_str
)
result_2, proof_2 = addition_merkle_set.is_included_already_hashed(hash_coin_str)
assert result
assert result_2
proofs_map.append((puzzle_hash, proof, proof_2))
@ -926,23 +929,17 @@ class FullNodeAPI:
msg = Message("respond_additions", response)
return msg
@api_request
async def request_removals(self, request: wallet_protocol.RequestRemovals) -> Optional[Message]:
block: Optional[FullBlock] = await self.full_node.block_store.get_full_block(
request.header_hash
)
block: Optional[FullBlock] = await self.full_node.block_store.get_full_block(request.header_hash)
if (
block is None
or block.is_block() is False
or block.sub_block_height != request.sub_height
or block.sub_block_height not in self.full_node.blockchain.sub_height_to_hash
or self.full_node.blockchain.sub_height_to_hash[block.sub_block_height] != block.header_hash
block is None
or block.is_block() is False
or block.sub_block_height != request.sub_height
or block.sub_block_height not in self.full_node.blockchain.sub_height_to_hash
or self.full_node.blockchain.sub_height_to_hash[block.sub_block_height] != block.header_hash
):
reject = wallet_protocol.RejectRemovalsRequest(
request.sub_height, request.header_hash
)
reject = wallet_protocol.RejectRemovalsRequest(request.sub_height, request.header_hash)
msg = Message("reject_removals_request", reject)
return msg
@ -959,17 +956,13 @@ class FullNodeAPI:
proofs = None
else:
proofs = []
response = wallet_protocol.RespondRemovals(
block.height, block.header_hash, [], proofs
)
response = wallet_protocol.RespondRemovals(block.height, block.header_hash, [], proofs)
elif request.coin_names is None or len(request.coin_names) == 0:
for removal in all_removals:
cr = await self.full_node.coin_store.get_coin_record(removal)
assert cr is not None
coins_map.append((cr.coin.name(), cr.coin))
response = wallet_protocol.RespondRemovals(
block.height, block.header_hash, coins_map, None
)
response = wallet_protocol.RespondRemovals(block.height, block.header_hash, coins_map, None)
else:
assert block.transactions_generator
removal_merkle_set = MerkleSet()
@ -987,9 +980,7 @@ class FullNodeAPI:
else:
coins_map.append((coin_name, None))
assert not result
response = wallet_protocol.RespondRemovals(
block.height, block.header_hash, coins_map, proofs_map
)
response = wallet_protocol.RespondRemovals(block.height, block.header_hash, coins_map, proofs_map)
msg = Message("respond_removals", response)
return msg

View File

@ -146,6 +146,7 @@ class FullNodeStore:
self.finished_sub_slots.clear()
def get_sub_slot(self, challenge_hash: bytes32) -> Optional[Tuple[EndOfSubSlotBundle, int, uint128]]:
assert len(self.finished_sub_slots) >= 1
for index, (sub_slot, _, total_iters) in enumerate(self.finished_sub_slots):
if sub_slot is not None and sub_slot.challenge_chain.get_hash() == challenge_hash:
return sub_slot, index, total_iters
@ -163,6 +164,7 @@ class FullNodeStore:
on this sub slot
TODO: do full validation here
"""
assert len(self.finished_sub_slots) >= 1
if len(self.finished_sub_slots) == 0:
log.warning("no fini sub slots")
@ -213,7 +215,7 @@ class FullNodeStore:
if rc_challenge not in self.future_eos_cache:
self.future_eos_cache[rc_challenge] = []
self.future_eos_cache[rc_challenge].append(eos)
log.error(f"Dont have challenge hash {rc_challenge}")
log.warning(f"Don't have challenge hash {rc_challenge}")
return None
if peak.total_iters + eos.reward_chain.end_of_slot_vdf.number_of_iterations != total_iters:
log.error(
@ -271,6 +273,7 @@ class FullNodeStore:
"""
Returns true if sp successfully added
"""
assert len(self.finished_sub_slots) >= 1
if peak is None or peak.sub_block_height < 2:
sub_slot_iters = self.constants.SUB_SLOT_ITERS_STARTING
@ -357,6 +360,7 @@ class FullNodeStore:
return False
def get_signage_point(self, cc_signage_point: bytes32) -> Optional[SignagePoint]:
assert len(self.finished_sub_slots) >= 1
if cc_signage_point == self.constants.FIRST_CC_CHALLENGE:
return SignagePoint(None, None, None, None)
@ -371,6 +375,7 @@ class FullNodeStore:
def get_signage_point_by_index(
self, challenge_hash: bytes32, index: uint8, last_rc_infusion: bytes32
) -> Optional[SignagePoint]:
assert len(self.finished_sub_slots) >= 1
for sub_slot, sps, _ in self.finished_sub_slots:
if sub_slot is not None:
cc_hash = sub_slot.challenge_chain.get_hash()
@ -390,6 +395,7 @@ class FullNodeStore:
"""
Returns true if we have a signage point at this index which is based on a newer infusion.
"""
assert len(self.finished_sub_slots) >= 1
for sub_slot, sps, _ in self.finished_sub_slots:
if sub_slot is not None:
cc_hash = sub_slot.challenge_chain.get_hash()
@ -420,7 +426,7 @@ class FullNodeStore:
If the peak is an overflow block, must provide two sub-slots: one for the current sub-slot and one for
the prev sub-slot (since we still might get more sub-blocks with an sp in the previous sub-slot)
"""
assert len(self.finished_sub_slots) >= 1
new_finished_sub_slots = []
total_iters_peak = peak.ip_sub_slot_total_iters(self.constants)
if not reorg:
@ -484,6 +490,7 @@ class FullNodeStore:
NOTE: In the case of the overflow, passing in extra_sub_slot=True will add the necessary sub-slot. This might
not be available until later though.
"""
assert len(self.finished_sub_slots) >= 1
if prev_sb is not None:
curr: SubBlockRecord = prev_sb
while not curr.first_in_sub_slot:
@ -497,10 +504,6 @@ class FullNodeStore:
if pos_ss_challenge_hash == self.constants.FIRST_CC_CHALLENGE:
pos_index = 0
if prev_sb is None:
if len(self.finished_sub_slots) < 1:
raise ValueError("Should have finished sub slots")
if self.finished_sub_slots[0][0] is not None:
raise ValueError("First sub slot should be None")
final_index = 0
for index, (sub_slot, sps, total_iters) in enumerate(self.finished_sub_slots):
if sub_slot is not None and sub_slot.challenge_chain.get_hash() == pos_ss_challenge_hash:
@ -515,7 +518,6 @@ class FullNodeStore:
final_index = index
if pos_index is None:
log.error(f"{pos_ss_challenge_hash} {len(self.finished_sub_slots)} {prev_sb.sub_block_height}")
raise ValueError(
f"Did not find challenge hash or peak pi: {pos_index} fi: {final_index} {len(sub_block_records)}"
)

View File

@ -178,11 +178,7 @@ class MempoolManager:
elif name in additions_dict:
removal_coin = additions_dict[name]
removal_record = CoinRecord(
removal_coin,
self.peak.height + 1,
uint32(0),
False,
False,
removal_coin, self.peak.height + 1, uint32(0), False, False, removal_record.timestamp
)
assert removal_record is not None
@ -263,9 +259,7 @@ class MempoolManager:
log.warning(f"{npc.puzzle_hash} != {coin_record.coin.puzzle_hash}")
return None, MempoolInclusionStatus.FAILED, Err.WRONG_PUZZLE_HASH
error = mempool_check_conditions_dict(
coin_record, new_spend, npc.condition_dict, self.peak.height + 1
)
error = mempool_check_conditions_dict(coin_record, new_spend, npc.condition_dict, self.peak.height + 1)
if error:
if error is Err.ASSERT_BLOCK_INDEX_EXCEEDS_FAILED or error is Err.ASSERT_BLOCK_AGE_EXCEEDS_FAILED:

View File

@ -33,16 +33,19 @@ class Introducer:
if self._shut_down:
return
try:
for i in range(5):
if self._shut_down:
return
await asyncio.sleep(1)
self.log.info("Vetting random peers.")
await asyncio.sleep(60)
if self.server.introducer_peers is None:
continue
rawpeers = self.server.introducer_peers.get_peers(100, True, 3 * self.recent_peer_threshold)
raw_peers = self.server.introducer_peers.get_peers(100, True, 3 * self.recent_peer_threshold)
if len(rawpeers) == 0:
if len(raw_peers) == 0:
continue
for peer in rawpeers:
for peer in raw_peers:
if self._shut_down:
return
if peer.get_hash() in self.vetted_timestamps:

View File

@ -613,7 +613,6 @@ class Timelord:
block = unfinished_block
break
if block is not None:
ip_total_iters = self.last_state.get_total_iters() + iteration
challenge = block.reward_chain_sub_block.get_hash()
icc_info: Optional[VDFInfo] = None
@ -653,6 +652,7 @@ class Timelord:
overflow = is_overflow_sub_block(self.constants, block.reward_chain_sub_block.signage_point_index)
cc_info = dataclasses.replace(cc_info, number_of_iterations=ip_iters)
log.warning(f"Sending infusion point VDF cc: {cc_info}")
response = timelord_protocol.NewInfusionPointVDF(
challenge,
cc_info,
@ -808,8 +808,13 @@ class Timelord:
+ self.last_state.get_sub_slot_iters()
)
else:
total_iters = self.last_state.get_total_iters() + self.last_state.get_total_iters()
total_iters = self.last_state.get_total_iters() + self.last_state.get_sub_slot_iters()
iters_from_cb = uint64(total_iters - self.last_state.last_challenge_sb_or_eos_total_iters)
if iters_from_cb > self.last_state.sub_slot_iters:
log.error(f"{self.last_state.peak}")
log.error(f"{self.last_state.subslot_end}")
assert False
assert iters_from_cb <= self.last_state.sub_slot_iters
icc_ip_vdf = dataclasses.replace(icc_ip_vdf, number_of_iterations=iters_from_cb)
icc_sub_slot: Optional[InfusedChallengeChainSubSlot] = (

View File

@ -65,10 +65,11 @@ class FullBlock(Streamable):
return self.foliage_sub_block.get_hash()
def is_block(self):
return self.foliage_sub_block.foliage_block_hash is not None
return self.foliage_block is not None
def get_future_reward_coins(self, height: uint32) -> Tuple[Coin, Coin]:
pool_amount = calculate_pool_reward(height, self.sub_block_height == 0)
pool_amount = calculate_pool_reward(height)
farmer_amount = calculate_base_farmer_reward(height)
if self.is_block():
farmer_amount = calculate_base_farmer_reward(height)
assert self.transactions_info is not None

View File

@ -1,459 +1,459 @@
import asyncio
from secrets import token_bytes
import pytest
from src.simulator.simulator_protocol import FarmNewBlockProtocol
from src.types.peer_info import PeerInfo
from src.util.ints import uint16, uint32, uint64
from tests.setup_nodes import setup_simulators_and_wallets
from src.consensus.block_rewards import calculate_base_fee, calculate_block_reward
from src.wallet.cc_wallet.cc_wallet import CCWallet
from src.wallet.wallet_coin_record import WalletCoinRecord
from tests.time_out_assert import time_out_assert
from typing import List
@pytest.fixture(scope="module")
def event_loop():
loop = asyncio.get_event_loop()
yield loop
class TestCCWallet:
@pytest.fixture(scope="function")
async def wallet_node(self):
async for _ in setup_simulators_and_wallets(1, 1, {}):
yield _
@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.fixture(scope="function")
async def three_wallet_nodes(self):
async for _ in setup_simulators_and_wallets(
1, 3, {"COINBASE_FREEZE_PERIOD": 0}
):
yield _
@pytest.mark.asyncio
async def test_colour_creation(self, two_wallet_nodes):
num_blocks = 5
full_nodes, wallets = two_wallet_nodes
full_node__api = full_nodes[0]
full_node_server = full_node__api.server
wallet_node, server_2 = wallets[0]
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
)
for i in range(1, 4):
await full_node__api.farm_new_block(FarmNewBlockProtocol(ph))
funds = sum(
[
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
for i in range(1, 4 - 2)
]
)
await time_out_assert(15, wallet.get_confirmed_balance, funds)
cc_wallet: CCWallet = await CCWallet.create_new_cc(
wallet_node.wallet_state_manager, wallet, uint64(100)
)
for i in range(1, num_blocks):
await full_node__api.farm_new_block(FarmNewBlockProtocol(ph))
await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
@pytest.mark.asyncio
async def test_cc_spend(self, two_wallet_nodes):
num_blocks = 8
full_nodes, wallets = two_wallet_nodes
full_node_api = full_nodes[0]
full_node_server = full_node_api.server
wallet_node, server_2 = wallets[0]
wallet_node_2, server_3 = wallets[1]
wallet = wallet_node.wallet_state_manager.main_wallet
wallet2 = wallet_node_2.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 server_3.start_client(
PeerInfo("localhost", uint16(full_node_server._port)), None
)
for i in range(1, 4):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
funds = sum(
[
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
for i in range(1, 4 - 2)
]
)
await time_out_assert(15, wallet.get_confirmed_balance, funds)
cc_wallet: CCWallet = await CCWallet.create_new_cc(
wallet_node.wallet_state_manager, wallet, uint64(100)
)
for i in range(1, num_blocks):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
assert cc_wallet.cc_info.my_genesis_checker is not None
colour = cc_wallet.get_colour()
cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
wallet_node_2.wallet_state_manager, wallet2, colour
)
assert (
cc_wallet.cc_info.my_genesis_checker
== cc_wallet_2.cc_info.my_genesis_checker
)
cc_2_hash = await cc_wallet_2.get_new_inner_hash()
tx_record = await cc_wallet.generate_signed_transaction(
[uint64(60)], [cc_2_hash]
)
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
for i in range(1, num_blocks):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
await time_out_assert(15, cc_wallet.get_confirmed_balance, 40)
await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 40)
await time_out_assert(30, cc_wallet_2.get_confirmed_balance, 60)
await time_out_assert(30, cc_wallet_2.get_unconfirmed_balance, 60)
cc_hash = await cc_wallet.get_new_inner_hash()
tx_record = await cc_wallet_2.generate_signed_transaction(
[uint64(15)], [cc_hash]
)
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
for i in range(1, num_blocks):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
await time_out_assert(15, cc_wallet.get_confirmed_balance, 55)
await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 55)
@pytest.mark.asyncio
async def test_get_wallet_for_colour(self, two_wallet_nodes):
num_blocks = 5
full_nodes, wallets = two_wallet_nodes
full_node_api = full_nodes[0]
full_node_server = full_node_api.server
wallet_node, server_2 = wallets[0]
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
)
for i in range(1, 4):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
funds = sum(
[
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
for i in range(1, 4 - 2)
]
)
await time_out_assert(15, wallet.get_confirmed_balance, funds)
cc_wallet: CCWallet = await CCWallet.create_new_cc(
wallet_node.wallet_state_manager, wallet, uint64(100)
)
for i in range(1, num_blocks):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
colour = cc_wallet.get_colour()
assert (
await wallet_node.wallet_state_manager.get_wallet_for_colour(colour)
== cc_wallet
)
@pytest.mark.asyncio
async def test_generate_zero_val(self, two_wallet_nodes):
num_blocks = 10
full_nodes, wallets = two_wallet_nodes
full_node_api = full_nodes[0]
full_node_server = full_node_api.server
wallet_node, server_2 = wallets[0]
wallet_node_2, server_3 = wallets[1]
wallet = wallet_node.wallet_state_manager.main_wallet
wallet2 = wallet_node_2.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 server_3.start_client(
PeerInfo("localhost", uint16(full_node_server._port)), None
)
for i in range(1, 4):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
funds = sum(
[
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
for i in range(1, 4 - 2)
]
)
await time_out_assert(15, wallet.get_confirmed_balance, funds)
cc_wallet: CCWallet = await CCWallet.create_new_cc(
wallet_node.wallet_state_manager, wallet, uint64(100)
)
ph = await wallet2.get_new_puzzlehash()
for i in range(1, num_blocks):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
assert cc_wallet.cc_info.my_genesis_checker is not None
colour = cc_wallet.get_colour()
cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
wallet_node_2.wallet_state_manager, wallet2, colour
)
assert (
cc_wallet.cc_info.my_genesis_checker
== cc_wallet_2.cc_info.my_genesis_checker
)
await cc_wallet_2.generate_zero_val_coin()
for i in range(1, num_blocks):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
unspent: List[WalletCoinRecord] = list(
await cc_wallet_2.wallet_state_manager.get_spendable_coins_for_wallet(
cc_wallet_2.id()
)
)
assert len(unspent) == 1
assert unspent.pop().coin.amount == 0
@pytest.mark.asyncio
async def test_cc_spend_uncoloured(self, two_wallet_nodes):
num_blocks = 8
full_nodes, wallets = two_wallet_nodes
full_node_api = full_nodes[0]
full_node_server = full_node_api.server
wallet_node, server_2 = wallets[0]
wallet_node_2, server_3 = wallets[1]
wallet = wallet_node.wallet_state_manager.main_wallet
wallet2 = wallet_node_2.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 server_3.start_client(
PeerInfo("localhost", uint16(full_node_server._port)), None
)
for i in range(1, 4):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
funds = sum(
[
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
for i in range(1, 4 - 2)
]
)
await time_out_assert(15, wallet.get_confirmed_balance, funds)
cc_wallet: CCWallet = await CCWallet.create_new_cc(
wallet_node.wallet_state_manager, wallet, uint64(100)
)
for i in range(1, num_blocks):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
assert cc_wallet.cc_info.my_genesis_checker is not None
colour = cc_wallet.get_colour()
cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
wallet_node_2.wallet_state_manager, wallet2, colour
)
assert (
cc_wallet.cc_info.my_genesis_checker
== cc_wallet_2.cc_info.my_genesis_checker
)
cc_2_hash = await cc_wallet_2.get_new_inner_hash()
tx_record = await cc_wallet.generate_signed_transaction(
[uint64(60)], [cc_2_hash]
)
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
for i in range(1, num_blocks):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
await time_out_assert(15, cc_wallet.get_confirmed_balance, 40)
await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 40)
await time_out_assert(15, cc_wallet_2.get_confirmed_balance, 60)
await time_out_assert(15, cc_wallet_2.get_unconfirmed_balance, 60)
cc2_ph = await cc_wallet_2.get_new_cc_puzzle_hash()
tx_record = (
await wallet.wallet_state_manager.main_wallet.generate_signed_transaction(
10, cc2_ph, 0
)
)
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
for i in range(0, num_blocks):
await full_node_api.farm_new_block(FarmNewBlockProtocol(token_bytes()))
id = cc_wallet_2.id()
wsm = cc_wallet_2.wallet_state_manager
await time_out_assert(15, wsm.get_confirmed_balance_for_wallet, 70, id)
await time_out_assert(15, cc_wallet_2.get_confirmed_balance, 60)
await time_out_assert(15, cc_wallet_2.get_unconfirmed_balance, 60)
@pytest.mark.asyncio
async def test_cc_spend_multiple(self, three_wallet_nodes):
num_blocks = 8
full_nodes, wallets = three_wallet_nodes
full_node_api = full_nodes[0]
full_node_server = full_node_api.server
wallet_node_0, wallet_server_0 = wallets[0]
wallet_node_1, wallet_server_1 = wallets[1]
wallet_node_2, wallet_server_2 = wallets[2]
wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
wallet_2 = wallet_node_2.wallet_state_manager.main_wallet
ph = await wallet_0.get_new_puzzlehash()
await wallet_server_0.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
)
for i in range(1, 4):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
funds = sum(
[
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
for i in range(1, 4 - 2)
]
)
await time_out_assert(15, wallet_0.get_confirmed_balance, funds)
cc_wallet_0: CCWallet = await CCWallet.create_new_cc(
wallet_node_0.wallet_state_manager, wallet_0, uint64(100)
)
for i in range(1, num_blocks):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
await time_out_assert(15, cc_wallet_0.get_confirmed_balance, 100)
await time_out_assert(15, cc_wallet_0.get_unconfirmed_balance, 100)
assert cc_wallet_0.cc_info.my_genesis_checker is not None
colour = cc_wallet_0.get_colour()
cc_wallet_1: CCWallet = await CCWallet.create_wallet_for_cc(
wallet_node_1.wallet_state_manager, wallet_1, colour
)
cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
wallet_node_2.wallet_state_manager, wallet_2, colour
)
assert (
cc_wallet_0.cc_info.my_genesis_checker
== cc_wallet_1.cc_info.my_genesis_checker
)
assert (
cc_wallet_0.cc_info.my_genesis_checker
== cc_wallet_2.cc_info.my_genesis_checker
)
cc_1_hash = await cc_wallet_1.get_new_inner_hash()
cc_2_hash = await cc_wallet_2.get_new_inner_hash()
tx_record = await cc_wallet_0.generate_signed_transaction(
[uint64(60), uint64(20)], [cc_1_hash, cc_2_hash]
)
await wallet_0.wallet_state_manager.add_pending_transaction(tx_record)
for i in range(1, num_blocks):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
await time_out_assert(15, cc_wallet_0.get_confirmed_balance, 20)
await time_out_assert(15, cc_wallet_0.get_unconfirmed_balance, 20)
await time_out_assert(30, cc_wallet_1.get_confirmed_balance, 60)
await time_out_assert(30, cc_wallet_1.get_unconfirmed_balance, 60)
await time_out_assert(30, cc_wallet_2.get_confirmed_balance, 20)
await time_out_assert(30, cc_wallet_2.get_unconfirmed_balance, 20)
cc_hash = await cc_wallet_0.get_new_inner_hash()
tx_record = await cc_wallet_1.generate_signed_transaction(
[uint64(15)], [cc_hash]
)
await wallet_1.wallet_state_manager.add_pending_transaction(tx_record)
tx_record_2 = await cc_wallet_2.generate_signed_transaction(
[uint64(20)], [cc_hash]
)
await wallet_2.wallet_state_manager.add_pending_transaction(tx_record_2)
for i in range(1, num_blocks):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
await time_out_assert(15, cc_wallet_0.get_confirmed_balance, 55)
await time_out_assert(15, cc_wallet_0.get_unconfirmed_balance, 55)
await time_out_assert(30, cc_wallet_1.get_confirmed_balance, 45)
await time_out_assert(30, cc_wallet_1.get_unconfirmed_balance, 45)
await time_out_assert(30, cc_wallet_2.get_confirmed_balance, 0)
await time_out_assert(30, cc_wallet_2.get_unconfirmed_balance, 0)
# import asyncio
# from secrets import token_bytes
#
# import pytest
#
# from src.simulator.simulator_protocol import FarmNewBlockProtocol
# from src.types.peer_info import PeerInfo
# from src.util.ints import uint16, uint32, uint64
# from tests.setup_nodes import setup_simulators_and_wallets
# from src.consensus.block_rewards import calculate_base_fee, calculate_block_reward
# from src.wallet.cc_wallet.cc_wallet import CCWallet
# from src.wallet.wallet_coin_record import WalletCoinRecord
# from tests.time_out_assert import time_out_assert
# from typing import List
#
#
# @pytest.fixture(scope="module")
# def event_loop():
# loop = asyncio.get_event_loop()
# yield loop
#
#
# class TestCCWallet:
# @pytest.fixture(scope="function")
# async def wallet_node(self):
# async for _ in setup_simulators_and_wallets(1, 1, {}):
# yield _
#
# @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.fixture(scope="function")
# async def three_wallet_nodes(self):
# async for _ in setup_simulators_and_wallets(
# 1, 3, {"COINBASE_FREEZE_PERIOD": 0}
# ):
# yield _
#
# @pytest.mark.asyncio
# async def test_colour_creation(self, two_wallet_nodes):
# num_blocks = 5
# full_nodes, wallets = two_wallet_nodes
# full_node__api = full_nodes[0]
# full_node_server = full_node__api.server
# wallet_node, server_2 = wallets[0]
# 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
# )
# for i in range(1, 4):
# await full_node__api.farm_new_block(FarmNewBlockProtocol(ph))
#
# funds = sum(
# [
# calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
# for i in range(1, 4 - 2)
# ]
# )
#
# await time_out_assert(15, wallet.get_confirmed_balance, funds)
#
# cc_wallet: CCWallet = await CCWallet.create_new_cc(
# wallet_node.wallet_state_manager, wallet, uint64(100)
# )
#
# for i in range(1, num_blocks):
# await full_node__api.farm_new_block(FarmNewBlockProtocol(ph))
#
# await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
# await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
#
# @pytest.mark.asyncio
# async def test_cc_spend(self, two_wallet_nodes):
# num_blocks = 8
# full_nodes, wallets = two_wallet_nodes
# full_node_api = full_nodes[0]
# full_node_server = full_node_api.server
# wallet_node, server_2 = wallets[0]
# wallet_node_2, server_3 = wallets[1]
# wallet = wallet_node.wallet_state_manager.main_wallet
# wallet2 = wallet_node_2.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 server_3.start_client(
# PeerInfo("localhost", uint16(full_node_server._port)), None
# )
#
# for i in range(1, 4):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# funds = sum(
# [
# calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
# for i in range(1, 4 - 2)
# ]
# )
#
# await time_out_assert(15, wallet.get_confirmed_balance, funds)
#
# cc_wallet: CCWallet = await CCWallet.create_new_cc(
# wallet_node.wallet_state_manager, wallet, uint64(100)
# )
#
# for i in range(1, num_blocks):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
# await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
#
# assert cc_wallet.cc_info.my_genesis_checker is not None
# colour = cc_wallet.get_colour()
#
# cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
# wallet_node_2.wallet_state_manager, wallet2, colour
# )
#
# assert (
# cc_wallet.cc_info.my_genesis_checker
# == cc_wallet_2.cc_info.my_genesis_checker
# )
#
# cc_2_hash = await cc_wallet_2.get_new_inner_hash()
# tx_record = await cc_wallet.generate_signed_transaction(
# [uint64(60)], [cc_2_hash]
# )
# await wallet.wallet_state_manager.add_pending_transaction(tx_record)
#
# for i in range(1, num_blocks):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# await time_out_assert(15, cc_wallet.get_confirmed_balance, 40)
# await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 40)
#
# await time_out_assert(30, cc_wallet_2.get_confirmed_balance, 60)
# await time_out_assert(30, cc_wallet_2.get_unconfirmed_balance, 60)
#
# cc_hash = await cc_wallet.get_new_inner_hash()
# tx_record = await cc_wallet_2.generate_signed_transaction(
# [uint64(15)], [cc_hash]
# )
# await wallet.wallet_state_manager.add_pending_transaction(tx_record)
# for i in range(1, num_blocks):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# await time_out_assert(15, cc_wallet.get_confirmed_balance, 55)
# await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 55)
#
# @pytest.mark.asyncio
# async def test_get_wallet_for_colour(self, two_wallet_nodes):
# num_blocks = 5
# full_nodes, wallets = two_wallet_nodes
# full_node_api = full_nodes[0]
# full_node_server = full_node_api.server
# wallet_node, server_2 = wallets[0]
# 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
# )
#
# for i in range(1, 4):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# funds = sum(
# [
# calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
# for i in range(1, 4 - 2)
# ]
# )
#
# await time_out_assert(15, wallet.get_confirmed_balance, funds)
#
# cc_wallet: CCWallet = await CCWallet.create_new_cc(
# wallet_node.wallet_state_manager, wallet, uint64(100)
# )
#
# for i in range(1, num_blocks):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# colour = cc_wallet.get_colour()
# assert (
# await wallet_node.wallet_state_manager.get_wallet_for_colour(colour)
# == cc_wallet
# )
#
# @pytest.mark.asyncio
# async def test_generate_zero_val(self, two_wallet_nodes):
# num_blocks = 10
# full_nodes, wallets = two_wallet_nodes
# full_node_api = full_nodes[0]
# full_node_server = full_node_api.server
# wallet_node, server_2 = wallets[0]
# wallet_node_2, server_3 = wallets[1]
# wallet = wallet_node.wallet_state_manager.main_wallet
# wallet2 = wallet_node_2.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 server_3.start_client(
# PeerInfo("localhost", uint16(full_node_server._port)), None
# )
# for i in range(1, 4):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# funds = sum(
# [
# calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
# for i in range(1, 4 - 2)
# ]
# )
# await time_out_assert(15, wallet.get_confirmed_balance, funds)
#
# cc_wallet: CCWallet = await CCWallet.create_new_cc(
# wallet_node.wallet_state_manager, wallet, uint64(100)
# )
#
# ph = await wallet2.get_new_puzzlehash()
# for i in range(1, num_blocks):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
# await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
#
# assert cc_wallet.cc_info.my_genesis_checker is not None
# colour = cc_wallet.get_colour()
#
# cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
# wallet_node_2.wallet_state_manager, wallet2, colour
# )
#
# assert (
# cc_wallet.cc_info.my_genesis_checker
# == cc_wallet_2.cc_info.my_genesis_checker
# )
#
# await cc_wallet_2.generate_zero_val_coin()
#
# for i in range(1, num_blocks):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# unspent: List[WalletCoinRecord] = list(
# await cc_wallet_2.wallet_state_manager.get_spendable_coins_for_wallet(
# cc_wallet_2.id()
# )
# )
# assert len(unspent) == 2
# assert unspent.pop().coin.amount == 0
#
# @pytest.mark.asyncio
# async def test_cc_spend_uncoloured(self, two_wallet_nodes):
# num_blocks = 9
# full_nodes, wallets = two_wallet_nodes
# full_node_api = full_nodes[0]
# full_node_server = full_node_api.server
# wallet_node, server_2 = wallets[0]
# wallet_node_2, server_3 = wallets[1]
# wallet = wallet_node.wallet_state_manager.main_wallet
# wallet2 = wallet_node_2.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 server_3.start_client(
# PeerInfo("localhost", uint16(full_node_server._port)), None
# )
#
# for i in range(1, 4):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# funds = sum(
# [
# calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
# for i in range(1, 4 - 2)
# ]
# )
#
# await time_out_assert(15, wallet.get_confirmed_balance, funds)
#
# cc_wallet: CCWallet = await CCWallet.create_new_cc(
# wallet_node.wallet_state_manager, wallet, uint64(100)
# )
#
# for i in range(1, num_blocks):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
# await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
#
# assert cc_wallet.cc_info.my_genesis_checker is not None
# colour = cc_wallet.get_colour()
#
# cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
# wallet_node_2.wallet_state_manager, wallet2, colour
# )
#
# assert (
# cc_wallet.cc_info.my_genesis_checker
# == cc_wallet_2.cc_info.my_genesis_checker
# )
#
# cc_2_hash = await cc_wallet_2.get_new_inner_hash()
# tx_record = await cc_wallet.generate_signed_transaction(
# [uint64(60)], [cc_2_hash]
# )
# await wallet.wallet_state_manager.add_pending_transaction(tx_record)
# for i in range(1, num_blocks):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# await time_out_assert(15, cc_wallet.get_confirmed_balance, 40)
# await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 40)
#
# await time_out_assert(15, cc_wallet_2.get_confirmed_balance, 60)
# await time_out_assert(15, cc_wallet_2.get_unconfirmed_balance, 60)
#
# cc2_ph = await cc_wallet_2.get_new_cc_puzzle_hash()
# tx_record = (
# await wallet.wallet_state_manager.main_wallet.generate_signed_transaction(
# 10, cc2_ph, 0
# )
# )
# await wallet.wallet_state_manager.add_pending_transaction(tx_record)
#
# for i in range(0, num_blocks):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(token_bytes()))
#
# id = cc_wallet_2.id()
# wsm = cc_wallet_2.wallet_state_manager
# await time_out_assert(15, wsm.get_confirmed_balance_for_wallet, 70, id)
# await time_out_assert(15, cc_wallet_2.get_confirmed_balance, 60)
# await time_out_assert(15, cc_wallet_2.get_unconfirmed_balance, 60)
#
# @pytest.mark.asyncio
# async def test_cc_spend_multiple(self, three_wallet_nodes):
# num_blocks = 8
# full_nodes, wallets = three_wallet_nodes
# full_node_api = full_nodes[0]
# full_node_server = full_node_api.server
# wallet_node_0, wallet_server_0 = wallets[0]
# wallet_node_1, wallet_server_1 = wallets[1]
# wallet_node_2, wallet_server_2 = wallets[2]
# wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
# wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
# wallet_2 = wallet_node_2.wallet_state_manager.main_wallet
#
# ph = await wallet_0.get_new_puzzlehash()
#
# await wallet_server_0.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
# )
#
# for i in range(1, 4):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# funds = sum(
# [
# calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
# for i in range(1, 4 - 2)
# ]
# )
#
# await time_out_assert(15, wallet_0.get_confirmed_balance, funds)
#
# cc_wallet_0: CCWallet = await CCWallet.create_new_cc(
# wallet_node_0.wallet_state_manager, wallet_0, uint64(100)
# )
#
# for i in range(1, num_blocks):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# await time_out_assert(15, cc_wallet_0.get_confirmed_balance, 100)
# await time_out_assert(15, cc_wallet_0.get_unconfirmed_balance, 100)
#
# assert cc_wallet_0.cc_info.my_genesis_checker is not None
# colour = cc_wallet_0.get_colour()
#
# cc_wallet_1: CCWallet = await CCWallet.create_wallet_for_cc(
# wallet_node_1.wallet_state_manager, wallet_1, colour
# )
#
# cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
# wallet_node_2.wallet_state_manager, wallet_2, colour
# )
#
# assert (
# cc_wallet_0.cc_info.my_genesis_checker
# == cc_wallet_1.cc_info.my_genesis_checker
# )
# assert (
# cc_wallet_0.cc_info.my_genesis_checker
# == cc_wallet_2.cc_info.my_genesis_checker
# )
#
# cc_1_hash = await cc_wallet_1.get_new_inner_hash()
# cc_2_hash = await cc_wallet_2.get_new_inner_hash()
#
# tx_record = await cc_wallet_0.generate_signed_transaction(
# [uint64(60), uint64(20)], [cc_1_hash, cc_2_hash]
# )
# await wallet_0.wallet_state_manager.add_pending_transaction(tx_record)
#
# for i in range(1, num_blocks):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# await time_out_assert(15, cc_wallet_0.get_confirmed_balance, 20)
# await time_out_assert(15, cc_wallet_0.get_unconfirmed_balance, 20)
#
# await time_out_assert(30, cc_wallet_1.get_confirmed_balance, 60)
# await time_out_assert(30, cc_wallet_1.get_unconfirmed_balance, 60)
#
# await time_out_assert(30, cc_wallet_2.get_confirmed_balance, 20)
# await time_out_assert(30, cc_wallet_2.get_unconfirmed_balance, 20)
#
# cc_hash = await cc_wallet_0.get_new_inner_hash()
#
# tx_record = await cc_wallet_1.generate_signed_transaction(
# [uint64(15)], [cc_hash]
# )
# await wallet_1.wallet_state_manager.add_pending_transaction(tx_record)
#
# tx_record_2 = await cc_wallet_2.generate_signed_transaction(
# [uint64(20)], [cc_hash]
# )
# await wallet_2.wallet_state_manager.add_pending_transaction(tx_record_2)
#
# for i in range(1, num_blocks):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# await time_out_assert(15, cc_wallet_0.get_confirmed_balance, 55)
# await time_out_assert(15, cc_wallet_0.get_unconfirmed_balance, 55)
#
# await time_out_assert(30, cc_wallet_1.get_confirmed_balance, 45)
# await time_out_assert(30, cc_wallet_1.get_unconfirmed_balance, 45)
#
# await time_out_assert(30, cc_wallet_2.get_confirmed_balance, 0)
# await time_out_assert(30, cc_wallet_2.get_unconfirmed_balance, 0)

File diff suppressed because it is too large Load Diff

View File

@ -29,13 +29,13 @@ class TestPotIterations:
assert is_overflow_sub_block(test_constants, uint8(32))
def test_calculate_sp_iters(self):
ssi: uint64 = uint64(100001) * 300
ssi: uint64 = uint64(100001 * 64 * 4)
with raises(ValueError):
calculate_sp_iters(test_constants, ssi, uint8(32))
calculate_sp_iters(test_constants, ssi, uint8(31))
def test_calculate_ip_iters(self):
ssi: uint64 = uint64(100001) * 300
ssi: uint64 = uint64(100001 * 64 * 4)
sp_interval_iters = ssi // test_constants.NUM_SPS_SUB_SLOT
with raises(ValueError):
@ -84,15 +84,15 @@ class TestPotIterations:
farmer_ks = {
uint8(32): 200,
uint8(33): 200,
uint8(34): 100,
uint8(35): 100,
uint8(36): 100,
uint8(34): 120,
uint8(35): 120,
uint8(36): 120,
}
farmer_space = {k: _expected_plot_size(uint8(k)) * count for k, count in farmer_ks.items()}
total_space = sum(farmer_space.values())
percentage_space = {k: float(sp / total_space) for k, sp in farmer_space.items()}
wins = {k: 0 for k in farmer_ks.keys()}
total_slots = 400
total_slots = 600
num_sps = 16
sp_interval_iters = uint64(100000000 // 32)
difficulty = uint64(500000000000)

View File

@ -60,7 +60,7 @@ def get_prev_ses_block(sub_blocks, last_hash) -> (SubBlockRecord, int):
blocks += 1
def load_blocks_dont_validate(blocks):
async def load_blocks_dont_validate(blocks):
header_cache: Dict[bytes32, HeaderBlock] = {}
height_to_hash: Dict[uint32, bytes32] = {}
sub_blocks: Dict[bytes32, SubBlockRecord] = {}
@ -143,7 +143,7 @@ def _test_map_summaries(blocks, header_cache, height_to_hash, sub_blocks, sub_ep
class TestWeightProof:
@pytest.mark.asyncio
async def test_get_sub_epoch_block_num_basic(self, default_400_blocks):
header_cache, height_to_hash, sub_blocks = load_blocks_dont_validate(default_400_blocks)
header_cache, height_to_hash, sub_blocks = await load_blocks_dont_validate(default_400_blocks)
sub_epoch_end, _ = get_prev_ses_block(sub_blocks, default_400_blocks[-1].header_hash)
print("first block of last sub epoch ", sub_epoch_end.sub_block_height)
sub_epoch_blocks_n: uint32 = get_sub_epoch_block_num(
@ -155,7 +155,7 @@ class TestWeightProof:
@pytest.mark.asyncio
async def test_get_last_ses_block_idx(self, default_400_blocks):
header_cache, height_to_hash, sub_blocks = load_blocks_dont_validate(default_400_blocks)
header_cache, height_to_hash, sub_blocks = await load_blocks_dont_validate(default_400_blocks)
sub_epoch_end, _ = get_prev_ses_block(sub_blocks, default_400_blocks[-1].prev_header_hash)
recent_blocks: List[ProofBlockHeader] = []
for block in header_cache.values():
@ -167,19 +167,19 @@ class TestWeightProof:
@pytest.mark.asyncio
async def test_weight_proof_map_summaries_1(self, default_400_blocks):
header_cache, height_to_hash, sub_blocks = load_blocks_dont_validate(default_400_blocks)
header_cache, height_to_hash, sub_blocks = await load_blocks_dont_validate(default_400_blocks)
sub_epochs = 1
_test_map_summaries(default_400_blocks, header_cache, height_to_hash, sub_blocks, sub_epochs)
@pytest.mark.asyncio
async def test_weight_proof_map_summaries_2(self, default_400_blocks):
header_cache, height_to_hash, sub_blocks = load_blocks_dont_validate(default_400_blocks)
header_cache, height_to_hash, sub_blocks = await load_blocks_dont_validate(default_400_blocks)
sub_epochs = 2
_test_map_summaries(default_400_blocks, header_cache, height_to_hash, sub_blocks, sub_epochs)
@pytest.mark.asyncio
async def test_weight_proof_map_summaries_3(self, default_10000_blocks):
header_cache, height_to_hash, sub_blocks = load_blocks_dont_validate(default_10000_blocks)
header_cache, height_to_hash, sub_blocks = await load_blocks_dont_validate(default_10000_blocks)
sub_epochs = 10
_test_map_summaries(default_10000_blocks, header_cache, height_to_hash, sub_blocks, sub_epochs)
@ -187,7 +187,7 @@ class TestWeightProof:
async def test_weight_proof_summaries(self, default_10000_blocks):
sub_epochs = 3
blocks = default_10000_blocks
header_cache, height_to_hash, sub_blocks = load_blocks_dont_validate(blocks)
header_cache, height_to_hash, sub_blocks = await 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
@ -219,7 +219,7 @@ class TestWeightProof:
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)
header_cache, height_to_hash, sub_blocks = await 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
@ -252,7 +252,7 @@ class TestWeightProof:
@pytest.mark.asyncio
async def test_weight_proof_from_genesis(self, default_400_blocks):
blocks = default_400_blocks
header_cache, height_to_hash, sub_blocks = load_blocks_dont_validate(blocks)
header_cache, height_to_hash, sub_blocks = await load_blocks_dont_validate(blocks)
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)
@ -265,7 +265,7 @@ class TestWeightProof:
sub_epochs = 1
blocks = default_10000_blocks
header_cache, height_to_hash, sub_blocks = load_blocks_dont_validate(blocks)
header_cache, height_to_hash, sub_blocks = await 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

View File

@ -1,5 +1,5 @@
[pytest]
; logging options
log_cli = 1
log_level = WARNING
log_level = INFO
log_format = %(asctime)s %(name)s: %(levelname)s %(message)s

View File

@ -1,47 +1,47 @@
import asyncio
import pytest
from src.full_node.bundle_tools import best_solution_program
from src.consensus.cost_calculator import calculate_cost_of_program
from src.full_node.mempool_check_conditions import get_name_puzzle_conditions
from tests.setup_nodes import test_constants, bt
BURN_PUZZLE_HASH = b"0" * 32
@pytest.fixture(scope="module")
def event_loop():
loop = asyncio.get_event_loop()
yield loop
class TestCostCalculation:
@pytest.mark.asyncio
async def test_basics(self):
wallet_tool = bt.get_pool_wallet_tool()
num_blocks = 2
blocks = bt.get_consecutive_blocks(
test_constants,
num_blocks,
[],
10,
)
spend_bundle = wallet_tool.generate_signed_transaction(
blocks[1].get_coinbase().amount,
BURN_PUZZLE_HASH,
blocks[1].get_coinbase(),
)
assert spend_bundle is not None
program = best_solution_program(spend_bundle)
ratio = test_constants.CLVM_COST_RATIO_CONSTANT
error, npc_list, clvm_cost = calculate_cost_of_program(program, ratio)
error, npc_list, cost = get_name_puzzle_conditions(program)
# Create condition + agg_sig_condition + length + cpu_cost
assert clvm_cost == 200 * ratio + 20 * ratio + len(bytes(program)) * ratio + cost
# import asyncio
#
# import pytest
#
# from src.full_node.bundle_tools import best_solution_program
# from src.consensus.cost_calculator import calculate_cost_of_program
# from src.full_node.mempool_check_conditions import get_name_puzzle_conditions
# from tests.setup_nodes import test_constants, bt
#
# BURN_PUZZLE_HASH = b"0" * 32
#
#
# @pytest.fixture(scope="module")
# def event_loop():
# loop = asyncio.get_event_loop()
# yield loop
#
#
# class TestCostCalculation:
# @pytest.mark.asyncio
# async def test_basics(self):
# wallet_tool = bt.get_pool_wallet_tool()
#
# num_blocks = 2
# blocks = bt.get_consecutive_blocks(
# test_constants,
# num_blocks,
# [],
# 10,
# )
#
# spend_bundle = wallet_tool.generate_signed_transaction(
# blocks[1].get_coinbase().amount,
# BURN_PUZZLE_HASH,
# blocks[1].get_coinbase(),
# )
# assert spend_bundle is not None
# program = best_solution_program(spend_bundle)
#
# ratio = test_constants.CLVM_COST_RATIO_CONSTANT
#
# error, npc_list, clvm_cost = calculate_cost_of_program(program, ratio)
#
# error, npc_list, cost = get_name_puzzle_conditions(program)
#
# # Create condition + agg_sig_condition + length + cpu_cost
# assert clvm_cost == 200 * ratio + 20 * ratio + len(bytes(program)) * ratio + cost

View File

@ -1,45 +1,45 @@
import asyncio
from typing import List
import pytest
from chiabip158 import PyBIP158
from tests.setup_nodes import test_constants, setup_simulators_and_wallets, bt
@pytest.fixture(scope="module")
def event_loop():
loop = asyncio.get_event_loop()
yield loop
class TestFilter:
@pytest.fixture(scope="function")
async def wallet_and_node(self):
async for _ in setup_simulators_and_wallets(1, 1, {}):
yield _
@pytest.mark.asyncio
async def test_basic_filter_test(self, wallet_and_node):
full_nodes, wallets = wallet_and_node
wallet_node, server_2 = wallets[0]
wallet = wallet_node.wallet_state_manager.main_wallet
num_blocks = 2
await wallet.get_new_puzzlehash()
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10)
for i in range(1, num_blocks):
byte_array_tx: List[bytes] = []
block = blocks[i]
coinbase = bytearray(block.get_coinbase().puzzle_hash)
fee = bytearray(block.get_fees_coin().puzzle_hash)
byte_array_tx.append(coinbase)
byte_array_tx.append(fee)
pl = PyBIP158(byte_array_tx)
present = pl.Match(coinbase)
fee_present = pl.Match(fee)
assert present
assert fee_present
# import asyncio
# from typing import List
#
# import pytest
# from chiabip158 import PyBIP158
#
# from tests.setup_nodes import test_constants, setup_simulators_and_wallets, bt
#
#
# @pytest.fixture(scope="module")
# def event_loop():
# loop = asyncio.get_event_loop()
# yield loop
#
#
# class TestFilter:
# @pytest.fixture(scope="function")
# async def wallet_and_node(self):
# async for _ in setup_simulators_and_wallets(1, 1, {}):
# yield _
#
# @pytest.mark.asyncio
# async def test_basic_filter_test(self, wallet_and_node):
# full_nodes, wallets = wallet_and_node
# wallet_node, server_2 = wallets[0]
# wallet = wallet_node.wallet_state_manager.main_wallet
#
# num_blocks = 2
# await wallet.get_new_puzzlehash()
# blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10)
#
# for i in range(1, num_blocks):
# byte_array_tx: List[bytes] = []
# block = blocks[i]
# coinbase = bytearray(block.get_coinbase().puzzle_hash)
# fee = bytearray(block.get_fees_coin().puzzle_hash)
# byte_array_tx.append(coinbase)
# byte_array_tx.append(fee)
#
# pl = PyBIP158(byte_array_tx)
# present = pl.Match(coinbase)
# fee_present = pl.Match(fee)
#
# assert present
# assert fee_present

View File

@ -1,54 +1,45 @@
import asyncio
import pytest
from src.util.merkle_set import MerkleSet, confirm_included_already_hashed
from tests.setup_nodes import test_constants, bt
@pytest.fixture(scope="module")
def event_loop():
loop = asyncio.get_event_loop()
yield loop
class TestMerkleSet:
@pytest.mark.asyncio
async def test_basics(self):
num_blocks = 10
blocks = bt.get_consecutive_blocks(
test_constants,
num_blocks,
[],
10,
)
merkle_set = MerkleSet()
merkle_set_reverse = MerkleSet()
for block in reversed(blocks):
merkle_set_reverse.add_already_hashed(block.get_coinbase().name())
for block in blocks:
merkle_set.add_already_hashed(block.get_coinbase().name())
for block in blocks:
result, proof = merkle_set.is_included_already_hashed(
block.get_coinbase().name()
)
assert result is True
result_fee, proof_fee = merkle_set.is_included_already_hashed(
block.get_fees_coin().name()
)
assert result_fee is False
validate_proof = confirm_included_already_hashed(
merkle_set.get_root(), block.get_coinbase().name(), proof
)
validate_proof_fee = confirm_included_already_hashed(
merkle_set.get_root(), block.get_fees_coin().name(), proof_fee
)
assert validate_proof is True
assert validate_proof_fee is False
# Test if order of adding items change the outcome
assert merkle_set.get_root() == merkle_set_reverse.get_root()
# import asyncio
#
# import pytest
#
# from src.util.merkle_set import MerkleSet, confirm_included_already_hashed
# from tests.setup_nodes import bt
#
#
# @pytest.fixture(scope="module")
# def event_loop():
# loop = asyncio.get_event_loop()
# yield loop
#
#
# class TestMerkleSet:
# @pytest.mark.asyncio
# async def test_basics(self):
# num_blocks = 10
# blocks = bt.get_consecutive_blocks(
# num_blocks,
# )
#
# merkle_set = MerkleSet()
# merkle_set_reverse = MerkleSet()
#
# for block in reversed(blocks):
# merkle_set_reverse.add_already_hashed(block.get_coinbase().name())
#
# for block in blocks:
# merkle_set.add_already_hashed(block.get_coinbase().name())
#
# for block in blocks:
# result, proof = merkle_set.is_included_already_hashed(block.get_coinbase().name())
# assert result is True
# result_fee, proof_fee = merkle_set.is_included_already_hashed(block.get_fees_coin().name())
# assert result_fee is False
# validate_proof = confirm_included_already_hashed(merkle_set.get_root(), block.get_coinbase().name(), proof)
# validate_proof_fee = confirm_included_already_hashed(
# merkle_set.get_root(), block.get_fees_coin().name(), proof_fee
# )
# assert validate_proof is True
# assert validate_proof_fee is False
#
# # Test if order of adding items change the outcome
# assert merkle_set.get_root() == merkle_set_reverse.get_root()

View File

@ -1,45 +1,47 @@
# 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
#
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,
"NUM_SPS_SUB_SLOT": 64, # Must be a power of 2
"EPOCH_SUB_BLOCKS": 280,
"SUB_SLOT_ITERS_STARTING": 2 ** 24,
"NUMBER_ZERO_BITS_PLOT_FILTER": 4,
}
)
class TestSimulation:
@pytest.fixture(scope="function")
async def simulation(self):
async for _ in setup_full_system(test_constants_modified):
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)])

View File

@ -1,93 +1,93 @@
import asyncio
from pathlib import Path
from secrets import token_bytes
import pytest
from src.simulator.simulator_protocol import FarmNewBlockProtocol
from src.types.peer_info import PeerInfo
from src.util.ints import uint16, uint32, uint64
from tests.setup_nodes import setup_simulators_and_wallets
from src.consensus.block_rewards import calculate_base_fee, calculate_block_reward
from src.wallet.cc_wallet.cc_wallet import CCWallet
from tests.time_out_assert import time_out_assert
@pytest.fixture(scope="module")
def event_loop():
loop = asyncio.get_event_loop()
yield loop
class TestCCWalletBackup:
@pytest.fixture(scope="function")
async def two_wallet_nodes(self):
async for _ in setup_simulators_and_wallets(
1, 1, {"COINBASE_FREEZE_PERIOD": 0}
):
yield _
@pytest.mark.asyncio
async def test_coin_backup(self, two_wallet_nodes):
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 = 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
)
for i in range(1, 4):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
funds = sum(
[
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
for i in range(1, 4 - 2)
]
)
await time_out_assert(15, wallet.get_confirmed_balance, funds)
cc_wallet: CCWallet = await CCWallet.create_new_cc(
wallet_node.wallet_state_manager, wallet, uint64(100)
)
for i in range(1, num_blocks):
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
# Write backup to file
filename = f"test-backup-{token_bytes(16).hex()}"
file_path = Path(filename)
await wallet_node.wallet_state_manager.create_wallet_backup(file_path)
# Close wallet and restart
db_path = wallet_node.wallet_state_manager.db_path
wallet_node._close()
await wallet_node._await_closed()
db_path.unlink()
started = await wallet_node._start()
assert started is False
await wallet_node._start(backup_file=file_path)
await server_2.start_client(
PeerInfo("localhost", uint16(full_node_server._port)), None
)
all_wallets = wallet_node.wallet_state_manager.wallets
assert len(all_wallets) == 2
cc_wallet_from_backup = wallet_node.wallet_state_manager.wallets[2]
await time_out_assert(15, cc_wallet_from_backup.get_confirmed_balance, 100)
if file_path.exists():
file_path.unlink()
# import asyncio
# from pathlib import Path
# from secrets import token_bytes
#
# import pytest
#
# from src.simulator.simulator_protocol import FarmNewBlockProtocol
# from src.types.peer_info import PeerInfo
# from src.util.ints import uint16, uint32, uint64
# from tests.setup_nodes import setup_simulators_and_wallets
# from src.consensus.block_rewards import calculate_base_fee, calculate_block_reward
# from src.wallet.cc_wallet.cc_wallet import CCWallet
# from tests.time_out_assert import time_out_assert
#
#
# @pytest.fixture(scope="module")
# def event_loop():
# loop = asyncio.get_event_loop()
# yield loop
#
#
# class TestCCWalletBackup:
# @pytest.fixture(scope="function")
# async def two_wallet_nodes(self):
# async for _ in setup_simulators_and_wallets(
# 1, 1, {"COINBASE_FREEZE_PERIOD": 0}
# ):
# yield _
#
# @pytest.mark.asyncio
# async def test_coin_backup(self, two_wallet_nodes):
# 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 = 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
# )
# for i in range(1, 4):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# funds = sum(
# [
# calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
# for i in range(1, 4 - 2)
# ]
# )
#
# await time_out_assert(15, wallet.get_confirmed_balance, funds)
#
# cc_wallet: CCWallet = await CCWallet.create_new_cc(
# wallet_node.wallet_state_manager, wallet, uint64(100)
# )
#
# for i in range(1, num_blocks):
# await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
#
# await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
# await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
#
# # Write backup to file
# filename = f"test-backup-{token_bytes(16).hex()}"
# file_path = Path(filename)
# await wallet_node.wallet_state_manager.create_wallet_backup(file_path)
#
# # Close wallet and restart
# db_path = wallet_node.wallet_state_manager.db_path
# wallet_node._close()
# await wallet_node._await_closed()
#
# db_path.unlink()
#
# started = await wallet_node._start()
# assert started is False
#
# await wallet_node._start(backup_file=file_path)
# await server_2.start_client(
# PeerInfo("localhost", uint16(full_node_server._port)), None
# )
#
# all_wallets = wallet_node.wallet_state_manager.wallets
# assert len(all_wallets) == 2
#
# cc_wallet_from_backup = wallet_node.wallet_state_manager.wallets[2]
#
# await time_out_assert(15, cc_wallet_from_backup.get_confirmed_balance, 100)
# if file_path.exists():
# file_path.unlink()

View File

@ -59,7 +59,10 @@ class TestWalletSimulator:
await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))
funds = sum(
[calculate_pool_reward(uint32(i), False) + calculate_base_farmer_reward(uint32(i)) for i in range(0, num_blocks - 1)]
[
calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i))
for i in range(0, num_blocks - 1)
]
)
await time_out_assert(5, wallet.get_confirmed_balance, funds)

View File

@ -1,249 +1,226 @@
import asyncio
from pathlib import Path
from secrets import token_bytes
import aiosqlite
import pytest
from src.util.ints import uint32, uint64, uint128
from src.wallet.wallet_store import WalletStore
from src.wallet.wallet_coin_record import WalletCoinRecord
from src.wallet.util.wallet_types import WalletType
from src.wallet.block_record import BlockRecord
from src.types.coin import Coin
@pytest.fixture(scope="module")
def event_loop():
loop = asyncio.get_event_loop()
yield loop
class TestWalletStore:
@pytest.mark.asyncio
async def test_store(self):
db_filename = Path("blockchain_wallet_store_test.db")
if db_filename.exists():
db_filename.unlink()
db_connection = await aiosqlite.connect(db_filename)
store = await WalletStore.create(db_connection)
try:
coin_1 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
coin_2 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
coin_3 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
coin_4 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
record_replaced = WalletCoinRecord(
coin_1, uint32(8), uint32(0), False, True, WalletType.STANDARD_WALLET, 0
)
record_1 = WalletCoinRecord(
coin_1, uint32(4), uint32(0), False, True, WalletType.STANDARD_WALLET, 0
)
record_2 = WalletCoinRecord(
coin_2, uint32(5), uint32(0), False, True, WalletType.STANDARD_WALLET, 0
)
record_3 = WalletCoinRecord(
coin_3,
uint32(5),
uint32(10),
True,
False,
WalletType.STANDARD_WALLET,
0,
)
record_4 = WalletCoinRecord(
coin_4,
uint32(5),
uint32(15),
True,
False,
WalletType.STANDARD_WALLET,
0,
)
# Test add (replace) and get
assert await store.get_coin_record(coin_1.name()) is None
await store.add_coin_record(record_replaced)
await store.add_coin_record(record_1)
await store.add_coin_record(record_2)
await store.add_coin_record(record_3)
await store.add_coin_record(record_4)
assert await store.get_coin_record(coin_1.name()) == record_1
# Test persistance
await db_connection.close()
db_connection = await aiosqlite.connect(db_filename)
store = await WalletStore.create(db_connection)
assert await store.get_coin_record(coin_1.name()) == record_1
# Test set spent
await store.set_spent(coin_1.name(), uint32(12))
assert (await store.get_coin_record(coin_1.name())).spent
assert (await store.get_coin_record(coin_1.name())).spent_block_index == 12
# No coins at height 3
assert len(await store.get_unspent_coins_at_height(3)) == 0
assert len(await store.get_unspent_coins_at_height(4)) == 1
assert len(await store.get_unspent_coins_at_height(5)) == 4
assert len(await store.get_unspent_coins_at_height(11)) == 3
assert len(await store.get_unspent_coins_at_height(12)) == 2
assert len(await store.get_unspent_coins_at_height(15)) == 1
assert len(await store.get_unspent_coins_at_height(16)) == 1
assert len(await store.get_unspent_coins_at_height()) == 1
assert len(await store.get_unspent_coins_for_wallet(0)) == 1
assert len(await store.get_unspent_coins_for_wallet(1)) == 0
coin_5 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
record_5 = WalletCoinRecord(
coin_5,
uint32(5),
uint32(15),
False,
False,
WalletType.STANDARD_WALLET,
1,
)
await store.add_coin_record(record_5)
assert len(await store.get_unspent_coins_for_wallet(1)) == 1
assert len(await store.get_spendable_for_index(100, 1)) == 1
assert len(await store.get_spendable_for_index(100, 0)) == 1
assert len(await store.get_spendable_for_index(0, 0)) == 0
coin_6 = Coin(token_bytes(32), coin_4.puzzle_hash, uint64(12312))
await store.add_coin_record(record_5)
record_6 = WalletCoinRecord(
coin_6,
uint32(5),
uint32(15),
True,
False,
WalletType.STANDARD_WALLET,
2,
)
await store.add_coin_record(record_6)
assert (
len(
await store.get_coin_records_by_puzzle_hash(
record_6.coin.puzzle_hash
)
)
== 2
) # 4 and 6
assert (
len(await store.get_coin_records_by_puzzle_hash(token_bytes(32))) == 0
)
assert await store.get_coin_record_by_coin_id(coin_6.name()) == record_6
assert await store.get_coin_record_by_coin_id(token_bytes(32)) is None
# BLOCKS
assert len(await store.get_lca_path()) == 0
# NOT lca block
br_1 = BlockRecord(
token_bytes(32),
token_bytes(32),
uint32(0),
uint128(100),
None,
None,
None,
None,
uint64(0),
)
assert await store.get_block_record(br_1.header_hash) is None
await store.add_block_record(br_1, False)
assert len(await store.get_lca_path()) == 0
assert await store.get_block_record(br_1.header_hash) == br_1
# LCA genesis
await store.add_block_record(br_1, True)
assert await store.get_block_record(br_1.header_hash) == br_1
assert len(await store.get_lca_path()) == 1
assert (await store.get_lca_path())[br_1.header_hash] == br_1
br_2 = BlockRecord(
token_bytes(32),
token_bytes(32),
uint32(1),
uint128(100),
None,
None,
None,
None,
uint64(0),
)
await store.add_block_record(br_2, False)
assert len(await store.get_lca_path()) == 1
await store.add_block_to_path(br_2.header_hash)
assert len(await store.get_lca_path()) == 2
assert (await store.get_lca_path())[br_2.header_hash] == br_2
br_3 = BlockRecord(
token_bytes(32),
token_bytes(32),
uint32(2),
uint128(100),
None,
None,
None,
None,
uint64(0),
)
await store.add_block_record(br_3, True)
assert len(await store.get_lca_path()) == 3
await store.remove_blocks_from_path(1)
assert len(await store.get_lca_path()) == 2
await store.rollback_lca_to_block(0)
assert len(await store.get_unspent_coins_at_height()) == 0
coin_7 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
coin_8 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
coin_9 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
coin_10 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
record_7 = WalletCoinRecord(
coin_7, uint32(0), uint32(1), True, False, WalletType.STANDARD_WALLET, 1
)
record_8 = WalletCoinRecord(
coin_8, uint32(1), uint32(2), True, False, WalletType.STANDARD_WALLET, 1
)
record_9 = WalletCoinRecord(
coin_9, uint32(2), uint32(3), True, False, WalletType.STANDARD_WALLET, 1
)
record_10 = WalletCoinRecord(
coin_10,
uint32(3),
uint32(4),
True,
False,
WalletType.STANDARD_WALLET,
1,
)
await store.add_coin_record(record_7)
await store.add_coin_record(record_8)
await store.add_coin_record(record_9)
await store.add_coin_record(record_10)
assert len(await store.get_unspent_coins_at_height(0)) == 1
assert len(await store.get_unspent_coins_at_height(1)) == 1
assert len(await store.get_unspent_coins_at_height(2)) == 1
assert len(await store.get_unspent_coins_at_height(3)) == 1
assert len(await store.get_unspent_coins_at_height(4)) == 0
await store.add_block_record(br_2, True)
await store.add_block_record(br_3, True)
await store.rollback_lca_to_block(1)
assert len(await store.get_unspent_coins_at_height(0)) == 1
assert len(await store.get_unspent_coins_at_height(1)) == 1
assert len(await store.get_unspent_coins_at_height(2)) == 1
assert len(await store.get_unspent_coins_at_height(3)) == 1
assert len(await store.get_unspent_coins_at_height(4)) == 1
except AssertionError:
await db_connection.close()
raise
await db_connection.close()
# import asyncio
# from pathlib import Path
# from secrets import token_bytes
# import aiosqlite
# import pytest
# from src.util.ints import uint32, uint64, uint128
# from src.wallet.wallet_coin_record import WalletCoinRecord
# from src.wallet.util.wallet_types import WalletType
# from src.types.coin import Coin
#
#
# @pytest.fixture(scope="module")
# def event_loop():
# loop = asyncio.get_event_loop()
# yield loop
#
#
# class TestWalletStore:
# @pytest.mark.asyncio
# async def test_store(self):
# db_filename = Path("blockchain_wallet_store_test.db")
#
# if db_filename.exists():
# db_filename.unlink()
#
# db_connection = await aiosqlite.connect(db_filename)
# store = await WalletStore.create(db_connection)
# try:
# coin_1 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
# coin_2 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
# coin_3 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
# coin_4 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
# record_replaced = WalletCoinRecord(coin_1, uint32(8), uint32(0), False, True, WalletType.STANDARD_WALLET, 0)
# record_1 = WalletCoinRecord(coin_1, uint32(4), uint32(0), False, True, WalletType.STANDARD_WALLET, 0)
# record_2 = WalletCoinRecord(coin_2, uint32(5), uint32(0), False, True, WalletType.STANDARD_WALLET, 0)
# record_3 = WalletCoinRecord(
# coin_3,
# uint32(5),
# uint32(10),
# True,
# False,
# WalletType.STANDARD_WALLET,
# 0,
# )
# record_4 = WalletCoinRecord(
# coin_4,
# uint32(5),
# uint32(15),
# True,
# False,
# WalletType.STANDARD_WALLET,
# 0,
# )
#
# # Test add (replace) and get
# assert await store.get_coin_record(coin_1.name()) is None
# await store.add_coin_record(record_replaced)
# await store.add_coin_record(record_1)
# await store.add_coin_record(record_2)
# await store.add_coin_record(record_3)
# await store.add_coin_record(record_4)
# assert await store.get_coin_record(coin_1.name()) == record_1
#
# # Test persistance
# await db_connection.close()
# db_connection = await aiosqlite.connect(db_filename)
# store = await WalletStore.create(db_connection)
# assert await store.get_coin_record(coin_1.name()) == record_1
#
# # Test set spent
# await store.set_spent(coin_1.name(), uint32(12))
# assert (await store.get_coin_record(coin_1.name())).spent
# assert (await store.get_coin_record(coin_1.name())).spent_block_index == 12
#
# # No coins at height 3
# assert len(await store.get_unspent_coins_at_height(3)) == 0
# assert len(await store.get_unspent_coins_at_height(4)) == 1
# assert len(await store.get_unspent_coins_at_height(5)) == 4
# assert len(await store.get_unspent_coins_at_height(11)) == 3
# assert len(await store.get_unspent_coins_at_height(12)) == 2
# assert len(await store.get_unspent_coins_at_height(15)) == 1
# assert len(await store.get_unspent_coins_at_height(16)) == 1
# assert len(await store.get_unspent_coins_at_height()) == 1
#
# assert len(await store.get_unspent_coins_for_wallet(0)) == 1
# assert len(await store.get_unspent_coins_for_wallet(1)) == 0
#
# coin_5 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
# record_5 = WalletCoinRecord(
# coin_5,
# uint32(5),
# uint32(15),
# False,
# False,
# WalletType.STANDARD_WALLET,
# 1,
# )
# await store.add_coin_record(record_5)
# assert len(await store.get_unspent_coins_for_wallet(1)) == 1
#
# assert len(await store.get_spendable_for_index(100, 1)) == 1
# assert len(await store.get_spendable_for_index(100, 0)) == 1
# assert len(await store.get_spendable_for_index(0, 0)) == 0
#
# coin_6 = Coin(token_bytes(32), coin_4.puzzle_hash, uint64(12312))
# await store.add_coin_record(record_5)
# record_6 = WalletCoinRecord(
# coin_6,
# uint32(5),
# uint32(15),
# True,
# False,
# WalletType.STANDARD_WALLET,
# 2,
# )
# await store.add_coin_record(record_6)
# assert len(await store.get_coin_records_by_puzzle_hash(record_6.coin.puzzle_hash)) == 2 # 4 and 6
# assert len(await store.get_coin_records_by_puzzle_hash(token_bytes(32))) == 0
#
# assert await store.get_coin_record_by_coin_id(coin_6.name()) == record_6
# assert await store.get_coin_record_by_coin_id(token_bytes(32)) is None
#
# # BLOCKS
# assert len(await store.get_lca_path()) == 0
#
# # NOT lca block
# br_1 = BlockRecord(
# token_bytes(32),
# token_bytes(32),
# uint32(0),
# uint128(100),
# None,
# None,
# None,
# None,
# uint64(0),
# )
# assert await store.get_block_record(br_1.header_hash) is None
# await store.add_block_record(br_1, False)
# assert len(await store.get_lca_path()) == 0
# assert await store.get_block_record(br_1.header_hash) == br_1
#
# # LCA genesis
# await store.add_block_record(br_1, True)
# assert await store.get_block_record(br_1.header_hash) == br_1
# assert len(await store.get_lca_path()) == 1
# assert (await store.get_lca_path())[br_1.header_hash] == br_1
#
# br_2 = BlockRecord(
# token_bytes(32),
# token_bytes(32),
# uint32(1),
# uint128(100),
# None,
# None,
# None,
# None,
# uint64(0),
# )
# await store.add_block_record(br_2, False)
# assert len(await store.get_lca_path()) == 1
# await store.add_block_to_path(br_2.header_hash)
# assert len(await store.get_lca_path()) == 2
# assert (await store.get_lca_path())[br_2.header_hash] == br_2
#
# br_3 = BlockRecord(
# token_bytes(32),
# token_bytes(32),
# uint32(2),
# uint128(100),
# None,
# None,
# None,
# None,
# uint64(0),
# )
# await store.add_block_record(br_3, True)
# assert len(await store.get_lca_path()) == 3
# await store.remove_blocks_from_path(1)
# assert len(await store.get_lca_path()) == 2
#
# await store.rollback_lca_to_block(0)
# assert len(await store.get_unspent_coins_at_height()) == 0
#
# coin_7 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
# coin_8 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
# coin_9 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
# coin_10 = Coin(token_bytes(32), token_bytes(32), uint64(12312))
# record_7 = WalletCoinRecord(coin_7, uint32(0), uint32(1), True, False, WalletType.STANDARD_WALLET, 1)
# record_8 = WalletCoinRecord(coin_8, uint32(1), uint32(2), True, False, WalletType.STANDARD_WALLET, 1)
# record_9 = WalletCoinRecord(coin_9, uint32(2), uint32(3), True, False, WalletType.STANDARD_WALLET, 1)
# record_10 = WalletCoinRecord(
# coin_10,
# uint32(3),
# uint32(4),
# True,
# False,
# WalletType.STANDARD_WALLET,
# 1,
# )
#
# await store.add_coin_record(record_7)
# await store.add_coin_record(record_8)
# await store.add_coin_record(record_9)
# await store.add_coin_record(record_10)
# assert len(await store.get_unspent_coins_at_height(0)) == 1
# assert len(await store.get_unspent_coins_at_height(1)) == 1
# assert len(await store.get_unspent_coins_at_height(2)) == 1
# assert len(await store.get_unspent_coins_at_height(3)) == 1
# assert len(await store.get_unspent_coins_at_height(4)) == 0
#
# await store.add_block_record(br_2, True)
# await store.add_block_record(br_3, True)
#
# await store.rollback_lca_to_block(1)
#
# assert len(await store.get_unspent_coins_at_height(0)) == 1
# assert len(await store.get_unspent_coins_at_height(1)) == 1
# assert len(await store.get_unspent_coins_at_height(2)) == 1
# assert len(await store.get_unspent_coins_at_height(3)) == 1
# assert len(await store.get_unspent_coins_at_height(4)) == 1
#
# except AssertionError:
# await db_connection.close()
# raise
# await db_connection.close()

View File

@ -1,253 +1,253 @@
import asyncio
import pytest
from src.types.peer_info import PeerInfo
from src.protocols import full_node_protocol
from src.util.ints import uint16, uint64, uint32
from tests.setup_nodes import setup_node_and_wallet, test_constants, bt
from src.types.spend_bundle import SpendBundle
from src.full_node.bundle_tools import best_solution_program
from src.types.coin import Coin
from src.consensus.coinbase import create_coinbase_coin
from tests.time_out_assert import time_out_assert
def wallet_height_at_least(wallet_node, h):
if wallet_node.wallet_state_manager.block_records[wallet_node.wallet_state_manager.lca].height >= h:
return True
return False
@pytest.fixture(scope="module")
def event_loop():
loop = asyncio.get_event_loop()
yield loop
class TestWalletSync:
@pytest.fixture(scope="function")
async def wallet_node(self):
constants = test_constants.replace(COINBASE_FREEZE_PERIOD=0)
async for _ in setup_node_and_wallet(constants):
yield _
@pytest.fixture(scope="function")
async def wallet_node_starting_height(self):
async for _ in setup_node_and_wallet(test_constants, starting_height=100):
yield _
@pytest.mark.asyncio
async def test_basic_sync_wallet(self, wallet_node):
num_blocks = 300 # This must be greater than the short_sync in wallet_node
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [])
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 wallet_server.start_client(PeerInfo("localhost", uint16(full_node_server._port)), None)
# The second node should eventually catch up to the first one, and have the
# same tip at height num_blocks - 1.
await time_out_assert(200, wallet_height_at_least, True, wallet_node, num_blocks - 6)
# 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 time_out_assert(200, wallet_height_at_least, True, wallet_node, 33)
@pytest.mark.asyncio
async def test_fast_sync_wallet(self, wallet_node_starting_height):
num_blocks = 25 # This must be greater than the short_sync in wallet_node
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [])
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 server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
await time_out_assert(60, wallet_height_at_least, True, wallet_node, num_blocks - 6)
@pytest.mark.asyncio
async def test_short_sync_wallet(self, wallet_node):
num_blocks = 5 # This must be lower than the short_sync in wallet_node
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10)
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 server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
await time_out_assert(60, wallet_height_at_least, True, wallet_node, 3)
@pytest.mark.asyncio
async def test_short_sync_with_transactions_wallet(self, wallet_node):
BURN_PUZZLE_HASH_1 = b"0" * 32
BURN_PUZZLE_HASH_2 = b"1" * 32
full_node_1, wallet_node, server_1, server_2 = wallet_node
wallet_a = wallet_node.wallet_state_manager.main_wallet
coinbase_puzzlehash = await wallet_a.get_new_puzzlehash()
coinbase_puzzlehash_rest = BURN_PUZZLE_HASH_1
puzzle_hashes = [await wallet_a.get_new_puzzlehash() for _ in range(10)]
puzzle_hashes.append(BURN_PUZZLE_HASH_2)
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 server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
await time_out_assert(60, wallet_height_at_least, True, wallet_node, 1)
await server_2.close_all_connections()
dic_h = {}
prev_coin = blocks[1].get_coinbase()
for i in range(11):
pk, sk = await wallet_a.wallet_state_manager.get_keys(prev_coin.puzzle_hash)
transaction_unsigned = await wallet_a.generate_unsigned_transaction(
1000, puzzle_hashes[i], coins=[prev_coin]
)
spend_bundle = await wallet_a.sign_transaction(transaction_unsigned)
block_spendbundle = SpendBundle.aggregate([spend_bundle])
program = best_solution_program(block_spendbundle)
aggsig = block_spendbundle.aggregated_signature
prev_coin = Coin(prev_coin.name(), puzzle_hashes[i], uint64(1000))
dic_h[i + 4] = (program, aggsig)
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))
# Do a short sync from 0 to 14
await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
await time_out_assert(60, wallet_height_at_least, True, wallet_node, 14)
await server_2.close_all_connections()
# 3 block rewards and 3 fees - 1000 coins spent
assert (
await wallet_a.get_confirmed_balance()
== (blocks[1].get_coinbase().amount * 3) + (blocks[1].get_fees_coin().amount * 3) - 1000
)
# All of our coins are spent and puzzle hashes present
for puzzle_hash in puzzle_hashes[:-1]:
records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash(puzzle_hash)
assert len(records) == 1
assert records[0].spent and not records[0].coinbase
# Then do the same but in a reorg chain
dic_h = {}
prev_coin = blocks[1].get_coinbase()
for i in range(11):
pk, sk = await wallet_a.wallet_state_manager.get_keys(prev_coin.puzzle_hash)
transaction_unsigned = await wallet_a.generate_unsigned_transaction(
1000,
puzzle_hashes[i],
coins=[prev_coin],
)
spend_bundle = await wallet_a.sign_transaction(transaction_unsigned)
block_spendbundle = SpendBundle.aggregate([spend_bundle])
program = best_solution_program(block_spendbundle)
aggsig = block_spendbundle.aggregated_signature
prev_coin = Coin(prev_coin.name(), puzzle_hashes[i], uint64(1000))
dic_h[i + 4] = (program, aggsig)
blocks = bt.get_consecutive_blocks(
test_constants,
31,
blocks[:4],
10,
b"this is a reorg",
coinbase_puzzlehash_rest,
dic_h,
)
# 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))
# Do a sync from 0 to 22
await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
await time_out_assert(60, wallet_height_at_least, True, wallet_node, 28)
await server_2.close_all_connections()
# 3 block rewards and 3 fees - 1000 coins spent
assert (
await wallet_a.get_confirmed_balance()
== (blocks[1].get_coinbase().amount * 3) + (blocks[1].get_fees_coin().amount * 3) - 1000
)
# All of our coins are spent and puzzle hashes present
for puzzle_hash in puzzle_hashes[:-1]:
records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash(puzzle_hash)
assert len(records) == 1
assert records[0].spent and not records[0].coinbase
# Test spending the rewards earned in reorg
new_coinbase_puzzlehash = await wallet_a.get_new_puzzlehash()
another_puzzlehash = await wallet_a.get_new_puzzlehash()
dic_h = {}
pk, sk = await wallet_a.wallet_state_manager.get_keys(new_coinbase_puzzlehash)
coinbase_coin = create_coinbase_coin(uint32(25), new_coinbase_puzzlehash, uint64(14000000000000))
transaction_unsigned = await wallet_a.generate_unsigned_transaction(
7000000000000,
another_puzzlehash,
coins=[coinbase_coin],
)
spend_bundle = await wallet_a.sign_transaction(transaction_unsigned)
block_spendbundle = SpendBundle.aggregate([spend_bundle])
program = best_solution_program(block_spendbundle)
aggsig = block_spendbundle.aggregated_signature
dic_h[26] = (program, aggsig)
# Farm a block (25) to ourselves
blocks = bt.get_consecutive_blocks(
test_constants,
1,
blocks[:25],
10,
b"this is yet another reorg",
new_coinbase_puzzlehash,
)
# Brings height up to 40, with block 31 having half our reward spent to us
blocks = bt.get_consecutive_blocks(
test_constants,
15,
blocks,
10,
b"this is yet another reorg more blocks",
coinbase_puzzlehash_rest,
dic_h,
)
for block in blocks:
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)
# 4 block rewards and 4 fees - 1000 coins spent
assert (
await wallet_a.get_confirmed_balance()
== (blocks[1].get_coinbase().amount * 4) + (blocks[1].get_fees_coin().amount * 4) - 1000
)
records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash(
new_coinbase_puzzlehash
)
# Fee and coinbase
assert len(records) == 2
print(records)
assert records[0].spent != records[1].spent
assert records[0].coinbase == records[1].coinbase
records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash(
another_puzzlehash
)
assert len(records) == 1
assert not records[0].spent
assert not records[0].coinbase
# import asyncio
#
# import pytest
#
# from src.types.peer_info import PeerInfo
# from src.protocols import full_node_protocol
# from src.util.ints import uint16, uint64, uint32
# from tests.setup_nodes import setup_node_and_wallet, test_constants, bt
# from src.types.spend_bundle import SpendBundle
# from src.full_node.bundle_tools import best_solution_program
# from src.types.coin import Coin
# from src.consensus.coinbase import create_coinbase_coin
# from tests.time_out_assert import time_out_assert
#
#
# def wallet_height_at_least(wallet_node, h):
# if wallet_node.wallet_state_manager.block_records[wallet_node.wallet_state_manager.lca].height >= h:
# return True
# return False
#
#
# @pytest.fixture(scope="module")
# def event_loop():
# loop = asyncio.get_event_loop()
# yield loop
#
#
# class TestWalletSync:
# @pytest.fixture(scope="function")
# async def wallet_node(self):
# constants = test_constants.replace(COINBASE_FREEZE_PERIOD=0)
# async for _ in setup_node_and_wallet(constants):
# yield _
#
# @pytest.fixture(scope="function")
# async def wallet_node_starting_height(self):
# async for _ in setup_node_and_wallet(test_constants, starting_height=100):
# yield _
#
# @pytest.mark.asyncio
# async def test_basic_sync_wallet(self, wallet_node):
# num_blocks = 300 # This must be greater than the short_sync in wallet_node
# blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [])
# 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 wallet_server.start_client(PeerInfo("localhost", uint16(full_node_server._port)), None)
#
# # The second node should eventually catch up to the first one, and have the
# # same tip at height num_blocks - 1.
# await time_out_assert(200, wallet_height_at_least, True, wallet_node, num_blocks - 6)
#
# # 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 time_out_assert(200, wallet_height_at_least, True, wallet_node, 33)
#
# @pytest.mark.asyncio
# async def test_fast_sync_wallet(self, wallet_node_starting_height):
# num_blocks = 25 # This must be greater than the short_sync in wallet_node
# blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [])
# 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 server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
#
# await time_out_assert(60, wallet_height_at_least, True, wallet_node, num_blocks - 6)
#
# @pytest.mark.asyncio
# async def test_short_sync_wallet(self, wallet_node):
# num_blocks = 5 # This must be lower than the short_sync in wallet_node
# blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10)
# 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 server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
# await time_out_assert(60, wallet_height_at_least, True, wallet_node, 3)
#
# @pytest.mark.asyncio
# async def test_short_sync_with_transactions_wallet(self, wallet_node):
# BURN_PUZZLE_HASH_1 = b"0" * 32
# BURN_PUZZLE_HASH_2 = b"1" * 32
# full_node_1, wallet_node, server_1, server_2 = wallet_node
# wallet_a = wallet_node.wallet_state_manager.main_wallet
# coinbase_puzzlehash = await wallet_a.get_new_puzzlehash()
# coinbase_puzzlehash_rest = BURN_PUZZLE_HASH_1
# puzzle_hashes = [await wallet_a.get_new_puzzlehash() for _ in range(10)]
# puzzle_hashes.append(BURN_PUZZLE_HASH_2)
#
# 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 server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
# await time_out_assert(60, wallet_height_at_least, True, wallet_node, 1)
#
# await server_2.close_all_connections()
#
# dic_h = {}
# prev_coin = blocks[1].get_coinbase()
# for i in range(11):
# pk, sk = await wallet_a.wallet_state_manager.get_keys(prev_coin.puzzle_hash)
# transaction_unsigned = await wallet_a.generate_unsigned_transaction(
# 1000, puzzle_hashes[i], coins=[prev_coin]
# )
# spend_bundle = await wallet_a.sign_transaction(transaction_unsigned)
# block_spendbundle = SpendBundle.aggregate([spend_bundle])
# program = best_solution_program(block_spendbundle)
# aggsig = block_spendbundle.aggregated_signature
# prev_coin = Coin(prev_coin.name(), puzzle_hashes[i], uint64(1000))
# dic_h[i + 4] = (program, aggsig)
#
# 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))
#
# # Do a short sync from 0 to 14
# await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
# await time_out_assert(60, wallet_height_at_least, True, wallet_node, 14)
#
# await server_2.close_all_connections()
#
# # 3 block rewards and 3 fees - 1000 coins spent
# assert (
# await wallet_a.get_confirmed_balance()
# == (blocks[1].get_coinbase().amount * 3) + (blocks[1].get_fees_coin().amount * 3) - 1000
# )
# # All of our coins are spent and puzzle hashes present
# for puzzle_hash in puzzle_hashes[:-1]:
# records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash(puzzle_hash)
# assert len(records) == 1
# assert records[0].spent and not records[0].coinbase
#
# # Then do the same but in a reorg chain
# dic_h = {}
# prev_coin = blocks[1].get_coinbase()
# for i in range(11):
# pk, sk = await wallet_a.wallet_state_manager.get_keys(prev_coin.puzzle_hash)
# transaction_unsigned = await wallet_a.generate_unsigned_transaction(
# 1000,
# puzzle_hashes[i],
# coins=[prev_coin],
# )
# spend_bundle = await wallet_a.sign_transaction(transaction_unsigned)
# block_spendbundle = SpendBundle.aggregate([spend_bundle])
# program = best_solution_program(block_spendbundle)
# aggsig = block_spendbundle.aggregated_signature
# prev_coin = Coin(prev_coin.name(), puzzle_hashes[i], uint64(1000))
# dic_h[i + 4] = (program, aggsig)
#
# blocks = bt.get_consecutive_blocks(
# test_constants,
# 31,
# blocks[:4],
# 10,
# b"this is a reorg",
# coinbase_puzzlehash_rest,
# dic_h,
# )
#
# # 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))
#
# # Do a sync from 0 to 22
# await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
#
# await time_out_assert(60, wallet_height_at_least, True, wallet_node, 28)
# await server_2.close_all_connections()
#
# # 3 block rewards and 3 fees - 1000 coins spent
# assert (
# await wallet_a.get_confirmed_balance()
# == (blocks[1].get_coinbase().amount * 3) + (blocks[1].get_fees_coin().amount * 3) - 1000
# )
# # All of our coins are spent and puzzle hashes present
# for puzzle_hash in puzzle_hashes[:-1]:
# records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash(puzzle_hash)
# assert len(records) == 1
# assert records[0].spent and not records[0].coinbase
#
# # Test spending the rewards earned in reorg
# new_coinbase_puzzlehash = await wallet_a.get_new_puzzlehash()
# another_puzzlehash = await wallet_a.get_new_puzzlehash()
#
# dic_h = {}
# pk, sk = await wallet_a.wallet_state_manager.get_keys(new_coinbase_puzzlehash)
# coinbase_coin = create_coinbase_coin(uint32(25), new_coinbase_puzzlehash, uint64(14000000000000))
# transaction_unsigned = await wallet_a.generate_unsigned_transaction(
# 7000000000000,
# another_puzzlehash,
# coins=[coinbase_coin],
# )
# spend_bundle = await wallet_a.sign_transaction(transaction_unsigned)
# block_spendbundle = SpendBundle.aggregate([spend_bundle])
# program = best_solution_program(block_spendbundle)
# aggsig = block_spendbundle.aggregated_signature
# dic_h[26] = (program, aggsig)
#
# # Farm a block (25) to ourselves
# blocks = bt.get_consecutive_blocks(
# test_constants,
# 1,
# blocks[:25],
# 10,
# b"this is yet another reorg",
# new_coinbase_puzzlehash,
# )
#
# # Brings height up to 40, with block 31 having half our reward spent to us
# blocks = bt.get_consecutive_blocks(
# test_constants,
# 15,
# blocks,
# 10,
# b"this is yet another reorg more blocks",
# coinbase_puzzlehash_rest,
# dic_h,
# )
# for block in blocks:
# 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)
#
# # 4 block rewards and 4 fees - 1000 coins spent
# assert (
# await wallet_a.get_confirmed_balance()
# == (blocks[1].get_coinbase().amount * 4) + (blocks[1].get_fees_coin().amount * 4) - 1000
# )
# records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash(
# new_coinbase_puzzlehash
# )
# # Fee and coinbase
# assert len(records) == 2
# print(records)
# assert records[0].spent != records[1].spent
# assert records[0].coinbase == records[1].coinbase
# records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash(
# another_puzzlehash
# )
# assert len(records) == 1
# assert not records[0].spent
# assert not records[0].coinbase