async def test_assert_time_exceeds_both_cases(self, two_nodes): num_blocks = 2 blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"") full_node_1, full_node_2, server_1, server_2 = two_nodes block = blocks[1] for b in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(b) ): pass time_now = uint64(int(time() * 1000)) time_now_plus_3 = time_now + 3000 cvp = ConditionVarPair( ConditionOpcode.ASSERT_TIME_EXCEEDS, time_now_plus_3.to_bytes(8, "big"), None, ) dic = {cvp.opcode: [cvp]} spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = ( full_node_protocol.RespondTransaction(spend_bundle1) ) async for _ in full_node_1.respond_transaction(tx1): outbound: OutboundMessage = _ assert outbound.message.function != "new_transaction" # Sleep so that 3 sec passes await asyncio.sleep(3) tx2: full_node_protocol.RespondTransaction = ( full_node_protocol.RespondTransaction(spend_bundle1) ) async for _ in full_node_1.respond_transaction(tx2): outbound_2: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound_2.message.function == "new_transaction" sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name()) assert sb1 is spend_bundle1
async def test_assert_fee_condition_wrong_fee(self, two_nodes): num_blocks = 2 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() wallet_receiver = WalletTool() receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() 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 block = blocks[1] for b in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(b)): pass cvp = ConditionVarPair( ConditionOpcode.ASSERT_FEE, int_to_bytes(10), None, ) dic = {cvp.opcode: [cvp]} spend_bundle1 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block.header.data.coinbase, dic, 9) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle1) outbound_messages: List[OutboundMessage] = [] async for outbound in full_node_1.respond_transaction(tx1): outbound_messages.append(outbound) new_transaction = False for msg in outbound_messages: if msg.message.function == "new_transaction": new_transaction = True assert new_transaction == False mempool_bundle = full_node_1.mempool_manager.get_spendbundle( spend_bundle1.name()) assert mempool_bundle is None
async def test_correct_announcement_consumed(self, two_nodes): reward_ph = WALLET_A.get_new_puzzlehash() full_node_1, full_node_2, server_1, server_2 = two_nodes blocks = await full_node_1.get_all_full_blocks() start_height = blocks[-1].height if len(blocks) > 0 else -1 blocks = bt.get_consecutive_blocks( 3, block_list_input=blocks, guarantee_transaction_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph, ) peer = await connect_and_get_peer(server_1, server_2) for block in blocks: await full_node_1.full_node.respond_block( full_node_protocol.RespondBlock(block)) await time_out_assert(60, node_height_at_least, True, full_node_1, start_height + 3) coin_1 = list(blocks[-2].get_included_reward_coins())[0] coin_2 = list(blocks[-1].get_included_reward_coins())[0] announce = Announcement(coin_2.name(), bytes("test", "utf-8")) cvp = ConditionVarPair(ConditionOpcode.ASSERT_ANNOUNCEMENT, [announce.name()]) dic = {cvp.opcode: [cvp]} cvp2 = ConditionVarPair(ConditionOpcode.CREATE_ANNOUNCEMENT, [bytes("test", "utf-8")]) dic2 = {cvp.opcode: [cvp2]} spend_bundle1 = generate_test_spend_bundle(coin_1, dic) spend_bundle2 = generate_test_spend_bundle(coin_2, dic2) bundle = SpendBundle.aggregate([spend_bundle1, spend_bundle2]) tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( bundle) await full_node_1.respond_transaction(tx1, peer) mempool_bundle = full_node_1.full_node.mempool_manager.get_spendbundle( bundle.name()) assert mempool_bundle is bundle
async def test_backtrack_sync_1(self, two_nodes): blocks = bt.get_consecutive_blocks(1, skip_slots=1) blocks = bt.get_consecutive_blocks(1, blocks, skip_slots=0) blocks = bt.get_consecutive_blocks(1, blocks, skip_slots=0) full_node_1, full_node_2, server_1, server_2 = two_nodes # 3 blocks to node_1 in different sub slots for block in blocks: await full_node_1.full_node.respond_block( full_node_protocol.RespondBlock(block)) await server_2.start_client( PeerInfo(self_hostname, uint16(server_1._port)), on_connect=full_node_2.full_node.on_connect, ) await time_out_assert(60, node_height_exactly, True, full_node_2, 2)
async def test_double_spend(self, two_nodes): num_blocks = 2 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() wallet_receiver = WalletTool() receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() 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 block = blocks[1] async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block) ): pass spend_bundle1 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block.header.data.coinbase ) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle1 ) async for _ in full_node_1.respond_transaction(tx1): outbound: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound.message.function == "new_transaction" other_receiver = WalletTool() spend_bundle2 = wallet_a.generate_signed_transaction( 1000, other_receiver.get_new_puzzlehash(), block.header.data.coinbase ) assert spend_bundle2 is not None tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle2 ) async for _ in full_node_1.respond_transaction(tx2): pass sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name()) sb2 = full_node_1.mempool_manager.get_spendbundle(spend_bundle2.name()) assert sb1 == spend_bundle1 assert sb2 is None
async def test_assert_time_exceeds_both_cases(self, two_nodes): reward_ph = WALLET_A.get_new_puzzlehash() full_node_1, full_node_2, server_1, server_2 = two_nodes blocks = await full_node_1.get_all_full_blocks() start_height = blocks[-1].height if len(blocks) > 0 else -1 blocks = bt.get_consecutive_blocks( 3, block_list_input=blocks, guarantee_transaction_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph, ) peer = await connect_and_get_peer(server_1, server_2) for block in blocks: await full_node_1.full_node.respond_block( full_node_protocol.RespondBlock(block)) await time_out_assert(60, node_height_at_least, True, full_node_1, start_height + 3) time_now = uint64(int(time() * 1000)) time_now_plus_3 = time_now + 3000 cvp = ConditionVarPair(ConditionOpcode.ASSERT_SECONDS_NOW_EXCEEDS, [time_now_plus_3.to_bytes(8, "big")]) dic = {cvp.opcode: [cvp]} spend_bundle1 = generate_test_spend_bundle( list(blocks[-1].get_included_reward_coins())[0], dic) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle1) await full_node_1.respond_transaction(tx1, peer) # Sleep so that 3 sec passes await asyncio.sleep(3) tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle1) await full_node_1.respond_transaction(tx2, peer) sb1 = full_node_1.full_node.mempool_manager.get_spendbundle( spend_bundle1.name()) assert sb1 is spend_bundle1
async def test_agg_sig_condition(self, two_nodes): num_blocks = 2 blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"") full_node_1, full_node_2, server_1, server_2 = two_nodes block = blocks[1] async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block) ): pass # this code has been changed to use generate_test_spend_bundle # not quite sure why all the gymnastics are being performed spend_bundle_0 = generate_test_spend_bundle( block.get_coinbase(), ) unsigned: List[CoinSolution] = spend_bundle_0.coin_solutions assert len(unsigned) == 1 coin_solution = unsigned[0] err, con, cost = conditions_for_solution(coin_solution.solution) assert con is not None puzzle, solution = list(coin_solution.solution.as_iter()) conditions_dict = conditions_by_opcode(con) pkm_pairs = pkm_pairs_for_conditions_dict( conditions_dict, coin_solution.coin.name() ) assert len(pkm_pairs) == 1 assert pkm_pairs[0][1] == solution.first().get_tree_hash() spend_bundle = WALLET_A.sign_transaction(unsigned) assert spend_bundle is not None tx: full_node_protocol.RespondTransaction = ( full_node_protocol.RespondTransaction(spend_bundle) ) async for _ in full_node_1.respond_transaction(tx): outbound: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound.message.function == "new_transaction" sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name()) assert sb is spend_bundle
async def test_agg_sig_condition(self, two_nodes): num_blocks = 2 wallet_a = bt.get_pool_wallet_tool() wallet_receiver = WalletTool() receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"") full_node_1, full_node_2, server_1, server_2 = two_nodes block = blocks[1] async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass unsigned: List[Tuple[ Program, CoinSolution]] = wallet_a.generate_unsigned_transaction( 1000, receiver_puzzlehash, block.get_coinbase(), {}, 0) assert len(unsigned) == 1 puzzle, solution = unsigned[0] code_ = [puzzle, solution.solution] sexp = Program.to(code_) err, con, cost = conditions_for_solution(sexp) assert con is not None conditions_dict = conditions_by_opcode(con) pkm_pairs = pkm_pairs_for_conditions_dict(conditions_dict, solution.coin.name()) assert len(pkm_pairs) == 1 assert pkm_pairs[0][1] == solution.solution.first().get_tree_hash() spend_bundle = wallet_a.sign_transaction(unsigned) assert spend_bundle is not None tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle) async for _ in full_node_1.respond_transaction(tx): outbound: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound.message.function == "new_transaction" sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name()) assert sb is spend_bundle
async def test_double_spend_with_higher_fee(self, two_nodes): reward_ph = WALLET_A.get_new_puzzlehash() full_node_1, full_node_2, server_1, server_2 = two_nodes blocks = await full_node_1.get_all_full_blocks() start_height = blocks[-1].height blocks = bt.get_consecutive_blocks( 3, block_list_input=blocks, guarantee_transaction_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph, ) peer = await connect_and_get_peer(server_1, server_2) for block in blocks: await full_node_1.full_node.respond_block( full_node_protocol.RespondBlock(block)) await time_out_assert(60, node_height_at_least, True, full_node_1, start_height + 3) spend_bundle1 = generate_test_spend_bundle( list(blocks[-1].get_included_reward_coins())[0]) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle1) await full_node_1.respond_transaction(tx1, peer) spend_bundle2 = generate_test_spend_bundle(list( blocks[-1].get_included_reward_coins())[0], fee=uint64(1)) assert spend_bundle2 is not None tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle2) await full_node_1.respond_transaction(tx2, peer) sb1 = full_node_1.full_node.mempool_manager.get_spendbundle( spend_bundle1.name()) sb2 = full_node_1.full_node.mempool_manager.get_spendbundle( spend_bundle2.name()) assert sb1 is None assert sb2 == spend_bundle2
async def test_invalid_coin_consumed(self, two_nodes): num_blocks = 2 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() wallet_receiver = WalletTool() receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() 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 block = blocks[1] block2 = blocks[2] for b in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(b) ): pass cvp = ConditionVarPair( ConditionOpcode.ASSERT_COIN_CONSUMED, block2.header.data.coinbase.name(), None, ) dic = {cvp.opcode: [cvp]} spend_bundle1 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block.header.data.coinbase, dic ) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle1 ) async for _ in full_node_1.respond_transaction(tx1): outbound: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound.message.function == "new_transaction" mempool_bundle = full_node_1.mempool_manager.get_spendbundle( spend_bundle1.name() ) assert mempool_bundle is None
async def test_assert_fee_condition(self, two_nodes): num_blocks = 2 blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"") full_node_1, full_node_2, server_1, server_2 = two_nodes block = blocks[1] for b in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(b) ): pass cvp = ConditionVarPair( ConditionOpcode.ASSERT_FEE, int_to_bytes(10), None, ) dic = {cvp.opcode: [cvp]} spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic, 10) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = ( full_node_protocol.RespondTransaction(spend_bundle1) ) outbound_messages: List[OutboundMessage] = [] async for outbound in full_node_1.respond_transaction(tx1): outbound_messages.append(outbound) new_transaction = False for msg in outbound_messages: if msg.message.function == "new_transaction": new_transaction = True assert new_transaction mempool_bundle = full_node_1.mempool_manager.get_spendbundle( spend_bundle1.name() ) assert mempool_bundle is not None
async def test_basic_sync(self, two_nodes): num_blocks = 40 blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10) full_node_1, full_node_2, server_1, server_2 = two_nodes for i in range(1, num_blocks): async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(blocks[i])): pass await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) # The second node should eventually catch up to the first one, and have the # same tip at height num_blocks - 1 (or at least num_blocks - 3, in case we sync to a # worse tip) await time_out_assert(60, node_height_at_least, True, full_node_2, num_blocks - 3)
async def test_validate_blockchain_duplicate_output(self, two_nodes): num_blocks = 3 wallet_a = WALLET_A coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0] receiver_puzzlehash = BURN_PUZZLE_HASH blocks = bt.get_consecutive_blocks( num_blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, guarantee_transaction_block=True) full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes full_node_1 = full_node_api_1.full_node for block in blocks: await full_node_api_1.full_node.respond_block( full_node_protocol.RespondBlock(block)) spend_block = blocks[2] spend_coin = None for coin in list(spend_block.get_included_reward_coins()): if coin.puzzle_hash == coinbase_puzzlehash: spend_coin = coin spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spend_coin) spend_bundle_double = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spend_coin) block_spendbundle = SpendBundle.aggregate( [spend_bundle, spend_bundle_double]) new_blocks = bt.get_consecutive_blocks( 1, block_list_input=blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=block_spendbundle, guarantee_transaction_block=True, ) next_block = new_blocks[-1] res, err, _ = await full_node_1.blockchain.receive_block(next_block) assert res == ReceiveBlockResult.INVALID_BLOCK assert err == Err.DUPLICATE_OUTPUT
async def test_validate_blockchain_with_double_spend(self, two_nodes): num_blocks = 5 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() wallet_receiver = WalletTool() receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() 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 spent_block = blocks[1] spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spent_block.get_coinbase() ) spend_bundle_double = wallet_a.generate_signed_transaction( 1001, receiver_puzzlehash, spent_block.get_coinbase() ) block_spendbundle = SpendBundle.aggregate([spend_bundle, spend_bundle_double]) program = best_solution_program(block_spendbundle) aggsig = block_spendbundle.aggregated_signature dic_h = {(num_blocks + 1): (program, aggsig)} new_blocks = bt.get_consecutive_blocks( test_constants, 1, blocks, 10, b"", coinbase_puzzlehash, dic_h ) next_block = new_blocks[num_blocks + 1] error = await full_node_1.blockchain._validate_transactions( next_block, next_block.get_fees_coin().amount ) assert error is Err.DOUBLE_SPEND
async def test_double_spend_same_bundle(self, two_nodes): reward_ph = WALLET_A.get_new_puzzlehash() full_node_1, full_node_2, server_1, server_2 = two_nodes blocks = await full_node_1.get_all_full_blocks() start_height = blocks[-1].height blocks = bt.get_consecutive_blocks( 3, block_list_input=blocks, guarantee_transaction_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph, ) peer = await connect_and_get_peer(server_1, server_2) for block in blocks: await full_node_1.full_node.respond_block( full_node_protocol.RespondBlock(block)) await time_out_assert(60, node_height_at_least, True, full_node_1, start_height + 3) coin = list(blocks[-1].get_included_reward_coins())[0] spend_bundle1 = generate_test_spend_bundle(coin) assert spend_bundle1 is not None spend_bundle2 = generate_test_spend_bundle( coin, new_puzzle_hash=BURN_PUZZLE_HASH_2, ) assert spend_bundle2 is not None spend_bundle_combined = SpendBundle.aggregate( [spend_bundle1, spend_bundle2]) tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle_combined) await full_node_1.respond_transaction(tx, peer) sb = full_node_1.full_node.mempool_manager.get_spendbundle( spend_bundle_combined.name()) assert sb is None
async def test_assert_time_exceeds(self, two_nodes): num_blocks = 2 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() wallet_receiver = WalletTool() receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() 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 block = blocks[1] for b in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(b) ): pass time_now = uint64(int(time() * 1000)) cvp = ConditionVarPair( ConditionOpcode.ASSERT_TIME_EXCEEDS, time_now.to_bytes(8, "big"), None ) dic = {cvp.opcode: [cvp]} spend_bundle1 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block.header.data.coinbase, dic ) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle1 ) async for _ in full_node_1.respond_transaction(tx1): outbound: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound.message.function == "new_transaction" sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name()) assert sb1 is spend_bundle1
async def test_new_pot(self, two_nodes, wallet_blocks): full_node_1, full_node_2, server_1, server_2 = two_nodes wallet_a, wallet_receiver, _ = wallet_blocks no_unf_block = fnp.NewProofOfTime( uint32(5), bytes(32 * [1]), uint64(124512), uint8(2) ) assert len([x async for x in full_node_1.new_proof_of_time(no_unf_block)]) == 0 blocks = await get_block_path(full_node_1) blocks_new = bt.get_consecutive_blocks( test_constants, 1, blocks[:-1], 10, seed=b"1212412", ) unf_block = FullBlock( blocks_new[-1].proof_of_space, None, blocks_new[-1].header, blocks_new[-1].transactions_generator, blocks_new[-1].transactions_filter, ) unf_block_req = fnp.RespondUnfinishedBlock(unf_block) res = [x async for x in full_node_1.respond_unfinished_block(unf_block_req)] dont_have = fnp.NewProofOfTime( unf_block.height, unf_block.proof_of_space.challenge_hash, res[0].message.data.iterations_needed, uint8(2), ) assert len([x async for x in full_node_1.new_proof_of_time(dont_have)]) == 1 [x async for x in full_node_1.respond_block(fnp.RespondBlock(blocks_new[-1]))] assert blocks_new[-1].proof_of_time is not None already_have = fnp.NewProofOfTime( unf_block.height, unf_block.proof_of_space.challenge_hash, res[0].message.data.iterations_needed, blocks_new[-1].proof_of_time.witness_type, ) assert len([x async for x in full_node_1.new_proof_of_time(already_have)]) == 0
async def test_double_spend_same_bundle(self, two_nodes): num_blocks = 2 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() wallet_receiver = WalletTool() receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() 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 block = blocks[1] async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block) ): pass spend_bundle1 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block.header.data.coinbase ) assert spend_bundle1 is not None other_receiver = WalletTool() spend_bundle2 = wallet_a.generate_signed_transaction( 1000, other_receiver.get_new_puzzlehash(), block.header.data.coinbase ) assert spend_bundle2 is not None spend_bundle_combined = SpendBundle.aggregate([spend_bundle1, spend_bundle2]) tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle_combined ) messages = [] async for outbound in full_node_1.respond_transaction(tx): messages.append(outbound) sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle_combined.name()) assert sb is None
async def test_invalid_block_index(self, two_nodes): num_blocks = 2 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() wallet_receiver = WalletTool() receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() 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 block = blocks[1] async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block) ): pass cvp = ConditionVarPair( ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS, uint64(2).to_bytes(4, "big"), None, ) dic = {ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS: [cvp]} spend_bundle1 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block.header.data.coinbase, dic ) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle1 ) async for _ in full_node_1.respond_transaction(tx1): outbound: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound.message.function != "new_transaction" sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name()) assert sb1 is None
async def test_blocks_load(self, two_nodes): num_blocks = 50 full_node_1, full_node_2, server_1, server_2 = two_nodes blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10) await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None) async def num_connections(): return len(server_2.global_connections.get_connections()) await time_out_assert(10, num_connections, 1) start_unf = time.time() for i in range(1, num_blocks): await time_out_assert(5, node_height_at_least, True, full_node_2, i - 2) msg = Message("respond_block", full_node_protocol.RespondBlock(blocks[i])) server_1.push_message( OutboundMessage(NodeType.FULL_NODE, msg, Delivery.BROADCAST) ) print(f"Time taken to process {num_blocks} is {time.time() - start_unf}") assert time.time() - start_unf < 100
async def test_double_spend(self, two_nodes): num_blocks = 2 blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"") full_node_1, full_node_2, server_1, server_2 = two_nodes block = blocks[1] async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block) ): pass spend_bundle1 = generate_test_spend_bundle(block.get_coinbase()) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = ( full_node_protocol.RespondTransaction(spend_bundle1) ) async for _ in full_node_1.respond_transaction(tx1): outbound: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound.message.function == "new_transaction" spend_bundle2 = generate_test_spend_bundle( block.get_coinbase(), newpuzzlehash=BURN_PUZZLE_HASH_2, ) assert spend_bundle2 is not None tx2: full_node_protocol.RespondTransaction = ( full_node_protocol.RespondTransaction(spend_bundle2) ) async for _ in full_node_1.respond_transaction(tx2): pass sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name()) sb2 = full_node_1.mempool_manager.get_spendbundle(spend_bundle2.name()) assert sb1 == spend_bundle1 assert sb2 is None
async def test_request_unfinished(self, two_nodes, wallet_blocks): full_node_1, full_node_2, server_1, server_2 = two_nodes wallet_a, wallet_receiver, blocks = wallet_blocks blocks_list = await get_block_path(full_node_1) blocks_new = bt.get_consecutive_blocks( test_constants, 2, blocks_list, 10, seed=b"another seed 3", ) # Add one block [_ async for _ in full_node_1.respond_block(fnp.RespondBlock(blocks_new[-2]))] unf_block = FullBlock( blocks_new[-1].proof_of_space, None, blocks_new[-1].header, blocks_new[-1].transactions_generator, blocks_new[-1].transactions_filter, ) unf_block_req = fnp.RespondUnfinishedBlock(unf_block) # Don't have req = fnp.RequestUnfinishedBlock(unf_block.header_hash) res = [x async for x in full_node_1.request_unfinished_block(req)] assert len(res) == 1 assert res[0].message.data == fnp.RejectUnfinishedBlockRequest( unf_block.header_hash ) # Have unfinished block [x async for x in full_node_1.respond_unfinished_block(unf_block_req)] res = [x async for x in full_node_1.request_unfinished_block(req)] assert len(res) == 1 assert res[0].message.data == fnp.RespondUnfinishedBlock(unf_block) # Have full block (genesis in this case) req = fnp.RequestUnfinishedBlock(blocks_new[0].header_hash) res = [x async for x in full_node_1.request_unfinished_block(req)] assert len(res) == 1 assert res[0].message.data.block.header_hash == blocks_new[0].header_hash
async def test_correct_coin_consumed(self, two_nodes): num_blocks = 2 blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"") full_node_1, full_node_2, server_1, server_2 = two_nodes block = blocks[1] block2 = blocks[2] for b in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(b) ): pass cvp = ConditionVarPair( ConditionOpcode.ASSERT_COIN_CONSUMED, block2.get_coinbase().name(), None, ) dic = {cvp.opcode: [cvp]} spend_bundle1 = generate_test_spend_bundle(block.get_coinbase(), dic) spend_bundle2 = generate_test_spend_bundle(block2.get_coinbase()) bundle = SpendBundle.aggregate([spend_bundle1, spend_bundle2]) tx1: full_node_protocol.RespondTransaction = ( full_node_protocol.RespondTransaction(bundle) ) async for _ in full_node_1.respond_transaction(tx1): outbound: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound.message.function == "new_transaction" mempool_bundle = full_node_1.mempool_manager.get_spendbundle(bundle.name()) assert mempool_bundle is bundle
async def test_assert_fee_condition_wrong_fee(self, two_nodes): reward_ph = WALLET_A.get_new_puzzlehash() full_node_1, full_node_2, server_1, server_2 = two_nodes blocks = await full_node_1.get_all_full_blocks() start_height = blocks[-1].height blocks = bt.get_consecutive_blocks( 3, block_list_input=blocks, guarantee_transaction_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph, ) peer = await connect_and_get_peer(server_1, server_2) for block in blocks: await full_node_1.full_node.respond_block( full_node_protocol.RespondBlock(block)) await time_out_assert(60, node_height_at_least, True, full_node_1, start_height + 3) cvp = ConditionVarPair(ConditionOpcode.RESERVE_FEE, [int_to_bytes(10)]) dic = {cvp.opcode: [cvp]} spend_bundle1 = generate_test_spend_bundle( list(blocks[-1].get_included_reward_coins())[0], dic, uint64(9)) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle1) await full_node_1.respond_transaction(tx1, peer) mempool_bundle = full_node_1.full_node.mempool_manager.get_spendbundle( spend_bundle1.name()) assert mempool_bundle is None
async def test_invalid_my_id(self, two_nodes): reward_ph = WALLET_A.get_new_puzzlehash() full_node_1, full_node_2, server_1, server_2 = two_nodes blocks = await full_node_1.get_all_full_blocks() start_height = blocks[-1].height if len(blocks) > 0 else -1 blocks = bt.get_consecutive_blocks( 3, block_list_input=blocks, guarantee_transaction_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph, ) peer = await connect_and_get_peer(server_1, server_2) for block in blocks: await full_node_1.full_node.respond_block( full_node_protocol.RespondBlock(block)) await time_out_assert(60, node_height_at_least, True, full_node_1, start_height + 3) coin = list(blocks[-1].get_included_reward_coins())[0] coin_2 = list(blocks[-2].get_included_reward_coins())[0] cvp = ConditionVarPair(ConditionOpcode.ASSERT_MY_COIN_ID, [coin_2.name()]) dic = {cvp.opcode: [cvp]} spend_bundle1 = generate_test_spend_bundle(coin, dic) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle1) await full_node_1.respond_transaction(tx1, peer) sb1 = full_node_1.full_node.mempool_manager.get_spendbundle( spend_bundle1.name()) assert sb1 is None
async def test_invalid_block_index(self, two_nodes): reward_ph = WALLET_A.get_new_puzzlehash() full_node_1, full_node_2, server_1, server_2 = two_nodes blocks = await full_node_1.get_all_full_blocks() start_height = blocks[-1].height blocks = bt.get_consecutive_blocks( 3, block_list_input=blocks, guarantee_transaction_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph, ) peer = await connect_and_get_peer(server_1, server_2) for block in blocks: await full_node_1.full_node.respond_block( full_node_protocol.RespondBlock(block)) await time_out_assert(60, node_height_at_least, True, full_node_1, start_height + 3) cvp = ConditionVarPair( ConditionOpcode.ASSERT_HEIGHT_NOW_EXCEEDS, [uint64(start_height + 5).to_bytes(4, "big")], ) dic = {ConditionOpcode.ASSERT_HEIGHT_NOW_EXCEEDS: [cvp]} spend_bundle1 = generate_test_spend_bundle( list(blocks[-1].get_included_reward_coins())[0], dic) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle1) await full_node_1.respond_transaction(tx1, peer) sb1 = full_node_1.full_node.mempool_manager.get_spendbundle( spend_bundle1.name()) assert sb1 is None
async def test_short_sync_wallet(self, wallet_node): num_blocks = 8 blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10) full_node_1, wallet_node, server_1, server_2 = wallet_node for i in range(1, len(blocks)): async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(blocks[i])): pass await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) start = time.time() while time.time() - start < 60: # The second node should eventually catch up to the first one, and have the # same tip at height num_blocks - 1. if (wallet_node.wallet_state_manager.block_records[ wallet_node.wallet_state_manager.lca].height == 6): return await asyncio.sleep(0.1) raise Exception( f"Took too long to process blocks, stopped at: {time.time() - start}" )
async def reorg_from_index_to_new_index(self, request: ReorgProtocol): new_index = request.new_index old_index = request.old_index coinbase_ph = request.puzzle_hash top_tip = self.get_tip() current_blocks = await self.get_current_blocks(top_tip) block_count = new_index - old_index more_blocks = self.bt.get_consecutive_blocks( self.constants, block_count, current_blocks[:old_index], 10, seed=token_bytes(), reward_puzzlehash=coinbase_ph, transaction_data_at_height={}, ) assert self.server is not None for block in more_blocks: async for msg in self.respond_block(full_node_protocol.RespondBlock(block)): self.server.push_message(msg) self.log.info(f"New message: {msg}")
async def test_validate_blockchain_duplicate_output(self, two_nodes): num_blocks = 10 wallet_a = WALLET_A coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0] receiver_puzzlehash = BURN_PUZZLE_HASH 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 spent_block = blocks[1] spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spent_block.get_coinbase()) spend_bundle_double = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spent_block.get_coinbase()) block_spendbundle = SpendBundle.aggregate( [spend_bundle, spend_bundle_double]) program = best_solution_program(block_spendbundle) aggsig = block_spendbundle.aggregated_signature dic_h = {(num_blocks + 1): (program, aggsig)} new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks, 10, b"", coinbase_puzzlehash, dic_h) next_block = new_blocks[(num_blocks + 1)] error = await full_node_1.blockchain._validate_transactions( next_block, next_block.get_fees_coin().amount) assert error is Err.DUPLICATE_OUTPUT
async def test_basic_mempool(self, two_nodes): num_blocks = 2 blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"") full_node_1, full_node_2, server_1, server_2 = two_nodes block = blocks[1] async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block) ): pass spend_bundle = generate_test_spend_bundle(block.get_coinbase()) assert spend_bundle is not None tx: full_node_protocol.RespondTransaction = ( full_node_protocol.RespondTransaction(spend_bundle) ) async for _ in full_node_1.respond_transaction(tx): outbound: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound.message.function == "new_transaction" sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name()) assert sb is spend_bundle