Пример #1
0
    def __init__(self,
                 client: ExonumClient,
                 instance_name: str = "crypto",
                 version: str = "0.2.0"):
        self.client = client
        service_name = "exonum-cryptocurrency"
        self.service_version = version
        self.instance_name = instance_name
        self.loader = client.protobuf_loader()
        self.loader.initialize()
        self.loader.load_main_proto_files()
        self.loader.load_service_proto_files(runtime_id=0,
                                             artifact_name="exonum-supervisor",
                                             artifact_version="1.0.0")
        self.loader.load_service_proto_files(
            runtime_id=0,
            artifact_name=service_name,
            artifact_version=self.service_version)

        self.cryptocurrency_module = ModuleManager.import_service_module(
            service_name, self.service_version, "service")
        self.types_module = ModuleManager.import_service_module(
            service_name, self.service_version, "exonum.crypto.types")
        instance_id = client.public_api.get_instance_id_by_name(
            self.instance_name)
        self.msg_generator = MessageGenerator(
            instance_id=instance_id,
            artifact_name=service_name,
            artifact_version=self.service_version)
Пример #2
0
    def __init__(self, client: ExonumClient):
        self.client = client
        cryptocurrency_service_name = "exonum-cryptocurrency-advanced"
        cryptocurrency_service_version = "0.13.0-rc.2"
        self.loader = client.protobuf_loader()
        self.loader.initialize()
        self.loader.load_main_proto_files()
        self.loader.load_service_proto_files(
            runtime_id=0,
            artifact_name="exonum-supervisor",
            artifact_version="0.13.0-rc.2",
        )
        self.loader.load_service_proto_files(
            runtime_id=0,
            artifact_name=cryptocurrency_service_name,
            artifact_version=cryptocurrency_service_version,
        )

        self.cryptocurrency_module = ModuleManager.import_service_module(
            cryptocurrency_service_name, cryptocurrency_service_version,
            "service")
        self.types_module = ModuleManager.import_service_module(
            cryptocurrency_service_name, cryptocurrency_service_version,
            "types")
        instance_id = client.public_api.get_instance_id_by_name("crypto")
        self.msg_generator = MessageGenerator(
            instance_id=instance_id,
            artifact_name=cryptocurrency_service_name,
            artifact_version=cryptocurrency_service_version)
Пример #3
0
class ExonumCryptoAdvancedClient:
    """Class provides an interface to simplify interaction with cryptocurrency-advanced service."""
    def __init__(self, client: ExonumClient):
        self.client = client
        cryptocurrency_service_name = 'exonum-cryptocurrency-advanced:0.13.0-rc.2'
        self.loader = client.protobuf_loader()
        self.loader.initialize()
        self.loader.load_main_proto_files()
        self.loader.load_service_proto_files(
            runtime_id=0, service_name='exonum-supervisor:0.13.0-rc.2')
        self.loader.load_service_proto_files(
            runtime_id=0, service_name=cryptocurrency_service_name)

        self.cryptocurrency_module = ModuleManager.import_service_module(
            cryptocurrency_service_name, 'service')
        self.types_module = ModuleManager.import_service_module(
            cryptocurrency_service_name, 'types')
        instance_id = client.get_instance_id_by_name("crypto")
        self.msg_generator = MessageGenerator(
            instance_id=instance_id, artifact_name=cryptocurrency_service_name)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self.loader.deinitialize()

    def create_wallet(self, keys, wallet_name):
        """Wrapper for create wallet operation."""
        create_wallet = self.cryptocurrency_module.CreateWallet()
        create_wallet.name = wallet_name
        create_wallet_tx = self.msg_generator.create_message(create_wallet)
        create_wallet_tx.sign(keys)
        return self.client.send_transaction(create_wallet_tx)

    def issue(self, keys, amount):
        """Wrapper for issue operation."""
        issue = self.cryptocurrency_module.Issue()
        issue.amount = amount
        issue.seed = gen_seed()
        issue_tx = self.msg_generator.create_message(issue)
        issue_tx.sign(keys)
        return self.client.send_transaction(issue_tx)

    def get_wallet_info(self, keys):
        """Wrapper for get wallet info operation."""
        return self.client.get_service(
            "crypto/v1", "wallets/info?pub_key=" + keys.public_key.hex())

    def transfer(self, amount, from_wallet, to_wallet):
        """Wrapper for transfer operation."""
        transfer = self.cryptocurrency_module.Transfer()
        transfer.amount = amount
        transfer.seed = gen_seed()
        transfer.to.CopyFrom(self.types_module.PublicKey(data=to_wallet))
        transfer_tx = self.msg_generator.create_message(transfer)
        transfer_tx.sign(from_wallet)
        return self.client.send_transaction(transfer_tx)
