async def new_peak(self, new_peak: Optional[BlockRecord]) -> List[Tuple[SpendBundle, CostResult, bytes32]]: """ Called when a new peak is available, we try to recreate a mempool for the new tip. """ if new_peak is None: return [] if self.peak == new_peak: return [] if new_peak.height <= self.constants.INITIAL_FREEZE_PERIOD: return [] self.peak = new_peak old_pool = self.mempool self.mempool = Mempool.create(self.mempool_size) for item in old_pool.spends.values(): await self.add_spendbundle(item.spend_bundle, item.cost_result, item.spend_bundle_name, False) potential_txs_copy = self.potential_txs.copy() self.potential_txs = {} txs_added = [] for tx, cached_result, cached_name in potential_txs_copy.values(): cost, status, error = await self.add_spendbundle(tx, cached_result, cached_name) if status == MempoolInclusionStatus.SUCCESS: txs_added.append((tx, cached_result, cached_name)) log.debug( f"Size of mempool: {len(self.mempool.spends)}, minimum fee to get in: {self.mempool.get_min_fee_rate()}" ) return txs_added
def __init__(self, coin_store: CoinStore, consensus_constants: ConsensusConstants): self.constants: ConsensusConstants = consensus_constants self.constants_json = recurse_jsonify( dataclasses.asdict(self.constants)) # Transactions that were unable to enter mempool, used for retry. (they were invalid) self.potential_txs: Dict[bytes32, Tuple[SpendBundle, CostResult, bytes32]] = {} # Keep track of seen spend_bundles self.seen_bundle_hashes: Dict[bytes32, bytes32] = {} self.coin_store = coin_store tx_per_sec = self.constants.TX_PER_SEC sec_per_block = self.constants.SUB_SLOT_TIME_TARGET // self.constants.SLOT_BLOCKS_TARGET block_buffer_count = self.constants.MEMPOOL_BLOCK_BUFFER # MEMPOOL_SIZE = 60000 self.mempool_size = int(tx_per_sec * sec_per_block * block_buffer_count) self.potential_cache_size = 300 self.seen_cache_size = 10000 self.pool = ProcessPoolExecutor(max_workers=1) # The mempool will correspond to a certain peak self.peak: Optional[BlockRecord] = None self.mempool: Mempool = Mempool.create(self.mempool_size)
async def new_peak(self, new_peak: Optional[BlockRecord]): """ Called when a new peak is available, we try to recreate a mempool for the new tip. """ if new_peak is None: return if self.peak == new_peak: return if new_peak.height <= self.constants.INITIAL_FREEZE_PERIOD: return self.peak = new_peak old_pool = self.mempool self.mempool = Mempool.create(self.mempool_size) for item in old_pool.spends.values(): await self.add_spendbundle(item.spend_bundle, item.cost_result, item.spend_bundle_name, False) potential_txs_copy = self.potential_txs.copy() self.potential_txs = {} for tx, cached_result, cached_name in potential_txs_copy.values(): await self.add_spendbundle(tx, cached_result, cached_name) log.debug( f"Size of mempool: {len(self.mempool.spends)}, minimum fee to get in: {self.mempool.get_min_fee_rate()}" )
def __init__(self, coin_store: CoinStore, consensus_constants: ConsensusConstants): self.constants: ConsensusConstants = consensus_constants # Transactions that were unable to enter mempool, used for retry. (they were invalid) self.potential_txs: Dict[bytes32, Tuple[SpendBundle, CostResult]] = {} # Keep track of seen spend_bundles self.seen_bundle_hashes: Dict[bytes32, bytes32] = {} # old_mempools will contain transactions that were removed in the last 10 blocks self.old_mempools: SortedDict[uint32, Dict[bytes32, MempoolItem]] = SortedDict() # pylint: disable=E1136 self.coin_store = coin_store tx_per_sec = self.constants.TX_PER_SEC sec_per_block = self.constants.SUB_SLOT_TIME_TARGET // self.constants.SLOT_SUB_BLOCKS_TARGET block_buffer_count = self.constants.MEMPOOL_BLOCK_BUFFER # MEMPOOL_SIZE = 60000 self.mempool_size = int(tx_per_sec * sec_per_block * block_buffer_count) self.potential_cache_size = 300 self.seen_cache_size = 10000 # The mempool will correspond to a certain peak self.peak: Optional[SubBlockRecord] = None self.mempool: Mempool = Mempool.create(self.mempool_size)
async def new_tips(self, new_tips: List[FullBlock]): """ Called when new tips are available, we try to recreate a mempool for each of the new tips. For tip that we already have mempool we don't do anything. """ new_pools: Dict[bytes32, Mempool] = {} min_mempool_height = sys.maxsize for pool in self.mempools.values(): if pool.header.height < min_mempool_height: min_mempool_height = pool.header.height for tip in new_tips: if tip.header_hash in self.mempools: # Nothing to change, we already have mempool for this head new_pools[tip.header_hash] = self.mempools[tip.header_hash] continue new_pool = Mempool.create(tip.header, self.mempool_size) if tip.height < min_mempool_height: # Update old mempool if len(self.old_mempools) > 0: log.info(f"Creating new pool: {new_pool.header}") # If old spends height is bigger than the new tip height, try adding spends to the pool for height in self.old_mempools.keys(): old_spend_dict: Dict[bytes32, MempoolItem] = self.old_mempools[ height ] await self.add_old_spends_to_pool(new_pool, old_spend_dict) await self.initialize_pool_from_current_pools(new_pool) await self.add_potential_spends_to_pool(new_pool) new_pools[new_pool.header.header_hash] = new_pool for pool in self.mempools.values(): if pool.header.header_hash not in new_pools: await self.add_to_old_mempool_cache( list(pool.spends.values()), pool.header ) self.mempools = new_pools
async def new_peak(self, new_peak: Optional[SubBlockRecord]): """ Called when a new peak is available, we try to recreate a mempool for the new tip. """ if new_peak is None: return if self.peak == new_peak: return self.peak = new_peak old_pool = self.mempool self.mempool = Mempool.create(self.mempool_size) for item in old_pool.spends.values(): await self.add_spendbundle(item.spend_bundle, item.cost_result) self.potential_txs_copy = self.potential_txs.copy() self.potential_txs = {} for tx, cached_result in self.potential_txs_copy.values(): await self.add_spendbundle(tx, cached_result)