exonum package¶
Module Contents¶
Subpackages¶
Submodules¶
exonum_client.client module¶
exonum_client.crypto module¶
Module with the Common Cryptography-assotiated Utils.
This module uses libsodium as a backend.
-
class
Hash
(hash_bytes: bytes)¶ Representation of a SHA-256 hash.
-
classmethod
hash_data
(data: Optional[bytes]) → exonum_client.crypto.Hash¶ Calculates a hash of the provided bytes sequence and returns a Hash object.
If None is provided, a hash of the empty sequence will be returned.
-
classmethod
-
class
KeyPair
(public_key: exonum_client.crypto.PublicKey, secret_key: exonum_client.crypto.SecretKey)¶ Representation of a Ed25519 keypair.
-
classmethod
generate
() → exonum_client.crypto.KeyPair¶ Generates a new random keypair
-
classmethod
-
class
PublicKey
(key: bytes)¶ Representation of a Ed25519 Public Key.
-
class
SecretKey
(key: bytes)¶ Representation of a Ed25519 Secret Key.
-
class
Signature
(signature: bytes)¶ Representation of a Ed25519 signature
-
classmethod
sign
(data: bytes, key: exonum_client.crypto.SecretKey) → exonum_client.crypto.Signature¶ Signs the provided bytes sequence with the provided secret key.
-
verify
(data: bytes, key: exonum_client.crypto.PublicKey) → bool¶ Verifies the signature against the provided data and the public key.
-
classmethod
exonum_client.message module¶
This module is capable of creating and signing Exonum transactions.
-
class
ExonumMessage
(instance_id: int, message_id: int, msg: google.protobuf.message.Message, prebuilt: Optional[bytes] = None)¶ Generic Exonum transaction class.
- Exonum message can be created:
by using MessageGenerator (if you want to send a transaction to the Exonum blockchain)
by using ExonumMessage.from_hex (if you want to parse a retrieved transaction).
Example workflow:
Sending a message:
>>> instance_id = ... # Get the ID of the desired service instance. >>> artifact_name = ... # Get the name of the artifact (not the instance). >>> cryptocurrency_message_generator = MessageGenerator(instance_id, artifact_name) # Create a message generator. >>> create_wallet_alice = cryptocurrency_module.CreateWallet() # Create a Protobuf message. >>> create_wallet_alice.name = "Alice1" # Fill the Protobuf message manually. >>> create_wallet_alice_tx = cryptocurrency_message_generator.create_message(create_wallet_alice) >>> create_wallet_alice_tx.sign(keypair) # You should sign the message before sending. >>> client.public_api.send_transaction(create_wallet_alice_tx)
Parsing a message:
>>> message_hex = ... # Retrieve the message as a hexadecimal string. >>> artifact_name = ... # Get the name of the artifact (not the instance). >>> transaction_name = "CreateWallet" # Get the name of the transaction. >>> parsed_message = ExonumMessage.from_hex(message_hex, artifact_name, transaction_name) >>> assert parsed_message.validate() # Verify the signature of the retrieved message.
Other methods: >>> message = ExonumMessage.from_hex(…) >>> author = message.author() # Get the author’s public key. >>> tx_hash = message.hash() # Get the transaction hash. >>> signature = message.signature() # Get the transaction signature. >>> any_tx_raw = message.any_tx_raw() # Get AnyTx of the message serialized to bytes. >>> signed_tx_raw = message.signed_tx_raw() # Get SignedMessage of the message serialized to bytes. >>> tx_json = message.pack_into_json() # Create a JSON with the transaction in the format expected by Exonum.
-
__init__
(instance_id: int, message_id: int, msg: google.protobuf.message.Message, prebuilt: Optional[bytes] = None)¶ Exonum message constructor. It is not intended to be used directly, see MessageGenerator.create_message and ExonumMessage.from_hex instead.
-
any_tx_raw
() → bytes¶ Returns a serialized AnyTx message as bytes.
Returns an author’s public key. If the author is not set, returns None.
-
classmethod
from_hex
(message_hex: str, artifact_name: str, artifact_version: str, tx_name: str) → Optional[exonum_client.message.ExonumMessage]¶ Attempts to parse an Exonum message from a serialized hexadecimal string.
- Parameters
message_hex (str) – Serialized message as a hexadecimal string.
artifact_name (str) – The name of the service artifact you want to communicate with, e.g. ‘exonum-cryptocurrency-advanced’.
artifact_version (str) – Version of artifact as string, e.g. ‘1.0.0’.
tx_name (str) – The name of the transaction to be parsed, e.g. ‘CreateWallet’.
- Returns
parsed_message – If parsing is successfull, an ExonumMessage object is returned. Otherwise the returned value is None.
- Return type
Optional[ExonumMessage]
-
hash
() → exonum_client.crypto.Hash¶ Returns a hash of the message. If the message is not signed, a hash of an empty message will be returned.
-
pack_into_json
() → str¶ Packs a serialized signed message into the JSON format expected by Exonum.
Please note that this method does not serialize the message to JSON.
- Returns
json_message – String with a JSON representation of the serialized message.
- Return type
str
- Raises
RuntimeError – An error will be raised on attempt to call pack_into_json with an unsigned message.
-
sign
(keys: exonum_client.crypto.KeyPair) → None¶ Signs the message with the provided pair of keys.
Please note that signing is required before sending a message to the Exonum blockchain.
- Parameters
keys (exonum.crypto.KeyPair) – A pair of public_key and secret_key as bytes.
-
signature
() → Optional[exonum_client.crypto.Signature]¶ Returns a signature. If the message is not signed, returns None.
-
signed_raw
() → Optional[bytes]¶ Returns a serialized SignedMessage as bytes. If the message is not signed, returns None.
-
validate
() → bool¶ Validates the message. Checks if the transaction signature is correct. :return: bool
-
class
MessageGenerator
(instance_id: int, artifact_name: str, artifact_version: str)¶ MessageGenerator is a class which helps you create transactions. It is capable of transforming a Protobuf message object into an Exonum transaction with a set of the required metadata.
Example of usage: >>> instance_id = … # Get the ID of the desired service instance. >>> artifact_name = … # Get the name of the artifact (not the instance). >>> artifact_version = … # Get the version of the artifact (not the instance). >>> cryptocurrency_message_generator = MessageGenerator(instance_id, artifact_name, artifact_version) >>> create_wallet_alice = cryptocurrency_message_generator.CreateWallet() # Create a Protobuf message. >>> create_wallet_alice.name = “Alice1” # Fill the Protobuf message manually.
Then you can transform the Protobuf message into an Exonum transaction.
>>> create_wallet_alice_tx = cryptocurrency_message_generator.create_message(create_wallet_alice) >>> create_wallet_alice_tx.sign(keypair) # You should sign the message before sending. >>> client.public_api.send_transaction(create_wallet_alice_tx)
-
__init__
(instance_id: int, artifact_name: str, artifact_version: str)¶ MessageGenerator constructor.
- Parameters
instance_id (int) – ID of the desired Exonum service instance.
artifact_name (str) – The name of the service artifact you want to communicate with. The name should be in the format provided by Exonum, like ‘exonum-cryptocurrency-advanced:1.0.0’.
-
create_message
(message: google.protobuf.message.Message) → exonum_client.message.ExonumMessage¶ Method to convert a Protobuf message into an Exonum message.
- Parameters
message (google.protobuf.message.Message) – A Protobuf message.
- Returns
exonum_message – Exonum message object.
- Return type
-
static
pk_to_hash_address
(public_key: exonum_client.crypto.PublicKey) → Optional[exonum_client.crypto.Hash]¶ Converts PublicKey into a Hash, which is a uniform presentation of any transaction authorization supported by Exonum.
-
exonum_client.module_manager module¶
Module capable of loading the Protobuf-generated modules.
-
class
ModuleManager
¶ ModuleManager class provides an interface for importing modules generated from the previously downloaded Protobuf sources.
It is supposed that you call those methods only after downloading the corresponding module via ProtobufLoader. Otherwise an error will be raised.
Example usage:
>>> with client.protobuf_loader() as loader: >>> loader.load_main_proto_files() >>> loader.load_service_proto_files(0, "exonum-supervisor", "1.0.0") >>> blockchanin_module = ModuleManager.import_main_module("exonum.blockchain") >>> auth_module = ModuleManager.import_main_module("exonum.runtime.auth") >>> service_module = ModuleManager.import_service_module("exonum-supervisor", "1.0.0", "service")
-
static
import_main_module
(module_name: str) → Any¶ Imports the main (used by the Exonum core) module, e.g. “consensus”, “runtime”, etc.
-
static
import_service_module
(artifact_name: str, artifact_version: str, module_name: str) → Any¶ Imports the service (corresponding to some artifact) module.
-
static
exonum_client.protobuf_loader module¶
Module Containing the ProtobufLoader Class.
ProtobufLoader is capable of downloading Protobuf sources from Exonum.
-
class
ProtoFile
¶ Structure that represents a proto file.
-
property
content
¶ Alias for field number 1
-
property
name
¶ Alias for field number 0
-
property
-
class
ProtobufLoader
(client: Optional[exonum_client.protobuf_loader.ProtobufProviderInterface] = None)¶ ProtobufLoader is a class capable of loading and compiling Protobuf sources from Exonum.
This class is a Singleton, meaning that only one entity of that class is created at a time.
Example workflow:
>>> with client.protobuf_loader() as loader: >>> loader.load_main_proto_files() >>> loader.load_service_proto_files(0, "exonum-supervisor", "1.0.0")
Code above will initialize loader, download core Exonum proto files and proto files for the Supervisor service. The code will compile the files into the Python modules. After that you will be able to load those modules via ModuleManager.
Please note that it is recommended to create a ProtobufLoader object via the context manager. Otherwise you will have to call initialize and deinitialize methods manually:
>>> loader = client.protobuf_loader() >>> loader.initialize() >>> ... # Some code >>> loader.deinitialize()
If you forget to call deinitialize (or if the code exits earlier, for example because of unhandled exception), the recourses created in the temp folder (which may differ depending on your OS) will not be removed.
Creating more than one entity at a time will result in retrieving the same object:
>>> with client.protobuf_loader() as loader_1: >>> with client.protobuf_loader() as loader_2: >>> assert loader_1 == loader_2
This may be useful if you have several modules that should work with ProtobufLoader:
>>> # main.py >>> loader = ProtobufLoader(client) >>> loader.initialize() >>> loader.load_main_proto_files() >>> ... >>> loader.deinitialize()
>>> # module_a.py >>> loader = ProtobufLoader() # Since loader is already initialized with the client, you do not have to provide it. >>> loader.load_service_proto_files(runtime_a, service_a, service_a_version)
>>> # module_b.py >>> loader = ProtobufLoader() >>> loader.load_service_proto_files(runtime_b, service_b, service_b_version)
However, if you try to create the second loader, different from the first one, from the client, ValueError will be raised.
-
deinitialize
() → None¶ Performs a deinitialization process.
-
initialize
() → None¶ Performs an initialization process.
-
load_main_proto_files
() → None¶ Loads and compiles the main Exonum proto files.
-
load_service_proto_files
(runtime_id: int, artifact_name: str, artifact_version: str) → None¶ Loads and compiles proto files for a service.
-
-
class
ProtobufProviderInterface
¶ Interface for Protobuf sources provider.
-
get_main_proto_sources
() → List[exonum_client.protobuf_loader.ProtoFile]¶ Gets the Exonum core proto sources.
-
get_proto_sources_for_artifact
(runtime_id: int, artifact_name: str, artifact_version: str) → List[exonum_client.protobuf_loader.ProtoFile]¶ Gets the Exonum core proto sources.
-