def test_verify_challenge_transaction_signers_raise_no_signers(self):
        server_kp = Keypair.random()
        client_kp_a = Keypair.random()
        client_kp_b = Keypair.random()
        client_kp_c = Keypair.random()
        timeout = 600
        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
        anchor_name = "SDF"

        challenge = build_challenge_transaction(
            server_secret=server_kp.secret,
            client_account_id=client_kp_a.public_key,
            anchor_name=anchor_name,
            network_passphrase=network_passphrase,
            timeout=timeout,
        )

        transaction = TransactionEnvelope.from_xdr(challenge,
                                                   network_passphrase)
        transaction.sign(client_kp_a)
        transaction.sign(client_kp_b)
        transaction.sign(client_kp_c)

        challenge_tx = transaction.to_xdr()
        signers = []

        with pytest.raises(InvalidSep10ChallengeError,
                           match="No signers provided."):
            verify_challenge_transaction_signers(challenge_tx,
                                                 server_kp.public_key,
                                                 network_passphrase, signers)
    def test_verify_challenge_tx_transaction_is_not_signed_by_the_server(self):
        server_kp = Keypair.random()
        client_kp = Keypair.random()
        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
        anchor_name = "SDF"
        timeout = 900

        now = int(time.time())
        server_keypair = Keypair.from_secret(server_kp.secret)
        server_account = Account(account_id=server_keypair.public_key,
                                 sequence=-1)
        transaction_builder = TransactionBuilder(server_account,
                                                 network_passphrase, 100)
        transaction_builder.add_time_bounds(min_time=now,
                                            max_time=now + timeout)
        nonce = os.urandom(48)
        nonce_encoded = base64.b64encode(nonce)
        transaction_builder.append_manage_data_op(
            data_name="{} auth".format(anchor_name),
            data_value=nonce_encoded,
            source=client_kp.public_key,
        )
        challenge = transaction_builder.build().to_xdr()

        transaction = TransactionEnvelope.from_xdr(challenge,
                                                   network_passphrase)
        transaction.sign(client_kp)
        challenge_tx = transaction.to_xdr()
        with pytest.raises(
                InvalidSep10ChallengeError,
                match="Transaction not signed by server: {}".format(
                    server_kp.public_key),
        ):
            verify_challenge_transaction(challenge_tx, server_kp.public_key,
                                         network_passphrase)
    def test_verify_challenge_transaction_signed_by_client_raise_not_signed(
            self):
        server_kp = Keypair.random()
        client_kp = Keypair.random()
        timeout = 600
        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
        anchor_name = "SDF"

        challenge = build_challenge_transaction(
            server_secret=server_kp.secret,
            client_account_id=client_kp.public_key,
            anchor_name=anchor_name,
            network_passphrase=network_passphrase,
            timeout=timeout,
        )

        transaction = TransactionEnvelope.from_xdr(challenge,
                                                   network_passphrase)
        challenge_tx = transaction.to_xdr()

        with pytest.raises(
                InvalidSep10ChallengeError,
                match="Transaction not signed by client: {}.".format(
                    client_kp.public_key),
        ):
            verify_challenge_transaction_signed_by_client_master_key(
                challenge_tx, server_kp.public_key, network_passphrase)
    def test_verify_challenge_tx_sequence_not_zero(self):
        server_kp = Keypair.random()
        client_kp = Keypair.random()
        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
        anchor_name = "SDF"
        now = int(time.time())
        nonce = os.urandom(48)
        nonce_encoded = base64.b64encode(nonce)
        server_account = Account(server_kp.public_key, 10086)
        challenge_te = (TransactionBuilder(
            server_account, network_passphrase, 100).append_manage_data_op(
                data_name="{} auth".format(anchor_name),
                data_value=nonce_encoded,
                source=client_kp.public_key,
            ).add_time_bounds(now, now + 900).build())

        challenge_te.sign(server_kp)
        challenge_te.sign(client_kp)
        challenge_tx_signed = challenge_te.to_xdr()

        with pytest.raises(
                InvalidSep10ChallengeError,
                match="The transaction sequence number should be zero.",
        ):
            verify_challenge_transaction(challenge_tx_signed,
                                         server_kp.public_key,
                                         network_passphrase)
    def test_verify_challenge_tx_source_is_different_to_server_account_id(
            self):
        server_kp = Keypair.random()
        client_kp = Keypair.random()
        network_passphrase = Network.TESTNET_NETWORK_PASSPHRASE
        anchor_name = "SDF"

        challenge = build_challenge_transaction(server_kp.secret,
                                                client_kp.public_key,
                                                anchor_name,
                                                network_passphrase)

        transaction = TransactionEnvelope.from_xdr(challenge,
                                                   network_passphrase)
        transaction.sign(client_kp)

        challenge_tx = transaction.to_xdr()
        with pytest.raises(
                InvalidSep10ChallengeError,
                match=
                "Transaction source account is not equal to server's account.",
        ):
            verify_challenge_transaction(challenge_tx,
                                         Keypair.random().public_key,
                                         network_passphrase)
    def test_verify_challenge_tx_not_within_range_of_the_specified_timebounds(
            self):
        server_kp = Keypair.random()
        client_kp = Keypair.random()
        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
        anchor_name = "SDF"
        now = int(time.time())
        nonce = os.urandom(48)
        nonce_encoded = base64.b64encode(nonce)
        server_account = Account(server_kp.public_key, -1)
        challenge_te = (TransactionBuilder(
            server_account, network_passphrase, 100).append_manage_data_op(
                data_name="{} auth".format(anchor_name),
                data_value=nonce_encoded,
                source=client_kp.public_key,
            ).add_time_bounds(now - 100, now - 50).build())

        challenge_te.sign(server_kp)
        challenge_te.sign(client_kp)
        challenge_tx_signed = challenge_te.to_xdr()

        with pytest.raises(
                InvalidSep10ChallengeError,
                match=
                "Transaction is not within range of the specified timebounds.",
        ):
            verify_challenge_transaction(challenge_tx_signed,
                                         server_kp.public_key,
                                         network_passphrase)
    def test_verify_transaction_signatures(self):
        server_kp = Keypair.random()
        client_kp_a = Keypair.random()
        client_kp_b = Keypair.random()
        client_kp_c = Keypair.random()
        timeout = 600
        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
        anchor_name = "SDF"

        challenge = build_challenge_transaction(
            server_secret=server_kp.secret,
            client_account_id=client_kp_a.public_key,
            anchor_name=anchor_name,
            network_passphrase=network_passphrase,
            timeout=timeout,
        )

        transaction = TransactionEnvelope.from_xdr(challenge,
                                                   network_passphrase)
        transaction.sign(client_kp_a)
        transaction.sign(client_kp_b)
        transaction.sign(client_kp_c)
        signers = [
            Ed25519PublicKeySigner(client_kp_a.public_key, 1),
            Ed25519PublicKeySigner(client_kp_b.public_key, 2),
            Ed25519PublicKeySigner(client_kp_c.public_key, 3),
            Ed25519PublicKeySigner(Keypair.random().public_key, 4),
        ]
        signers_found = _verify_transaction_signatures(transaction, signers)
        assert signers_found == [
            Ed25519PublicKeySigner(client_kp_a.public_key, 1),
            Ed25519PublicKeySigner(client_kp_b.public_key, 2),
            Ed25519PublicKeySigner(client_kp_c.public_key, 3),
        ]
    def test_challenge_transaction(self):
        server_kp = Keypair.random()
        client_account_id = "GBDIT5GUJ7R5BXO3GJHFXJ6AZ5UQK6MNOIDMPQUSMXLIHTUNR2Q5CFNF"
        timeout = 600
        network_passphrase = Network.TESTNET_NETWORK_PASSPHRASE
        anchor_name = "SDF"

        challenge = build_challenge_transaction(
            server_secret=server_kp.secret,
            client_account_id=client_account_id,
            anchor_name=anchor_name,
            network_passphrase=network_passphrase,
            timeout=timeout,
        )

        transaction = TransactionEnvelope.from_xdr(
            challenge, network_passphrase).transaction
        assert len(transaction.operations) == 1
        op = transaction.operations[0]
        assert isinstance(op, ManageData)
        assert op.data_name == "SDF auth"
        assert len(op.data_value) == 64
        assert len(base64.b64decode(op.data_value)) == 48
        assert op.source == client_account_id

        now = int(time.time())
        assert now - 3 < transaction.time_bounds.min_time < now + 3
        assert (transaction.time_bounds.max_time -
                transaction.time_bounds.min_time == timeout)
        assert transaction.source.public_key == server_kp.public_key
        assert transaction.sequence == 0
