async def test_assert_fee_condition(self, two_nodes):

        num_blocks = 10
        wallet_a = WALLET_A
        coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0]
        receiver_puzzlehash = BURN_PUZZLE_HASH

        # Farm blocks
        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))

        # Coinbase that gets spent
        block1 = blocks[2]
        spend_coin_block_1 = None
        for coin in list(block1.get_included_reward_coins()):
            if coin.puzzle_hash == coinbase_puzzlehash:
                spend_coin_block_1 = coin

        # This condition requires fee to be 10 mojo
        cvp_fee = ConditionWithArgs(ConditionOpcode.RESERVE_FEE, [int_to_bytes(10)])
        # This spend bundle has 9 mojo as fee
        block1_dic_bad = {cvp_fee.opcode: [cvp_fee]}
        block1_dic_good = {cvp_fee.opcode: [cvp_fee]}
        block1_spend_bundle_bad = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spend_coin_block_1, block1_dic_bad, fee=9
        )
        block1_spend_bundle_good = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spend_coin_block_1, block1_dic_good, fee=10
        )
        log.warning(block1_spend_bundle_good.additions())
        log.warning(f"Spend bundle fees: {block1_spend_bundle_good.fees()}")
        invalid_new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=block1_spend_bundle_bad,
            guarantee_transaction_block=True,
        )

        res, err, _ = await full_node_1.blockchain.receive_block(invalid_new_blocks[-1])
        assert res == ReceiveBlockResult.INVALID_BLOCK
        assert err == Err.RESERVE_FEE_CONDITION_FAILED

        valid_new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=block1_spend_bundle_good,
            guarantee_transaction_block=True,
        )
        res, err, _ = await full_node_1.blockchain.receive_block(valid_new_blocks[-1])
        assert err is None
        assert res == ReceiveBlockResult.NEW_PEAK
    async def test_assert_seconds_absolute(self, two_nodes):

        num_blocks = 10
        wallet_a = WALLET_A
        coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0]
        receiver_puzzlehash = BURN_PUZZLE_HASH

        # Farm blocks
        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))

        # Coinbase that gets spent
        block1 = blocks[2]
        spend_coin_block_1 = None
        for coin in list(block1.get_included_reward_coins()):
            if coin.puzzle_hash == coinbase_puzzlehash:
                spend_coin_block_1 = coin

        # This condition requires block1 coinbase to be spent after 30 seconds from now
        current_time_plus3 = uint64(blocks[-1].foliage_transaction_block.timestamp + 30)
        block1_cvp = ConditionWithArgs(ConditionOpcode.ASSERT_SECONDS_ABSOLUTE, [int_to_bytes(current_time_plus3)])
        block1_dic = {block1_cvp.opcode: [block1_cvp]}
        block1_spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spend_coin_block_1, block1_dic
        )

        # program that will be sent to early
        assert block1_spend_bundle is not None
        invalid_new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=block1_spend_bundle,
            time_per_block=20,
            guarantee_transaction_block=True,
        )

        # Try to validate that block before 30 sec
        res, err, _ = await full_node_1.blockchain.receive_block(invalid_new_blocks[-1])
        assert res == ReceiveBlockResult.INVALID_BLOCK
        assert err == Err.ASSERT_SECONDS_ABSOLUTE_FAILED

        valid_new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=block1_spend_bundle,
            guarantee_transaction_block=True,
            time_per_block=31,
        )
        res, err, _ = await full_node_1.blockchain.receive_block(valid_new_blocks[-1])
        assert err is None
        assert res == ReceiveBlockResult.NEW_PEAK
def add_int_cond(
    conds: Dict[ConditionOpcode, List[ConditionWithArgs]],
    op: ConditionOpcode,
    arg: int,
):
    if op not in conds:
        conds[op] = []
    conds[op].append(ConditionWithArgs(op, [int_to_bytes(arg)]))
示例#4
0
def type_for_atom(atom):
    if len(atom) > 2:
        try:
            v = atom.decode("utf8")
            if all(c in string.printable for c in v):
                return Type.QUOTES
        except UnicodeDecodeError:
            pass
        return Type.HEX
    if int_to_bytes(int_from_bytes(atom)) == atom:
        return Type.INT
    return Type.HEX
