예제 #1
0
    def test_policy_before_future(
            self, cluster: clusterlib.ClusterLib,
            issuers_addrs: List[clusterlib.AddressRecord]):
        """Test that it's NOT possible to mint tokens.

        The "before" slot is in the future and the given range is invalid.
        """
        temp_template = helpers.get_func_name()
        rand = clusterlib.get_rand_str(4)
        amount = 5

        token_mint_addr = issuers_addrs[0]
        payment_vkey_files = [p.vkey_file for p in issuers_addrs]

        before_slot = cluster.get_slot_no() + 10_000

        # create multisig script
        multisig_script = cluster.build_multisig_script(
            script_name=temp_template,
            script_type_arg=clusterlib.MultiSigTypeArgs.ALL,
            payment_vkey_files=payment_vkey_files[1:],
            slot=before_slot,
            slot_type_arg=clusterlib.MultiSlotTypeArgs.BEFORE,
        )
        policyid = cluster.get_policyid(multisig_script)

        tokens_to_mint = []
        for tnum in range(5):
            asset_name = f"couttscoin{rand}{tnum}"
            token = f"{policyid}.{asset_name}"

            assert not cluster.get_utxo(token_mint_addr.address, coins=[
                token
            ]), "The token already exists"

            tokens_to_mint.append(
                clusterlib_utils.TokenRecord(
                    token=token,
                    asset_name=asset_name,
                    amount=amount,
                    issuers_addrs=issuers_addrs,
                    token_mint_addr=token_mint_addr,
                    script=multisig_script,
                ))

        # token minting - invalid range, slot is in the future
        with pytest.raises(clusterlib.CLIError) as excinfo:
            _mint_or_burn_witness(
                cluster_obj=cluster,
                new_tokens=tokens_to_mint,
                temp_template=f"{temp_template}_mint",
                invalid_before=1,
                invalid_hereafter=before_slot + 1,
            )
        assert "ScriptWitnessNotValidatingUTXOW" in str(excinfo.value)

        for t in tokens_to_mint:
            token_utxo = cluster.get_utxo(token_mint_addr.address,
                                          coins=[t.token])
            assert not token_utxo, "The token was minted unexpectedly"
예제 #2
0
    def test_address_info_script(self, cluster: clusterlib.ClusterLib):
        """Check script address info."""
        temp_template = helpers.get_func_name()

        # create payment address
        payment_rec = cluster.gen_payment_addr_and_keys(
            name=temp_template,
        )

        # create multisig script
        multisig_script = cluster.build_multisig_script(
            script_name=temp_template,
            script_type_arg=clusterlib.MultiSigTypeArgs.ALL,
            payment_vkey_files=[payment_rec.vkey_file],
            slot=100,
            slot_type_arg=clusterlib.MultiSlotTypeArgs.AFTER,
        )

        # create script address
        address = cluster.gen_script_addr(addr_name=temp_template, script_file=multisig_script)

        addr_info = cluster.address_info(address=address)

        assert addr_info.address == address
        assert addr_info.era == "shelley"
        assert addr_info.encoding == "bech32"
        assert addr_info.type == "payment"
예제 #3
0
    def test_after_past(self, cluster: clusterlib.ClusterLib,
                        payment_addrs: List[clusterlib.AddressRecord]):
        """Check that it's NOT possible to spend from the script address.

        The "after" slot is in the past.
        """
        temp_template = helpers.get_func_name()

        payment_vkey_files = [p.vkey_file for p in payment_addrs]
        payment_skey_files = [p.skey_file for p in payment_addrs]

        after_slot = cluster.get_slot_no() - 1

        # create multisig script
        multisig_script = cluster.build_multisig_script(
            script_name=temp_template,
            script_type_arg=clusterlib.MultiSigTypeArgs.ALL,
            payment_vkey_files=payment_vkey_files,
            slot=after_slot,
            slot_type_arg=clusterlib.MultiSlotTypeArgs.AFTER,
        )

        # create script address
        script_address = cluster.gen_script_addr(addr_name=temp_template,
                                                 script_file=multisig_script)

        # send funds to script address
        multisig_tx(
            cluster_obj=cluster,
            temp_template=f"{temp_template}_to",
            src_address=payment_addrs[0].address,
            dst_address=script_address,
            amount=500_000,
            multisig_script=multisig_script,
            payment_skey_files=[payment_skey_files[0]],
        )

        # send funds from script address - valid slot,
        # invalid range - `invalid_hereafter` is in the past
        with pytest.raises(clusterlib.CLIError) as excinfo:
            multisig_tx(
                cluster_obj=cluster,
                temp_template=f"{temp_template}_from",
                src_address=script_address,
                dst_address=payment_addrs[0].address,
                amount=10,
                multisig_script=multisig_script,
                payment_skey_files=payment_skey_files,
                invalid_before=1,
                invalid_hereafter=after_slot,
                script_is_src=True,
            )
        assert "ScriptWitnessNotValidatingUTXOW" in str(excinfo.value)
