mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2024-09-21 08:31:52 +03:00
Fix some serious timelord issues
This commit is contained in:
parent
5df0c275d4
commit
6d4e32d93c
@ -7,17 +7,17 @@ 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 ** 27,
|
||||
"SUB_SLOT_ITERS_STARTING": 2 ** 25,
|
||||
# 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 ** 15,
|
||||
"DIFFICULTY_STARTING": 2 ** 14,
|
||||
"DIFFICULTY_FACTOR": 3, # The next difficulty is truncated to range [prev / FACTOR, prev * FACTOR]
|
||||
# These 3 constants must be changed at the same time
|
||||
"SUB_EPOCH_SUB_BLOCKS": 128, # The number of sub-blocks per sub-epoch, mainnet 284
|
||||
"EPOCH_SUB_BLOCKS": 4096, # The number of sub-blocks per epoch, mainnet 32256
|
||||
"SIGNIFICANT_BITS": 12, # The number of bits to look at in difficulty and min iters. The rest are zeroed
|
||||
"DISCRIMINANT_SIZE_BITS": 1024, # Max is 1024 (based on ClassGroupElement int size)
|
||||
"NUMBER_ZERO_BITS_PLOT_FILTER": 9, # H(plot signature of the challenge) must start with these many zeroes
|
||||
"NUMBER_ZERO_BITS_PLOT_FILTER": 7, # H(plot signature of the challenge) must start with these many zeroes
|
||||
"SUB_SLOT_TIME_TARGET": 600, # The target number of seconds per slot
|
||||
"NUM_SP_INTERVALS_EXTRA": 3, # The number of sp intervals to add to the signage point
|
||||
"MAX_FUTURE_TIME": 7200, # The next block can have a timestamp of at most these many seconds more
|
||||
|
@ -600,7 +600,7 @@ class FullNodeAPI:
|
||||
prev_sb = self.full_node.blockchain.sub_blocks.get(prev_sb.prev_hash, None)
|
||||
attempts += 1
|
||||
if not found:
|
||||
self.log.error("Did not find a previous block with the correct reward chain hash")
|
||||
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
|
||||
@ -716,18 +716,18 @@ class FullNodeAPI:
|
||||
self.log.warning(f"Previous block is None, infusion point {request.reward_chain_ip_vdf.challenge}")
|
||||
return
|
||||
|
||||
# We should also find the prev block from the signage point, in the path. If not found, that means
|
||||
# it was based on a reorged block.
|
||||
curr = prev_sb
|
||||
attempts = 0
|
||||
while curr is not None and curr.header_hash != unfinished_block.prev_header_hash and attempts < 10:
|
||||
curr = self.full_node.blockchain.sub_blocks.get(curr.prev_hash, None)
|
||||
attempts += 1
|
||||
if attempts == 10 or (
|
||||
curr is None and unfinished_block.prev_header_hash != self.full_node.constants.GENESIS_PREV_HASH
|
||||
):
|
||||
self.log.error("Have IP VDF that does not match SP VDF")
|
||||
return
|
||||
# # We should also find the prev block from the signage point, in the path. If not found, that means
|
||||
# # it was based on a reorged block.
|
||||
# curr = prev_sb
|
||||
# attempts = 0
|
||||
# while curr is not None and curr.header_hash != unfinished_block.prev_header_hash and attempts < 10:
|
||||
# curr = self.full_node.blockchain.sub_blocks.get(curr.prev_hash, None)
|
||||
# attempts += 1
|
||||
# if attempts == 10 or (
|
||||
# curr is None and unfinished_block.prev_header_hash != self.full_node.constants.GENESIS_PREV_HASH
|
||||
# ):
|
||||
# self.log.error("Have IP VDF that does not match SP VDF")
|
||||
# return
|
||||
|
||||
sub_slot_iters, difficulty = get_sub_slot_iters_and_difficulty(
|
||||
self.full_node.constants,
|
||||
@ -785,7 +785,7 @@ class FullNodeAPI:
|
||||
try:
|
||||
await self.respond_sub_block(full_node_protocol.RespondSubBlock(block))
|
||||
except ConsensusError as e:
|
||||
self.log.warning("Consensus error validating sub-block: {e}")
|
||||
self.log.warning(f"Consensus error validating sub-block: {e}")
|
||||
|
||||
@peer_required
|
||||
@api_request
|
||||
|
@ -134,7 +134,7 @@ class LastState:
|
||||
self.sub_slot_iters = state.challenge_chain.new_sub_slot_iters
|
||||
|
||||
self.reward_challenge_cache.append((self.get_challenge(Chain.REWARD_CHAIN), self.total_iters))
|
||||
log.warning(f"Updated peak to {self.peak.reward_chain_sub_block.get_hash()}")
|
||||
log.info(f"Updated timelord peak to {self.get_challenge(Chain.REWARD_CHAIN)}, total iters: {self.total_iters}")
|
||||
while len(self.reward_challenge_cache) > 2 * self.constants.MAX_SUB_SLOT_SUB_BLOCKS:
|
||||
self.reward_challenge_cache.pop(0)
|
||||
|
||||
@ -315,14 +315,53 @@ class Timelord:
|
||||
self.allows_iters.remove(chain)
|
||||
self.unspawned_chains.append(chain)
|
||||
|
||||
def _can_infuse_unfinished_block(self, block: timelord_protocol.NewUnfinishedSubBlock) -> Optional[uint64]:
|
||||
sub_slot_iters = self.last_state.get_sub_slot_iters()
|
||||
difficulty = self.last_state.get_difficulty()
|
||||
ip_iters = self.last_state.get_last_ip()
|
||||
rc_block = block.reward_chain_sub_block
|
||||
block_sp_iters, block_ip_iters = iters_from_sub_block(
|
||||
self.constants,
|
||||
rc_block,
|
||||
sub_slot_iters,
|
||||
difficulty,
|
||||
)
|
||||
block_sp_total_iters = self.last_state.total_iters - ip_iters + block_sp_iters
|
||||
found_index = -1
|
||||
for index, (rc, total_iters) in enumerate(self.last_state.reward_challenge_cache):
|
||||
if rc == block.rc_prev:
|
||||
found_index = index
|
||||
break
|
||||
if found_index == -1:
|
||||
log.warning(f"Will not infuse {block.rc_prev} because it's reward chain challenge is not in the chain")
|
||||
return None
|
||||
|
||||
new_block_iters = block_ip_iters - ip_iters
|
||||
if len(self.last_state.reward_challenge_cache) > found_index + 1:
|
||||
if self.last_state.reward_challenge_cache[found_index + 1][1] < block_sp_total_iters:
|
||||
log.warning(
|
||||
f"Will not infuse unfinished block {block.rc_prev} total iters {block_sp_total_iters}, "
|
||||
f"because there is another infusion before it's SP"
|
||||
)
|
||||
return None
|
||||
if self.last_state.reward_challenge_cache[found_index][1] > block_sp_total_iters:
|
||||
log.error(
|
||||
f"Will not infuse unfinished block {block.rc_prev}, total iters: {block_sp_total_iters}, "
|
||||
f"because it's iters are too low"
|
||||
)
|
||||
return None
|
||||
|
||||
if new_block_iters > 0:
|
||||
return new_block_iters
|
||||
|
||||
async def _reset_chains(self):
|
||||
# First, stop all chains.
|
||||
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 = [
|
||||
@ -341,30 +380,8 @@ class Timelord:
|
||||
self.iters_submitted[chain] = []
|
||||
self.iteration_to_proof_type = {}
|
||||
for block in self.unfinished_blocks:
|
||||
found_index = -1
|
||||
for index, (rc, total_iters) in enumerate(self.last_state.reward_challenge_cache):
|
||||
if rc == block.rc_prev:
|
||||
found_index = index
|
||||
break
|
||||
if found_index == -1:
|
||||
log.error(f"INVALID unfinished block will not infuse it {block.rc_prev}")
|
||||
continue
|
||||
|
||||
rc_block = block.reward_chain_sub_block
|
||||
block_sp_iters, block_ip_iters = iters_from_sub_block(
|
||||
self.constants,
|
||||
rc_block,
|
||||
sub_slot_iters,
|
||||
difficulty,
|
||||
)
|
||||
block_sp_total_iters = self.last_state.total_iters - ip_iters + block_sp_iters
|
||||
if len(self.last_state.reward_challenge_cache) > found_index + 1:
|
||||
if self.last_state.reward_challenge_cache[found_index + 1][1] < block_sp_total_iters:
|
||||
log.error(f"INVALID2 unfinished block will not infuse it {block.rc_prev}")
|
||||
continue
|
||||
|
||||
new_block_iters = block_ip_iters - ip_iters
|
||||
if new_block_iters > 0:
|
||||
new_block_iters: Optional[uint64] = self._can_infuse_unfinished_block(block)
|
||||
if new_block_iters:
|
||||
new_unfinished_blocks.append(block)
|
||||
for chain in Chain:
|
||||
self.iters_to_submit[chain].append(new_block_iters)
|
||||
@ -514,6 +531,8 @@ class Timelord:
|
||||
next_iters_count += 1
|
||||
if next_iters_count == 3:
|
||||
break
|
||||
|
||||
# Break so we alternate between checking SP and IP
|
||||
break
|
||||
for r in to_remove:
|
||||
self.signage_point_iters.remove(r)
|
||||
@ -646,6 +665,7 @@ class Timelord:
|
||||
self.last_state.reward_challenge_cache,
|
||||
)
|
||||
await self._handle_new_peak()
|
||||
# Break so we alternate between checking SP and IP
|
||||
break
|
||||
|
||||
async def _check_for_end_of_subslot(self):
|
||||
|
@ -1,4 +1,4 @@
|
||||
from typing import Callable
|
||||
from typing import Callable, Optional
|
||||
import logging
|
||||
from src.protocols import timelord_protocol
|
||||
from src.timelord import Timelord, iters_from_sub_block, Chain, IterationType
|
||||
@ -44,7 +44,9 @@ class TimelordAPI:
|
||||
if sp_iters > ip_iters:
|
||||
self.timelord.overflow_blocks.append(new_unfinished_subblock)
|
||||
elif ip_iters > last_ip_iters:
|
||||
self.timelord.unfinished_blocks.append(new_unfinished_subblock)
|
||||
for chain in Chain:
|
||||
self.timelord.iters_to_submit[chain].append(uint64(ip_iters - last_ip_iters))
|
||||
self.timelord.iteration_to_proof_type[ip_iters - last_ip_iters] = IterationType.INFUSION_POINT
|
||||
new_block_iters: Optional[uint64] = self.timelord._can_infuse_unfinished_block(new_unfinished_subblock)
|
||||
if new_block_iters:
|
||||
self.timelord.unfinished_blocks.append(new_unfinished_subblock)
|
||||
for chain in Chain:
|
||||
self.timelord.iters_to_submit[chain].append(new_block_iters)
|
||||
self.timelord.iteration_to_proof_type[new_block_iters] = IterationType.INFUSION_POINT
|
||||
|
Loading…
Reference in New Issue
Block a user