async def test_basics(self): wallet_tool = bt.get_pool_wallet_tool() receiver = WalletTool() num_blocks = 2 blocks = bt.get_consecutive_blocks( test_constants, num_blocks, [], 10, ) spend_bundle = wallet_tool.generate_signed_transaction( blocks[1].get_coinbase().amount, receiver.get_new_puzzlehash(), blocks[1].get_coinbase(), ) assert spend_bundle is not None program = best_solution_program(spend_bundle) ratio = test_constants.CLVM_COST_RATIO_CONSTANT error, npc_list, clvm_cost = calculate_cost_of_program(program, ratio) error, npc_list, cost = get_name_puzzle_conditions(program) # Create condition + agg_sig_condition + length + cpu_cost assert (clvm_cost == 200 * ratio + 20 * ratio + len(bytes(program)) * ratio + cost)
async def test_basic_mempool(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 spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, 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
async def test_correct_my_id(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] for b in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(b)): pass cvp = ConditionVarPair(ConditionOpcode.ASSERT_MY_COIN_ID, block.get_coinbase().name(), None) dic = {cvp.opcode: [cvp]} spend_bundle1 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, 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 = _ # 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_validate_blockchain_spend_reorg_cb_coin(self, two_nodes): num_blocks = 10 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() receiver_1_puzzlehash = wallet_a.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 # Spends a coinbase created in reorg new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks[:6], 10, b"reorg cb coin", coinbase_puzzlehash) [ _ async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(new_blocks[-1])) ] assert new_blocks[-1].header_hash in full_node_1.blockchain.headers spent_block = new_blocks[-1] spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_1_puzzlehash, spent_block.get_coinbase()) spend_bundle_2 = wallet_a.generate_signed_transaction( 1000, receiver_1_puzzlehash, spent_block.get_fees_coin()) block_spendbundle = SpendBundle.aggregate( [spend_bundle, spend_bundle_2]) program = best_solution_program(block_spendbundle) aggsig = block_spendbundle.aggregated_signature dic_h = {7: (program, aggsig)} new_blocks = bt.get_consecutive_blocks( test_constants, 1, new_blocks, 10, b"reorg cb coin", coinbase_puzzlehash, dic_h, ) error = await full_node_1.blockchain._validate_transactions( new_blocks[-1], new_blocks[-1].get_fees_coin().amount) assert error is None [ _ async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(new_blocks[-1])) ] assert new_blocks[-1].header_hash in full_node_1.blockchain.headers coins_created = [] for coin in new_blocks[-1].additions(): if coin.puzzle_hash == receiver_1_puzzlehash: coins_created.append(coin) assert len(coins_created) == 2
async def test_validate_blockchain_spend_reorg_since_genesis(self, two_nodes): num_blocks = 10 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() receiver_1_puzzlehash = wallet_a.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_1_puzzlehash, spent_block.get_coinbase() ) block_spendbundle = SpendBundle.aggregate([spend_bundle]) program = best_solution_program(block_spendbundle) aggsig = block_spendbundle.aggregated_signature dic_h = {11: (program, aggsig)} new_blocks = bt.get_consecutive_blocks( test_constants, 1, blocks, 10, b"", coinbase_puzzlehash, dic_h ) [ _ async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(new_blocks[-1]) ) ] # Spends a coin in a genesis reorg, that was already spent dic_h = {5: (program, aggsig)} new_blocks = bt.get_consecutive_blocks( test_constants, 12, [], 10, b"reorg since genesis", coinbase_puzzlehash, dic_h, ) for block in new_blocks: [ _ async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block) ) ] assert new_blocks[-1].header_hash in full_node_1.blockchain.headers
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 wb(num_blocks, two_nodes): full_node_1, _, _, _ = two_nodes wallet_a = bt.get_pool_wallet_tool() wallet_receiver = WalletTool() blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10) for i in range(1, num_blocks): async for _ in full_node_1.respond_block(fnp.RespondBlock(blocks[i])): pass return wallet_a, wallet_receiver, blocks
async def test_validate_blockchain_spend_reorg_cb_coin_freeze( self, two_nodes_standard_freeze ): num_blocks = 10 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() receiver_1_puzzlehash = wallet_a.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_standard_freeze for block in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block) ): pass # Spends a coinbase created in reorg new_blocks = bt.get_consecutive_blocks( test_constants, 1, blocks[:6], 10, b"reorg cb coin", coinbase_puzzlehash ) [ _ async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(new_blocks[-1]) ) ] assert new_blocks[-1].header_hash in full_node_1.blockchain.headers spent_block = new_blocks[-1] spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_1_puzzlehash, spent_block.get_coinbase() ) block_spendbundle = SpendBundle.aggregate([spend_bundle]) program = best_solution_program(block_spendbundle) aggsig = block_spendbundle.aggregated_signature dic_h = {7: (program, aggsig)} new_blocks = bt.get_consecutive_blocks( test_constants, 1, new_blocks, 10, b"reorg cb coin", coinbase_puzzlehash, dic_h, ) error = await full_node_1.blockchain._validate_transactions( new_blocks[-1], new_blocks[-1].get_coinbase().amount ) assert error is Err.COINBASE_NOT_YET_SPENDABLE
async def test_double_spend_same_bundle(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 spend_bundle1 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block.get_coinbase()) assert spend_bundle1 is not None other_receiver = WalletTool() spend_bundle2 = wallet_a.generate_signed_transaction( 1000, other_receiver.get_new_puzzlehash(), block.get_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_assert_time_exceeds_both_cases(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] 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 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, 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 = 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] 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.get_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 is False mempool_bundle = full_node_1.mempool_manager.get_spendbundle( spend_bundle1.name()) assert mempool_bundle is None
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_correct_coin_consumed(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] 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 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block.get_coinbase(), dic) spend_bundle2 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, 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_double_spend_with_higher_fee(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 spend_bundle1 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, 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 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block.get_coinbase(), fee=1) 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 is None assert sb2 == spend_bundle2
async def test_basics(self): WalletTool() num_blocks = 10 blocks = bt.get_consecutive_blocks( test_constants, num_blocks, [], 10, ) merkle_set = MerkleSet() merkle_set_reverse = MerkleSet() for block in reversed(blocks): merkle_set_reverse.add_already_hashed(block.get_coinbase().name()) for block in blocks: merkle_set.add_already_hashed(block.get_coinbase().name()) for block in blocks: result, proof = merkle_set.is_included_already_hashed( block.get_coinbase().name()) assert result is True result_fee, proof_fee = merkle_set.is_included_already_hashed( block.get_fees_coin().name()) assert result_fee is False validate_proof = confirm_included_already_hashed( merkle_set.get_root(), block.get_coinbase().name(), proof) validate_proof_fee = confirm_included_already_hashed( merkle_set.get_root(), block.get_fees_coin().name(), proof_fee) assert validate_proof is True assert validate_proof_fee is False # Test if order of adding items change the outcome assert merkle_set.get_root() == merkle_set_reverse.get_root()
async def test_invalid_block_index(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 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.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 = _ # 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_short_sync_with_transactions_wallet(self, wallet_node): full_node_1, wallet_node, server_1, server_2 = wallet_node wallet_a = wallet_node.wallet_state_manager.main_wallet wallet_a_dummy = WalletTool() wallet_b = WalletTool() coinbase_puzzlehash = await wallet_a.get_new_puzzlehash() coinbase_puzzlehash_rest = wallet_b.get_new_puzzlehash() puzzle_hashes = [ await wallet_a.get_new_puzzlehash() for _ in range(10) ] puzzle_hashes.append(wallet_b.get_new_puzzlehash()) blocks = bt.get_consecutive_blocks(test_constants, 3, [], 10, b"", coinbase_puzzlehash) for block in blocks: [ _ async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)) ] await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) await time_out_assert(60, wallet_height_at_least, True, wallet_node, 1) server_2.global_connections.close_all_connections() dic_h = {} prev_coin = blocks[1].get_coinbase() for i in range(11): pk, sk = await wallet_a.wallet_state_manager.get_keys( prev_coin.puzzle_hash) transaction_unsigned = wallet_a_dummy.generate_unsigned_transaction( 1000, puzzle_hashes[i], prev_coin, {}, 0, secretkey=sk) spend_bundle = await wallet_a.sign_transaction(transaction_unsigned ) block_spendbundle = SpendBundle.aggregate([spend_bundle]) program = best_solution_program(block_spendbundle) aggsig = block_spendbundle.aggregated_signature prev_coin = Coin(prev_coin.name(), puzzle_hashes[i], uint64(1000)) dic_h[i + 4] = (program, aggsig) blocks = bt.get_consecutive_blocks(test_constants, 13, blocks, 10, b"", coinbase_puzzlehash_rest, dic_h) # Move chain to height 16, with consecutive transactions in blocks 4 to 14 for block in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass # Do a short sync from 0 to 14 await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) await time_out_assert(60, wallet_height_at_least, True, wallet_node, 14) server_2.global_connections.close_all_connections() # 2 block rewards and 3 fees assert await wallet_a.get_confirmed_balance() == ( blocks[1].get_coinbase().amount * 2) + (blocks[1].get_fees_coin().amount * 3) # All of our coins are spent and puzzle hashes present for puzzle_hash in puzzle_hashes[:-1]: records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash( puzzle_hash) assert len(records) == 1 assert records[0].spent and not records[0].coinbase # Then do the same but in a reorg chain dic_h = {} prev_coin = blocks[1].get_coinbase() for i in range(11): pk, sk = await wallet_a.wallet_state_manager.get_keys( prev_coin.puzzle_hash) transaction_unsigned = wallet_a_dummy.generate_unsigned_transaction( 1000, puzzle_hashes[i], prev_coin, {}, 0, secretkey=sk) spend_bundle = await wallet_a.sign_transaction(transaction_unsigned ) block_spendbundle = SpendBundle.aggregate([spend_bundle]) program = best_solution_program(block_spendbundle) aggsig = block_spendbundle.aggregated_signature prev_coin = Coin(prev_coin.name(), puzzle_hashes[i], uint64(1000)) dic_h[i + 4] = (program, aggsig) blocks = bt.get_consecutive_blocks( test_constants, 31, blocks[:4], 10, b"this is a reorg", coinbase_puzzlehash_rest, dic_h, ) # Move chain to height 34, with consecutive transactions in blocks 4 to 14 for block in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass # Do a sync from 0 to 22 await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) await time_out_assert(60, wallet_height_at_least, True, wallet_node, 28) server_2.global_connections.close_all_connections() # 2 block rewards and 3 fees assert await wallet_a.get_confirmed_balance() == ( blocks[1].get_coinbase().amount * 2) + (blocks[1].get_fees_coin().amount * 3) # All of our coins are spent and puzzle hashes present for puzzle_hash in puzzle_hashes[:-1]: records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash( puzzle_hash) assert len(records) == 1 assert records[0].spent and not records[0].coinbase # Test spending the rewards earned in reorg new_coinbase_puzzlehash = await wallet_a.get_new_puzzlehash() another_puzzlehash = await wallet_a.get_new_puzzlehash() dic_h = {} pk, sk = await wallet_a.wallet_state_manager.get_keys( new_coinbase_puzzlehash) coinbase_coin = create_coinbase_coin(uint32(25), new_coinbase_puzzlehash, uint64(14000000000000)) transaction_unsigned = wallet_a_dummy.generate_unsigned_transaction( 7000000000000, another_puzzlehash, coinbase_coin, {}, 0, secretkey=sk) spend_bundle = await wallet_a.sign_transaction(transaction_unsigned) block_spendbundle = SpendBundle.aggregate([spend_bundle]) program = best_solution_program(block_spendbundle) aggsig = block_spendbundle.aggregated_signature dic_h[26] = (program, aggsig) # Farm a block (25) to ourselves blocks = bt.get_consecutive_blocks( test_constants, 1, blocks[:25], 10, b"this is yet another reorg", new_coinbase_puzzlehash, ) # Brings height up to 40, with block 31 having half our reward spent to us blocks = bt.get_consecutive_blocks( test_constants, 15, blocks, 10, b"this is yet another reorg more blocks", coinbase_puzzlehash_rest, dic_h, ) for block in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) await time_out_assert(60, wallet_height_at_least, True, wallet_node, 38) # 2 block rewards and 4 fees, plus 7000000000000 coins assert (await wallet_a.get_confirmed_balance() == (blocks[1].get_coinbase().amount * 2) + (blocks[1].get_fees_coin().amount * 4) + 7000000000000) records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash( new_coinbase_puzzlehash) # Fee and coinbase assert len(records) == 2 print(records) assert records[0].spent != records[1].spent assert records[0].coinbase == records[1].coinbase records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash( another_puzzlehash) assert len(records) == 1 assert not records[0].spent assert not records[0].coinbase
async def test_basic_blockchain_tx(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() 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()) 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 last_block = blocks[10] next_spendbundle = await full_node_1.mempool_manager.create_bundle_for_tip( last_block.header) assert next_spendbundle is not None program = best_solution_program(next_spendbundle) aggsig = next_spendbundle.aggregated_signature dic_h = {11: (program, aggsig)} new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks, 10, b"", coinbase_puzzlehash, dic_h) next_block = new_blocks[11] async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(next_block)): pass tips = full_node_1.blockchain.get_current_tips() assert next_block.header in tips added_coins = next_spendbundle.additions() # Two coins are added, main spend and change assert len(added_coins) == 2 for coin in added_coins: unspent = await full_node_1.coin_store.get_coin_record( coin.name(), next_block.header) assert unspent is not None full_tips = await full_node_1.blockchain.get_full_tips() in_full_tips = False farmed_block: Optional[FullBlock] = None for tip in full_tips: if tip.header == next_block.header: in_full_tips = True farmed_block = tip assert in_full_tips assert farmed_block is not None assert farmed_block.transactions_generator == program
async def test_invalid_filter(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() 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()) 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 last_block = blocks[10] next_spendbundle = await full_node_1.mempool_manager.create_bundle_for_tip( last_block.header) assert next_spendbundle is not None program = best_solution_program(next_spendbundle) aggsig = next_spendbundle.aggregated_signature dic_h = {11: (program, aggsig)} new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks, 10, b"", coinbase_puzzlehash, dic_h) next_block = new_blocks[11] bad_header = HeaderData( next_block.header.data.height, next_block.header.data.prev_header_hash, next_block.header.data.timestamp, bytes32(bytes([3] * 32)), next_block.header.data.proof_of_space_hash, next_block.header.data.weight, next_block.header.data.total_iters, next_block.header.data.additions_root, next_block.header.data.removals_root, next_block.header.data.farmer_rewards_puzzle_hash, next_block.header.data.total_transaction_fees, next_block.header.data.pool_target, next_block.header.data.aggregated_signature, next_block.header.data.cost, next_block.header.data.extension_data, next_block.header.data.generator_hash, ) bad_block = FullBlock( next_block.proof_of_space, next_block.proof_of_time, Header( bad_header, bt.get_plot_signature( bad_header, next_block.proof_of_space.plot_public_key), ), next_block.transactions_generator, next_block.transactions_filter, ) result, removed, error_code = await full_node_1.blockchain.receive_block( bad_block) assert result == ReceiveBlockResult.INVALID_BLOCK assert error_code == Err.INVALID_TRANSACTIONS_FILTER_HASH result, removed, error_code = await full_node_1.blockchain.receive_block( next_block) assert result == ReceiveBlockResult.ADDED_TO_HEAD
def get_farmer_wallet_tool(self): return WalletTool(self.farmer_master_sk)
import asyncio from pathlib import Path from typing import Optional, List, Set import aiosqlite import pytest from src.consensus.blockchain import Blockchain, ReceiveBlockResult from src.full_node.coin_store import CoinStore from src.full_node.block_store import BlockStore from src.types.coin import Coin from src.types.coin_record import CoinRecord from tests.setup_nodes import test_constants, bt from src.util.wallet_tools import WalletTool WALLET_A = WalletTool() @pytest.fixture(scope="module") def event_loop(): loop = asyncio.get_event_loop() yield loop constants = test_constants class TestCoinStore: @pytest.mark.asyncio async def test_basic_coin_store(self): wallet_a = WALLET_A
async def test_assert_my_coin_id(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 spent_block = blocks[1] bad_block = blocks[2] valid_cvp = ConditionVarPair( ConditionOpcode.ASSERT_MY_COIN_ID, spent_block.get_coinbase().name(), None, ) valid_dic = {valid_cvp.opcode: [valid_cvp]} bad_cvp = ConditionVarPair( ConditionOpcode.ASSERT_MY_COIN_ID, bad_block.get_coinbase().name(), None, ) bad_dic = {bad_cvp.opcode: [bad_cvp]} bad_spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spent_block.get_coinbase(), bad_dic) valid_spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spent_block.get_coinbase(), valid_dic) # Invalid block bundle assert bad_spend_bundle is not None invalid_program = best_solution_program(bad_spend_bundle) aggsig = bad_spend_bundle.aggregated_signature # Create another block that includes our transaction dic_h = {11: (invalid_program, aggsig)} invalid_new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks, 10, b"", coinbase_puzzlehash, dic_h) # Try to validate that block 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_MY_COIN_ID_FAILED # Valid block bundle assert valid_spend_bundle is not None valid_program = best_solution_program(valid_spend_bundle) aggsig = valid_spend_bundle.aggregated_signature # Create another block that includes our transaction dic_h = {11: (valid_program, aggsig)} new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks[:11], 10, b"1", coinbase_puzzlehash, dic_h) next_block = new_blocks[11] error = await full_node_1.blockchain._validate_transactions( next_block, next_block.get_fees_coin().amount) assert error is None
async def test_validate_blockchain_with_reorg_double_spend( 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() 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()) block_spendbundle = SpendBundle.aggregate([spend_bundle]) program = best_solution_program(block_spendbundle) aggsig = block_spendbundle.aggregated_signature dic_h = {11: (program, aggsig)} blocks = bt.get_consecutive_blocks(test_constants, 10, blocks, 10, b"", coinbase_puzzlehash, dic_h) # Move chain to height 20, with a spend at height 11 for block in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass # Reorg at block 5, same spend at block 13 and 14 that was previously at block 11 dic_h = {13: (program, aggsig), 14: (program, aggsig)} new_blocks = bt.get_consecutive_blocks( test_constants, 9, blocks[:6], 10, b"another seed", coinbase_puzzlehash, dic_h, ) for block in new_blocks[:13]: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass next_block = new_blocks[13] error = await full_node_1.blockchain._validate_transactions( next_block, next_block.get_fees_coin().amount) assert error is None [ _ async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(new_blocks[13])) ] next_block = new_blocks[14] error = await full_node_1.blockchain._validate_transactions( next_block, next_block.get_fees_coin().amount) assert error is Err.DOUBLE_SPEND # Now test Reorg at block 5, same spend at block 9 that was previously at block 11 dic_h = {9: (program, aggsig)} new_blocks = bt.get_consecutive_blocks( test_constants, 4, blocks[:6], 10, b"another seed 2", coinbase_puzzlehash, dic_h, ) for block in new_blocks[:9]: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass next_block = new_blocks[9] error = await full_node_1.blockchain._validate_transactions( next_block, next_block.get_fees_coin().amount) assert error is None # Now test Reorg at block 10, same spend at block 11 that was previously at block 11 dic_h = {11: (program, aggsig)} new_blocks = bt.get_consecutive_blocks( test_constants, 4, blocks[:11], 10, b"another seed 3", coinbase_puzzlehash, dic_h, ) for block in new_blocks[:11]: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass next_block = new_blocks[11] error = await full_node_1.blockchain._validate_transactions( next_block, next_block.get_fees_coin().amount) assert error is None # Now test Reorg at block 11, same spend at block 12 that was previously at block 11 dic_h = {12: (program, aggsig)} new_blocks = bt.get_consecutive_blocks( test_constants, 4, blocks[:12], 10, b"another seed 4", coinbase_puzzlehash, dic_h, ) for block in new_blocks[:12]: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass next_block = new_blocks[12] error = await full_node_1.blockchain._validate_transactions( next_block, next_block.get_fees_coin().amount) assert error is Err.DOUBLE_SPEND # Now test Reorg at block 11, same spend at block 15 that was previously at block 11 dic_h = {15: (program, aggsig)} new_blocks = bt.get_consecutive_blocks( test_constants, 4, blocks[:12], 10, b"another seed 5", coinbase_puzzlehash, dic_h, ) for block in new_blocks[:15]: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass next_block = new_blocks[15] 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_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
async def test_assert_coin_consumed(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] block2 = blocks[2] # This condition requires block2 coinbase to be spent block1_cvp = ConditionVarPair( ConditionOpcode.ASSERT_COIN_CONSUMED, block2.get_coinbase().name(), None, ) block1_dic = {block1_cvp.opcode: [block1_cvp]} block1_spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block1.get_coinbase(), block1_dic) # This condition requires block1 coinbase to be spent block2_cvp = ConditionVarPair( ConditionOpcode.ASSERT_COIN_CONSUMED, block1.get_coinbase().name(), None, ) block2_dic = {block2_cvp.opcode: [block2_cvp]} block2_spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block2.get_coinbase(), block2_dic) # Invalid block bundle assert block1_spend_bundle is not None solo_program = best_solution_program(block1_spend_bundle) aggsig = block1_spend_bundle.aggregated_signature # Create another block that includes our transaction dic_h = {11: (solo_program, aggsig)} invalid_new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks, 10, b"", coinbase_puzzlehash, dic_h) # Try to validate that block 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_COIN_CONSUMED_FAILED # bundle_together contains both transactions bundle_together = SpendBundle.aggregate( [block1_spend_bundle, block2_spend_bundle]) valid_program = best_solution_program(bundle_together) aggsig = bundle_together.aggregated_signature # Create another block that includes our transaction dic_h = {11: (valid_program, aggsig)} new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks[:11], 10, b"1", coinbase_puzzlehash, dic_h) # Try to validate newly created block next_block = new_blocks[11] error = await full_node_1.blockchain._validate_transactions( next_block, next_block.get_fees_coin().amount) assert error is None
async def test_validate_blockchain_spend_reorg_coin(self, two_nodes): num_blocks = 10 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() receiver_1_puzzlehash = wallet_a.get_new_puzzlehash() receiver_2_puzzlehash = wallet_a.get_new_puzzlehash() receiver_3_puzzlehash = wallet_a.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_1_puzzlehash, spent_block.get_coinbase()) block_spendbundle = SpendBundle.aggregate([spend_bundle]) program = best_solution_program(block_spendbundle) aggsig = block_spendbundle.aggregated_signature dic_h = {5: (program, aggsig)} new_blocks = bt.get_consecutive_blocks( test_constants, 1, blocks[:5], 10, b"spend_reorg_coin", coinbase_puzzlehash, dic_h, ) [ _ async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(new_blocks[-1])) ] assert new_blocks[-1].header_hash in full_node_1.blockchain.headers coin_2 = None for coin in new_blocks[-1].additions(): if coin.puzzle_hash == receiver_1_puzzlehash: coin_2 = coin break assert coin_2 is not None spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_2_puzzlehash, coin_2) block_spendbundle = SpendBundle.aggregate([spend_bundle]) program = best_solution_program(block_spendbundle) aggsig = block_spendbundle.aggregated_signature dic_h = {6: (program, aggsig)} new_blocks = bt.get_consecutive_blocks( test_constants, 1, new_blocks[:6], 10, b"spend_reorg_coin", coinbase_puzzlehash, dic_h, ) [ _ async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(new_blocks[-1])) ] assert new_blocks[-1].header_hash in full_node_1.blockchain.headers coin_3 = None for coin in new_blocks[-1].additions(): if coin.puzzle_hash == receiver_2_puzzlehash: coin_3 = coin break assert coin_3 is not None spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_3_puzzlehash, coin_3) block_spendbundle = SpendBundle.aggregate([spend_bundle]) program = best_solution_program(block_spendbundle) aggsig = block_spendbundle.aggregated_signature dic_h = {7: (program, aggsig)} new_blocks = bt.get_consecutive_blocks( test_constants, 1, new_blocks[:7], 10, b"spend_reorg_coin", coinbase_puzzlehash, dic_h, ) [ _ async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(new_blocks[-1])) ] assert new_blocks[-1].header_hash in full_node_1.blockchain.headers coin_4 = None for coin in new_blocks[-1].additions(): if coin.puzzle_hash == receiver_3_puzzlehash: coin_4 = coin break assert coin_4 is not None
print(f"cost of one_substraction is: {one_substraction}") print(f"cost of one_multiply is: {one_multiply}") print(f"cost of one_greater is: {one_greater}") print(f"cost of one_equal is: {one_equal}") print(f"cost of one_if is: {one_if}") print(f"cost of one_sha256 is: {one_sha256}") print(f"cost of one_pubkey_for_exp is: {one_pubkey_for_exp}") print(f"cost of one_point_add is: {one_point_add}") if __name__ == "__main__": """ Naive way to calculate cost ratio between vByte and CLVM cost unit. AggSig has assigned cost of 20vBytes, simple CLVM program is benchmarked against it. """ wallet_tool = WalletTool() benchmark_all_operators() secret_key: PrivateKey = PrivateKey.from_seed(bytes([2] * 32)) puzzles = [] solutions = [] private_keys = [] public_keys = [] for i in range(0, 1000): private_key: PrivateKey = master_sk_to_wallet_sk(secret_key, uint32(i)) public_key = private_key.public_key() solution = wallet_tool.make_solution({ ConditionOpcode.ASSERT_MY_COIN_ID: [ ConditionVarPair(ConditionOpcode.ASSERT_MY_COIN_ID, token_bytes(), None) ]
async def test_assert_block_age_exceeds(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 block1 coinbase to be spent more than 10 block after it was farmed # block index has to be greater than (1 + 10 = 11) block1_cvp = ConditionVarPair(ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS, int_to_bytes(10), None) block1_dic = {block1_cvp.opcode: [block1_cvp]} block1_spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block1.get_coinbase(), block1_dic) # program that will be sent to early assert block1_spend_bundle is not None program = best_solution_program(block1_spend_bundle) aggsig = block1_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) # 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_BLOCK_AGE_EXCEEDS_FAILED dic_h = {12: (program, aggsig)} valid_new_blocks = bt.get_consecutive_blocks(test_constants, 2, blocks[:11], 10, b"", coinbase_puzzlehash, dic_h) for block in valid_new_blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass # Try to validate that block at index 12 next_block = valid_new_blocks[12] error = await full_node_1.blockchain._validate_transactions( next_block, next_block.get_fees_coin().amount) assert error is None
def get_pool_wallet_tool(self): return WalletTool(self.pool_master_sk)
async def test_assert_time_exceeds(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 block1 coinbase to be spent after 3 seconds from now current_time_plus3 = uint64(int(time.time() * 1000) + 3000) block1_cvp = ConditionVarPair(ConditionOpcode.ASSERT_TIME_EXCEEDS, int_to_bytes(current_time_plus3), None) block1_dic = {block1_cvp.opcode: [block1_cvp]} block1_spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block1.get_coinbase(), block1_dic) # program that will be sent to early assert block1_spend_bundle is not None program = best_solution_program(block1_spend_bundle) aggsig = block1_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) # Try to validate that block before 3 sec 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_TIME_EXCEEDS_FAILED # wait 3 sec to pass await asyncio.sleep(3.1) dic_h = {12: (program, aggsig)} valid_new_blocks = bt.get_consecutive_blocks(test_constants, 2, blocks[:11], 10, b"", coinbase_puzzlehash, dic_h) for block in valid_new_blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass # Try to validate that block after 3 sec have passed next_block = valid_new_blocks[12] error = await full_node_1.blockchain._validate_transactions( next_block, next_block.get_fees_coin().amount) assert error is None