Concept
Managing private keys can be difficult and exposes users to various risks, such as sending assets to the wrong recipient or having their private keys compromised by malicious fishing campaigns. One solution to this problem is to provide users with tools for protecting their digital assets. This is the role of the Custody Module, which adds an extra layer of protection by providing users with three additional safeguards. This helps to ensure that users are better able to secure their funds and reduce the risks associated with managing private keys.
Parameters
Collaborative custody
The first layer is collaborative custody, which allows users to set up specific transaction signature schemes. This means that transactions can only be sent if one or more configurable other addresses (third parties) give their approval. The collaborative custody differs from traditional m-of-n multi-signatures in that it maintains the concept of ownership. This means that third parties cannot sign transactions without the original address owning the assets also signing the transaction. Simply put, collaborative custody can be thought of as a 2-factor authentication that can be set up to N-factor authentication, where N is the number of extra KIRA addresses needed to sign transactions.
Secret protected transfers
The second layer of protection offered by the Custody Module is a mechanism that allows token transfers to occur only when the recipient of funds submits a secret provided off-chain by the sender. If the funds are not claimed within a predefined period of time, they are returned to the sender's account. This mechanism, when combined with collaborative custody, ensures that both the sender and the recipient can be verified in more than one way effectively adding an extra layer of security to the process of transferring digital assets.
Withdrawal address whitelist & transfer limit
The third layer of account protection enable users to manage a withdraw whitelist & set up custom time period transfer limits for every tokens (day, week, month…), i.e. the user’s account cannot transfer tokens unless the recipient address figures in the user’s whitelist and the withdraw amount for the given token doesn’t exceeds the current current withdrawal capacity. The whitelisting & limits setup processes can be protected by secrets, effectively preventing malicious actors getting around this protection in the case where the user’s private key is compromised. Additionally withdrawal limits have a 24-hour waiting period to prevent an attacker to immediately change limits and withdraw all funds at once in the event user’s secrets have also been compromised.
Custodian transaction propagation
When a user’s custody_enabled is enabled, all token transfers must be performed using the custody send CLI. Attempts to use the bank send CLI will be automatically rejected. Transactions are placed in an on-chain buffer awaiting approval by the quorum of custodian addresses defined by the user via the custody_mode property. The buffer has limited size defined by the max_custody_buffer_size network property (default 10) and the transaction/stored data size by max_custody_tx_size (default 8192 characters). It is important that each transaction includes adequate fees to motivate custodians to cast their approval. The fees should be at least double the cost of approving or denying the transaction, which will effectively cover the refund of transaction fees. If a custodian does not cast a judgement, they do not receive any rewards and any remaining rewards will be returned to the user. Transactions without sufficient fees included will be automatically rejected.
Custody module’s security
All transactions of the custody module can only be propagated by providing a key defined by the user or the frontend. However a key becomes exposed and thereby obsolete as soon as it used to submit a transaction. Therefore, to circumvent this security weakness, keys can only be used once and each transaction (except the first one) require providing the previously defined key hashed once SHA256(secret) as well as setting up the new key SHA256(SHA256(secret)) for the subsequent transaction.
All transactions of the custody module can only be propagated by providing a key. This key is a secret password defined by the user that is hashed twice before being stored on the blockchain to ensure its security. For each subsequent transaction the user must provide the previously set password hashed once for the system to check, but also set a new key for the next transaction. The reason for this design is due to the very public nature of transaction data in blockchains, making the secret obsolete as soon as it is used to submit a transaction. By hashing the key twice before storing it on the blockchain, and requiring the user to provide the same secret password, hashed once, for subsequent transactions, the module provides an added layer of security for the user's digital assets.
CLI syntax & examples
Governance
Each user is responsible of its own custody account parameters and does not depend on specific governance permissions. However, the module has two network properties, max_custody_tx_size and max_custody_buffer_size, which require a specific governance process to be modified (cf. Network Properties).
Transactions
sekaid tx custody
create - Create new custody settings
send - When custody_enabled is set to true, allows to send funds from one account to another.
approve - Approve custody transaction by receiver address and transaction hash
confirm - Confirm password-protected transaction
decline - Decline custody transaction by receiver address and transaction hash
add - Add one or multiple addresses to the custodians list
drop - Drop the entire custodians list
remove - Remove address from custodians list
add - Add new address to the custody limits
drop - Drop the custody limits
remove - Remove address from the custody limits
add - Add new address to the custody whitelist
drop - Drop the custody whitelist
remove - Remove address from the custody whitelist
Queries
sekaid query customgov
get - Query the current custody settings assigned to an address
custodians- Query commands for the custody custodians
get - Query custody custodians assigned to an address
pool - Query all pending transactions
limits get - Query transfer limits assigned to an address
whitelist get - Query whitelisted addressed assigned to an address
custody-registrar-query - list all details regarding custody of a specific account, including all incoming/outgoing transactions to/from specific account and their status. We should allow verifier to easily check if they have any pending tx’es to sign as well as the beneficiary so that UI can easily find & display incoming transactions.
bank-tx-query-protected - query all pending transactions that you are sending or receiving
custody-accounts-list - list all accounts which use custody module
custody-registrar-clean-txs - remove one or many/all transactions from the registrar
custody-registrar-propagate-txs (optional) - propagate one, many or all approved transactions - this should be optional if transactions can be automatically propagated
Syntax & examples
Each CLI command and proposal process in KIRA requires specific permissions. These permissions must be added to the account's whitelist or obtained as sudo permissions for direct changes. Refer to the Roles & Permissions documentation for more details. $SIGNER represents the transaction signer's account name or address. For instructions on setting common flags as environment variables, such as $FLAGS_TX and $FLAGS_QR, see the CLI flags configuration section
Custody settings management
Custody settings are set using the create CLI. Settings are stored in a dedicated registry and can then be retrieved using the custodians get CLI.
Bash
Copy
sekaid tx custody create --fees=100ukex \
--keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--from=$SIGNER --chain-id=$NETWORK_NAME --home=$SEKAID_HOME \
--okey=$OKEY --nkey=$NKEY \
$MODE $PASSWORD $LIMITS $WHITELIST
Bash
Copy
# Example
sekaid tx custody create --fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--from="kira1rxu5ltg5z63rl6du80xe45vghhy4cxlna5mzfm" --chain-id="localnet-1" --home="/root/.sekaid-localnet-1" \
--okey="0" --nkey="e0bc614e4fd035a488619799853b075143deea596c477b8dc077e309c0fe42e9" \
33 false false false
Custodians list management
Adding custodians can be done one by one or by providing a comma-separated list of addresses using custodians add.
Bash
Copy
sekaid tx custody custodians add \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--from=$SIGNER --chain-id=$NETWORK_NAME --home=$SEKAID_HOME \
--okey=$OKEY --nkey=$NKEY \
$CUSTODIANS
Bash
Copy
# Example
LIST="kira1kjx6g2sd5rev3dnuzqh8q9fznkq22qaz52kpt4,kira1j8d78jzk460a6tn8e22jm0ynmnvc79mg8h7t77,kira1lxeslhhus8qw63fxm4l0gphmf2flxajxg5l5tz"
sekaid tx custody custodians add \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--from="kira1rxu5ltg5z63rl6du80xe45vghhy4cxlna5mzfm" --chain-id="localnet-1" --home="/root/.sekaid-localnet-1" \
--okey="e2d8ce14e4zf189zffze18f88619853b075143deea596c477b8dc077e309c0cece2d58" --nkey="e0bc614e4fd035a488619799853b075143deea596c477b8dc077e309c0fe42e9" \
$LIST
Removing a single custodian address with custodians remove.
Removing a custodian address will not erase it from the list but simply set it to false. It can be switched back to true using custodians add.
Bash
Copy
sekaid tx custody custodians remove \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--from=$SIGNER --chain-id=$NETWORK_NAME --home=$SEKAID_HOME \
--okey=$OKEY --nkey=$NKEY \
$CUSTODIAN
The list of custodians addresses can be dropped all at once using custodians drop.
Dropping the list will erase all addresses completely.
Bash
Copy
sekaid tx custody custodians drop \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--from=$SIGNER --chain-id=$NETWORK_NAME --home=$SEKAID_HOME \
--okey=$OKEY --nkey=$NKEY
Transfer limits management
Adding transfer limit for a specific token can be done using limits add.
Note that there is a 24h waiting period before any subsequent modification takes effect.
Bash
Copy
sekaid tx custody limits add \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--from=$SIGNER --chain-id=$NETWORK_NAME --home=$SEKAID_HOME \
--okey=$OKEY --nkey=$NKEY \
$DENOM $AMOUNT $PERIOD
Bash
Copy
# Example
sekaid tx custody limits add \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--from="kira1rxu5ltg5z63rl6du80xe45vghhy4cxlna5mzfm" --chain-id="localnet-1" --home="/root/.sekaid-localnet-1" \
--okey="e2d8ce14e4zf189zffze18f88619853b075143deea596c477b8dc077e309c0cece2d58" --nkey="e0bc614e4fd035a488619799853b075143deea596c477b8dc077e309c0fe42e9" \
ukex 100000 24h
Removing a limit is done using limits remove.
Bash
Copy
sekaid tx custody limits remove \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--from=$SIGNER --chain-id=$NETWORK_NAME --home=$SEKAID_HOME \
--okey=$OKEY --nkey=$NKEY \
$DENOM
All limits can be dropped at once using limits drop.
Bash
Copy
sekaid tx custody limits drop \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--from=$SIGNER --chain-id=$NETWORK_NAME --home=$SEKAID_HOME \
--okey=$OKEY --nkey=$NKEY
Withdrawal address whitelist management
Adding addresses to the withdrawal whitelist can be done one by one or by providing a comma-separated list of addresses using whitelist add.
Note that there is a 24h waiting period before any subsequent modification takes effect.
Bash
Copy
sekaid tx custody whitelist add \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--from=$SIGNER --chain-id=$NETWORK_NAME --home=$SEKAID_HOME \
--okey=$OKEY --nkey=$NKEY \
$ADDRESS
Bash
Copy
# Example
LIST="kira1kjx6g2sd5rev3dnuzqh8q9fznkq22qaz52kpt4,kira1j8d78jzk460a6tn8e22jm0ynmnvc79mg8h7t77,kira1lxeslhhus8qw63fxm4l0gphmf2flxajxg5l5tz"
sekaid tx custody whitelist add \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--from="kira1rxu5ltg5z63rl6du80xe45vghhy4cxlna5mzfm" --chain-id="localnet-1" --home="/root/.sekaid-localnet-1" \
--okey="e2d8ce14e4zf189zffze18f88619853b075143deea596c477b8dc077e309c0cece2d58" --nkey="e0bc614e4fd035a488619799853b075143deea596c477b8dc077e309c0fe42e9" \
$LIST
Removing an address from the whitelist is done using whitelist remove.
Removed addresses are not erased but simply set to false and can be switched back to true using whitelist add.
Bash
Copy
sekaid tx custody whitelist remove \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--from=$SIGNER --chain-id=$NETWORK_NAME --home=$SEKAID_HOME \
--okey=$OKEY --nkey=$NKEY \
$ADDRESS
All whitelisted addresses can be dropped at once using whitelist drop.
Dropping the whitelist will erase all addresses completely.
Bash
Copy
sekaid tx custody whitelist drop \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--from=$SIGNER --chain-id=$NETWORK_NAME --home=$SEKAID_HOME \
--okey=$OKEY --nkey=$NKEY
Send custody transaction
When custody_enabled is set to true, token transfers have to be performed with the custody send CLI and will be propagated once the quorum of custodians approval is reached. Additionally, if use_password is set totrue, the beneficiary will have to provide the digest of the password used for $PASSWORD. Note that the $PASSWORD argument always has to be provided (can be random value if not needed).
Note: A sufficient amount of —fees must be provided for the transaction to be valid which is at least N+1 times the standard transaction cost with N being the numbers of custodians required to reach quorum. Note, the'--from' flag is ignored as it is implied from [from_key_or_address].
Bash
Copy
sekaid tx custody send \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--chain-id=$NETWORK_NAME --home=$SEKAID_HOME \
$FROM $TO $COINS $PASSWORD
Bash
Copy
# Example (5 custodians to reach quorum = 600ukex fees)
sekaid tx custody send \
--fees=600ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--chain-id="localnet-1" --home="/root/.sekaid-localnet-1" \
--okey="e2d8ce14e4zf189zffze18f88619853b075143deea596c477b8dc077e309c0cece2d58" --nkey="e0bc614e4fd035a488619799853b075143deea596c477b8dc077e309c0fe42e9" \
kira1rxu5ltg5z63rl6du80xe45vghhy4cxlna5mzfm kira1lxeslhhus8qw63fxm4l0gphmf2flxajxg5l5tz 5000ukex "test"
Approve & decline transaction (Custodians)
Custodians can approve or decline incoming transactions using custody approve/ decline.
Bash
Copy
sekaid tx custody approve \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--chain-id=$NETWORK_NAME --home=$SEKAID_HOME \
$SENDER $HASH
Confirm transaction (Beneficiary)
When use_password is set totrue, the transfer beneficiary can confirm the transaction by providing the $PASSWORD using custody confirm.
Approve
Bash
Copy
sekaid tx custody confirm \
--fees=100ukex --keyring-backend=test --broadcast-mode=block --log_format=json --output=json \
--chain-id=$NETWORK_NAME --home=$SEKAID_HOME \
$SENDER $HASH $PASSWORD
Queries syntax & examples
Custody settings
The custody settings of a specific Kira address can be obtain using the get query.
Bash
Copy
sekaid query custody get $FROM --home=$SEKAID_HOME --chain-id=$NETWORK_NAME --output=json | jq
Which should return the following response:
JSON
Copy
{
"custody_settings": {
"custody_enabled": true,
"custody_mode": "33",
"use_password": false,
"use_white_list": false,
"use_limits": false,
"key": "e0bc614e4fd035a488619799853b075143deea596c477b8dc077e309c0fe42e9"
}
}
Custodians list & custody send pending transactions
The list of custodians addresses assigned to a Kira address can be obtained using the custodians get query CLI.
Bash
Copy
sekaid query custody custodians get $FROM --home=$SEKAID_HOME --chain-id=$NETWORK_NAME --output=json | jq
It will return the following response:
JSON
Copy
{
"custody_custodians": {
"addresses": {
"kira1j8d78jzk460a6tn8e22jm0ynmnvc79mg8h7t77": true,
"kira1kjx6g2sd5rev3dnuzqh8q9fznkq22qaz52kpt4": true,
"kira1lxeslhhus8qw63fxm4l0gphmf2flxajxg5l5tz": true
}
}
}
The list of transactions sent via custody send by a specific Kira address which are pending for custodians’ quorum approval can be obtained by using the custodians pool query.
Bash
Copy
sekaid query custody custodians pool $FROM --home=$SEKAID_HOME --chain-id=$NETWORK_NAME --output=json | jq
It will return the following response:
JSON
Copy
TODO
Transfer limits
The list of different transfer limits for specific token assigned to a Kira address can be obtained using the whitelist get query CLI.
Bash
Copy
sekaid query custody limits get $FROM --home=$SEKAID_HOME --chain-id=$NETWORK_NAME --output=json | jq
It will return the following response:
JSON
Copy
TODO
Withdrawal address whitelist
The list of whitelisted addresses assigned to a Kira address can be obtained using the whitelist get query CLI.
Bash
Copy
sekaid query custody whitelist get $FROM --home=$SEKAID_HOME --chain-id=$NETWORK_NAME --output=json | jq
It will return the following response:
JSON
Copy
{
"custody_white_list": {
"addresses": {
"kira1kjx6g2sd5rev3dnuzqh8q9fznkq22qaz52kpt4": true,
"kira1lxeslhhus8qw63fxm4l0gphmf2flxajxg5l5tz": true
}
}
}