mitum-py-util

'mitum-py-util' will introduce the usage of mitum-currency and mitum-data-blocksign for python.

This project is being totally copied to ProtoconNet/mitum-py-util.

Installation

Recommended requirements for 'mitum-py-util' is,

  • python v3.9 or later.
$ python --version
Python 3.9.2

$ git clone https://github.com/ProtoconNet/mitum-py-util.git

$ cd mitum-py-util

$ python setup.py install

If setup.py doesn't work properly, please just install necessary packages with requirements.txt before running setup.py.

$ cd mitum-py-util

$ pip install -r requirements.txt

Generate New Operation

Operations

'mitum-py-util' provides three operations of 'mitum-currency',

  • 'Create-Accounts' creates an account corresponding to any public key with a pre-registered account.
  • 'Key-Updater' updates the public key of the account to something else.
  • 'Transfers' transfers tokens from the account to another account.

'mitum-currency' supports various kinds of operations, but 'mitum-py-util' will provide these frequently used operations.

In addition, 'mitum-py-util' provides three operations of 'mitum-data-blocksign',

  • 'Create-Documents' creates an document with filehash.
  • 'Sign-Documents' signs the document.
  • 'Transfer-Documents' transfers documents from the account to another account.

Prerequisite

Before generating new operation, you should check below for 'mitum-currency',

  • 'private key' of source account to generate signatures (a.k.a signing key)
  • 'public address' of source account
  • 'public key' of target account
  • 'network id'

Additionally, you should check below for 'mitum-data-blocksign',

  • 'filehash' for Create-Documents
  • 'owner' and 'documentid' for Sign-Documents and Transfer-Documents

Note that the package name of 'mitum-py-util' is 'mitumc' for python codes.

  • Every key, address, and keypair must be that of mitum-currency.

Generator

'mitumc' package provides 'Generator' class to generate operations.

Modules that 'Generator' supports are,

>>> Generator.set_id(net_id) 
>>> Generator.createKeys(keys, threshold)
>>> Generator.createAmounts(amounts) 
>>> Generator.createCreateAccountsItem(keys_o, amounts)
>>> Generator.createTransfersItem(receiver, amoutns)
>>> Generator.createCreateDocumentsItem(filehash, did, signcode, title, size, cid, signers, signcodes)
>>> Generator.createSignDocumentsItem(owner, documentid, cid)
>>> Generator.createTransferDocumentsItem(owner, receiver, documentid, cid)
>>> Generator.createCreateAccountsFact(sender, items)
>>> Generator.createKeyUpdaterFact(target, cid, keys_o)
>>> Generator.createTransfersFact(sender, items)
>>> Generator.createCreateDocumentsFact(sender, items)
>>> Generator.createSignDocumentsFact(sender, items)
>>> Generator.createTransferDocumentsFact(sender, items)
>>> Generator.createOperation(fact, memo)
>>> Generator.createSeal(sign_key, operations)

You can check use-cases of Generator in the next part.

Generate Create-Accounts

For new account, 'currency id' and 'initial amount' must be set. With source account, you can create and register new account of target public key.

When you use 'Generator', you must set 'network id' before you create something.

Usage

>>> from mitumc.operation import Generator

>>> source_priv = "L5GTSKkRs9NPsXwYgACZdodNUJqCAWjz2BccuR4cAgxJumEZWjok:btc-priv-v0.0.1"
>>> source_addr = "GbymDFuVmJwP4bjjyYu4L6xgBfUmdceufrMDdn4x1oz:mca-v0.0.1"
>>> target_pub = "GBYLIBJYZP6ZIYPFGOZSXSAPMRDA6XXRKNSMOMRCKNV2YZ35DGRPEQ35:stellar-pub-v0.0.1"

>>> generator = Generator("mitum")

>>> key = (target_pub, 100)
>>> keys_o = generator.createKeys([key], 100)

>>> amount = (100, "MCC")
>>> amounts = generator.createAmounts([amount])

>>> createAccountsItem = generator.createCreateAccountsItem(keys_o, amounts)
>>> createAccountsFact = generator.createCreateAccountsFact(source_addr, [createAccountsItem])

>>> createAccounts = generator.createOperation(createAccountsFact, "")
>>> createAccounts.addFactSign(source_priv)

You must add new fact signature by addFactSign before creating seal or json files from an operation.

Then Operation.to_dict() and Operation.to_json(file_name) methods work correctly.

>>> createAccounts.to_dict()
>>> createAccounts.to_json("create_account.json")