示例#5
0
    def generate_unsigned_transaction(
        self,
        amount,
        newpuzzlehash,
        coin: Coin,
        condition_dic: Dict[ConditionOpcode, List[ConditionVarPair]],
        fee: int = 0,
        secretkey=None,
    ):
        spends = []
        spend_value = coin.amount
        puzzle_hash = coin.puzzle_hash
        if secretkey is None:
            pubkey, secretkey = self.get_keys(puzzle_hash)
        else:
            pubkey = secretkey.get_public_key()
        puzzle = puzzle_for_pk(bytes(pubkey))
        if ConditionOpcode.CREATE_COIN not in condition_dic:
            condition_dic[ConditionOpcode.CREATE_COIN] = []

        output = ConditionVarPair(ConditionOpcode.CREATE_COIN, newpuzzlehash,
                                  int_to_bytes(amount))
        condition_dic[output.opcode].append(output)
        amount_total = sum(
            int_from_bytes(cvp.var2)
            for cvp in condition_dic[ConditionOpcode.CREATE_COIN])
        change = spend_value - amount_total - fee
        if change > 0:
            changepuzzlehash = self.get_new_puzzlehash()
            change_output = ConditionVarPair(ConditionOpcode.CREATE_COIN,
                                             changepuzzlehash,
                                             int_to_bytes(change))
            condition_dic[output.opcode].append(change_output)
            solution = self.make_solution(condition_dic)
        else:
            solution = self.make_solution(condition_dic)

        spends.append((puzzle, CoinSolution(coin, solution)))
        return spends
示例#6
0
    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
示例#7
0
    async def test_hints_in_blockchain(self, empty_blockchain):  # noqa: F811
        blockchain: Blockchain = empty_blockchain

        blocks = bt.get_consecutive_blocks(
            5,
            block_list_input=[],
            guarantee_transaction_block=True,
            farmer_reward_puzzle_hash=bt.pool_ph,
            pool_reward_puzzle_hash=bt.pool_ph,
        )
        for block in blocks:
            await blockchain.receive_block(block)

        wt: WalletTool = bt.get_pool_wallet_tool()
        puzzle_hash = 32 * b"\0"
        amount = int_to_bytes(1)
        hint = 32 * b"\5"
        coin_spent = list(blocks[-1].get_included_reward_coins())[0]
        condition_dict = {
            ConditionOpcode.CREATE_COIN: [
                ConditionWithArgs(ConditionOpcode.CREATE_COIN,
                                  [puzzle_hash, amount, hint])
            ]
        }
        tx: SpendBundle = wt.generate_signed_transaction(
            10,
            wt.get_new_puzzlehash(),
            coin_spent,
            condition_dic=condition_dict,
        )

        blocks = bt.get_consecutive_blocks(10,
                                           block_list_input=blocks,
                                           guarantee_transaction_block=True,
                                           transaction_data=tx)

        for block in blocks:
            await blockchain.receive_block(block)

        get_hint = await blockchain.hint_store.get_coin_ids(hint)

        assert get_hint[0] == Coin(coin_spent.name(), puzzle_hash, 1).name()
示例#8
0
def launcher_id_to_p2_puzzle_hash(launcher_id: bytes32, seconds_delay: uint64,
                                  delayed_puzzle_hash: bytes32) -> bytes32:
    return create_p2_singleton_puzzle(SINGLETON_MOD_HASH, launcher_id,
                                      int_to_bytes(seconds_delay),
                                      delayed_puzzle_hash).get_tree_hash()
示例#9
0
def piggybank_announcement_assertion(pb_coin: Coin, contrib_amount: uint64):
    return [
        ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT,
        std_hash(pb_coin.name() +
                 int_to_bytes(pb_coin.amount + contrib_amount))
    ]