예제 #4
0
    def test_multisig_atleast_low_num_of_skeys(
            self, cluster: clusterlib.ClusterLib,
            payment_addrs: List[clusterlib.AddressRecord]):
        """Try to send funds from script address using the *atLeast* script.

        Num of skeys < required. Expect failure.
        """
        temp_template = helpers.get_func_name()

        payment_vkey_files = [p.vkey_file for p in payment_addrs]
        payment_skey_files = [p.skey_file for p in payment_addrs]

        skeys_len = len(payment_skey_files)
        required = skeys_len - 4

        # create multisig script
        multisig_script = cluster.build_multisig_script(
            script_name=temp_template,
            script_type_arg=clusterlib.MultiSigTypeArgs.AT_LEAST,
            payment_vkey_files=payment_vkey_files,
            required=required,
        )

        # create script address
        script_address = cluster.gen_script_addr(addr_name=temp_template,
                                                 script_file=multisig_script)

        # send funds to script address
        multisig_tx(
            cluster_obj=cluster,
            temp_template=temp_template,
            src_address=payment_addrs[0].address,
            dst_address=script_address,
            amount=300_000,
            multisig_script=multisig_script,
            payment_skey_files=[payment_skey_files[0]],
        )

        # send funds from script address, use lower number of skeys then required
        for num_of_skeys in range(required):
            with pytest.raises(clusterlib.CLIError) as excinfo:
                multisig_tx(
                    cluster_obj=cluster,
                    temp_template=temp_template,
                    src_address=script_address,
                    dst_address=payment_addrs[0].address,
                    amount=1000,
                    multisig_script=multisig_script,
                    payment_skey_files=random.sample(payment_skey_files,
                                                     k=num_of_skeys),
                    script_is_src=True,
                )
            assert "ScriptWitnessNotValidatingUTXOW" in str(excinfo.value)
예제 #5
0
    def test_normal_tx_to_script_addr(
            self, cluster: clusterlib.ClusterLib,
            payment_addrs: List[clusterlib.AddressRecord]):
        """Send funds to script address using TX signed with skeys (not using witness files)."""
        temp_template = helpers.get_func_name()
        src_address = payment_addrs[0].address
        amount = 1000

        # create multisig script
        multisig_script = cluster.build_multisig_script(
            script_name=temp_template,
            script_type_arg=clusterlib.MultiSigTypeArgs.ALL,
            payment_vkey_files=[p.vkey_file for p in payment_addrs],
        )

        # create script address
        script_address = cluster.gen_script_addr(addr_name=temp_template,
                                                 script_file=multisig_script)

        # record initial balances
        src_init_balance = cluster.get_address_balance(src_address)
        dst_init_balance = cluster.get_address_balance(script_address)

        # send funds to script address
        destinations = [
            clusterlib.TxOut(address=script_address, amount=amount)
        ]
        tx_files = clusterlib.TxFiles(
            signing_key_files=[payment_addrs[0].skey_file])

        tx_raw_output = cluster.send_funds(
            src_address=src_address,
            tx_name=temp_template,
            destinations=destinations,
            tx_files=tx_files,
        )
        cluster.wait_for_new_block(new_blocks=2)

        # check final balances
        assert (
            cluster.get_address_balance(src_address) == src_init_balance -
            tx_raw_output.fee -
            amount), f"Incorrect balance for source address `{src_address}`"

        assert (
            cluster.get_address_balance(script_address) == dst_init_balance +
            amount
        ), f"Incorrect balance for destination address `{script_address}`"