Then the result format will be like this. (Each value is up to input arguments and time)

Generate Key-Updater

Key-Updater literally supports to update source public key to something else.

Usage

>>> from mitumc.operation import Generator

>>> source_priv = "L5GTSKkRs9NPsXwYgACZdodNUJqCAWjz2BccuR4cAgxJumEZWjok:btc-priv-v0.0.1"
>>> source_addr = "GbymDFuVmJwP4bjjyYu4L6xgBfUmdceufrMDdn4x1oz:mca-v0.0.1"
>>> target_pub = "04c7a0b69c4041d2d3cf60d9318b5fdb1c29c7f63b3514aab52db6a852083dd3e1065afa8524c4ba54688ae36055377b2bb3de931054c124f01f38e7eab27e9e8f:ether-pub-v0.0.1"

>>> generator = Generator('mitum')

>>> key = (target_pub, 100)
>>> keys = generator.createKeys([key], 100)

>>> keyUpdaterFact = generator.createKeyUpdaterFact(source_addr, "MCC", keys)

>>> keyUpdater = generator.createOperation(keyUpdaterFact, "")
>>> keyUpdater.addFactSign(source_priv)

>>> keyUpdater.to_dict()
>>> keyUpdater.to_json("key_updater.json")

Generate Transfers

To generate an operation, you must prepare target address, not public key. Transfers supports to send tokens to another account.

Usage

>>> from mitumc.operation import Generator

>>> source_priv = "L5GTSKkRs9NPsXwYgACZdodNUJqCAWjz2BccuR4cAgxJumEZWjok:btc-priv-v0.0.1"
>>> source_addr = "GbymDFuVmJwP4bjjyYu4L6xgBfUmdceufrMDdn4x1oz:mca-v0.0.1"
>>> target_addr = "CzCW7V9Doi71dLJVXcdnS6V4BJDzvPdY28YCn1ksiG4m:mca-v0.0.1"

>>> generator = Generator('mitum')

>>> amount = (100, "MCC")
>>> amounts = generator.createAmounts([amount])

>>> transfersItem = generator.createTransfersItem(target_addr, amounts)

>>> transfersFact = generator.createTransfersFact(source_addr, [transfersItem])

>>> transfers = generator.createOperation(transfersFact, "")
>>> transfers.addFactSign(source_priv)

>>> transfers.to_dict()
>>> transfers.to_json('transfers.json')

Generate Create-Documents

To generate an operation, you must prepare file-hash. Create-Document supports to create documents with setting signers who must sign them.

Usage

>>> from mitumc.operation import Generator

>>> source_priv = "L5GTSKkRs9NPsXwYgACZdodNUJqCAWjz2BccuR4cAgxJumEZWjok:btc-priv-v0.0.1"
>>> source_addr = "GbymDFuVmJwP4bjjyYu4L6xgBfUmdceufrMDdn4x1oz:mca-v0.0.1"

>>> generator = Generator('mitum')

>>> createDocumentsItem = generator.createCreateDocumentsItem("abcdddd:mbhf-v0.0.1", 100, "user01", "title100", 1234, "MCC", [], ["user02"])

>>> createDocumentsFact = generator.createCreateDocumentsFact(source_addr, [createDocumentsItem])

>>> createDocuments = generator.createOperation(createDocumentsFact, "")
>>> createDocuments.addFactSign(source_prv)

>>> createDocuments.to_dict()
>>> createDocuments.to_json('create_documents.json')

Generate Sign-Documents

To generate an operation, you must prepare owner and document id. Sign-Document supports to sign documents registered by 'mitum-data-blocksign'

Usage

>>> from mitumc.operation import Generator

>>> source_priv = "L5GTSKkRs9NPsXwYgACZdodNUJqCAWjz2BccuR4cAgxJumEZWjok:btc-priv-v0.0.1"
>>> source_addr = "GbymDFuVmJwP4bjjyYu4L6xgBfUmdceufrMDdn4x1oz:mca-v0.0.1"

>>> generator = Generator('mitum')

>>> signDocumentsItem = generator.createSignDocumentsItem(source_addr, 0, "MCC")

>>> signDocumentsFact = generator.createSignDocumentsFact(source_addr, [signDocumentsItem])

>>> signDocuments = generator.createOperation(signDocumentsFact, "")
>>> signDocuments.addFactSign(source_prv)

>>> signDocuments.to_dict()
>>> signDocuments.to_json('sign_documents.json')

Generate Transfer-Documents

This operation is not supported anymore.