Пример #4
0
def create_wallet(client: ExonumClient, message_generator: MessageGenerator,
                  name: str) -> KeyPair:
    """Creates a wallet with the given name and returns a KeyPair for it."""
    key_pair = KeyPair.generate()

    # Load the "service.proto" from the Cryptocurrency service:
    cryptocurrency_module = ModuleManager.import_service_module(
        CRYPTOCURRENCY_ARTIFACT_NAME, "service")

    # Create a Protobuf message:
    create_wallet_message = cryptocurrency_module.TxCreateWallet()
    create_wallet_message.name = name

    # Convert the Protobuf message to an Exonum message and sign it:
    create_wallet_tx = message_generator.create_message(create_wallet_message)
    create_wallet_tx.sign(key_pair)

    # Send the transaction to Exonum:
    response = client.send_transaction(create_wallet_tx)
    ensure_status_code(response)
    tx_hash = response.json()["tx_hash"]

    # Wait for new blocks:
    with client.create_subscriber() as subscriber:
        subscriber.wait_for_new_block()
        subscriber.wait_for_new_block()

    ensure_transaction_success(client, tx_hash)

    print(f"Successfully created wallet with name '{name}'")

    return key_pair
Пример #5
0
def transfer(
    client: ExonumClient, message_generator: MessageGenerator, from_keypair: KeyPair, to_key: PublicKey, amount: int
) -> Tuple[int, int]:
    """This example transfers tokens from one wallet to the other one and
    returns the balances of these wallets."""

    cryptocurrency_module = ModuleManager.import_service_module(CRYPTOCURRENCY_ARTIFACT_NAME, "service")
    # Note that since we are using the Cryptocurrency module,
    # we need to load helpers from this module and not from the main module:
    helpers_module = ModuleManager.import_service_module(CRYPTOCURRENCY_ARTIFACT_NAME, "helpers")

    transfer_message = cryptocurrency_module.Transfer()
    transfer_message.to.CopyFrom(helpers_module.PublicKey(data=to_key.value))
    transfer_message.amount = amount
    transfer_message.seed = Seed.get_seed()

    transfer_tx = message_generator.create_message(transfer_message)
    transfer_tx.sign(from_keypair)

    response = client.send_transaction(transfer_tx)
    ensure_status_code(response)
    tx_hash = response.json()["tx_hash"]

    # Wait for new blocks:

    with client.create_subscriber() as subscriber:
        subscriber.wait_for_new_block()
        subscriber.wait_for_new_block()

    ensure_transaction_success(client, tx_hash)

    from_balance = get_balance(client, from_keypair.public_key)
    to_balance = get_balance(client, to_key)

    return from_balance, to_balance
Пример #6
0
    def __init__(self, client: ExonumClient):
        self.client = client
        cryptocurrency_service_name = 'exonum-cryptocurrency-advanced:0.13.0-rc.2'
        self.loader = client.protobuf_loader()
        self.loader.initialize()
        self.loader.load_main_proto_files()
        self.loader.load_service_proto_files(
            runtime_id=0, service_name='exonum-supervisor:0.13.0-rc.2')
        self.loader.load_service_proto_files(
            runtime_id=0, service_name=cryptocurrency_service_name)

        self.cryptocurrency_module = ModuleManager.import_service_module(
            cryptocurrency_service_name, 'service')
        self.types_module = ModuleManager.import_service_module(
            cryptocurrency_service_name, 'types')
        instance_id = client.get_instance_id_by_name("crypto")
        self.msg_generator = MessageGenerator(
            instance_id=instance_id, artifact_name=cryptocurrency_service_name)
