async def test_weight_proof_extend_multiple_ses(self, default_1000_blocks): blocks = default_1000_blocks header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate( blocks) last_ses_height = sorted(summaries.keys())[-1] last_ses = summaries[last_ses_height] before_last_ses_height = sorted(summaries.keys())[-2] before_last_ses = summaries[before_last_ses_height] wpf = WeightProofHandler( test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, summaries)) wpf_verify = WeightProofHandler( test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, {})) for x in range(10, -1, -1): wp = await wpf.get_proof_of_weight(blocks[before_last_ses_height - x].header_hash) assert wp is not None valid, fork_point, _ = await wpf_verify.validate_weight_proof(wp) assert valid assert fork_point == 0 # extend proof with 100 blocks summaries[last_ses_height] = last_ses summaries[before_last_ses_height] = before_last_ses wpf = WeightProofHandler( test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, summaries)) new_wp = await wpf._create_proof_of_weight(blocks[-1].header_hash) valid, fork_point, _ = await wpf.validate_weight_proof(new_wp) assert valid assert fork_point != 0
async def test_weight_proof_from_database(self): connection = await aiosqlite.connect("path to db") block_store: BlockStore = await BlockStore.create(connection) blocks, peak = await block_store.get_block_records() peak_height = blocks[peak].height headers = await block_store.get_header_blocks_in_range(0, peak_height) sub_height_to_hash = {} sub_epoch_summaries = {} # peak_header = await block_store.get_full_blocks_at([peak_height]) if len(blocks) == 0: return None, None assert peak is not None # Sets the other state variables (peak_height and height_to_hash) curr: BlockRecord = blocks[peak] while True: sub_height_to_hash[curr.height] = curr.header_hash if curr.sub_epoch_summary_included is not None: sub_epoch_summaries[ curr.height] = curr.sub_epoch_summary_included if curr.height == 0: break curr = blocks[curr.prev_hash] assert len(sub_height_to_hash) == peak_height + 1 block_cache = BlockCache(blocks, headers, sub_height_to_hash, sub_epoch_summaries) wpf = WeightProofHandler(DEFAULT_CONSTANTS, block_cache) wp = await wpf._create_proof_of_weight(sub_height_to_hash[peak_height - 50]) valid, fork_point = wpf.validate_weight_proof_single_proc(wp) await connection.close() assert valid print(f"size of proof is {get_size(wp)}")
async def test_weight_proof_extend_no_ses(self, default_1000_blocks): blocks = default_1000_blocks header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate( blocks) last_ses_height = sorted(summaries.keys())[-1] wpf_synced = WeightProofHandler( test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, summaries)) wp = await wpf_synced.get_proof_of_weight( blocks[last_ses_height].header_hash) assert wp is not None # todo for each sampled sub epoch, validate number of segments wpf_not_synced = WeightProofHandler( test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, {})) valid, fork_point, _ = await wpf_not_synced.validate_weight_proof(wp) assert valid assert fork_point == 0 # extend proof with 100 blocks new_wp = await wpf_synced._create_proof_of_weight( blocks[-1].header_hash) valid, fork_point, _ = await wpf_not_synced.validate_weight_proof( new_wp) assert valid assert fork_point == 0
async def test_weight_proof10000__blocks_compact(self, default_10000_blocks_compact): blocks = default_10000_blocks_compact header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate(blocks) wpf = WeightProofHandler(test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, summaries)) wp = await wpf.get_proof_of_weight(blocks[-1].header_hash) assert wp is not None wpf = WeightProofHandler(test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, {})) valid, fork_point = wpf.validate_weight_proof_single_proc(wp) assert valid assert fork_point == 0
async def test_weight_proof_from_genesis(self, default_400_blocks): blocks = default_400_blocks header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate(blocks) wpf = WeightProofHandler(test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, summaries)) wp = await wpf.get_proof_of_weight(blocks[-1].header_hash) assert wp is not None wp = await wpf.get_proof_of_weight(blocks[-1].header_hash) assert wp is not None
async def test_weight_proof_bad_peak_hash(self, default_1000_blocks): blocks = default_1000_blocks header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate( blocks) wpf = WeightProofHandler( test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, summaries)) wp = await wpf.get_proof_of_weight(b"sadgfhjhgdgsfadfgh") assert wp is None
async def test_weight_proof1000_partial_blocks_compact(self, default_10000_blocks_compact): blocks: List[FullBlock] = bt.get_consecutive_blocks( 100, block_list_input=default_10000_blocks_compact, seed=b"asdfghjkl", normalized_to_identity_cc_ip=True, normalized_to_identity_cc_eos=True, normalized_to_identity_icc_eos=True, ) header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate(blocks) wpf = WeightProofHandler(test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, summaries)) wp = await wpf.get_proof_of_weight(blocks[-1].header_hash) assert wp is not None wpf = WeightProofHandler(test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, {})) valid, fork_point = wpf.validate_weight_proof_single_proc(wp) assert valid assert fork_point == 0
async def test_check_num_of_samples(self, default_10000_blocks): blocks = default_10000_blocks header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate(blocks) wpf = WeightProofHandler(test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, summaries)) wp = await wpf.get_proof_of_weight(blocks[-1].header_hash) curr = -1 samples = 0 for sub_epoch_segment in wp.sub_epoch_segments: if sub_epoch_segment.sub_epoch_n > curr: curr = sub_epoch_segment.sub_epoch_n samples += 1 assert samples <= wpf.MAX_SAMPLES
async def test_weight_proof_summaries_1000_blocks(self, default_1000_blocks): blocks = default_1000_blocks header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate(blocks) wpf = WeightProofHandler(test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, summaries)) wp = await wpf.get_proof_of_weight(blocks[-1].header_hash) summaries, sub_epoch_data_weight, _ = _map_sub_epoch_summaries( wpf.constants.SUB_EPOCH_BLOCKS, wpf.constants.GENESIS_CHALLENGE, wp.sub_epochs, wpf.constants.DIFFICULTY_STARTING, ) assert _validate_summaries_weight(test_constants, sub_epoch_data_weight, summaries, wp)
async def test_weight_proof_extend_new_ses(self, default_1000_blocks): blocks = default_1000_blocks header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate(blocks) # delete last summary last_ses_height = sorted(summaries.keys())[-1] last_ses = summaries[last_ses_height] del summaries[last_ses_height] wpf_synced = WeightProofHandler(test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, summaries)) wp = await wpf_synced.get_proof_of_weight(blocks[last_ses_height - 10].header_hash) assert wp is not None wpf_not_synced = WeightProofHandler(test_constants, BlockCache(sub_blocks, height_to_hash, header_cache, {})) valid, fork_point = await wpf_not_synced.validate_weight_proof(wp) assert valid assert fork_point == 0 # extend proof with 100 blocks wpf = WeightProofHandler(test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, summaries)) summaries[last_ses_height] = last_ses wpf_synced.blockchain = BlockCache(sub_blocks, header_cache, height_to_hash, summaries) new_wp = await wpf_synced._create_proof_of_weight(blocks[-1].header_hash) valid, fork_point = await wpf_not_synced.validate_weight_proof(new_wp) assert valid assert fork_point == 0 wpf_synced.blockchain = BlockCache(sub_blocks, header_cache, height_to_hash, summaries) new_wp = await wpf_synced._create_proof_of_weight(blocks[last_ses_height].header_hash) valid, fork_point = await wpf_not_synced.validate_weight_proof(new_wp) assert valid assert fork_point == 0 valid, fork_point = await wpf.validate_weight_proof(new_wp) assert valid assert fork_point != 0
async def _test_map_summaries(blocks, header_cache, height_to_hash, sub_blocks, summaries): curr = sub_blocks[blocks[-1].header_hash] orig_summaries: Dict[int, SubEpochSummary] = {} while curr.height > 0: if curr.sub_epoch_summary_included is not None: orig_summaries[curr.height] = curr.sub_epoch_summary_included # next sub block curr = sub_blocks[curr.prev_hash] wpf = WeightProofHandler(test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, summaries)) wp = await wpf.get_proof_of_weight(blocks[-1].header_hash) assert wp is not None # sub epoch summaries validate hashes summaries, sub_epoch_data_weight, _ = _map_sub_epoch_summaries( test_constants.SUB_EPOCH_BLOCKS, test_constants.GENESIS_CHALLENGE, wp.sub_epochs, test_constants.DIFFICULTY_STARTING, ) assert len(summaries) == len(orig_summaries)
async def create( private_key: PrivateKey, config: Dict, db_path: Path, constants: ConsensusConstants, server: ChiaServer, name: str = None, ): self = WalletStateManager() self.new_wallet = False self.config = config self.constants = constants self.server = server if name: self.log = logging.getLogger(name) else: self.log = logging.getLogger(__name__) self.lock = asyncio.Lock() self.log.debug(f"Starting in db path: {db_path}") self.db_connection = await aiosqlite.connect(db_path) self.db_wrapper = DBWrapper(self.db_connection) self.coin_store = await WalletCoinStore.create(self.db_wrapper) self.tx_store = await WalletTransactionStore.create(self.db_wrapper) self.puzzle_store = await WalletPuzzleStore.create(self.db_wrapper) self.user_store = await WalletUserStore.create(self.db_wrapper) self.action_store = await WalletActionStore.create(self.db_wrapper) self.basic_store = await KeyValStore.create(self.db_wrapper) self.trade_manager = await TradeManager.create(self, self.db_wrapper) self.user_settings = await UserSettings.create(self.basic_store) self.block_store = await WalletBlockStore.create(self.db_wrapper) self.blockchain = await WalletBlockchain.create( self.block_store, self.constants, self.coins_of_interest_received, self.reorg_rollback, ) self.weight_proof_handler = WeightProofHandler(self.constants, self.blockchain) self.sync_mode = False self.sync_store = await WalletSyncStore.create() self.state_changed_callback = None self.pending_tx_callback = None self.db_path = db_path main_wallet_info = await self.user_store.get_wallet_by_id(1) assert main_wallet_info is not None self.private_key = private_key self.main_wallet = await Wallet.create(self, main_wallet_info) self.wallets = {main_wallet_info.id: self.main_wallet} wallet = None for wallet_info in await self.get_all_wallet_info_entries(): # self.log.info(f"wallet_info {wallet_info}") if wallet_info.type == WalletType.STANDARD_WALLET: if wallet_info.id == 1: continue wallet = await Wallet.create(config, wallet_info) elif wallet_info.type == WalletType.COLOURED_COIN: wallet = await CCWallet.create( self, self.main_wallet, wallet_info, ) elif wallet_info.type == WalletType.RATE_LIMITED: wallet = await RLWallet.create(self, wallet_info) elif wallet_info.type == WalletType.DISTRIBUTED_ID: wallet = await DIDWallet.create( self, self.main_wallet, wallet_info, ) if wallet is not None: self.wallets[wallet_info.id] = wallet async with self.puzzle_store.lock: index = await self.puzzle_store.get_last_derivation_path() if index is None or index < self.config[ "initial_num_public_keys"] - 1: await self.create_more_puzzle_hashes(from_zero=True) return self
async def test_weight_proof_edge_cases(self, default_400_blocks): blocks: List[FullBlock] = default_400_blocks blocks: List[FullBlock] = bt.get_consecutive_blocks( 1, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, skip_slots=2) blocks: List[FullBlock] = bt.get_consecutive_blocks( 1, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, skip_slots=1) blocks: List[FullBlock] = bt.get_consecutive_blocks( 1, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, ) blocks: List[FullBlock] = bt.get_consecutive_blocks( 1, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, skip_slots=2) blocks: List[FullBlock] = bt.get_consecutive_blocks( 1, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, ) blocks: List[FullBlock] = bt.get_consecutive_blocks( 1, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, ) blocks: List[FullBlock] = bt.get_consecutive_blocks( 1, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, ) blocks: List[FullBlock] = bt.get_consecutive_blocks( 1, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, ) blocks: List[FullBlock] = bt.get_consecutive_blocks( 1, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, skip_slots=4, normalized_to_identity_cc_eos=True, ) blocks: List[FullBlock] = bt.get_consecutive_blocks( 10, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, ) blocks: List[FullBlock] = bt.get_consecutive_blocks( 1, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, skip_slots=4, normalized_to_identity_icc_eos=True, ) blocks: List[FullBlock] = bt.get_consecutive_blocks( 10, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, ) blocks: List[FullBlock] = bt.get_consecutive_blocks( 1, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, skip_slots=4, normalized_to_identity_cc_ip=True, ) blocks: List[FullBlock] = bt.get_consecutive_blocks( 10, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, ) blocks: List[FullBlock] = bt.get_consecutive_blocks( 1, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, skip_slots=4, normalized_to_identity_cc_sp=True, ) blocks: List[FullBlock] = bt.get_consecutive_blocks( 1, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, skip_slots=4) blocks: List[FullBlock] = bt.get_consecutive_blocks( 10, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=True, ) blocks: List[FullBlock] = bt.get_consecutive_blocks( 300, block_list_input=blocks, seed=b"asdfghjkl", force_overflow=False, ) header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate( blocks) wpf = WeightProofHandler( test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, summaries)) wp = await wpf.get_proof_of_weight(blocks[-1].header_hash) assert wp is not None wpf = WeightProofHandler( test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, {})) valid, fork_point = wpf.validate_weight_proof_single_proc(wp) assert valid assert fork_point == 0