async def process_blocks(wallet, ledger_api, last_known_header, current_header_hash): r = await ledger_api.hash_preimage(hash=current_header_hash) header = Header.from_bytes(r) body = Body.from_bytes(await ledger_api.hash_preimage(hash=header.body_hash)) if header.previous_hash != last_known_header: await process_blocks(wallet, ledger_api, last_known_header, header.previous_hash) print(f'processing block {HeaderHash(header)}') additions = list(additions_for_body(body)) removals = removals_for_body(body) removals = [ Coin.from_bytes(await ledger_api.hash_preimage(hash=x)) for x in removals ] wallet.notify(additions, removals) clawback_coins = [coin for coin in additions if wallet.is_in_escrow(coin)] if len(clawback_coins) != 0: print(f'WARNING! Coins from this wallet have been moved to escrow!\n' f'Attempting to send a clawback for these coins:') for coin in clawback_coins: print(f'Coin ID: {coin.name()}, Amount: {coin.amount}') transaction = wallet.generate_clawback_transaction(clawback_coins) r = await ledger_api.push_tx(tx=transaction) if type(r) is RemoteError: print('Clawback failed') else: print('Clawback transaction submitted')
def farm_new_block(previous_header: HeaderHash, previous_signature: Signature, block_index: int, proof_of_space: ProofOfSpace, spend_bundle: SpendBundle, coinbase_coin: Coin, coinbase_signature: BLSSignature, fees_puzzle_hash: ProgramHash, timestamp: uint64): """ Steps: - collect up a consistent set of removals and solutions - run solutions to get the additions - select a timestamp = max(now, minimum_legal_timestamp) - create blank extension data - collect up coinbase coin with coinbase signature (if solo mining, we get these locally) - return Header, Body """ program_cost = 0 assert validate_spend_bundle_signature(spend_bundle) solution_program = best_solution_program(spend_bundle) extension_data = std_hash(b'') block_index_hash = block_index.to_bytes(32, "big") fees_coin = Coin(block_index_hash, fees_puzzle_hash, spend_bundle.fees()) body = Body(coinbase_signature, coinbase_coin, fees_coin, solution_program, program_cost, spend_bundle.aggregated_signature) header = Header(previous_header, previous_signature, timestamp, proof_of_space, body, extension_data) return header, body
async def get_coin_age(coin, ledger_api, header_hash): r = await ledger_api.get_tip() if r['genesis_hash'] == header_hash: return float('-inf') r = await ledger_api.hash_preimage(hash=header_hash) header = Header.from_bytes(r) body = Body.from_bytes(await ledger_api.hash_preimage(hash=header.body_hash)) additions = list(additions_for_body(body)) if coin in additions: return 0 return 1 + await get_coin_age(coin, ledger_api, header.previous_hash)
async def process_blocks(wallet, ledger_api, last_known_header, current_header_hash): r = await ledger_api.hash_preimage(hash=current_header_hash) header = Header.from_bytes(r) body = Body.from_bytes(await ledger_api.hash_preimage(hash=header.body_hash)) if header.previous_hash != last_known_header: await process_blocks(wallet, ledger_api, last_known_header, header.previous_hash) print(f'processing block {HeaderHash(header)}') additions = list(additions_for_body(body)) removals = removals_for_body(body) removals = [ Coin.from_bytes(await ledger_api.hash_preimage(hash=x)) for x in removals ] wallet.notify(additions, removals)
async def get_unspent_coins(ledger_api, header_hash): r = await ledger_api.get_tip() if r['genesis_hash'] == header_hash: return set() r = await ledger_api.hash_preimage(hash=header_hash) header = Header.from_bytes(r) unspent_coins = await get_unspent_coins(ledger_api, header.previous_hash) body = Body.from_bytes(await ledger_api.hash_preimage(hash=header.body_hash)) additions = list(additions_for_body(body)) unspent_coins.update(additions) removals = removals_for_body(body) removals = [ Coin.from_bytes(await ledger_api.hash_preimage(hash=x)) for x in removals ] unspent_coins.difference_update(removals) return unspent_coins
async def sync(self): """ Get blocks from ledger sim and make a note of new and spent coins that are "interesting". """ headers = [] tip_dict = await self._ledger_sim.get_tip() genesis_hash = tip_dict["genesis_hash"] header_hash = tip_dict["tip_hash"] header_index = tip_dict["tip_index"] while True: if header_hash == genesis_hash: break if len(self._header_list ) >= header_index and header_hash == HeaderHash( self._header_list[header_index - 1]): break preimage = await self._ledger_sim.hash_preimage(hash=header_hash) header = Header.from_bytes(preimage) headers.append(header) header_hash = header.previous_hash header_index -= 1 await self.rollback_to_block(header_index) new_block_count = len(headers) while headers: header = headers.pop() preimage = await self._ledger_sim.hash_preimage( hash=header.body_hash) body = Body.from_bytes(preimage) additions = [ _ for _ in additions_for_body(body) if _.puzzle_hash in self._interested_puzzled_hashes ] removals = [ _ for _ in removals_for_body(body) if _ in self._interested_puzzled_hashes ] await apply_deltas(header_index, additions, removals, self, self) self._header_list.append(header) header_index += 1 return new_block_count