Пример #7
0
def transfer(client: ExonumClient, message_generator: MessageGenerator,
             from_keypair: KeyPair, to_key: PublicKey,
             amount: int) -> Tuple[int, int]:
    """This example transfers tokens from one wallet to the other one and
    returns the balances of these wallets."""

    cryptocurrency_module = ModuleManager.import_service_module(
        CRYPTOCURRENCY_ARTIFACT_NAME, CRYPTOCURRENCY_ARTIFACT_VERSION,
        "service")
    # Note that since we are using the Cryptocurrency module,
    # we need to load types from this module and not from the main module:
    types_module = ModuleManager.import_service_module(
        CRYPTOCURRENCY_ARTIFACT_NAME, CRYPTOCURRENCY_ARTIFACT_VERSION,
        "exonum.crypto.types")

    transfer_message = cryptocurrency_module.Transfer()
    # The address is a hash of a `Caller` protobuf message.
    hash_address = message_generator.pk_to_hash_address(to_key)
    if hash_address is None:
        raise Exception
    transfer_message.to.CopyFrom(types_module.Hash(data=hash_address.value))
    transfer_message.amount = amount
    transfer_message.seed = Seed.get_seed()

    transfer_tx = message_generator.create_message(transfer_message)
    transfer_tx.sign(from_keypair)

    response = client.public_api.send_transaction(transfer_tx)
    ensure_status_code(response)
    tx_hash = response.json()["tx_hash"]

    # Wait for new blocks:

    with client.create_subscriber("blocks") as subscriber:
        subscriber.wait_for_new_event()
        subscriber.wait_for_new_event()

    ensure_transaction_success(client, tx_hash)

    from_balance = get_balance(client, from_keypair.public_key)
    to_balance = get_balance(client, to_key)

    return from_balance, to_balance
Пример #8
0
def run() -> None:
    """This example creates two wallets (for Alice and Bob) and performs several
    transactions between these wallets."""
    client = ExonumClient(hostname="127.0.0.1",
                          public_api_port=8080,
                          private_api_port=8081)

    with client.protobuf_loader() as loader:
        # Load and compile proto files:
        loader.load_main_proto_files()
        loader.load_service_proto_files(RUST_RUNTIME_ID,
                                        CRYPTOCURRENCY_ARTIFACT_NAME,
                                        CRYPTOCURRENCY_ARTIFACT_VERSION)

        instance_id = get_cryptocurrency_instance_id(client)

        cryptocurrency_message_generator = MessageGenerator(
            instance_id, CRYPTOCURRENCY_ARTIFACT_NAME,
            CRYPTOCURRENCY_ARTIFACT_VERSION)

        alice_keypair = create_wallet(client, cryptocurrency_message_generator,
                                      "Alice")
        bob_keypair = create_wallet(client, cryptocurrency_message_generator,
                                    "Bob")

        alice_balance = get_balance(client, alice_keypair.public_key)
        bob_balance = get_balance(client, bob_keypair.public_key)
        print("Created the wallets for Alice and Bob. Balance:")
        print(f" Alice => {alice_balance}")
        print(f" Bob => {bob_balance}")

        amount = 10
        alice_balance, bob_balance = transfer(
            client, cryptocurrency_message_generator, alice_keypair,
            bob_keypair.public_key, amount)

        print(f"Transferred {amount} tokens from Alice's wallet to Bob's one")
        print(f" Alice => {alice_balance}")
        print(f" Bob => {bob_balance}")

        amount = 25
        bob_balance, alice_balance = transfer(
            client, cryptocurrency_message_generator, bob_keypair,
            alice_keypair.public_key, amount)

        print(f"Transferred {amount} tokens from Bob's wallet to Alice's one")
        print(f" Alice => {alice_balance}")
        print(f" Bob => {bob_balance}")
