# The Basics¶

## Block Lattice Design¶

Nano's ledger is built on a data-structure called a "Block Lattice." Every account (private/public key pair) has their own blockchain (account-chain). Only the holder of the private key may sign and publish blocks to their own account-chain. Each block represents a transaction.

Action Description
Send Send funds from users account to another account

The system is akin to writing (send) and cashing (receive) a Cashier's Check. There are a few things to consider about transactions:

• The receiving account does not have to be online during the Send transaction.
• The transaction will stay as pending indefinitely until a Receive transaction is created.
• Once funds are sent, they cannot be revoked by the sender.

## Representatives¶

The Nano Network achieves consensus using the unique Open Representative Voting (ORV) model. In this setup, representatives (accounts where nano_node with the private keys are running 24/7) vote on transactions.

Info

Below are some helpful things to remember about Nano's representatives and consensus:

• A representative's voting power is directly proportional to the amount of funds delegated to that account by other users of the protocol.
• An account's representative has no bearing on its transactions or nano_node operation.
• Choosing a representative with good uptime that is also a unique entity (to prevent sybil attacks) helps maintain high Nano network security.
• If an account's representative goes offline, the account's funds are no longer used to help secure the network; however, the account is unaffected.
• Anyone that runs a full-time node may be a representative and be delegated voting weight from other users of the protocol.
• An account can freely change its representative anytime within any transaction or explicitly by publishing a block which only changes the representative (sends no funds), which most wallets support.

## Proof-of-Work¶

Every Nano transaction contains a small Proof-of-Work (PoW) which is only used as an anti-spam measure. It is not used in the consensus mechanism.

Within the Nano Protocol, Proof-of-Work is used only as an anti-spam measure.

In general, PoW is the solving of a simple math problem where a solution can only be found by repeatedly guessing and checking. The harder the problem, the more guesses it takes on average to find an answer. Once found, the non-unique solution can then be verified with a single check. This allows computers to prove (on average) that they spent a certain amount of computation power.

Info

Nano's Proof of Work uses the blake2b cryptographic hash function

### Calculating Work¶

The "work" field in transactions contains a 64-bit nonce found using the blake2b hash function. The nonce satisfies the equation.

blake2b(\text{nonce} || \text{prev_block_hash}) \ge \text{threshold}

Currently the mainnet's base threshold is 0xffffffc000000000. When running a node the work is automatically calculated for you, but options exist for delegating work generation to work peers and allowing GPU acceleration by enabling OpenCL. With the addition of Dynamic PoW and rework in V19.0, the threshold used to calculate work can vary under certain conditions.

Info

At the base threshold, any random nonce has a $1.49 * 10^{-8}$ chance of being a correct solution. This results in an average of $67,108,864$ guesses to generate a valid nonce that requires only a single blake2b hash to validate.

#### First Account Block¶

The first block on an account-chain doesn't have a previous (head) block, so a variant of the above equation is used to calculate the "work" field:

blake2b(\text{nonce} || \text{public_key}) \ge \text{threshold}

### Difficulty Multiplier¶

Relative difficulty, or difficulty multiplier, describes how much more value a PoW has compared to another. In the node this is typically used to compare against the base threshold, often in relation to rework being performed or validated for the Dynamic PoW feature introduced in V19.0.

A multiplier can be obtained with the following expression.

\frac{(2^{64} - \text{base_difficulty})}{(2^{64} - \text{work_difficulty})}

In the inverse direction, in order to get the equivalent difficulty for a certain multiplier, the following expression can be used.

2^{64} - \frac{2^{64} - \text{base_difficulty}}{\text{multiplier}}
Code Snippets

Python

def to_multiplier(difficulty: int, base_difficulty) -> float:
return float((1 << 64) - base_difficulty) / float((1 << 64) - difficulty)

def from_multiplier(multiplier: float, base_difficulty: int = NANO_DIFFICULTY) -> int:
return int((1 << 64) - ((1 << 64) - base_difficulty) / multiplier)