Exemplo n.º 9
0
    def test_to_xdr_str_source(self):
        source = "GCEZWKCA5VLDNRLN3RPRJMRZOX3Z6G5CHCGSNFHEYVXM3XOJMDS674JZ"
        destination = "GDJJRRMBK4IWLEPJGIE6SXD2LP7REGZODU7WDC3I2D6MR37F4XSHBKX2"
        amount = "1000.0"
        sequence = 1
        memo = IdMemo(100)
        fee = 200
        asset = Asset.native()
        time_bounds = TimeBounds(12345, 56789)
        ops = [Payment(destination, asset, amount), ManageData("hello", "world")]

        tx_object = Transaction(
            source, sequence, fee, ops, memo, time_bounds
        ).to_xdr_object()
        assert (
            tx_object.to_xdr()
            == "AAAAAImbKEDtVjbFbdxfFLI5dfefG6I4jSaU5MVuzd3JYOXvAAAAyAAAAAAAAAABAAAAAQAAAAAAADA5AAAAAAAA3dUAAAACAAAAAAAAAGQAAAACAAAAAAAAAAEAAAAA0pjFgVcRZZHpMgnpXHpb/xIbLh0/YYto0PzI7+Xl5HAAAAAAAAAAAlQL5AAAAAAAAAAACgAAAAVoZWxsbwAAAAAAAAEAAAAFd29ybGQAAAAAAAAA"
        )

        restore_transaction = Transaction.from_xdr_object(tx_object)
        assert isinstance(restore_transaction, Transaction)
        assert restore_transaction.source == Keypair.from_public_key(source)
        assert restore_transaction.fee == fee
        assert restore_transaction.memo == memo
        assert restore_transaction.time_bounds == time_bounds
        assert restore_transaction.sequence == sequence
    def test_verify_challenge_transaction_threshold_raise_not_meet_threshold(
            self):
        server_kp = Keypair.random()
        client_kp_a = Keypair.random()
        client_kp_b = Keypair.random()
        client_kp_c = Keypair.random()
        timeout = 600
        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
        anchor_name = "SDF"

        challenge = build_challenge_transaction(
            server_secret=server_kp.secret,
            client_account_id=client_kp_a.public_key,
            anchor_name=anchor_name,
            network_passphrase=network_passphrase,
            timeout=timeout,
        )

        transaction = TransactionEnvelope.from_xdr(challenge,
                                                   network_passphrase)
        transaction.sign(client_kp_a)
        transaction.sign(client_kp_b)
        transaction.sign(client_kp_c)

        challenge_tx = transaction.to_xdr()
        signers = [
            Ed25519PublicKeySigner(client_kp_a.public_key, 1),
            Ed25519PublicKeySigner(client_kp_b.public_key, 2),
            Ed25519PublicKeySigner(client_kp_c.public_key, 4),
            Ed25519PublicKeySigner(Keypair.random().public_key, 255),
        ]
        med_threshold = 10
        with pytest.raises(
                InvalidSep10ChallengeError,
                match="signers with weight 7 do not meet threshold 10.",
        ):
            verify_challenge_transaction_threshold(
                challenge_tx,
                server_kp.public_key,
                network_passphrase,
                med_threshold,
                signers,
            )
    def test_verify_challenge_tx_donot_contain_managedata_operation(self):
        server_kp = Keypair.random()
        client_kp = Keypair.random()
        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
        now = int(time.time())
        server_account = Account(server_kp.public_key, -1)
        challenge_te = (TransactionBuilder(
            server_account, network_passphrase,
            100).append_set_options_op().add_time_bounds(now,
                                                         now + 900).build())

        challenge_te.sign(server_kp)
        challenge_te.sign(client_kp)
        challenge_tx_signed = challenge_te.to_xdr()

        with pytest.raises(InvalidSep10ChallengeError,
                           match="Operation type should be ManageData."):
            verify_challenge_transaction(challenge_tx_signed,
                                         server_kp.public_key,
                                         network_passphrase)
    def test_verify_transaction_signatures_raise_no_signature(self):
        server_kp = Keypair.random()
        client_kp = Keypair.random()
        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
        anchor_name = "SDF"
        now = int(time.time())
        nonce = os.urandom(48)
        nonce_encoded = base64.b64encode(nonce)
        server_account = Account(server_kp.public_key, -1)
        challenge_te = (TransactionBuilder(
            server_account, network_passphrase, 100).append_manage_data_op(
                data_name="{} auth".format(anchor_name),
                data_value=nonce_encoded,
                source=client_kp.public_key,
            ).add_time_bounds(now, now + 900).build())

        signers = []
        with pytest.raises(InvalidSep10ChallengeError,
                           match="Transaction has no signatures."):
            _verify_transaction_signatures(challenge_te, signers)
    def test_verify_challenge_transaction(self):
        server_kp = Keypair.random()
        client_kp = Keypair.random()
        timeout = 600
        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
        anchor_name = "SDF"

        challenge = build_challenge_transaction(
            server_secret=server_kp.secret,
            client_account_id=client_kp.public_key,
            anchor_name=anchor_name,
            network_passphrase=network_passphrase,
            timeout=timeout,
        )

        transaction = TransactionEnvelope.from_xdr(challenge,
                                                   network_passphrase)
        transaction.sign(client_kp)
        challenge_tx = transaction.to_xdr()
        verify_challenge_transaction(challenge_tx, server_kp.public_key,
                                     network_passphrase)
    def test_verify_challenge_transaction_signers_raise_no_server_signature(
            self):
        server_kp = Keypair.random()
        client_kp_a = Keypair.random()
        client_kp_b = Keypair.random()
        client_kp_c = Keypair.random()
        timeout = 600
        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
        anchor_name = "SDF"

        challenge = build_challenge_transaction(
            server_secret=server_kp.secret,
            client_account_id=client_kp_a.public_key,
            anchor_name=anchor_name,
            network_passphrase=network_passphrase,
            timeout=timeout,
        )

        transaction = TransactionEnvelope.from_xdr(challenge,
                                                   network_passphrase)
        transaction.signatures = []
        transaction.sign(client_kp_a)
        transaction.sign(client_kp_b)
        transaction.sign(client_kp_c)

        challenge_tx = transaction.to_xdr()
        signers = [
            Ed25519PublicKeySigner(client_kp_a.public_key, 1),
            Ed25519PublicKeySigner(client_kp_b.public_key, 2),
            Ed25519PublicKeySigner(client_kp_c.public_key, 4),
            Ed25519PublicKeySigner(Keypair.random().public_key, 255),
        ]
        with pytest.raises(
                InvalidSep10ChallengeError,
                match="Transaction not signed by server: {}.".format(
                    server_kp.public_key),
        ):
            verify_challenge_transaction_signers(challenge_tx,
                                                 server_kp.public_key,
                                                 network_passphrase, signers)
