Introduce Auth module

Hello everyone,

Today I would like to propose a LIP for the roadmap objective “Define state model and state root”. This LIP specifies the authentication (or auth) module.

Looking forward to your feedback!

Here is the LIP draft:

LIP: <LIP number>
Title: Introduce auth module
Author: Alessandro Ricottone <alessandro.ricottone@lightcurve.io>
        Ishan Tiwari <ishan.tiwari@lightcurve.io> 
Type: Standards Track
Created: <YYYY-MM-DD>
Updated: <YYYY-MM-DD>
Requires: LIP 0040

Abstract

The auth module is responsible for handling and verifying nonces and for transaction signature validation, including transactions from multisignature accounts. In this LIP, we specify the properties of the auth module, along with their serialization and default values. Furthermore, we specify the state transitions logic defined within this module, i.e. the commands, the protocol logic injected during the block lifecycle, and the functions that can be called from other modules or off-chain services.

Copyright

This LIP is licensed under the Creative Commons Zero 1.0 Universal.

Motivation

In the Lisk protocol, some verification steps are common to all transactions. In particular, to validate a transaction it is necessary to validate the signatures and the nonce. These validation steps are handled by the authentication (auth) module.

In this LIP we specify the properties, serialization, and default values of the auth module, as well as the protocol logic processed during a block lifecycle, the commands, and the functions exposed to other modules and to off-chain services.

Rationale

Validating a transaction requires reading the state to get the nonce and possibly the multisignature keys from the user account. Since both these checks are necessarily done together, it makes sense to store these values together, to reduce the number of database accesses.

Specification

In this section, we specify the substores that are part of the auth module store, the commands, and the protocol logic called during the block lifecycle. The auth module has module ID MODULE_ID_AUTH (see the table below).

Constants

We define the following constants:

Name Type Value Description
MODULE_ID_AUTH uint32 TBA ID of the auth module
STORE_PREFIX_AUTH bytes 0x0000 Store prefix of the auth data substore

Auth Module Store

The key-value pairs in the module store are organized in the following substore.

Auth Data Substore

Store Prefix, Store Key, and Store Value
  • The store prefix is set to STORE_PREFIX_AUTH.
  • Store keys are set to 20 bytes addresses, representing a user address.
  • Store values are set to auth account data structures, holding the properties indicated below, serialized using the JSON schema authAccountSchema, presented below.
  • Notation: For the rest of this proposal let authAccount(address) be an entry in the auth data substore identified by the store key address.
JSON Schema
authAccountSchema = {
  type: "object",
  properties: {
    nonce: {
      dataType: "uint64",
      fieldNumber: 1
    },
    numberOfSignatures: {
      dataType: "uint32",
      fieldNumber: 2
    },
    mandatoryKeys: {
      type: "array",
      items: {
        dataType: "bytes"
      },
      fieldNumber: 3
    },
    optionalKeys: {
      type: "array",
      items: {
        dataType: "bytes"
      },
      fieldNumber: 4
    }
  },
  required: ["nonce", 
              "numberOfSignatures", 
              "mandatoryKeys", 
              "optionalKeys"]
}
Properties and Default values

In this section, we describe the properties of an auth account and specify their default values.

  • nonce: The nonce represents the total number of transactions sent from the account. Each time a new transaction is sent, the nonce is incremented by one. The default value of this property is 0.
  • numberOfSignatures: The number of private keys that must sign a transaction. This value is greater than 0 if and only if a register multisignature group transaction for this account was included. The default value of this property is 0.
  • mandatoryKeys: An array of public keys in lexicographical order. The corresponding private keys have to necessarily sign the transaction. A valid public key is 32 bytes long. The default value of this property is an empty array.
  • optionalKeys: An array of public keys in lexicographical order. The corresponding private keys can optionally sign the transaction. The number of corresponding private keys that have to sign the transaction equals numberOfSignatures minus the length of mandatoryKeys. A valid public key is 32 bytes long. The default value of this property is an empty array.

Commands

registerMultisignatureGroup

This command is specified in LIP 0017. It allows users to register a multisignature group for the sender account.

Parameters

The properties and schema for this command are defined in LIP 0028.

Verification

The verification of this command is defined in LIP 0017.

Execution

This command updates the entries in the sender authAccount to the values specified in the command parameters.

Protocol Logic for Other Modules

getAuthAccount

This function is used to retrieve information about an auth account.

Parameters
  • address: A 20 bytes value identifying the auth account.
Returns

This function returns authAccount(address). If there is no entry corresponding to address, it returns an empty object.

Endpoints for Off-Chain Services

getAuthAccount

This function is used to retrieve information about an auth account.

Parameters
  • address: A 20 bytes value identifying the auth account.
Returns

This function returns authAccount(address). If there is no auth account corresponding to address, it returns an empty object.

verifySignatures

This function verifies the signatures of a given transaction trs, including transactions from multisignature accounts.

Parameters
  • trs: A transaction object.
Returns

This function returns true if the transaction object contains a valid signature, false otherwise, as specified in LIP 0017.

verifyNonce

This function verifies the nonce of a given transaction trs and returns a boolean value.

Parameters
  • trs: A transaction object.
Returns

This function returns true if the transaction object contains a valid nonce, false otherwise. This is done using the isValidNonce function defined below.

Block Processing

Transaction Verification

As part of the verification of a transaction trs, the following checks are applied. If the checks fail the transaction is invalid and the whole block is discarded.

  • Check that the transaction nonce is equal to the account nonce by returning isValidNonce(trs).
isValidNonce(trs):
    let senderAddress be the address corresponding to trs.senderPublicKey
    return trs.nonce == authAccount(senderAddress).nonce

Notice that a transaction in the transaction pool with a nonce greater than the account nonce is considered “pending” rather than invalid, since it could become valid in the future.

  • Check the signatures property of the transaction as explained in LIP 0017 using authAccount(address), where address is the address corresponding to trs.senderPublicKey.

After Transaction Execution

After a transaction trs is executed, the following logic is applied.

  • Increment account nonce:

    let senderAddress be the address corresponding to trs.senderPublicKey
    authAccount(senderAddress).nonce += 1
    

Backwards Compatibility

This LIP defines a new module and specify its store, which in turn will become part of the state tree and will be authenticated by the state root. As such, it will induce a hardfork.

1 Like

I opened a PR on the LIPs repository to merge this LIP.

The PR has been merged.