예제 #6
0
    def test_multisig_atleast(self, cluster: clusterlib.ClusterLib,
                              payment_addrs: List[clusterlib.AddressRecord]):
        """Send funds to and from script address using the *atLeast* script."""
        temp_template = helpers.get_func_name()

        payment_vkey_files = [p.vkey_file for p in payment_addrs]
        payment_skey_files = [p.skey_file for p in payment_addrs]

        skeys_len = len(payment_skey_files)
        required = skeys_len - 4

        # create multisig script
        multisig_script = cluster.build_multisig_script(
            script_name=temp_template,
            script_type_arg=clusterlib.MultiSigTypeArgs.AT_LEAST,
            payment_vkey_files=payment_vkey_files,
            required=required,
        )

        # create script address
        script_address = cluster.gen_script_addr(addr_name=temp_template,
                                                 script_file=multisig_script)

        # send funds to script address
        multisig_tx(
            cluster_obj=cluster,
            temp_template=f"{temp_template}_to",
            src_address=payment_addrs[0].address,
            dst_address=script_address,
            amount=2_000_000,
            multisig_script=multisig_script,
            payment_skey_files=[payment_skey_files[0]],
        )

        # send funds from script address
        for i in range(5):
            num_of_skeys = random.randrange(required, skeys_len)
            multisig_tx(
                cluster_obj=cluster,
                temp_template=f"{temp_template}_from_{i}",
                src_address=script_address,
                dst_address=payment_addrs[0].address,
                amount=1000,
                multisig_script=multisig_script,
                payment_skey_files=random.sample(payment_skey_files,
                                                 k=num_of_skeys),
                script_is_src=True,
            )
예제 #7
0
    def test_script_before(self, cluster: clusterlib.ClusterLib,
                           payment_addrs: List[clusterlib.AddressRecord]):
        """Check that it is possible to spend from script address before given slot."""
        temp_template = helpers.get_func_name()

        payment_vkey_files = [p.vkey_file for p in payment_addrs]
        payment_skey_files = [p.skey_file for p in payment_addrs]

        before_slot = cluster.get_slot_no() + 10_000

        # create multisig script
        multisig_script = cluster.build_multisig_script(
            script_name=temp_template,
            script_type_arg=clusterlib.MultiSigTypeArgs.ALL,
            payment_vkey_files=payment_vkey_files,
            slot=before_slot,
            slot_type_arg=clusterlib.MultiSlotTypeArgs.BEFORE,
        )

        # create script address
        script_address = cluster.gen_script_addr(addr_name=temp_template,
                                                 script_file=multisig_script)

        # send funds to script address
        multisig_tx(
            cluster_obj=cluster,
            temp_template=f"{temp_template}_to",
            src_address=payment_addrs[0].address,
            dst_address=script_address,
            amount=2_000_000,
            multisig_script=multisig_script,
            payment_skey_files=[payment_skey_files[0]],
        )

        # send funds from script address
        multisig_tx(
            cluster_obj=cluster,
            temp_template=f"{temp_template}_from",
            src_address=script_address,
            dst_address=payment_addrs[0].address,
            amount=1000,
            multisig_script=multisig_script,
            payment_skey_files=payment_skey_files,
            invalid_before=100,
            invalid_hereafter=cluster.get_slot_no() + 1000,
            script_is_src=True,
        )
예제 #8
0
    def test_multisig_any_unlisted_skey(
            self, cluster: clusterlib.ClusterLib,
            payment_addrs: List[clusterlib.AddressRecord]):
        """Try to send funds from script address using the *any* script with unlisted skey.

        Expect failure.
        """
        temp_template = helpers.get_func_name()

        payment_vkey_files = [p.vkey_file for p in payment_addrs[:-1]]
        payment_skey_files = [p.skey_file for p in payment_addrs]

        # create multisig script
        multisig_script = cluster.build_multisig_script(
            script_name=temp_template,
            script_type_arg=clusterlib.MultiSigTypeArgs.ANY,
            payment_vkey_files=payment_vkey_files,
        )

        # create script address
        script_address = cluster.gen_script_addr(addr_name=temp_template,
                                                 script_file=multisig_script)

        # send funds to script address
        multisig_tx(
            cluster_obj=cluster,
            temp_template=temp_template,
            src_address=payment_addrs[0].address,
            dst_address=script_address,
            amount=300_000,
            multisig_script=multisig_script,
            payment_skey_files=[payment_skey_files[0]],
        )

        # send funds from script address, use skey that is not listed in the script
        with pytest.raises(clusterlib.CLIError) as excinfo:
            multisig_tx(
                cluster_obj=cluster,
                temp_template=temp_template,
                src_address=script_address,
                dst_address=payment_addrs[0].address,
                amount=1000,
                multisig_script=multisig_script,
                payment_skey_files=[payment_skey_files[-1]],
                script_is_src=True,
            )
        assert "ScriptWitnessNotValidatingUTXOW" in str(excinfo.value)