示例#10
0
    async def test_subscribe_for_hint_long_sync(self,
                                                wallet_two_node_simulator):
        num_blocks = 4
        full_nodes, wallets = wallet_two_node_simulator
        full_node_api = full_nodes[0]
        full_node_api_1 = full_nodes[1]

        wallet_node, server_2 = wallets[0]
        fn_server = full_node_api.full_node.server
        fn_server_1 = full_node_api_1.full_node.server

        wsm: WalletStateManager = wallet_node.wallet_state_manager

        await server_2.start_client(
            PeerInfo(self_hostname, uint16(fn_server._port)), None)
        incoming_queue, peer_id = await add_dummy_connection(
            fn_server, 12312, NodeType.WALLET)
        incoming_queue_1, peer_id_1 = await add_dummy_connection(
            fn_server_1, 12313, NodeType.WALLET)

        wt: WalletTool = bt.get_pool_wallet_tool()
        ph = wt.get_new_puzzlehash()
        for i in range(0, num_blocks):
            await full_node_api.farm_new_transaction_block(
                FarmNewBlockProtocol(ph))

        await asyncio.sleep(6)
        coins = await full_node_api.full_node.coin_store.get_coin_records_by_puzzle_hashes(
            False, [ph])
        coin_spent = coins[0].coin
        hint_puzzle_hash = 32 * b"\2"
        amount = 1
        amount_bin = int_to_bytes(1)
        hint = 32 * b"\5"

        fake_wallet_peer = fn_server.all_connections[peer_id]
        fake_wallet_peer_1 = fn_server_1.all_connections[peer_id_1]
        msg = wallet_protocol.RegisterForPhUpdates([hint], 0)
        msg_response = await full_node_api.register_interest_in_puzzle_hash(
            msg, fake_wallet_peer)
        msg_response_1 = await full_node_api_1.register_interest_in_puzzle_hash(
            msg, fake_wallet_peer_1)

        assert msg_response.type == ProtocolMessageTypes.respond_to_ph_update.value
        data_response: RespondToPhUpdates = RespondToCoinUpdates.from_bytes(
            msg_response.data)
        assert len(data_response.coin_states) == 0

        condition_dict = {
            ConditionOpcode.CREATE_COIN: [
                ConditionWithArgs(ConditionOpcode.CREATE_COIN,
                                  [hint_puzzle_hash, amount_bin, hint])
            ]
        }
        tx: SpendBundle = wt.generate_signed_transaction(
            10,
            wt.get_new_puzzlehash(),
            coin_spent,
            condition_dic=condition_dict,
        )
        await full_node_api.respond_transaction(RespondTransaction(tx),
                                                fake_wallet_peer)

        await time_out_assert(15, tx_in_pool,
                              True, full_node_api.full_node.mempool_manager,
                              tx.name())

        # Create more blocks than recent "short_sync_blocks_behind_threshold" so that node enters batch
        for i in range(0, 100):
            await full_node_api.farm_new_transaction_block(
                FarmNewBlockProtocol(ph))

        node1_height = full_node_api_1.full_node.blockchain.get_peak_height()
        assert node1_height is None

        await fn_server_1.start_client(
            PeerInfo(self_hostname, uint16(fn_server._port)), None)
        node0_height = full_node_api.full_node.blockchain.get_peak_height()
        await time_out_assert(
            15, full_node_api_1.full_node.blockchain.get_peak_height,
            node0_height)

        all_messages = await self.get_all_messages_in_queue(incoming_queue)
        all_messages_1 = await self.get_all_messages_in_queue(incoming_queue_1)

        def check_messages_for_hint(messages):
            notified_state = None

            for message in messages:
                if message.type == ProtocolMessageTypes.coin_state_update.value:
                    data_response: CoinStateUpdate = CoinStateUpdate.from_bytes(
                        message.data)
                    notified_state = data_response
                    break

            assert notified_state is not None
            assert notified_state.items[0].coin == Coin(
                coin_spent.name(), hint_puzzle_hash, amount)

        check_messages_for_hint(all_messages)
        check_messages_for_hint(all_messages_1)