Пример #9
0
class ExonumCryptoAdvancedClient:
    """Class provides an interface to simplify interaction with cryptocurrency-advanced service."""
    def __init__(self,
                 client: ExonumClient,
                 instance_name: str = "crypto",
                 version: str = "0.2.0"):
        self.client = client
        service_name = "exonum-cryptocurrency"
        self.service_version = version
        self.instance_name = instance_name
        self.loader = client.protobuf_loader()
        self.loader.initialize()
        self.loader.load_main_proto_files()
        self.loader.load_service_proto_files(runtime_id=0,
                                             artifact_name="exonum-supervisor",
                                             artifact_version="1.0.0")
        self.loader.load_service_proto_files(
            runtime_id=0,
            artifact_name=service_name,
            artifact_version=self.service_version)

        self.cryptocurrency_module = ModuleManager.import_service_module(
            service_name, self.service_version, "service")
        self.types_module = ModuleManager.import_service_module(
            service_name, self.service_version, "exonum.crypto.types")
        instance_id = client.public_api.get_instance_id_by_name(
            self.instance_name)
        self.msg_generator = MessageGenerator(
            instance_id=instance_id,
            artifact_name=service_name,
            artifact_version=self.service_version)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self.loader.deinitialize()

    def create_wallet(self, keys, wallet_name):
        """Wrapper for create wallet operation."""
        if self.service_version == "0.1.0":
            create_wallet = self.cryptocurrency_module.TxCreateWallet()
        else:
            create_wallet = self.cryptocurrency_module.CreateWallet()

        create_wallet.name = wallet_name
        create_wallet_tx = self.msg_generator.create_message(create_wallet)
        create_wallet_tx.sign(keys)
        return self.client.public_api.send_transaction(create_wallet_tx)

    def issue(self, keys, amount):
        """Wrapper for issue operation."""
        issue = self.cryptocurrency_module.Issue()
        issue.amount = amount
        issue.seed = gen_seed()
        issue_tx = self.msg_generator.create_message(issue)
        issue_tx.sign(keys)
        return self.client.public_api.send_transaction(issue_tx)

    def get_wallet_info(self, keys):
        """Wrapper for get wallet info operation."""
        public_service_api = self.client.service_public_api(self.instance_name)
        return public_service_api.get_service("v1/wallets/info?pub_key=" +
                                              keys.public_key.hex())

    def get_balance(self, keys):
        wallet = self.get_wallet_info(keys).json()
        return wallet["wallet_proof"]["to_wallet"]["entries"][0]["value"][
            "balance"]

    def get_history_len(self, keys):
        wallet = self.get_wallet_info(keys).json()
        return wallet["wallet_proof"]["to_wallet"]["entries"][0]["value"][
            "history_len"]

    def transfer(self, amount, from_wallet, to_wallet):
        """Wrapper for transfer operation."""
        transfer = self.cryptocurrency_module.Transfer()
        transfer.amount = amount
        transfer.seed = gen_seed()
        hash_address = self.msg_generator.pk_to_hash_address(to_wallet)
        transfer.to.CopyFrom(self.types_module.Hash(data=hash_address.value))
        transfer_tx = self.msg_generator.create_message(transfer)
        transfer_tx.sign(from_wallet)
        return self.client.public_api.send_transaction(transfer_tx)
Пример #10
0
def run() -> None:
    """This example creates a wallet in the Cryptocurrency service, retrieves
    proofs for the wallet and verifies them.
    For the example to work, be sure to have `exonum-cryptocurrency-advanced`
    service instance with name `XNM` deployed."""
    client = ExonumClient(hostname="127.0.0.1",
                          public_api_port=8080,
                          private_api_port=8081)

    with client.protobuf_loader() as loader:
        # Load and compile proto files:
        loader.load_main_proto_files()
        loader.load_service_proto_files(RUST_RUNTIME_ID,
                                        CRYPTOCURRENCY_ARTIFACT_NAME)

        instance_id = get_cryptocurrency_instance_id(client)

        cryptocurrency_message_generator = MessageGenerator(
            instance_id, CRYPTOCURRENCY_ARTIFACT_NAME)

        alice_keypair = create_wallet(client, cryptocurrency_message_generator,
                                      "Alice")

        wallet_info_response = client.get_service(
            CRYPTOCURRENCY_INSTANCE_NAME, "v1/wallets/info?pub_key={}".format(
                alice_keypair.public_key.hex()))
        ensure_status_code(wallet_info_response)
        wallet_info = wallet_info_response.json()

        # `MapProof` to the whole Exonum state hash:
        proof_to_table = wallet_info["wallet_proof"]["to_table"]
        # Expected hash of the proof to the table is a state hash of the block:
        expected_to_table_hash_raw = wallet_info["block_proof"]["block"][
            "state_hash"]
        expected_to_table_hash = Hash(
            bytes.fromhex(expected_to_table_hash_raw))

        # Verify the proof to the table:
        verify_proof_to_table(proof_to_table, expected_to_table_hash)

        # `MapProof` to the wallet as a part of the Cryptocurrency schema:
        proof_to_wallet = wallet_info["wallet_proof"]["to_wallet"]
        # Expected hash of the proof to the wallet is the value stored in the
        # proof to the table:
        expected_to_wallet_hash_raw = wallet_info["wallet_proof"]["to_table"][
            "entries"][0]["value"]
        expected_to_wallet_hash = Hash(
            bytes.fromhex(expected_to_wallet_hash_raw))

        # Verify the proof to the wallet:
        verify_proof_to_wallet(proof_to_wallet, expected_to_wallet_hash)

        # `ListProof` for the transactions associtated with the wallet:
        proof_wallet_history = wallet_info["wallet_history"]["proof"]
        # Expected hash for the wallet history is the hash stored in the proof
        # to the wallet:
        expected_history_hash_raw = wallet_info["wallet_proof"]["to_wallet"][
            "entries"][0]["value"]["history_hash"]
        expected_history_hash = Hash(bytes(expected_history_hash_raw["data"]))

        # Verify the proof for the wallet history:
        verify_wallet_history_proof(proof_wallet_history,
                                    expected_history_hash)