To generate an operation, you must prepare owner and document id. Transfer-Document supports to transfer documents to other account.

Usage

>>> from mitumc.operation import Generator

>>> source_priv = "L5GTSKkRs9NPsXwYgACZdodNUJqCAWjz2BccuR4cAgxJumEZWjok:btc-priv-v0.0.1"
>>> source_addr = "GbymDFuVmJwP4bjjyYu4L6xgBfUmdceufrMDdn4x1oz:mca-v0.0.1"
>>> target_addr = "ATDxH32CL7hdrpgLcvtNroNTF111V6wUJCK5JTa4f8Po:mca-v0.0.1"

>>> generator = Generator('mitum')

>>> transferDocumentsItem = generator.createTransferDocumentsItem(source_addr, target_addr, 0, "MCC")

>>> transferDocumentsFact = generator.createTransferDocumentsFact(source_addr, [transferDocumentsItem])

>>> transferDocuments = generator.createOperation(transferDocumentsFact, "")
>>> transferDocuments.addFactSign(source_prv)

>>> transferDocuments.to_dict()
>>> transferDocuments.to_json('transfer_documents.json')

Generate New Seal

Supports you to generate a seal json file such that the seal is able to consist of several operations. Those operations can be any type 'mitum-py-util' provides.

Prerequisite

To generate a seal, 'mitum-py-util' requires,

  • 'signing key'
  • 'a list of pre-constructed operations' not empty

Registration of 'signing key' is not neccessary.

JSONParser

You can create a json file from generated seal object without 'JSONParser' class provided by 'mitumc'. However, I recommend to use 'JSONParser' for convenience.

Modules that 'JSONParser' supports are,

>>> JSONParser.toJSONString(seal)
>>> JSONParser.generateFile(seal, fName)

A use-case of 'JSONParser' will be introduced in the next part.

Usage

First of all, suppose that every operation is that generated by 'Generator'. (createAccounts, keyUpdater, Transfers)

>>> from mitumc.operation import Generator, JSONParser

>>> generator = Generator('mitum')

... omitted
''' Create each operation [createAccounts, keyUpdater, transfers] with generator. See above sections.
'''
...

>>> source_priv = "L5GTSKkRs9NPsXwYgACZdodNUJqCAWjz2BccuR4cAgxJumEZWjok:btc-priv-v0.0.1"

>>> operations = [createAccounts, keyUpdater, transfers]
>>> seal = generator.createSeal(source_priv, operations)

>>> JSONParser.toJSONString(seal)
>>> JSONParser.generateFile(seal, 'seal.json')

Then the result format of generateFile() will be like this. (Each value is up to input arguments and time)

Send Seal to Network

Created seal json files will be used to send seals by 'mitum-currency'.

Use below command to send them to the target network. (See mitum-currency for details)

$ ./mc seal send --network-id=$NETWORK_ID $SIGNING_KEY --seal=seal.json
  • seal.json is your seal file.

Sign Message

Sign message with btc, ether, stellar keypair.

'mitumc.key' module supports generate and get keypairs. You can get signature digest which contains a signature by signing with keypairs.

Usage

Generate Keypair

>>> from mitumc.key import getKeypair

>>> btckp = getKeypair('btc') # returns BTCKeyPair
>>> ethkp = getKeypair('ether') # returns ETHKeyPair
>>> stlkp = getKeypair('stellar') # returns StellarKeyPair

>>> btckp.privkey.key
5JDCaUK6NoD8vdUdmxptiKXGqgx7ngH3aL3c1FQ19jHLo9anwW3

>>> btckp.pubkey.key
wk4RnmibruceqbjcunJpAE9ufXVgpAHuvXXBBKQUvzas

>>> ethkp.privkey.key
7222d364be36e4f038270065a5c9f5c1dadf97a85ab14305f6580e243e224d8a

>>> ethkp.pubkey.key
049757460673bbd7d6e9904eb3554055614dce1d39aea623a07483065fb655d87d1797a0ce131ca8ae8bd8da20097a6cbc1c60b8246dc770907ef30a3dc78cdd9d

>>> stlkp.privkey.key
SCEKV2MWAZQCQGKYYTPVMOBR52CRFVROT4XGMOLVSSFYD5K7AM24L57T

>>> stlkp.pubkey.key
GBQRPKLCB7BTURVHA33LC5HKKXAOISMELEN6YYSDECKH4LSOS6YJCYCT

Note that 'mitumc.key' provides uncompressed btc key.