def get_name_puzzle_conditions(generator: BlockGenerator,
                               max_cost: int,
                               *,
                               cost_per_byte: int,
                               mempool_mode: bool,
                               height: Optional[uint32] = None) -> NPCResult:
    block_program, block_program_args = setup_generator_args(generator)
    size_cost = len(bytes(generator.program)) * cost_per_byte
    max_cost -= size_cost
    if max_cost < 0:
        return NPCResult(uint16(Err.INVALID_BLOCK_COST.value), [], uint64(0))

    # in mempool mode, the height doesn't matter, because it's always strict.
    # But otherwise, height must be specified to know which rules to apply
    assert mempool_mode or height is not None

    # mempool mode also has these rules apply
    assert (MEMPOOL_MODE & COND_CANON_INTS) != 0
    assert (MEMPOOL_MODE & NO_NEG_DIV) != 0

    if mempool_mode:
        flags = MEMPOOL_MODE
    elif unwrap(height) >= DEFAULT_CONSTANTS.SOFT_FORK_HEIGHT:
        # conditions must use integers in canonical encoding (i.e. no redundant
        # leading zeros)
        # the division operator may not be used with negative operands
        flags = COND_CANON_INTS | NO_NEG_DIV
    else:
        flags = 0

    try:
        err, result = GENERATOR_MOD.run_as_generator(max_cost, flags,
                                                     block_program,
                                                     block_program_args)

        if err is not None:
            assert err != 0
            return NPCResult(uint16(err), [], uint64(0))

        first = True
        npc_list = []
        for r in result.spends:
            conditions: Dict[ConditionOpcode, List[ConditionWithArgs]] = {}
            if r.height_relative is not None:
                add_int_cond(conditions,
                             ConditionOpcode.ASSERT_HEIGHT_RELATIVE,
                             r.height_relative)
            if r.seconds_relative > 0:
                add_int_cond(conditions,
                             ConditionOpcode.ASSERT_SECONDS_RELATIVE,
                             r.seconds_relative)
            for cc in r.create_coin:
                if cc[2] == b"":
                    add_cond(conditions, ConditionOpcode.CREATE_COIN,
                             [cc[0], int_to_bytes(cc[1])])
                else:
                    add_cond(conditions, ConditionOpcode.CREATE_COIN,
                             [cc[0], int_to_bytes(cc[1]), cc[2]])
            for sig in r.agg_sig_me:
                add_cond(conditions, ConditionOpcode.AGG_SIG_ME,
                         [sig[0], sig[1]])

            # all conditions that aren't tied to a specific spent coin, we roll into the first one
            if first:
                first = False
                if result.reserve_fee > 0:
                    add_int_cond(conditions, ConditionOpcode.RESERVE_FEE,
                                 result.reserve_fee)
                if result.height_absolute > 0:
                    add_int_cond(conditions,
                                 ConditionOpcode.ASSERT_HEIGHT_ABSOLUTE,
                                 result.height_absolute)
                if result.seconds_absolute > 0:
                    add_int_cond(conditions,
                                 ConditionOpcode.ASSERT_SECONDS_ABSOLUTE,
                                 result.seconds_absolute)
                for sig in result.agg_sig_unsafe:
                    add_cond(conditions, ConditionOpcode.AGG_SIG_UNSAFE,
                             [sig[0], sig[1]])

            npc_list.append(
                NPC(r.coin_id, r.puzzle_hash,
                    [(op, cond) for op, cond in conditions.items()]))

        return NPCResult(None, npc_list, uint64(result.cost + size_cost))

    except BaseException as e:
        log.debug(f"get_name_puzzle_condition failed: {e}")
        return NPCResult(uint16(Err.GENERATOR_RUNTIME_ERROR.value), [],
                         uint64(0))
示例#12
0
 def __bytes__(self):
     return self.parent_coin_info + self.puzzle_hash + int_to_bytes(self.amount)
