Keypair

Zetrix Keypair Guide

Overview

This document outlines the full process of generating Keypairs (public/private keys), creating an address, and signing a transaction using those keys. It explains two interface methods for executing transaction calls and details the related processes. Additionally, it includes reference information for ProtoBuf data structures and demonstrates two ways to submit transactions:

  1. Using an interface call to generate transaction_blob, and

  2. Manually generating transaction_blob.

Schematic Diagram

The following diagram ilustrates how the private, public keys and address are generated.

Generating Private Keys

Generating a private key requires multiple algorithms such as a random algorithm and SHA256. Generating a private key includes the following steps:

  1. Generate a 256-bit random number (a private key in the mathematical sense) with a random algorithm and get a byte array, the raw private key, as shown below:

  1. Add a 3-byte prefix and a 1-byte version number before the raw private key, and then add a 1-byte Fill after the raw private key to get a new byte array, as shown below:

Note : For the Prefix, Version, Checksum and Fill, please refer to Table 1.

  1. Perform SHA256 calculations twice on the byte array obtained in Step

  2. Take the first 4 bytes of the operation result as the byte array of the Checksum, as shown below:

  1. Combine the byte array in Step 2 and the checksum byte array in Step 3 in order, resulting in a new byte array, as shown below:

  1. Encode the byte array generated in Step 4 with Base58, and get the string starting with priv, namely the private key, as shown below:

note : Now the private key is generated.

Table 1

Name
Data
Length

Prefix

0xDA 0x37 0x9F

3 Bytes

Version

0x01

1 Byte

Fill

0x00

1 Byte

Checksum

After performing SHA256 calculation twice on the byte array obtained in Step 2,take the first 4 bytes of the operation result.

4 Bytes

This table illustrates the Prefix, Version, Fill and Checksum used in generating the private key.

Generating Public Keys

The public key can be generated with the ED25519 algorithm after the private key is generated. Generating a public key includes the following steps:

  1. Generate a 32-bit byte array (raw public key) by processing the raw private key with the ED25519 algorithm. For example, the raw public key of the private key privbsGZFUoRv8aXZbSGd3bwzZWFn3L5QKq74RXAQYcmfXhhZ54CLr9z is shown below:

  1. Add a 1-byte prefix in the raw public key, and then add a 1-byte version number to get a new byte array, as shown below:

Note : For the Prefix, Version and Checksum, please refer to Table 2.

  1. Perform SHA256 calculation twice on the byte array in Step 2. Take the first 4 bytes of the operation result as the byte array of the Checksum, as shown below:

  1. Combine the byte array in Step 2 and the checksum byte array in Step 3 in order, resulting in a new byte array, as shown below:

  1. Encode the byte array in Step 4 into hexadecimal and get a hexadecimal string, namely the public key, as shown below:

Note : Now the public key is generated.

Table 2

Name
Data
Length

Prefix

0xB0

1 Byte

Version

0x01

1 Byte

Checksum

After performing SHA256 calculation twice on the byte array obtained in step 2, take the first 4 bytes of the operation result

4 Bytes

This table illustrates the Prefix, Version and Checksum used in generating the public key.

Generating Addresses

The address can be further generated by an algorithm after generating the private key and the public key. Generating an address includes the following steps:

  1. Generate a 32-bit byte array (raw public key) by processing the raw private key with the ED25519 algorithm. For example, the raw public key of the private key privbsGZFUoRv8aXZbSGd3bwzZWFn3L5QKq74RXAQYcmfXhhZ54CLr9z is shown below:

  1. Perform SHA256 calculation once on the raw public key and take the last 20 bytes of the operation result as the byte array, as shown below:

  1. Add a 2-byte prefix in the byte array generated in Step 2, and then add a 1-byte version number to get a new byte array, as shown below:

    Note : For the Prefix, Version and Checksum, please refer to Table 3.

  2. Perform SHA256 calculation twice on the byte array in Step 3. Take the first 4 bytes of the operation result as the byte array of the Checksum, as shown below:

  3. Combine the byte array in Step 3 and the Checksum byte array in Step 4 in order, resulting in a new byte array, as shown below:

  4. Encode the byte array generated in Step 5 with Base58, and get the string starting with adx, namely the address, as shown below:

Note : Now the address is generated.

Table 3

Name
Data
Length

Prefix

0xF0 0x26

2 Bytes

Version

0x01

1 Byte

PublicKey

Take the last 20bytes in raw public key

20 Bytes

Checksum

After performing SHA256 calculation twice on the byte array obtained in step 3, take the first 4 bytes of the operation result

4 Bytes

This table illustrates the Prefix, Version and Checksum used in generating the address.

Signing Transactions

Sign the pending transaction (the byte array obtained by the inverse hexadecimal encoding of the transaction_blob) with the ED25519 algorithm and the private key to get sign_data, the signature string.

The following example shows how to sign the transaction_blob with ED25519 and the private key.

The private key:

The transaction blob:

After signing the pending transaction (the byte array obtained by the inverse hexadecimal encoding of the transaction_blob) with the signature interface of ED25519 and performing hexadecimal conversion, the resulting sign_data is:

Methods of Submitting Transactions