If you want to get compressed wif key, use 'BTCKeyPair.wifc'.

>>> from mitumc.key import getKeypair

>>> btckp = getKeypair('btc')
>>> btckp.wifc
Kxxr6jYrjCxZyhzyKTQPFNkcuuLGxcMpN74VW6YXfXd8NXALHhDE

Of course, you can get any keypair with your known private key.

Note that it works with either hintless or hinted keys to generate keypairs.
(key-hint ex. btc-priv, ether-pub, etc...)

>>> from mitumc.key import to_btc_keypair, to_ether_keypair, to_stellar_keypair

# both work same
>>> btckp = to_btc_keypair("L2ddEkdgYVBkhtdN8HVXLZk5eAcdqXxecd17FDTobVeFfZNPk2ZD:btc-priv-v0.0.1")
>>> btckp = to_btc_keypair("L2ddEkdgYVBkhtdN8HVXLZk5eAcdqXxecd17FDTobVeFfZNPk2ZD") # returns BTCKeyPair

>>> ethkp = to_ether_keypair("013e56aca7cf88d95aa6535fb6c66f366d449a0380128e0eb656a863b45a5ad5:ether-priv-v0.0.1") # returns ETHKeyPair
>>> stlkp = to_stellar_keypair("SBZV72AJVXGARRY6BYXF5IPNQYWMGZJ5YVF6NIENEEATETDF6LGH4CLL:stellar-priv-v0.0.1") # returns StellarKeyPair

Sign Message

Each keypair supports 'sign' method that generates bytes format signature by signing bytes format message.

If you want to get signature for 'mitum-currency', use 'base58' to encode the signature.

>>> from mitumc.key import getKeypair
>>> import base58

>>> msg = b'mitum'

>>> btckp = getKeypair('btc')
>>> sign = btckp.sign(msg)

>>> sign
b'0E\x02!\x00\xd4\xcb\xa3\x05\xec\x92-\xde\xcc\xb9;,\xf7k\x0bl\x8d\xf7@B\xaf\xf6 \x0f\xa5\xd1\x10]N1\xcc<\x02 \x119; lJ\x83\x1e\xdd\xfd\xce\x12vVK\x8aG\xae\xba\xe7\x03%\x98\xa5\x1b\'\x99"\xc2\xaf\xa5c'

>>> base58.b58encode(sign).decode()
AN1rKvtXAEWjt4KUGZxoZ8e8YMVuLPo6MqciW9En5DbA1w1FLp6NhGmMFCuAjVipRBibWDkiVLQYvp4PcTiVezqNv4GtUKx18

Omit ether/stellar keypair sign. (bcz same...)

Add Fact Signature to Operation

With 'Signer' object in 'mitum-py-util', you can add new fact signature to operation json.

To add signatures, you must prepare 'network id' and 'signing key'.

Usage

For example, suppose that you already have an implemented operation json file like below.

operation.json

{
    "memo": "",
    "_hint": "mitum-currency-transfers-operation-v0.0.1",
    "fact": {
        "_hint": "mitum-currency-transfers-operation-fact-v0.0.1",
        "hash": "HdVp5vNCVcdnTA5H36cEfNsjjZAktpgBLdL66rgTqFVA",
        "token": "MjAyMS0wNi0xMFQwNzowMjo0MS45NzgyOTErMDA6MDA=",
        "sender": "GbymDFuVmJwP4bjjyYu4L6xgBfUmdceufrMDdn4x1oz:mca-v0.0.1",
        "items": [
            {
                "_hint": "mitum-currency-transfers-item-single-amount-v0.0.1",
                "receiver": "8dsqP9dUPKv3TjJg6DCKJ7NE7vsMx47Gc4VrseEcyXtt:mca-v0.0.1",
                "amounts": [
                    {
                        "_hint": "mitum-currency-amount-v0.0.1",
                        "amount": "100",
                        "currency": "MCC"
                    }
                ]
            }
        ]
    },
    "hash": "6KJQdbLvomAh2HmjVuqQbYEVvVMMrsMgJEsrwcRMiqCx",
    "fact_signs": [
        {
            "_hint": "base-fact-sign-v0.0.1",
            "signer": "rcrd3KA2wWNhKdAP8rHRzfRmgp91oR9mqopckyXRmCvG:btc-pub-v0.0.1",
            "signature": "AN1rKvt3cim48ETgzpEaXC5EiRJfcPhVtsK7bUTNB3f9c9152Px4enY3xh59e7EmCgmiwVvzk3tvkmTk7B3MA74E2f5gpqFzG",
            "signed_at": "2021-06-10T07:02:42.614946Z"
        }
    ]
}

