mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2024-09-21 00:24:37 +03:00
Got simulation test to pass
This commit is contained in:
parent
1ccd1632ef
commit
fff9ccb026
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)}"
|
||||
)
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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] = (
|
||||
|
@ -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
|
||||
|
@ -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
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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)])
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user