예제 #9
0
    def test_multisig_no_required_atleast(
            self, cluster: clusterlib.ClusterLib,
            payment_addrs: List[clusterlib.AddressRecord]):
        """Send funds from script address using the *atLeast* script with no required witnesses."""
        temp_template = helpers.get_func_name()

        payment_vkey_files = [p.vkey_file for p in payment_addrs]
        payment_skey_files = [p.skey_file for p in payment_addrs]

        # create multisig script
        multisig_script = cluster.build_multisig_script(
            script_name=temp_template,
            script_type_arg=clusterlib.MultiSigTypeArgs.AT_LEAST,
            payment_vkey_files=payment_vkey_files,
            required=0,
        )

        # create script address
        script_address = cluster.gen_script_addr(addr_name=temp_template,
                                                 script_file=multisig_script)

        # send funds to script address
        multisig_tx(
            cluster_obj=cluster,
            temp_template=f"{temp_template}_to",
            src_address=payment_addrs[0].address,
            dst_address=script_address,
            amount=2_000_000,
            multisig_script=multisig_script,
            payment_skey_files=[payment_skey_files[0]],
        )

        # send funds from script address
        multisig_tx(
            cluster_obj=cluster,
            temp_template=f"{temp_template}_from",
            src_address=script_address,
            dst_address=payment_addrs[0].address,
            amount=1000,
            multisig_script=multisig_script,
            payment_skey_files=[],
            script_is_src=True,
        )
예제 #10
0
    def test_tx_script_metadata_cbor(
            self, cluster: clusterlib.ClusterLib,
            payment_addrs: List[clusterlib.AddressRecord]):
        """Send transaction with auxiliary script and metadata CBOR.

        Check that the auxiliary script is present in the TX body.
        """
        temp_template = helpers.get_func_name()

        payment_vkey_files = [p.vkey_file for p in payment_addrs]

        # create multisig script
        multisig_script = cluster.build_multisig_script(
            script_name=temp_template,
            script_type_arg=clusterlib.MultiSigTypeArgs.AT_LEAST,
            payment_vkey_files=payment_vkey_files,
            required=2,
            slot=1000,
            slot_type_arg=clusterlib.MultiSlotTypeArgs.BEFORE,
        )

        tx_files = clusterlib.TxFiles(
            signing_key_files=[payment_addrs[0].skey_file],
            metadata_cbor_files=[self.CBOR_METADATA_FILE],
            script_files=[multisig_script],
        )
        tx_raw_output = cluster.send_tx(src_address=payment_addrs[0].address,
                                        tx_name=temp_template,
                                        tx_files=tx_files)
        cluster.wait_for_new_block(new_blocks=2)
        assert tx_raw_output.fee, "Transaction had no fee"

        with open(tx_raw_output.out_file) as body_fp:
            tx_body_json = json.load(body_fp)

        cbor_body = bytes.fromhex(tx_body_json["cborHex"])
        cbor_body_metadata = cbor2.loads(cbor_body)[1]

        cbor_body_script = cbor_body_metadata[1]
        assert cbor_body_script, "Auxiliary script not present"
예제 #11
0
def multisig_script_policyid(
    cluster_manager: cluster_management.ClusterManager,
    cluster: clusterlib.ClusterLib,
    issuers_addrs: List[clusterlib.AddressRecord],
) -> Tuple[Path, str]:
    """Return multisig script and it's PolicyId."""
    with cluster_manager.cache_fixture() as fixture_cache:
        if fixture_cache.value:
            return fixture_cache.value  # type: ignore

    temp_template = "test_native_tokens_multisig"
    payment_vkey_files = [p.vkey_file for p in issuers_addrs]

    # create multisig script
    multisig_script = cluster.build_multisig_script(
        script_name=temp_template,
        script_type_arg=clusterlib.MultiSigTypeArgs.ALL,
        payment_vkey_files=payment_vkey_files[1:],
    )
    policyid = cluster.get_policyid(multisig_script)

    return multisig_script, policyid