There are two methods of calling the interface to execute transactions: Generating Transaction_blobs by Calling the Interface and Generating Transaction_blobs by Yourself.

Generating Transaction_blobs by Calling the Interface

Attention : As the transaction_blob is likely to be intercepted and tampered with, it is not recommended to generate transaction_blobs in this way.

If you need to call the interface to generate transaction_blobs, sign and submit transactions, please refer to the Serializing Transaction Data interface of http.

Calling the interface to generate a transaction_blob includes the following steps:

  1. Call the getAccount interface to get the nonce value of the account that is to initiate a transaction. The code is shown below:

  2. Populate the json data as needed and complete filling the transaction data. The format is shown below:

    Note : The nonce value needs to be incremented by 1 based on the value obtained in Step 1.

  3. By calling the getTransactionBlob interface, the json data generated in Step 2 is passed as a parameter, and a transaction hash and a transaction_blob are obtained to implement transaction serialization. The format is shown below:

  4. Sign the transaction and populate the transaction data. Sign the transaction_blob according to the previously generated private key, and then populate the json data of the submitted transaction. The format is shown below:

  5. By calling the submitTransaction interface, the json data generated in Step 4 is passed as a parameter, the response result is obtained and transaction submission is completed. The format of the response result is shown below:

Generating Transaction_blobs by Yourself

Generating the transaction_blob by yourself, signing, and submitting the transaction include the following steps:

  1. Call the getAccount interface to get the nonce value of the account that is to initiate a transaction. The code is shown below:

  2. Populate the transaction object Transaction of the protocol buffer and serialize it to get the transaction_blob. For details of the specific transaction data structure, please refer to ProtoBuf Data Structure.

  3. Sign the transaction and populate the transaction data. Generate a public key based on the private key, sign the transaction_blob with the private key, and then populate the json data of the submitted transaction. The format is shown below:

  4. By calling the submitTransaction interface, the json data generated in Step 3 is passed as a parameter to complete the transaction submission. The response result format is shown below:

ProtoBuf Data Structure

Protocol Buffer (ProtoBuf) is a lightweight and efficient structured data storage format that can be used for serializing structured data. It is ideal for data storage or RPC data exchange formats. It can be used in communication protocols, data storage and other fields of language-independent, platform-independent, scalable serialized structured data formats. Currently the APIs in C++, Java, and Python are available.

For more information about ProtoBuf, please refer to the protocolarrow-up-right.

Now, we will introduce the data structure details of Protocol Buffer, and provide the file and simple test program for the protocol buffer of various languages generated by the script.

Data Structure

The following section describes the various ProtoBuf data structures that might be used in transactions and their uses for your reference.

Transaction

This data structure is for complete transactions.

Operation

This data structure is for operations in transactions.

OperationCreateAccount

This data structure is for creating accounts.

Contract

This data structure is for setting contracts.

AccountPrivilege

This data structure is for setting account privilege.

Signer

This data structure is for setting signer weight.

AccountThreshold

This data structure is for setting account threshold.

OperationTypeThreshold

This data structure is for operation threshold of specified types.

OperationIssueAsset

This data structure is for issuing assets.

OperationPayAsset

This data structure is for transferring assets.

Asset

This data structure is for asset.

AssetKey

This data structure is for identifying the uniqueness of asset.

OperationSetMetadata

This data structure is for setting Metadata.

OperationSetSignerWeight

This data structure is for setting signer weight.

OperationSetThreshold

This data structure is for setting threshold.

OperationPayCoin

This data structure is for sending coin.

OperationLog

This data structure is for recording log information.

OperationSetPrivilege

This data structure is for setting account privilege.

Examples for Transaction Submission

Scenario: Account A(ztxSrb2CPEcE7gK7AUPLorFW8sE3JTgrKX51z) creates account B(Generate an address by Generating Addresses in keypair).

Generating Transaction_blobs by Interface

Generating transaction_blobs by the interface includes the following steps:

  1. Obtain the nonce value of the account to initiate a transaction by GET.

Response message:

  1. Complete populating the transaction data.

The account address of account B generated by Generating Address in keypair is ztxSWs62LxjYERH3qo22QjGAw4hrjZNt9LaUG, the populated json data is shown below:

Note : The nonce value is not 6, so this transaction would fail.

  1. Serialize the transaction data.

Request message:

Response message:

  1. Sign the transaction_blob with the private key.

Import package: import zetrix.encryption.key.PrivateKey;

Private key:

The sign_data after being signed:

  1. Complete populating the transaction data.

  1. Submit the transaction by POST.

Response message:

Generating Transaction_blobs by Yourself

Generating transaction_blobs by yourself (take Java as an example) includes the following steps:

  1. Obtain the nonce value of the account that is to initiate a transaction by GET.

Response message:

  1. Populate the transaction data structure and generate a transaction_blob.

The transaction_blob obtained:

Note : The nonce value is not 6, so this transaction would fail.

  1. Sign the transaction_blob with the private key.

Import package: import zetrix.encryption.key.PrivateKey;

The private key:

The sign_data after being signed:

  1. Complete populating the transaction data.

  1. Submit the transaction by POST.

Response message:

Last updated