Rust

fn to_multiplier(difficulty: u64, base_difficulty: u64) -> f64 {
(base_difficulty.wrapping_neg() as f64) / (difficulty.wrapping_neg() as f64)
}

fn from_multiplier(multiplier: f64, base_difficulty: u64) -> u64 {
(((base_difficulty.wrapping_neg() as f64) / multiplier) as u64).wrapping_neg()
}


C++

double to_multiplier(uint64_t const difficulty, uint64_t const base_difficulty) {
return static_cast<double>(-base_difficulty) / (-difficulty);
}

uint64_t from_multiplier(double const multiplier, uint64_t const base_difficulty) {
return (-static_cast<uint64_t>((-base_difficulty) / multiplier));
}


## Account, Key, Seed and Wallet IDs¶

When dealing with the various IDs in the node it is important to understand the function and implication of each one.

Similar IDs, Different Functions

There are several things that can have a similar form but may have very different functions, and mixing them up can result in loss of funds. Use caution when handling them.

### Wallet ID¶

This is a series of 32 random bytes of data and is not the seed. It is used in several RPC actions and command line options for the node. It is a purely local UUID that is a reference to a block of data about a specific wallet (set of seed/private keys/info about them) in your node's local database file.

The reason this is necessary is because we want to store information about each account in a wallet: whether it's been used, what its account is so we don't have to generate it every time, its balance, etc. Also, so we can hold ad hoc accounts, which are accounts that are not derived from the seed. This identifier is only useful in conjunction with your node's database file and it will not recover funds if that database is lost or corrupted.

This is the value that you get back when using the wallet_create etc RPC commands, and what the node expects for RPC commands with a "wallet" field as input.

### Seed¶

This is a series of 32 random bytes of data, usually represented as a 64 character, uppercase hexadecimal string (0-9A-F). This value is used to derive account private keys for accounts by combining it with an index and then putting that into the following hash function where || means concatentation and i is a 32bit unsigned integer: PrivK[i] = blake2b(outLen = 32, input = seed || i)

Private keys are derived deterministically from the seed, which means that as long as you put the same seed and index into the derivation function, you will get the same resulting private key every time. Therefore, knowing just the seed allows you to be able to access all the derived private keys from index 0 to 2^32 - 1 (because the index value is a unsigned 32 bit integer).

Wallet implementations will commonly start from index 0 and increment it by 1 each time you create a new account so that recovering accounts is as easy as importing the seed and then repeating this account creation process.

### Account private key¶

This is also a 32 byte value, usually represented as a 64 character, uppercase hexadecimal string(0-9A-F). It can either be random (an ad-hoc key) or derived from a seed, as described above. This is what represents control of a specific account on the ledger. If you know or can know the private key of someone's account, you can transact as if you own that account.

### Account public key¶

This is also a 32 byte value, usually represented as a 64 character, uppercase hexadecimal string (0-9A-F). It is derived from an account private key by using the ed25519 curve using blake2b as the hash function (instead of sha). Usually account public keys will not be passed around in this form, rather the below address is used.

This is what you think of as someone's Nano address: it's a string that starts with nano_ (previously xrb_), then has 52 characters which are the account public key but encoded with a specific base32 encoding algorithm to prevent human transcription errors by limiting ambiguity between different characters (no O and 0 for example). Then the final 8 characters are a checksum of the account public key to aid in discovering typos, also encoded with the same base32 scheme.

So for address nano_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs:

Prefix Encoded Account Public Key Checksum
nano_ 1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjt wnqposrs

For basic address validation, the following regular expression can be used: ^(nano|xrb)_[13]{1}[13456789abcdefghijkmnopqrstuwxyz]{59}\$. Validation of the checksum is also recommended, depending on the integration.

Prefixes: nano_ vs. xrb_

