Appendix

Serialization

The Lisk protocol specifies in LIP 0027 how to serialize objects used by the protocol. Generating a binary message from a JavaScript object is performed by following a stricter version of the Protocol Buffers specification. Objects to be encoded have their format specified in a JSON schema. The schemas for transactions, blocks and accounts can be found in LIP 0028, LIP 0029 and LIP 0030 respectively.

Signature scheme

The Lisk protocol uses the Ed25519 signature scheme (see Wikipedia page and the specification page for Ed225519). The signing procedure uses the message and the private key of the signatory to generate 64 bytes, called the signature. Other users can then verify this signature with respect to the message and the public key of the signatory.

In the Lisk protocol the procedure for signing blocks and transactions is as follows:

  1. Serialize the object into the corresponding binary message.

  2. Prepend the 32 bytes network identifier to the binary message (see LIP 0009 and LIP 0024). The network identifier uniquely binds a transaction or a block to one network. Different blockchains created with the Lisk SDK should use different network identifiers to avoid transaction replay between chains.

  3. Compute the signature of the output of step 2 above, as described in the Ed25519 specifications.

signature_process

Verifying signatures

The network identifier is not transmitted with the binary message. The procedure to verify transactions is therefore as follows:

  1. Remove the signature from the object received.

  2. Serialize the output of step 1 to a binary message.

  3. Prepend the network identifier to the binary message.

  4. Verify the output of step 3 with respect to the signature and the signer public key.

Object ID

The Lisk ecosystem uses IDs to identify objects, such as blocks and transactions. The ID is obtained by serializing the object, including the signature, and taking the SHA-256 hash (see Wikipedia page) of this binary message.

objectID

Address

Key pair and address creation

To create a new address, first a 12-word passphrase is generated following the specifications of BIP39. The passphrase is then hashed using SHA-256 into a 256-bit string. The resulting hash is used as the seed to generate the private key and the public key using Ed25519 signature scheme. Finally, the address is generated by taking the first 20 bytes of the SHA-256 hash of the public key.

addressCreation

Base32 representation

We display addresses in a Base32 representation including a checksum and the "lsk" prefix. The procedure to obtain the Base32 representation of the address is as follows:

  1. Calculate a 30-bit checksum of the 20-byte address of the account using a BCH code, see BIP173. This step provides protection against accidentally typing mistakes.

  2. Concatenate the 20-byte address and the output of step 1.

  3. Encode the output of step 2 in a custom Base32 format, see LIP 0018 for details. Lower-case letters and digits are used, the characters i, l, 1 and 0 are removed for usability reasons.

  4. Add the prefix "lsk" to the output of step 3. This ensures that the Base32 representation used in the Lisk wallet start with "lsk" and that the final address is 41 characters long.

As an example, the address 0xc247a42e09e6aafd818821f75b2f5b0de47c8235 has the Base32 representation lsk24cd35u4jdq8szo3pnsqe5dsxwrnazyqqqg5eu.