async def test_wallet_coinbase_reorg(self, wallet_node): num_blocks = 10 full_nodes, wallets = wallet_node full_node_1, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) await asyncio.sleep(3) funds = sum( [ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks - 2) ] ) assert await wallet.get_confirmed_balance() == funds await full_node_1.reorg_from_index_to_new_index( ReorgProtocol(uint32(5), uint32(num_blocks + 3), token_bytes()) ) await asyncio.sleep(3) funds = sum( [ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, 5) ] ) assert await wallet.get_confirmed_balance() == funds
async def test_wallet_make_transaction(self, two_wallet_nodes): num_blocks = 10 full_nodes, wallets = two_wallet_nodes full_node_1, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None) for i in range(0, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) funds = sum( [ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(0, num_blocks - 2) ] ) await asyncio.sleep(2) assert await wallet.get_confirmed_balance() == funds assert await wallet.get_unconfirmed_balance() == funds spend_bundle = await wallet.generate_signed_transaction( 10, await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash(), 0, ) await wallet.push_transaction(spend_bundle) await asyncio.sleep(2) confirmed_balance = await wallet.get_confirmed_balance() unconfirmed_balance = await wallet.get_unconfirmed_balance() assert confirmed_balance == funds assert unconfirmed_balance == funds - 10 for i in range(0, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) await asyncio.sleep(2) new_funds = sum( [ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(0, (2 * num_blocks) - 2) ] ) confirmed_balance = await wallet.get_confirmed_balance() unconfirmed_balance = await wallet.get_unconfirmed_balance() assert confirmed_balance == new_funds - 10 assert unconfirmed_balance == new_funds - 10
async def test_colour_creation(self, two_wallet_nodes): num_blocks = 5 full_nodes, wallets = two_wallet_nodes full_node_1, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None) for i in range(1, 4): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) funds = sum( [ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, 4 - 2) ] ) await time_out_assert(15, wallet.get_confirmed_balance, funds) cc_wallet: CCWallet = await CCWallet.create_new_cc( wallet_node.wallet_state_manager, wallet, uint64(100) ) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, cc_wallet.get_confirmed_balance, 100) await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
async def test_generate_zero_val(self, two_wallet_nodes): num_blocks = 10 full_nodes, wallets = two_wallet_nodes full_node_1, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet wallet2 = wallet_node_2.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None) await server_3.start_client(PeerInfo("localhost", uint16(server_1._port)), None) for i in range(1, 4): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) funds = sum( [ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, 4 - 2) ] ) await time_out_assert(15, wallet.get_confirmed_balance, funds) cc_wallet: CCWallet = await CCWallet.create_new_cc( wallet_node.wallet_state_manager, wallet, uint64(100) ) ph = await wallet2.get_new_puzzlehash() for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, cc_wallet.get_confirmed_balance, 100) await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100) assert cc_wallet.cc_info.my_genesis_checker is not None colour = cc_wallet.get_colour() cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc( wallet_node_2.wallet_state_manager, wallet2, colour ) assert ( cc_wallet.cc_info.my_genesis_checker == cc_wallet_2.cc_info.my_genesis_checker ) await cc_wallet_2.generate_zero_val_coin() for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) unspent: List[WalletCoinRecord] = list( await cc_wallet_2.wallet_state_manager.get_spendable_coins_for_wallet( cc_wallet_2.id() ) ) assert len(unspent) == 1 assert unspent.pop().coin.amount == 0
async def test_coin_backup(self, two_wallet_nodes): num_blocks = 5 full_nodes, wallets = two_wallet_nodes full_node_1, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) for i in range(1, 4): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, 4 - 2) ]) await time_out_assert(15, wallet.get_confirmed_balance, funds) cc_wallet: CCWallet = await CCWallet.create_new_cc( wallet_node.wallet_state_manager, wallet, uint64(100)) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, cc_wallet.get_confirmed_balance, 100) await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100) # Write backup to file filename = f"test-backup-{token_bytes(16).hex()}" file_path = Path(filename) await wallet_node.wallet_state_manager.create_wallet_backup(file_path) # Close wallet and restart db_path = wallet_node.wallet_state_manager.db_path wallet_node._close() await wallet_node._await_closed() db_path.unlink() started = await wallet_node._start() assert started is False await wallet_node._start(backup_file=file_path) await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) all_wallets = wallet_node.wallet_state_manager.wallets assert len(all_wallets) == 2 cc_wallet_from_backup = wallet_node.wallet_state_manager.wallets[2] await time_out_assert(15, cc_wallet_from_backup.get_confirmed_balance, 100) if file_path.exists(): file_path.unlink()
async def test_wallet_make_transaction(self, two_wallet_nodes): num_blocks = 5 full_nodes, wallets = two_wallet_nodes full_node_1, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) for i in range(0, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks - 1) ]) await time_out_assert(5, wallet.get_confirmed_balance, funds) await time_out_assert(5, wallet.get_unconfirmed_balance, funds) tx = await wallet.generate_signed_transaction( 10, await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash( ), 0, ) await wallet.push_transaction(tx) await time_out_assert(5, wallet.get_confirmed_balance, funds) await time_out_assert(5, wallet.get_unconfirmed_balance, funds - 10) for i in range(0, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) new_funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, (2 * num_blocks) - 1) ]) await time_out_assert(5, wallet.get_confirmed_balance, new_funds - 10) await time_out_assert(5, wallet.get_unconfirmed_balance, new_funds - 10)
async def validate_block_body(self, block: FullBlock) -> Optional[Err]: """ Validates the transactions and body of the block. Returns None if everything validates correctly, or an Err if something does not validate. """ # 6. The compact block filter must be correct, according to the body (BIP158) if std_hash(block.transactions_filter) != block.header.data.filter_hash: return Err.INVALID_TRANSACTIONS_FILTER_HASH fee_base = calculate_base_fee(block.height) # target reward_fee = 1/8 coinbase reward + tx fees if block.transactions_generator is not None: # 14. Make sure transactions generator hash is valid (or all 0 if not present) if ( block.transactions_generator.get_tree_hash() != block.header.data.generator_hash ): return Err.INVALID_TRANSACTIONS_GENERATOR_HASH # 15. If not genesis, the transactions must be valid and fee must be valid # Verifies that fee_base + TX fees = fee_coin.amount err = await self._validate_transactions(block, fee_base) if err is not None: return err else: # Make sure transactions generator hash is valid (or all 0 if not present) if block.header.data.generator_hash != bytes32(bytes([0] * 32)): return Err.INVALID_TRANSACTIONS_GENERATOR_HASH # 16. If genesis, the fee must be the base fee, agg_sig must be None, and merkle roots must be valid if fee_base != block.header.data.total_transaction_fees: return Err.INVALID_BLOCK_FEE_AMOUNT root_error = self._validate_merkle_root(block) if root_error: return root_error # 17. Verify the pool signature even if there are no transactions pool_target_m = bytes(block.header.data.pool_target) validates = AugSchemeMPL.verify( block.proof_of_space.pool_public_key, pool_target_m, block.header.data.aggregated_signature, ) if not validates: return Err.BAD_AGGREGATE_SIGNATURE return None
async def test_wallet_coinbase(self, wallet_node): num_blocks = 5 full_nodes, wallets = wallet_node full_node_1, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks - 2) ]) await time_out_assert(5, wallet.get_confirmed_balance, funds)
async def test_wallet_make_transaction_hop(self, two_wallet_nodes_five_freeze): num_blocks = 10 full_nodes, wallets = two_wallet_nodes_five_freeze full_node_0, full_node_server = full_nodes[0] wallet_node_0, wallet_0_server = wallets[0] wallet_node_1, wallet_1_server = wallets[1] wallet_0 = wallet_node_0.wallet_state_manager.main_wallet wallet_1 = wallet_node_1.wallet_state_manager.main_wallet ph = await wallet_0.get_new_puzzlehash() await wallet_0_server.start_client( PeerInfo("localhost", uint16(full_node_server._port)), None ) await wallet_1_server.start_client( PeerInfo("localhost", uint16(full_node_server._port)), None ) for i in range(0, num_blocks): await full_node_0.farm_new_block(FarmNewBlockProtocol(ph)) funds = sum( [ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(0, num_blocks - 2) ] ) await asyncio.sleep(2) assert await wallet_0.get_confirmed_balance() == funds assert await wallet_0.get_unconfirmed_balance() == funds spend_bundle = await wallet_0.generate_signed_transaction( 10, await wallet_node_1.wallet_state_manager.main_wallet.get_new_puzzlehash(), 0, ) await wallet_0.push_transaction(spend_bundle) await asyncio.sleep(1) # Full node height 11, wallet height 9 confirmed_balance = await wallet_0.get_confirmed_balance() unconfirmed_balance = await wallet_0.get_unconfirmed_balance() assert confirmed_balance == funds assert unconfirmed_balance == funds - 10 for i in range(0, 7): await full_node_0.farm_new_block(FarmNewBlockProtocol(token_bytes())) await asyncio.sleep(1) new_funds = sum( [ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(0, num_blocks) ] ) # Full node height 17, wallet height 15 confirmed_balance = await wallet_0.get_confirmed_balance() unconfirmed_balance = await wallet_0.get_unconfirmed_balance() wallet_2_confirmed_balance = await wallet_1.get_confirmed_balance() assert confirmed_balance == new_funds - 10 assert unconfirmed_balance == new_funds - 10 assert wallet_2_confirmed_balance == 10 spend_bundle = await wallet_1.generate_signed_transaction( 5, await wallet_0.get_new_puzzlehash(), 0 ) await wallet_1.push_transaction(spend_bundle) for i in range(0, 7): await full_node_0.farm_new_block(FarmNewBlockProtocol(token_bytes())) await asyncio.sleep(1) confirmed_balance = await wallet_0.get_confirmed_balance() unconfirmed_balance = await wallet_0.get_unconfirmed_balance() wallet_2_confirmed_balance = await wallet_1.get_confirmed_balance() assert confirmed_balance == new_funds - 5 assert unconfirmed_balance == new_funds - 5 assert wallet_2_confirmed_balance == 5
async def test_wallet_send_to_three_peers(self, three_sim_two_wallets): num_blocks = 10 full_nodes, wallets = three_sim_two_wallets wallet_0, wallet_server_0 = wallets[0] full_node_0, server_0 = full_nodes[0] full_node_1, server_1 = full_nodes[1] full_node_2, server_2 = full_nodes[2] ph = await wallet_0.wallet_state_manager.main_wallet.get_new_puzzlehash() # wallet0 <-> sever0 await wallet_server_0.start_client( PeerInfo("localhost", uint16(server_0._port)), None ) for i in range(1, num_blocks): await full_node_0.farm_new_block(FarmNewBlockProtocol(ph)) all_blocks = await full_node_0.get_current_blocks(full_node_0.get_tip()) for block in all_blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block) ): pass async for _ in full_node_2.respond_block( full_node_protocol.RespondBlock(block) ): pass await asyncio.sleep(2) funds = sum( [ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks - 2) ] ) assert ( await wallet_0.wallet_state_manager.main_wallet.get_confirmed_balance() == funds ) spend_bundle = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction( 10, token_bytes(), 0 ) await wallet_0.wallet_state_manager.main_wallet.push_transaction(spend_bundle) await asyncio.sleep(1) bundle0 = full_node_0.mempool_manager.get_spendbundle(spend_bundle.name()) assert bundle0 is not None # wallet0 <-> sever1 await wallet_server_0.start_client( PeerInfo("localhost", uint16(server_1._port)), wallet_0._on_connect ) await asyncio.sleep(1) bundle1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name()) assert bundle1 is not None # wallet0 <-> sever2 await wallet_server_0.start_client( PeerInfo("localhost", uint16(server_2._port)), wallet_0._on_connect ) await asyncio.sleep(1) bundle2 = full_node_2.mempool_manager.get_spendbundle(spend_bundle.name()) assert bundle2 is not None
async def test_cc_spend_multiple(self, three_wallet_nodes): num_blocks = 8 full_nodes, wallets = three_wallet_nodes full_node_1, server_1 = full_nodes[0] wallet_node_0, wallet_server_0 = wallets[0] wallet_node_1, wallet_server_1 = wallets[1] wallet_node_2, wallet_server_2 = wallets[2] wallet_0 = wallet_node_0.wallet_state_manager.main_wallet wallet_1 = wallet_node_1.wallet_state_manager.main_wallet wallet_2 = wallet_node_2.wallet_state_manager.main_wallet ph = await wallet_0.get_new_puzzlehash() await wallet_server_0.start_client( PeerInfo("localhost", uint16(server_1._port)), None ) await wallet_server_1.start_client( PeerInfo("localhost", uint16(server_1._port)), None ) await wallet_server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None ) for i in range(1, 4): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) funds = sum( [ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, 4 - 2) ] ) await time_out_assert(15, wallet_0.get_confirmed_balance, funds) cc_wallet_0: CCWallet = await CCWallet.create_new_cc( wallet_node_0.wallet_state_manager, wallet_0, uint64(100) ) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, cc_wallet_0.get_confirmed_balance, 100) await time_out_assert(15, cc_wallet_0.get_unconfirmed_balance, 100) assert cc_wallet_0.cc_info.my_genesis_checker is not None colour = cc_wallet_0.get_colour() cc_wallet_1: CCWallet = await CCWallet.create_wallet_for_cc( wallet_node_1.wallet_state_manager, wallet_1, colour ) cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc( wallet_node_2.wallet_state_manager, wallet_2, colour ) assert ( cc_wallet_0.cc_info.my_genesis_checker == cc_wallet_1.cc_info.my_genesis_checker ) assert ( cc_wallet_0.cc_info.my_genesis_checker == cc_wallet_2.cc_info.my_genesis_checker ) cc_1_hash = await cc_wallet_1.get_new_inner_hash() cc_2_hash = await cc_wallet_2.get_new_inner_hash() tx_record = await cc_wallet_0.generate_signed_transaction( [uint64(60), uint64(20)], [cc_1_hash, cc_2_hash] ) await wallet_0.wallet_state_manager.add_pending_transaction(tx_record) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, cc_wallet_0.get_confirmed_balance, 20) await time_out_assert(15, cc_wallet_0.get_unconfirmed_balance, 20) await time_out_assert(30, cc_wallet_1.get_confirmed_balance, 60) await time_out_assert(30, cc_wallet_1.get_unconfirmed_balance, 60) await time_out_assert(30, cc_wallet_2.get_confirmed_balance, 20) await time_out_assert(30, cc_wallet_2.get_unconfirmed_balance, 20) cc_hash = await cc_wallet_0.get_new_inner_hash() tx_record = await cc_wallet_1.generate_signed_transaction( [uint64(15)], [cc_hash] ) await wallet_1.wallet_state_manager.add_pending_transaction(tx_record) tx_record_2 = await cc_wallet_2.generate_signed_transaction( [uint64(20)], [cc_hash] ) await wallet_2.wallet_state_manager.add_pending_transaction(tx_record_2) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, cc_wallet_0.get_confirmed_balance, 55) await time_out_assert(15, cc_wallet_0.get_unconfirmed_balance, 55) await time_out_assert(30, cc_wallet_1.get_confirmed_balance, 45) await time_out_assert(30, cc_wallet_1.get_unconfirmed_balance, 45) await time_out_assert(30, cc_wallet_2.get_confirmed_balance, 0) await time_out_assert(30, cc_wallet_2.get_unconfirmed_balance, 0)
async def test_assert_fee_condition(self, two_nodes): num_blocks = 10 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() wallet_receiver = WalletTool() receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() # Farm blocks blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash) full_node_1, full_node_2, server_1, server_2 = two_nodes for block in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass # Coinbase that gets spent block1 = blocks[1] # This condition requires fee to be 10 mojo cvp_fee = ConditionVarPair(ConditionOpcode.ASSERT_FEE, int_to_bytes(10), None) block1_dic = {cvp_fee.opcode: [cvp_fee]} # This spendbundle has 9 mojo as fee invalid_spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block1.get_coinbase(), block1_dic, 9) assert invalid_spend_bundle is not None program = best_solution_program(invalid_spend_bundle) aggsig = invalid_spend_bundle.aggregated_signature # Create another block that includes our transaction dic_h = {11: (program, aggsig)} invalid_new_blocks = bt.get_consecutive_blocks( test_constants, 1, blocks, 10, b"", coinbase_puzzlehash, dic_h, fees=uint64(9), ) # Try to validate that block at index 11 next_block = invalid_new_blocks[11] error = await full_node_1.blockchain._validate_transactions( next_block, next_block.get_fees_coin().amount) assert error is Err.ASSERT_FEE_CONDITION_FAILED # This condition requires fee to be 10 mojo cvp_fee = ConditionVarPair(ConditionOpcode.ASSERT_FEE, int_to_bytes(10), None) condition_dict = {cvp_fee.opcode: [cvp_fee]} valid_spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block1.get_coinbase(), condition_dict, 10) assert valid_spend_bundle is not None valid_program = best_solution_program(valid_spend_bundle) aggsig = valid_spend_bundle.aggregated_signature dic_h = {11: (valid_program, aggsig)} valid_new_blocks = bt.get_consecutive_blocks( test_constants, 1, blocks[:11], 10, b"", coinbase_puzzlehash, dic_h, fees=uint64(10), ) next_block = valid_new_blocks[11] fee_base = calculate_base_fee(next_block.height) error = await full_node_1.blockchain._validate_transactions( next_block, fee_base) assert error is None for block in valid_new_blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass
def _create_block( self, test_constants: Dict, challenge_hash: bytes32, height: uint32, prev_header_hash: bytes32, prev_iters: uint64, prev_weight: uint128, timestamp: uint64, difficulty: uint64, min_iters: uint64, seed: bytes, genesis: bool = False, reward_puzzlehash: bytes32 = None, transactions: Program = None, aggsig: BLSSignature = None, fees: uint64 = uint64(0), ) -> FullBlock: """ Creates a block with the specified details. Uses the stored plots to create a proof of space, and also evaluates the VDF for the proof of time. """ selected_prover = None selected_plot_sk = None selected_pool_sk = None selected_proof_index = 0 plots = list(self.plot_config["plots"].items()) selected_quality: Optional[bytes] = None best_quality = 0 if self.use_any_pos: for i in range(len(plots) * 3): # Allow passing in seed, to create reorgs and different chains random.seed(seed + i.to_bytes(4, "big")) seeded_pn = random.randint(0, len(plots) - 1) pool_sk = PrivateKey.from_bytes( bytes.fromhex(plots[seeded_pn][1]["pool_sk"]) ) plot_sk = PrivateKey.from_bytes( bytes.fromhex(plots[seeded_pn][1]["sk"]) ) prover = DiskProver(plots[seeded_pn][0]) qualities = prover.get_qualities_for_challenge(challenge_hash) if len(qualities) > 0: if self.use_any_pos: selected_quality = qualities[0] selected_prover = prover selected_pool_sk = pool_sk selected_plot_sk = plot_sk break else: for i in range(len(plots)): pool_sk = PrivateKey.from_bytes(bytes.fromhex(plots[i][1]["pool_sk"])) plot_sk = PrivateKey.from_bytes(bytes.fromhex(plots[i][1]["sk"])) prover = DiskProver(plots[i][0]) qualities = prover.get_qualities_for_challenge(challenge_hash) j = 0 for quality in qualities: qual_int = int.from_bytes(quality, "big", signed=False) if qual_int > best_quality: best_quality = qual_int selected_quality = quality selected_prover = prover selected_pool_sk = pool_sk selected_plot_sk = plot_sk selected_proof_index = j j += 1 assert selected_prover assert selected_pool_sk assert selected_plot_sk pool_pk = selected_pool_sk.get_public_key() plot_pk = selected_plot_sk.get_public_key() if selected_quality is None: raise RuntimeError("No proofs for this challenge") proof_xs: bytes = selected_prover.get_full_proof( challenge_hash, selected_proof_index ) proof_of_space: ProofOfSpace = ProofOfSpace( challenge_hash, pool_pk, plot_pk, selected_prover.get_size(), proof_xs ) number_iters: uint64 = pot_iterations.calculate_iterations( proof_of_space, difficulty, min_iters ) # print("Doing iters", number_iters) int_size = (test_constants["DISCRIMINANT_SIZE_BITS"] + 16) >> 4 result = prove( challenge_hash, test_constants["DISCRIMINANT_SIZE_BITS"], number_iters ) output = ClassgroupElement( int512(int.from_bytes(result[0:int_size], "big", signed=True,)), int512( int.from_bytes(result[int_size : 2 * int_size], "big", signed=True,) ), ) proof_bytes = result[2 * int_size : 4 * int_size] proof_of_time = ProofOfTime( challenge_hash, number_iters, output, self.n_wesolowski, proof_bytes, ) if not reward_puzzlehash: reward_puzzlehash = self.fee_target # Use the extension data to create different blocks based on header hash extension_data: bytes32 = bytes32([random.randint(0, 255) for _ in range(32)]) cost = uint64(0) coinbase_reward = block_rewards.calculate_block_reward(height) fee_reward = uint64(block_rewards.calculate_base_fee(height) + fees) coinbase_coin, coinbase_signature = create_coinbase_coin_and_signature( height, reward_puzzlehash, coinbase_reward, selected_pool_sk ) parent_coin_name = std_hash(std_hash(height)) fees_coin = Coin(parent_coin_name, reward_puzzlehash, uint64(fee_reward)) # Create filter byte_array_tx: List[bytes32] = [] tx_additions: List[Coin] = [] tx_removals: List[bytes32] = [] encoded = None if transactions: error, npc_list, _ = get_name_puzzle_conditions(transactions) additions: List[Coin] = additions_for_npc(npc_list) for coin in additions: tx_additions.append(coin) byte_array_tx.append(bytearray(coin.puzzle_hash)) for npc in npc_list: tx_removals.append(npc.coin_name) byte_array_tx.append(bytearray(npc.coin_name)) bip158: PyBIP158 = PyBIP158(byte_array_tx) encoded = bytes(bip158.GetEncoded()) removal_merkle_set = MerkleSet() addition_merkle_set = MerkleSet() # Create removal Merkle set for coin_name in tx_removals: removal_merkle_set.add_already_hashed(coin_name) # Create addition Merkle set puzzlehash_coin_map: Dict[bytes32, List[Coin]] = {} for coin in tx_additions: if coin.puzzle_hash in puzzlehash_coin_map: puzzlehash_coin_map[coin.puzzle_hash].append(coin) else: puzzlehash_coin_map[coin.puzzle_hash] = [coin] # Addition Merkle set contains puzzlehash and hash of all coins with that puzzlehash for puzzle, coins in puzzlehash_coin_map.items(): addition_merkle_set.add_already_hashed(puzzle) addition_merkle_set.add_already_hashed(hash_coin_list(coins)) additions_root = addition_merkle_set.get_root() removal_root = removal_merkle_set.get_root() generator_hash = ( transactions.get_tree_hash() if transactions is not None else bytes32([0] * 32) ) filter_hash = std_hash(encoded) if encoded is not None else bytes32([0] * 32) header_data: HeaderData = HeaderData( height, prev_header_hash, timestamp, filter_hash, proof_of_space.get_hash(), uint128(prev_weight + difficulty), uint64(prev_iters + number_iters), additions_root, removal_root, coinbase_coin, coinbase_signature, fees_coin, aggsig, cost, extension_data, generator_hash, ) header_hash_sig: PrependSignature = selected_plot_sk.sign_prepend( header_data.get_hash() ) header: Header = Header(header_data, header_hash_sig) full_block: FullBlock = FullBlock( proof_of_space, proof_of_time, header, transactions, encoded ) return full_block
async def test_create_offer_with_zero_val(self, two_wallet_nodes): num_blocks = 10 full_nodes, wallets = two_wallet_nodes full_node_1, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet wallet2 = wallet_node_2.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() ph2 = await wallet2.get_new_puzzlehash() await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) await server_3.start_client( PeerInfo("localhost", uint16(server_1._port)), None) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks - 2) ]) await self.time_out_assert(15, wallet.get_confirmed_balance, funds) cc_wallet: CCWallet = await CCWallet.create_new_cc( wallet_node.wallet_state_manager, wallet, uint64(100)) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) await self.time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100) await self.time_out_assert(15, cc_wallet.get_confirmed_balance, 100) assert cc_wallet.cc_info.my_core is not None colour = cc_wallet_puzzles.get_genesis_from_core( cc_wallet.cc_info.my_core) cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc( wallet_node_2.wallet_state_manager, wallet2, colour) assert cc_wallet.cc_info.my_core == cc_wallet_2.cc_info.my_core await full_node_1.farm_new_block(FarmNewBlockProtocol(ph2)) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) trade_manager_1 = await TradeManager.create( wallet_node.wallet_state_manager) trade_manager_2 = await TradeManager.create( wallet_node_2.wallet_state_manager) file = "test_offer_file.offer" file_path = Path(file) if file_path.exists(): file_path.unlink() offer_dict = {1: -10, 2: 30} success, spend_bundle, error = await trade_manager_2.create_offer_for_ids( offer_dict) assert success is True assert spend_bundle is not None trade_manager_2.write_offer_to_disk(file_path, spend_bundle) success, offer, error = await trade_manager_1.get_discrepancies_for_offer( file_path) assert error is None assert success is True assert offer is not None assert offer["chia"] == 10 assert offer[colour] == -30 success, reason = await trade_manager_1.respond_to_offer(file_path) assert success is True for i in range(0, num_blocks): await full_node_1.farm_new_block( FarmNewBlockProtocol(token_bytes())) await self.time_out_assert(15, cc_wallet_2.get_confirmed_balance, 30) await self.time_out_assert(15, cc_wallet_2.get_confirmed_balance, 30)
async def test_cc_spend_uncoloured(self, two_wallet_nodes): num_blocks = 10 full_nodes, wallets = two_wallet_nodes full_node_1, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet wallet2 = wallet_node_2.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) await server_3.start_client( PeerInfo("localhost", uint16(server_1._port)), None) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks - 2) ]) await self.time_out_assert(15, wallet.get_confirmed_balance, funds) cc_wallet: CCWallet = await CCWallet.create_new_cc( wallet_node.wallet_state_manager, wallet, uint64(100)) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) await self.time_out_assert(15, cc_wallet.get_confirmed_balance, 100) await self.time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100) assert cc_wallet.cc_info.my_core is not None colour = cc_wallet_puzzles.get_genesis_from_core( cc_wallet.cc_info.my_core) cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc( wallet_node_2.wallet_state_manager, wallet2, colour) assert cc_wallet.cc_info.my_core == cc_wallet_2.cc_info.my_core cc_2_hash = await cc_wallet_2.get_new_inner_hash() await cc_wallet.cc_spend(uint64(60), cc_2_hash) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) await self.time_out_assert(15, cc_wallet.get_confirmed_balance, 40) await self.time_out_assert(15, cc_wallet.get_unconfirmed_balance, 40) await self.time_out_assert(15, cc_wallet_2.get_confirmed_balance, 60) await self.time_out_assert(15, cc_wallet_2.get_unconfirmed_balance, 60) cc2_ph = await cc_wallet_2.get_new_cc_puzzle_hash() spend_bundle = await wallet.wallet_state_manager.main_wallet.generate_signed_transaction( 10, cc2_ph, 0) await wallet.wallet_state_manager.main_wallet.push_transaction( spend_bundle) for i in range(0, num_blocks): await full_node_1.farm_new_block( FarmNewBlockProtocol(token_bytes())) id = cc_wallet_2.wallet_info.id wsm = cc_wallet_2.wallet_state_manager await self.time_out_assert(15, wsm.get_confirmed_balance_for_wallet, 70, id) await self.time_out_assert(15, cc_wallet_2.get_confirmed_balance, 60) await self.time_out_assert(15, cc_wallet_2.get_unconfirmed_balance, 60)
async def test_wallet_make_transaction_hop(self, two_wallet_nodes_five_freeze): num_blocks = 10 full_nodes, wallets = two_wallet_nodes_five_freeze full_node_0, full_node_server = full_nodes[0] wallet_node_0, wallet_0_server = wallets[0] wallet_node_1, wallet_1_server = wallets[1] wallet_0 = wallet_node_0.wallet_state_manager.main_wallet wallet_1 = wallet_node_1.wallet_state_manager.main_wallet ph = await wallet_0.get_new_puzzlehash() await wallet_0_server.start_client( PeerInfo("localhost", uint16(full_node_server._port)), None) await wallet_1_server.start_client( PeerInfo("localhost", uint16(full_node_server._port)), None) for i in range(0, num_blocks): await full_node_0.farm_new_block(FarmNewBlockProtocol(ph)) funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks - 1) ]) await time_out_assert(5, wallet_0.get_confirmed_balance, funds) await time_out_assert(5, wallet_0.get_unconfirmed_balance, funds) assert await wallet_0.get_confirmed_balance() == funds assert await wallet_0.get_unconfirmed_balance() == funds tx = await wallet_0.generate_signed_transaction( 10, await wallet_node_1.wallet_state_manager.main_wallet.get_new_puzzlehash( ), 0, ) await wallet_0.push_transaction(tx) # Full node height 11, wallet height 9 await time_out_assert(5, wallet_0.get_confirmed_balance, funds) await time_out_assert(5, wallet_0.get_unconfirmed_balance, funds - 10) for i in range(0, 4): await full_node_0.farm_new_block( FarmNewBlockProtocol(token_bytes())) new_funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks + 1) ]) # Full node height 17, wallet height 15 await time_out_assert(5, wallet_0.get_confirmed_balance, new_funds - 10) await time_out_assert(5, wallet_0.get_unconfirmed_balance, new_funds - 10) await time_out_assert(5, wallet_1.get_confirmed_balance, 10) tx = await wallet_1.generate_signed_transaction( 5, await wallet_0.get_new_puzzlehash(), 0) await wallet_1.push_transaction(tx) for i in range(0, 4): await full_node_0.farm_new_block( FarmNewBlockProtocol(token_bytes())) await wallet_0.get_confirmed_balance() await wallet_0.get_unconfirmed_balance() await wallet_1.get_confirmed_balance() await time_out_assert(5, wallet_0.get_confirmed_balance, new_funds - 5) await time_out_assert(5, wallet_0.get_unconfirmed_balance, new_funds - 5) await time_out_assert(5, wallet_1.get_confirmed_balance, 5)
async def test_wallet_make_transaction(self, two_wallet_nodes): test_rpc_port = uint16(21529) num_blocks = 5 full_nodes, wallets = two_wallet_nodes full_node_1, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet wallet_2 = wallet_node_2.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() ph_2 = await wallet_2.get_new_puzzlehash() await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) for i in range(0, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) initial_funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks - 1) ]) initial_funds_eventually = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks + 1) ]) wallet_rpc_api = WalletRpcApi(wallet_node) config = load_config(bt.root_path, "config.yaml") hostname = config["self_hostname"] daemon_port = config["daemon_port"] def stop_node_cb(): pass rpc_cleanup = await start_rpc_server( wallet_rpc_api, hostname, daemon_port, test_rpc_port, stop_node_cb, connect_to_daemon=False, ) await time_out_assert(5, wallet.get_confirmed_balance, initial_funds) await time_out_assert(5, wallet.get_unconfirmed_balance, initial_funds) client = await WalletRpcClient.create("localhost", test_rpc_port) try: addr = encode_puzzle_hash(await wallet_node_2.wallet_state_manager. main_wallet.get_new_puzzlehash()) tx_amount = 15600000 try: await client.send_transaction("1", 100000000000000000, addr) raise Exception("Should not create high value tx") except ValueError: pass tx = await client.send_transaction("1", tx_amount, addr) transaction_id = tx.name() async def tx_in_mempool(): tx = await client.get_transaction("1", transaction_id) return tx.is_in_mempool() await time_out_assert(5, tx_in_mempool, True) await time_out_assert(5, wallet.get_unconfirmed_balance, initial_funds - tx_amount) assert ( await client.get_wallet_balance("1") )["unconfirmed_wallet_balance"] == initial_funds - tx_amount assert (await client.get_wallet_balance("1") )["confirmed_wallet_balance"] == initial_funds for i in range(0, 5): await client.farm_block(encode_puzzle_hash(ph_2)) await asyncio.sleep(1) async def eventual_balance(): return ( await client.get_wallet_balance("1"))["confirmed_wallet_balance"] await time_out_assert(5, eventual_balance, initial_funds_eventually - tx_amount) address = await client.get_next_address("1") assert len(address) > 10 transactions = await client.get_transactions("1") assert len(transactions) > 1 pks = await client.get_public_keys() assert len(pks) == 1 assert (await client.get_height_info()) > 0 sk_dict = await client.get_private_key(pks[0]) assert sk_dict["fingerprint"] == pks[0] assert sk_dict["sk"] is not None assert sk_dict["pk"] is not None assert sk_dict["seed"] is not None mnemonic = await client.generate_mnemonic() assert len(mnemonic) == 24 await client.add_key(mnemonic) pks = await client.get_public_keys() assert len(pks) == 2 await client.log_in_and_skip(pks[1]) sk_dict = await client.get_private_key(pks[1]) assert sk_dict["fingerprint"] == pks[1] await client.delete_key(pks[0]) await client.log_in_and_skip(pks[1]) assert len(await client.get_public_keys()) == 1 assert not (await client.get_sync_status()) wallets = await client.get_wallets() assert len(wallets) == 1 balance = await client.get_wallet_balance(wallets[0]["id"]) assert balance["unconfirmed_wallet_balance"] == 0 test_wallet_backup_path = Path("test_wallet_backup_file") await client.create_backup(test_wallet_backup_path) assert test_wallet_backup_path.exists() test_wallet_backup_path.unlink() try: await client.send_transaction(wallets[0]["id"], 100, addr) raise Exception("Should not create tx if no balance") except ValueError: pass await client.delete_all_keys() assert len(await client.get_public_keys()) == 0 except Exception: # Checks that the RPC manages to stop the node client.close() await client.await_closed() await rpc_cleanup() raise client.close() await client.await_closed() await rpc_cleanup()
async def test_wallet_make_transaction_with_fee(self, two_wallet_nodes): num_blocks = 10 full_nodes, wallets = two_wallet_nodes full_node_1, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) for i in range(0, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks - 1) ]) await asyncio.sleep(2) assert await wallet.get_confirmed_balance() == funds assert await wallet.get_unconfirmed_balance() == funds tx_amount = 32000000000000 tx_fee = 10 tx = await wallet.generate_signed_transaction( tx_amount, await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash( ), tx_fee, ) fees = tx.spend_bundle.fees() assert fees == tx_fee await wallet.push_transaction(tx) await asyncio.sleep(2) confirmed_balance = await wallet.get_confirmed_balance() unconfirmed_balance = await wallet.get_unconfirmed_balance() assert confirmed_balance == funds assert unconfirmed_balance == funds - tx_amount - tx_fee for i in range(0, num_blocks): await full_node_1.farm_new_block( FarmNewBlockProtocol(token_bytes())) await asyncio.sleep(2) new_funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks + 1) ]) confirmed_balance = await wallet.get_confirmed_balance() unconfirmed_balance = await wallet.get_unconfirmed_balance() assert confirmed_balance == new_funds - tx_amount - tx_fee assert unconfirmed_balance == new_funds - tx_amount - tx_fee
async def test_cc_spend(self, two_wallet_nodes): num_blocks = 8 full_nodes, wallets = two_wallet_nodes full_node_1, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet wallet2 = wallet_node_2.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None) await server_3.start_client(PeerInfo("localhost", uint16(server_1._port)), None) for i in range(1, 4): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) funds = sum( [ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, 4 - 2) ] ) await time_out_assert(15, wallet.get_confirmed_balance, funds) cc_wallet: CCWallet = await CCWallet.create_new_cc( wallet_node.wallet_state_manager, wallet, uint64(100) ) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, cc_wallet.get_confirmed_balance, 100) await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100) assert cc_wallet.cc_info.my_core is not None colour = cc_wallet_puzzles.get_genesis_from_core(cc_wallet.cc_info.my_core) cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc( wallet_node_2.wallet_state_manager, wallet2, colour ) assert cc_wallet.cc_info.my_core == cc_wallet_2.cc_info.my_core cc_2_hash = await cc_wallet_2.get_new_inner_hash() tx_record = await cc_wallet.generate_signed_transaction(uint64(60), cc_2_hash) await wallet.wallet_state_manager.add_pending_transaction(tx_record) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, cc_wallet.get_confirmed_balance, 40) await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 40) await time_out_assert(30, cc_wallet_2.get_confirmed_balance, 60) await time_out_assert(30, cc_wallet_2.get_unconfirmed_balance, 60) cc_hash = await cc_wallet.get_new_inner_hash() tx_record = await cc_wallet_2.generate_signed_transaction(uint64(15), cc_hash) await wallet.wallet_state_manager.add_pending_transaction(tx_record) for i in range(1, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, cc_wallet.get_confirmed_balance, 55) await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 55)
async def test_mempool_tx_sync(self, three_nodes_two_wallets): num_blocks = 5 full_nodes, wallets = three_nodes_two_wallets wallet_0, wallet_server_0 = wallets[0] full_node_0, server_0 = full_nodes[0] full_node_1, server_1 = full_nodes[1] full_node_2, server_2 = full_nodes[2] ph = await wallet_0.wallet_state_manager.main_wallet.get_new_puzzlehash( ) # wallet0 <-> sever0 <-> server1 await wallet_server_0.start_client( PeerInfo("localhost", uint16(server_0._port)), None) await server_0.start_client( PeerInfo("localhost", uint16(server_1._port)), None) for i in range(1, num_blocks): await full_node_0.farm_new_block(FarmNewBlockProtocol(ph)) all_blocks = await full_node_0.get_current_blocks( full_node_0.get_tip()) for block in all_blocks: async for _ in full_node_2.respond_block( full_node_protocol.RespondBlock(block)): pass funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks - 2) ]) await time_out_assert( 10, wallet_0.wallet_state_manager.main_wallet.get_confirmed_balance, funds) tx = (await wallet_0.wallet_state_manager.main_wallet. generate_signed_transaction(10, token_bytes(), 0)) await wallet_0.wallet_state_manager.main_wallet.push_transaction(tx) await time_out_assert(10, full_node_0.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name()) await time_out_assert(10, full_node_1.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name()) await time_out_assert(10, full_node_2.mempool_manager.get_spendbundle, None, tx.name()) # make a final connection. # wallet0 <-> sever0 <-> server1 <-> server2 await server_1.start_client( PeerInfo("localhost", uint16(server_2._port)), None) await time_out_assert(10, full_node_0.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name()) await time_out_assert(10, full_node_1.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name()) await time_out_assert(10, full_node_2.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name())
def _create_block( self, test_constants: ConsensusConstants, challenge_hash: bytes32, height: uint32, prev_header_hash: bytes32, prev_iters: uint64, prev_weight: uint128, timestamp: uint64, difficulty: int, min_iters: int, seed: bytes, genesis: bool = False, reward_puzzlehash: bytes32 = None, transactions: Program = None, aggsig: G2Element = None, fees: uint64 = uint64(0), ) -> FullBlock: """ Creates a block with the specified details. Uses the stored plots to create a proof of space, and also evaluates the VDF for the proof of time. """ selected_plot_info = None selected_proof_index = 0 selected_quality: Optional[bytes] = None best_quality = 0 plots = [ pinfo for _, pinfo in sorted(list(self.plots.items()), key=lambda x: str(x[0])) ] if self.use_any_pos: random.seed(seed) for i in range(len(plots) * 3): # Allow passing in seed, to create reorgs and different chains seeded_pn = random.randint(0, len(plots) - 1) plot_info = plots[seeded_pn] plot_id = plot_info.prover.get_id() ccp = ProofOfSpace.can_create_proof( plot_id, challenge_hash, test_constants.NUMBER_ZERO_BITS_CHALLENGE_SIG, ) if not ccp: continue qualities = plot_info.prover.get_qualities_for_challenge( challenge_hash) if len(qualities) > 0: selected_plot_info = plot_info selected_quality = qualities[0] break else: for i in range(len(plots)): plot_info = plots[i] j = 0 plot_id = plot_info.prover.get_id() ccp = ProofOfSpace.can_create_proof( plot_id, challenge_hash, test_constants.NUMBER_ZERO_BITS_CHALLENGE_SIG, ) if not ccp: continue qualities = plot_info.prover.get_qualities_for_challenge( challenge_hash) for quality in qualities: qual_int = int.from_bytes(quality, "big", signed=False) if qual_int > best_quality: best_quality = qual_int selected_quality = quality selected_plot_info = plot_info selected_proof_index = j j += 1 assert selected_plot_info is not None if selected_quality is None: raise RuntimeError("No proofs for this challenge") proof_xs: bytes = selected_plot_info.prover.get_full_proof( challenge_hash, selected_proof_index) plot_pk = ProofOfSpace.generate_plot_public_key( selected_plot_info.local_sk.get_g1(), selected_plot_info.farmer_public_key, ) proof_of_space: ProofOfSpace = ProofOfSpace( challenge_hash, selected_plot_info.pool_public_key, plot_pk, selected_plot_info.prover.get_size(), proof_xs, ) number_iters: uint64 = pot_iterations.calculate_iterations( proof_of_space, difficulty, min_iters, test_constants.NUMBER_ZERO_BITS_CHALLENGE_SIG, ) if self.real_plots: print(f"Performing {number_iters} VDF iterations") int_size = (test_constants.DISCRIMINANT_SIZE_BITS + 16) >> 4 result = prove(challenge_hash, test_constants.DISCRIMINANT_SIZE_BITS, number_iters) output = ClassgroupElement( int512(int.from_bytes( result[0:int_size], "big", signed=True, )), int512( int.from_bytes( result[int_size:2 * int_size], "big", signed=True, )), ) proof_bytes = result[2 * int_size:4 * int_size] proof_of_time = ProofOfTime( challenge_hash, number_iters, output, uint8(0), proof_bytes, ) # Use the extension data to create different blocks based on header hash extension_data: bytes32 = bytes32( [random.randint(0, 255) for _ in range(32)]) cost = uint64(0) fee_reward = uint64(block_rewards.calculate_base_fee(height) + fees) std_hash(std_hash(height)) # Create filter byte_array_tx: List[bytes32] = [] tx_additions: List[Coin] = [] tx_removals: List[bytes32] = [] if transactions: error, npc_list, _ = get_name_puzzle_conditions(transactions) additions: List[Coin] = additions_for_npc(npc_list) for coin in additions: tx_additions.append(coin) byte_array_tx.append(bytearray(coin.puzzle_hash)) for npc in npc_list: tx_removals.append(npc.coin_name) byte_array_tx.append(bytearray(npc.coin_name)) farmer_ph = self.farmer_ph pool_ph = self.pool_ph if reward_puzzlehash is not None: farmer_ph = reward_puzzlehash pool_ph = reward_puzzlehash byte_array_tx.append(bytearray(farmer_ph)) byte_array_tx.append(bytearray(pool_ph)) bip158: PyBIP158 = PyBIP158(byte_array_tx) encoded = bytes(bip158.GetEncoded()) removal_merkle_set = MerkleSet() addition_merkle_set = MerkleSet() # Create removal Merkle set for coin_name in tx_removals: removal_merkle_set.add_already_hashed(coin_name) # Create addition Merkle set puzzlehash_coin_map: Dict[bytes32, List[Coin]] = {} cb_reward = calculate_block_reward(height) cb_coin = create_coinbase_coin(height, pool_ph, cb_reward) fees_coin = create_fees_coin(height, farmer_ph, fee_reward) for coin in tx_additions + [cb_coin, fees_coin]: if coin.puzzle_hash in puzzlehash_coin_map: puzzlehash_coin_map[coin.puzzle_hash].append(coin) else: puzzlehash_coin_map[coin.puzzle_hash] = [coin] # Addition Merkle set contains puzzlehash and hash of all coins with that puzzlehash for puzzle, coins in puzzlehash_coin_map.items(): addition_merkle_set.add_already_hashed(puzzle) addition_merkle_set.add_already_hashed(hash_coin_list(coins)) additions_root = addition_merkle_set.get_root() removal_root = removal_merkle_set.get_root() generator_hash = (transactions.get_tree_hash() if transactions is not None else bytes32([0] * 32)) filter_hash = std_hash(encoded) pool_target = PoolTarget(pool_ph, uint32(height)) pool_target_signature = self.get_pool_key_signature( pool_target, proof_of_space.pool_public_key) assert pool_target_signature is not None final_aggsig: G2Element = pool_target_signature if aggsig is not None: final_aggsig = AugSchemeMPL.aggregate([final_aggsig, aggsig]) header_data: HeaderData = HeaderData( height, prev_header_hash, timestamp, filter_hash, proof_of_space.get_hash(), uint128(prev_weight + difficulty), uint64(prev_iters + number_iters), additions_root, removal_root, farmer_ph, fee_reward, pool_target, final_aggsig, cost, extension_data, generator_hash, ) header_hash_sig: G2Element = self.get_plot_signature( header_data, plot_pk) header: Header = Header(header_data, header_hash_sig) full_block: FullBlock = FullBlock(proof_of_space, proof_of_time, header, transactions, encoded) return full_block
async def test_tx_propagation(self, three_nodes_two_wallets): num_blocks = 5 full_nodes, wallets = three_nodes_two_wallets wallet_0, wallet_server_0 = wallets[0] wallet_1, wallet_server_1 = wallets[1] full_node_0, server_0 = full_nodes[0] full_node_1, server_1 = full_nodes[1] full_node_2, server_2 = full_nodes[2] ph = await wallet_0.wallet_state_manager.main_wallet.get_new_puzzlehash( ) ph1 = await wallet_1.wallet_state_manager.main_wallet.get_new_puzzlehash( ) # # wallet0 <-> sever0 <-> server1 <-> server2 <-> wallet1 # await wallet_server_0.start_client( PeerInfo("localhost", uint16(server_0._port)), None) await server_0.start_client( PeerInfo("localhost", uint16(server_1._port)), None) await server_1.start_client( PeerInfo("localhost", uint16(server_2._port)), None) await wallet_server_1.start_client( PeerInfo("localhost", uint16(server_2._port)), None) for i in range(1, num_blocks): await full_node_0.farm_new_block(FarmNewBlockProtocol(ph)) funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks - 2) ]) await time_out_assert( 10, wallet_0.wallet_state_manager.main_wallet.get_confirmed_balance, funds) tx = (await wallet_0.wallet_state_manager.main_wallet. generate_signed_transaction(10, ph1, 0)) await wallet_0.wallet_state_manager.main_wallet.push_transaction(tx) await time_out_assert(10, full_node_0.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name()) await time_out_assert(10, full_node_1.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name()) await time_out_assert(10, full_node_2.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name()) # Farm another block for i in range(1, 8): await full_node_1.farm_new_block( FarmNewBlockProtocol(token_bytes())) funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks) ]) await time_out_assert( 10, wallet_0.wallet_state_manager.main_wallet.get_confirmed_balance, (funds - 10), ) await time_out_assert( 15, wallet_1.wallet_state_manager.main_wallet.get_confirmed_balance, (10))