As of V19.0 the Nano node only returns nano_ addresses in all actions, but prior versions returned xrb_ addresses. These prefixes are interchangeable — everything after the _ remains the same. If you have an issue using one or the other prefix with any exchange or service, you can safely switch between nano_ and xrb_ prefixes as needed — they both represent the same account owned by your private key or seed.

## Units¶

Nano can be represented using more than one unit of measurement. While the most common unit is the $nano$, the smallest unit is the $raw$. Below is the formula for converting between $raw$ and $nano$.

1 nano = 10^{30} raw

Important

• All RPC commands expect units to be represented as $raw$.
• Always keep units in integer $raw$ amounts to prevent any floating-point error or unit confusion.
• Depending on your implementation language, you may require a big number library to perform arithmetic directly on $raw$.
• See Distribution and Units page for more details on units.
• Because final balances are recorded rather than transaction amounts, API calls must be done carefully to avoid loss of funds. Incorrect arithmetic or use of fields may change an intended receive to a send to a non-existent address.

## Blocks Specifications¶

All new transactions on the Nano Protocol are communicated via blocks. The account's entire state, including the balance after each transaction, is recorded in every block. Transaction amounts are interpreted as the difference in balance between consecutive blocks.

If an account balance decreases, the transaction that caused the decrease is considered a send. Similarly, if an account balance increases, the transaction that caused the increase is considered a receive.

Important

Because final balances are recorded rather than transaction amounts, API calls must be done carefully to avoid sending erroneous amounts.

### Block Format¶

Because each block contains the current state of the account, the "type" of the block is always "state". The following table presents the anatomy of a block, along with the format used within RPC calls for building blocks, and the serialized, binary representation:

Key RPC Format Serialized Description
type string - "state"
account string 32 bytes This account's nano_ address
previous 64 hex-char string 32 bytes Previous head block on account; 0 if open block
representative string 32 bytes Representative nano_ address
balance decimal string 16 bytes Resulting balance (in raw)
signature 128 hex-char string 64 bytes ED25519+Blake2b 512-bit signature
work 16 hex-char string 8 bytes Proof of Work Nonce

Depending on the action each transaction intends to perform, the "link" field will have a different value for block_create RPC command:

Action RPC Format Description
Change string Must be "0"
Receive 64 hex-char string Pairing block's hash (block sending funds)

Note

• Any transaction may also simultaneously change the representative. The above description of the "Change" action is for creating a block with an explicit representative change where no funds are transferred (balance is not changed).
• In the completed, signed transaction json, the "link" field is always hexadecimal.
• The first block on an account must be receiving funds (cannot be an explicit representative change). The first block is often referred to as "opening the account".

### Self-Signed Blocks¶

If you choose to implement your own signing, the order of data (in bytes) to hash prior to signing is as follows.

• All values are binary representations
• No ASCII/UTF-8 strings.

Order of data:

1. block preamble (32-Bytes, value 0x6)
2. account (32-Bytes)
3. previous (32-Bytes)
4. representative (32-Bytes)
5. balance (16-Bytes)

The digital signing algorithm (which internally applies another Blake2b hashing) is applied on the resulting digest.

Private/public key usage

Make sure that your private key uses the correct partnering public key while signing as using an incorrect public key may leak information about your private key.

### Block Creation Examples¶

Read these examples in order to correctly interpret balances and block hashes on the example account-chain.

Note

All example "work" values included in the responses are not valid (0000000000000000).

Scenario

• Address creates block sending 5 $nano$ to nano_3igf8hd4sjshoibbbkeitmgkp1o6ug4xads43j6e4gqkj5xk5o83j8ja9php
• Hash of block sending funds is B2EC73C1F503F47E051AD72ECB512C63BA8E1A0ACC2CEE4EA9A22FE1CBDB693F
• We want to receive the pending 5 $nano$ into this new (unopened) account

Action