Exemplo n.º 15
0
    def test_none_memo(self):
        source = Keypair.from_public_key(
            "GCEZWKCA5VLDNRLN3RPRJMRZOX3Z6G5CHCGSNFHEYVXM3XOJMDS674JZ"
        )
        destination = "GDJJRRMBK4IWLEPJGIE6SXD2LP7REGZODU7WDC3I2D6MR37F4XSHBKX2"
        amount = "1000.0"
        sequence = 1
        fee = 200
        asset = Asset.native()
        ops = [Payment(destination, asset, amount), ManageData("hello", "world")]

        tx = Transaction(source, sequence, fee, ops)
        assert tx.memo == NoneMemo()
    def test_verify_challenge_tx_dont_contains_timebound(self):
        server_kp = Keypair.random()
        client_kp = Keypair.random()
        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
        anchor_name = "SDF"
        nonce = os.urandom(48)
        nonce_encoded = base64.b64encode(nonce)
        server_account = Account(server_kp.public_key, -1)
        challenge_te = (TransactionBuilder(
            server_account, network_passphrase, 100).append_manage_data_op(
                data_name="{} auth".format(anchor_name),
                data_value=nonce_encoded,
                source=client_kp.public_key,
            ).build())

        challenge_te.sign(server_kp)
        challenge_te.sign(client_kp)
        challenge_tx_signed = challenge_te.to_xdr()

        with pytest.raises(InvalidSep10ChallengeError,
                           match="Transaction requires timebounds."):
            verify_challenge_transaction(challenge_tx_signed,
                                         server_kp.public_key,
                                         network_passphrase)
    def test_verify_challenge_tx_transaction_is_not_signed_by_the_client(self):
        server_kp = Keypair.random()
        client_account_id = "GBDIT5GUJ7R5BXO3GJHFXJ6AZ5UQK6MNOIDMPQUSMXLIHTUNR2Q5CFNF"
        timeout = 600
        network_passphrase = Network.TESTNET_NETWORK_PASSPHRASE
        anchor_name = "SDF"

        challenge = build_challenge_transaction(
            server_secret=server_kp.secret,
            client_account_id=client_account_id,
            anchor_name=anchor_name,
            network_passphrase=network_passphrase,
            timeout=timeout,
        )

        with pytest.raises(
                InvalidSep10ChallengeError,
                match="Transaction not signed by client: {}".format(
                    client_account_id),
        ):
            verify_challenge_transaction(challenge, server_kp.public_key,
                                         network_passphrase)