예제 #12
0
    def test_script_addr_length(self, cluster: clusterlib.ClusterLib,
                                payment_addrs: List[clusterlib.AddressRecord]):
        """Check that script address length is the same as lenght of other addresses.

        There was an issue that script address was 32 bytes instead of 28 bytes.
        """
        temp_template = helpers.get_func_name()

        payment_vkey_files = [p.vkey_file for p in payment_addrs]

        # create multisig script
        multisig_script = cluster.build_multisig_script(
            script_name=temp_template,
            script_type_arg=clusterlib.MultiSigTypeArgs.ALL,
            payment_vkey_files=payment_vkey_files,
        )

        # create script address
        script_address = cluster.gen_script_addr(addr_name=temp_template,
                                                 script_file=multisig_script)

        # check script address length
        assert len(script_address) == len(payment_addrs[0].address)
예제 #13
0
    def test_valid_policy_before(
            self, cluster: clusterlib.ClusterLib,
            issuers_addrs: List[clusterlib.AddressRecord]):
        """Test minting and burning tokens before given slot."""
        expected_fee = 351093

        temp_template = helpers.get_func_name()
        rand = clusterlib.get_rand_str(4)
        amount = 5

        token_mint_addr = issuers_addrs[0]
        payment_vkey_files = [p.vkey_file for p in issuers_addrs]

        before_slot = cluster.get_slot_no() + 10_000

        # create multisig script
        multisig_script = cluster.build_multisig_script(
            script_name=temp_template,
            script_type_arg=clusterlib.MultiSigTypeArgs.ALL,
            payment_vkey_files=payment_vkey_files[1:],
            slot=before_slot,
            slot_type_arg=clusterlib.MultiSlotTypeArgs.BEFORE,
        )
        policyid = cluster.get_policyid(multisig_script)

        tokens_to_mint = []
        for tnum in range(5):
            asset_name = f"couttscoin{rand}{tnum}"
            token = f"{policyid}.{asset_name}"

            assert not cluster.get_utxo(token_mint_addr.address, coins=[
                token
            ]), "The token already exists"

            tokens_to_mint.append(
                clusterlib_utils.TokenRecord(
                    token=token,
                    asset_name=asset_name,
                    amount=amount,
                    issuers_addrs=issuers_addrs,
                    token_mint_addr=token_mint_addr,
                    script=multisig_script,
                ))

        # token minting
        tx_out_mint = _mint_or_burn_witness(
            cluster_obj=cluster,
            new_tokens=tokens_to_mint,
            temp_template=f"{temp_template}_mint",
            invalid_before=100,
            invalid_hereafter=cluster.get_slot_no() + 1000,
        )

        for t in tokens_to_mint:
            token_utxo = cluster.get_utxo(token_mint_addr.address,
                                          coins=[t.token])
            assert token_utxo and token_utxo[
                0].amount == amount, "The token was not minted"

        # token burning
        tokens_to_burn = [t._replace(amount=-amount) for t in tokens_to_mint]
        tx_out_burn = _mint_or_burn_witness(
            cluster_obj=cluster,
            new_tokens=tokens_to_burn,
            temp_template=f"{temp_template}_burn",
            invalid_before=100,
            invalid_hereafter=cluster.get_slot_no() + 1000,
        )

        for t in tokens_to_burn:
            token_utxo = cluster.get_utxo(token_mint_addr.address,
                                          coins=[t.token])
            assert not token_utxo, "The token was not burnt"

        # check expected fees
        assert helpers.is_in_interval(
            tx_out_mint.fee, expected_fee,
            frac=0.15) and helpers.is_in_interval(
                tx_out_burn.fee, expected_fee,
                frac=0.15), "TX fee doesn't fit the expected interval"