• Create a block to receive Nano for account: nano_3igf8hd4sjshoibbbkeitmgkp1o6ug4xads43j6e4gqkj5xk5o83j8ja9php account-chain.
• Sets nano_3p1asma84n8k84joneka776q4egm5wwru3suho9wjsfyuem8j95b3c78nw8j as the representative.
• This receives the block hash B2EC73C1F503F47E051AD72ECB512C63BA8E1A0ACC2CEE4EA9A22FE1CBDB693F and because this is the first block on the account, the account is considered "opened".
curl -d '{
"action":"block_create",
"json_block": "true",
"type":"state",
"previous":"FC5A7FB777110A858052468D448B2DF22B648943C097C0608D1E2341007438B0",
"representative":"nano_3p1asma84n8k84joneka776q4egm5wwru3suho9wjsfyuem8j95b3c78nw8j",
"balance":"5000000000000000000000000000000",
"wallet":"557832FF41BAF4860ED4D7023E9ACE74F1427C3F8232B6AFFB491D98DD0EA1A2"
}' http://127.0.0.1:7076

{
"block": {
"type": "state",
"previous": "FC5A7FB777110A858052468D448B2DF22B648943C097C0608D1E2341007438B0",
"representative": "nano_3p1asma84n8k84joneka776q4egm5wwru3suho9wjsfyuem8j95b3c78nw8j",
"balance": "5000000000000000000000000000001",
"work": "0000000000000000"
}
}


Info

• The "balance" field is in $raw$ format. For more information, see units.
• Take note of the field "link_as_account". This is if the "link" field were to be interpreted as a 256-bit public key and translated into an "nano_..." address. This field is only provided for convenience and is stripped away before it is broadcast to the network.
• If you are creating and signing your own blocks external to nano_node, you do not need to include a "link_as_account" field.

#### Send¶

Scenario

• We want to send from our account nano_3igf8hd4sjshoibbbkeitmgkp1o6ug4xads43j6e4gqkj5xk5o83j8ja9php.
• We want to send 2 $nano$ to account nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p.

Response

curl -d '{
"action":"block_create",
"type":"state",
"representative":"nano_3p1asma84n8k84joneka776q4egm5wwru3suho9wjsfyuem8j95b3c78nw8j",
"balance":"3000000000000000000000000000000",
"wallet":"557832FF41BAF4860ED4D7023E9ACE74F1427C3F8232B6AFFB491D98DD0EA1A2"
}' http://127.0.0.1:7076

{
"hash": "128106287002E595F479ACD615C818117FCB3860EC112670557A2467386249D4",
"block": {
"type": "state",
"representative": "nano_3p1asma84n8k84joneka776q4egm5wwru3suho9wjsfyuem8j95b3c78nw8j",
"balance": "3000000000000000000000000000000",
"signature": "D7975EE2F6FAE1FC7DA336FB9DD5F7E30FC1A6825021194E614F0588073D1A4901E34E3CAE8739F1DE2FD85A73D2A0B26F8BE6539E0548C9A45E1C1887BFFC05",
"work": "0000000000000000"
}
}


Info

Because the account balance was reduced from 5000000000000000000000000000000 $raw$ to 3000000000000000000000000000000 $raw$, the block is interpreted as a send. The "link" field is populated with the public key of the account we are sending to.

#### Change¶

Scenario

• We want to change the representative of our account nano_3igf8hd4sjshoibbbkeitmgkp1o6ug4xads43j6e4gqkj5xk5o83j8ja9php
• We want the representative to be nano_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs

Response

curl -d '{
"action":"block_create",
"type":"state",
"previous":"128106287002E595F479ACD615C818117FCB3860EC112670557A2467386249D4",
"representative":"nano_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs",
"balance":"3000000000000000000000000000000",
"wallet":"557832FF41BAF4860ED4D7023E9ACE74F1427C3F8232B6AFFB491D98DD0EA1A2"
}' http://127.0.0.1:7076