Exemplo n.º 18
0
    def test_to_xdr(self):
        sequence = 1
        source = Account(
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM", sequence
        )
        builder = TransactionBuilder(
            source, Network.TESTNET_NETWORK_PASSPHRASE, base_fee=150
        )
        builder.add_text_memo("Paydex Python SDK")
        builder.add_time_bounds(1565590000, 1565600000)
        te = (
            builder.append_create_account_op(
                "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                "5.5",
                "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            )
            .append_change_trust_op(
                "XCN",
                "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
                "100000",
            )
            .append_payment_op(
                "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
                "12.25",
                "PAYDEX",
            )
            .append_path_payment_op(
                "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
                "PAYDEX",
                None,
                "100",
                "XCN",
                "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
                "1000.5",
                [
                    Asset(
                        "USD",
                        "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                    ),
                    Asset(
                        "BTC",
                        "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                    ),
                ],
            )
            .append_path_payment_strict_receive_op(
                "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
                "PAYDEX",
                None,
                "100",
                "XCN",
                "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
                "1000.5",
                [
                    Asset(
                        "USD",
                        "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                    ),
                    Asset(
                        "BTC",
                        "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                    ),
                ],
            )
            .append_path_payment_strict_send_op(
                "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
                "PAYDEX",
                None,
                "100",
                "XCN",
                "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
                "1000.5",
                [
                    Asset(
                        "USD",
                        "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                    ),
                    Asset(
                        "BTC",
                        "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                    ),
                ],
            )
            .append_allow_trust_op(
                "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6", "XCN", True
            )
            .append_set_options_op(
                "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
                1,
                6,
                20,
                20,
                20,
                20,
                "paydexcn.org",
                Signer.ed25519_public_key(
                    "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF", 10
                ),
                "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            )
            .append_ed25519_public_key_signer(
                "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD", 5
            )
            .append_hashx_signer(
                bytes.fromhex(
                    "3389e9f0f1a65f19736cacf544c2e825313e8447f569233bb8db39aa607c8000"
                ),
                10,
            )
            .append_pre_auth_tx_signer(
                bytes.fromhex(
                    "2db4b22ca018119c5027a80578813ffcf582cda4aa9e31cd92b43cfa4fc5a000"
                ),
                10,
            )
            .append_inflation_op()
            .append_manage_data_op("hello", "overcat")
            .append_bump_sequence_op(10)
            .append_manage_buy_offer_op(
                "XCN",
                "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD",
                "PAYDEX",
                None,
                "10.5",
                "11.25",
            )
            .append_manage_sell_offer_op(
                "PAYDEX",
                None,
                "XCN",
                "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD",
                "10.5",
                Price(8, 9),
                10086,
            )
            .append_create_passive_sell_offer_op(
                "XCN",
                "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD",
                "PAYDEX",
                None,
                "10.5",
                "11.25",
            )
            .append_account_merge_op(
                "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF"
            )
            .build()
        )

        xdr = "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"
        assert te.to_xdr() == xdr

        xdr_signed = "AAAAAMvXcdYjKhx0qxnsDsczxKuqa/65lZz6sjjHHczyh50JAAAKjAAAAAAAAAACAAAAAQAAAABdUQHwAAAAAF1RKQAAAAABAAAAElN0ZWxsYXIgUHl0aG9uIFNESwAAAAAAEgAAAAEAAAAAy9dx1iMqHHSrGewOxzPEq6pr/rmVnPqyOMcdzPKHnQkAAAAAAAAAANspYkKUk/8Uke2IS7CdNxkxUCocYSU7D9+VRVRh1UTCAAAAAANHO8AAAAAAAAAABgAAAAFYQ04AAAAAAMvXcdYjKhx0qxnsDsczxKuqa/65lZz6sjjHHczyh50JAAAA6NSlEAAAAAAAAAAAAQAAAAAu358wmdD7fbo5nguyPNLentV4uwQnX4PaRcFDJkD3TAAAAAAAAAAAB00zoAAAAAAAAAACAAAAAAAAAAA7msoAAAAAAC7fnzCZ0Pt9ujmeC7I80t6e1Xi7BCdfg9pFwUMmQPdMAAAAAVhDTgAAAAAAy9dx1iMqHHSrGewOxzPEq6pr/rmVnPqyOMcdzPKHnQkAAAACVFgvQAAAAAIAAAABVVNEAAAAAADbKWJClJP/FJHtiEuwnTcZMVAqHGElOw/flUVUYdVEwgAAAAFCVEMAAAAAANspYkKUk/8Uke2IS7CdNxkxUCocYSU7D9+VRVRh1UTCAAAAAAAAAAIAAAAAAAAAADuaygAAAAAALt+fMJnQ+326OZ4LsjzS3p7VeLsEJ1+D2kXBQyZA90wAAAABWENOAAAAAADL13HWIyocdKsZ7A7HM8Srqmv+uZWc+rI4xx3M8oedCQAAAAJUWC9AAAAAAgAAAAFVU0QAAAAAANspYkKUk/8Uke2IS7CdNxkxUCocYSU7D9+VRVRh1UTCAAAAAUJUQwAAAAAA2yliQpST/xSR7YhLsJ03GTFQKhxhJTsP35VFVGHVRMIAAAAAAAAADQAAAAAAAAAAO5rKAAAAAAAu358wmdD7fbo5nguyPNLentV4uwQnX4PaRcFDJkD3TAAAAAFYQ04AAAAAAMvXcdYjKhx0qxnsDsczxKuqa/65lZz6sjjHHczyh50JAAAAAlRYL0AAAAACAAAAAVVTRAAAAAAA2yliQpST/xSR7YhLsJ03GTFQKhxhJTsP35VFVGHVRMIAAAABQlRDAAAAAADbKWJClJP/FJHtiEuwnTcZMVAqHGElOw/flUVUYdVEwgAAAAAAAAAHAAAAANspYkKUk/8Uke2IS7CdNxkxUCocYSU7D9+VRVRh1UTCAAAAAVhDTgAAAAABAAAAAQAAAADL13HWIyocdKsZ7A7HM8Srqmv+uZWc+rI4xx3M8oedCQAAAAUAAAABAAAAAC7fnzCZ0Pt9ujmeC7I80t6e1Xi7BCdfg9pFwUMmQPdMAAAAAQAAAAEAAAABAAAABgAAAAEAAAAUAAAAAQAAABQAAAABAAAAFAAAAAEAAAAUAAAAAQAAAA1zdGVsbGFyY24ub3JnAAAAAAAAAQAAAAAu358wmdD7fbo5nguyPNLentV4uwQnX4PaRcFDJkD3TAAAAAoAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAACbw4cmK9wEdGXmIIl5wReUlQxfEmUuh4WxLsTKznkwAAAAAAUAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIzienw8aZfGXNsrPVEwuglMT6ER/VpIzu42zmqYHyAAAAAAAoAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEttLIsoBgRnFAnqAV4gT/89YLNpKqeMc2StDz6T8WgAAAAAAoAAAAAAAAACQAAAAAAAAAKAAAABWhlbGxvAAAAAAAAAQAAAAdvdmVyY2F0AAAAAAAAAAALAAAAAAAAAAoAAAAAAAAADAAAAAFYQ04AAAAAAJvDhyYr3AR0ZeYgiXnBF5SVDF8SZS6HhbEuxMrOeTAAAAAAAAAAAAAGQixAAAAALQAAAAQAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAFYQ04AAAAAAJvDhyYr3AR0ZeYgiXnBF5SVDF8SZS6HhbEuxMrOeTAAAAAAAAZCLEAAAAAIAAAACQAAAAAAACdmAAAAAAAAAAQAAAABWENOAAAAAACbw4cmK9wEdGXmIIl5wReUlQxfEmUuh4WxLsTKznkwAAAAAAAAAAAABkIsQAAAAC0AAAAEAAAAAAAAAAgAAAAALt+fMJnQ+326OZ4LsjzS3p7VeLsEJ1+D2kXBQyZA90wAAAAAAAAAAfKHnQkAAABAK4QrN2s/qldwTQG+XHZ/KgKmc1t3MoTE7wa34OuIBVCDdC58WChaHVaB40hcGGbR6Q9Y83Qdj+e1dPNLBQ18Bw=="
        signer = Keypair.from_secret(
            "SCCS5ZBI7WVIJ4SW36WGOQQIWJYCL3VOAULSXX3FB57USIO25EDOYQHH"
        )
        te.sign(signer)
        assert te.to_xdr() == xdr_signed

        restore_te = TransactionBuilder.from_xdr(
            xdr_signed, Network.TESTNET_NETWORK_PASSPHRASE
        ).build()
        assert restore_te.to_xdr() == xdr
        assert source.sequence == sequence + 1