Sign Operation

Use 'Signer.signOperation(#operation-file-path)' to add new fact signature to "fact_signs" key.

After adding a fact signature, operation hash will be changed.

>>> import mitumc.operation as op
>>> signer = op.Signer('mitum', "L4qMcVKwQkqrnPPtEhj8idCQyvCN2zyG374i5oftGQfraJEP8iek:btc-priv-v0.0.1")

>>> # Signer.signOperation(#target)
>>> # #target must be a dictionary object or the path of opertaion json file
>>> newOperation = signer.signOperation('operation.json') # or an object itself instead of the path 'operation.json'

After signing, above operation must be like below.(Each value is up to input arguments and time)

{
    "memo": "",
    "_hint": "mitum-currency-transfers-operation-v0.0.1",
    "fact": {
        "_hint": "mitum-currency-transfers-operation-fact-v0.0.1",
        "hash": "HdVp5vNCVcdnTA5H36cEfNsjjZAktpgBLdL66rgTqFVA",
        "token": "MjAyMS0wNi0xMFQwNzowMjo0MS45NzgyOTErMDA6MDA=",
        "sender": "GbymDFuVmJwP4bjjyYu4L6xgBfUmdceufrMDdn4x1oz:mca-v0.0.1",
        "items": [{
            "_hint": "mitum-currency-transfers-item-single-amount-v0.0.1",
            "receiver": "8dsqP9dUPKv3TjJg6DCKJ7NE7vsMx47Gc4VrseEcyXtt:mca-v0.0.1",
            "amounts": [{
                "_hint": "mitum-currency-amount-v0.0.1",
                "amount": "100",
                "currency": "MCC"
            }]
        }]
    },
    "fact_signs": [{
        "_hint": "base-fact-sign-v0.0.1",
        "signer": "rcrd3KA2wWNhKdAP8rHRzfRmgp91oR9mqopckyXRmCvG:btc-pub-v0.0.1",
        "signature": "AN1rKvt3cim48ETgzpEaXC5EiRJfcPhVtsK7bUTNB3f9c9152Px4enY3xh59e7EmCgmiwVvzk3tvkmTk7B3MA74E2f5gpqFzG",
        "signed_at": "2021-06-10T07:02:42.614946Z"
    }, {
        "_hint": "base-fact-sign-v0.0.1",
        "signer": "cnMJqt1Q7LXKqFAWprm6FBC7fRbWQeZhrymTavN11PKJ:btc-pub-v0.0.1",
        "signature": "AN1rKvt7VpVb76PXpKV2Znvixvo8bqmUJqha7WrkaTm3GKwZWfH8U2La13jJuPGvpcrbgLJqSYR5gHP2SwvtCM81NrtiBCW8a",
        "signed_at": "2021-07-20T08:24:29.163696Z"
    }],
    "hash": "DdwC2wAmvctrzCvnZSTu1xK2uKwNxNr9Y73xcHKLpqYb"
}

Signer class returns a dictionary object.

Hash Functions

'mitumc.hash' module supports sha2(sha256) and sha3(sum256) hashing.

Example

mitumc_hash.py

>>> from mitumc.hash import sha256, sum256

>>> msg = b'mitum'
>>> sha2_hash = sha256(msg)
>>> sha3_hash = sum256(msg)

>>> print(sha2_hash.digest)
>>> print(sha2_hash.hash)
>>> print(sha3_hash.digest)
>>> print(sha3_hash.hash)

The result will be,

$ python mitumc_hash.py
b'\xf7.\xd28\xfd\xc1+\xfc\x1d\xa9\xcdb9y\x8cF+RW4\x89)\x99\xcb\xdc\xf5\xbe\xf5\xa7J\xf2\x95'
Hdu7PqjA1p55GAcBiULmCAfzoksdwW1oSxaMH83kw9BJ
b'jf\x10J>\xb9O]\x14\xab}d,r\x88(B\xab\x9a\xb1x\x18\x04\xeb\x10!\x9f\xebY\xa5v"'
8ALUvxZ5Q1qQEsPUcHsoAzuzEp8Bm4HQpYqNNSafjDAR
GitHub - wyuinche/mitum-py-util: mitum-currency / mitum-data-blocksign python SDK
mitum-currency / mitum-data-blocksign python SDK. Contribute to wyuinche/mitum-py-util development by creating an account on GitHub.