Accounts
Klaytn Accounts
Overview of Account, State, and Address
An account in Klaytn is a data structure containing information about a person's balance or a smart contract. Klaytn's state is the collection of all its accounts' states - that is, the past and current state of all data stored across Klaytn's accounts. When a transaction is executed on a Klaytn node, the state of Klaytn consequently changes across all its nodes. The state should be the same across all nodes in the Klaytn network if they have processed the same blocks in the same order. State information of each account is associated with a 20-byte address, which is used to identify each account.
Decoupling Key Pairs From Addresses
An account in a typical blockchain platform is associated with a cryptographically processed address of a certain length that usually looks like this: "0x0fe2e20716753082222b52e753854f40afddffd2". This address is strongly coupled with a key pair. If a key pair is chosen, the address is derived from the public key. This has many disadvantages in terms of user experience. Some of them are the following:
It is impossible for users to have addresses they want.
It is impossible for users to use multiple key pairs to increase security of their accounts.
It is impossible for users to change the account's key pair when the private key is accidentally exposed or when users want to update the private key periodically to increase the account's security.
Those are big hurdles that users cannot think of an address as an identifier in the blockchain platform. To clear this hurdle, Klaytn provides a feature that users can choose their addresses and key pairs. With this feature, users can choose addresses that they want and they can use multiple key pairs to increase security. The number of key pairs can be one or more, and the key pairs can have different roles. For details of multiple key pairs or role-based keys, please refer to Multiple Key Pairs & Role-Based Keys.
It is worth noting that Klaytn also supports the old scheme that a key pair and an address are strongly coupled.
Multiple Key Pairs and Role-Based Keys
As described before, when the private key is stolen, exposed, or somehow compromised, there is nothing to do to restore the account’s security: the best option is to generate another key pair to create a new account, and migrate the balance from the old compromised account to the new one. Lack of support for advanced key schemes such as multi-sig or usage-specific key is yet another source of major inconvenience. To address those problems more efficiently, Klaytn accounts provide the following capabilities:
Klaytn account allows the key pair associated with the account to be changed.
Klaytn account supports multiple key pairs, along with the ability to assign each key with different purpose.
Klaytn account maintains compatibility with accounts having a single key that is strongly coupled with the address.
By utilizing Klaytn account’s role-based multi-key support, end-users can better handle real-life security risk situations such as private key mismanagement. For example, when a user realizes that his or her private key has been exposed, the user can simply replace the compromised private key by removing the exposed key pair from his or her account and creating a new key pair to replace them. This could be achieved by using a dedicated key used for updating account information, created in advance and stored separately from the compromised private key.
Human-Readable Address (HRA)
Although the address scheme (e.g., "0x0fe2e20716753082222b52e753854f40afddffd2") has its own strengths in that it efficiently protects the privacy of account holders, it also proposes major problems in terms of end-user experience. First, it is very difficult for a human brain to memorize, or even recognize, such addresses, making them prone to input mistakes and various human errors that often lead to non-trivial financial damages. Second, such scheme takes away from end-users the power to choose one’s own preferred identity handle that’s easier to memorize or use. Combined, these problems are among the toughest usability hurdles that cause dApp user experience for typical end-users (who are more accustomed to the simpler, frictionless user experience offered by legacy mobile apps or services) to be perceived as alien, incomprehensible, and severely inconvenient. To overcome such challenges without undergoing architectural modifications at large-scale and while preserving backward compatibility, Klaytn opts to provide a mapping between a 20-byte address to a 20-byte length text string that end-users could assign their own preferred values to. This feature in Klaytn is called human-readable address (HRA). Currently, this feature is under development, and we will provide more information when it is ready.
Klaytn Wallet Key Format
Klaytn wallet key format is provided to easily handle a private key along with the corresponding address. It makes easier for a user to maintain his/her private key with an address. The format is 0x{private key}0x{type}0x{address in hex}
in hexadecimal notation, where {type}
must be 00
. Other values are reserved. An example is shown below:
This format is currently supported in Klaytn Wallet.
Klaytn Account Types
There are two types of accounts in Klaytn: externally owned accounts (EOAs), and smart contract accounts (SCAs).
Externally Owned Accounts (EOAs)
Externally owned accounts have information such as nonce and balance. This type of accounts does not have code or storage. EOAs are controlled by private keys and do not have code associated with them. An EOA can be created using key pairs and subsequently controlled by anyone with the key pairs. The account key is described in the section Account Key.
Attributes
type
uint8 (Go)
The type of externally owned accounts. It must be 0x1 for EOAs.
nonce
uint64 (Go)
A sequence number used to determine the order of transactions. The transaction to be processed next has the same nonce with this value.
balance
*big.Int (Go)
The amount of KLAY the account has.
humanReadable
bool (Go)
A boolean value indicating that the account is associated with a human-readable address. Since HRA is under development, this value is false for all accounts.
key
The key associated with this account. This field can be any of AccountKeyLegacy, AccountKeyPublic, AccountKeyFail, AccountKeyWeightedMultisig, AccountKeyRoleBased. Signatures in transactions are verified with this key.
Smart Contract Accounts (SCAs)
In contrast to EOAs, SCAs have code associated with them and are controlled by their code. SCAs are created by smart contract deployment transactions; once deployed, an SCA cannot initiate new transactions by itself and must be triggered by another account, either by an EOA or another SCA.
Attributes
type
uint8 (Go)
The type of smart contract accounts. It must be 0x2 for SCAs.
nonce
uint64 (Go)
A sequence number used to determine the order of transactions. The transaction to be processed next has the same nonce with this value.
balance
*big.Int (Go)
The amount of KLAY the account has.
humanReadable
bool (Go)
A boolean value indicating that the account is associated with a human-readable address. Since HRA is under development, this value is false for all accounts.
key
The key associated with this account. This field can be any of AccountKeyLegacy, AccountKeyPublic, AccountKeyFail, AccountKeyWeightedMultisig, AccountKeyRoleBased. Signatures in transactions are verified with this key.
codeHash
[]byte (Go)
The hash of the account's smart contract code. This value is immutable, which means it is set only when the smart contract is created.
storageRoot
[32]byte (Go)
A 256-bit hash of the root of the Merkle Patricia Trie that contains the values of all the storage variables in the account.
codeFormat
uint8 (Go)
Supporting interpreter version. Up to 16 can be set. Currently, it supports EVM(0x00) only.
vmVersion
uint8 (Go)
The protocol upgrade (hard fork) information at contract deployment time (ex. 0x0(constantinople), 0x1(istanbul,london,...)). Up to 16 can be used. It is automatically created with the contract.
NOTE: From klaytn v1.7.0 onwards, vmVersion attribute will be added to the Smart Contract Account.
Klaytn Account Type ID
Below are the Account Type ID assigned to each Account Type.
Externally Owned Account (EOA)
0x1
Smart Contract Account (SCA)
0x2
Account Key
An account key represents the key structure associated with an account.
AccountKeyNil
AccountKeyNil represents an empty key. If an account tries to have an AccountKeyNil object, the transaction will be failed. AccountKeyNil is used only for TxTypeAccountUpdate transactions with role-based keys. For example, if an account tries to update RoleAccountUpdate key only, the key field of the TxTypeAccountUpdate transaction would be:
[AccountKeyNil, NewKey, AccountKeyNil]
Then, only the RoleAccountUpdate key is updated. Other roles are not updated. Refer to the AccountKeyRoleBased for more detail.
Attributes
No attributes for AccountKeyNil.
RLP Encoding
0x80
AccountKeyLegacy
AccountKeyLegacy is used for the account having an address derived from the corresponding key pair. If an account has AccountKeyLegacy, the transaction validation process is done like below (as typical Blockchain platforms did):
Get the public key from
ecrecover(txhash, txsig)
.Get the address of the public key.
The address is the sender.
Attributes
Type
uint8 (Go)
The type of AccountKeyLegacy. This must be 0x01.
RLP Encoding
0x01c0
AccountKeyPublic
AccountKeyPublic is used for accounts having one public key. If an account has an AccountKeyPublic object, the transaction validation process is done like below:
Get the public key derived from
ecrecover(txhash, txsig)
.Check that the derived public key is the same as the corresponding
account's public key.
Attributes
Type
uint8 (Go)
The type of AccountKeyPublic. This must be 0x02.
Key
[33]byte (Go)
Key should be a compressed public key on S256 curve.
RLP Encoding
0x02 + encode(CompressedPubKey)
NOTE: CompressedPubKey is a public key in a compressed format defined in SEC1. In short, 0x02{PubkeyX} if PubkeyY is an even number or 0x03{PubkeyX} otherwise.
RLP Encoding (Example)
AccountKeyFail
If an account has the key AccountKeyFail, the transaction validation process always fails. It can be used for smart contract accounts so that a transaction sent from the smart contract account always fails.
Attributes
Type
uint8 (Go)
The type of AcccountKeyFail. It must be 0x03.
RLP Encoding
0x03c0
AccountKeyWeightedMultiSig
AccountKeyWeightedMultiSig is an account key type containing a threshold and WeightedPublicKeys which contains a list consisting of a public key and its weight. In order for a transaction to be valid for an account associated with AccountKeyWeightedMultiSig, the following conditions should be satisfied:
The weighted sum of the signed public keys should be larger than the threshold.
The invalid signature should not be included in the transaction.
The number of signed public keys should be less than the number of weightedPublicKeys.
NOTE: The following multiSig validation logic has changed with the IstanbulEVM
protocol upgrade, or the "hard fork".
The invalid signature should not be included in the transaction.
The number of signed public keys should be less than the number of weightedPublicKeys. If you want the previous document, please refer to previous document.
IstanbulEVM
protocol upgrade block number is as follows.
Baobab Testnet:
#75373312
Cypress Mainnet:
#86816005
Attributes
Type
uint8 (Go)
The type of AccountKeyWeightedMultiSig. This must be 0x04.
Threshold
uint (Go)
Validation threshold. To be a valid transaction, the weight sum of signatures should be larger than or equal to the threshold.
WeightedPublicKeys
[]{uint, [33]byte} (Go)
A list of weighted public keys. A weighted public key contains a compressed public key and its weight.
RLP Encoding
0x04 + encode([threshold, [[weight, CompressedPubKey1], [weight2, CompressedPubKey2]]])
RLP Encoding (Example)
AccountKeyRoleBased
AccountKeyRoleBased represents a role-based key. The roles are specified at Roles.
Attributes
Type
uint8 (Go)
The type of AccountKeyRoleBased. It must be 0x05.
Keys
[]{AccountKey} (Go)
A list of keys. A key can be any of AccountKeyNil, AccountKeyLegacy, AccountKeyPublic, AccountKeyFail, and AccountKeyWeightedMultiSig.
Roles
Roles of AccountKeyRoleBased are defined as below:
RoleTransaction
Index 0. Default key. Transactions other than TxTypeAccountUpdate should be signed by the key of this role.
RoleAccountUpdate
Index 1. TxTypeAccountUpdate transaction should be signed by this key. If this key is not present in the account, TxTypeAccountUpdate transaction is validated using RoleTransaction key.
RoleFeePayer
Index 2. If this account wants to send tx fee instead of the sender, the transaction should be signed by this key. If this key is not present in the account, a fee-delegated transaction is validated using RoleTransaction key.
RLP Encoding
0x05 + encode([key1, key2, key3])
Note that key1, key2, and key3 can be any of above keys (AccountKeyNil, AccountKeyLegacy, AccountKeyPublic, AccountKeyFail, and AccountKeyWeightedMultiSig).
Omissible and Expandable Roles
The roles can be omitted from the last index, and the omitted roles are mapped to the first role. However, a role in the middle cannot be omitted, which means RoleTransaction and RoleFeePayer cannot be set without RoleAccountUpdate. For example, if a role-based key is set to 0x05 + encode([key1, key2])
, RoleFeePayer works as if the key is set like 0x05 + encode([key1, key2, key1])
.
This feature allows for more roles to be added in the future. If a new role is provided, the new role of accounts already created with old roles is mapped to the first role.
RLP Encoding (Example)
Account Key Type ID
Below are the Account Key Type ID assigned to each Account Key Type.
AccountKeyLegacy
0x01
AccountKeyPublic
0x02
AccountKeyFail
0x03
AccountKeyWeightedMultiSig
0x04
AccountKeyRoleBased
0x05
Last updated