示例#13
0
    async def test_everything_with_signature(self, setup_sim):
        sim, sim_client = setup_sim

        try:
            sk = PrivateKey.from_bytes(secret_exponent_for_index(1).to_bytes(32, "big"))
            tail: Program = EverythingWithSig.construct([Program.to(sk.get_g1())])
            checker_solution: Program = EverythingWithSig.solve([], {})
            cat_puzzle: Program = construct_cat_puzzle(CAT_MOD, tail.get_tree_hash(), acs)
            cat_ph: bytes32 = cat_puzzle.get_tree_hash()
            await sim.farm_block(cat_ph)

            # Test eve spend
            # We don't sign any message data because CLVM 0 translates to b'' apparently
            starting_coin: Coin = (await sim_client.get_coin_records_by_puzzle_hash(cat_ph))[0].coin
            signature: G2Element = AugSchemeMPL.sign(
                sk, (starting_coin.name() + sim.defaults.AGG_SIG_ME_ADDITIONAL_DATA)
            )

            await self.do_spend(
                sim,
                sim_client,
                tail,
                [starting_coin],
                [NO_LINEAGE_PROOF],
                [
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), starting_coin.amount],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    )
                ],
                (MempoolInclusionStatus.SUCCESS, None),
                limitations_solutions=[checker_solution],
                signatures=[signature],
                cost_str="Signature Issuance",
            )

            # Test melting value
            coin: Coin = (await sim_client.get_coin_records_by_puzzle_hash(cat_ph, include_spent_coins=False))[0].coin
            signature = AugSchemeMPL.sign(
                sk, (int_to_bytes(-1) + coin.name() + sim.defaults.AGG_SIG_ME_ADDITIONAL_DATA)
            )

            await self.do_spend(
                sim,
                sim_client,
                tail,
                [coin],
                [NO_LINEAGE_PROOF],
                [
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), coin.amount - 1],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    )
                ],
                (MempoolInclusionStatus.SUCCESS, None),
                extra_deltas=[-1],
                limitations_solutions=[checker_solution],
                signatures=[signature],
                cost_str="Signature Melt",
            )

            # Test minting value
            coin = (await sim_client.get_coin_records_by_puzzle_hash(cat_ph, include_spent_coins=False))[0].coin
            signature = AugSchemeMPL.sign(sk, (int_to_bytes(1) + coin.name() + sim.defaults.AGG_SIG_ME_ADDITIONAL_DATA))

            # Need something to fund the minting
            temp_p = Program.to(1)
            temp_ph: bytes32 = temp_p.get_tree_hash()
            await sim.farm_block(temp_ph)
            acs_coin: Coin = (await sim_client.get_coin_records_by_puzzle_hash(temp_ph, include_spent_coins=False))[
                0
            ].coin
            acs_bundle = SpendBundle(
                [
                    CoinSpend(
                        acs_coin,
                        temp_p,
                        Program.to([]),
                    )
                ],
                G2Element(),
            )

            await self.do_spend(
                sim,
                sim_client,
                tail,
                [coin],
                [NO_LINEAGE_PROOF],
                [
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), coin.amount + 1],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    )
                ],
                (MempoolInclusionStatus.SUCCESS, None),
                extra_deltas=[1],
                limitations_solutions=[checker_solution],
                signatures=[signature],
                additional_spends=[acs_bundle],
                cost_str="Signature Mint",
            )

        finally:
            await sim.close()
    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.header.data.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.header.data.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.header.data.fees_coin.amount
        )

        assert error is None
示例#15
0
 def to_atom(class_, v):
     if isinstance(v, int):
         v = int_to_bytes(v)
     return v
示例#16
0
 def __bytes__(self):
     f = io.BytesIO()
     f.write(self.parent_coin_info)
     f.write(self.puzzle_hash)
     f.write(int_to_bytes(self.amount))
     return f.getvalue()
示例#17
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.header.data.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.header.data.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.header.data.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
示例#18
0
    async def test_assert_block_age_exceeds(self, two_nodes):
        num_blocks = 11
        wallet_a = WALLET_A
        coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0]
        receiver_puzzlehash = BURN_PUZZLE_HASH

        # Farm blocks
        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))

        # Coinbase that gets spent
        block1 = blocks[2]
        spend_coin_block_1 = None
        for coin in list(block1.get_included_reward_coins()):
            if coin.puzzle_hash == coinbase_puzzlehash:
                spend_coin_block_1 = coin

        # This condition requires block1 coinbase to be spent after index 11
        # This condition requires block1 coinbase to be spent more than 10 block after it was farmed
        # block index has to be greater than (2 + 9 = 11)
        block1_cvp = ConditionWithArgs(
            ConditionOpcode.ASSERT_HEIGHT_AGE_EXCEEDS, [int_to_bytes(9)])
        block1_dic = {block1_cvp.opcode: [block1_cvp]}
        block1_spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spend_coin_block_1, block1_dic)

        # program that will be sent too early
        assert block1_spend_bundle is not None
        invalid_new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=block1_spend_bundle,
            guarantee_transaction_block=True,
        )

        # Try to validate that block at index 11
        res, err, _ = await full_node_1.blockchain.receive_block(
            invalid_new_blocks[-1])
        assert res == ReceiveBlockResult.INVALID_BLOCK
        assert err == Err.ASSERT_HEIGHT_AGE_EXCEEDS_FAILED

        new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            guarantee_transaction_block=True,
        )
        res, _, _ = await full_node_1.blockchain.receive_block(new_blocks[-1])
        assert res == ReceiveBlockResult.NEW_PEAK

        # At index 12, it can be spent
        new_blocks = bt.get_consecutive_blocks(
            1,
            new_blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=block1_spend_bundle,
            guarantee_transaction_block=True,
        )
        res, err, _ = await full_node_1.blockchain.receive_block(new_blocks[-1]
                                                                 )
        assert err is None
        assert res == ReceiveBlockResult.NEW_PEAK
    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.header.data.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.header.data.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.header.data.fees_coin.amount
        )

        assert error is None