예제 #14
0
    def test_minting_and_partial_burning(
            self, cluster: clusterlib.ClusterLib,
            issuers_addrs: List[clusterlib.AddressRecord]):
        """Test minting and partial burning of tokens."""
        expected_fee = 201141

        temp_template = helpers.get_func_name()
        asset_name = f"couttscoin{clusterlib.get_rand_str(4)}"
        amount = 50

        payment_vkey_files = [p.vkey_file for p in issuers_addrs]
        token_mint_addr = issuers_addrs[0]

        # create multisig script
        multisig_script = cluster.build_multisig_script(
            script_name=temp_template,
            script_type_arg=clusterlib.MultiSigTypeArgs.ALL,
            payment_vkey_files=payment_vkey_files[1:],
        )

        policyid = cluster.get_policyid(multisig_script)
        token = f"{policyid}.{asset_name}"

        assert not cluster.get_utxo(token_mint_addr.address,
                                    coins=[token]), "The token already exists"

        token_mint = clusterlib_utils.TokenRecord(
            token=token,
            asset_name=asset_name,
            amount=amount,
            issuers_addrs=issuers_addrs,
            token_mint_addr=token_mint_addr,
            script=multisig_script,
        )

        # token minting
        tx_out_mint = _mint_or_burn_witness(
            cluster_obj=cluster,
            new_tokens=[token_mint],
            temp_template=f"{temp_template}_mint",
        )

        token_utxo = cluster.get_utxo(token_mint_addr.address, coins=[token])
        assert token_utxo and token_utxo[
            0].amount == amount, "The token was not minted"

        # token burning
        burn_amount = amount - 10
        token_burn = token_mint._replace(amount=-burn_amount)
        _mint_or_burn_witness(
            cluster_obj=cluster,
            new_tokens=[token_burn],
            temp_template=f"{temp_template}_burn",
        )

        token_utxo = cluster.get_utxo(token_mint_addr.address, coins=[token])
        assert (token_utxo and token_utxo[0].amount
                == amount - burn_amount), "The token was not burned"

        # burn the rest of tokens
        final_burn = token_mint._replace(amount=-10)
        _mint_or_burn_witness(
            cluster_obj=cluster,
            new_tokens=[final_burn],
            temp_template=f"{temp_template}_burn",
        )

        # check expected fee
        assert helpers.is_in_interval(
            tx_out_mint.fee, expected_fee,
            frac=0.15), "TX fee doesn't fit the expected interval"
예제 #15
0
    def test_multisig_any(self, cluster: clusterlib.ClusterLib,
                          payment_addrs: List[clusterlib.AddressRecord]):
        """Send funds using the *any* script.

        * send funds to script address
        * send funds from script address using single witness
        * send funds from script address using multiple witnesses
        """
        temp_template = helpers.get_func_name()

        payment_vkey_files = [p.vkey_file for p in payment_addrs]
        payment_skey_files = [p.skey_file for p in payment_addrs]

        skeys_len = len(payment_skey_files)

        # create multisig script
        multisig_script = cluster.build_multisig_script(
            script_name=temp_template,
            script_type_arg=clusterlib.MultiSigTypeArgs.ANY,
            payment_vkey_files=payment_vkey_files,
        )

        # create script address
        script_address = cluster.gen_script_addr(addr_name=temp_template,
                                                 script_file=multisig_script)

        # send funds to script address
        multisig_tx(
            cluster_obj=cluster,
            temp_template=f"{temp_template}_to",
            src_address=payment_addrs[0].address,
            dst_address=script_address,
            amount=5_000_000,
            multisig_script=multisig_script,
            payment_skey_files=[payment_skey_files[0]],
        )

        # send funds from script address using single witness
        for i in range(5):
            multisig_tx(
                cluster_obj=cluster,
                temp_template=f"{temp_template}_from_single_{i}",
                src_address=script_address,
                dst_address=payment_addrs[0].address,
                amount=1000,
                multisig_script=multisig_script,
                payment_skey_files=[
                    payment_skey_files[random.randrange(0, skeys_len)]
                ],
                script_is_src=True,
            )

        # send funds from script address using multiple witnesses
        for i in range(5):
            num_of_skeys = random.randrange(2, skeys_len)
            multisig_tx(
                cluster_obj=cluster,
                temp_template=f"{temp_template}_from_multi_{i}",
                src_address=script_address,
                dst_address=payment_addrs[0].address,
                amount=1000,
                multisig_script=multisig_script,
                payment_skey_files=random.sample(payment_skey_files,
                                                 k=num_of_skeys),
                script_is_src=True,
            )