Timelord fixes
This commit is contained in:
parent
4fc8e4e0b3
commit
1df5594e94
|
@ -7,7 +7,7 @@ from src.util.ints import uint64, uint32, uint8
|
|||
@dataclasses.dataclass(frozen=True)
|
||||
class ConsensusConstants:
|
||||
SLOT_SUB_BLOCKS_TARGET: uint32 # How many sub-blocks to target per sub-slot
|
||||
MIN_SUB_BLOCKS_PER_CHALLENGE_BLOCK: uint32 # How many sub-blocks must be created per slot (to make challenge sb)
|
||||
MIN_SUB_BLOCKS_PER_CHALLENGE_BLOCK: uint8 # How many sub-blocks must be created per slot (to make challenge sb)
|
||||
# Max number of sub-blocks that can be infused into a sub-slot.
|
||||
# Note: this must be less than SUB_EPOCH_SUB_BLOCKS/2, and > SLOT_SUB_BLOCKS_TARGET
|
||||
MAX_SUB_SLOT_SUB_BLOCKS: uint32
|
||||
|
|
|
@ -7,7 +7,7 @@ testnet_kwargs = {
|
|||
"MIN_SUB_BLOCKS_PER_CHALLENGE_BLOCK": 16,
|
||||
"MAX_SUB_SLOT_SUB_BLOCKS": 128,
|
||||
"NUM_SPS_SUB_SLOT": 64,
|
||||
"SUB_SLOT_ITERS_STARTING": 2 ** 25,
|
||||
"SUB_SLOT_ITERS_STARTING": 2 ** 24,
|
||||
# DIFFICULTY_STARTING is the starting difficulty for the first epoch, which is then further
|
||||
# multiplied by another factor of 2^25, to be used in the VDF iter calculation formula.
|
||||
"DIFFICULTY_STARTING": 2 ** 20,
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import asyncio
|
||||
import socket
|
||||
import logging
|
||||
|
||||
from src.server.server import ChiaServer
|
||||
from src.types.peer_info import PeerInfo
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def start_reconnect_task(server, peer_info_arg, log, auth):
|
||||
def start_reconnect_task(server: ChiaServer, peer_info_arg: PeerInfo, log, auth: bool):
|
||||
"""
|
||||
Start a background task that checks connection and reconnects periodically to a peer.
|
||||
"""
|
||||
|
@ -16,20 +14,15 @@ def start_reconnect_task(server, peer_info_arg, log, auth):
|
|||
async def connection_check():
|
||||
while True:
|
||||
peer_retry = True
|
||||
for id, connection in server.all_connections.items():
|
||||
if (
|
||||
connection.get_peer_info() == peer_info
|
||||
or connection.get_peer_info() == peer_info_arg
|
||||
):
|
||||
log.info(f"Not reconnecting to peer {peer_info}")
|
||||
for _, connection in server.all_connections.items():
|
||||
if connection.get_peer_info() == peer_info or connection.get_peer_info() == peer_info_arg:
|
||||
peer_retry = False
|
||||
|
||||
if peer_retry:
|
||||
log.info(f"Reconnecting to peer {peer_info}")
|
||||
try:
|
||||
await server.start_client(peer_info, None, auth=auth)
|
||||
except Exception as e:
|
||||
log.info(f"Failed to connect to {peer_info} {e}")
|
||||
await asyncio.sleep(3)
|
||||
await asyncio.sleep(300)
|
||||
|
||||
return asyncio.create_task(connection_check())
|
||||
|
|
141
src/timelord.py
141
src/timelord.py
|
@ -62,19 +62,6 @@ def iters_from_sub_block(
|
|||
)
|
||||
|
||||
|
||||
class EndOfSubSlotData:
|
||||
eos_bundle: EndOfSubSlotBundle
|
||||
sub_slot_iters: uint64
|
||||
new_difficulty: uint64
|
||||
deficit: uint8
|
||||
|
||||
def __init__(self, eos_bundle, sub_slot_iters, new_difficulty, deficit):
|
||||
self.eos_bundle = eos_bundle
|
||||
self.sub_slot_iters = sub_slot_iters
|
||||
self.new_difficulty = new_difficulty
|
||||
self.deficit = deficit
|
||||
|
||||
|
||||
class Chain(Enum):
|
||||
CHALLENGE_CHAIN = 1
|
||||
REWARD_CHAIN = 2
|
||||
|
@ -90,16 +77,19 @@ class IterationType(Enum):
|
|||
class LastState:
|
||||
def __init__(self, constants: ConsensusConstants):
|
||||
self.peak: Optional[timelord_protocol.NewPeak] = None
|
||||
self.subslot_end: Optional[EndOfSubSlotData] = None
|
||||
self.subslot_end: Optional[EndOfSubSlotBundle] = None
|
||||
self.last_ip: uint64 = uint64(0)
|
||||
self.deficit: uint8 = uint8(0)
|
||||
self.deficit: uint8 = constants.MIN_SUB_BLOCKS_PER_CHALLENGE_BLOCK
|
||||
self.sub_epoch_summary: Optional[SubEpochSummary] = None
|
||||
self.constants: ConsensusConstants = constants
|
||||
self.last_weight: uint128 = uint128(0)
|
||||
self.total_iters: uint128 = uint128(0)
|
||||
self.last_peak_challenge: Optional[bytes32] = None
|
||||
self.last_peak_challenge: bytes32 = constants.FIRST_RC_CHALLENGE
|
||||
self.first_sub_slot_no_peak: bool = True
|
||||
self.difficulty: uint64 = constants.DIFFICULTY_STARTING
|
||||
self.sub_slot_iters: uint64 = constants.SUB_SLOT_ITERS_STARTING
|
||||
|
||||
def set_state(self, state):
|
||||
def set_state(self, state: Union[timelord_protocol.NewPeak, EndOfSubSlotBundle]):
|
||||
if isinstance(state, timelord_protocol.NewPeak):
|
||||
self.peak = state
|
||||
self.subslot_end = None
|
||||
|
@ -114,19 +104,21 @@ class LastState:
|
|||
self.last_weight = state.reward_chain_sub_block.weight
|
||||
self.total_iters = state.reward_chain_sub_block.total_iters
|
||||
self.last_peak_challenge = state.reward_chain_sub_block.get_hash()
|
||||
if isinstance(state, EndOfSubSlotData):
|
||||
self.difficulty = state.difficulty
|
||||
self.sub_slot_iters = state.sub_slot_iters
|
||||
|
||||
if isinstance(state, EndOfSubSlotBundle):
|
||||
self.peak = None
|
||||
self.subslot_end = state
|
||||
self.last_ip = 0
|
||||
self.deficit = state.deficit
|
||||
|
||||
def is_empty(self) -> bool:
|
||||
return self.peak is None and self.subslot_end is None
|
||||
self.deficit = state.reward_chain.deficit
|
||||
if state.challenge_chain.new_difficulty is not None:
|
||||
self.difficulty = state.challenge_chain.new_difficulty
|
||||
self.sub_slot_iters = state.challenge_chain.new_sub_slot_iters
|
||||
self.first_sub_slot_no_peak = False
|
||||
|
||||
def get_sub_slot_iters(self) -> uint64:
|
||||
if self.peak is not None:
|
||||
return self.peak.sub_slot_iters
|
||||
return self.subslot_end.sub_slot_iters
|
||||
return self.sub_slot_iters
|
||||
|
||||
def get_weight(self) -> uint128:
|
||||
return self.last_weight
|
||||
|
@ -138,32 +130,35 @@ class LastState:
|
|||
return self.last_peak_challenge
|
||||
|
||||
def get_difficulty(self) -> uint64:
|
||||
if self.peak is not None:
|
||||
return self.peak.difficulty
|
||||
return self.subslot_end.new_difficulty
|
||||
return self.difficulty
|
||||
|
||||
def get_last_ip(self) -> uint64:
|
||||
return self.last_ip
|
||||
|
||||
def get_deficit(self) -> uint8:
|
||||
if self.peak is not None:
|
||||
return self.peak.deficit
|
||||
return self.subslot_end.deficit
|
||||
return self.deficit
|
||||
|
||||
def get_sub_epoch_summary(self) -> Optional[SubEpochSummary]:
|
||||
return self.sub_epoch_summary
|
||||
|
||||
def get_challenge(self, chain: Chain) -> Optional[bytes32]:
|
||||
if self.peak is not None:
|
||||
if self.first_sub_slot_no_peak:
|
||||
if chain == Chain.CHALLENGE_CHAIN:
|
||||
return self.constants.FIRST_CC_CHALLENGE
|
||||
elif chain == Chain.REWARD_CHAIN:
|
||||
return self.constants.FIRST_RC_CHALLENGE
|
||||
elif chain == Chain.INFUSED_CHALLENGE_CHAIN:
|
||||
return None
|
||||
elif self.peak is not None:
|
||||
sub_block = self.peak.reward_chain_sub_block
|
||||
if chain == Chain.CHALLENGE_CHAIN:
|
||||
return sub_block.challenge_chain_ip_vdf.challenge_hash
|
||||
if chain == Chain.REWARD_CHAIN:
|
||||
elif chain == Chain.REWARD_CHAIN:
|
||||
return sub_block.get_hash()
|
||||
if chain == Chain.INFUSED_CHALLENGE_CHAIN:
|
||||
elif chain == Chain.INFUSED_CHALLENGE_CHAIN:
|
||||
if sub_block.infused_challenge_chain_ip_vdf is not None:
|
||||
return sub_block.infused_challenge_chain_ip_vdf.challenge_hash
|
||||
if self.peak.deficit == 4:
|
||||
elif self.peak.deficit == 4:
|
||||
return ChallengeBlockInfo(
|
||||
sub_block.proof_of_space,
|
||||
sub_block.challenge_chain_sp_vdf,
|
||||
|
@ -171,19 +166,20 @@ class LastState:
|
|||
sub_block.challenge_chain_ip_vdf,
|
||||
).get_hash()
|
||||
return None
|
||||
if self.subslot_end is not None:
|
||||
elif self.subslot_end is not None:
|
||||
if chain == Chain.CHALLENGE_CHAIN:
|
||||
return self.subslot_end.eos_bundle.challenge_chain.get_hash()
|
||||
if chain == Chain.REWARD_CHAIN:
|
||||
return self.subslot_end.eos_bundle.reward_chain.get_hash()
|
||||
if chain == Chain.INFUSED_CHALLENGE_CHAIN:
|
||||
if self.subslot_end.deficit < self.constants.MIN_SUB_BLOCKS_PER_CHALLENGE_BLOCK:
|
||||
return self.subslot_end.eos_bundle.infused_challenge_chain.get_hash()
|
||||
else:
|
||||
return None
|
||||
return self.subslot_end.challenge_chain.get_hash()
|
||||
elif chain == Chain.REWARD_CHAIN:
|
||||
return self.subslot_end.reward_chain.get_hash()
|
||||
elif chain == Chain.INFUSED_CHALLENGE_CHAIN:
|
||||
if self.subslot_end.reward_chain.deficit < self.constants.MIN_SUB_BLOCKS_PER_CHALLENGE_BLOCK:
|
||||
return self.subslot_end.infused_challenge_chain.get_hash()
|
||||
return None
|
||||
return None
|
||||
|
||||
def get_initial_form(self, chain: Chain) -> Optional[ClassgroupElement]:
|
||||
if self.first_sub_slot_no_peak:
|
||||
return ClassgroupElement.get_default_element()
|
||||
if self.peak is not None:
|
||||
sub_block = self.peak.reward_chain_sub_block
|
||||
if chain == Chain.CHALLENGE_CHAIN:
|
||||
|
@ -201,7 +197,7 @@ class LastState:
|
|||
if chain == Chain.CHALLENGE_CHAIN or chain == Chain.REWARD_CHAIN:
|
||||
return ClassgroupElement.get_default_element()
|
||||
if chain == Chain.INFUSED_CHALLENGE_CHAIN:
|
||||
if self.subslot_end.deficit < self.constants.MIN_SUB_BLOCKS_PER_CHALLENGE_BLOCK:
|
||||
if self.subslot_end.reward_chain.deficit < self.constants.MIN_SUB_BLOCKS_PER_CHALLENGE_BLOCK:
|
||||
return ClassgroupElement.get_default_element()
|
||||
else:
|
||||
return None
|
||||
|
@ -214,7 +210,6 @@ class Timelord:
|
|||
self.constants = constants
|
||||
self._shut_down = False
|
||||
self.free_clients: List[Tuple[str, asyncio.StreamReader, asyncio.StreamWriter]] = []
|
||||
self.lock: asyncio.Lock = asyncio.Lock()
|
||||
self.potential_free_clients: List = []
|
||||
self.ip_whitelist = self.config["vdf_clients"]["ip"]
|
||||
self.server: Optional[ChiaServer] = None
|
||||
|
@ -231,13 +226,13 @@ class Timelord:
|
|||
# Last peak received, None if it's already processed.
|
||||
self.new_peak: Optional[timelord_protocol.NewPeak] = None
|
||||
# Last end of subslot bundle, None if we built a peak on top of it.
|
||||
self.new_subslot_end: Optional[EndOfSubSlotData] = None
|
||||
self.new_subslot_end: Optional[EndOfSubSlotBundle] = None
|
||||
# Last state received. Can either be a new peak or a new EndOfSubslotBundle.
|
||||
self.last_state: LastState = LastState(self.constants)
|
||||
# Unfinished block info, iters adjusted to the last peak.
|
||||
self.unfinished_blocks: List[timelord_protocol.NewUnfinishedSubBlock] = []
|
||||
# Signage points iters, adjusted to the last peak.
|
||||
self.signage_point_iters: List[uint64] = []
|
||||
self.signage_point_iters: List[Tuple[uint64, uint8]] = []
|
||||
# For each chain, send those info when the process spawns.
|
||||
self.iters_to_submit: Dict[Chain, List[uint64]] = {}
|
||||
self.iters_submitted: Dict[Chain, List[uint64]] = {}
|
||||
|
@ -246,14 +241,13 @@ class Timelord:
|
|||
# List of proofs finished.
|
||||
self.proofs_finished: List[Tuple[Chain, VDFInfo, VDFProof]] = []
|
||||
# Data to send at vdf_client initialization.
|
||||
self.finished_sp = 0
|
||||
self.overflow_blocks: List[timelord_protocol.NewUnfinishedSubBlock] = []
|
||||
self.main_loop = None
|
||||
self.vdf_server = None
|
||||
self._shut_down = False
|
||||
|
||||
async def _start(self):
|
||||
log.info("Starting timelord.")
|
||||
self.lock: asyncio.Lock = asyncio.Lock()
|
||||
self.main_loop = asyncio.create_task(self._manage_chains())
|
||||
|
||||
self.vdf_server = await asyncio.start_server(
|
||||
|
@ -290,6 +284,7 @@ class Timelord:
|
|||
async with self.lock:
|
||||
client_ip = writer.get_extra_info("peername")[0]
|
||||
log.info(f"New timelord connection from client: {client_ip}.")
|
||||
print(client_ip, self.ip_whitelist)
|
||||
if client_ip in self.ip_whitelist:
|
||||
self.free_clients.append((client_ip, reader, writer))
|
||||
log.info(f"Added new VDF client {client_ip}.")
|
||||
|
@ -312,15 +307,17 @@ class Timelord:
|
|||
ip_iters = self.last_state.get_last_ip()
|
||||
sub_slot_iters = self.last_state.get_sub_slot_iters()
|
||||
difficulty = self.last_state.get_difficulty()
|
||||
print(ip_iters, sub_slot_iters, difficulty)
|
||||
for chain in self.chain_type_to_stream.keys():
|
||||
await self._stop_chain(chain)
|
||||
# Adjust all signage points iterations to the peak.
|
||||
iters_per_signage = uint64(sub_slot_iters // self.constants.NUM_SPS_SUB_SLOT)
|
||||
self.signage_point_iters = [
|
||||
k * iters_per_signage - ip_iters
|
||||
for k in range(1, self.constants.NUM_SPS_SUB_SLOT + 1)
|
||||
if k * iters_per_signage - ip_iters > 0 and k * iters_per_signage < sub_slot_iters
|
||||
(k * iters_per_signage - ip_iters, k) for k in range(1, self.constants.NUM_SPS_SUB_SLOT)
|
||||
]
|
||||
for sp, k in self.signage_point_iters:
|
||||
assert k * iters_per_signage > 0
|
||||
assert k * iters_per_signage < sub_slot_iters
|
||||
# Adjust all unfinished blocks iterations to the peak.
|
||||
new_unfinished_blocks = []
|
||||
self.proofs_finished = []
|
||||
|
@ -348,7 +345,7 @@ class Timelord:
|
|||
# Signage points.
|
||||
if len(self.signage_point_iters) > 0:
|
||||
count_signage = 0
|
||||
for signage in self.signage_point_iters:
|
||||
for signage, k in self.signage_point_iters:
|
||||
for chain in [Chain.CHALLENGE_CHAIN, Chain.REWARD_CHAIN]:
|
||||
self.iters_to_submit[chain].append(signage)
|
||||
self.iteration_to_proof_type[signage] = IterationType.SIGNAGE_POINT
|
||||
|
@ -360,6 +357,8 @@ class Timelord:
|
|||
log.info(f"Left subslot iters: {left_subslot_iters}.")
|
||||
for chain in Chain:
|
||||
self.iters_to_submit[chain].append(left_subslot_iters)
|
||||
|
||||
log.warning(f"Iters to submit {self.iters_to_submit}")
|
||||
self.iteration_to_proof_type[left_subslot_iters] = IterationType.END_OF_SUBSLOT
|
||||
|
||||
async def _handle_new_peak(self):
|
||||
|
@ -368,7 +367,6 @@ class Timelord:
|
|||
await self._reset_chains()
|
||||
|
||||
async def _handle_subslot_end(self):
|
||||
self.finished_sp = 0
|
||||
self.last_state.set_state(self.new_subslot_end)
|
||||
self.new_subslot_end = None
|
||||
await self._reset_chains()
|
||||
|
@ -425,7 +423,11 @@ class Timelord:
|
|||
]
|
||||
if len(signage_iters) == 0:
|
||||
return
|
||||
for signage_iter in signage_iters:
|
||||
to_remove = []
|
||||
for potential_sp_iters, signage_point_index in self.signage_point_iters:
|
||||
if potential_sp_iters not in signage_iters:
|
||||
continue
|
||||
signage_iter = potential_sp_iters
|
||||
proofs_with_iter = [
|
||||
(chain, info, proof)
|
||||
for chain, info, proof in self.proofs_finished
|
||||
|
@ -447,8 +449,9 @@ class Timelord:
|
|||
if cc_info is None or cc_proof is None or rc_info is None or rc_proof is None:
|
||||
log.error(f"Insufficient signage point data {signage_iter}")
|
||||
continue
|
||||
|
||||
response = timelord_protocol.NewSignagePointVDF(
|
||||
uint8(self.finished_sp),
|
||||
signage_point_index,
|
||||
cc_info,
|
||||
cc_proof,
|
||||
rc_info,
|
||||
|
@ -458,12 +461,13 @@ class Timelord:
|
|||
msg = Message("new_signage_point_vdf", response)
|
||||
await self.server.send_to_all([msg], NodeType.FULL_NODE)
|
||||
# Cleanup the signage point from memory.
|
||||
self.signage_point_iters.remove(signage_iter)
|
||||
self.finished_sp += 1
|
||||
to_remove.append((signage_iter, signage_point_index))
|
||||
|
||||
print(f"Finished signage point at {signage_point_index}")
|
||||
self.proofs_finished = self._clear_proof_list(signage_iter)
|
||||
# Send the next 3 signage point to the chains.
|
||||
next_iters_count = 0
|
||||
for next_sp in self.signage_point_iters:
|
||||
for next_sp, k in self.signage_point_iters:
|
||||
for chain in [Chain.CHALLENGE_CHAIN, Chain.REWARD_CHAIN]:
|
||||
if next_sp not in self.iters_submitted[chain] and next_sp not in self.iters_to_submit[chain]:
|
||||
self.iters_to_submit[chain].append(next_sp)
|
||||
|
@ -471,6 +475,8 @@ class Timelord:
|
|||
next_iters_count += 1
|
||||
if next_iters_count == 3:
|
||||
break
|
||||
for r in to_remove:
|
||||
self.signage_point_iters.remove(r)
|
||||
|
||||
async def _check_for_new_ip(self):
|
||||
infusion_iters = [
|
||||
|
@ -606,20 +612,15 @@ class Timelord:
|
|||
log.info("Built end of subslot bundle.")
|
||||
self.unfinished_blocks = self.overflow_blocks
|
||||
self.overflow_blocks = []
|
||||
self.new_subslot_end = EndOfSubSlotData(
|
||||
eos_bundle,
|
||||
new_sub_slot_iters,
|
||||
new_difficulty,
|
||||
eos_deficit,
|
||||
)
|
||||
self.new_subslot_end = eos_bundle
|
||||
|
||||
async def _manage_chains(self):
|
||||
async with self.lock:
|
||||
await asyncio.sleep(5)
|
||||
await self._reset_chains()
|
||||
while not self._shut_down:
|
||||
await asyncio.sleep(0.1)
|
||||
# Didn't get any useful data, continue.
|
||||
async with self.lock:
|
||||
if self.last_state.is_empty() and self.new_peak is None:
|
||||
continue
|
||||
# Map free vdf_clients to unspawned chains.
|
||||
await self._map_chains_with_vdf_clients()
|
||||
async with self.lock:
|
||||
|
@ -696,7 +697,7 @@ class Timelord:
|
|||
try:
|
||||
msg = data.decode()
|
||||
except Exception as e:
|
||||
log.error(f"Exception while decoding data {e}")
|
||||
log.warning(f"Exception while decoding data {e}")
|
||||
if msg == "STOP":
|
||||
log.info(f"Stopped client running on ip {ip}.")
|
||||
async with self.lock:
|
||||
|
|
|
@ -69,13 +69,10 @@ async def spawn_process(host, port, counter):
|
|||
|
||||
|
||||
async def spawn_all_processes(config, net_config):
|
||||
await asyncio.sleep(15)
|
||||
await asyncio.sleep(5)
|
||||
port = config["port"]
|
||||
process_count = config["process_count"]
|
||||
awaitables = [
|
||||
spawn_process(net_config["self_hostname"], port, i)
|
||||
for i in range(process_count)
|
||||
]
|
||||
awaitables = [spawn_process(net_config["self_hostname"], port, i) for i in range(process_count)]
|
||||
await asyncio.gather(*awaitables)
|
||||
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ timelord_launcher:
|
|||
# The server where the VDF clients will connect to.
|
||||
port: 8000
|
||||
# Number of VDF client processes to keep alive in the local machine.
|
||||
process_count: 2
|
||||
process_count: 3
|
||||
logging: *logging
|
||||
|
||||
|
||||
|
|
|
@ -384,195 +384,88 @@ class TestFullNodeProtocol:
|
|||
assert msg is not None
|
||||
assert msg.data == fnp.RespondTransaction(spend_bundle)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_respond_transaction_fail(self, two_nodes, wallet_blocks):
|
||||
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
wallet_a, wallet_receiver, blocks = wallet_blocks
|
||||
|
||||
incoming_queue, dummy_node_id = await add_dummy_connection(server_1, 12312)
|
||||
|
||||
tx_id = token_bytes(32)
|
||||
request_transaction = fnp.RequestTransaction(tx_id)
|
||||
msg = await full_node_1.request_transaction(request_transaction)
|
||||
assert msg is None
|
||||
|
||||
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
||||
|
||||
# Invalid transaction does not propagate
|
||||
spend_bundle = wallet_a.generate_signed_transaction(
|
||||
100000000000000,
|
||||
receiver_puzzlehash,
|
||||
blocks[3].get_coinbase(),
|
||||
)
|
||||
while incoming_queue.qsize() > 0:
|
||||
await incoming_queue.get()
|
||||
assert spend_bundle is not None
|
||||
respond_transaction = fnp.RespondTransaction(spend_bundle)
|
||||
msg = await full_node_1.respond_transaction(respond_transaction)
|
||||
assert msg is None
|
||||
await asyncio.sleep(1)
|
||||
assert incoming_queue.qsize() == 0
|
||||
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_new_unfinished(self, two_nodes, wallet_blocks):
|
||||
# full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
# wallet_a, wallet_receiver, blocks = wallet_blocks
|
||||
#
|
||||
# blocks_list = await get_block_path(full_node_1.full_node)
|
||||
#
|
||||
# blocks_new = bt.get_consecutive_blocks(
|
||||
# 1,
|
||||
# block_list_input=blocks_list,
|
||||
# seed=b"another seed 2",
|
||||
# )
|
||||
# block = blocks_new[-1].
|
||||
# assert blocks_new[-1].proof_of_time is not None
|
||||
# assert blocks_new[-2].proof_of_time is not None
|
||||
# already_have = fnp.NewUnfinishedBlock(
|
||||
# blocks_new[-2].prev_header_hash,
|
||||
# blocks_new[-2].proof_of_time.number_of_iterations,
|
||||
# blocks_new[-2].header_hash,
|
||||
# )
|
||||
# res = await full_node_1.new_unfinished_block(already_have)
|
||||
# assert res is None
|
||||
#
|
||||
# bad_prev = fnp.NewUnfinishedBlock(
|
||||
# blocks_new[-1].header_hash,
|
||||
# blocks_new[-1].proof_of_time.number_of_iterations,
|
||||
# blocks_new[-1].header_hash,
|
||||
# )
|
||||
#
|
||||
# res = await full_node_1.new_unfinished_block(bad_prev)
|
||||
# assert res is None
|
||||
# good = fnp.NewUnfinishedBlock(
|
||||
# blocks_new[-1].prev_header_hash,
|
||||
# blocks_new[-1].proof_of_time.number_of_iterations,
|
||||
# blocks_new[-1].header_hash,
|
||||
# )
|
||||
# res = full_node_1.new_unfinished_block(good)
|
||||
# assert res is not None
|
||||
#
|
||||
# unf_block = FullBlock(
|
||||
# blocks_new[-1].proof_of_space,
|
||||
# None,
|
||||
# blocks_new[-1].header,
|
||||
# blocks_new[-1].transactions_generator,
|
||||
# blocks_new[-1].transactions_filter,
|
||||
# )
|
||||
# unf_block_req = fnp.RespondUnfinishedBlock(unf_block)
|
||||
# await full_node_1.respond_unfinished_block(unf_block_req)
|
||||
#
|
||||
# res = await full_node_1.new_unfinished_block(good)
|
||||
# assert res is None
|
||||
|
||||
|
||||
#
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_respond_transaction_fail(self, two_nodes, wallet_blocks):
|
||||
# full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
# wallet_a, wallet_receiver, blocks = wallet_blocks
|
||||
#
|
||||
# tx_id = token_bytes(32)
|
||||
# request_transaction = fnp.RequestTransaction(tx_id)
|
||||
# msg = await full_node_1.request_transaction(request_transaction)
|
||||
# assert msg is not None
|
||||
# assert msg.data == fnp.RejectTransactionRequest(tx_id)
|
||||
#
|
||||
# receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
||||
#
|
||||
# # Invalid transaction does not propagate
|
||||
# spend_bundle = wallet_a.generate_signed_transaction(
|
||||
# 100000000000000,
|
||||
# receiver_puzzlehash,
|
||||
# blocks[3].get_coinbase(),
|
||||
# )
|
||||
# assert spend_bundle is not None
|
||||
# respond_transaction = fnp.RespondTransaction(spend_bundle)
|
||||
# msg = await full_node_1.respond_transaction(respond_transaction)
|
||||
# assert msg is None
|
||||
#
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_new_pot(self, two_nodes, wallet_blocks):
|
||||
# full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
# wallet_a, wallet_receiver, _ = wallet_blocks
|
||||
#
|
||||
# no_unf_block = fnp.NewProofOfTime(uint32(5), bytes(32 * [1]), uint64(124512), uint8(2))
|
||||
# msg = await full_node_1.new_proof_of_time(no_unf_block)
|
||||
# assert msg is None
|
||||
#
|
||||
# blocks = await get_block_path(full_node_1.full_node)
|
||||
#
|
||||
# blocks_new = bt.get_consecutive_blocks(
|
||||
# 1,
|
||||
# blocks[:-1],
|
||||
# 10,
|
||||
# seed=b"1212412",
|
||||
# )
|
||||
#
|
||||
# unf_block = FullBlock(
|
||||
# blocks_new[-1].proof_of_space,
|
||||
# None,
|
||||
# blocks_new[-1].header,
|
||||
# blocks_new[-1].transactions_generator,
|
||||
# blocks_new[-1].transactions_filter,
|
||||
# )
|
||||
# unf_block_req = fnp.RespondUnfinishedBlock(unf_block)
|
||||
# await full_node_1.respond_unfinished_block(unf_block_req)
|
||||
#
|
||||
# dont_have = fnp.NewProofOfTime(
|
||||
# unf_block.height,
|
||||
# unf_block.proof_of_space.challenge,
|
||||
# res[0].message.data.iterations_needed,
|
||||
# uint8(2),
|
||||
# )
|
||||
# msg = await full_node_1.new_proof_of_time(dont_have)
|
||||
# assert msg is not None
|
||||
# await full_node_1.respond_sub_block(fnp.RespondSubBlock(blocks_new[-1]))
|
||||
# assert blocks_new[-1].proof_of_time is not None
|
||||
# already_have = fnp.NewProofOfTime(
|
||||
# unf_block.height,
|
||||
# unf_block.proof_of_space.challenge,
|
||||
# res[0].message.data.iterations_needed,
|
||||
# blocks_new[-1].proof_of_time.witness_type,
|
||||
# )
|
||||
# msg = await full_node_1.new_proof_of_time(already_have)
|
||||
# assert msg is None
|
||||
#
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_request_pot(self, two_nodes, wallet_blocks):
|
||||
# full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
# wallet_a, wallet_receiver, blocks = wallet_blocks
|
||||
#
|
||||
# request = fnp.RequestProofOfTime(
|
||||
# blocks[3].height,
|
||||
# blocks[3].proof_of_space.challenge,
|
||||
# blocks[3].proof_of_time.number_of_iterations,
|
||||
# blocks[3].proof_of_time.witness_type,
|
||||
# )
|
||||
# res = await full_node_1.request_proof_of_time(request)
|
||||
# assert res.data.proof == blocks[3].proof_of_time
|
||||
#
|
||||
# request_bad = fnp.RequestProofOfTime(
|
||||
# blocks[3].height,
|
||||
# blocks[3].proof_of_space.challenge,
|
||||
# blocks[3].proof_of_time.number_of_iterations + 1,
|
||||
# blocks[3].proof_of_time.witness_type,
|
||||
# )
|
||||
# res_bad = await full_node_1.request_proof_of_time(request_bad)
|
||||
# assert isinstance(res_bad.data, fnp.RejectProofOfTimeRequest)
|
||||
#
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_respond_pot(self, two_nodes, wallet_blocks):
|
||||
# full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
# wallet_a, wallet_receiver, blocks = wallet_blocks
|
||||
#
|
||||
# blocks_list = await get_block_path(full_node_1.full_node)
|
||||
#
|
||||
# blocks_new = bt.get_consecutive_blocks(
|
||||
# 1,
|
||||
# blocks_list,
|
||||
# 10,
|
||||
# seed=b"another seed",
|
||||
# )
|
||||
# assert blocks_new[-1].proof_of_time is not None
|
||||
# new_pot = fnp.NewProofOfTime(
|
||||
# blocks_new[-1].height,
|
||||
# blocks_new[-1].proof_of_space.challenge,
|
||||
# blocks_new[-1].proof_of_time.number_of_iterations,
|
||||
# blocks_new[-1].proof_of_time.witness_type,
|
||||
# )
|
||||
# await full_node_1.new_proof_of_time(new_pot)
|
||||
#
|
||||
# # Don't have unfinished block
|
||||
# respond_pot = fnp.RespondProofOfTime(blocks_new[-1].proof_of_time)
|
||||
# res = await full_node_1.respond_proof_of_time(respond_pot)
|
||||
# assert res is None
|
||||
#
|
||||
# unf_block = FullBlock(
|
||||
# blocks_new[-1].proof_of_space,
|
||||
# None,
|
||||
# blocks_new[-1].header,
|
||||
# blocks_new[-1].transactions_generator,
|
||||
# blocks_new[-1].transactions_filter,
|
||||
# )
|
||||
# unf_block_req = fnp.RespondUnfinishedBlock(unf_block)
|
||||
# await full_node_1.respond_unfinished_block(unf_block_req)
|
||||
# # Have unfinished block, finish
|
||||
# assert blocks_new[-1].proof_of_time is not None
|
||||
# respond_pot = fnp.RespondProofOfTime(blocks_new[-1].proof_of_time)
|
||||
# res = await full_node_1.respond_proof_of_time(respond_pot)
|
||||
# # TODO Test this assert len(res) == 4
|
||||
#
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_new_unfinished(self, two_nodes, wallet_blocks):
|
||||
# full_node_1, full_node_2, server_1, server_2 = two_nodes
|
||||
# wallet_a, wallet_receiver, blocks = wallet_blocks
|
||||
#
|
||||
# blocks_list = await get_block_path(full_node_1.full_node)
|
||||
#
|
||||
# blocks_new = bt.get_consecutive_blocks(
|
||||
# 1,
|
||||
# blocks_list,
|
||||
# 10,
|
||||
# seed=b"another seed 2",
|
||||
# )
|
||||
# assert blocks_new[-1].proof_of_time is not None
|
||||
# assert blocks_new[-2].proof_of_time is not None
|
||||
# already_have = fnp.NewUnfinishedBlock(
|
||||
# blocks_new[-2].prev_header_hash,
|
||||
# blocks_new[-2].proof_of_time.number_of_iterations,
|
||||
# blocks_new[-2].header_hash,
|
||||
# )
|
||||
# res = await full_node_1.new_unfinished_block(already_have)
|
||||
# assert res is None
|
||||
#
|
||||
# bad_prev = fnp.NewUnfinishedBlock(
|
||||
# blocks_new[-1].header_hash,
|
||||
# blocks_new[-1].proof_of_time.number_of_iterations,
|
||||
# blocks_new[-1].header_hash,
|
||||
# )
|
||||
#
|
||||
# res = await full_node_1.new_unfinished_block(bad_prev)
|
||||
# assert res is None
|
||||
# good = fnp.NewUnfinishedBlock(
|
||||
# blocks_new[-1].prev_header_hash,
|
||||
# blocks_new[-1].proof_of_time.number_of_iterations,
|
||||
# blocks_new[-1].header_hash,
|
||||
# )
|
||||
# res = full_node_1.new_unfinished_block(good)
|
||||
# assert res is not None
|
||||
#
|
||||
# unf_block = FullBlock(
|
||||
# blocks_new[-1].proof_of_space,
|
||||
# None,
|
||||
# blocks_new[-1].header,
|
||||
# blocks_new[-1].transactions_generator,
|
||||
# blocks_new[-1].transactions_filter,
|
||||
# )
|
||||
# unf_block_req = fnp.RespondUnfinishedBlock(unf_block)
|
||||
# await full_node_1.respond_unfinished_block(unf_block_req)
|
||||
#
|
||||
# res = await full_node_1.new_unfinished_block(good)
|
||||
# assert res is None
|
||||
#
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_request_unfinished(self, two_nodes, wallet_blocks):
|
||||
|
|
Loading…
Reference in New Issue