async def test_basic_store(self, empty_blockchain, normalized_to_identity: bool = False): blockchain = empty_blockchain blocks = bt.get_consecutive_blocks( 10, seed=b"1234", normalized_to_identity_cc_eos=normalized_to_identity, normalized_to_identity_icc_eos=normalized_to_identity, normalized_to_identity_cc_ip=normalized_to_identity, normalized_to_identity_cc_sp=normalized_to_identity, ) store = FullNodeStore(test_constants) unfinished_blocks = [] for block in blocks: unfinished_blocks.append( UnfinishedBlock( block.finished_sub_slots, block.reward_chain_block.get_unfinished(), block.challenge_chain_sp_proof, block.reward_chain_sp_proof, block.foliage, block.foliage_transaction_block, block.transactions_info, block.transactions_generator, [], )) # Add/get candidate block assert store.get_candidate_block( unfinished_blocks[0].get_hash()) is None for height, unf_block in enumerate(unfinished_blocks): store.add_candidate_block(unf_block.get_hash(), uint32(height), unf_block) candidate = store.get_candidate_block(unfinished_blocks[4].get_hash()) assert candidate is not None assert candidate[1] == unfinished_blocks[4] store.clear_candidate_blocks_below(uint32(8)) assert store.get_candidate_block( unfinished_blocks[5].get_hash()) is None assert store.get_candidate_block( unfinished_blocks[8].get_hash()) is not None # Test seen unfinished blocks h_hash_1 = bytes32(token_bytes(32)) assert not store.seen_unfinished_block(h_hash_1) assert store.seen_unfinished_block(h_hash_1) store.clear_seen_unfinished_blocks() assert not store.seen_unfinished_block(h_hash_1) # Add/get unfinished block for height, unf_block in enumerate(unfinished_blocks): assert store.get_unfinished_block(unf_block.partial_hash) is None store.add_unfinished_block( uint32(height), unf_block, PreValidationResult(None, uint64(123532), None, False)) assert store.get_unfinished_block( unf_block.partial_hash) == unf_block store.remove_unfinished_block(unf_block.partial_hash) assert store.get_unfinished_block(unf_block.partial_hash) is None blocks = bt.get_consecutive_blocks( 1, skip_slots=5, normalized_to_identity_cc_ip=normalized_to_identity, normalized_to_identity_cc_sp=normalized_to_identity, normalized_to_identity_cc_eos=normalized_to_identity, normalized_to_identity_icc_eos=normalized_to_identity, ) sub_slots = blocks[0].finished_sub_slots assert len(sub_slots) == 5 assert (store.get_finished_sub_slots( BlockCache({}), None, sub_slots[0].challenge_chain.challenge_chain_end_of_slot_vdf. challenge, ) == []) # Test adding non-connecting sub-slots genesis assert store.get_sub_slot(test_constants.GENESIS_CHALLENGE) is None assert store.get_sub_slot( sub_slots[0].challenge_chain.get_hash()) is None assert store.get_sub_slot( sub_slots[1].challenge_chain.get_hash()) is None assert store.new_finished_sub_slot(sub_slots[1], blockchain, None, None) is None assert store.new_finished_sub_slot(sub_slots[2], blockchain, None, None) is None # Test adding sub-slots after genesis assert store.new_finished_sub_slot(sub_slots[0], blockchain, None, None) is not None sub_slot = store.get_sub_slot(sub_slots[0].challenge_chain.get_hash()) assert sub_slot is not None assert sub_slot[0] == sub_slots[0] assert store.get_sub_slot( sub_slots[1].challenge_chain.get_hash()) is None assert store.new_finished_sub_slot(sub_slots[1], blockchain, None, None) is not None for i in range(len(sub_slots)): assert store.new_finished_sub_slot(sub_slots[i], blockchain, None, None) is not None slot_i = store.get_sub_slot( sub_slots[i].challenge_chain.get_hash()) assert slot_i is not None assert slot_i[0] == sub_slots[i] assert store.get_finished_sub_slots( BlockCache({}), None, sub_slots[-1].challenge_chain.get_hash()) == sub_slots assert store.get_finished_sub_slots(BlockCache( {}), None, std_hash(b"not a valid hash")) is None assert (store.get_finished_sub_slots( BlockCache({}), None, sub_slots[-2].challenge_chain.get_hash()) == sub_slots[:-1]) # Test adding genesis peak await _validate_and_add_block(blockchain, blocks[0]) peak = blockchain.get_peak() peak_full_block = await blockchain.get_full_peak() if peak.overflow: store.new_peak(peak, peak_full_block, sub_slots[-2], sub_slots[-1], None, blockchain) else: store.new_peak(peak, peak_full_block, None, sub_slots[-1], None, blockchain) assert store.get_sub_slot( sub_slots[0].challenge_chain.get_hash()) is None assert store.get_sub_slot( sub_slots[1].challenge_chain.get_hash()) is None assert store.get_sub_slot( sub_slots[2].challenge_chain.get_hash()) is None if peak.overflow: slot_3 = store.get_sub_slot( sub_slots[3].challenge_chain.get_hash()) assert slot_3 is not None assert slot_3[0] == sub_slots[3] else: assert store.get_sub_slot( sub_slots[3].challenge_chain.get_hash()) is None slot_4 = store.get_sub_slot(sub_slots[4].challenge_chain.get_hash()) assert slot_4 is not None assert slot_4[0] == sub_slots[4] assert (store.get_finished_sub_slots( blockchain, peak, sub_slots[-1].challenge_chain.get_hash(), ) == []) # Test adding non genesis peak directly blocks = bt.get_consecutive_blocks( 2, skip_slots=2, normalized_to_identity_cc_eos=normalized_to_identity, normalized_to_identity_icc_eos=normalized_to_identity, normalized_to_identity_cc_ip=normalized_to_identity, normalized_to_identity_cc_sp=normalized_to_identity, ) blocks = bt.get_consecutive_blocks( 3, block_list_input=blocks, normalized_to_identity_cc_eos=normalized_to_identity, normalized_to_identity_icc_eos=normalized_to_identity, normalized_to_identity_cc_ip=normalized_to_identity, normalized_to_identity_cc_sp=normalized_to_identity, ) for block in blocks: await _validate_and_add_block_no_error(blockchain, block) sb = blockchain.block_record(block.header_hash) sp_sub_slot, ip_sub_slot = await blockchain.get_sp_and_ip_sub_slots( block.header_hash) res = store.new_peak(sb, block, sp_sub_slot, ip_sub_slot, None, blockchain) assert res.added_eos is None # Add reorg blocks blocks_reorg = bt.get_consecutive_blocks( 20, normalized_to_identity_cc_eos=normalized_to_identity, normalized_to_identity_icc_eos=normalized_to_identity, normalized_to_identity_cc_ip=normalized_to_identity, normalized_to_identity_cc_sp=normalized_to_identity, ) for block in blocks_reorg: peak = blockchain.get_peak() assert peak is not None await _validate_and_add_block_no_error(blockchain, block) if blockchain.get_peak().header_hash == block.header_hash: sb = blockchain.block_record(block.header_hash) fork = find_fork_point_in_chain( blockchain, peak, blockchain.block_record(sb.header_hash)) if fork > 0: fork_block = blockchain.height_to_block_record(fork) else: fork_block = None sp_sub_slot, ip_sub_slot = await blockchain.get_sp_and_ip_sub_slots( block.header_hash) res = store.new_peak(sb, block, sp_sub_slot, ip_sub_slot, fork_block, blockchain) assert res.added_eos is None # Add slots to the end blocks_2 = bt.get_consecutive_blocks( 1, block_list_input=blocks_reorg, skip_slots=2, normalized_to_identity_cc_eos=normalized_to_identity, normalized_to_identity_icc_eos=normalized_to_identity, normalized_to_identity_cc_ip=normalized_to_identity, normalized_to_identity_cc_sp=normalized_to_identity, ) for slot in blocks_2[-1].finished_sub_slots: store.new_finished_sub_slot(slot, blockchain, blockchain.get_peak(), await blockchain.get_full_peak()) assert store.get_sub_slot( sub_slots[3].challenge_chain.get_hash()) is None assert store.get_sub_slot( sub_slots[4].challenge_chain.get_hash()) is None # Test adding signage point peak = blockchain.get_peak() ss_start_iters = peak.ip_sub_slot_total_iters(test_constants) for i in range( 1, test_constants.NUM_SPS_SUB_SLOT - test_constants.NUM_SP_INTERVALS_EXTRA): sp = get_signage_point( test_constants, blockchain, peak, ss_start_iters, uint8(i), [], peak.sub_slot_iters, ) assert store.new_signage_point(uint8(i), blockchain, peak, peak.sub_slot_iters, sp) blocks = blocks_reorg while True: blocks = bt.get_consecutive_blocks( 1, block_list_input=blocks, normalized_to_identity_cc_eos=normalized_to_identity, normalized_to_identity_icc_eos=normalized_to_identity, normalized_to_identity_cc_ip=normalized_to_identity, normalized_to_identity_cc_sp=normalized_to_identity, ) await _validate_and_add_block(blockchain, blocks[-1]) if blockchain.get_peak().header_hash == blocks[-1].header_hash: sb = blockchain.block_record(blocks[-1].header_hash) fork = find_fork_point_in_chain( blockchain, peak, blockchain.block_record(sb.header_hash)) if fork > 0: fork_block = blockchain.height_to_block_record(fork) else: fork_block = None sp_sub_slot, ip_sub_slot = await blockchain.get_sp_and_ip_sub_slots( blocks[-1].header_hash) res = store.new_peak(sb, blocks[-1], sp_sub_slot, ip_sub_slot, fork_block, blockchain) assert res.added_eos is None if sb.overflow and sp_sub_slot is not None: assert sp_sub_slot != ip_sub_slot break peak = blockchain.get_peak() assert peak.overflow # Overflow peak should result in 2 finished sub slots assert len(store.finished_sub_slots) == 2 # Add slots to the end, except for the last one, which we will use to test invalid SP blocks_2 = bt.get_consecutive_blocks( 1, block_list_input=blocks, skip_slots=3, normalized_to_identity_cc_eos=normalized_to_identity, normalized_to_identity_icc_eos=normalized_to_identity, normalized_to_identity_cc_ip=normalized_to_identity, normalized_to_identity_cc_sp=normalized_to_identity, ) for slot in blocks_2[-1].finished_sub_slots[:-1]: store.new_finished_sub_slot(slot, blockchain, blockchain.get_peak(), await blockchain.get_full_peak()) finished_sub_slots = blocks_2[-1].finished_sub_slots assert len(store.finished_sub_slots) == 4 # Test adding signage points for overflow blocks (sp_sub_slot) ss_start_iters = peak.sp_sub_slot_total_iters(test_constants) # for i in range(peak.signage_point_index, test_constants.NUM_SPS_SUB_SLOT): # if i < peak.signage_point_index: # continue # latest = peak # while latest.total_iters > peak.sp_total_iters(test_constants): # latest = blockchain.blocks[latest.prev_hash] # sp = get_signage_point( # test_constants, # blockchain.blocks, # latest, # ss_start_iters, # uint8(i), # [], # peak.sub_slot_iters, # ) # assert store.new_signage_point(i, blockchain.blocks, peak, peak.sub_slot_iters, sp) # Test adding signage points for overflow blocks (ip_sub_slot) for i in range( 1, test_constants.NUM_SPS_SUB_SLOT - test_constants.NUM_SP_INTERVALS_EXTRA): sp = get_signage_point( test_constants, blockchain, peak, peak.ip_sub_slot_total_iters(test_constants), uint8(i), [], peak.sub_slot_iters, ) assert store.new_signage_point(uint8(i), blockchain, peak, peak.sub_slot_iters, sp) # Test adding future signage point, a few slots forward (good) saved_sp_hash = None for slot_offset in range(1, len(finished_sub_slots)): for i in range( 1, test_constants.NUM_SPS_SUB_SLOT - test_constants.NUM_SP_INTERVALS_EXTRA, ): sp = get_signage_point( test_constants, blockchain, peak, peak.ip_sub_slot_total_iters(test_constants) + slot_offset * peak.sub_slot_iters, uint8(i), finished_sub_slots[:slot_offset], peak.sub_slot_iters, ) assert sp.cc_vdf is not None saved_sp_hash = sp.cc_vdf.output.get_hash() assert store.new_signage_point(uint8(i), blockchain, peak, peak.sub_slot_iters, sp) # Test adding future signage point (bad) for i in range( 1, test_constants.NUM_SPS_SUB_SLOT - test_constants.NUM_SP_INTERVALS_EXTRA): sp = get_signage_point( test_constants, blockchain, peak, peak.ip_sub_slot_total_iters(test_constants) + len(finished_sub_slots) * peak.sub_slot_iters, uint8(i), finished_sub_slots[:len(finished_sub_slots)], peak.sub_slot_iters, ) assert not store.new_signage_point(uint8(i), blockchain, peak, peak.sub_slot_iters, sp) # Test adding past signage point sp = SignagePoint( blocks[1].reward_chain_block.challenge_chain_sp_vdf, blocks[1].challenge_chain_sp_proof, blocks[1].reward_chain_block.reward_chain_sp_vdf, blocks[1].reward_chain_sp_proof, ) assert not store.new_signage_point( blocks[1].reward_chain_block.signage_point_index, blockchain, peak, blockchain.block_record( blocks[1].header_hash).sp_sub_slot_total_iters(test_constants), sp, ) # Get signage point by index assert (store.get_signage_point_by_index( finished_sub_slots[0].challenge_chain.get_hash(), uint8(4), finished_sub_slots[0].reward_chain.get_hash(), ) is not None) assert (store.get_signage_point_by_index( finished_sub_slots[0].challenge_chain.get_hash(), uint8(4), std_hash(b"1")) is None) # Get signage point by hash # TODO: address hint error and remove ignore # error: Argument 1 to "get_signage_point" of "FullNodeStore" has incompatible type "Optional[bytes32]"; # expected "bytes32" [arg-type] assert store.get_signage_point( saved_sp_hash) is not None # type: ignore[arg-type] assert store.get_signage_point(std_hash(b"2")) is None # Test adding signage points before genesis store.initialize_genesis_sub_slot() assert len(store.finished_sub_slots) == 1 for i in range( 1, test_constants.NUM_SPS_SUB_SLOT - test_constants.NUM_SP_INTERVALS_EXTRA): sp = get_signage_point( test_constants, BlockCache({}, {}), None, uint128(0), uint8(i), [], peak.sub_slot_iters, ) assert store.new_signage_point(uint8(i), blockchain, None, peak.sub_slot_iters, sp) blocks_3 = bt.get_consecutive_blocks( 1, skip_slots=2, normalized_to_identity_cc_eos=normalized_to_identity, normalized_to_identity_icc_eos=normalized_to_identity, normalized_to_identity_cc_ip=normalized_to_identity, normalized_to_identity_cc_sp=normalized_to_identity, ) for slot in blocks_3[-1].finished_sub_slots: store.new_finished_sub_slot(slot, blockchain, None, None) assert len(store.finished_sub_slots) == 3 finished_sub_slots = blocks_3[-1].finished_sub_slots for slot_offset in range(1, len(finished_sub_slots) + 1): for i in range( 1, test_constants.NUM_SPS_SUB_SLOT - test_constants.NUM_SP_INTERVALS_EXTRA, ): sp = get_signage_point( test_constants, BlockCache({}, {}), None, slot_offset * peak.sub_slot_iters, uint8(i), finished_sub_slots[:slot_offset], peak.sub_slot_iters, ) assert store.new_signage_point(uint8(i), blockchain, None, peak.sub_slot_iters, sp) # Test adding signage points after genesis blocks_4 = bt.get_consecutive_blocks( 1, normalized_to_identity_cc_eos=normalized_to_identity, normalized_to_identity_icc_eos=normalized_to_identity, normalized_to_identity_cc_ip=normalized_to_identity, normalized_to_identity_cc_sp=normalized_to_identity, ) blocks_5 = bt.get_consecutive_blocks( 1, block_list_input=blocks_4, skip_slots=1, normalized_to_identity_cc_eos=normalized_to_identity, normalized_to_identity_icc_eos=normalized_to_identity, normalized_to_identity_cc_ip=normalized_to_identity, normalized_to_identity_cc_sp=normalized_to_identity, ) # If this is not the case, fix test to find a block that is assert (blocks_4[-1].reward_chain_block.signage_point_index < test_constants.NUM_SPS_SUB_SLOT - test_constants.NUM_SP_INTERVALS_EXTRA) await _validate_and_add_block( blockchain, blocks_4[-1], expected_result=ReceiveBlockResult.ADDED_AS_ORPHAN) sb = blockchain.block_record(blocks_4[-1].header_hash) store.new_peak(sb, blocks_4[-1], None, None, None, blockchain) for i in range( sb.signage_point_index + test_constants.NUM_SP_INTERVALS_EXTRA, test_constants.NUM_SPS_SUB_SLOT, ): if is_overflow_block(test_constants, uint8(i)): finished_sub_slots = blocks_5[-1].finished_sub_slots else: finished_sub_slots = [] sp = get_signage_point( test_constants, blockchain, sb, uint128(0), uint8(i), finished_sub_slots, peak.sub_slot_iters, ) assert store.new_signage_point(uint8(i), empty_blockchain, sb, peak.sub_slot_iters, sp) # Test future EOS cache store.initialize_genesis_sub_slot() blocks = bt.get_consecutive_blocks( 1, normalized_to_identity_cc_eos=normalized_to_identity, normalized_to_identity_icc_eos=normalized_to_identity, normalized_to_identity_cc_ip=normalized_to_identity, normalized_to_identity_cc_sp=normalized_to_identity, ) await _validate_and_add_block_no_error(blockchain, blocks[-1]) while True: blocks = bt.get_consecutive_blocks( 1, block_list_input=blocks, normalized_to_identity_cc_eos=normalized_to_identity, normalized_to_identity_icc_eos=normalized_to_identity, normalized_to_identity_cc_ip=normalized_to_identity, normalized_to_identity_cc_sp=normalized_to_identity, ) await _validate_and_add_block_no_error(blockchain, blocks[-1]) sb = blockchain.block_record(blocks[-1].header_hash) if sb.first_in_sub_slot: break assert len(blocks) >= 2 dependant_sub_slots = blocks[-1].finished_sub_slots peak = blockchain.get_peak() peak_full_block = await blockchain.get_full_peak() for block in blocks[:-2]: sb = blockchain.block_record(block.header_hash) sp_sub_slot, ip_sub_slot = await blockchain.get_sp_and_ip_sub_slots( block.header_hash) peak = sb peak_full_block = block res = store.new_peak(sb, block, sp_sub_slot, ip_sub_slot, None, blockchain) assert res.added_eos is None assert store.new_finished_sub_slot(dependant_sub_slots[0], blockchain, peak, peak_full_block) is None block = blocks[-2] sb = blockchain.block_record(block.header_hash) sp_sub_slot, ip_sub_slot = await blockchain.get_sp_and_ip_sub_slots( block.header_hash) res = store.new_peak(sb, block, sp_sub_slot, ip_sub_slot, None, blockchain) assert res.added_eos == dependant_sub_slots[0] assert res.new_signage_points == res.new_infusion_points == [] # Test future IP cache store.initialize_genesis_sub_slot() blocks = bt.get_consecutive_blocks( 60, normalized_to_identity_cc_ip=normalized_to_identity, normalized_to_identity_cc_sp=normalized_to_identity, normalized_to_identity_cc_eos=normalized_to_identity, normalized_to_identity_icc_eos=normalized_to_identity, ) for block in blocks[:5]: await _validate_and_add_block_no_error(blockchain, block) sb = blockchain.block_record(block.header_hash) sp_sub_slot, ip_sub_slot = await blockchain.get_sp_and_ip_sub_slots( block.header_hash) res = store.new_peak(sb, block, sp_sub_slot, ip_sub_slot, None, blockchain) assert res.added_eos is None case_0, case_1 = False, False for i in range(5, len(blocks) - 1): prev_block = blocks[i] block = blocks[i + 1] new_ip = NewInfusionPointVDF( block.reward_chain_block.get_unfinished().get_hash(), block.reward_chain_block.challenge_chain_ip_vdf, block.challenge_chain_ip_proof, block.reward_chain_block.reward_chain_ip_vdf, block.reward_chain_ip_proof, block.reward_chain_block.infused_challenge_chain_ip_vdf, block.infused_challenge_chain_ip_proof, ) store.add_to_future_ip(new_ip) await _validate_and_add_block_no_error(blockchain, prev_block) sp_sub_slot, ip_sub_slot = await blockchain.get_sp_and_ip_sub_slots( prev_block.header_hash) sb = blockchain.block_record(prev_block.header_hash) res = store.new_peak(sb, prev_block, sp_sub_slot, ip_sub_slot, None, blockchain) if len(block.finished_sub_slots) == 0: case_0 = True assert res.new_infusion_points == [new_ip] else: case_1 = True assert res.new_infusion_points == [] found_ips: List[timelord_protocol.NewInfusionPointVDF] = [] for ss in block.finished_sub_slots: ipvdf = store.new_finished_sub_slot( ss, blockchain, sb, prev_block) assert ipvdf is not None found_ips += ipvdf assert found_ips == [new_ip] # If flaky, increase the number of blocks created assert case_0 and case_1 # Try to get two blocks in the same slot, such that we have # SP, B2 SP .... SP B1 # i2 ......... i1 # Then do a reorg up to B2, removing all signage points after B2, but not before log.warning(f"Adding blocks up to {blocks[-1]}") for block in blocks: await _validate_and_add_block_no_error(blockchain, block) log.warning(f"Starting loop") while True: log.warning("Looping") blocks = bt.get_consecutive_blocks(1, block_list_input=blocks, skip_slots=1) await _validate_and_add_block_no_error(blockchain, blocks[-1]) peak = blockchain.get_peak() sub_slots = await blockchain.get_sp_and_ip_sub_slots( peak.header_hash) store.new_peak(peak, blocks[-1], sub_slots[0], sub_slots[1], None, blockchain) blocks = bt.get_consecutive_blocks( 2, block_list_input=blocks, guarantee_transaction_block=True) i3 = blocks[-3].reward_chain_block.signage_point_index i2 = blocks[-2].reward_chain_block.signage_point_index i1 = blocks[-1].reward_chain_block.signage_point_index if (len(blocks[-2].finished_sub_slots) == len( blocks[-1].finished_sub_slots) == 0 and not is_overflow_block(test_constants, signage_point_index=i2) and not is_overflow_block(test_constants, signage_point_index=i1) and i2 > i3 + 3 and i1 > (i2 + 3)): # We hit all the conditions that we want all_sps: List[Optional[SignagePoint]] = [ None ] * test_constants.NUM_SPS_SUB_SLOT def assert_sp_none(sp_index: int, is_none: bool): sp_to_check: Optional[SignagePoint] = all_sps[sp_index] assert sp_to_check is not None assert sp_to_check.cc_vdf is not None fetched = store.get_signage_point( sp_to_check.cc_vdf.output.get_hash()) assert (fetched is None) == is_none if fetched is not None: assert fetched == sp_to_check for i in range(i3 + 1, test_constants.NUM_SPS_SUB_SLOT - 3): finished_sub_slots = [] sp = get_signage_point( test_constants, blockchain, peak, uint128(peak.ip_sub_slot_total_iters(bt.constants)), uint8(i), finished_sub_slots, peak.sub_slot_iters, ) all_sps[i] = sp assert store.new_signage_point(uint8(i), blockchain, peak, peak.sub_slot_iters, sp) # Adding a new peak clears all SPs after that peak await _validate_and_add_block_no_error(blockchain, blocks[-2]) peak = blockchain.get_peak() sub_slots = await blockchain.get_sp_and_ip_sub_slots( peak.header_hash) store.new_peak(peak, blocks[-2], sub_slots[0], sub_slots[1], None, blockchain) assert_sp_none(i2, False) assert_sp_none(i2 + 1, False) assert_sp_none(i1, True) assert_sp_none(i1 + 1, True) assert_sp_none(i1 + 4, True) for i in range(i2, test_constants.NUM_SPS_SUB_SLOT): if is_overflow_block(test_constants, uint8(i)): blocks_alt = bt.get_consecutive_blocks( 1, block_list_input=blocks[:-1], skip_slots=1) finished_sub_slots = blocks_alt[-1].finished_sub_slots else: finished_sub_slots = [] sp = get_signage_point( test_constants, blockchain, peak, uint128(peak.ip_sub_slot_total_iters(bt.constants)), uint8(i), finished_sub_slots, peak.sub_slot_iters, ) all_sps[i] = sp assert store.new_signage_point(uint8(i), blockchain, peak, peak.sub_slot_iters, sp) assert_sp_none(i2, False) assert_sp_none(i2 + 1, False) assert_sp_none(i1, False) assert_sp_none(i1 + 1, False) assert_sp_none(i1 + 4, False) await _validate_and_add_block_no_error(blockchain, blocks[-1]) peak = blockchain.get_peak() sub_slots = await blockchain.get_sp_and_ip_sub_slots( peak.header_hash) # Do a reorg, which should remove everything after B2 store.new_peak( peak, blocks[-1], sub_slots[0], sub_slots[1], (await blockchain.get_block_records_at([blocks[-2].height]))[0], blockchain, ) assert_sp_none(i2, False) assert_sp_none(i2 + 1, False) assert_sp_none(i1, True) assert_sp_none(i1 + 1, True) assert_sp_none(i1 + 4, True) break else: for block in blocks[-2:]: await _validate_and_add_block_no_error(blockchain, block)
async def test_signage_points(self, two_nodes, empty_blockchain): test_rpc_port = uint16(21522) nodes, _ = two_nodes full_node_api_1, full_node_api_2 = nodes server_1 = full_node_api_1.full_node.server server_2 = full_node_api_2.full_node.server peer = await connect_and_get_peer(server_1, server_2) def stop_node_cb(): full_node_api_1._close() server_1.close_all() full_node_rpc_api = FullNodeRpcApi(full_node_api_1.full_node) config = bt.config hostname = config["self_hostname"] daemon_port = config["daemon_port"] rpc_cleanup = await start_rpc_server( full_node_rpc_api, hostname, daemon_port, test_rpc_port, stop_node_cb, bt.root_path, config, connect_to_daemon=False, ) try: client = await FullNodeRpcClient.create(self_hostname, test_rpc_port, bt.root_path, config) # Only provide one res = await client.get_recent_signage_point_or_eos(None, None) assert res is None res = await client.get_recent_signage_point_or_eos(std_hash(b"0"), std_hash(b"1")) assert res is None # Not found res = await client.get_recent_signage_point_or_eos(std_hash(b"0"), None) assert res is None res = await client.get_recent_signage_point_or_eos(None, std_hash(b"0")) assert res is None blocks = bt.get_consecutive_blocks(5) for block in blocks: await full_node_api_1.full_node.respond_block(full_node_protocol.RespondBlock(block)) blocks = bt.get_consecutive_blocks(1, block_list_input=blocks, skip_slots=1, force_overflow=True) blockchain = full_node_api_1.full_node.blockchain second_blockchain = empty_blockchain for block in blocks: await second_blockchain.receive_block(block) # Creates a signage point based on the last block peak_2 = second_blockchain.get_peak() sp: SignagePoint = get_signage_point( test_constants, blockchain, peak_2, peak_2.ip_sub_slot_total_iters(test_constants), uint8(4), [], peak_2.sub_slot_iters, ) # Don't have SP yet res = await client.get_recent_signage_point_or_eos(sp.cc_vdf.output.get_hash(), None) assert res is None # Add the last block await full_node_api_1.full_node.respond_block(full_node_protocol.RespondBlock(blocks[-1])) await full_node_api_1.respond_signage_point( full_node_protocol.RespondSignagePoint(uint8(4), sp.cc_vdf, sp.cc_proof, sp.rc_vdf, sp.rc_proof), peer ) assert full_node_api_1.full_node.full_node_store.get_signage_point(sp.cc_vdf.output.get_hash()) is not None # Properly fetch a signage point res = await client.get_recent_signage_point_or_eos(sp.cc_vdf.output.get_hash(), None) assert res is not None assert "eos" not in res assert res["signage_point"] == sp assert not res["reverted"] blocks = bt.get_consecutive_blocks(1, block_list_input=blocks, skip_slots=1) selected_eos = blocks[-1].finished_sub_slots[0] # Don't have EOS yet res = await client.get_recent_signage_point_or_eos(None, selected_eos.challenge_chain.get_hash()) assert res is None # Properly fetch an EOS for eos in blocks[-1].finished_sub_slots: await full_node_api_1.full_node.respond_end_of_sub_slot( full_node_protocol.RespondEndOfSubSlot(eos), peer ) res = await client.get_recent_signage_point_or_eos(None, selected_eos.challenge_chain.get_hash()) assert res is not None assert "signage_point" not in res assert res["eos"] == selected_eos assert not res["reverted"] # Do another one but without sending the slot await full_node_api_1.full_node.respond_block(full_node_protocol.RespondBlock(blocks[-1])) blocks = bt.get_consecutive_blocks(1, block_list_input=blocks, skip_slots=1) selected_eos = blocks[-1].finished_sub_slots[-1] await full_node_api_1.full_node.respond_block(full_node_protocol.RespondBlock(blocks[-1])) res = await client.get_recent_signage_point_or_eos(None, selected_eos.challenge_chain.get_hash()) assert res is not None assert "signage_point" not in res assert res["eos"] == selected_eos assert not res["reverted"] # Perform a reorg blocks = bt.get_consecutive_blocks(12, seed=b"1234") for block in blocks: await full_node_api_1.full_node.respond_block(full_node_protocol.RespondBlock(block)) # Signage point is no longer in the blockchain res = await client.get_recent_signage_point_or_eos(sp.cc_vdf.output.get_hash(), None) assert res["reverted"] assert res["signage_point"] == sp assert "eos" not in res # EOS is no longer in the blockchain res = await client.get_recent_signage_point_or_eos(None, selected_eos.challenge_chain.get_hash()) assert res is not None assert "signage_point" not in res assert res["eos"] == selected_eos assert res["reverted"] finally: # Checks that the RPC manages to stop the node client.close() await client.await_closed() await rpc_cleanup()