{
"hash": "2A322FD5ACAF50C057A8CF5200A000CF1193494C79C786B579E0B4A7D10E5A1E",
"block": {
"type": "state",
"previous": "128106287002E595F479ACD615C818117FCB3860EC112670557A2467386249D4",
"representative": "nano_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs",
"balance": "3000000000000000000000000000000",
"signature": "7E9A7B368DBEB280B01C22633DC82F6CEF00F529E07B76A0232614D2BCDAF85BF52AC9DA4DBE4468B6F144CE82F2FDE44080C8363F903A6EC3D999252CB1E801",
"work": "0000000000000000"
}
}


Note

Note that the ""link" field is all 0's. As another sanity check, we notice the all 0 public key gets translated into the burn address nano_1111111111111111111111111111111111111111111111111111hifc8npp

#### Change & Send¶

Scenario

• We want to change our representative at the same time we perform a send or receive of funds.
• We want to send 2 more $nano$ to account nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p
• We want to revert our representative back to nano_3p1asma84n8k84joneka776q4egm5wwru3suho9wjsfyuem8j95b3c78nw8j

Response

curl -d '{
"action":"block_create",
"type":"state",
"previous":"2A322FD5ACAF50C057A8CF5200A000CF1193494C79C786B579E0B4A7D10E5A1E",
"representative":"nano_3p1asma84n8k84joneka776q4egm5wwru3suho9wjsfyuem8j95b3c78nw8j",
"balance":"1000000000000000000000000000000",
"wallet":"557832FF41BAF4860ED4D7023E9ACE74F1427C3F8232B6AFFB491D98DD0EA1A2"
}' http://127.0.0.1:7076

{
"hash": "9664412A834F0C27056C7BC4A363FBAE86DF8EF51341A5A5EA14061727AE519F",
"block": {
"type": "state",
"previous": "2A322FD5ACAF50C057A8CF5200A000CF1193494C79C786B579E0B4A7D10E5A1E",
"representative": "nano_3p1asma84n8k84joneka776q4egm5wwru3suho9wjsfyuem8j95b3c78nw8j",
"balance": "1000000000000000000000000000000",
"signature": "4D388F982188E337D22E0E66CD24BCABD09BED1E920940C453039B55B6A4724D7BD106019AACC1840480938FF4FA024F041E6E6A32B3641C28E0262025020B03",
"work": "0000000000000000"
}
}


## URI and QR Code Standards¶

Note: amount values should always be in RAW.

Note: Please use nano:// for deep links

nano:nano_<encoded address>[?][amount=<raw amount>][&][label=<label>][&][message=<message>]


nano:nano_3wm37qz19zhei7nzscjcopbrbnnachs4p1gnwo5oroi3qonw6inwgoeuufdp


Address and an amount (as RAW)

nano:nano_3wm37qz19zhei7nzscjcopbrbnnachs4p1gnwo5oroi3qonw6inwgoeuufdp?amount=1000


nano:nano_3wm37qz19zhei7nzscjcopbrbnnachs4p1gnwo5oroi3qonw6inwgoeuufdp?label=Developers%20Fund%20Address


Send to an address with amount, label and message

nano:nano_3wm37qz19zhei7nzscjcopbrbnnachs4p1gnwo5oroi3qonw6inwgoeuufdp?amount=10&label=Developers%20Fund&message=Donate%20Now


### Representative change¶

nanorep:nano_<encoded address>[?][label=<label>][&][message=<message>]


Change to representative with label and message

nanorep:nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou?label=Official%20Rep%202&message=Thank%20you%20for%20changing%20your%20representative%21


### Private Key Import¶

nanokey:<encoded private key>[?][label=<label>][&][message=<message>]


### Seed Import¶

nanoseed:<encoded seed>[?][label=<label>][&][message=<message>][&][lastindex=<index>]


### Process a JSON blob block¶

(to be sent as the block argument to the RPC call process)

nanoblock:<blob>