Repository: nanocurrency/nano-docs Branch: main Commit: cfb6ed4239ca Files: 172 Total size: 815.0 KB Directory structure: gitextract_g8vbq387/ ├── .github/ │ └── workflows/ │ ├── build.yml │ ├── cleanup-docker-pr.yml │ ├── cleanup-docker-untagged.yml │ ├── deploy-staging.yml │ ├── deploy.yml │ ├── publish-docker-master.yml │ ├── publish-docker-pr.yml │ └── push-to-staging.yml ├── .gitignore ├── Dockerfile ├── deploy-key.enc ├── docs/ │ ├── CNAME │ ├── articles/ │ │ └── readme.md │ ├── commands/ │ │ ├── command-line-interface.md │ │ └── rpc-protocol.md │ ├── core-development/ │ │ ├── code-standards.md │ │ ├── collaboration-process.md │ │ ├── developer-discussions.md │ │ ├── overview.md │ │ └── understanding-the-code.md │ ├── glossary.md │ ├── index.md │ ├── integration-guides/ │ │ ├── advanced.md │ │ ├── block-confirmation-tracking.md │ │ ├── build-options.md │ │ ├── index.md │ │ ├── ipc-integration.md │ │ ├── key-management.md │ │ ├── the-basics.md │ │ ├── websockets.md │ │ └── work-generation.md │ ├── javascript/ │ │ └── mermaid-loose-security.js │ ├── living-whitepaper/ │ │ └── index.md │ ├── node-implementation/ │ │ ├── blocks.md │ │ ├── components.md │ │ ├── database.md │ │ ├── introduction.md │ │ ├── networking.md │ │ ├── voting.md │ │ └── work.md │ ├── protocol-design/ │ │ ├── attack-vectors.md │ │ ├── blocks.md │ │ ├── distribution-and-units.md │ │ ├── introduction.md │ │ ├── ledger.md │ │ ├── networking.md │ │ ├── orv-consensus.md │ │ ├── resource-usage.md │ │ ├── signing-hashing-and-key-derivation.md │ │ └── spam-work-and-prioritization.md │ ├── releases/ │ │ ├── network-upgrades.md │ │ ├── node-releases.md │ │ ├── release-v19-0.md │ │ ├── release-v20-0.md │ │ ├── release-v21-0.md │ │ ├── release-v21-1.md │ │ ├── release-v21-2.md │ │ ├── release-v21-3.md │ │ ├── release-v22-0.md │ │ ├── release-v22-1.md │ │ ├── release-v23-0.md │ │ ├── release-v23-1.md │ │ ├── release-v23-3.md │ │ ├── release-v24-0.md │ │ ├── release-v25-0.md │ │ ├── release-v25-1.md │ │ ├── release-v26-0.md │ │ ├── release-v26-1.md │ │ ├── release-v27-0.md │ │ ├── release-v27-1.md │ │ ├── release-v28-0.md │ │ ├── release-v28-1.md │ │ ├── release-v28-2.md │ │ └── roadmap.md │ ├── running-a-node/ │ │ ├── advanced-monitoring.md │ │ ├── beta-network.md │ │ ├── beyond-the-node.md │ │ ├── configuration.md │ │ ├── docker-management.md │ │ ├── ledger-management.md │ │ ├── logging-tracing.md │ │ ├── node-setup.md │ │ ├── overview.md │ │ ├── security.md │ │ ├── test-network.md │ │ ├── troubleshooting.md │ │ ├── voting-as-a-representative.md │ │ └── wallet-setup.md │ ├── snippets/ │ │ ├── community-links.md │ │ ├── config-node-option-node-enable-voting-true.md │ │ ├── config-node-option-rpc-enable-control-false.md │ │ ├── config-node-option-rpc-enable-control-true.md │ │ ├── config-node-option-rpc-enable-true.md │ │ ├── contributing-code.md │ │ ├── current-build-links-all.md │ │ ├── current-build-links-beta.md │ │ ├── current-build-links-main.md │ │ ├── current-build-links-test.md │ │ ├── dedicated-representative-nodes.md │ │ ├── deprecation-info-pending.md │ │ ├── directory-contents.md │ │ ├── directory-locations-all.md │ │ ├── directory-locations-beta.md │ │ ├── directory-locations-main.md │ │ ├── directory-locations-test.md │ │ ├── docker-ipv6-tip.md │ │ ├── docker-run-command-beta.md │ │ ├── docker-run-command-main.md │ │ ├── docker-run-command-test.md │ │ ├── enable-voting.md │ │ ├── hardware-recommendations.md │ │ ├── join-technical-mailing-list.md │ │ ├── known-issue-macos-too-many-open-files.md │ │ ├── known-issue-peers-stake-reporting.md │ │ ├── known-issue-unable-to-find-libboost.md │ │ ├── known-issue-unchecked-keys-rpc-rocksdb.md │ │ ├── known-issue-windows-logging-stable.md │ │ ├── network-details-simple-beta.md │ │ ├── network-details-simple-main.md │ │ ├── network-details-simple-test.md │ │ ├── network-details.md │ │ ├── release-details-v18-0.md │ │ ├── release-details-v19-0.md │ │ ├── release-details-v20-0.md │ │ ├── release-details-v21-0.md │ │ ├── release-details-v21-1.md │ │ ├── release-details-v21-2.md │ │ ├── release-details-v21-3.md │ │ ├── release-details-v22-0.md │ │ ├── release-details-v22-1.md │ │ ├── release-details-v23-0.md │ │ ├── release-details-v23-1.md │ │ ├── release-details-v23-3.md │ │ ├── release-details-v24-0.md │ │ ├── release-details-v25-0.md │ │ ├── release-details-v25-1.md │ │ ├── release-details-v26-0.md │ │ ├── release-details-v26-1.md │ │ ├── release-details-v27-0.md │ │ ├── release-details-v27-1.md │ │ ├── release-details-v28-0.md │ │ ├── release-details-v28-1.md │ │ ├── release-details-v28-2.md │ │ ├── release-details-v29-0.md │ │ ├── security-vulnerability-reporting.md │ │ ├── setup-beta-test-testing.md │ │ ├── terms-block-transaction-transfer.md │ │ ├── toml-config-commands.md │ │ ├── unconfirmed-information.md │ │ ├── warning-alternative-work-generation-setup-preferred.md │ │ ├── warning-debug-only-command.md │ │ ├── warning-docker-limitations.md │ │ ├── warning-enable-control.md │ │ ├── warning-external-libraries.md │ │ ├── warning-includes-unconfirmed.md │ │ ├── warning-multiple-confirmation-notifications.md │ │ ├── warning-multiple-node-setups.md │ │ ├── warning-node-wallet-not-for-prod-use.md │ │ ├── warning-only-official-builds-supported.md │ │ ├── warning-process-sub-type-recommended.md │ │ ├── warning-security-vulnerability-reporting.md │ │ ├── warning-telemetry-can-be-forged.md │ │ ├── warning-unsupported-configuration.md │ │ └── wip-living-whitepaper.md │ ├── stylesheets/ │ │ └── extras.css │ ├── what-is-nano/ │ │ └── overview.md │ └── whitepaper/ │ └── english.md ├── mkdocs.yml ├── readme.md ├── requirements.txt └── theme-overrides/ ├── main.html └── partials/ └── footer.html ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/build.yml ================================================ name: build on: pull_request jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 #v3.1.0 - uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 #v4.3.0 with: python-version: 3.x - run: pip install -r requirements.txt - run: mkdocs build --strict env: GH_TOKEN: ${{ secrets.GH_TOKEN }} ================================================ FILE: .github/workflows/cleanup-docker-pr.yml ================================================ name: cleanup-docker-pr on: pull_request: types: [closed] env: PR_NUMBER: ${{ github.event.number }} OWNER: orgs/nanocurrency PACKAGE_NAME: nano-docs PER_PAGE: 100 jobs: container_cleanup: runs-on: ubuntu-latest steps: - name: Clean up PR specific container uses: actions/github-script@d556feaca394842dc55e4734bf3bb9f685482fa0 #v6.3.3 with: github-token: ${{ secrets.GHCR_TOKEN }} script: | const response = await github.request("GET /${{ env.OWNER }}/packages/container/${{ env.PACKAGE_NAME }}/versions", { per_page: ${{ env.PER_PAGE }} }); for(version of response.data) { if (version.metadata.container.tags[0] == "pr-${{ env.PR_NUMBER }}") { console.log("delete " + version.id) const deleteResponse = await github.request("DELETE /${{ env.OWNER }}/packages/container/${{ env.PACKAGE_NAME }}/versions/" + version.id, { }); console.log("status " + deleteResponse.status) } } ================================================ FILE: .github/workflows/cleanup-docker-untagged.yml ================================================ name: cleanup-docker-untagged on: push: branches: - main env: OWNER: orgs/nanocurrency PACKAGE_NAME: nano-docs PER_PAGE: 100 jobs: container_cleanup: runs-on: ubuntu-latest steps: - name: Clean up untagged containers uses: actions/github-script@d556feaca394842dc55e4734bf3bb9f685482fa0 #v6.3.3 with: github-token: ${{ secrets.GHCR_TOKEN }} script: | const response = await github.request("GET /${{ env.OWNER }}/packages/container/${{ env.PACKAGE_NAME }}/versions", { per_page: ${{ env.PER_PAGE }} }); for(version of response.data) { if ( version.metadata.container.tags.length == 0 ) { console.log("delete " + version.id) const deleteResponse = await github.request("DELETE /${{ env.OWNER }}/packages/container/${{ env.PACKAGE_NAME }}/versions/" + version.id, { }); console.log("status " + deleteResponse.status) } } ================================================ FILE: .github/workflows/deploy-staging.yml ================================================ name: deploy on: push: branches: - staging jobs: deploy: runs-on: ubuntu-latest env: PRODUCTION: TRUE if: github.repository == 'nanocurrency/nano-docs-staging' steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: 3.x - run: pip install -r requirements.txt - run: mkdocs gh-deploy --force env: GH_TOKEN: ${{ secrets.GH_TOKEN }} ================================================ FILE: .github/workflows/deploy.yml ================================================ name: deploy on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest env: PRODUCTION: TRUE steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: 3.x - run: pip install -r requirements.txt - run: mkdocs gh-deploy --force env: GH_TOKEN: ${{ secrets.GH_TOKEN }} ================================================ FILE: .github/workflows/publish-docker-master.yml ================================================ name: publish-docker-master on: push: branches: - main jobs: build_publish: runs-on: ubuntu-latest env: PRODUCTION: TRUE steps: - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 #v3.1.0 # Build and test Docker image - run: | echo ${{ secrets.GHCR_TOKEN }} | docker login ghcr.io -u nanocurrency --password-stdin docker pull squidfunk/mkdocs-material:9.4.10@sha256:01605a03397a654b74b9de3157f56915d1e075e2d3bd22fcf3fb82c443553c25 docker build -t ghcr.io/nanocurrency/nano-docs:latest . docker push ghcr.io/nanocurrency/nano-docs:latest ================================================ FILE: .github/workflows/publish-docker-pr.yml ================================================ name: publish-docker-pr on: pull_request env: PR_NUMBER: ${{ github.event.number }} jobs: build_publish: runs-on: ubuntu-latest env: PRODUCTION: TRUE steps: - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 #v3.1.0 # Build and test Docker image - run: | echo ${{ secrets.GHCR_TOKEN }} | docker login ghcr.io -u nanocurrency --password-stdin docker pull squidfunk/mkdocs-material:9.4.10@sha256:01605a03397a654b74b9de3157f56915d1e075e2d3bd22fcf3fb82c443553c25 docker build -t ghcr.io/nanocurrency/nano-docs:pr-${{ env.PR_NUMBER }} . docker push ghcr.io/nanocurrency/nano-docs:pr-${{ env.PR_NUMBER }} ================================================ FILE: .github/workflows/push-to-staging.yml ================================================ name: push-to-staging on: workflow_dispatch: inputs: branch: description: "nano-docs branch to push to staging" default: "staging" required: true jobs: push: runs-on: ubuntu-latest steps: - name: push uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 #v3.1.0 with: fetch-depth: 0 ref: ${{ github.event.inputs.branch }} token: ${{ secrets.GH_TOKEN }} - run: | git remote add nano-docs-staging https://github.com/nanocurrency/nano-docs-staging.git git push nano-docs-staging ${{ github.event.inputs.branch }}:staging ================================================ FILE: .gitignore ================================================ site/ .idea venv .cache ================================================ FILE: Dockerfile ================================================ FROM squidfunk/mkdocs-material:9.4.10@sha256:01605a03397a654b74b9de3157f56915d1e075e2d3bd22fcf3fb82c443553c25 # Set build directory #WORKDIR /docs # Copy files necessary for build COPY ./ /docs RUN \ pip install --upgrade pip && \ pip install -r /docs/requirements.txt # Set working directory WORKDIR /docs # Expose MkDocs development server port EXPOSE 8000 # Start development server by default ENTRYPOINT ["mkdocs"] CMD ["serve", "--dev-addr=0.0.0.0:8000"] ================================================ FILE: docs/CNAME ================================================ docs.nano.org ================================================ FILE: docs/articles/readme.md ================================================ Please see https://github.com/nanocurrency/nano-docs/issues/555 for details the article management process and list of ideas. ================================================ FILE: docs/commands/command-line-interface.md ================================================ title: Command Line Interface description: Reference for the CLI commands available for the nano node # Command Line Interface ## nano_node commands | Command | Description | |---------|-------------| | `--account_create --wallet=` | Insert next deterministic key into `` | | `--account_get --key=` | Get account number for the `` | | `--account_key --account=` | Get the public key for `` | | `--clear_send_ids` | Remove all send IDs from the database (dangerous: not intended for production use). Optional `--data_path=`| | `--compare_rep_weights` | Displays a summarized comparison between the hardcoded bootstrap weights and representative weights from the ledger. Full comparison is output to logs. Optional `--data_path=`. | | `--confirmation_height_clear` | Requires `--account` and sets the confirmation heights of the specified account to 0. Use `all` to reset all accounts. Do not use while the node is running. | | `--daemon` | Start node daemon. Network and path will be output. | | `--diagnostics` | Run internal diagnostics and validate existing config file (or create default config file if it doesn't exist). | | `--final_vote_clear` | Either specify a single `--root` to clear or `--all` to clear all final votes (not recommended). | | `--generate_config node|rpc|log` | Write configuration to stdout, populated with commented-out defaults suitable for this system. Use `--use_defaults` for uncommented values. | | `--help` | Print out options. | | `--initialize` | Initializes the data folder, if it is not already initialized. Meant for an empty data folder. | | `--key_create` | Generates an adhoc random keypair and prints it to stdout. | | `--key_expand --key=` | Derive public key and account number from ``. | | `--migrate_database_lmdb_to_rocksdb` | Deletes existing rocksdb subfolder if it exists and migrates the ledger from LMDB to RocksDB. Does not delete the data.ldb file afterwards. Optional `--data_path=` | | `--online_weight_clear` | Clear record history for long term online weight trending. Optional `--data_path=`| | `--peer_clear` | Clear cached peers. Optional `--data_path=`| | `--rebuild_database` | Rebuild LMDB database with `--vacuum` for best compaction. Requires approximately `data.ldb size * 2` free space on disk. | | `--snapshot` | Compact database and create snapshot, functions similar to vacuum but does not replace the existing database. Optional: `--unchecked_clear`, `--clear_send_ids`, `--online_weight_clear`, `--peer_clear`, `--confirmation_height_clear`. | | `--unchecked_clear` | Clear unchecked blocks. Optional `--data_path=`| | `--update_config`| Reads the current node configuration and updates it with missing keys and values and delete keys that are no longer used. Updated configuration is written to stdout. | | `--vacuum` | Compact database. If `data_path` is missing, the database in the data directory is compacted. Optional: `--unchecked_clear`, `--clear_send_ids`, `--online_weight_clear`, `--peer_clear`, `--confirmation_height_clear`, `--rebuild_database`. Requires approximately `data.ldb size * 2` free space on disk. | | `--validate_blocks` | Validate blocks in the ledger, includes checks for confirmation height. Optional `--threads` for multithreaded validation. | | `--version` | Prints out version. | | `--wallet_add_adhoc`
  `--wallet=`
  `--key=` | Insert `` into ``. | | `--wallet_create`
  `--seed=`
  `--password=` | Creates a new wallet with optional `` and optional ``, and prints the ID. | | `--wallet_change_seed`
  `--wallet=`
  `--seed=` | Changes seed for `` to ``. | | `--wallet_decrypt_unsafe`
  `--wallet=`
  `--password=` | Decrypts `` using ``.
**USE WITH CAUTION: THIS WILL PRINT YOUR PRIVATE KEY AND SEED TO STDOUT** | | `--wallet_destroy --wallet=` | Destroys `` and all keys it contains. | | `--wallet_import`
  `--file=`
  `--wallet=`
  `--password=` | Imports keys in `` using `` into ``. If the wallet id does not exist and `--force` is included, a new wallet will be created with the provided wallet id value. | | `--wallet_list` | Dumps wallet IDs and public keys. | | `--wallet_remove`
  `--wallet=`
  `--account=` | Remove `` from ``. | | `--wallet_representative_get`
  `--wallet=` | Prints default representative for ``. | | `--wallet_representative_set`
`--wallet=`
  `--account=` | Set `` as default representative for ``. | ## Launch Options The node is typically run like this: ```bash ./nano_node --daemon [--launch_options] ``` !!! note "Intended for developer use" These options are only for developer use so please understand the impacts before use. | Option | Description | |--------|-------------| | `--network` | Allows selection of a different network at runtime. Values `live`, `beta` and `test` supported. | | `--data_path=` | Use the supplied `` as the data directory. | | `--config key=value` | Pass node configuration values. This takes precedence over any values in the configuration file. This option can be repeated multiple times. | | `--rpcconfig key=value` | Pass RPC configuration values. This takes precedence over any values in the configuration file. This option can be repeated multiple times. | | `--enable_pruning` | "Enable experimental ledger pruning" | | `--block_processor_batch_size` | Increase block processor transaction batch write size, default 0 (limited by config block_processor_batch_max_time), 256k for fast_bootstrap. | | `--block_processor_full_size` | Increase block processor allowed blocks queue size before dropping live network packets and holding bootstrap download, default 65536, 1 million for fast_bootstrap. | | `--block_processor_verification_size` | Increase batch signature verification size in block processor, default 0 (limited by config signature_checker_threads), unlimited for fast_bootstrap. | | `--fast_bootstrap` | **legacy bootstrap:** Increase bootstrap processor limits to allow more blocks before hitting full state and verify/write more per database call. Also disable deletion of processed unchecked blocks. | | `--allow_bootstrap_peers_duplicates` | **legacy bootstrap:** Allow multiple connections to the same peer in bootstrap attempts. | | `--inactive_votes_cache_size` | Increase cached votes without active elections size, default 16384. | | `--vote_processor_capacity` | Vote processor queue size before dropping votes, default 144k. | | `--disable_activate_successors` | Disables activate_successors in active_elections | | `--disable_add_initial_peers` | Disables the add initial peers function called on startup which reads the peers table and contacts all the peers listed in it. | | `--disable_ascending_bootstrap` | Disable ascending bootstrap | | `--disable_backup` | Turn off automatic wallet backup process. | | `--disable_block_processor_republishing` | Disables block republishing by disabling the local_block_broadcaster component | | `--disable_block_processor_unchecked_deletion` | Disable deletion of unchecked blocks after processing. | | `--disable_bootstrap_bulk_pull_server` | Disables the legacy bulk pull server for bootstrap operations | | `--disable_bootstrap_bulk_push_client` | Disables the legacy bulk push client for bootstrap operations | | `--disable_bootstrap_listener` | Turn off listener on the bootstrap network so incoming TCP (bootstrap) connections are rejected. Note: this does not impact TCP traffic for the live network. | | `--disable_lazy_bootstrap` | Turn off use of lazy bootstrap. | | `--disable_legacy_bootstrap` | Turn off use of legacy bootstrap. | | `--disable_max_peers_per_ip` | Disables the limit on the number of peer connections allowed per IP address | | `--disable_max_peers_per_subnetwork` | Disables the limit on the number of peer connections allowed per subnetwork | | `--disable_ongoing_bootstrap` | Turn off the ability for ongoing bootstraps to occur. | | `--disable_ongoing_telemetry_requests` | Disables ongoing telemetry requests to peers | | `--disable_providing_telemetry_metrics` | Do not provide any telemetry data to nodes requesting it. Responses are still made to requests, but they will have an empty payload. | | `--disable_rep_crawler` | Turn off the rep crawler process. | | `--disable_request_loop` | Turn off the request loop. | | `--disable_search_pending` | Disables the periodic search for pending transactions | | `--disable_tcp_realtime` | Turn off use of TCP live network (TCP for bootstrap will remain available). | | `--disable_unchecked_cleanup` | Prevent periodic cleaning of unchecked table. | | `--disable_unchecked_drop` | Prevent drop of all unchecked entries at node/wallet start. | | `--disable_wallet_bootstrap` | Turn off use of wallet-based bootstrap. | ## Debug commands | Command | Description | |---------|-------------| | `--debug_account_count` | Display the number of accounts. | | `--debug_account` | Display the total counts of each version for all accounts (including unpocketed). | | `--debug_block_count` | Display the number of blocks. | | `--debug_block_dump` | Print ledger blocks - use with caution due to the potentially large amount of data this can output. | | `--debug_bootstrap_generate` | Generate bootstrap sequence of blocks. | | `--debug_cemented_block_count` | Display the number of cemented blocks (blocks which are under the confirmation height of their accounts). | | `--debug_dump_frontier_unchecked_dependents` | Dump frontiers which have matching unchecked keys. | | `--debug_dump_online_weight` | List online weights table and current online_weights value. | | `--debug_dump_representatives` | List representatives and weights. | | `--debug_generate_crash_report` | After a node crash on Linux, this command reads the dump files generated from that crash and produces a "nano_node_crash_report.txt" file. Requires `addr2line` to be installed on the system. | | `--debug_opencl` | Profile OpenCL work generation for (optional) `--device=` on `--device=` using `--threads=` count. | | `--debug_output_last_backtrace_dump` | Output the stacktrace stored after a node crash. | | `--debug_profile_bootstrap` | Profile simulated bootstrap process. | | `--debug_profile_frontiers_confirmation` | Profile frontiers confirmation speed. | | `--debug_profile_generate` | Profile work generation. Optional: `--pow_sleep_interval` which sets an amount to sleep (in nanoseconds) between batches of POW calculations when using the CPU. `--difficulty`, `--multiplier` (only the latter is used if both given) to set the work generation threshold. | | `--debug_profile_kdf` | Profile kdf function. | | `--debug_profile_sign` | Profile signature generation. | | `--debug_profile_validate` | Profile work validation. | | `--debug_profile_votes` | Profile vote verification. | | `--debug_rpc` | Allows running RPC commands without enabling the RPC server. Not recommended for daily usage. Example: `echo '{"action": "block_count"}' | nano_node --debug_rpc` | | `--debug_stacktrace` | Prints a stacktrace example, useful to verify that it includes the desired information, such as files, function names and line numbers. | | `--debug_sys_logging` | On *nix system this checks writing to the system log. On Windows it writes to the event viewer, a registry entry needs to exist for this to work correctly which can be created by running this command for the first time as an administrator. | | `--debug_unconfirmed_frontiers` | Prints the account, height, frontiers and cemented frontier for all accounts which are not fully confirmed. Sorted by height in descending order. | | `--debug_validate_blocks` | Alias to `--validate_blocks`. | | `--debug_verify_profile` | Profile signature verification. | | `--debug_dump_trended_weight`| Dump trended weights table | | `--debug_profile_process`| Profile active blocks processing (only for nano_dev_network)| | `--debug_random_feed`| Generates output to RNG test suites | | `--debug_peers`| Display peer IPv6:port connections | | `--debug_prune`| Prune accounts up to last confirmed blocks **EXPERIMENTAL**| ## Removed | Command | Description | |---------|-------------| | `--vote_dump` | Dump most recent votes from representatives. | ================================================ FILE: docs/commands/rpc-protocol.md ================================================ title: RPC Protocol description: Reference for the RPC commands available for the Nano node # RPC Protocol The RPC protocol accepts JSON HTTP POST requests. The following are RPC commands along with the responses that are expected. This page is split into the following sections: | Section | Purpose | |---------|---------| | **[Node RPCs](#node-rpcs)** | For interacting with the node and ledger. | | **[Wallet RPCs](#wallet-rpcs)** | For interacting with the built-in, QT-based node wallet. **NOTE**: This wallet is only recommended for development and testing. | | **[Unit Conversion RPCs](#unit-conversion-rpcs)** | For converting different units to and from raw. | | **[Deprecated RPCs](#deprecated-rpcs)** | No longer recommended for use. | ## Node RPCs !!! warning "Unconfirmed blocks returned" Unless otherwise specified, RPC calls can return unconfirmed blocks and related details. In the most important cases where balances or similar details may include unconfirmed amounts, additional warnings have been included. Refer to [Block confirmation procedures](/integration-guides/key-management/#block-confirmation-procedures) for details. --- ### account_balance Returns how many RAW is owned and how many have not yet been received by **account** --8<-- "deprecation-info-pending.md" **Request:** ```json { "action": "account_balance", "account": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" } ``` **Response:** ```json { "balance": "10000", "pending": "10000", "receivable": "10000" } ``` **Optional "include_only_confirmed"** _version 22.0+_ Boolean, true by default. Results in `balance` only including blocks on this account that have already been confirmed and `receivable` only including incoming send blocks that have already been confirmed on the sending account. --- ### account_block_count Get number of blocks for a specific **account** **Request:** ```json { "action": "account_block_count", "account": "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" } ``` **Response:** ```json { "block_count" : "19" } ``` --- ### account_get Get account number for the **public key** **Request:** ```json { "action": "account_get", "key": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039" } ``` **Response:** ```json { "account" : "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx" } ``` --- ### account_history Reports send/receive information for an account. Returns only **send & receive** blocks by default (unless raw is set to true - see optional parameters below): change, state change & state epoch blocks are skipped, open & state open blocks will appear as receive, state receive/send blocks will appear as receive/send entries. Response will start with the latest block for the account (the frontier), and will list all blocks back to the open block of this account when "count" is set to "-1". **Note**: "local_timestamp" returned since version 18.0, "height" field returned since version 19.0 and "confirmed" returned since version 23.0 --8<-- "warning-includes-unconfirmed.md" **Request:** ```json { "action": "account_history", "account": "nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est", "count": "1" } ``` **Response:** ```json { "account": "nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est", "history": [ { "type": "send", "account": "nano_38ztgpejb7yrm7rr586nenkn597s3a1sqiy3m3uyqjicht7kzuhnihdk6zpz", "amount": "80000000000000000000000000000000000", "local_timestamp": "1551532723", "height": "60", "hash": "80392607E85E73CC3E94B4126F24488EBDFEB174944B890C97E8F36D89591DC5", "confirmed": "true" } ], "previous": "8D3AB98B301224253750D448B4BD997132400CEDD0A8432F775724F2D9821C72" } ``` If the `count` limit results in stopping before the end of the account chain, then the response will also contain a `previous` field (outside of the `history` field) which contains the block hash that would be next to process if `count` was larger. **Optional parameters:** - `raw` (bool): if set to `true` instead of the default `false`, instead of outputting a simplified send or receive explanation of blocks (intended for wallets), output all parameters of the block itself as seen in block_create or other APIs returning blocks. It still includes the "account" and "amount" properties you'd see without this option. State/universal blocks in the raw history will also have a `subtype` field indicating their equivalent "old" block. Unfortunately, the "account" parameter for open blocks is the account of the source block, not the account of the open block, to preserve similarity with the non-raw history. - `head` (64 hexadecimal digits string, 256 bit): instead of using the latest block for a specified account, use this block as the head of the account instead. Useful for pagination. - `include_linked_account` (bool): _version 28.0+._ When set to `true`, the response will include a new field `linked_account`, which returns the linked account associated with the block (or "0" if no linked account exists/was found e.g. due to pruning). - `offset` (decimal integer): skips a number of blocks starting from `head` (if given). Not often used. _Available since version 11.0_ - `reverse` (bool): if set to `true` instead of the default `false`, the response starts from `head` (if given, otherwise the first block of the account), and lists blocks up to the frontier (limited by "count"). **Note**: the field `previous` in the response changes to `next`. _Available since version 19.0_ - `account_filter` (array of public addresses): results will be filtered to only show sends/receives connected to the provided account(s). _Available since version 19.0_. **Note:** In v19.0, this option does not handle receive blocks; fixed in v20.0. --- ### account_info Returns frontier, open block, change representative block, balance, last modified timestamp from local database & block count for **account**. Only works for accounts that have received their first transaction and have an entry on the ledger, will return "Account not found" otherwise. To open an account, use [receive](#receive). --8<-- "unconfirmed-information.md" The balance is obtained from the frontier, which may be unconfirmed. As long as you follow the [guidelines](/integration-guides/key-management/#transaction-order-and-correctness), you can rely on the **balance** for the purposes of creating transactions for this account. If the frontier is never confirmed, then the blocks that proceed it will also never be confirmed. If you need only details for confirmed blocks, use the `include_confirmed` option below and referenced the `confirmed_*` fields added in to the response. **Request:** ```json { "action": "account_info", "account": "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" } ``` **Response:** ```json { "frontier": "FF84533A571D953A596EA401FD41743AC85D04F406E76FDE4408EAED50B473C5", "open_block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", "representative_block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", "balance": "235580100176034320859259343606608761791", "modified_timestamp": "1501793775", "block_count": "33", "account_version": "1", "confirmation_height" : "28", "confirmation_height_frontier" : "34C70FCA0952E29ADC7BEE6F20381466AE42BD1CFBA4B7DFFE8BD69DF95449EB" } ``` In response `confirmation_height` only available for _version 19.0+_ In response `confirmation_height_frontier` only available for _version 21.0+_ which is the block hash at that confirmation height. **Optional "include_confirmed"** _version 22.0+_ Boolean, false by default. Adds new return fields with prefix of `confirmed_` for consistency: - `confirmed_balance`: balance for only blocks on this account that have already been confirmed - `confirmed_height`: matches `confirmation_height` value - `confirmed_frontier`: matches `confirmation_height_frontier` value - If `representative` option also `true`, `confirmed_representative` included: representative account from the confirmed frontier block - If `receivable` option also `true`, `confirmed_receivable` included: balance of all receivable amounts where the matching incoming send blocks have been confirmed on their account --8<-- "deprecation-info-pending.md" **Request:** ```json { "action": "account_info", "account": "nano_1gyeqc6u5j3oaxbe5qy1hyz3q745a318kh8h9ocnpan7fuxnq85cxqboapu5", "representative": "true", "weight": "true", "receivable": "true", "include_confirmed": "true" } ``` **Response:** ```json { "frontier": "80A6745762493FA21A22718ABFA4F635656A707B48B3324198AC7F3938DE6D4F", "open_block": "0E3F07F7F2B8AEDEA4A984E29BFE1E3933BA473DD3E27C662EC041F6EA3917A0", "representative_block": "80A6745762493FA21A22718ABFA4F635656A707B48B3324198AC7F3938DE6D4F", "balance": "11999999999999999918751838129509869131", "confirmed_balance": "11999999999999999918751838129509869131", "modified_timestamp": "1606934662", "block_count": "22966", "account_version": "1", "confirmed_height": "22966", "confirmed_frontier": "80A6745762493FA21A22718ABFA4F635656A707B48B3324198AC7F3938DE6D4F", "representative": "nano_1gyeqc6u5j3oaxbe5qy1hyz3q745a318kh8h9ocnpan7fuxnq85cxqboapu5", "confirmed_representative": "nano_1gyeqc6u5j3oaxbe5qy1hyz3q745a318kh8h9ocnpan7fuxnq85cxqboapu5", "weight": "11999999999999999918751838129509869131", "pending": "0", "receivable": "0", "confirmed_pending": "0", "confirmed_receivable": "0" } ``` **Optional "representative", "weight", "pending"** _version 9.0+_ Booleans, false by default. Additionally returns representative, voting weight, pending/receivable balance for account **Request:** ```json { "action": "account_info", "account": "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", "representative": "true", "weight": "true", "pending": "true" } ``` **Response:** ```json { "frontier": "FF84533A571D953A596EA401FD41743AC85D04F406E76FDE4408EAED50B473C5", "open_block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", "representative_block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", "balance": "235580100176034320859259343606608761791", "modified_timestamp": "1501793775", "block_count": "33", "account_version": "1", "confirmation_height" : "28", "confirmation_height_frontier" : "34C70FCA0952E29ADC7BEE6F20381466AE42BD1CFBA4B7DFFE8BD69DF95449EB", "representative": "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", "weight": "1105577030935649664609129644855132177", "pending": "2309370929000000000000000000000000", "receivable": "2309370929000000000000000000000000" } ``` --- ### account_key Get the public key for **account** **Request:** ```json { "action": "account_key", "account" : "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx" } ``` **Response:** ```json { "key": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039" } ``` --- ### account_representative Returns the representative for **account** **Request:** ```json { "action": "account_representative", "account": "nano_39a73oy5ungrhxy5z5oao1xso4zo7dmgpjd4u74xcrx3r1w6rtazuouw6qfi" } ``` **Response:** ```json { "representative" : "nano_16u1uufyoig8777y6r8iqjtrw8sg8maqrm36zzcm95jmbd9i9aj5i8abr8u5" } ``` --- ### account_weight Returns the voting weight for **account** **Request:** ```json { "action": "account_weight", "account": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" } ``` **Response:** ```json { "weight": "10000" } ``` --- ### accounts_balances Returns how many RAW is owned and how many have not yet been received by **accounts list** --8<-- "unconfirmed-information.md" The receivable balances are calculated from potentially unconfirmed blocks. Account balances are obtained from their frontiers. An atomic [account_info](#account_info) RPC call is recommended for the purposes of creating transactions. --8<-- "deprecation-info-pending.md" **Request:** ```json { "action": "accounts_balances", "accounts": ["nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", "nano_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7"] } ``` **Response:** ```json { "balances" : { "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": { "balance": "325586539664609129644855132177", "pending": "2309372032769300000000000000000000", "receivable": "2309372032769300000000000000000000" }, "nano_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7": { "balance": "10000000", "pending": "0", "receivable": "0" } } } ``` **Optional "include_only_confirmed"** _version 25.0+_ Boolean, true by default. Results in `balance` only including blocks on the provided account that have already been confirmed and `receivable` only including incoming send blocks that have already been confirmed on the sending account. !!! info "Error handling" With _version 25.0+_, `accounts_balances` response errors come in a different entry, named as `errors`. This fixes the breaking change added in V24.0. Please notice that when an account is not found in the ledger, no error is returned anymore. It now returns a zero balance and zero as receivable. ```json { "balances": { "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": { "balance": "325586539664609129644855132177", "pending": "2309370929000000000000000000000000", "receivable": "2309370929000000000000000000000000" }, "nano_1hrts7hcoozxccnffoq9hqhngnn9jz783usapejm57ejtqcyz9dpso1bibuy": { "balance": "0", "pending": "0", "receivable": "0" } }, "errors": { "nano_36uccgpjzhjsdbj44wm1y5hyz8gefx3wjpp1jircxt84nopxkxti5bzq1rnz": "Bad account number" } } ``` If all requested entries result in errors, no entry will be added in the response for `balances`. Similarly, if there are no errors, no entry will be added for `errors`. Request: ```json { "action": "accounts_balances", "accounts": ["nano_36uccgpjzhjsdbj44wm1y5hyz8gefx3wjpp1jircxt84nopxkxti5bzq1rnz"] } ``` Response: ```json { "errors": { "nano_36uccgpjzhjsdbj44wm1y5hyz8gefx3wjpp1jircxt84nopxkxti5bzq1rnz": "Bad account number" } } ``` In _version 24.0+_, `accounts_balances` response errors are returned per account entry in `balances` object. If an account does not exist, zero balance and zero receivables should be returned, but V24.0 has a bug: unopened accounts with receivables return an error instead of the receivables. ```json { "balances": { "nano_3wfddg7a1paogrcwi3yhwnaerboukbr7rs3z3ino5toyq3yyhimo6f6egij6": { "balance": "442000000000000000000000000000", "pending": "0", "receivable": "0" }, "nano_1hrts7hcoozxccnffoq9hqhngnn9jz783usapejm57ejtqcyz9dpso1bibuy": { "error": "Account not found" } } } ``` --- ### accounts_frontiers Returns a list of pairs of account and block hash representing the head block for **accounts list** --8<-- "warning-includes-unconfirmed.md" **Request:** ```json { "action": "accounts_frontiers", "accounts": ["nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", "nano_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7"] } ``` **Response:** ```json { "frontiers" : { "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": "791AF413173EEE674A6FCF633B5DFC0F3C33F397F0DA08E987D9E0741D40D81A", "nano_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7": "6A32397F4E95AF025DE29D9BF1ACE864D5404362258E06489FABDBA9DCCC046F" } } ``` !!! info "Error handling" With _version 25.0+_, `accounts_frontiers` response errors come in a different entry, named `errors`. ```json { "frontiers": { "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": "023B94B7D27B311666C8636954FE17F1FD2EAA97A8BAC27DE5084FBBD5C6B02C" }, "errors": { "nano_36uccgpjzhjsdbj44wm1y5hyz8gefx3wjpp1jircxt84nopxkxti5bzq1rnz": "Bad account number", "nano_1hrts7hcoozxccnffoq9hqhngnn9jz783usapejm57ejtqcyz9dpso1bibuy": "Account not found" } } ``` If all requested entries result in errors, no entry will be added in the response for `frontiers`. Similarly, if there are no errors, no entry will be added for `errors`. Request: ```json { "action": "accounts_frontiers", "accounts": ["nano_1hrts7hcoozxccnffoq9hqhngnn9jz783usapejm57ejtqcyz9dpso1bibuy"] } ``` Response: ```json { "errors": { "nano_1hrts7hcoozxccnffoq9hqhngnn9jz783usapejm57ejtqcyz9dpso1bibuy": "Account not found" } } ``` In _version 24.0+_, `accounts_frontiers` response errors were returned per account entry in the `frontiers` object. ```json { "frontiers": { "nano_3wfddg7a1paogrcwi3yhwnaerboukbr7rs3z3ino5toyq3yyhimo6f6egij6": "75BD65296241EB871918EBE3E99E9A191970A2724B3214B27F8AB205FF4FC30A", "nano_36uccgpjzhjsdbj44wm1y5hyz8gefx3wjpp1jircxt84nopxkxti5bzq1rnz": "error: Bad account number", "nano_1hrts7hcoozxccnffoq9hqhngnn9jz783usapejm57ejtqcyz9dpso1bibuy": "error: Account not found" } } ``` --- ### accounts_receivable _since V24.0, use [accounts_pending](#accounts_pending) for V23.3 and below_ Returns a list of confirmed block hashes which have not yet been received by these **accounts** **Request:** ```json { "action": "accounts_receivable", "accounts": ["nano_1111111111111111111111111111111111111111111111111117353trpda", "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3"], "count": "1" } ``` **Response:** ```json { "blocks" : { "nano_1111111111111111111111111111111111111111111111111117353trpda": ["142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D"], "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": ["4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74"] } } ``` **Optional "threshold"** _version 8.0+_ Number (128 bit, decimal). Returns a list of receivable block hashes with amount more or equal to **threshold** **Request:** ```json { "action": "accounts_receivable", "accounts": ["nano_1111111111111111111111111111111111111111111111111117353trpda", "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3"], "count": "1", "threshold": "1000000000000000000000000" } ``` **Response:** ```json { "blocks" : { "nano_1111111111111111111111111111111111111111111111111117353trpda": { "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D": "6000000000000000000000000000000" }, "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": { "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74": "106370018000000000000000000000000" } } } ``` **Optional "source"** _version 9.0+_ Boolean, false by default. Returns a list of receivable block hashes with amount and source accounts **Request:** ```json { "action": "accounts_receivable", "accounts": ["nano_1111111111111111111111111111111111111111111111111117353trpda", "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3"], "count": "1", "source": "true" } ``` **Response:** ```json { "blocks" : { "nano_1111111111111111111111111111111111111111111111111117353trpda": { "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D": { "amount": "6000000000000000000000000000000", "source": "nano_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr" } }, "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": { "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74": { "amount": "106370018000000000000000000000000", "source": "nano_13ezf4od79h1tgj9aiu4djzcmmguendtjfuhwfukhuucboua8cpoihmh8byo" } } } } ``` **Optional "include_active"** _version 15.0+_ Boolean, false by default. Include active (not confirmed) blocks **Request:** ```json { "action": "accounts_receivable", "accounts": ["nano_1111111111111111111111111111111111111111111111111117353trpda", "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3"], "count": "1", "include_active": "true" } ``` **Optional "sorting"** _version 19.0+_ Boolean, false by default. Additionally sorts each account's blocks by their amounts in descending order. **Optional "include_only_confirmed"** _version 19.0+_ Boolean, true by default (_version 22.0+_), previously false by default. Only returns confirmed blocks but with the caveat that their confirmation height might not be up-to-date yet. If false, unconfirmed blocks will also be returned. --- ### accounts_representatives Returns the representatives for given **accounts** **Request:** ```json { "action": "accounts_representatives", "accounts": ["nano_16u1uufyoig8777y6r8iqjtrw8sg8maqrm36zzcm95jmbd9i9aj5i8abr8u5","nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3"] } ``` **Response:** ```json { "representatives" : { "nano_16u1uufyoig8777y6r8iqjtrw8sg8maqrm36zzcm95jmbd9i9aj5i8abr8u5": "nano_3hd4ezdgsp15iemx7h81in7xz5tpxi43b6b41zn3qmwiuypankocw3awes5k", "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" } } ``` !!! info "Error handling" With _version 25.0+_, `accounts_representatives` response errors come in a different entry, named `errors`. ```json { "representatives": { "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" }, "errors": { "nano_36uccgpjzhjsdbj44wm1y5hyz8gefx3wjpp1jircxt84nopxkxti5bzq1rnz": "Bad account number", "nano_1hrts7hcoozxccnffoq9hqhngnn9jz783usapejm57ejtqcyz9dpso1bibuy": "Account not found" } } ``` If all requested entries result in errors, no entry will be added in the response for `representatives`. Similarly, if there are no errors, no entry will be added for `errors`. Request: ```json { "action": "accounts_representatives", "accounts": ["nano_1hrts7hcoozxccnffoq9hqhngnn9jz783usapejm57ejtqcyz9dpso1bibuy"] } ``` Response: ```json { "errors": { "nano_1hrts7hcoozxccnffoq9hqhngnn9jz783usapejm57ejtqcyz9dpso1bibuy": "Account not found" } } ``` In _version 24.0+_, `accounts_representatives` response errors were returned per account entry in the `representatives` object. ```json { "representatives": { "nano_3wfddg7a1paogrcwi3yhwnaerboukbr7rs3z3ino5toyq3yyhimo6f6egij6": "nano_3wfddg7a1paogrcwi3yhwnaerboukbr7rs3z3ino5toyq3yyhimo6f6egij6", "nano_36uccgpjzhjsdbj44wm1y5hyz8gefx3wjpp1jircxt84nopxkxti5bzq1rnz": "error: Bad account number", "nano_1hrts7hcoozxccnffoq9hqhngnn9jz783usapejm57ejtqcyz9dpso1bibuy": "error: Account not found" } } ``` --- ### available_supply Returns how many raw are in the public supply **Request:** ```json { "action": "available_supply" } ``` **Response:** ```json { "available": "133248061996216572282917317807824970865" } ``` --- ### block_account Returns the account containing block **Request:** ```json { "action": "block_account", "hash": "023B94B7D27B311666C8636954FE17F1FD2EAA97A8BAC27DE5084FBBD5C6B02C" } ``` **Response:** ```json { "account": "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" } ``` --- ### block_confirm _version 12.2+_ Request confirmation for **block** from known online representative nodes. Check results with [confirmation history](#confirmation_history). **Request:** ```json { "action": "block_confirm", "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "started": "1" } ``` **NOTE:** Unless there was an error encountered during the command, the response will always return `"started": "1"`. This response does not indicate the block was successfully confirmed, only that an error did not occur. This response happens even if the block has already been confirmed previously and notifications will be triggered for this block (via HTTP callbacks or WebSockets) in all cases. This behavior may change in a future release. --- ### block_count Reports the number of blocks in the ledger and unchecked synchronizing blocks **Request:** ```json { "action": "block_count" } ``` **Response:** ```json { "count": "1000", "unchecked": "10", "cemented": "25" } ``` **Note:** If the node is running the RocksDB backend the unchecked count may only be estimate. **Optional "include_cemented"** _version 19.0+ (enable_control required in version 19.0, not required in version 20.0+)_ Default "true". If "true", "cemented" in the response will contain the number of cemented blocks. (In V19.0 default was "false") --8<-- "warning-enable-control.md" --- ### block_create _enable_control required, version 9.0+_ Creates a json representations of new block based on input data & signed with **private key** or **account** in **wallet**. Use for offline signing. Using the optional `json_block` is recommended since v19.0. --8<-- "warning-enable-control.md" **Request sample for state block:** ```json { "action": "block_create", "json_block": "true", "type": "state", "balance": "1000000000000000000000", "key": "0000000000000000000000000000000000000000000000000000000000000002", "representative": "nano_1hza3f7wiiqa7ig3jczyxj5yo86yegcmqk3criaz838j91sxcckpfhbhhra1", "link": "19D3D919475DEED4696B5D13018151D1AF88B2BD3BCFF048B45031C1F36D1858", "previous": "F47B23107E5F34B2CE06F562B5C435DF72A533251CB414C51B2B62A8F63A00E4" } ``` Parameters for state block: * `balance`: **final** balance for account after block creation, formatted in 'raw' units using a decimal integer. If balance is less than previous, block is considered as send subtype! * `wallet` (optional): The wallet ID that the account the block is being created for is in. * `account` (optional): The [account](../glossary.md#account) the block is being created for. * `key` (optional): Instead of using "wallet" & "account" parameters, you can directly pass in a private key. * `source` (optional): The block hash of the source of funds for this receive block (the send block that this receive block will pocket). * `destination` (optional): The [account](../glossary.md#account) that the sent funds should be accessible to. * `link` (optional): Instead of using "source" and "destination" parameters, you can directly pass "link". If the block is sending funds, set link to the public key of the destination account. If it is receiving funds, set link to the hash of the block to receive. If the block has no balance change but is updating representative only, set link to 0. See [Block format section](../integration-guides/the-basics.md#block-format) for more information * `representative`: The [account](../glossary.md#account) that block account will use as its representative. * `previous`: The block hash of the previous block on this account's block chain ("0" for first block). **Warning:** It is **critical** that `balance` is the balance of the account **after** created block! **Optional "json_block"** _version 19.0+_ Default "false". If "true", "block" in the response will contain a JSON subtree instead of a JSON string. **Optional "work"** Work value (16 hexadecimal digits string, 64 bit). Uses **work** value for block from external source **Optional "version"** _version 21.0+_ Work version string. Currently "work_1" is the default and only valid option. Only used if optional **work** is not given. **Optional "difficulty"** _version 21.0+_ Difficulty value (16 hexadecimal digits string, 64 bit). Uses **difficulty** value to generate work. Only used if optional **work** is not given. If difficulty and work values are both not given, RPC processor tries to calculate difficulty for work generation based on ledger data: epoch from previous block or from link for receive subtype; block subtype from previous block balance. **Examples** **Response sample for above request**: ```json { "hash": "FF0144381CFF0B2C079A115E7ADA7E96F43FD219446E7524C48D1CC9900C4F17", "difficulty": "ffffffe1278b3dc6", // since V21.0 "block": { "type": "state", "account": "nano_3qgmh14nwztqw4wmcdzy4xpqeejey68chx6nciczwn9abji7ihhum9qtpmdr", "previous": "F47B23107E5F34B2CE06F562B5C435DF72A533251CB414C51B2B62A8F63A00E4", "representative": "nano_1hza3f7wiiqa7ig3jczyxj5yo86yegcmqk3criaz838j91sxcckpfhbhhra1", "balance": "1000000000000000000000", "link": "19D3D919475DEED4696B5D13018151D1AF88B2BD3BCFF048B45031C1F36D1858", "link_as_account": "nano_18gmu6engqhgtjnppqam181o5nfhj4sdtgyhy36dan3jr9spt84rzwmktafc", "signature": "3BFBA64A775550E6D49DF1EB8EEC2136DCD74F090E2ED658FBD9E80F17CB1C9F9F7BDE2B93D95558EC2F277FFF15FD11E6E2162A1714731B743D1E941FA4560A", "work": "cab7404f0b5449d0" } } ``` --- ### block_hash _version 13.0+_ Returning block hash for given **block** content. Using the optional `json_block` is recommended since v19.0. **Request:** ```json { "action": "block_hash", "json_block": "true", "block": { "type": "state", "account": "nano_3qgmh14nwztqw4wmcdzy4xpqeejey68chx6nciczwn9abji7ihhum9qtpmdr", "previous": "F47B23107E5F34B2CE06F562B5C435DF72A533251CB414C51B2B62A8F63A00E4", "representative": "nano_1hza3f7wiiqa7ig3jczyxj5yo86yegcmqk3criaz838j91sxcckpfhbhhra1", "balance": "1000000000000000000000", "link": "19D3D919475DEED4696B5D13018151D1AF88B2BD3BCFF048B45031C1F36D1858", "link_as_account": "nano_18gmu6engqhgtjnppqam181o5nfhj4sdtgyhy36dan3jr9spt84rzwmktafc", "signature": "3BFBA64A775550E6D49DF1EB8EEC2136DCD74F090E2ED658FBD9E80F17CB1C9F9F7BDE2B93D95558EC2F277FFF15FD11E6E2162A1714731B743D1E941FA4560A", "work": "cab7404f0b5449d0" } } ``` **Response:** ```json { "hash": "FF0144381CFF0B2C079A115E7ADA7E96F43FD219446E7524C48D1CC9900C4F17" } ``` **Optional "json_block"** _version 19.0+_ Default "false". If "true", "block" must contain a JSON subtree instead of a JSON string. --- ### block_info Retrieves a json representation of the block in `contents` along with: * _since version 18.0_: `block_account`, transaction `amount`, block `balance`, block `height` in account chain, block local modification `timestamp` * _since version 19.0_: Whether block was `confirmed`, `subtype` (_for state blocks_) of `send`, `receive`, `change` or `epoch` * _since version 23.0_: `successor` returned Using the optional `json_block` is recommended since v19.0. **Request:** ```json { "action": "block_info", "json_block": "true", "hash": "87434F8041869A01C8F6F263B87972D7BA443A72E0A97D7A3FD0CCC2358FD6F9" } ``` **Response:** ```json { "block_account": "nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est", "amount": "30000000000000000000000000000000000", "balance": "5606157000000000000000000000000000000", "height": "58", "local_timestamp": "0", "successor": "8D3AB98B301224253750D448B4BD997132400CEDD0A8432F775724F2D9821C72", "confirmed": "true", "contents": { "type": "state", "account": "nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est", "previous": "CE898C131AAEE25E05362F247760F8A3ACF34A9796A5AE0D9204E86B0637965E", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", "balance": "5606157000000000000000000000000000000", "link": "5D1AA8A45F8736519D707FCB375976A7F9AF795091021D7E9C7548D6F45DD8D5", "link_as_account": "nano_1qato4k7z3spc8gq1zyd8xeqfbzsoxwo36a45ozbrxcatut7up8ohyardu1z", "signature": "82D41BC16F313E4B2243D14DFFA2FB04679C540C2095FEE7EAE0F2F26880AD56DD48D87A7CC5DD760C5B2D76EE2C205506AA557BF00B60D8DEE312EC7343A501", "work": "8a142e07a10996d5" }, "subtype": "send" } ``` Note: The `Balance` in contents is a uint128. However, it will be a hex-encoded (like `0000000C9F2C9CD04674EDEA40000000` for [1 nano](../protocol-design/distribution-and-units.md#unit-dividers)) when the block is a legacy *Send Block*. If the block is a *State-Block*, the same `Balance` will be a numeric-string (like `1000000000000000000000000000000`). **Optional "json_block"** _version 19.0+_ Default "false". If "true", "contents" will contain a JSON subtree instead of a JSON string. **Optional `include_linked_account`** _version 28.0+_ (bool): When set to `true`, the response will include a new field `linked_account`, which returns the linked account associated with the block (or "0" if no linked account exists/was found e.g. due to pruning). --- ### blocks Retrieves a json representations of **blocks**. Using the optional `json_block` is recommended since v19.0. **Request:** ```json { "action": "blocks", "json_block": "true", "hashes": ["87434F8041869A01C8F6F263B87972D7BA443A72E0A97D7A3FD0CCC2358FD6F9"] } ``` **Response:** ```json { "blocks": { "87434F8041869A01C8F6F263B87972D7BA443A72E0A97D7A3FD0CCC2358FD6F9": { "type": "state", "account": "nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est", "previous": "CE898C131AAEE25E05362F247760F8A3ACF34A9796A5AE0D9204E86B0637965E", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", "balance": "5606157000000000000000000000000000000", "link": "5D1AA8A45F8736519D707FCB375976A7F9AF795091021D7E9C7548D6F45DD8D5", "link_as_account": "nano_1qato4k7z3spc8gq1zyd8xeqfbzsoxwo36a45ozbrxcatut7up8ohyardu1z", "signature": "82D41BC16F313E4B2243D14DFFA2FB04679C540C2095FEE7EAE0F2F26880AD56DD48D87A7CC5DD760C5B2D76EE2C205506AA557BF00B60D8DEE312EC7343A501", "work": "8a142e07a10996d5" } } } ``` **Optional "json_block"** _version 19.0+_ Default "false". If "true", "contents" will contain a JSON subtree instead of a JSON string. --- ### blocks_info Retrieves a json representations of `blocks` in `contents` along with: * _since version 18.0_: `block_account`, transaction `amount`, block `balance`, block `height` in account chain, block local modification `timestamp` * _since version 19.0_: Whether block was `confirmed`, `subtype` (_for state blocks_) of `send`, `receive`, `change` or `epoch` * _since version 23.0_: `successor` returned Using the optional `json_block` is recommended since v19.0. **Request:** ```json { "action": "blocks_info", "json_block": "true", "hashes": ["87434F8041869A01C8F6F263B87972D7BA443A72E0A97D7A3FD0CCC2358FD6F9"] } ``` **Response:** ```json { "blocks": { "87434F8041869A01C8F6F263B87972D7BA443A72E0A97D7A3FD0CCC2358FD6F9": { "block_account": "nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est", "amount": "30000000000000000000000000000000000", "balance": "5606157000000000000000000000000000000", "height": "58", "local_timestamp": "0", "successor": "8D3AB98B301224253750D448B4BD997132400CEDD0A8432F775724F2D9821C72", "confirmed": "true", "contents": { "type": "state", "account": "nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est", "previous": "CE898C131AAEE25E05362F247760F8A3ACF34A9796A5AE0D9204E86B0637965E", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", "balance": "5606157000000000000000000000000000000", "link": "5D1AA8A45F8736519D707FCB375976A7F9AF795091021D7E9C7548D6F45DD8D5", "link_as_account": "nano_1qato4k7z3spc8gq1zyd8xeqfbzsoxwo36a45ozbrxcatut7up8ohyardu1z", "signature": "82D41BC16F313E4B2243D14DFFA2FB04679C540C2095FEE7EAE0F2F26880AD56DD48D87A7CC5DD760C5B2D76EE2C205506AA557BF00B60D8DEE312EC7343A501", "work": "8a142e07a10996d5" }, "subtype": "send" } } } ``` **Optional `include_linked_account`** _version 28.0+_ (bool): When set to `true`, the response will include a new field `linked_account`, which returns the linked account associated with the block (or "0" if no linked account exists/was found e.g. due to pruning). **Optional "pending", "source"** _pending, source: version 9.0+_ Booleans, false by default. Additionally checks if block is pending, returns source account for receive & open blocks (0 for send & change blocks). --8<-- "deprecation-info-pending.md" **Request:** ```json { "action": "blocks_info", "hashes": ["E2FB233EF4554077A7BF1AA85851D5BF0B36965D2B0FB504B2BC778AB89917D3"], "pending": "true", "source": "true" } ``` **Response:** ```json { "blocks" : { "E2FB233EF4554077A7BF1AA85851D5BF0B36965D2B0FB504B2BC778AB89917D3": { "block_account": "nano_1qato4k7z3spc8gq1zyd8xeqfbzsoxwo36a45ozbrxcatut7up8ohyardu1z", "amount": "30000000000000000000000000000000000", "contents": { ... }, "pending": "0", "source_account": "nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est", "balance": "40200000001000000000000000000000000" } } } ``` **Optional "receive_hash"** _version 24.0+_ Boolean, default false. If "true", displays the hash of the send block's corresponding receive (if any). Returns 0 for non-send blocks, and for receivable blocks that do not yet have a corresponding receive. **Request:** ```json { "action": "blocks_info", "hashes": ["67D9F9F03566D22926159193BD5BDE549FBE8308807C666BCCD3CEA098FBF49D"], "receive_hash": "true" } ``` **Response** ```json { "blocks": { "67D9F9F03566D22926159193BD5BDE549FBE8308807C666BCCD3CEA098FBF49D": { "block_account": "nano_1pnano6m6o1ix3eshr6fj9rryd4ckziyii1mf3ychqno9t3soz638dc9fj9a", "amount": "1240000000000000000000000000", "balance": "11017588042701000000000000000000", "height": "271199", "local_timestamp": "1674588370", "successor": "0000000000000000000000000000000000000000000000000000000000000000", "confirmed": "true", "contents": { ... }, "subtype": "send", "receive_hash": "4DCA5A5E2C732A6899292B9091B7A90CE87E8063954498DF30F469416E6DD6C0" } } } ``` **Optional "json_block"** _version 19.0+_ Default "false". If "true", "contents" will contain a JSON subtree instead of a JSON string. **Optional "include_not_found"** _version 19.0+_ Default "false". If "true", an additional "blocks_not_found" is provided in the response, containing a list of the block hashes that were not found in the local database. Previously to this version an error would be produced if any block was not found. **Request:** ```json { "action": "blocks_info", "include_not_found": "true", "hashes": ["87434F8041869A01C8F6F263B87972D7BA443A72E0A97D7A3FD0CCC2358FD6F9", "0000000000000000000000000000000000000000000000000000000000000001"] } ``` **Response:** ```json { "blocks" : { "87434F8041869A01C8F6F263B87972D7BA443A72E0A97D7A3FD0CCC2358FD6F9": { "block_account": "nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est", "amount": "30000000000000000000000000000000000", "balance": "5606157000000000000000000000000000000", "height": "58", "local_timestamp": "0", "confirmed": "false", "contents": { ... } } }, "blocks_not_found": [ "0000000000000000000000000000000000000000000000000000000000000001" ] } ``` --- ### bootstrap Initialize bootstrap to specific **IP address** and **port**. Not compatible with launch flag [--disable_legacy_bootstrap](/commands/command-line-interface/#-disable_legacy_bootstrap) **Request:** ```json { "action": "bootstrap", "address": "::ffff:138.201.94.249", "port": "7075" } ``` **Response:** ```json { "success": "" } ``` **Optional "bypass_frontier_confirmation"** _version 20.0-21.3_ Default "false". If "true", frontier confirmation will not be performed for this bootstrap. Normally not to be changed. **Optional "id"** _version 21.0+_ String, empty by default. Set specific ID for new bootstrap attempt for better tracking. --- ### bootstrap_any Initialize multi-connection bootstrap to random peers. Not compatible with launch flag [--disable_legacy_bootstrap](/commands/command-line-interface/#-disable_legacy_bootstrap) **Request:** ```json { "action": "bootstrap_any" } ``` **Response:** ```json { "success": "" } ``` **Optional "force"** _version 20.0+_ Boolean, false by default. Manually force closing of all current bootstraps **Optional "id"** _version 21.0+_ String, empty by default. Set specific ID for new bootstrap attempt for better tracking. **Optional "account"** _version 22.0+_ String, empty by default. Public address for targeting a specific account on bootstrap attempt --- ### bootstrap_lazy _enable_control required, version 17.0+_ Initialize lazy bootstrap with given block **hash**. Not compatible with launch flag [--disable_lazy_bootstrap](/commands/command-line-interface/#-disable_lazy_bootstrap). As of _version 22.0_, response includes whether new election was `started` and whether a new lazy `key_inserted` was successful. --8<-- "warning-enable-control.md" **Request:** ```json { "action": "bootstrap_lazy", "hash": "FF0144381CFF0B2C079A115E7ADA7E96F43FD219446E7524C48D1CC9900C4F17" } ``` **Response:** ```json { "started": "1", "key_inserted": "0" } ``` **Optional "force"** Boolean, false by default. Manually force closing of all current bootstraps **Optional "id"** _version 21.0+_ String, empty by default. Set specific ID for new bootstrap attempt for better tracking. --- ### bootstrap_priorities _enable_control required, version 28.0+_ Dumps info about priority and blocking sets to aid in debugging any potential problems --8<-- "warning-enable-control.md" **Request:** ```json { "action": "bootstrap_priorities" } ``` --- ### bootstrap_reset _enable_control required, version 28.0+_ Resets ascending bootstrap state - both priority and blocking sets are cleared. --8<-- "warning-enable-control.md" **Request:** ```json { "action": "bootstrap_reset" } ``` --- ### bootstrap_status _version 17.0+_ --8<-- "warning-debug-only-command.md" Returning status of current bootstrap attempt **Request:** ```json { "action": "bootstrap_status" } ``` **Response:** _versions 21.0+_ ```json { "bootstrap_threads": "2", "running_attempts_count": "2", "total_attempts_count": "6", "connections": { "clients": "31", "connections": "45", "idle": "0", "target_connections": "64", "pulls": "1158514" }, "attempts": [ { "id": "EE778222D6407F94A666B8A9E03D242D", "mode": "legacy", "started": "true", "pulling": "1158544", "total_blocks": "4311", "requeued_pulls": "7", "frontier_pulls": "0", "frontiers_received": "true", "frontiers_confirmed": "false", "frontiers_confirmation_pending": "false", "frontiers_age": "4294967295", "last_account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp", "duration": "133" }, { "id": "291D2CC32F44E004896C4215A6CDEDAFEF317F6AC802C244E8F4B4F2456175CB", "mode": "lazy", "started": "true", "pulling": "1", "total_blocks": "1878", "requeued_pulls": "4", "lazy_blocks": "1878", "lazy_state_backlog": "1", "lazy_balances": "4", "lazy_destinations": "0", "lazy_undefined_links": "0", "lazy_pulls": "13", "lazy_keys": "2", "lazy_key_1": "E6D0B5BD5EBDB3CEC7DBC32EDC3C2DBD5ABA17C54E34485A358BF8948039ED6A", "duration": "17" } ] } ``` ??? abstract "Response V17.0-V20.0" ```json { "clients": "0", "pulls": "0", "pulling": "0", "connections": "31", "idle": "31", "target_connections": "16", "total_blocks": "13558", "runs_count": "0", "requeued_pulls": "31", "frontiers_received": "true", "frontiers_confirmed": "false", "mode": "legacy", "lazy_blocks": "0", "lazy_state_backlog": "0", "lazy_balances": "0", "lazy_destinations": "0", "lazy_undefined_links": "0", "lazy_pulls": "32", "lazy_keys": "32", "lazy_key_1": "36897874BDA3028DC8544C106BE1394891F23DDDF84DE100FED450F6FBC8122C", "duration": "29" } ``` --- ### chain Returns a consecutive list of block hashes in the account chain starting at **block** back to **count** (direction from frontier back to open block, from newer blocks to older). Will list all blocks back to the open block of this chain when count is set to "-1". The requested block hash is included in the answer. **Request:** ```json { "action": "chain", "block": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "count": "1" } ``` **Response:** ```json { "blocks": [ "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" ] } ``` **Optional "offset"** _version 18.0+_ Number, 0 by default. Return the account chain block hashes **offset** by the specified number of blocks **Optional "reverse"** _version 18.0+_ Boolean, false by default. Returns a list of block hashes in the account chain starting at **block** up to **count** (direction from open block up to frontier, from older blocks to newer). Equal to [successors](#successors) --- ### confirmation_active _version 16.0+_ Returns list of active elections qualified roots (excluding stopped & aborted elections); since V21, also includes the number of unconfirmed and confirmed active elections. Find info about specific qualified root with [confirmation_info](#confirmation_info) !!! note The roots provided are two parts and differ between the first account block and subsequent blocks: * First account block (open): account public key + `0000000000000000000000000000000000000000000000000000000000000000` * Other blocks: previous hash + previous hash **Request:** ```json { "action": "confirmation_active" } ``` **Response:** ```json { "confirmations": [ "8031B600827C5CC05FDC911C28BBAC12A0E096CCB30FA8324F56C123676281B28031B600827C5CC05FDC911C28BBAC12A0E096CCB30FA8324F56C123676281B2" ], "unconfirmed": "133", // since V21.0 "confirmed": "5" // since V21.0 } ``` **Optional "announcements"** Number, 0 by default. Returns only active elections with equal or higher announcements count. Useful to find long running elections --- ### confirmation_history _version 12.0+_ --8<-- "warning-debug-only-command.md" duration, time, confirmation_stats: version 17.0+_ Returns hash, tally weight, election duration (in milliseconds), election confirmation timestamp for recent elections winners; since V20.0, the confirmation request count; since V21.0, the number of blocks and voters. Also returns stats: count of elections in history (limited to 2048) & average duration time. With version 19.0+ `confirmation_history_size` can be managed in the configuration file to adjust the number of elections to be kept in history and returned by this call. Due to timings inside the node, the default 2048 limit will return all confirmations up to traffic levels of approximately 56 confirmations/sec. To properly track levels above this, increase this value or use the confirmation subscription through the [websocket](/integration-guides/websockets) instead. **Request:** ```json { "action": "confirmation_history" } ``` **Response:** ```json { "confirmation_stats": { "count": "2", "average": "5000" }, "confirmations": [ { "hash": "EA70B32C55C193345D625F766EEA2FCA52D3F2CCE0B3A30838CC543026BB0FEA", "duration": "4000", "time": "1544819986", "tally": "80394786589602980996311817874549318248", "final": "80394786589602980996311817874549318248", // since V22.0 "blocks": "1", // since V21.0 "voters": "37", // since V21.0 "request_count": "2" // since V20.0 }, { "hash": "F2F8DA6D2CA0A4D78EB043A7A29E12BDE5B4CE7DE1B99A93A5210428EE5B8667", "duration": "6000", "time": "1544819988", "tally": "68921714529890443063672782079965877749", "final": "68921714529890443063672782079965877749", // since V22.0 "blocks": "1", // since V21.0 "voters": "64", // since V21.0 "request_count": "7" // since V20.0 } ] } ``` **Optional "hash"** Valid block hash, filters return for only the provided hash. If there is no confirmation available for that hash anymore, the following return can be expected: ```json { "confirmation_stats": { "count": "0" }, "confirmations": "" } ``` If the block is unknown on the node, the following error will be returned: ```"error": "Invalid block hash"``` --- ### confirmation_info _version 16.0+_ Returns info about an unconfirmed active election by **root**. Including announcements count, last winner (initially local ledger block), total tally of voted representatives, concurrent blocks with tally & block contents for each. Using the optional `json_block` is recommended since v19.0. Updated in v28.0 to include a list of representatives_final (representatives that have voted with final votes). !!! note The roots provided are two parts and differ between the first account block and subsequent blocks: * First account block (open): `0000000000000000000000000000000000000000000000000000000000000000` + account public key * Other blocks: previous hash + previous hash **Request:** ```json { "action": "confirmation_info", "json_block": "true", "root": "EE125B1B1D85D3C24636B3590E1642D9F21B166C0C6CD99C9C6087A1224A0C44EE125B1B1D85D3C24636B3590E1642D9F21B166C0C6CD99C9C6087A1224A0C44" } ``` **Response:** ```json { "announcements": "2", "voters": "29", "last_winner": "B94C505029F04BC057A0486ADA8BD07981B4A8736AE6581F2E98C6D18498146F", "total_tally": "51145880360832646375807054724596663794", "final_tally": "51145880360832646375807054724596663794", "blocks": { "B94C505029F04BC057A0486ADA8BD07981B4A8736AE6581F2E98C6D18498146F": { "tally": "51145880360832646375807054724596663794", "contents": { "type": "state", "account": "nano_3fihmbtuod33s4nrbqfczhk9zy9ddqimwjshzg4c3857es8c9631i5rg6h9p", "previous": "EE125B1B1D85D3C24636B3590E1642D9F21B166C0C6CD99C9C6087A1224A0C44", "representative": "nano_3o7uzba8b9e1wqu5ziwpruteyrs3scyqr761x7ke6w1xctohxfh5du75qgaj", "balance": "218195000000000000000000000000", "link": "0000000000000000000000000000000000000000000000000000000000000000", "link_as_account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp", "signature": "B1BD285235C612C5A141FA61793D7C6C762D3F104A85102DED5FBD6B4514971C4D044ACD3EC8C06A9495D8E83B6941B54F8DABA825ADF799412ED9E2C86D7A0C", "work": "05bb28cd8acbe71d" } } } } ``` **Optional "contents"** Boolean, true by default. Disable contents for each block **Optional "json_block"** _version 19.0+_ Default "false". If "true", "contents" will contain a JSON subtree instead of a JSON string. **Optional "representatives"** Boolean, false by default. Returns list of votes representatives & its weights for each block **Request:** ```json { "action": "confirmation_info", "json_block": "true", "root": "EE125B1B1D85D3C24636B3590E1642D9F21B166C0C6CD99C9C6087A1224A0C44EE125B1B1D85D3C24636B3590E1642D9F21B166C0C6CD99C9C6087A1224A0C44", "representatives": "true" } ``` **Response:** ```json { "announcements": "5", "last_winner": "B94C505029F04BC057A0486ADA8BD07981B4A8736AE6581F2E98C6D18498146F", "total_tally": "51145880360792646375807054724596663794", "blocks": { "B94C505029F04BC057A0486ADA8BD07981B4A8736AE6581F2E98C6D18498146F": { "tally": "51145880360792646375807054724596663794", "contents": { "type": "state", "account": "nano_3fihmbtuod33s4nrbqfczhk9zy9ddqimwjshzg4c3857es8c9631i5rg6h9p", "previous": "EE125B1B1D85D3C24636B3590E1642D9F21B166C0C6CD99C9C6087A1224A0C44", "representative": "nano_3o7uzba8b9e1wqu5ziwpruteyrs3scyqr761x7ke6w1xctohxfh5du75qgaj", "balance": "218195000000000000000000000000", "link": "0000000000000000000000000000000000000000000000000000000000000000", "link_as_account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp", "signature": "B1BD285235C612C5A141FA61793D7C6C762D3F104A85102DED5FBD6B4514971C4D044ACD3EC8C06A9495D8E83B6941B54F8DABA825ADF799412ED9E2C86D7A0C", "work": "05bb28cd8acbe71d" }, "representatives": { "nano_3pczxuorp48td8645bs3m6c3xotxd3idskrenmi65rbrga5zmkemzhwkaznh": "12617828599372664613607727105312358589", "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou": "5953738757270291536911559258663615240", ... "nano_3i4n5n6c6xssapbdtkdoutm88c5zjmatc5tc77xyzdkpef8akid9errcpjnx": "0" } } } } ``` --- ### confirmation_quorum _version 16.0+_ Returns information about node elections settings & observed network state: - `quorum_delta`: Online weight times `online_weight_quorum_percent` - `online_weight_quorum_percent`: Percent of online vote weight required for confirmation - `online_weight_minimum`: When calculating online weight, the node is forced to assume at least this much voting weight is online, thus setting a floor for voting weight to confirm transactions at `online_weight_minimum` * `quorum_delta` - `online_stake_total`: Total online weight from gossip vote traffic - `peers_stake_total`: Total online weight from direct node connections - `trended_stake_total`: Median of online weight samples taken every 5 minutes over previous 2 week period - Removed in _version 22.0_: `peers_stake_required` **Request:** ```json { "action": "confirmation_quorum" } ``` **Response:** ```json { "quorum_delta": "41469707173777717318245825935516662250", "online_weight_quorum_percent": "50", "online_weight_minimum": "60000000000000000000000000000000000000", "online_stake_total": "82939414347555434636491651871033324568", "peers_stake_total": "69026910610720098597176027400951402360", "trended_stake_total": "81939414347555434636491651871033324568" } ``` **Optional "peer_details"** _version 17.0+_ Boolean, false by default. If true, add account/ip/rep weight for each peer considered in the summation of *peers_stake_total*. **Response field "peers_stake_required"** _version 19.0+_ The effective stake needed from directly connected peers for quorum. Per v19, this field is computed as `max(quorum_delta, online_weight_minimum)`. If `peers_stake_total` is lower than this value, the node will not mark blocks as confirmed. --- ### database_txn_tracker _enable_control required, v19.0+_ --8<-- "warning-debug-only-command.md" Returns a list of open database transactions which are equal or greater than the `min_read_time` or `min_write_time` for reads and read-writes respectively. --8<-- "warning-enable-control.md" **Request:** ```json { "action": "database_txn_tracker", "min_read_time" : "1000", "min_write_time" : "0" } ``` **Response on Windows/Debug:** ```json { "txn_tracking": [ { "thread": "Blck processing", // Which thread held the transaction "time_held_open": "2", // Seconds the transaction has currently been held open for "write": "true", // If true it is a write lock, otherwise false. "stacktrace": [ { "name": "nano::mdb_store::tx_begin_write", "address": "00007FF7142C5F86", "source_file": "c:\\users\\wesley\\documents\\raiblocks\\nano\\node\\lmdb.cpp", "source_line": "825" }, { "name": "nano::block_processor::process_batch", "address": "00007FF714121EEA", "source_file": "c:\\users\\wesley\\documents\\raiblocks\\nano\\node\\blockprocessor.cpp", "source_line": "243" }, { "name": "nano::block_processor::process_blocks", "address": "00007FF71411F8A6", "source_file": "c:\\users\\wesley\\documents\\raiblocks\\nano\\node\\blockprocessor.cpp", "source_line": "103" }, ... ] } ... // other threads ] } ``` --- ### delegators _version 8.0+_ Returns a list of pairs of delegator accounts and balances given a representative **account** **Request:** ```json { "action": "delegators", "account": "nano_1111111111111111111111111111111111111111111111111117353trpda" } ``` **Response:** ```json { "delegators": { "nano_13bqhi1cdqq8yb9szneoc38qk899d58i5rcrgdk5mkdm86hekpoez3zxw5sd": "500000000000000000000000000000000000", "nano_17k6ug685154an8gri9whhe5kb5z1mf5w6y39gokc1657sh95fegm8ht1zpn": "961647970820730000000000000000000000" } } ``` **Optional parameters:** _since V23.0_ * `threshold`: minimum required balance for a delegating account to be included in the response * `count`: number of delegators to return * `start`: account in the list you would like to start after, to allow for paging responses --- ### delegators_count _version 8.0+_ Get number of delegators for a specific representative **account** **Request:** ```json { "action": "delegators_count", "account": "nano_1111111111111111111111111111111111111111111111111117353trpda" } ``` **Response:** ```json { "count": "2" } ``` --- ### deterministic_key Derive deterministic keypair from **seed** based on **index** **Request:** ```json { "action": "deterministic_key", "seed": "0000000000000000000000000000000000000000000000000000000000000000", "index": "0" } ``` **Response:** ```json { "private": "9F0E444C69F77A49BD0BE89DB92C38FE713E0963165CCA12FAF5712D7657120F", "public": "C008B814A7D269A1FA3C6528B19201A24D797912DB9996FF02A1FF356E45552B", "account": "nano_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7" } ``` --- ### election_statistics _version 27.0+_ Returns the number of each election type, the maximum and average election age from Active Election Container (AEC). Values in `max_election_age` and `average_election_age` are in milliseconds. **Request:** ```json { "action": "election_statistics" } ``` **Response sample:** ```json { "normal": "152", "priority": "1", "hinted": "0", "optimistic": "19", "total": "172", "aec_utilization_percentage": "3.42", "max_election_age": "5493", "average_election_age": "421" } ``` --- ### epoch_upgrade _enable_control required, version 20.0+_ --8<-- "warning-debug-only-command.md" Upgrade network to new **epoch** with epoch signer private **key**. This spawns a background task to iterate over all accounts and add the epoch block to any accounts that do not have it. It will return `{ "started" = "1" }` if the background task was spawned successfully or `{ "started" = "0" }` if the operation could not be started. Reasons for not being able to start the operations include the node being stopped and a previous being in progress. `epoch` can be set to either 1 (representing the [network upgrade to state blocks](../releases/network-upgrades.md#state-blocks)) or 2 (representing the [network upgrade for increase work difficulty](../releases/network-upgrades.md#increased-work-difficulty)). --8<-- "warning-enable-control.md" **Request:** ```json { "action": "epoch_upgrade", "epoch": "1", "key": "0000000000000000000000000000000000000000000000000000000000000000" } ``` **Response:** ```json { "started": "1" } ``` **Optional "count"** Number. Determines limit of number of accounts to upgrade. **Optional "threads"** _version 21.0+_ Number. Determines limit of work threads to use for concurrent upgrade processes (useful with multiple work peers or high work peer latency). --- ### frontier_count Reports the number of accounts in the ledger **Request:** ```json { "action": "frontier_count" } ``` **Response:** ```json { "count": "920471" } ``` --- ### frontiers Returns a list of pairs of account and block hash representing the head block starting at **account** up to **count** **Request:** ```json { "action": "frontiers", "account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp", "count": "1" } ``` **Response:** ```json { "frontiers" : { "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } } ``` --- ### keepalive _enable_control required_ Tells the node to send a keepalive packet to **address**:**port** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "keepalive", "address": "::ffff:192.169.0.1", "port": "1024" } ``` **Response:** ```json { "started": "1" } ``` --- ### key_create Generates an **adhoc random keypair** **Request:** ```json { "action": "key_create" } ``` **Response:** ```json { "private": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3", "public": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039", "account": "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx" } ``` --- ### key_expand Derive public key and account number from **private key** **Request:** ```json { "action": "key_expand", "key": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3" } ``` **Response:** ```json { "private": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3", "public": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039", "account": "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx" } ``` --- ### ledger _enable_control required, version 9.0+_ Returns frontier, open block, change representative block, balance, last modified timestamp from local database & block count starting at **account** up to **count** --8<-- "warning-enable-control.md" --8<-- "warning-includes-unconfirmed.md" **Request:** ```json { "action": "ledger", "account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp", "count": "1" } ``` **Response:** ```json { "accounts": { "nano_11119gbh8hb4hj1duf7fdtfyf5s75okzxdgupgpgm1bj78ex3kgy7frt3s9n": { "frontier": "E71AF3E9DD86BBD8B4620EFA63E065B34D358CFC091ACB4E103B965F95783321", "open_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F", "representative_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F", "balance": "0", "modified_timestamp": "1511476234", "block_count": "2" } } } ``` **Optional "representative", "weight", "receivable"** Booleans, false by default. Additionally returns representative, voting weight, receivable balance for each account **Request:** ```json { "action": "ledger", "account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp", "count": "1", "representative": "true", "weight": "true", "receivable": "true" } ``` **Response:** ```json { "accounts": { "nano_11119gbh8hb4hj1duf7fdtfyf5s75okzxdgupgpgm1bj78ex3kgy7frt3s9n": { "frontier": "E71AF3E9DD86BBD8B4620EFA63E065B34D358CFC091ACB4E103B965F95783321", "open_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F", "representative_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F", "balance": "0", "modified_timestamp": "1511476234", "block_count": "2", "representative": "nano_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs", "weight": "0", "pending": "0", "receivable": "0" } } } ``` **Optional "modified_since"** _version 11.0+_ UNIX timestamp (number), 0 by default. Return only accounts modified in local database after specific timestamp **Optional "sorting"** Boolean, false by default. Additional sorting accounts in descending order NOTE: The "count" option is ignored if "sorting" is specified **Optional "threshold"** _version 19.0+_ Number (128 bit, decimal), default 0. Return only accounts with balance above **threshold**. If **receivable** is also given, the number compared with the threshold is the sum of account balance and receivable balance. --- ### node_id _enable_control required, version 17.0+_ --8<-- "warning-debug-only-command.md" Returns private key, public key and node ID number with checksum (similar to account representation) from the existing node ID created on startup. "as_account" field is **deprecated** _version 20.0 will generate the node_id with `node_` prefix, earlier versions will generate with `nano_` prefix_ --8<-- "warning-enable-control.md" **Request:** ```json { "action": "node_id" } ``` **Response:** ```json { "private": "2AD75C9DC20EA497E41722290C4DC966ECC4D6C75CAA4E447961F918FD73D8C7", "public": "78B11E1777B8E7DF9090004376C3EDE008E84680A497C0805F68CA5928626E1C", "as_account": "nano_1y7j5rdqhg99uyab1145gu3yur1ax35a3b6qr417yt8cd6n86uiw3d4whty3", "node_id": "node_1y7j5rdqhg99uyab1145gu3yur1ax35a3b6qr417yt8cd6n86uiw3d4whty3" } ``` --- ### peers Returns a list of pairs of online peer IPv6:port and its node protocol network version **Request:** ```json { "action": "peers" } ``` **Response version 8.0+:** ```json { "peers": { "[::ffff:172.17.0.1]:32841": "16" } } ``` **Response before version 8.0:** ```json { "peers": [ "[::ffff:172.17.0.1]:32841" ] } ``` **Optional "peer_details"** _version 18.0+_ Boolean, false by default. Returns a list of peers IPv6:port with its node protocol network version and node ID. The node ID is random and is not a Nano address. As of Version V21+ `type` returns `tcp`, as `udp` was **deprecated** and is not longer used for peering with that node. _version 20.0 will generate the node_id with `node_` prefix, earlier versions will generate with `nano_` prefix_ **Request:** ```json { "action": "peers", "peer_details": "true" } ``` **Response:** ```json { "peers": { "[::ffff:172.17.0.1]:7075": { "protocol_version": "18", "node_id": "node_1y7j5rdqhg99uyab1145gu3yur1ax35a3b6qr417yt8cd6n86uiw3d4whty3", "type": "tcp" } } } ``` --- ### populate_backlog _enable_control required_ Scans all accounts, checks for unconfirmed blocks in account chains, and then queues those blocks for confirmation via the election scheduler. Useful for local test networks, since default backlog population is normally done over longer intervals (e.g. 5 minutes). --8<-- "warning-enable-control.md" **Request** ```json { "action": "populate_backlog" } ``` **Response** ```json { "success": "" } ``` --- ### process Publish **block** to the network. Using the optional `json_block` is recommended since v19.0. In v20.0-v21.3, blocks are watched for confirmation by default (see optional `watch_work`). If `enable_control` is not set to `true` on the node, then the optional `watch_work` must be set to `false`. In V22.0+ the work watcher has been removed. Note: after v25.0, it is possible that the block processing queue can internally drop a block if the queue gets full. This stat can be checked for `blockprocessor` type, and `drop` details. --8<-- "warning-process-sub-type-recommended.md" **Request:** ```json { "action": "process", "json_block": "true", "subtype": "send", "block": { "type": "state", "account": "nano_1qato4k7z3spc8gq1zyd8xeqfbzsoxwo36a45ozbrxcatut7up8ohyardu1z", "previous": "6CDDA48608C7843A0AC1122BDD46D9E20E21190986B19EAC23E7F33F2E6A6766", "representative": "nano_3pczxuorp48td8645bs3m6c3xotxd3idskrenmi65rbrga5zmkemzhwkaznh", "balance": "40200000001000000000000000000000000", "link": "87434F8041869A01C8F6F263B87972D7BA443A72E0A97D7A3FD0CCC2358FD6F9", "link_as_account": "nano_33t5by1653nt196hfwm5q3wq7oxtaix97r7bhox5zn8eratrzoqsny49ftsd", "signature": "A5DB164F6B81648F914E49CAB533900C389FAAD64FBB24F6902F9261312B29F730D07E9BCCD21D918301419B4E05B181637CF8419ED4DCBF8EF2539EB2467F07", "work": "000bc55b014e807d" } } ``` **Response:** ```json { "hash": "E2FB233EF4554077A7BF1AA85851D5BF0B36965D2B0FB504B2BC778AB89917D3" } ``` **Optional "force"** _version 13.1+_ Boolean, false by default. Manually forcing fork resolution if processed block is not accepted as fork **Optional "subtype"** _version 18.0+_ String, empty by default. Additional check for state blocks subtype, i.e. prevent accidental sending to incorrect accounts instead of receiving receivable blocks. Options: * `send` - account balance is reduced * `receive` - account balance is increased * `open` - first block on account with account balance initially set higher than 0 * `change` - account balance is unchanged, representative field value changed to valid public address * `epoch` - block signed with epoch signer private key (does not allow balance or representative changes) **Optional "json_block"** _version 19.0+_ Boolean, default "false". If "true", "block" must contain a JSON subtree instead of a JSON string. **Optional "watch_work"** _added in version 20.0+_ _removed in version 22.0_ Boolean, default "true". If "true", **block** will be placed on watch for confirmation, with equivalent functionality to in-wallet transactions using [send](#send), [receive](#receive) and [account_representative_set](#account_representative_set), including republishing and rework if confirmation is delayed (default is 5 seconds, set by `work_watcher_period` config entry) and if [active_difficulty](#active_difficulty) is higher than the block's PoW difficulty. **Optional "async"** _version 22.0+_ Boolean, default "false". If "true", requests will add the blocks to the block processor queue and `{"started":"1"}` will be immediately returned, instead of waiting for block process completion to return. To know if the block was properly processed, monitor the [WebSocket topic `new_unconfirmed_block`](../integration-guides/websockets.md#new-unconfirmed-blocks) and a notification for that successful block will be sent. --- ### receivable _since V23.0, use [pending](#pending) for V22.1 and below_ Returns a list of block hashes which have not yet been received by this account. **Request:** ```json { "action": "receivable", "account": "nano_1111111111111111111111111111111111111111111111111117353trpda", "count": "1" } ``` **Response:** ```json { "blocks": [ "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" ] } ``` **Optional "count"** Number. Determines limit of number of blocks to return. **Optional "threshold"** _version 8.0+_ Number (128 bit, decimal). Returns a list of receivable block hashes with amount more or equal to **threshold** **Request:** ```json { "action": "receivable", "account": "nano_1111111111111111111111111111111111111111111111111117353trpda", "count": "1", "threshold": "1000000000000000000000000" } ``` **Response:** ```json { "blocks" : { "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": "6000000000000000000000000000000" } } ``` **Optional "source"** _version 9.0+_ Boolean, false by default. Returns a list of receivable block hashes with amount and source accounts **Request:** ```json { "action": "receivable", "account": "nano_1111111111111111111111111111111111111111111111111117353trpda", "count": "1", "source": "true" } ``` **Response:** ```json { "blocks" : { "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": { "amount": "6000000000000000000000000000000", "source": "nano_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr" } } } ``` **Optional "include_active"** _version 15.0+_ Boolean, false by default. Include active blocks without finished confirmations **Request:** ```json { "action": "receivable", "account": "nano_1111111111111111111111111111111111111111111111111117353trpda", "count": "1", "include_active": "true" } ``` **Optional "min_version"** _version 15.0+_ Boolean, false by default. Returns the minimum version (epoch) of a block which can pocket this receivable block. **Optional "sorting"** Boolean, false by default. Additionally sorts the blocks by their amounts in descending order. _version 22.0+_ If used with "count" returns the absolute sorted values. _version 19.0+_ If used with "count" only sorts relative to the first receivable entries found up to count so not necessarily the ones with the largest receivable balance. **Optional "include_only_confirmed"** _version 19.0+_ Boolean, true by default (_version 22.0+_), previously false by default. Only returns confirmed blocks but with the caveat that their confirmation height might not be up-to-date yet. If false, unconfirmed blocks will also be returned. --- ### receivable_exists _since V23.0, use [pending_exists](#pending_exists) for V22.1 and below_ Check whether block is receivable by **hash** **Request:** ```json { "action": "receivable_exists", "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "exists" : "1" } ``` **Optional "include_active"** _version 15.0+_ Boolean, false by default. Include active blocks without finished confirmations **Request:** ```json { "action": "receivable_exists", "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "include_active": "true" } ``` **Optional "include_only_confirmed"** _version 19.0+_ Boolean, true by default (_version 22.0+_), previously false by default. Only returns confirmed blocks but with the caveat that their confirmation height might not be up-to-date yet. If false, unconfirmed blocks will also be returned. --- ### representatives Returns a list of pairs of representative and its voting weight **Request:** ```json { "action": "representatives" } ``` **Response:** ```json { "representatives": { "nano_1111111111111111111111111111111111111111111111111117353trpda": "3822372327060170000000000000000000000", "nano_1111111111111111111111111111111111111111111111111awsq94gtecn": "30999999999999999999999999000000", "nano_114nk4rwjctu6n6tr6g6ps61g1w3hdpjxfas4xj1tq6i8jyomc5d858xr1xi": "0" } } ``` **Optional "count"** _version 9.0+_ Number. Returns a list of pairs of representative and its voting weight up to **count** **Optional "sorting"** _version 9.0+_ Boolean, false by default. Additional sorting representatives in descending order NOTE: The "count" option is ignored if "sorting" is specified --- ### representatives_online _version 18.0+_ Returns a list of online representative accounts that have voted recently **Request:** ```json { "action": "representatives_online" } ``` **Response:** ```json { "representatives": [ "nano_1111111111111111111111111111111111111111111111111117353trpda", "nano_1111111111111111111111111111111111111111111111111awsq94gtecn", "nano_114nk4rwjctu6n6tr6g6ps61g1w3hdpjxfas4xj1tq6i8jyomc5d858xr1xi" ] } ``` _versions 11.2–17.1_ Returns a list of pairs of online representative accounts that have voted recently and empty strings **Response:** ```json { "representatives" : { "nano_1111111111111111111111111111111111111111111111111117353trpda": "", "nano_1111111111111111111111111111111111111111111111111awsq94gtecn": "", "nano_114nk4rwjctu6n6tr6g6ps61g1w3hdpjxfas4xj1tq6i8jyomc5d858xr1xi": "" } } ``` **Optional "weight"** _version 17.0+_ Boolean, false by default. Returns voting weight for each representative. **Response:** ```json { "representatives": { "nano_114nk4rwjctu6n6tr6g6ps61g1w3hdpjxfas4xj1tq6i8jyomc5d858xr1xi": { "weight": "150462654614686936429917024683496890" } } } ``` **Optional "accounts"** Array of accounts. Returned list is filtered for only these accounts. **Request:** ```json { "action": "representatives_online", "accounts": ["nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p", "nano_1111111111111111111111111111111111111111111111111117353trpda"] } ``` **Response:** ```json { "representatives": [ "nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p" ] } ``` --- ### republish Rebroadcast blocks starting at **hash** to the network **Request:** ```json { "action": "republish", "hash": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948" } ``` **Response:** ```json { "success": "", "blocks": [ "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293" ] } ``` **Optional "sources"** _version 8.0+_ Boolean, false by default. Additionally rebroadcast source chain blocks for receive/open up to **sources** depth **Request:** ```json { "action": "republish", "hash": "90D0C16AC92DD35814E84BFBCC739A039615D0A42A76EF44ADAEF1D99E9F8A35", "count": "1", "sources": "2" } ``` **Response:** ```json { "blocks": [ "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293", "90D0C16AC92DD35814E84BFBCC739A039615D0A42A76EF44ADAEF1D99E9F8A35" ] } ``` **Optional "destinations"** _version 8.0+_ Boolean, false by default. Additionally rebroadcast destination chain blocks from receive up to **destinations** depth **Request:** ```json { "action": "republish", "hash": "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293", "count": "1", "destinations": "2" } ``` **Response:** ```json { "blocks": [ "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293", "90D0C16AC92DD35814E84BFBCC739A039615D0A42A76EF44ADAEF1D99E9F8A35", "18563C814A54535B7C12BF76A0E23291BA3769536634AB90AD0305776A533E8E" ] } ``` --- ### sign _version 18.0+_ Signing provided **block** with private **key** or key of **account** from **wallet**. Using the optional `json_block` is recommended since v19.0. **Request with private key:** ```json { "action": "sign", "json_block": "true", "key": "1D3759BB2CA187A66875D3B8497624159A576FD315E07F702B99B92BC59FC14A", "block": { "type": "state", "account": "nano_1qato4k7z3spc8gq1zyd8xeqfbzsoxwo36a45ozbrxcatut7up8ohyardu1z", "previous": "6CDDA48608C7843A0AC1122BDD46D9E20E21190986B19EAC23E7F33F2E6A6766", "representative": "nano_3pczxuorp48td8645bs3m6c3xotxd3idskrenmi65rbrga5zmkemzhwkaznh", "balance": "40200000001000000000000000000000000", "link": "87434F8041869A01C8F6F263B87972D7BA443A72E0A97D7A3FD0CCC2358FD6F9", "link_as_account": "nano_33t5by1653nt196hfwm5q3wq7oxtaix97r7bhox5zn8eratrzoqsny49ftsd", "signature": "A5DB164F6B81648F914E49CAB533900C389FAAD64FBB24F6902F9261312B29F730D07E9BCCD21D918301419B4E05B181637CF8419ED4DCBF8EF2539EB2467F07", "work": "000bc55b014e807d" } } ``` **Request with account from wallet:** ```json { "action": "sign", "json_block": "true", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "account": "nano_18ky5chy5ws89oi46ki4zjy6x5ezpmj98zg6icwke9bmuy99nosieyqf8c1h", "block": { "type": "state", "account": "nano_1qato4k7z3spc8gq1zyd8xeqfbzsoxwo36a45ozbrxcatut7up8ohyardu1z", "previous": "6CDDA48608C7843A0AC1122BDD46D9E20E21190986B19EAC23E7F33F2E6A6766", "representative": "nano_3pczxuorp48td8645bs3m6c3xotxd3idskrenmi65rbrga5zmkemzhwkaznh", "balance": "40200000001000000000000000000000000", "link": "87434F8041869A01C8F6F263B87972D7BA443A72E0A97D7A3FD0CCC2358FD6F9", "link_as_account": "nano_33t5by1653nt196hfwm5q3wq7oxtaix97r7bhox5zn8eratrzoqsny49ftsd", "signature": "A5DB164F6B81648F914E49CAB533900C389FAAD64FBB24F6902F9261312B29F730D07E9BCCD21D918301419B4E05B181637CF8419ED4DCBF8EF2539EB2467F07", "work": "000bc55b014e807d" } } ``` **Response:** ```json { "signature": "2A71F3877033F5966735F260E906BFCB7FA82CDD543BCD1224F180F85A96FC26CB3F0E4180E662332A0DFE4EE6A0F798A71C401011E635604E532383EC08C70D", "block": { "type": "state", "account": "nano_1qato4k7z3spc8gq1zyd8xeqfbzsoxwo36a45ozbrxcatut7up8ohyardu1z", "previous": "6CDDA48608C7843A0AC1122BDD46D9E20E21190986B19EAC23E7F33F2E6A6766", "representative": "nano_3pczxuorp48td8645bs3m6c3xotxd3idskrenmi65rbrga5zmkemzhwkaznh", "balance": "40200000001000000000000000000000000", "link": "87434F8041869A01C8F6F263B87972D7BA443A72E0A97D7A3FD0CCC2358FD6F9", "link_as_account": "nano_33t5by1653nt196hfwm5q3wq7oxtaix97r7bhox5zn8eratrzoqsny49ftsd", "signature": "2A71F3877033F5966735F260E906BFCB7FA82CDD543BCD1224F180F85A96FC26CB3F0E4180E662332A0DFE4EE6A0F798A71C401011E635604E532383EC08C70D", "work": "000bc55b014e807d" } } ``` **Optional "json_block"** _version 19.0+_ Default "false". If "true", the input "block" must contain a JSON subtree instead of a JSON string. In addition, the response block will be a JSON subtree. **Optional sign block hash** _Requires configuration changes. Set "rpc.enable_sign_hash" to "true"_ **Request:** ```json { "action": "sign", "hash": "E2FB233EF4554077A7BF1AA85851D5BF0B36965D2B0FB504B2BC778AB89917D3" } ``` **Response:** ```json { "signature": "2A71F3877033F5966735F260E906BFCB7FA82CDD543BCD1224F180F85A96FC26CB3F0E4180E662332A0DFE4EE6A0F798A71C401011E635604E532383EC08C70D" } ``` --- ### stats _version 12.2+_ For configuration and other details, please see [Statistics from RPC](/running-a-node/troubleshooting/#statistics-from-rpc) **Request counters:** ```json { "action": "stats", "type": "counters" } ``` **Counters response:** ```json { "type": "counters", "created": "2018.03.29 01:46:36", "entries": [ { "time": "01:46:36", "type": "traffic_tcp", "detail": "all", "dir": "in", "value": "3122792" }, { "time": "01:46:36", "type": "traffic_tcp", "detail": "all", "dir": "out", "value": "203184" } ... ] } ``` _version 18.0+ also returns "stat_duration_seconds": the number of seconds since startup or since the last "stats_clear" call_ **Request samples:** ```json { "action": "stats", "type": "samples" } ``` **Samples response:** ```json { "type": "samples", "created": "2018.03.29 01:47:08", "entries": [ { "time": "01:47:04", "type": "traffic_tcp", "detail": "all", "dir": "in", "value": "59480" }, { "time": "01:47:05", "type": "traffic_tcp", "detail": "all", "dir": "in", "value": "44496" } ... ] } ``` _version 18.0+_ NOTE: This call is for debug purposes only and is unstable as returned objects may be frequently changed. **Request objects:** ```json { "action": "stats", "type": "objects" } ``` **Objects response:** ```json { "node": { "ledger": { "bootstrap_weights": { "count": "125", "size": "7000" } }, "peers": { "peers": { "count": "38", "size": "7296" }, "attempts": { "count": "95", "size": "3800" }, }, ... } } ``` _version 22.0+_ NOTE: This call is for debug purposes only and is unstable as returned objects may be frequently changed and will be different depending on the ledger backend. **Request database:** ```json { "action": "stats", "type": "database" } ``` **Database response:** **LMDB:** ```json { "branch_pages": "0", "depth": "1", "entries": "11", "leaf_pages": "1", "overflow_pages": "0", "page_size": "4096" } ``` **RocksDB:** ```json { "cur-size-all-mem-tables": "74063072", "size-all-mem-tables": "487744504", "estimate-table-readers-mem": "113431016", "estimate-live-data-size": "17756425993", "compaction-pending": "0", "estimate-num-keys": "81835964", "estimate-pending-compaction-bytes": "0", "total-sst-files-size": "20350606013", "block-cache-capacity": "318767104", "block-cache-usage": "150310696" } ``` --- ### stats_clear _version 18.0+_ Clears all collected statistics. The "stat_duration_seconds" value in the "stats" action is also reset. **Request:** ```json { "action": "stats_clear" } ``` **Response:** ```json { "success": "" } ``` --- ### stop _enable_control required_ Method to safely shutdown node --8<-- "warning-enable-control.md" **Request:** ```json { "action": "stop" } ``` **Response:** ```json { "success": "" } ``` --- ### successors Returns a list of block hashes in the account chain starting at **block** up to **count** (direction from open block up to frontier, from older blocks to newer). Will list all blocks up to frontier (latest block) of this chain when count is set to "-1". The requested block hash is included in the answer. **Request:** ```json { "action": "successors", "block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", "count": "1" } ``` **Response:** ```json { "blocks" : [ "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948" ] } ``` **Optional "offset"** _version 18.0+_ Number, 0 by default. Return the account chain block hashes **offset** by the specified number of blocks **Optional "reverse"** _version 18.0+_ Boolean, false by default. Returns a consecutive list of block hashes in the account chain starting at **block** back to **count** (direction from frontier back to open block, from newer blocks to older). Equal to [chain](#chain) --- ### telemetry _version 21.0+_ Return metrics from other nodes on the network. By default, returns a summarized view of the whole network. See below for details on obtaining local telemetry data. [Networking - node telemetry](/protocol-design/networking#node-telemetry) contains more detailed information on the protocol implementation of telemetry. **Request:** ```json { "action": "telemetry" } ``` **Response:** ```json { "block_count": "214104509", "cemented_count": "214104509", "unchecked_count": "5161", "account_count": "37186909", "bandwidth_cap": "10485760", "peer_count": "176", "protocol_version": "21", "uptime": "3188200", "genesis_block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", "major_version": "28", "minor_version": "2", "patch_version": "0", "pre_release_version": "0", "maker": "0", "timestamp": "1765074100220", "active_difficulty": "fffffff800000000", "database_backend": "lmdb", "confirmation_latency_ms_p50": "254", "confirmation_latency_ms_p90": "510", "confirmation_latency_ms_p99": "1205", "bootstrap_status": "idle", "node_id": "node_3odec59q6i9qarh5txyrxmu3aqhfzm54mxoxgtumwpzyq6obxqktdzcxkfag", "signature": "067523993D0B4C07525DF4C5AA814FBCC40875F868C2A04A85AC288F75E152763196B7DCB11240921F6D8BA92E3E9F094D8F2F9D8B0970114CDAD48838372100" } ``` This contains a summarized view of the network with 10% of lower/upper bound results removed to reduce the effect of outliers. Returned values are calculated as follows: | Field Name | Response details | |------------|------------------------------------| | **block_count** | average count of blocks in ledger (including unconfirmed) | | **cemented_count** | average count of blocks cemented in ledger (only confirmed) | | **unchecked_count** | average count of unchecked blocks. This should only be considered an estimate as nodes running RocksDB may not return exact counts. | | **account_count** | average count of accounts in ledger | | **bandwidth_cap** | `0` = unlimited; the mode is chosen if there is more than 1 common result otherwise the results are averaged (excluding `0`) | | **peer_count** | average count of peers nodes are connected to | | **\*_version** | mode (most common) of (protocol, major, minor, patch, pre_release) versions | | **uptime** | average number of seconds since the UTC epoch at the point where the response is sent from the peer | | **genesis_block** | mode (most common) of genesis block hashes | | **maker** | mode (most common), meant for third party node software implementing the protocol so that it can be distinguished, `0` = Nano Foundation, `1` = Nano Foundation pruned node | | **timestamp** | number of milliseconds since the UTC epoch at the point where the response is sent from the peer | | **active_difficulty** | _V22.0+_ returns minimum network difficulty due to deprecated active difficulty measurements

_up to V21.3_ returns average of the current network difficulty, see [active_difficulty](/commands/rpc-protocol/#active_difficulty) "network_current" | | **database_backend** | the database backend used by the node: `lmdb` or `rocksdb` | | **confirmation_latency_ms_p50** | 50th percentile (median) confirmation latency in milliseconds, based on recently confirmed elections | | **confirmation_latency_ms_p90** | 90th percentile confirmation latency in milliseconds, based on recently confirmed elections | | **confirmation_latency_ms_p99** | 99th percentile confirmation latency in milliseconds, based on recently confirmed elections | | **bootstrap_status** | current bootstrap status of the node: `idle` or `active` | | **node_id** | _V21.0+_ returns the node identifier used to sign the telemetry message. This allows receivers to verify which peer the telemetry originated from. | | **signature** | _V21.0+_ returns the signature of the telemetry payload, created using the node's private key. It enables verification that the data was produced by the reported `node_id` and has not been altered. | This only returns values which have been cached by the ongoing polling of peer metric data. Each response is cached for 60 seconds on the main network and 15 seconds on beta; a few additional seconds are added on for response delays. **Optional "raw"** When setting raw to true metrics from all nodes are displayed. It additionally contains **address** and **port** from each peer. **Request:** ```json { "action": "telemetry", "raw" : "true" } ``` **Response:** ```json { "metrics": [ { "block_count": "5777903", ... "node_id": "node_1cmi8difuruopgzpnb4ybrnnj5rproxwuwe5mad7ucbsekakiwn37qqg1zo5", "signature": "5F8DEE5F895D53E122FDEB4B1B4118A41F9DDB818C6B299B09DF59131AF9F201BB7057769423F6B0C868B57509177B54D5D2C731405FE607527F5E2B6B2E290F", "address": "::ffff:152.89.106.89", "port": "54000" }, { "block_count": "5777902", ... "node_id": "node_3ipxdjrha3rfg9h3spiz5jkprw8kdj7bph9fir51kf6pmryzznsyhakqznk3", "signature": "D691B855D9EC70EA6320DE609EB379EB706845433E034AD22721E8F91BF3A26156F40CCB2E98653F1E63D4CE5F10F530A835DE1B154D1213464E3B9BB9BE4908", "address": "::ffff:95.216.205.215", "port": "54006" } ... ] } ``` **Optional "address" & "port"** Get metrics from a specific peer. It accepts both ipv4 and ipv6 addresses ```json { "action": "telemetry", "address": "246.125.123.456", "port": "7075" } ``` !!!tip "Requesting telemetry data from the local node" Metrics for the local node can be requested using the peering port and any loopback address **127.0.0.1**, **::1** or **[::1]** --- ### validate_account_number Check whether **account** is a valid account number using checksum **Request:** ```json { "action": "validate_account_number", "account": "nano_1111111111111111111111111111111111111111111111111117353trpda" } ``` **Response:** ```json { "valid" : "1" } ``` --- ### version Returns version information for RPC, Store, Protocol (network), Node (Major & Minor version). Since _version 20.0_ also returns the Network label and identifier (hash of the genesis open block), and Build Info. Since _version 21.0_ also returns Database backend information. _RPC Version always returns "1" as of 01/11/2018_ **Request:** ```json { "action": "version" } ``` **Response:** ```json { "rpc_version": "1", "store_version": "14", "protocol_version": "17", "node_vendor": "Nano 20.0", "store_vendor": "LMDB 0.9.23", // since V21.0 "network": "live", // since v20.0 "network_identifier": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", // since v20.0 "build_info": "Build Info \" version \" \"\" \"BOOST \" BUILT \"\"" // since v20.0 } ``` --- ### unchecked _version 8.0+_ Returns a list of pairs of unchecked block hashes and their json representation up to **count**. Using the optional `json_block` is recommended since v20.0. **Request:** ```json { "action": "unchecked", "json_block": "true", "count": "1", } ``` **Response:** ```json { "blocks": { "87434F8041869A01C8F6F263B87972D7BA443A72E0A97D7A3FD0CCC2358FD6F9": { "type": "state", "account": "nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est", "previous": "CE898C131AAEE25E05362F247760F8A3ACF34A9796A5AE0D9204E86B0637965E", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", "balance": "5606157000000000000000000000000000000", "link": "5D1AA8A45F8736519D707FCB375976A7F9AF795091021D7E9C7548D6F45DD8D5", "link_as_account": "nano_1qato4k7z3spc8gq1zyd8xeqfbzsoxwo36a45ozbrxcatut7up8ohyardu1z", "signature": "82D41BC16F313E4B2243D14DFFA2FB04679C540C2095FEE7EAE0F2F26880AD56DD48D87A7CC5DD760C5B2D76EE2C205506AA557BF00B60D8DEE312EC7343A501", "work": "8a142e07a10996d5" } } } ``` --- ### unchecked_clear _enable_control required, version 8.0+_ Clear unchecked synchronizing blocks --8<-- "warning-enable-control.md" **Request:** ```json { "action": "unchecked_clear" } ``` **Response:** ```json { "success": "" } ``` --- ### unchecked_get _version 8.0+_ Retrieves a json representation of unchecked synchronizing block by **hash**. Using the optional `json_block` is recommended since v19.0. **Request:** ```json { "action": "unchecked_get", "json_block": "true", "hash": "19BF0C268C2D9AED1A8C02E40961B67EA56B1681DE274CD0C50F3DD972F0655C" } ``` **Response:** ```json { "modified_timestamp": "1565856525", "contents": { "type": "state", "account": "nano_1hmqzugsmsn4jxtzo5yrm4rsysftkh9343363hctgrjch1984d8ey9zoyqex", "previous": "009C587914611E83EE7F75BD9C000C430C720D0364D032E84F37678D7D012911", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", "balance": "189012679592109992600249228", "link": "0000000000000000000000000000000000000000000000000000000000000000", "link_as_account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp", "signature": "845C8660750895843C013CE33E31B80EF0A7A69E52DDAF74A5F1BDFAA9A52E4D9EA2C3BE1AB0BD5790FCC1AD9B7A3D2F4B44EECE4279A8184D414A30A1B4620F", "work": "0dfb32653e189699" } } ``` **Optional "json_block"** _version 19.0+_ Default "false". If "true", "contents" will contain a JSON subtree instead of a JSON string. --- ### unchecked_keys _version 8.0+_ Retrieves unchecked database keys, blocks hashes & a json representations of unchecked receivable blocks starting from **key** up to **count**. Using the optional `json_block` is recommended since v19.0. --8<-- "known-issue-unchecked-keys-rpc-rocksdb.md" **Request:** ```json { "action": "unchecked_keys", "json_block": "true", "key": "19BF0C268C2D9AED1A8C02E40961B67EA56B1681DE274CD0C50F3DD972F0655C", "count": "1" } ``` **Response:** ```json { "unchecked": [ { "key": "19BF0C268C2D9AED1A8C02E40961B67EA56B1681DE274CD0C50F3DD972F0655C", "hash": "A1A8558CBABD3F7C1D70F8CB882355F2EF688E7F30F5FDBD0204CAE157885056", "modified_timestamp": "1565856744", "contents": { "type": "state", "account": "nano_1hmqzugsmsn4jxtzo5yrm4rsysftkh9343363hctgrjch1984d8ey9zoyqex", "previous": "19BF0C268C2D9AED1A8C02E40961B67EA56B1681DE274CD0C50F3DD972F0655C", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", "balance": "189012679592109992600249226", "link": "0000000000000000000000000000000000000000000000000000000000000000", "link_as_account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp", "signature": "FF5D49925AD3C8705E6EEDD993E8C4120E6107D7F1CB53B287773448DEA0B1D32918E67804248FC83609F0D93401D833DFA33127F21B6CD02F75D6E31A00450A", "work": "8193ddf00947e694" } } ] } ``` **Optional "json_block"** _version 19.0+_ Default "false". If "true", "contents" will contain a JSON subtree instead of a JSON string. --- ### unopened _enable_control required, version 19.0+_ Returns the total receivable balance for unopened accounts in the local database, starting at **account** (optional) up to **count** (optional), sorted by account number. _**Notes:**_ By default excludes the burn account. --8<-- "warning-enable-control.md" **Request:** ```json { "action": "unopened", "account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp", "count": "1" } ``` **Response:** ```json { "accounts": { "nano_1111111111111111111111111111111111111111111111111111hifc8npp": "207034077034226183413773082289554618448" } } ``` **Optional "threshold"** Number (128 bit, decimal), default 0. Return only accounts with total receivable balance above **threshold**. --- ### uptime _version 18.0+_ Return node uptime in seconds **Request:** ```json { "action": "uptime" } ``` **Response:** ```json { "seconds": "6000" } ``` --- ### work_cancel _enable_control required_ Stop generating **work** for block --8<-- "warning-enable-control.md" **Request:** ```json { "action": "work_cancel", "hash": "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2" } ``` **Response:** ```json { "success": "" } ``` --- ### work_generate _enable_control required_ Generates **work** for block. **hash** is the frontier of the account or in the case of an open block, the public key representation of the account which can be found with [account_key](#account_key). --8<-- "warning-enable-control.md" **Request:** ```json { "action": "work_generate", "hash": "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2" } ``` **Response:** ```json { "work": "2b3d689bbcb21dca", "difficulty": "fffffff93c41ec94", // of the resulting work "multiplier": "1.182623871097636", // since v19.0, calculated from default base difficulty "hash": "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2" // since v20.0 } ``` **Optional "use_peers"** _version 14.0+_ Boolean, false by default. If the optional `use_peers` parameter is set to `true`, then the node will query its work peers (if it has any). Without this parameter, the node will only generate work locally. **Optional "difficulty"** !!! info "Difficulty no longer useful" With _version 22.0+_ the difficulty is no longer used for prioritization so targeting higher difficulty thresholds on work generation is not useful. However, this can still be used for targeting a lower difficulty for receive blocks. This option may be removed in a future release. _version 19.0+_ Difficulty value (16 hexadecimal digits string, 64 bit). Uses **difficulty** value to generate work. Defaults to the network base difficulty. **Optional "multiplier"** !!! info "Multiplier no longer useful" With _version 22.0+_ the difficulty is no longer used for prioritization so targeting higher multipliers on work generation is not useful. This option will be removed in a future release. _version 20.0+_ Multiplier from base difficulty (positive number). Uses equivalent difficulty as **multiplier** from base difficulty to generate work. ***Note:*** overrides the `difficulty` parameter. **Optional "account"** _version 20.0+_ A valid Nano account. If provided and `use_peers` is set to `true`, this information will be relayed to work peers. **Optional "version"** _version 21.0+_ Work version string. Currently "work_1" is the default and only valid option. **Optional "block"** _version 21.0+_ A valid Nano block (string or JSON). Using the optional `json_block` is recommended. If provided and `difficulty` or `multiplier` are both not given, RPC processor tries to calculate the appropriate difficulty threshold based on ledger data. ***Note:*** block should be the one where the resulting work value will be used, not the previous block. **Optional "json_block"** _version 21.0+_ Default "false". If "true", `block` in the request should contain a JSON subtree instead of a JSON string. --- ### work_peer_add _enable_control required, version 8.0+_ Add specific **IP address** and **port** as work peer for node until restart --8<-- "warning-enable-control.md" **Request:** ```json { "action": "work_peer_add", "address": "::ffff:172.17.0.1", "port": "7076" } ``` **Response:** ```json { "success": "" } ``` --- ### work_peers _enable_control required, version 8.0+_ --8<-- "warning-enable-control.md" **Request:** ```json { "action": "work_peers" } ``` **Response:** ```json { "work_peers": [ "::ffff:172.17.0.1:7076" ] } ``` --- ### work_peers_clear _enable_control required, version 8.0+_ Clear work peers node list until restart --8<-- "warning-enable-control.md" **Request:** ```json { "action": "work_peers_clear" } ``` **Response:** ```json { "success": "" } ``` --- ### work_validate Check whether **work** is valid for block. Provides two values: **valid_all** is `true` if the work is valid at the current network difficulty (work can be used for any block). **valid_receive** is `true` if the work is valid for use in a receive block. **Read the details below when using this RPC in V21**. !!! warning "Semantics change in V21.0" In V21.0, when the optional **difficulty** is *not* given, **valid** is no longer included in the response. Use the new response fields **"valid_all"** and **"valid_receive"** taking into account the subtype of the block using this work value: - **valid_all** validates at the current network difficulty. As soon as the node processes the first [epoch_2 block](/releases/network-upgrades#increased-work-difficulty), this difficulty is increased. - **valid_receive** is completely accurate **only once the [epoch_2 upgrade](/releases/network-upgrades#increased-work-difficulty) is finished.** Until the upgrade is finished, it is only accurate if the account where this work will be used is already upgraded. The upgrade status of an account can be obtained from [account_info](#account_info). The account is upgraded if "account_version" is `"2"`. **Request:** ```json { "action": "work_validate", "work": "2bf29ef00786a6bc", "hash": "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2" } ``` **Response since v21.0:** ```json { "valid_all": "1", "valid_receive": "1", "difficulty": "fffffff93c41ec94", "multiplier": "1.182623871097636" // calculated from the default base difficulty } ``` ??? abstract "Response up to v20.0" ```json { "valid": "1", "difficulty": "fffffff93c41ec94", // since v19.0 "multiplier": "9.4609" // since v19.0 } ``` **Optional "difficulty"** _version 19.0+_ Difficulty value (16 hexadecimal digits string, 64 bit). Uses **difficulty** value to validate work. Defaults to the network base difficulty. Response includes extra field **valid** signifying validity at the given difficulty. **Request with given "difficulty"** ```json { "action": "work_validate", "difficulty": "ffffffffffffffff", "work": "2bf29ef00786a6bc", "hash": "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2" } ``` **Response with given "difficulty:** ```json { "valid": "0", "valid_all": "1", // since v21.0 "valid_receive": "1", // since v21.0 "difficulty": "fffffff93c41ec94", "multiplier": "1.182623871097636" } ``` **Optional "multiplier"** _version 20.0+_ Multiplier from base difficulty (positive number). Uses equivalent difficulty as **multiplier** from base difficulty to validate work. ***Note:*** overrides the `difficulty` parameter. **Optional "version"** _version 21.0+_ Work version string. Currently "work_1" is the default and only valid option. --- ## Wallet RPCs !!! warning "For development and testing only" Below are RPC commands that interact with the built-in, QT-based node wallet. This wallet is only recommended for development and testing. For production integrations, setting up custom [External Management](/integration-guides/key-management/#external-management) processes is required. --- ### account_create _enable_control required_ Creates a new account, insert next deterministic key in **wallet** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "account_create", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "account": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" } ``` **Optional "index"** _version 18.0+_ unset by default. Indicates which index to create account for starting with 0 **Request:** ```json { "action": "account_create", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "index": "1" } ``` **Optional "work"** _version 9.0+_ Boolean, true by default. Setting false disables work generation after creating account **Request:** ```json { "action": "account_create", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "work": "false" } ``` --- ### account_list Lists all the accounts inside **wallet** **Request:** ```json { "action": "account_list", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "accounts": [ "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" ] } ``` --- ### account_move _enable_control required_ Moves **accounts** from **source** to **wallet** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "account_move", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "source": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "accounts": [ "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" ] } ``` **Response:** ```json { "moved" : "1" } ``` --- ### account_remove _enable_control required_ Remove **account** from **wallet** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "account_remove", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "account": "nano_39a73oy5ungrhxy5z5oao1xso4zo7dmgpjd4u74xcrx3r1w6rtazuouw6qfi" } ``` **Response:** ```json { "removed": "1" } ``` --- ### account_representative_set _enable_control required_ Sets the representative for **account** in **wallet** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "account_representative_set", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "account": "nano_39a73oy5ungrhxy5z5oao1xso4zo7dmgpjd4u74xcrx3r1w6rtazuouw6qfi", "representative": "nano_16u1uufyoig8777y6r8iqjtrw8sg8maqrm36zzcm95jmbd9i9aj5i8abr8u5" } ``` **Response:** ```json { "block": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Optional "work"** _version 9.0+_ Work value (16 hexadecimal digits string, 64 bit). Uses **work** value for block from external source and disables work precaching for this account. Not using this field re-enables work precaching. --- ### accounts_create _enable_control required, version 9.0+_ Creates new accounts, insert next deterministic keys in **wallet** up to **count** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "accounts_create", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "count": "2" } ``` **Response:** ```json { "accounts": [ "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3s00000000" ] } ``` **Optional enabling work generation** _version 11.2+_ Boolean, false by default. Enables work generation after creating accounts **Request:** ```json { "action": "accounts_create", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "count": "2", "work": "true" } ``` ***Note:*** Before version 11.2 work generation was enabled by default, if you want to disable work generation for previous versions, use "work": "false" --- ### block_create (optional wallet) See [block_create](#block_create) Node RPC command above --- ### password_change _enable_control required_ Changes the password for **wallet** to **password** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "password_change", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "password": "test" } ``` **Response:** ```json { "changed" : "1" } ``` --- ### password_enter Enters the **password** in to **wallet** to unlock it **Request:** ```json { "action": "password_enter", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "password": "test" } ``` **Response:** ```json { "valid": "1" } ``` --- ### password_valid Checks whether the password entered for **wallet** is valid **Request:** ```json { "action": "password_valid", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "valid" : "1" } ``` --- ### receive _enable_control required_ Receive receivable **block** for **account** in **wallet**. If receiving the block opens the account, sets the account representative to a [wallet representative](#wallet_representative). Before v21, the representative is set to the account itself. --8<-- "warning-enable-control.md" **Request:** ```json { "action": "receive", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "account": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", "block": "53EAA25CE28FA0E6D55EA9704B32604A736966255948594D55CBB05267CECD48" } ``` **Response:** ```json { "block": "EE5286AB32F580AB65FD84A69E107C69FBEB571DEC4D99297E19E3FA5529547B" } ``` **Optional "work"** _version 9.0+_ Work value (16 hexadecimal digits string, 64 bit). Uses **work** value for block from external source and disables work precaching for this account. Not using this field re-enables work precaching. --- ### receive_minimum _enable_control required, version 8.0+_ Returns receive minimum for node wallet --8<-- "warning-enable-control.md" **Request:** ```json { "action": "receive_minimum" } ``` **Response:** ```json { "amount": "1000000000000000000000000" } ``` --- ### receive_minimum_set _enable_control required, version 8.0+_ Set **amount** as new receive minimum for node wallet until restart --8<-- "warning-enable-control.md" **Request:** ```json { "action": "receive_minimum_set", "amount": "1000000000000000000000000000000" } ``` **Response:** ```json { "success": "" } ``` --- ### search_pending Deprecated in V24.0+. Replaced by [search_receivable](#search_receivable) --- ### search_receivable _since V24.0, use [search_pending](#search_pending) for V23.3 and below_ _enable_control required_ Tells the node to look for receivable blocks for any account in **wallet** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "search_receivable", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "started": "1" } ``` --- ### search_pending_all Deprecated in V24.0+. Replaced by [search_receivable_all](#search_receivable_all) --- ### search_receivable_all _since V24.0, use [search_pending_all](#search_pending_all) for V23.3 and below_ _enable_control required, version 8.0+_ Tells the node to look for receivable blocks for any account in all available wallets --8<-- "warning-enable-control.md" **Request:** ```json { "action": "search_receivable_all" } ``` **Response:** ```json { "success": "" } ``` --- ### send _enable_control required_ Send **amount** from **source** in **wallet** to **destination** --8<-- "warning-enable-control.md" !!! success "Use of `id` option is highly recommended" Integrations using the node wallet must ensure idempotency for transactions and this can be done externally if preferred. Using the `id` field provides this option internally and is highly recommended for all node wallet uses. **Request:** ```json { "action": "send", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "source": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", "destination": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", "amount": "1000000", "id": "your-unique-id" } ``` **Response:** ```json { "block": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` Proof of Work is precomputed for **one** transaction in the background when you are using the node wallet to track accounts. If it has been a while since your last transaction it will send instantly, the next one will need to wait for Proof of Work to be generated. If the request times out, then the send may or may not have gone through. If you want to the ability to retry a failed send, all send calls must specify the id parameter as follows **Highly recommended "id"** _version 10.0+_ You can (and should) specify a **unique** id for each spend to provide [idempotency](https://en.wikipedia.org/wiki/Idempotence#Computer_science_meaning). That means that if you call `send` two times with the same id, the second request won't send any additional Nano, and will return the first block instead. The id can be any string. **This may be a required parameter in the future.** If you accidentally reuse an id, the send will not go through (it will be seen as a duplicate request), so make sure your ids are unique! They must be unique per node, and are not segregated per wallet. Using the same id for requests with different parameters (wallet, source, destination, and amount) is undefined behavior and may result in an error in the future. **Request:** ```json { "action": "send", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "source": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", "destination": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", "amount": "1000000", "id": "7081e2b8fec9146e" } ``` **Response:** ```json { "block": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` Sending the request again will yield the same block, and will not affect the ledger. **Optional "work"** _version 9.0+_ Work value (16 hexadecimal digits string, 64 bit). Uses **work** value for block from external source and disables work precaching for this account. Not using this field re-enables work precaching. **Request:** ```json { "action": "send", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "source": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", "destination": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", "amount": "1000000", "work": "2bf29ef00786a6bc" } ``` --- ### sign (optional wallet) See [sign](#sign) Node RPC command above --- ### wallet_add _enable_control required_ Add an adhoc private key **key** to **wallet** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "wallet_add", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "key": "34F0A37AAD20F4A260F0A5B3CB3D7FB50673212263E58A380BC10474BB039CE4" } ``` **Response:** ```json { "account": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" } ``` **Optional disabling work generation** _version 9.0+_ Boolean, false by default. Disables work generation after adding account **Request:** ```json { "action": "wallet_add", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "key": "34F0A37AAD20F4A260F0A5B3CB3D7FB50673212263E58A380BC10474BB039CE4", "work": "false" } ``` --- ### wallet_add_watch _enable_control required, version 11.0+_ Add watch-only **accounts** to **wallet** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "wallet_add_watch", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "accounts": [ "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", "nano_111111111111111111111111111111111111111111111111111000000000" ] } ``` **Response:** ```json { "success" : "" } ``` --- ### wallet_balances Returns how many raw is owned and how many have not yet been received by all accounts in **wallet** --8<-- "warning-includes-unconfirmed.md" --8<-- "deprecation-info-pending.md" **Request:** ```json { "action": "wallet_balances", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "balances" : { "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000": { "balance": "10000", "pending": "10000", "receivable": "10000" } } } ``` **Optional "threshold"** _version 9.0+_ Number (128 bit, decimal). Returns wallet accounts balances more or equal to **threshold** --- ### wallet_change_seed _enable_control required_ Changes seed for **wallet** to **seed**. ***Notes:*** Clear all deterministic accounts in wallet! To restore account from new seed use RPC [accounts_create](#accounts_create). `last_restored_account` and `restored_count` fields in response returned since _version 19.0+_ --8<-- "warning-enable-control.md" **Request:** ```json { "action": "wallet_change_seed", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "seed": "74F2B37AAD20F4A260F0A5B3CB3D7FB51673212263E58A380BC10474BB039CEE" } ``` **Response:** ```json { "success" : "", "last_restored_account": "nano_1mhdfre3zczr86mp44jd3xft1g1jg66jwkjtjqixmh6eajfexxti7nxcot9c", "restored_count": "1" } ``` **Optional "count"** _version 18.0+_ Number, 0 by default. Manually set **count** of accounts to restore from seed --- ### wallet_contains Check whether **wallet** contains **account** **Request:** ```json { "action": "wallet_contains", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "account": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" } ``` **Response:** ```json { "exists": "1" } ``` --- ### wallet_create _enable_control required_ Creates a new random wallet id --8<-- "warning-enable-control.md" **Request:** ```json { "action": "wallet_create" } ``` **Response:** ```json { "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Optional "seed"** _version 18.0+_ Seed value (64 hexadecimal digits string, 256 bit). Changes seed for a new wallet to **seed**, returning last restored account from given seed & restored count --- ### wallet_destroy _enable_control required_ Destroys **wallet** and all contained accounts --8<-- "warning-enable-control.md" **Request:** ```json { "action": "wallet_destroy", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "destroyed": "1" } ``` --- ### wallet_export Return a json representation of **wallet** **Request:** ```json { "action": "wallet_export", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "json" : "{\"0000000000000000000000000000000000000000000000000000000000000000\": \"0000000000000000000000000000000000000000000000000000000000000001\"}" } ``` --- ### wallet_frontiers Returns a list of pairs of account and block hash representing the head block starting for accounts from **wallet** **Request:** ```json { "action": "wallet_frontiers", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "frontiers": { "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } } ``` --- ### wallet_history _version 18.0+_ Reports send/receive information for accounts in wallet. Change blocks are skipped, open blocks will appear as receive. Response will start with most recent blocks according to local ledger. --8<-- "warning-includes-unconfirmed.md" **Request:** ```json { "action": "wallet_history", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "history": [ { "type": "send", "account": "nano_1qato4k7z3spc8gq1zyd8xeqfbzsoxwo36a45ozbrxcatut7up8ohyardu1z", "amount": "30000000000000000000000000000000000", "block_account": "nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est", "hash": "87434F8041869A01C8F6F263B87972D7BA443A72E0A97D7A3FD0CCC2358FD6F9", "local_timestamp": "1527698508" }, { "type": "send", "account": "nano_38ztgpejb7yrm7rr586nenkn597s3a1sqiy3m3uyqjicht7kzuhnihdk6zpz", "amount": "40000000000000000000000000000000000", "block_account": "nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est", "hash": "CE898C131AAEE25E05362F247760F8A3ACF34A9796A5AE0D9204E86B0637965E", "local_timestamp": "1527698492" } ] } ``` **Optional "modified_since"** UNIX timestamp (number), 0 by default. Return only accounts modified in local database after specific timestamp --- ### wallet_info _version 15.0+_ Given a **wallet** id, from all of the accounts in the wallet, returns: * Sum of their **balance** amounts * Total number of accounts as **accounts_count** * Number of deterministic accounts as **deterministic_count** * Number of adhoc (non-deterministic) accounts as **adhoc_count** * Index of last account derived from the walet seed as **deterministic_index** (equal to deterministic accounts number if no accounts were removed) * Sum of all frontier block heights as **accounts_block_count** * Sum of confirmed block heights as **accounts_cemented_block_count** --8<-- "warning-includes-unconfirmed.md" --8<-- "deprecation-info-pending.md" **Request:** ```json { "action": "wallet_info", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "balance": "10000", "pending": "10000", "receivable": "10000", "accounts_count": "3", "adhoc_count": "1", "deterministic_count": "2", "deterministic_index": "2", "accounts_block_count": "14", "accounts_cemented_block_count": "13" } ``` --- ### wallet_ledger _enable_control required, version 11.0+_ Returns frontier, open block, change representative block, balance, last modified timestamp from local database & block count for accounts from **wallet** --8<-- "warning-includes-unconfirmed.md" --8<-- "warning-enable-control.md" --8<-- "deprecation-info-pending.md" **Request:** ```json { "action": "wallet_ledger", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "accounts": { "nano_11119gbh8hb4hj1duf7fdtfyf5s75okzxdgupgpgm1bj78ex3kgy7frt3s9n": { "frontier": "E71AF3E9DD86BBD8B4620EFA63E065B34D358CFC091ACB4E103B965F95783321", "open_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F", "representative_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F", "balance": "0", "modified_timestamp": "1511476234", "block_count": "2" } } } ``` **Optional "representative", "weight", "receivable"** Booleans, false by default. Additionally returns representative, voting weight, receivable balance for each account **Request:** ```json { "action": "wallet_ledger", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "representative": "true", "weight": "true", "receivable": "true" } ``` **Response:** ```json { "accounts": { "nano_11119gbh8hb4hj1duf7fdtfyf5s75okzxdgupgpgm1bj78ex3kgy7frt3s9n": { "frontier": "E71AF3E9DD86BBD8B4620EFA63E065B34D358CFC091ACB4E103B965F95783321", "open_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F", "representative_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F", "balance": "0", "modified_timestamp": "1511476234", "block_count": "2", "representative": "nano_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs", "weight": "0", "pending": "0", "receivable": "0" } } } ``` **Optional "modified_since"** UNIX timestamp (number), 0 by default. Return only accounts modified in local database after specific timestamp --- ### wallet_lock _enable_control required, version 9.0+_ Locks **wallet** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "wallet_lock", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "locked": "1" } ``` --- ### wallet_locked Checks whether **wallet** is locked **Request:** ```json { "action": "wallet_locked", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "locked": "0" } ``` --- ### wallet_pending Deprecated in V24.0+. Replaced by [wallet_receivable](#wallet_receivable) --- ### wallet_receivable _since V24.0, use [wallet_pending](#wallet_pending) for V23.3 and below_ _enable_control required_ Returns a list of block hashes which have not yet been received by accounts in this **wallet** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "wallet_receivable", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "count": "1" } ``` **Response:** ```json { "blocks": { "nano_1111111111111111111111111111111111111111111111111117353trpda": ["142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D"], "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": ["4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74"] } } ``` **Optional "threshold"** Number (128 bit, decimal). Returns a list of receivable block hashes with amount more or equal to **threshold** **Request:** ```json { "action": "wallet_receivable", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "count": "1", "threshold": "1000000000000000000000000" } ``` **Response:** ```json { "blocks": { "nano_1111111111111111111111111111111111111111111111111117353trpda": { "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D": "6000000000000000000000000000000" }, "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": { "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74": "106370018000000000000000000000000" } } } ``` **Optional "source"** _version 9.0+_ Boolean, false by default. Returns a list of receivable block hashes with amount and source accounts **Request:** ```json { "action": "wallet_receivable", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "count": "1", "source": "true" } ``` **Response:** ```json { "blocks": { "nano_1111111111111111111111111111111111111111111111111117353trpda": { "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D": { "amount": "6000000000000000000000000000000", "source": "nano_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr" } }, "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": { "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74": { "amount": "106370018000000000000000000000000", "source": "nano_13ezf4od79h1tgj9aiu4djzcmmguendtjfuhwfukhuucboua8cpoihmh8byo" } } } } ``` **Optional "include_active"** _version 15.0+_ Boolean, false by default. Include active blocks without finished confirmations **Request:** ```json { "action": "wallet_receivable", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "count": "1", "include_active": "true" } ``` **Optional "min_version"** _version 15.0+_ Boolean, false by default. Returns the minimum version (epoch) of a block which can pocket this receivable block. **Optional "include_only_confirmed"** _version 19.0+_ Boolean, true by default (_version 22.0+_), previously false by default. Only returns confirmed blocks but with the caveat that their confirmation height might not be up-to-date yet. If false, unconfirmed blocks will also be returned. --- ### wallet_representative Returns the default representative for **wallet** **Request:** ```json { "action": "wallet_representative", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "representative": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" } ``` --- ### wallet_representative_set _enable_control required_ Sets the default **representative** for **wallet** _(used only for new accounts, already existing accounts use already set representatives)_ --8<-- "warning-enable-control.md" **Request:** ```json { "action": "wallet_representative_set", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "representative": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" } ``` **Response:** ```json { "set": "1" } ``` **Optional "update_existing_accounts"** _version 18.0+_ Boolean, false by default. Change representative for existing accounts in wallet. May require a lot of time to complete for large wallets due to work generation for change type state blocks --- ### wallet_republish _enable_control required, version 8.0+_ Rebroadcast blocks for accounts from **wallet** starting at frontier down to **count** to the network --8<-- "warning-enable-control.md" **Request:** ```json { "action": "wallet_republish", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "count": "2" } ``` **Response:** ```json { "blocks": [ "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293", "90D0C16AC92DD35814E84BFBCC739A039615D0A42A76EF44ADAEF1D99E9F8A35" ] } ``` --- ### wallet_work_get _enable_control required, version 8.0+_ Returns a list of pairs of account and work from **wallet** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "wallet_work_get", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "works": { "nano_1111111111111111111111111111111111111111111111111111hifc8npp": "432e5cf728c90f4f" } } ``` --- ### work_get _enable_control required, version 8.0+_ Retrieves work for **account** in **wallet** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "work_get", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp" } ``` **Response:** ```json { "work": "432e5cf728c90f4f" } ``` --- ### work_set _enable_control required, version 8.0+_ Set **work** for **account** in **wallet** --8<-- "warning-enable-control.md" **Request:** ```json { "action": "work_set", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp", "work": "0000000000000000" } ``` **Response:** ```json { "success": "" } ``` --- ## Unit Conversion RPCs --- ### nano_to_raw Convert `nano` amount (10^30 raw) into `raw` (10^0) **Request:** ```json { "action": "nano_to_raw", "amount": "1" } ``` **Response:** ```json { "amount": "1000000000000000000000000000000" } ``` ### raw_to_nano Convert `raw` amount (10^0) into `nano` (10^30 raw) **Request:** ```json { "action": "raw_to_nano", "amount": "1000000000000000000000000000000" } ``` **Response:** ```json { "amount": "1" } ``` --- ## Deprecated RPCs --- ### active_difficulty _added in version 19.0+_ _deprecated in version 22.0_ Returns the difficulty values (16 hexadecimal digits string, 64 bit) and related multiplier from base difficulty. | Field Name | Response Details | |---------------------------|------------------| | `multiplier` | Multiplier of the `network_current` from the base difficulty of `network_minimum` for comparison. Note that in V22.0+ this will always be 1 (see below for details). | | `network_minimum` | Minimum difficulty required for the network for all block types | | `network_current` | _V22.0+_ same minimum difficulty above due to the deprecation of active difficulty calculations used for prioritization in previous versions; _up to V21.3_ 10 second trended average of adjusted difficulty seen on prioritized transactions, refreshed every 500ms | | `network_receive_minimum` | Lower difficulty threshold exclusively for receive blocks | | `network_receive_current` | _V22.0+_ same minimum receive difficulty above due to the deprecation of active difficulty calculations used for prioritization in previous versions; _up to V21.3_ 10 second trended average of adjusted difficulty seen on prioritized receive transactions, refreshed every 500ms | !!! info "Constant values returned" Due to the deprecation of active difficulty calculations as of V22.0, this RPC call will return constant values as seen below. These values can be used as difficulty thresholds for the respective block types, but this RPC call should not be used for retrieving these values going forward. **Request:** ```json { "action": "active_difficulty" } ``` **Response:** ```json { "deprecated": "1", "network_minimum": "fffffff800000000", "network_receive_minimum": "fffffe0000000000", // since V21.2 "network_current": "fffffff800000000", "network_receive_current": "fffffe0000000000", // since V21.2 "multiplier": "1" } ``` **Optional "include_trend"** Boolean, false by default. Also returns the trend of difficulty seen on the network as a **list of multipliers**. Sampling occurs every 500ms. The list is ordered such that the first value is the most recent sample. Note: Before v20, the sampling period was between 16 and 36 seconds. **Request:** ```json { "action": "active_difficulty", "include_trend": "true" } ``` **Response:** ```json { ..., "difficulty_trend": [ "1.156096135149775", "1.190133894573061", "1.135567138563921", "1.000000000000000", "...", "1.000000000000000" ] } ``` --- ### accounts_pending Deprecated in V24.0+. Replaced by [accounts_receivable](#accounts_receivable) --- ### history **Deprecated**: please use `account_history` instead. It provides a `head` option which is identical to the history `hash` option. --- ### krai_from_raw Deprecated in V28.0+. For alternatives, see [Unit Conversion RPCs](#unit-conversion-rpcs) Divide a raw amount down by the krai ratio. **Request:** ```json { "action": "krai_from_raw", "amount": "1000000000000000000000000000" } ``` **Response:** ```json { "amount": "1" } ``` --- ### krai_to_raw Deprecated in V28.0+. For alternatives, see [Unit Conversion RPCs](#unit-conversion-rpcs) Multiply an krai amount by the krai ratio. **Request:** ```json { "action": "krai_to_raw", "amount": "1" } ``` **Response:** ```json { "amount": "1000000000000000000000000000" } ``` --- ### mrai_from_raw Deprecated in V28.0+. For alternatives, see [Unit Conversion RPCs](#unit-conversion-rpcs) Divide a raw amount down by the Mrai ratio. **Request:** ```json { "action": "mrai_from_raw", "amount": "1000000000000000000000000000000" } ``` **Response:** ```json { "amount": "1" } ``` --- ### mrai_to_raw Deprecated in V28.0+. For alternatives, see [Unit Conversion RPCs](#unit-conversion-rpcs) Multiply an Mrai amount by the Mrai ratio. **Request:** ```json { "action": "mrai_to_raw", "amount": "1" } ``` **Response:** ```json { "amount": "1000000000000000000000000000000" } ``` --- ### node_id_delete _enable_control required, _added in version 17.0+_ _deprecated in version 19.0_ --8<-- "warning-debug-only-command.md" Removing node ID (restart required to take effect) --8<-- "warning-enable-control.md" **Request:** ```json { "action": "node_id_delete" } ``` **Response:** ```json { "deprecated": "1" } ``` --- ### rai_from_raw Deprecated in V28.0+. For alternatives, see [Unit Conversion RPCs](#unit-conversion-rpcs) Divide a raw amount down by the rai ratio. **Request:** ```json { "action": "rai_from_raw", "amount": "1000000000000000000000000" } ``` **Response:** ```json { "amount": "1" } ``` --- ### rai_to_raw Deprecated in V28.0+. For alternatives, see [Unit Conversion RPCs](#unit-conversion-rpcs) Multiply an rai amount by the rai ratio. **Request:** ```json { "action": "rai_to_raw", "amount": "1" } ``` **Response:** ```json { "amount": "1000000000000000000000000" } ``` --- ### pending Deprecated in V23.0+. Replaced by [receivable](#receivable) --- ### pending_exists Deprecated in V23.0+. Replaced by [receivable_exists](#receivable_exists) --- ## Removed RPCs --- ### confirmation_height_currently_processing _added in version 19.0+_ _removed in version 27.0_ --8<-- "warning-debug-only-command.md" Returns the hash of the block which is having the confirmation height set for, error otherwise. When a block is being confirmed, it must confirm all blocks in the chain below and iteratively follow all receive blocks. This can take a long time, so it can be useful to find which block was the original being confirmed. **Request:** ```json { "action": "confirmation_height_currently_processing" } ``` **Response:** ```json { "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` --- ### block_count_type Reports the number of blocks in the ledger by type (send, receive, open, change, state with version) **Request:** ```json { "action": "block_count_type" } ``` **Response:** ```json { "send": "5016664", "receive": "4081228", "open": "546457", "change": "24193", "state_v0": "4216537", "state_v1": "10653709", "state": "14870246" } ``` --- ### payment_begin Begin a new payment session. Searches wallet for an account that's marked as available and has a 0 balance. If one is found, the account number is returned and is marked as unavailable. If no account is found, a new account is created, placed in the wallet, and returned. **Request:** ```json { "action": "payment_begin", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "account" : "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" } ``` --- ### payment_end End a payment session. Marks the account as available for use in a payment session. **Request:** ```json { "action": "payment_end", "account": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", "wallet": "FFFD1BAEC8EC20814BBB9059B393051AAA8380F9B5A2E6B2489A277D81789EEE" } ``` **Response:** ```json { } ``` --- ### payment_init Marks all accounts in wallet as available for being used as a payment session. **Request:** ```json { "action": "payment_init", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` **Response:** ```json { "status": "Ready" } ``` --- ### payment_wait Wait for payment of 'amount' to arrive in 'account' or until 'timeout' milliseconds have elapsed. **Request:** ```json { "action": "payment_wait", "account": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", "amount": "1", "timeout": "1000" } ``` **Response:** ```json { "deprecated": "1", "status" : "success" } ``` ================================================ FILE: docs/core-development/code-standards.md ================================================ title: Code Standards description: Learn about the code standards expected when contributing to the nano protocol and node implementation # Code standards ## Formatting clang-format is used to enforce most of the formatting rules, such as: * Tabs for indentation. * Open braces go on new lines. * Space before open parenthesis. * Space after comma. Running `ci/clang-format-do.sh` on \*nix systems is required before pushing your code to ensure that the formatting is good. If you want to do formatting from the IDE, chances are there's a plugin available. Visual Studio for instance provides a way to automatically format on saving. The definition file `.clang-format` is located in the project root directory. For CMake changes, running `cmake-format-do.sh` is required as well. Make sure you set up your editor to use tabs. Use tabs for indentation, and spaces for alignment [^1]. That way, you can use any tab size you want in your favorite editor, but the code will still look good for people with different settings. ## General guidelines * Use `auto` type inference for local variables if it's clear from the context what the type will be. Use your best judgement, sometimes adding explicit types can increase readability [^2] * Handle exceptions, including IO exceptions for file and network operations. * Be liberal with `debug_assert`. Use asserts to check invariants, not potential runtime errors, which should be handled gracefully. `debug_assert` has an advantage over normal `assert` as it will always print out the stacktrace of the current thread when it hits. Debug asserts are for detecting bugs, not error handling. There is also `release_assert` which is similar to `debug_assert` but also hits in a release build. When there is unexpected behaviour and no suitable way to recover it can be used to halt program execution. * Be liberal with `logger.always_log` or `logger.try_log` statements, except in performance critical paths. * Add comments to explain complex and subtle situations, but avoid comments that reiterates what the code already says. * Use RAII and C++11 smart pointers to manage memory and other resources. ## Performance and scalabiliy considerations * When making changes, think about performance and scalability. Pick good data structures and think about algorithmic complexity. * Nested loops yield quadratic behavior - is there an alternative? A typical example is removing an inner lookup loop with an unordered set/map to improve lookup performance to O(1). * Make sure your change doesn't conflict with the scalability characteristics described in the white paper. ## Security Your code will be reviewed with security in mind, but please do your part before creating a pull request: * Familiarize yourself with best practices for writing secure C++ code. In particular: * Consult https://wiki.sei.cmu.edu/confluence/display/cplusplus * Avoid using ANSI C functions. Many of these are prone to buffer overruns. * Avoid using C strings and direct buffer manipulation. * Use static and dynamic analysis tools, such as valgrind, XCode instrumentation, linters and sanitizers. These tools are also great for debugging crashes and performance problems. [^1]: https://dmitryfrank.com/articles/indent_with_tabs_align_with_spaces [^2]: http://www.acodersjourney.com/2016/02/c-11-auto/ ================================================ FILE: docs/core-development/collaboration-process.md ================================================ title: Collaboration Process description: Find out how the open source collaboration process works with the nano protocol and node software # Collaboration Process ## Code Process **Fork and do all your work on a branch** Nano prefers the standard GitHub workflow. You create a fork of the nanocurrency/nano-node repository (or other repositories as needed), make changes on new branches for features/fixes, and push these up to be added as Pull Requests. **Create pull requests** Before: * Branch out of the **develop** branch. The **master** branch is only updated on new releases. * Review your code locally. Have you followed the [Code Standards](code-standards.md) closely? * Run tests: `core_test`,`qt_test`,`rpc_test` (see [running tests](understanding-the-code.md#tests) for more details). Did you consider adding a test case for your feature? * Run [ASAN](../integration-guides/build-options.md#address-sanitizer), [TSAN](../integration-guides/build-options.md#thread-sanitizer) and [Valgrind](../integration-guides/build-options.md#valgrind) to detect memory, threading or other bugs * Run clang formatting script and resolve any raised issues: `ci/clang-format-do.sh` * Commit and push your fork branch After: * Create pull request on the upstream repository: * Make sure you add a description that clearly describes the purpose of the PR. * If the PR solves one or more issues, please reference these in the description. * Check that CI completes successfully - this can take up to a few hours depending on current CI queues. If any failures exist, fix the problem and push an update. * Respond to comments and reviews in a timely fashion. **Resolve conflicts** If time passes between your pull request (PR) submission and the team accepting it, merge conflicts may occur due to activity on develop, such as merging other PR's before yours. In order for your PR to be accepted, you must resolve these conflicts. The preferred process is to rebase your changes, resolve any conflicts, and push your changes again. [^1][^2] * Check out your branch * `git fetch upstream` * `git rebase upstream/develop` * Resolve conflicts in your favorite editor * `git add {filename}` * `git rebase --continue` * Commit and push your branch **Consider squashing or amending commits** In the review process, you're likely to get feedback. You'll commit and push more changes, get more feedback, etc. This can lead to a messy git history, and can make stuff like bisecting harder. Once your PR is OK'ed, please squash the commits into a one.[^3] Note that you can also update the last commit with `git commit --amend`. Say your last commit had a typo. Instead of committing and having to squash it later, simply commit with amend and push the branch. ## Finding issues or features to work on - Issues are available on GitHub, with the most urgent being in the latest milestone for release - Start with issues labeled as [`good first issue`](https://github.com/nanocurrency/nano-node/labels/good%20first%20issue) or connect with the NF core developers on [Discord](https://chat.nano.org) or the [forum](https://forum.nano.org) for ideas on how to help - If you find an issue you'd like to help with, comment and tag a [Nano Foundation team member](https://github.com/orgs/nanocurrency/people) who can evaluate and assign it to you ## Submitting issues and feature requests Standard GitHub templates exist for submitting any found issues or feature requests. If you plan on working on a bug or feature that doesn't already have a GitHub Issue associated with it, please submit it first so the team is aware. See https://github.com/nanocurrency/nano-node/issues/new/choose for templates. ## Discussion channels Various channels exist for discussing code changes with the Nano Foundation and community. **GitHub** To help persist useful information about a particular issue or feature, it is best to discuss within the related GitHub Issue or Pull Request. Members of the nano community and Nano Foundation actively follow and will engage when available. **Discord for chat** For live chat, join the server at https://chat.nano.org and check out the `#protocol` and `#development` channels. The various channels under the `TESTING` section can also be helpful to follow. **Forum** Another area for technical and code related discussions is the [forum](https://forum.nano.org). There are categories for `Protocol Design` and `Development` that are useful in discussing ideas. This can be a great place for getting feedback on ideas and exploring further before finalizing fixes and features in GitHub. ## Proposals There currently is no formal process for proposals on the nano network. This is an area actively being investigated and if requirements for submissions change, this area will be updated. For now, if you wish to propose an new idea, it is recommended to discuss on the [forum](https://forum.nano.org) first to gather feedback and use the [GitHub Issues](https://github.com/nanocurrency/nano-node/issues/new/choose) on the concept is solidifed/validated. [^1]: https://help.github.com/articles/resolving-merge-conflicts-after-a-git-rebase/ [^2]: https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/ [^3]: https://github.com/todotxt/todo.txt-android/wiki/Squash-All-Commits-Related-to-a-Single-Issue-into-a-Single-Commit ================================================ FILE: docs/core-development/developer-discussions.md ================================================ title: Developer Discussions description: Links & notes for recurring live discussions about Nano development. Includes discussion between community developers and the Nano Foundation. Technical, developer-focused. # Developer Discussions Links & notes for recurring live discussions about Nano development. Includes discussion between community developers and the Nano Foundation. Technical, developer-focused. !!! note These developer discussions are best effort, live discussions, and may not contain the most accurate (or most recent) information. The intent of these discussions is to promote transparency, collaboration, & community-driven efforts, but development plans may change at any time. The below notes are also best effort, and may not be 100% accurate. ## Sept 3, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1830969052820578365?t=Abqg6T-exPd5FhaQ2inY2w&s=19) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1f822rt/weekly_nano_developer_space_aug_3_2024/) ## Aug 20, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1825895842437607934?t=3t1YvnV2gRsLJXoCgECw6w&s=19) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1ewzj2n/weekly_nano_developer_space_aug_20_2024/) ## Aug 6, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1820822202297819143) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1elry5z/weekly_nano_developer_space_aug_6_2024/) ## July 23, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1815748878320189616?t=L8QhI04wdbx87MQIJYoxug&s=19) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1eaa9i0/weekly_nano_developer_space_jul_23_2024/) - [YouTube](https://www.youtube.com/watch?v=cMK_Q50uWHk) ## July 16, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1813204252380070206) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1e54dvm/weekly_nano_developer_space_july_16_2024/) - [YouTube](https://www.youtube.com/watch?v=Dx5ZEYwdbyw) ## July 9, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1810675179137192279?t=hEmkKBHOxRK9RofyNnUwVg&s=19) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1dz36p3/weekly_nano_developer_space_jul_9_2024/) - [YouTube](https://www.youtube.com/watch?v=Z7n75b8i9sI) ## July 2, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1808138726742065452?t=eqerZHL7ApiqRzFOs91V5g&s=19) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1dtmuk4/weekly_nano_developer_space_jul_2_2024/) - [YouTube](https://www.youtube.com/watch?v=JSEBA5HNqgE) ## June 18, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1803065216919273931) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1dj46ct/weekly_nano_developer_space_june_18_2024/) ## June 11, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1800528535251267598?t=b7_ZOImygrwAW8yiRw8cdw&s=19) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1ddgvyj/weekly_nano_developer_talk_june_11_2024/) ## May 21, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1792897054726824333) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1cx7jqw/weekly_nano_developer_space_may_21_2024/) ## May 14, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1790381641107439731?t=Ms5Dy0bBFVqx8GbkOy8lGA) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1crv7i1/weekly_nano_developer_space_may_14_2024/) ## April 30, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1785308297924432315) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1ch55iu/weekly_nano_developer_space_apr_30_2024/) ## April 23, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1782771656408158483) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1cbhe9x/weekly_nano_developer_space_apr_23_2024/) ## April 16, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1780234655565746684?t=FGvjQKPRKAbxGRSIfCHR4A) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1c5gwux/weekly_nano_developer_space_apr_16_2024/) ## April 9, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1777697905698107554) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1c0268f/weekly_nano_developer_space_apr_9_2024/) ## March 26, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1772639556455567629?t=RTr-oEgf8ZoM1tEcfInxBw) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1bobrah/weekly_nano_developer_space_mar_26_2024/) ## March 19, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1770091771541828085) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1bin1m6/weekly_nano_developer_space_mar_19_2024/) ## March 12, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1767566192103825707) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1bd25p2/weekly_nano_developer_talk_mar_12_2024/) ## March 5, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1765029691398734023?t=r6mG_OO6tKdnu32F5dhjnQ) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1b79viz/weekly_nano_developer_space_mar_5_2024/) ## February 20, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1759956505606971745?t=98X_E9aTopR6qVaps1BEpw) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1avmgtd/weekly_nano_developer_space_feb_20_2024/) ## February 13, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1757414995858526559) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1apv3i4/weekly_nano_developer_space_feb_13_2024/) ## February 6, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1754882713926926420?t=3KncD_dJcwZeI07_JXuNdg) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1akexw7/weekly_nano_developer_space_feb_6_2024/) ## January 30, 2024 - [Developer call](https://x.com/gr0vity_dev/status/1752345979024490835) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/1af3o40/weekly_nano_developer_call_jan_30_2024/) ## January 23, 2024 - [Developer call](https://x.com/ColinLeMahieu/status/1749804269925232822) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/19dv1ca/weekly_nano_developer_call_jan_23_2024/) ## January 16, 2024 - [Developer call](https://twitter.com/ColinLeMahieu/status/1747272701008634175) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/198wdac/weekly_nano_developer_call_jan_16_2023/) ## January 9, 2024 - [Developer call](https://twitter.com/ColinLeMahieu/status/1744735898879811779) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/192my3t/weekly_nano_developer_space_jan_9_2024/) ## December 12, 2023 - [Developer call](https://twitter.com/ColinLeMahieu/status/1734588963585728526) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/18gs1kr/weekly_nano_developer_space_dec_12_2023_last_one/) ## December 5, 2023 - [Developer call](https://twitter.com/ColinLeMahieu/status/1732052255103221870) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/18bdsq8/weekly_nano_developer_talk_dec_5_2023/) ## November 28, 2023 - [Developer call](https://twitter.com/ColinLeMahieu/status/1729515603529023585) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/185xrqi/weekly_nano_developer_call_nov_28_2023/) ## November 21, 2023 - [Developer call](https://twitter.com/gr0vity_dev/status/1726978836074742207) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/180p7jf/weekly_nano_developer_space_nov_21_2023/) ## November 14, 2023 - [Developer call](https://twitter.com/ColinLeMahieu/status/1724442197179650478) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/17v5uat/weekly_nano_developer_space_november_14_2023/) ## November 7, 2023 - [Developer call](https://twitter.com/ColinLeMahieu/status/1721905435056488743) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/17pwaa2/weekly_nano_developer_space_nov_7_2023/) ## October 31, 2023 - [Developer call](https://twitter.com/ColinLeMahieu/status/1719368918895088121) ## October 24, 2023 - [Developer call](https://twitter.com/ColinLeMahieu/status/1716817097408524743) ## October 17, 2023 - [Developer call](https://twitter.com/ColinLeMahieu/status/1714280349738701183) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/17a344v/weekly_nano_developer_space_oct_17_2023/) ## October 10, 2023 - [Developer call](https://twitter.com/ColinLeMahieu/status/1711743518576672943) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/174yxtu/weekly_nano_developer_space_oct_10_2023/) ## October 3, 2023 - [Developer call](https://twitter.com/ColinLeMahieu/status/1709206677633782029) ## September 26, 2023 - [Developer call](https://twitter.com/ColinLeMahieu/status/1706669851912151247?t=YTMabUbEfkQgjIoVtGSKKg&s=19) - [Reddit discussion](https://www.reddit.com/r/nanocurrency/comments/16spnl2/colin_lemahieu_hosting_live_twitter_space_about/) ================================================ FILE: docs/core-development/overview.md ================================================ title: Core Development Overview description: All you need to know to help contribute to the core development of the nano node and protocol # Core Development Welcome and thanks for your interest in core development of the nano! The following resources contain information and guides for getting involved with the development of the node and protocol. ## Getting started It is recommended to have an understanding of how the nano protocol is designed to work so the code can be more easily read and evaluated. - Start by reviewing the [living whitepaper](../living-whitepaper/index.md) - Read through (or try out) the [running a node guides](../running-a-node/overview.md) - Understand [the basics](../integration-guides/the-basics.md) and maybe even some [advanced details](../integration-guides/advanced.md) about integrations - Learn how to [build the node yourself](../integration-guides/build-options.md) - Participate in the community through [Discord](https://chat.nano.org) - Start perusing the code in the repositories below and don't be afraid to ask questions ## Code repositories The Nano Foundation manages the [`nanocurrency`](https://github.com/nanocurrency) GitHub Organization account which includes various repositories for nano tools and implementations. Below is a partial list of the most common repositories referenced. | Name | Language | Purpose | |------|----------|---------| | [nanocurrency/nano-node](https://github.com/nanocurrency/nano-node) | C++| Primary node implementation used on the nano network | | [rs-nano-node](https://github.com/rsnano-node/rsnano-node) | Rust| Alternative node implementation by Gustav | | [nanocurrency/nano-work-server](https://github.com/nanocurrency/nano-work-server) | Rust | Standalone server for generating work values for blocks | | [nanocurrency/protocol](https://github.com/nanocurrency/protocol) | Kaitai Struct | Specification for nano network message protocol | | [nanocurrency/nanodb-specification](https://github.com/nanocurrency/nanodb-specification) | Kaitai Struct | Specification for database tables and fields used by the `nano-node` implementation | | [nanocurrency/nano-docs](https://github.com/nanocurrency/nano-docs) | Markdown | MKDocs based documentation this docs.nano.org site is built from | Most of the content in the following documentation is focused around the [nanocurrency/nano-node](https://github.com/nanocurrency/nano-node) repository, as that is where most development activity occurs. But there are tons of related projects creating useful tools, libraries, services and more for the nano ecosystem (see some options in [GitHub](https://github.com/search?q=nanocurrency&type=discussions)). ## Security vulnerability reporting --8<-- "warning-security-vulnerability-reporting.md" ## Nano Foundation core developers In addition to contributions from the wider nano community, the [Nano Foundation](https://nano.org/foundation) manages a team of core developers who contribute to the protocol and primary node implementation. For a list of code contributors, see the [GitHub Insights page](https://github.com/nanocurrency/nano-node/graphs/contributors). ================================================ FILE: docs/core-development/understanding-the-code.md ================================================ title: Understanding the code description: Learn about the nano code for better development practices # Understanding the code This guide is designed to give an overall structure of the core nano protocol codebase to help new developers get a better understanding of the different areas and how they interoperate. Due to the rapid changing nature of the protocol it’s possible some of the features are moved to different places or have changed entirely. Working on the protocol requires a very multi-disciplined and wide area of knowledge, none of it is particularly mandatory to get started but a good C++ understanding will help prevent being too overwhelmed initially: Items required include: - Windows/MacOS/Linux - C++20 compiler - Boost - Git - CMake Useful experience includes modern C++ knowledge (up to C++20) including multithreading primitives (mutex, condition variables, atomics) & templates, Boost (asio & beast), RocksDB, LMDB, FlatBuffers, JSON-RPC, IPC, networking communication (ip/tcp, message passing, broadcasting algorithms), QT, signal handling, PKI cryptography, git & cross-platform development. The main Nano projects are located inside the `/nano` subdirectory. ## Executable binaries All executables have `nano_` prefix and projects have a `main` function inside `entry.cpp` **nano_node** – The standard way to start a node. There are 2 source files in here, `entry.cpp` and `daemon.cpp`. `nano_daemon::daemon::run()` is always called so is a good place to put a breakpoint if there are any issues during node operation (especially errors when launching initially). **nano_rpc** – This executable does not need to be run explicitly unless out of process RPC is selected. https://docs.nano.org/integration-guides/advanced/?h=+nano_rpc#running-nano-as-a-service Because this project is quite small it is all done inside the `entry.cpp` file and is probably an easier starting point template should anything else need to be moved out of process in the future. **nano_wallet** – This essentially does the same as `nano_node` but doesn’t support all CLI commands and has a graphical user interface for the wallet. --- ## Tests The googletest (gtest) framework is used to validate a variety of functionality in the node, we do not currently use gmock in the codebase. ### Running tests The dev network is forced for locally run tests, this lowers work and other settings to make it simpler to test. Build with `cmake -DNANO_TEST=ON ..` See docs.nano.org for more information. There may be intermittent failures, if so add them here https://github.com/nanocurrency/nano-node/issues/1121 and fix if possible. ### Executables **core\_test** – This is where the majority of tests should go. If there is any new functionality added or something has changed, it more often than not should have a test here! Any new core areas should have their own separate test file to encapsulate the logic. **ipc\_flatbuffers\_test** – This actually doesn’t use the `gtest` library and has its own main file which just contains a simple example of using flatbuffers. **load_test** – This creates a dynamic number of nodes, sends blocks from 1 of the nodes (primary) and waits until all other nodes have the same number of blocks. This does not normally need to be modified but is run as part CI at the end. **rpc_test** – All RPC tests go here. There is some boilerplate to follow which creates an `ipc_server` for the node which mimics out of process rpc commands communicating with it. Care must be taken when creating write transactions as they are not allowed on io-threads (https://github.com/nanocurrency/nano-node/pull/1264). To make sure this is adhered to when calling the RPC commands, there is an RAII object `scoped_io_thread_name_change` which changes the current thread (normally the main one) to be `io`, and restores it when the object goes out of scope. For instance ``` ... scoped_thread_name_io.reset (); node.process (state_block); scoped_thread_name_io.renew (); ``` **slow_test** – Any core tests which are not suitable for CI because they take a long time (> a few seconds) should go here. There is a desire to make this file run once per night, but until then should be periodically run by developers. ### Work/Sig verification modifying for tests A common mistake is to request work for the hash of the block to be added, but it should happen on the root (previous one). The work difficulty is different for the live/beta/dev networks and are set using the `work_thresholds` class. During any local testing, where a lot of blocks are processed, work generation and signature verification can take the majority of the time. To speed this up it can make sense to manually lower the work difficulty even further and change the sig verification to always return `true`. ### Helpers **test_common** – This is a helper library which contains test specific (not node related) things which can be used by all test projects. This project should not have a `node` dependency. Anything which does should be put into `nano/node/testing.cpp`. ### Fuzzer The fuzzer uses libfuzzer which inputs arbitrary data continuously trying to find catch edge cases missed in traditional testing on specific examples. This is not currently supported on Windows. The executables are found in fuzzer_test/\*. The node must be built with the CMake option `-DNANO_FUZZER_TEST=ON`, this does not require that `NANO_TEST` be set. Currently there are 3 executables built: fuzz_bignum, fuzz_buffer, fuzz_endpoint_parsing. **Notes:** There aren’t currently tests for specific CLIs so it’s recommended to abstract the functionality so that it can be tested in `core_test`. ### Testing implementation details Sometimes it is necessary to be able to change something about a class only for a test. Rather than make this the class interface public just for tests, the specific tests can be added as friends to the class, this is done like so for a test named like so TEST (node, example); ``` class my_class { private: int private_member; // the Test (node, example); test can access this member friend class node_example_Test; }; ``` The test itself needs to be wrapped with the nano { } namespace for this to work correctly, if the class itself is in the nano namespace which is normally the case. ### Additional pre-release testing - Run tests with TSAN/ASAN/Valgrind. All errors should be fixed before launch unless these are determined to be test related or false positives. We currently have some errors with using coroutines. There are blacklist files for the sanitizers which remove some errors caused by lmdb & rocksdb. --- ## Bootstrapping When you first start a Nano node, it must download & validate transactions until its ledger (account & transaction history) is in sync with the other nodes on the network. This process is called bootstrapping. There are 3 bootstrapping methods, ascending, legacy, and lazy. See [here](https://github.com/nanocurrency/nano-node/issues/3837) and [here](https://medium.com/nanocurrency/nano-explainer-lazy-bootstrapping-6f091e1eae8c) for more information. `node/bootstrap/boostrap_attempt.hpp` contains the base class definition for bootstrap attempts. ### Ascending `node/bootstrap/bootstrap.cpp` Nano node versions V24 & V25 introduced ascended bootstrapping - a complete rewrite of how Nano nodes sync account & transaction history from scratch. Prior to V24, the bootstrap mechanism served transactions (blocks) in a top down format (i.e. newest to oldest / frontier to genesis), but since the blocks must be added to the local ledger from the bottom up (i.e. oldest to newest / genesis to frontier), the node spent a lot of time reordering transactions. This consumed a significant amount of disk space and disk IO (disk reads/writes), both of which contribute to long bootstrapping times (i.e. days or weeks). Ascending bootstrapping sends & processes transactions from the bottom up, allowing nodes to easily trace transaction order without a complicated (and time consuming) re-ordering process. This significantly improves the speed of bootstrapping, removes complexity from the codebase, & reduces overall resource usage. For more technical details, see [here](https://github.com/nanocurrency/nano-node/issues/3837). ### Legacy `node/bootstrap/bootstrap_legacy.cpp` Legacy bootstrapping works by requesting frontiers periodically (every 5 minutes) from a random selection of peers, this is done in `nano::node::ongoing_bootstrap ()`. `bootstrap_frontier.cpp` contains the frontier req client and server. A `frontier_req` message is send from `frontier_req_client` to get a list of frontiers from a peer’s `frontier_req_server` starting at `frontier_req.start` which is done as `accounts_begin (transaction, current + 1);`. The accounts are sorted by their hash. ### Lazy `node/bootstrap/bootstrap_lazy.hpp` Lazy bootstrapping works by having nodes monitor the real-time network and observing live block confirmation. In combination with [optimistic elections](https://github.com/nanocurrency/nano-node/pull/4111), when a node sees confirmation for a new block, all previous blocks in the newly confirmed block's account-chain are also considered valid & confirmed, and are then inserted into node's local ledger. ### Wallet lazy TODO ### How messages are handled `node/bootstrap/bootstrap_server.cpp` When a message is received through the bootstrap server, its header is first checked inside `nano::bootstrap_server::receive_header_action ()`. The message is deserialized and added in `add_request ()` to the `std::queue> requests` collection which holds a queue of messages. `run_next ()` is then called (and will be called after the request is finished if there are more messages to process), this runs the message through a `request_response_visitor` object which creates a `tcp_message_item` and adds it to the `tcp_message_manager` to be processed. The newest set of messages added were for telemetry. If new messages need adding that can be used as a guide: https://github.com/nanocurrency/nano-node/pull/2446 --- ## Workers (thread pool) The class definition for `thread_pool` is defined inside `nano/lib/threading.cpp`, which allows tasks to be added to a queue for execution as well as executed at a specific time. Previously there were worker/alarm classes, which were combined in https://github.com/nanocurrency/nano-node/pull/2871. Its primary purpose was to schedule write transactions off the io threads. It is generally recommended to push other tasks onto the io threads though to avoid bottlenecking these threads. --- ## Database There are 2 logical areas where a persistent file is needed: the ledger and wallets. For this 2 NoSQL databases which store binary data are used, namely LMDB & RocksDB. The ledger database is comprised of a few files: - `nano/secure/store.hpp`: database interfaces, value object conversions, visitors, and high-level implementations - `nano/node/lmdb/`: anything specific to LMDB goes here - `nano/node/rocksdb/`: anything specific to RocksDB goes here The wallets database uses the wallets_store which only has an LMDB backend. ### Database upgrades `nano::lmdb::store::do_upgrades ()` is where LMDB database upgrades are done. For instance `void nano::lmdb::store::upgrade_v21_to_v22 ()` combines all block databases into a single one. Raw mdb functions are normally required as `block_store::get ()` and other functions normally can’t be used because they are updated to the latest db spec. The RocksDB upgrades were introduced by V25.0. It follows a similar approach implemented for LMDB. There were in the past multiple upgrades during a release when a beta build went out and a subsequent upgrade was desired. Previously a ledger reset was done and the version was re-used but this was deemed too inconvenient. ### write_database_queue This was introduced to reduce LMDB write lock contention between the block processor and the confirmation height processor. As during bootstrapping or high TPS the block processor can hold onto the lock up to 5s (by default), before the lock is held by the blockprocessor it signals that it is about to get the LMDB lock, the confirmation height processor can make use of this information and continue processing where it would otherwise be stalled. Ongoing pruning also makes use of this. --- ## Block processing There are 4 types of legacy blocks: open, receive, send & change. There are the state blocks which encompass traits from the legacy subtypes as well as support epochs. In various places an `epoch_link` is checked, this indicates that the link field is set to one of the epoch accounts (for v1 state blocks), or possibly self for v2 state blocks upgrade blocks. No new legacy blocks can be created (there are about 10million), but they still need to be handled in any algorithm which deals with blocks because users can still be bootstrap from scratch. When a node is first launched without a ledger `block_store_partial::init ()` is called, this creates the genesis block. Blocks are then bootstrapped. --- ## Ledger `nano/secure/ledger.cpp` is where blocks are added and deleted to the ledger database. The ledger cache is used when it may be expensive to try and determine the count of something in the ledger. It was originally used for the cemented count, because this is determined by adding the confirmation height from all accounts. This does mean that any external write operations from LMDB (such as CLI command `--confirmation_height_clear`) will cause this number to get out of sync. This is not possible with RocksDB backend because it does not allow multi-process write transactions. --- ## Node initialization The biggest bottleneck for node start-up is caused by setting up the ledger cache. This requires scanning all accounts & conf height databases. A multi-threaded process (added in https://github.com/nanocurrency/nano-node/pull/2876) splits the account space into equal partitions (as accounts should be randomly distributed) and does sequential sorted reads in each partition; this is the most efficient way to search through any of the databases. Point/Random reads are very slow in comparison. ### Keeping build times low `nano/node/node.hpp` is the largest build bottleneck, it can increase build times of files by up to 10 seconds on some systems! Some boost files tend to be large too, they offer forward declaration headers such as `` & `` worth checking if they exist for any you are using in header files. ### node_initialized_latch Some classes use `node_initialized_latch.wait ();` The latch was added in https://github.com/nanocurrency/nano-node/pull/2042 this is to prevent some of the issues in the node constructor initializer list where the `node` object is passed and a child constructor is wants to use a node member which is not yet initialized. This makes it resume operation once the latch is incremented at the beginning of the `node` constructor. ### Initial output When the node is run it prints out some information about the database used, compiler etc. An example of appending to the output is here: https://github.com/nanocurrency/nano-node/pull/2807 --- ## CMake CMake is used as the build system, and git submodules for any third party dependencies (except boost which must be installed separately by the developer). In `CMakeLists.txt` header files (.hpp) are above source files (.cpp), no particular reason but consistency is important. ### Developer build options `-DNANO_TIMED_LOCKS=10` Added: https://github.com/nanocurrency/nano-node/pull/2267. In `nano/lib/locks.hpp(.cpp)`, `std::mutex`, `std::condition_variable`, `std::unique_lock` & `std::lock_guard` are wrapped in custom classes (with the same interface) which adds some extra timing functionality to check if a mutex was help for a time longer than `NANO_TIMED_LOCKS` in milliseconds. This is useful to see if mutex contention is a cause of any performance loss. To pinpoint a specific mutex https://github.com/nanocurrency/nano-node/pull/2765 added `NANO_TIMED_LOCKS_FILTER=confirmation_height_processor`. The full list of mutexes is available in `nano/lib/locks.cpp` - `mutex_identifier()` . --- ## APIs ### CLI There are 2 places that CLI commands can be added for use with `nano_node`, `nano/node/cli.cpp` & `nano/nano_node/entry.cpp`. The `nano/node/cli.cpp` CLI commands are also shared with `nano_wallet` so this is the place to put shared logic which can be used by both. CLI commands prefixed with `debug_*` shouldn’t really be used by end users unless they are diagnosing issues. Sometimes it can be useful to compare the RPC output with CLI, and rpc results such as `block_count` will return cached results. ### IPC When using the `nano_rpc` as a separate process (either child or manually starting it), there needs to be a way of communicating between processes. IPC supports tcp and unix domain sockets, `nano_rpc` only supports tcp as it can be run on a different computer. IPC 2.0 adds flatbuffer support (https://github.com/nanocurrency/nano-node/pull/2487) which can be used for the new RPC 2.0 (TBA). ### Websockets Websockets were introduced in https://github.com/nanocurrency/nano-node/pull/1840. Previously a HTTP callback had to be used, but websockets provides a more efficient 2 way communication protocol. Websocket events are available for various topics. For an example of adding a websocket topic look at: https://github.com/nanocurrency/nano-node/pull/2634. `observers.notify (message_a.data, endpoint);` is what ultimately invokes the websocket server to send a message which is deserialized inside `nano::websocket::message_builder`. --- ## Signal handling There are 2 sets of signal handlers registered (both are only set when the `nano_node` is run as a daemon. `SIGSEGV` & `SIGABRT` are set at the beginning which will create dump files if there is a segmentation fault during program execution (added in https://github.com/nanocurrency/nano-node/pull/1921/). `SIGINT` & `SIGTERM` signals catch non-kill intentional closing of the executable, such as pressing ctrl+c (added in https://github.com/nanocurrency/nano-node/pull/2018). This shuts down the node allows any running write transactions to finish. Only async signal safe functions should be used in signal handlers, this limits it to very specific functions. --- ## Memory allocators A lot of our heap usage is from deserializing block/votes off the wire and ledger database. To solve this we use a memory pool allocator which reuses memory in a freelist: https://github.com/nanocurrency/nano-node/pull/2047 In `nano/lib/memory.hpp` a `nano::make_shared` function is defined which checks if the global variable `use_memory_pool` is set (initialized during node startup reading the config `node.use_memory_pools`, which defaults to true). The memory is never reclaimed, this is a performance optimization. --- ## Libraries and submodules ### Boost We use the Boost library where possible, such as coroutine, filesystem, endian converter, lexical_cast, multi_index_container etc. If there is a static/dynamic Boost library which is not used, there are generally no issues in adding it. Just make sure the build scripts and documentation are updated. **nano/boost** Use `nano/boost/asio` `nano/boost/beast` for includes, this wraps up various includes and prevents warnings being shown (particularly on Windows builds). ### `nano/crypto_lib/` This is a small library which has no dependency to anything in the nano core, which is needed as it is included by the ed25519 library as well. More info here: https://github.com/nanocurrency/nano-node/pull/1870 ### `test/common/` Any functionality which is shared between test projects and may also use gtest library. There is also `nano/node/testing.cpp` which has no gtest dependency because it is also used in CLI commands too. ### `nano/lib` vs. `nano/secure` The`nano/lib` library was originally intended to be used by other programs wanting some of the nano functionality, but those specific external C functions were removed and it has now become the place to put all commonly used code. As such anything which doesn’t depend on the node should go here, and the `secure` library is now mostly for ledger specific things. ### git submodules We have a variety of submodules https://docs.nano.org/node-implementation/contributing/?h=+submodule#about-the-code-base third party dependencies are to be kept as minimal as possible in order to keep build times lean, but if there is a suitable one it can be added a submodule. --- ## Assertions `debug_assert` is essentially the same as the traditional C++ assert but also outputs a stacktrace. Added in https://github.com/nanocurrency/nano-node/pull/2568. This should be used to check programmer logic. `debug_assert (!mutex.try_lock ());` When functions require that a mutex is required before being called we often check that the mutex is locked. Although this is technically undefined behaviour to be called by a thread which already owns the mutex we have been using this idiom for years and found no issues with the major compilers. `release_assert` this is an assert which is triggered in both release/debug build, it also outputs a stacktrace. This was added https://github.com/nanocurrency/nano-node/pull/1114. This should be used if some invariant doesn’t hold and there is no suitable way to recover from this. Such as reading something from the ledger which is meant to exist but doesn’t, can indicate ledger corruption. --- ## Voting/Consensus To confirm a block a sufficient number of votes which are taken from `confirm_ack` messages are tallied up. If the tally is above the delta inside `nano::election::have_quorum ()` it returns true and the block is considered confirmed. `confirm_ack` messages can either contain the whole block or a hash (vote by hash). `confirm_req` message header as well as `confirm_ack` indicate what the type of the contents is in the header, either `not_a_block` which means dealing with block hashes or the block type. `nano/node/common.cpp` contains these messages (among others) and (de)serializing functions. ### voting The vote generator `nano::vote_generator::vote_generator` is responsible for collecting hashes that need a vote generated, combining them into a single `vote by hash` message, signing the package with the representative key and publishing the votes to the network. A maximum of `nano::network::confirm_ack_hashes_max` hashes can be combined into a single vote `confirm_ack` message, this provides a decent tradeoff between optimizing vote signatures and reducing bandwidth. While the process is running it waits for `config.vote_generator_delay` time in order to pack more hashes into a single vote message. If there are more than `config.vote_generator_threshold` after waiting then it will wait for one additional `config.vote_generator_delay` before broadcasting the message. This allows for fast vote publishing at lower rates while enabling more hashes to be combined together at higher rates. ### vote_processor Votes are signed by the representative and the vote processor schedules checking these votes through the `signature_checker` inside `nano::vote_processor::verify_votes ()`. Once a vote signature has been verified, the hashes within the vote packet are passed to active_elections where they are either added to an active election or added to the inactive votes cache if an election does not exist. ### active_transactions The active transactions class handles election management and prioritization. When a block is processed and `nano::active_transactions::insert` called, a new election is started for the block hash if one does not already exist. In addition to starting elections there is a 500ms `request_loop` that handles election management. This process assists with moving elections through the different transition states as well as moving elections to a prioritized status if there is a backlog of elections. During the requst loop the current network difficulty is updated through `update_active_multiplier` which takes the top `prioritized_cutoff` number of active elections that have not been confirmed and samples their difficulty multiplier. Finally, the active transactions class also handles frontiers that have not been confirmed. Most commonly this is from bootstrapping, where the frontier of an account is added to the active elections and vote requests are sent to other nodes to confirm the frontier and thereby the rest of the account and ancestors through confirmation height processing. ### confirmation_solicitor During the `request_loop` of the active transactions process, any election that is in the `active` state for more than 5 seconds will request votes from Principle Representative nodes that it has not seen a vote from yet. These requests are added to the `confirmation_solicitor` which aggregates the hashes up to `nano::network::confirm_req_hashes_max` into a single `confirm_req` message and publishes it to select PR nodes that have not voted. This helps fill any gaps in network communication failures where a vote may have been dropped which helps reach quorum on the highest priority elections. ### request_aggregator The request aggregator is responsible for collecting vote requests `confirm_req` messages from other nodes and finding the optimal responses. A local vote cache is used for recently generated votes, if the block hash in the request exists in the cache then a cached vote is returned, if the hash does not exist then the hash is added to the vote generator and a new vote is generated and published to the requesting node. The request aggregator also handles publishing forks if the request is for a competing fork. If the local node has a different winning hash it will publish a vote for the winning hash instead of the requested hash in addition to sending the requesting node the winning block as well. ### election An election is created when a new block is processed. The primary purpose of the election class is to tally the vote weight and ensure consensus between any competing forks. In order to efficiently move an election through the process it can have several states. Initially `passive` where it is waiting for votes from other nodes, then after 5 seconds if it has not been confirmed it will transition to `active` where vote requests to other nodes are made. After `active_request_count_min` rounds of requesting votes are complete if the election is still not confirmed it moves to `broadcasting` where it will publish the block to PR nodes that have not voted in an attempt to ensure the block has been propagated throughout the network. Under low load the `active` and `broadcasting` states are rarely used as all elections are complete within the `passive` window. Every vote that is added to the election triggers a check for whether quorum has been reached on the election. Quorum requires that the winning hash has `node.online_reps.delta` more weight than any competing forks. If quorum is reached the election is marked confirmed, transitions to the `confirmed` state and is added to the confirmation height procesor which updates the ledger. After an election is confirmed it can stay in the active elections container up to `confirmed_duration_factor` in order to continue to process votes and republish votes to other nodes, after which is it is removed. If an election lasts longer than 5 minutes and has not been confirmed it is transitioned to `expired_unconfirmed` and removed from the queue. This most often happens during high saturation when the active elections container reaches capacity. ### continuous backlog population Backlog population is a process in which a node scans all accounts in its ledger, with or without confirmed blocks, and forwards (activates) the accounts which do not have all their blocks confirmed to the election scheduler for prioritization and eventual queuing in the proper bucket. It is necessary to do this periodically because the amount of space in each bucket is limited, and the number of accounts needing confirmations can be much higher than that (especially during bootstrap or network spam attack). Continuous backlog population changes the ledger scan interval from every 5 minutes to constant, with population rate & frequency controlled by `backlog_scan_batch_size` and `backlog_scan_frequency`. See [here](https://github.com/nanocurrency/nano-node/pull/3999) for more details. ### optimistic elections Instead of confirming every block in every account-chain one-by-one, the optimistic scheduler randomly samples accounts with unconfirmed blocks and activates an election for the account's head block (the latest _unconfirmed_ block in the account-chain). Once the head block is confirmed, all previous dependent blocks (within the account-chain _and_ in other dependent account-chains; i.e. cross-chain) are considered confirmed. The number of optimistic elections is limited, so it doesn't replace or impact the default election scheduling behavior. See [here](https://github.com/nanocurrency/nano-node/pull/4111) for more details. ### Confirmation height processor When a block is confirmed `void nano::node::process_confirmed ()` the block is added to the confirmation height processor. This begins the process of cementing it and all of its dependents, once this occurs these blocks can never be rolled back. There are 2 confirmation height algorithms bounded and unbounded. Originally only the unbounded one existed, this would store the block hash for the original block confirmed, all its previous blocks, and recurse the bottom most receive block to the source and repeat the process. If this hit something like the binance chain or (any long chain) it could use a lot of memory (unbounded amount). So this brought about the bounded confirmation height processor algorithm which starts at the very bottom of the account chains but does the same recursion when a receive block is hit. This limits the amount of block hashes needing to be stored in memory to be able to cement the bottom most blocks. Checkpoints are used if there are a lot of accounts which need to be traversed to reach which exceeds the maximum amount of memory . It does mean in certain cases the same iteration will need to be done more than once but this should be a rare case only during initial cementing. Once the uncemented count (block count – cemented count) is less than 16K the unbounded processor is used. As mentioned above this instead starts from the top (original confirmed block) and works downwards and saves all the blocks hit (not just hash) which means they don’t need to be re-read during writing later. This does use a lot more memory though which is why this is limited to a certain number of blocks, once the unbounded cutoff is exceeded the bounded processor resumes. Both algorithms operate with a read transaction first which reduces write lock held time as it can do a lot of iterating. This does mean that there can be some inconsistency by the time the writing is done, but this shouldn’t be an issue because once a block is confirmed by the network it will stay confirmed by `debug_assert` checks are added to catch any programming mistakes. While it is more effort to maintain 2 algorithms the unbounded one largely existed before so it made sense to re-use it, given the performance improvements in almost cemented ledgers. ### Frontiers confirmation `nano/node/frontiers_confirmation.cpp` contains code which starts at the beginning of the accounts database (`nano::blockstore_partial::accounts_begin`) and iterates in ascending order and prioritises accounts based on the number of uncemented blocks (stores up to 100k) and requests confirmation for a limited number of these accounts. When the cemented count is above the hardcoded bootstrap weights this is limited to the number of optimistic elections which is 50 in this case so it is expected to be quite slow in this case. Accounts in wallets are also checked. --- ## Telemetry nano/node/telemetry.cpp contains the logic for telemetry processing. This sets up an ongoing telemetry request round (every 60 seconds on the live network) where a telemetry_req message is sent to every peer. There is an `alarm` timeout of about 10 seconds in which we require the response (telemetry_ack) to be received otherwise it is rejected. Any calls to get_metrics_* return a cached result. To add a new definition to the telemetry_ack message this can be used as a guide which added the `active_multiplier`: https://github.com/nanocurrency/nano-node/pull/2728 `telemetry_ack` messages are signed and are backwards compatible with older nodes (from v22 onwards). Those nodes will verify the whole message including any extra unknown data which is appended at the end is just ignored. To prevent ddosing by `telemetry_req` messages, nodes ignore messages received within that 60second (on live) boundary. This is done in `void nano::bootstrap_server::receive_header_action ()` --- ## Stats ### Counters The `stats` object is used to keep a count of events that have happened, this is a useful idiom for checking values in tests and is aggregated in the stats->counts RPC. There are main stat types and then details for that type. A simple example of adding new details and incrementing the stats can be seen here: https://github.com/nanocurrency/nano-node/pull/2515 Adding a type for a stat is a similar procedure just using the `nano::stat::type` enumerator. ### Objects Most classes which have a member variable of container of multiple items (map, vector, list etc..) should have a function with a prototype of: `std::unique_ptr collect_container_info (my_class & my_class, std::string const & name);` And then call this in an owning object which should itself be called recursively until it reaches the `node` object `collect_container_info`. They are typically not made as part of the class itself because it’s a very specialised function which is only called as part of the stats->object RPC, like so: `{"action":"stats","type":"objects"}` --- ## Pruning Pruning occurs periodically inside `nano::node::ongoing_ledger_pruning ()`. Pruning currently requires a full ledger to be bootstrapped and when an account frontier is confirmed it can then be pruned. The hashes of the pruned blocks are put into the pruned database so that we know to ignore any of these old blocks should the node bootstrap them again. Pending blocks cannot be pruned currently. --- ## Config files TOML config files are used, previously we used json files but TOML config files have the benefit of providing comments inside. There are no versions or upgrades done here, instead any defaults not explicitly overridden in the toml file get updated implicitly. There are few config files: ### config-node.toml This is actually called `daemonconfig.cpp` in the code base, but it wraps a `node_config` object. ### Other config files `config-rpc.toml` & `config-wallet.toml` contain settings which can be modified by the user to override the defaults. The most common ones are enabling rpc/websocket & rocksdb. The `nano/node/node_rpc_config.cpp` are the rpc settings for the node. --- ## Key resources **nanodb-specification & protocol repositories** There are 2 repositories which use kaitai specifications which should be updated (normally near the end of the release) if there are any changes to the https://github.com/nanocurrency/nanodb-specification or https://github.com/nanocurrency/protocol message **nano-docs** All RPC/CLI changes should have a documentation update specifying the version that they work. There is a documentation label in the nano-node repository which is useful as a reminder that they should be added, documentation updates are often overlooked. **nano.community** A great community built resource for developers is https://nano.community/getting-started-devs/getting-started where broad details of the design are outlined along with code-level insights. --- ## Other notes **All threads should have a name set** An easy example to follow is https://github.com/nanocurrency/nano-node/pull/2987/files This is so that debuggers/viewers which show threads can pick up the name to make it easier to navigate. It’s been known not to work in the Visual Studio Concurrency visualizer. **(de)serializing** Where possible we try and store primitives in big-endian. As most systems are little-endian this means using `boost::endian::native_to_big` on primitives when serializing and `boost::endian::big_to_native` when deserializing. **Signature checker** This is used by both blocks/votes and creates (total threads / 2) to perform signature verification of set batches; this is the biggest compute resource. Being able to lower this would be very beneficial, such as out of process sig verification and/or via GPU. **peers** Peers are written to disk periodically. This was added in https://github.com/nanocurrency/nano-node/pull/1608 If the node has not been run in a long time (1 week), the peers list is cleared and the preconfigured peers list is used, this was added in https://github.com/nanocurrency/nano-node/pull/2506 - Do not use the `node` object or include `node.hpp` in new core source files unless necessary, instead include the dependencies that it requires. We are still in the process of removing this idiom from other files because it adds circular dependencies, potentially ordering bugs and increases the build time. - Take care not to have nested `tx_begin_write ()`, it is quite easy to forget about this in tests, it will just cause a deadlock. To solve it, limit the scope: - Pass `std::shared_ptr` parameters by reference where possible, https://github.com/nanocurrency/nano-node/pull/3029 - Be cautious with random DB reads, they are much slower than sequential reads. This PR sped up the delegators by a factor of 100 RPC by removing the block_get call needed in the loop. https://github.com/nanocurrency/nano-node/pull/2283 ``` { // Limit scope auto transaction = store->tx_begin_write (); block_put (store.tx_begin_write (), block); } … auto transaction = store->tx_begin_write (); ``` or if it’s a single write can create a temporary just for that use: `block_put (store.tx_begin_write (), block);` Be cautious with callback lifetimes with asynchronous callbacks, such as the worker, alarm and asio. The following issue was because of them: ``` int x = 4; worker.push_back ([&x]() { std::cout << x; // x might not be valid by the time this is called, should have been a copy. }); ``` - Currently (as of V25) using C++20 with Boost 1.81. - There are known exceptions triggered when `consume_future` is called do not be alarmed when seeing this. ## Areas of future improvement - A lot of tests still use legacy blocks, any new ones should use state blocks. - Minimise heap allocation. This can lead to fragmentation which affects long running processes. - `slow_test` is not run as part of CI ## FAQs - Where are blocks added to the ledger? `nano::ledger::process ()` - Where are rpc calls handled? `nano/node/json_handler.cpp` - Where is the genesis block created? `nano::blockstore_partial::init ()` - How to stop the node effectively? `rpc->stop ();` - How to use RocksDB in tests? Set the environment variable: `TEST_USE_ROCKSDB=1` ================================================ FILE: docs/glossary.md ================================================ title: Glossary description: A glossary of common terms used within the nano documentation and network # Glossary #### account Refers to an address (starts with `xrb_` or `nano_` which are interchangeable) that you control the private keys of. An address is a reinterpretation of the 256-bit public key using BASE32 encoding and a checksum. Previously supported `xrb-` or `nano-` prefixes are deprecated. #### active transaction A newly downloaded block to the node which enters into the voting process. #### ad hoc accounts Accounts not derived from a private seed which can be held in the node wallet through the wallet ID. These accounts are only recommended for use with advanced systems. #### announcement rounds A repeating half-second cycle on the node during which votes are collected for active transactions in attempt to reach quorum. #### Block A single Nano transaction. All new transactions (e.g. sends, receives, representative changes, etc) on the Nano Protocol are communicated via state blocks (since node V11). The account's entire state, including the balance after each transaction, is recorded in each block. Transaction amounts are interpreted as the difference in balance between consecutive blocks. Before V11, each transaction type (open, send, receive, change) had its own legacy block type. #### block hash A 64 character, uppercase hexadecimal string (0-9A-F) value representing a unique block on an account. #### Block height A local integer value that represents the order of a block in an account chain. For example, the 15th block in an account would have a block height of 15. Related to (but different from) [confirmation height](#confirmation-height). #### Block Lattice The Block Lattice is a data-structure in which individual accounts control their own blockchain. This allows transactions to be added quickly without conflict and sent to the network for confirmation. #### Blocks Per Second (BPS) The transmission rate of [unconfirmed](#confirmation) blocks (transactions) on the network. #### bootstrap network A sub-network established between peers via Transmission Control Protocol (TCP) for managing bulk transmission of blocks. This is used on initial bootstrapping of peers and when out-of-sync peers attempt to fill large gaps in their ledgers. This is available within all Nano networks (main, beta and test networks). #### bootstrapping During initial sync, the nano\_node requests old transactions to independently verify and populate its local ledger database. Bootstrapping will also occur when the nano\_node becomes out of sync with the network. #### burn When a 'burn' takes place, funds are sent to a specifc address that no one can access. Because no one can ever access funds sent to a burn address, it reduces the [circulating supply](#circulating-supply). #### circulating supply 133,248,297.920938463463374607431768211455 Nano. This is the supply that resulted after [burns](#burn) were made from the [genesis](#genesis) account, landing account and faucet account, following original distribution. Actual circulating supply is lower due to lost keys and sends to burn accounts. The original supply minus any amounts sent to the burn account can be found using the [available_supply](/commands/rpc-protocol/#available_supply) RPC. #### Cementing When a specific node marks a [confirmed](#confirmation) transaction as locally irreversible by setting the [account's](#account) [confirmation height](#confirmation-height) (in the node database) to the now higher [block height](#block-height) of the confirmed transaction. Cementing is a node-level operation. #### Confirmation When a block (transaction) gathers enough votes from the network to pass [quorum](#quorum). Note that confirmed sends are irreversible (i.e. fully-settled), but the receiver must publish a corresponding receive block before they will be able to spend the [receivable](#receivable) funds. Confirmation is a network-level decision. #### Confirmation Height A number stored in the local node database that represents the highest (most recent) [confirmed](#confirmation) block in an account chain. Related to (but different from) [block height](#block-height). #### Confirmations Per Second (CPS) The rate of [confirmed](#confirmation) [blocks](#blocks). #### election #### frontier The most recent block added to the account chain. Also called the head block. Can be either confirmed or unconfirmed. #### genesis The first [account](#account) to be created, containing the maximum amount of Nano to ever exist. From here the funds were sent to other wallets; for distribution or to be [burned](#burn). #### head block See [frontier](#frontier). #### inbound send A block with funds being transferred to an [account](#account) owned by a [wallet](#wallet) on your node. #### legacy blocks Blocks on an account chain before the first v1 block (which is often the v1 epoch block but can be other types). The first v1 block and all subsequent blocks are stateful blocks. #### live network A sub-network established between peers via Transmission Control Protocol (TCP) for communicating newly published blocks, votes and other non-bootstrap related traffic. This is available within all Nano networks (main, beta and test networks). In versions prior to V19, this was done via User Datagram Protocol (UDP). UDP was retained as a fallback for peer connection for versions 19 and 20. In V21 it was deprecated, and in V25 it was fully removed. #### node version The version used to identify a unique release build of the node. Each node version is tied to a single [protocol version](#protocol-version), but they are updated independently. #### online voting weight Also called online stake, it is a trended value. The node samples online representative weights every 5 minutes across a rolling 2 week period. The online voting weight value is the median of those samples. #### peers Nodes connected over the public internet to share Nano network data. #### pending See [receivable](#receivable) #### Private Key See [wallet](#wallet). #### Public Key A public key is derived from a [private key](#private-key) using the ED25519 elliptic curve algorithm. An address is a representation of the public key, see [account](#account) for more info. #### Open Representative Voting (ORV) A consensus mechanism unique to Nano which involves accounts delegating their balance as [voting weight](#voting-weight) to [Representatives](#representative). The Representatives [vote](#voting) themselves on the validity of transactions published to the network using the voting weight delegated to them. These votes are shared with their directly connected peers and they also rebroadcast votes seen from [Principal Representatives](#principal-representative). Votes are tallied and once [quorum](#quorum) is reached on a published block, it is considered confirmed by the network. #### Proof-of-Work (PoW) A Proof-of-Work is a piece of data which satisfies certain requirements and is difficult (costly, time-consuming) to produce, but easy for others to verify. In some systems this data is a central part of the security model used to protect against double-spends and other types of attacks, but with Nano it is only used to increase economic costs of spamming the network. #### Principal Representative A Nano account with >= 0.1% of the [online voting weight](#online-voting-weight) delegated to it. When configured on a node which is voting, the votes it produces will be rebroadcasted by other nodes to who receive them, helping the network reach consensus more quickly. #### protocol version The version used to identify the set of protocol rules nodes are required to follow in order to properly communicate with peers. Nodes running older protocol versions are periodically de-peered on the network to keep communication efficient - see [Active Releases](/releases/node-releases/#active-releases) and [Inactive Releases](/releases/node-releases/#inactive-releases) for the latest versions allowed to peer with one another. #### qualified root The concatenation of the root and previous attributes of a block. For the first block on an account, this would be is the account public key following by 32 zero bytes. For the second or higher block on an account, this would be the previous field repeated twice (root + previous, where root == previous). #### quorum When the delta between the two successive blocks of a root is > 67% of the online voting weight. #### receivable A transaction state where a block sending funds was published and confirmed by the network, but a matching block receiving those funds has not yet been confirmed. #### Representative A Nano account with > 0 voting weight, but < 0.1% of the [online voting weight](#online-voting-weight), delegated to it. Unlike [Principal Representatives](#principal-representative), when configured on a node which is voting, the votes it produces and sends to directly connected peers won't be rebroadcasted by those peers. #### root If the block is the first block on the account, the root is the account public key. Otherwise it is the previous hash included in the block. The root of a block can never be zero. #### seed A 256-bit random value usually represented to the user as a 64 character hexidecimal (0-9 and A-F) value. Private keys are derived from a seed. #### Transactions Per Second (TPS) Historically, TPS was a per-node measurement that represented a node's perception of the rate of transactions on the network ([BPS](#blocks-per-second-bps)). This measurement was found to be inaccurate due to peering and propagation differences between nodes, so [CPS](#confirmations-per-second-cps) is now the preferred term for describing overall Nano network scalability. It's also important to note that while Nano sends do not require a corresponding receive to be [confirmed](#confirmation), a receive block must be confirmed before received funds can be sent again (see [receivable](#receivable)). #### unchecked (blocks) Blocks (transactions) that have been downloaded but not yet processed by the Nano node. The node software downloads all blocks from other nodes as unchecked, processes them and adds to block count, confirms the [frontier](#frontier) blocks for each account, and then marks them as [cemented](#cementing). #### unopened account An account address that does not have a first block on it (which must be a block to receive Nano sent from another account, cannot be a block only changing the Representative). #### unpocketed See [receivable](#receivable). #### vote-by-hash Allows representatives to only include the hash of a block in each vote to save bandwidth. Before vote-by-hash was activated the entire block contents were required. #### voting Each node configured with a [Representative](#representative) votes on every block by appending their Representative signature and a sequence number to the hash. These will be sent out to directly connected peers and if the vote originates from a [Principal Representative](#principal-representative), it will subsequently be rebroadcasted by nodes to their peers. #### voting weight The amount of weight delegated to a [Representative](#representative). #### wallet A wallet is an organizational object in a nano\_node that holds a single seed from which multiple accounts are deterministically derived via a 32-bit unsigned integer index starting at 0. Private keys are derived from the seed and index as follows: (`||` means concatenation; `blake2b` is a [highly optimized cryptographic hash function](/protocol-design/signing-hashing-and-key-derivation/#hashing-algorithm-blake2)) $$ k_{private} = blake2b(\text{seed} || \text{index}) $$ #### WALLET_ID A 256-bit random value name/identifier for a specific wallet in the local nano\_node database. The WALLET\_ID **is not** stored anywhere in the network and is only used in the local nano\_node. Even though a WALLET\_ID looks identical to a seed, do not confuse the WALLET\_ID with a seed; funds cannot be restored with a WALLET\_ID. Do not backup the WALLET\_ID as a means to backup funds. #### work peers Node peers which are configured to generate work for transactions at the originating nodes request. ================================================ FILE: docs/index.md ================================================ --- title: Home description: Explore the design, features, releases and other related resources for the nano protocol and node implementation. hide: - navigation - toc --- # Nano Node and Protocol Documentation Welcome! This documentation is focused on helping developers understand Nano, including setup, maintenance, and building on top of the Nano node. Details of how this documentation has been arranged are below: | Section | Details | Audience | | | | | |**[What is Nano?](what-is-nano/overview.md)**|Take a high-level tour - this is a great place to learn about how Nano is uniquely suited to being a global digital currency.|Everyone| |**[Running a Node](running-a-node/overview.md)**| Set up a Nano node to manage the ledger, create and publish blocks and participate in consensus. | Node operators, developers | |**[Integration Guides](integration-guides/the-basics.md)**| Learn practical concepts, structures and features for building wallets, payment systems and other services on the Nano network. | Developers | |**[Living Whitepaper](living-whitepaper/index.md)**| Dive into the details of why Nano was created & how it's designed. Split into two sub-sections: [Protocol Design](protocol-design/introduction.md) & [Node Implementation](node-implementation/introduction.md). | Developers | |**[Protocol Design](protocol-design/introduction.md)**| Dig deeper into the design and behaviors driving the protocol, including the election process, peering mechanics and more. | Developers | |**[Node Implementation](node-implementation/introduction.md)**| Details of the Nano Foundation managed node implementation of the protocol. | Developers | |**[Core Development](core-development/overview.md)**| Interested in contributing to the core Nano code or protocol? Here's how to get started. | Developers | |**[Commands](commands/rpc-protocol.md)**| Explore an exhaustive list of interaction methods for the node via RPC and CLI. | Node operators, developers | |**[Releases](releases/node-releases.md)**| Review past node releases and get details about the features coming soon in new releases. | Everyone | |**[Glossary](glossary.md)**| Commonly used terms throughout the documentation and Nano ecosystem. | Everyone | **Join the Community** If you are looking for other details about Nano, links to wallets, discussions about the network and more, check out our community: --8<-- "community-links.md" [Change cookie settings](#__consent) ================================================ FILE: docs/integration-guides/advanced.md ================================================ title: Advanced Integration Guide description: More advanced guides to integrating with nano including cold wallets, private key management and more # Advanced Integrations ## Cold Wallets When security of funds is critical, it is a best practice to split your balance between multiple wallets: 1. One or more **hot wallets** to handle daily user deposits/withdraws. 2. One or more **cold wallets** to securely store Nano in an offline environment. !!! warning "Important" A cold wallet manages private keys that have **never** been on a network-enabled computer. This guide extends the concepts covered in [External Private Key Management](/integration-guides/key-management/). It is advised that you read that section before continuing. !!! note Operations done on the hot, online, insecure computer will be prefaced with `(HOT)`. Operations done on the cold, offline, secure computer will be prefaced with `(COLD)`. Both the hot and cold computers need to have the nano\_node software installed. The hot nano\_node needs to be synced with the network; the cold nano\_node by definition should not be synced as it **never connects to the internet**. --- !!! info "Cold Wallet Workflow" The typical work flow for a cold wallet is as follows: 1. `(HOT)` Gather account and transaction data. 1. Transfer this data using an offline method (e.g. via USB stick) to the `(COLD)` secure offline computer. 1. `(COLD)` Verify Head Block hash. 1. `(COLD)` Generate and Sign new transaction data. 1. Transfer the signed transaction back to the `(HOT)` insecure online-computer. 1. `(HOT)` Publish the signed transaction to the Nano Network.
```mermaid sequenceDiagram participant Network participant HOT participant COLD HOT->>Network: Get Data Network->>HOT: Data Response HOT-->>COLD: Offline Transfer COLD-->>COLD: Verify COLD-->>COLD: Generate & Sign COLD-->>HOT: Return Signed HOT->>Network: Publish Signed Note over COLD,HOT: Cold/Hot Wallet transfers are done
offline using USB Stick or similar. ```
--- ### Private Key Management The process for external private key management in a cold wallet is very similar to external private key management for a hot wallet. The primary difference is that all signing commands (and thus information containing your private key) are isolated to a clean computer with no network connection. #### (HOT) Account Information Get account information by the [`account_info`](/commands/rpc-protocol#account_info) RPC Command: ##### Request Example ```bash curl -d '{ "action": "account_info", "representative": "true", "account": "nano_3qb1qckpady6njewfotrdrcgakrgbfh7ytqfrd9r8txsx7d91b9pu6z1ixrg" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "frontier": "DC8EC06D1F32F97BD69BF59E3297563BD23779F72176A4FF553CFF52309C337E", "open_block": "2E1F5AD4BD2C840FD9DC3929ECE9EE6D0B4A8C870E45EDA11048DE91EC409165", "representative_block": "DC8EC06D1F32F97BD69BF59E3297563BD23779F72176A4FF553CFF52309C337E", "balance": "8900000000000000000000000", "modified_timestamp": "1524812177", "block_count": "105", "representative": "nano_3rropjiqfxpmrrkooej4qtmm1pueu36f9ghinpho4esfdor8785a455d16nf" } ``` --- #### (HOT) Balance Validation (Part 1) We should always assume the `(HOT)` computer has been compromised, so cannot trust the balance returned by [`account_info`](/commands/rpc-protocol#account_info). We must obtain the headblock's transaction data and independently confirm the block's hash on our `(COLD)` offline computer. On the `(HOT)` online computer, this information can be obtained by the [`block_info`](/commands/rpc-protocol#block_info) RPC Command. ##### Request Format ```bash curl -d '{ "action": "block_info", "hash": "{{HEADBLOCK}}" }' http://127.0.0.1:7076 ``` ##### Request Example ```bash curl -d '{ "action": "block_info", "hash": "DC8EC06D1F32F97BD69BF59E3297563BD23779F72176A4FF553CFF52309C337E" }' http://127.0.0.1:7076 ``` ###### Success Response ```json { "block_account": "nano_3qb1qckpady6njewfotrdrcgakrgbfh7ytqfrd9r8txsx7d91b9pu6z1ixrg", "amount": "100000000000000000000000", "balance": "8900000000000000000000000", "height": "105", "local_timestamp": "0", "contents": "{\n \"type\": \"state\",\n \"account\": \"nano_3qb1qckpady6njewfotrdrcgakrgbfh7ytqfrd9r8txsx7d91b9pu6z1ixrg\",\n \"previous\": \"829C33C4E1F41F24F50AB6AF8D0893F484E7078F0FA05F8F56CB69223E8EEE77\",\n \"representative\": \"nano_3rropjiqfxpmrrkooej4qtmm1pueu36f9ghinpho4esfdor8785a455d16nf\",\n \"balance\": \"8900000000000000000000000\",\n \"link\": \"616349D5A5EBA49A73324EF29044B65E13644EC182FFC1ACA4371F897EFF22AA\",\n \"link_as_account\": \"nano_1rd5b9ctdtx6mbsm6mqkk34deqimej9e51qzr8pcafrzj7zhyaockuye93sk\",\n \"signature\": \"5058A5A1D371CE367D88DB232D398B33DF15FF95D84206986848F4165FFD9FB009B99D9DC6E90D2A3D96C639C7772497C6D6FFB8A67143AE9BB07DC49EB72401\",\n \"work\": \"5621a5a58ef8964a\"\n }\n" } ``` !!! info Below are a few important points to remember: * Contents are returned as a stringified JSON object. * The type of the block is `"state"`. This guide only covers on how to trustlessly process `"state"` blocks on an offline computer. Transfer the response over to the `(COLD)` computer. --- #### (COLD) Balance Validation (Part 2) On the `(COLD)` computer, we need to verify the block hash using the [`block_hash`](/commands/rpc-protocol#block_hash) RPC Command.. This allows us to create a safe transaction referencing the reported head block's balance. ##### Request Format ```bash curl -d '{ "action": "block_hash", "block": "" }' http://127.0.0.1:7076 ``` ##### Request Example ```bash curl -d '{ "action": "block_hash", "block": "{\n \"type\": \"state\",\n \"account\": \"nano_3qb1qckpady6njewfotrdrcgakrgbfh7ytqfrd9r8txsx7d91b9pu6z1ixrg\",\n \"previous\": \"829C33C4E1F41F24F50AB6AF8D0893F484E7078F0FA05F8F56CB69223E8EEE77\",\n \"representative\": \"nano_3rropjiqfxpmrrkooej4qtmm1pueu36f9ghinpho4esfdor8785a455d16nf\",\n \"balance\": \"8900000000000000000000000\",\n \"link\": \"616349D5A5EBA49A73324EF29044B65E13644EC182FFC1ACA4371F897EFF22AA\",\n \"link_as_account\": \"nano_1rd5b9ctdtx6mbsm6mqkk34deqimej9e51qzr8pcafrzj7zhyaockuye93sk\",\n \"signature\": \"5058A5A1D371CE367D88DB232D398B33DF15FF95D84206986848F4165FFD9FB009B99D9DC6E90D2A3D96C639C7772497C6D6FFB8A67143AE9BB07DC49EB72401\",\n \"work\": \"5621a5a58ef8964a\"\n }\n" }' http://127.0.0.1:7076 ``` ###### Success Response ```json { "hash": "DC8EC06D1F32F97BD69BF59E3297563BD23779F72176A4FF553CFF52309C337E" } ``` Using the responded hash on the `(COLD)` computer guarentees that the transaction we are about to create on the `(COLD)` computer will have a safe, expected outcome. !!! warning "Important" Lets consider the following scenarios where malicious software on the `(HOT)` computer modifies data: * You are creating a send transaction. * Malicious software alters the `balance` field of the head block to be lower than it actually is in an attempt to get you to send too much Nano to the destination address. * This alters the block's hash, but the malicious software could report the honest headblock's hash. By independently computing the headblock's hash on the `(COLD)` computer, the generated transaction would be rejected by the network since the `previous` field references a non-existent block which is certainly not the headblock of your account. Use the responded hash for the `previous` field in your new transaction. When computing final account balance, compute it relative to the `balance` field of the headblock on the `(COLD)` computer. Complete the rest of the [block creation as described in section External Private Key Management](/integration-guides/key-management/#send-transaction). Once the block is created and signed on the `(COLD)` computer, transfer the contents over to the `(HOT)` computer. From the `(HOT)` computer, run the [`process`](/commands/rpc-protocol#process) RPC command to broadcast the signed transaction to the network. --- ## HTTP callback !!! info "WebSockets recommended" The node supports [WebSockets](websockets.md) and these are recommended over the HTTP callbacks whenever possible. Send JSON POST requests with every confirmed block to callback server configured for the node. --8<-- "warning-multiple-confirmation-notifications.md" **Configuration** For details on configuring the HTTP callback within a node, see the [HTTP callback section of Running a Node Configuration](/running-a-node/configuration#http-callback). **Example Callback** ```json { "account": "nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est", "hash": "B785D56473DE6330AC9A2071F19BD44BCAF1DE5C200A826B4BBCC85E588620FB", "block": "{\n \"type\": \"state\",\n \"account\": \"nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est\",\n \"previous\": \"82D68AE43E3E04CBBF9ED150999A347C2ABBE74B38D6E506C18DF7B1994E06C2\",\n \"representative\": \"nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou\",\n \"balance\": \"5256159500000000000000000000000000000\",\n \"link\": \"8B95FEB05496327471F4729F0B0919E1994F9116FD213F44C76F696B7ECD386A\",\n \"link_as_account\": \"nano_34woztr7b7jkgjrzawnz3e6jmresbyajfzb39x4eguubffzetg5c96f3s16p\",\n \"signature\": \"FBE5CC5491B54FE9CD8C48312A7A6D3945835FD97F4526571E9BED50E407A27ED8FB0E4AA0BF67E2831B8DB32A74E686A62BF4EC162E8FBB6E665196135C050B\",\n \"work\": \"824ca671ce7067ac\"\n }\n", "amount": "2500000000000000000000000000000" } ``` Send state blocks have special fields "is_send" & "subtype" ```json { "account": "nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est", "hash": "82D68AE43E3E04CBBF9ED150999A347C2ABBE74B38D6E506C18DF7B1994E06C2", "block": "{\n \"type\": \"state\",\n \"account\": \"nano_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est\",\n \"previous\": \"BE716FE4E21E0DC923ED67543601090A17547474CBA6D6F4B3FD6C113775860F\",\n \"representative\": \"nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou\",\n \"balance\": \"5256157000000000000000000000000000000\",\n \"link\": \"5D1AA8A45F8736519D707FCB375976A7F9AF795091021D7E9C7548D6F45DD8D5\",\n \"link_as_account\": \"nano_1qato4k7z3spc8gq1zyd8xeqfbzsoxwo36a45ozbrxcatut7up8ohyardu1z\",\n \"signature\": \"5AF10D3DDD0E3D7A0EF18670560D194C35A519943150650BBBE0CBDB2A47A1E41817DA69112F996A9898E11F1D79EF51C041BD57C1686B81E7F9DFCCFFBAB000\",\n \"work\": \"13ae0ea3e2af9004\"\n }\n", "amount": "90000000000000000000000000000000000", "is_send": "true", "subtype": "send" } ``` !!! warning It is recommended to fetch the block using the hash provided in the callback rather than trust this data is valid, and check that data instead, since a malicious 3rd party can also make a fake callback request to your endpoint. --- ## Running Nano as a service There are 3 different ways to enable RPC for the node: **In process** * `rpc.enable` = **true** * `rpc.child_process.enable` = **false** (default, V19.0+) **Child process** *V19.0+ only* * `rpc.enable` = **true** * `rpc.child_process.enable` = **true** * `rpc.child_process.rpc_path` = [path to nano_rpc] * `ipc.tcp.enable` = **true** * `ipc.tcp.port` = `process.ipc_port` of `config-rpc.toml` **Out of node process** *V19.0+ only* * `rpc.enable` = **false** * `rpc.child_process.enable` = **false** * `node.ipc.tcp.enable` = **true** * `node.ipc.tcp.port` == `process.ipc_port` of `config-rpc.toml` The choice depends on the setup and security that you want. The easiest way is to use RPC *in_process* according to [configuration](/running-a-node/configuration) **Launch nano_node in test mode** ./nano_node --daemon --network=test **Check if RPC is enabled with curl (use different terminal or session)** ```bash curl -d '{ "action": "block_count" }' http://127.0.0.1:7076 ``` --8<-- "docker-ipv6-tip.md" **To stop node, use** ```bash curl -d '{ "action": "stop" }' http://127.0.0.1:7076 ``` **Launch nano_node as a service with systemd** sudo touch /etc/systemd/system/nano_node.service sudo chmod 664 /etc/systemd/system/nano_node.service sudo nano /etc/systemd/system/nano_node.service **Paste your specific user, group, path settings (example)** [Unit] Description=Nano node service After=network.target [Service] ExecStart=/path_to_nano_node/nano_node --daemon Restart=on-failure User=username Group=groupname [Install] WantedBy=multi-user.target **Start nano_node service** sudo service nano_node start **Enable at startup** sudo systemctl enable nano_node !!! tip To manage node, use [RPC commands](/commands/rpc-protocol) or [CLI](/commands/command-line-interface) ### Known issues **Error initiating bootstrap ... Too many open files** This issue has been seen on some versions of macOS and Linux. The node will detect when the file descriptor limit is considered too low and log a warning similar to: ``` WARNING: The file descriptor limit on this system may be too low (512) and should be increased to at least 16384. ``` To resolve this on Linux increase max open files limit by editing `/etc/security/limits.conf` and adding or updating: ``` * soft nofile 65535 * hard nofile 65535 root soft nofile 65535 root hard nofile 65535 ``` Then restart session & `nano_node` service. Check changes with `ulimit -n`. For macOS the version impacts the steps necessary, but some people had success with the recipe in [https://superuser.com/a/1171028](https://superuser.com/a/1171028). **Increasing max open file descriptors on a Droplet w/Ubuntu** Add `session required pam_limits.so` to these two files: ``` /etc/pam.d/common-session /etc/pam.d/common-session-noninteractive ``` Next, edit `/etc/security/limits.conf` ... and add the following lines: ``` * soft nofile 20000 * hard nofile 30000 root hard nofile 16384 root soft nofile 16384 ``` The last two lines can be skipped if you're not running the node as root. Log out and back in or reboot and see if `ulimit -n` picked it up On some systems, you may need to change systemd files, etc. **Docker** Once the host is updated, pass `--ulimit nofile=16384:16384` ================================================ FILE: docs/integration-guides/block-confirmation-tracking.md ================================================ title: Block Confirmation Tracking description: Guide detailing best practices for block confirmation tracking from the nano node # Block Confirmation Tracking !!! tip "Guide based on node V19.0" The recommendations below are based on node V19.0 and node versions earlier may not have all these options available. All integrations should upgrade their nodes to make use of easier block confirmation procedures detailed here. A primary function of any integration is to track confirmation of blocks on the network and the node provides both proactive notifications and options to request confirmation status on individual blocks. This combination allows building of robust systems for monitoring the status of any blocks of interest. !!! tip "Notifications and fallback requests both recommended" Due to notification methods not guaranteeing delivery of every block confirmed, it is recommended that manual requests for confirmation status be implemented as a fallback option. Both these types of methods are outlined below. ### Receiving notifications of confirmation The recommended method for receiving notifications is via [WebSockets](/integration-guides/websockets) through the confirmation `topic`. This method involves sending a subscribe command to start receiving notifications every time a block is confirmed by the network. It is recommended that the `confirmation_type` filtering options are not used for this purpose, to make it less likely to miss a notification. **Setup process** 1. Update your [WebSocket configuration](/running-a-node/configuration/#nodewebsocket) 1. Connect to the WebSocket at the configured endpoint 1. Send a [subscription request for all confirmations](/integration-guides/websockets#confirmations) including the ack option and validate the subscription request was successful 1. Listen for block confirmation notifications from the WebSocket As confirmations are received they can be parsed and handled as necessary. All operations handling notifications from the node on block confirmation should be idempotent as multiple notifications for the same block hash can occur. --8<-- "warning-multiple-confirmation-notifications.md" ### Requesting block confirmation status In the event confirmation notifications are not received from the WebSocket in an expected timeframe, the [block_info](/commands/rpc-protocol#block_info) RPC can be called on a specific block hash. The `confirmed` field will indicate whether the block has been confirmed. Typical confirmation times on the main network during low-traffic periods are within a few seconds, so a delay of 5 seconds before requesting block information is recommended. If confirmation has still not been seen on the block, the [block_confirm](/commands/rpc-protocol#block_confirm) RPC can be called. This will cause the following: * If the block is confirmed, it will trigger a notification through the WebSocket and HTTP Callbacks, and the block hash will also appear in the [confirmation_history](/commands/rpc-protocol/#confirmation_history) RPC (recommended for debug purposes only). * If the block is not in active elections, it will start an election which should result in confirmation and related notifications. * If the block is already in active elections, it will not have an effect and confirmation should eventually occur along with related notifications. Once [block_confirm](/commands/rpc-protocol#block_confirm) is called, a notification of confirmation through the WebSocket should be expected and if not received, then calling [block_info](/commands/rpc-protocol#block_info) RPC to check for confirmation again can be done. Escalation of potential delays in confirmation can be done after this point in external systems as necessary. ### Account frontier confirmation status For some systems the starting point for checking block status may be the account, such as when a user views their account. The following process is recommended when the account is known and the confirmation status of the frontier block is desired. 1. Call [account_info](/commands/rpc-protocol/#account_info) RPC to get current frontier hash 1. Call [block_info](/commands/rpc-protocol#block_info) for the frontier hash and check if `confirmed` = `true` If the block is not confirmed, you can follow a similar process outlined in the [Requesting block confirmation status](#requesting-block-confirmation-status) section above for requesting block confirmation and re-checking confirmation status before escalating in external systems. ================================================ FILE: docs/integration-guides/build-options.md ================================================ title: Build Options description: Instructions for manually building the Nano node for a variety of operating systems # Build Options --8<-- "warning-only-official-builds-supported.md" ## Official release builds Throughout the development cycle and after releases official builds of the node for Docker, Linux, macOS and Windows are generated and published for test, beta and main networks. === "Main network" --8<-- "current-build-links-main.md" === "Test network" --8<-- "current-build-links-test.md" === "Beta network" --8<-- "current-build-links-beta.md" ## Nano Directory ### Contents --8<-- "directory-contents.md" ### Locations === "Main network" --8<-- "directory-locations-main.md" === "Test network" --8<-- "directory-locations-test.md" === "Beta network" --8<-- "directory-locations-beta.md" ??? tip "Moving directory locations" Some users desire to change the blockchain download location. A solution is available for the no gui nano_node (see https://github.com/nanocurrency/nano-node/issues/79), but no concrete solution is available for the GUI client. However, a workaround can be acheived via the use of symbolic links. Below is a short tutorial for Windows builds: 1. Rename/delete the Nano directory in your `appdata` Local directory (if you haven't run the wallet yet, skip this step). This is necessary because the command to create a symbolic link in windows will fail if the the input directory already exists. 1. Decide on where you want to store the blockchain and create a symbolic link. The command is (in an administrative command-prompt): `mklink /d "C:\Users\\AppData\Local\Nano\" "E:\Some\Other\Directory"`. This command creates a symbolic link for a directory (`/d`) that 'redirects' all requests for files/directories in the `Local\Nano` directory to the `Other\Directory`. This means that a file created in the input directory will actually be in the output directory (on the other disk). 1. Verify it works. Create a file in your Nano directory in your appdata, and you should see it appear in the directory you linked it to (and vice-versa). If you have old wallets or a partially-downloaded blockchain, copy them back into the local directory. Start the wallet. --- ## Requirements & setup --8<-- "warning-unsupported-configuration.md" !!! tip "Alternate Windows setup" Some users have trouble using the command line approach below for getting setup to build on Windows. An alternative setup is available further down for [Windows 10 & Visual Studio 2019](#windows-10-visual-studio-2019). Variations on these instructions with different versions of Windows, Visual Studio, Cmake, etc. may work as well, but may require adjustments. ### Boost (before V25.0) If you are building a version before V25.0, the node build commands further down include bootstrapping Boost, but [pre-built binaries](https://sourceforge.net/projects/boost/files/boost-binaries/) can be used for Windows as well, or you can optionally build from the downloaded source instead as follows: * Download [Boost 1.81+](https://www.boost.org/users/history/version_1_81_0.html) * Extract to \[boost.src\] * From inside [boost.src] run: === "*nix" ```bash ./bootstrap.sh --with-libraries=context,coroutine,filesystem,log,program_options,system,thread ./b2 --prefix=[boost] --build-dir=[boost.build] link=static install ``` === "macOS" ```bash ./bootstrap.sh --with-libraries=context,coroutine,filesystem,log,program_options,system,thread ./b2 --prefix=[boost] --build-dir=[boost.build] link=static install ``` === "Windows" ```bash ./bootstrap.sh --with-libraries=context,coroutine,filesystem,log,program_options,system,thread ./b2 --prefix=[boost] --build-dir=[boost.build] address-model=64 link=static install ``` If using this option, remove `bash util/build_prep/bootstrap_boost.sh -m` from the [build command](#build-commands) below. ### Qt wallet If building the Qt-based `nano_wallet`, first download [Qt 5.15.2+ open source edition](https://www.qt.io/download) and extract to [qt.src]. In [qt.build] execute: === "*nix" ```bash [qt.src]/configure -shared -opensource -nomake examples -nomake tests -confirm-license -prefix [qt] make make install ``` === "macOS" ```bash [qt.src]/configure -shared -opensource -nomake examples -nomake tests -confirm-license -prefix [qt] make make install ``` === "Windows" ```bash [qt.src]/configure -shared -opensource -nomake examples -nomake tests -confirm-license -prefix [qt] nmake nmake install ``` ### Node === "*nix" **Required build tools** * CMake >= 3.8 * Clang >= 11 or GCC >= 11.3 === "Debian" **Version** * Debian 11 Bullseye (requires Clang 11) **Install dependencies** ```bash sudo apt-get update && sudo apt-get upgrade sudo apt-get install git cmake build-essential libc++-dev libc++abi-dev clang clang++11 curl wget sudo apt-get install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools ``` **Qt wallet dependencies** ```bash sudo apt-get install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools ``` **Before build** ```bash export CC=/usr/bin/clang-11 export CXX=/usr/bin/clang++-11 cmake ... ``` === "Ubuntu" **Version** * Ubuntu 22.04 LTS Server * Ubuntu 22.10+ **Install dependencies** ```bash sudo apt-get update && sudo apt-get upgrade sudo apt-get install git cmake g++ curl wget ``` **Qt wallet dependencies** ```bash sudo apt-get install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools ``` === "Rocky Linux" **Version** * Rocky Linux 8 **Install dependencies** ```bash sudo yum check-update sudo yum install git curl wget cmake ``` **Configure repository with modern GCC** ```bash sudo yum install gcc-toolset-12 scl enable gcc-toolset-12 bash ``` === "Arch Linux" **Install dependencies** ```bash pacman -Syu pacman -S base-devel git gcc cmake curl wget ``` === "macOS" **Required build tools** * CMake >= 3.8 * XCode >= 13.1 === "Windows" **Required build tools** * CMake >= 3.8 * NSIS package builder * [Visual Studio 2019 Community](https://my.visualstudio.com/Downloads?q=visual%20studio%202019&wt.mc_id=o~msft~vscom~older-downloads) (or higher edition, if you have a valid license. eg. Professional or Enterprise) * Select **Desktop development with C++** * Select the latest Windows 10 SDK --- ## Build commands ### Node The process below will create a release build of the node for the main network. See [network options](#network-options) below for details on building for the test or beta networks. === "*nix" ```bash git clone --branch V25.0 --recursive https://github.com/nanocurrency/nano-node.git nano_build cd nano_build # Boost is not required for building V25.0 or earlier versions # export BOOST_ROOT=`pwd`/../boost_build # bash util/build_prep/bootstrap_boost.sh -m cmake -G "Unix Makefiles" . make nano_node cp nano_node ../nano_node && cd .. && ./nano_node --diagnostics ``` === "macOS" ```bash git clone --branch V25.0 --recursive https://github.com/nanocurrency/nano-node.git nano_build cd nano_build # Boost is not required for building V25.0 or earlier versions # export BOOST_ROOT=`pwd`/../boost_build # bash util/build_prep/bootstrap_boost.sh -m cmake -G "Unix Makefiles" . make nano_node cp nano_node ../nano_node && cd .. && ./nano_node --diagnostics ``` === "Windows" **Setup** *Download Source* Using git_bash: ```bash git clone --branch V25.0 --recursive https://github.com/nanocurrency/nano-node cd nano-node ``` *Create a `build` directory inside nano-node (makes for easier cleaning of build)* Using git_bash: ```bash mkdir build cd build ``` * **Note:** all subsequent commands should be run within this "build" directory. *Get redistributables* Using Powershell: ```bash Invoke-WebRequest -Uri https://aka.ms/vs/16/release/vc_redist.x64.exe -OutFile .\vc_redist.x64.exe ``` *Generate the build configuration.* Using 64 Native Tools Command Prompt: * Ensure the Qt, Boost (if < V25.0), and Windows SDK paths match your installation. ```bash cmake -DNANO_GUI=ON -DQt5_DIR="C:\Qt\5.15.2\msvc2019_64\lib\cmake\Qt5" -DNANO_SIMD_OPTIMIZATIONS=TRUE -DBoost_COMPILER="-vc141" -DBOOST_ROOT="C:/local/boost_1_70_0" -DBOOST_LIBRARYDIR="C:/local/boost_1_70_0/lib64-msvc-14.1" -G "Visual Studio 16 2019" -DIPHLPAPI_LIBRARY="C:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0/um/x64/iphlpapi.lib" -DWINSOCK2_LIBRARY="C:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0/um/x64/WS2_32.lib" ..\. ``` * If you are building V25.0 or any earlier version, you do not need to specify the Boost library. ```bash cmake -DNANO_GUI=ON -DQt5_DIR="C:\Qt\5.15.2\msvc2019_64\lib\cmake\Qt5" -DNANO_SIMD_OPTIMIZATIONS=TRUE -G "Visual Studio 16 2019" -DIPHLPAPI_LIBRARY="C:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0/um/x64/iphlpapi.lib" -DWINSOCK2_LIBRARY="C:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0/um/x64/WS2_32.lib" ..\. ``` **Build** * Open `nano-node.sln` in Visual Studio * Build the configuration specified in the previous step * Alternative using 64 Native Tools Command Prompt: ```bash cmake --build . --target ALL_BUILD --config %CONFIGURATION% -- /m:%NUMBER_OF_PROCESSORS% ``` **Package up binaries** Using 64 Native Tools Command Prompt: * Replace **%CONFIGURATION%** with the build configuration specified in previous step * Replace **%GENERATOR%** with NSIS (if installed) or ZIP ```bash cpack -G %GENERATOR% -C %CONFIGURATION% ``` ### Qt wallet This is only required when the Qt wallet with GUI is needed. `make nano_wallet` ### RPC server This is only required for when the RPC server is being [run as a child process or outside the node process completely](advanced.md#running-nano-as-a-service). `make nano_rpc` --- ## Windows & Visual Studio An alternative node building process using Windows and Visual Studio can be found below. As this uses GUI options, some of the steps and images may vary if using versions other than those indicated. **Windows** Ensure Windows 10 or Windows 11 is running and the latest updates have been completed, restart Windows. **Visual Studio** Use Visual Studio 2019 or 2022 Visual Studio Community 2019 https://visualstudio.microsoft.com/vs/older-downloads/ Visual Studio Community 2022 https://visualstudio.microsoft.com/vs/community/ Run the installer and make sure to tick `Desktop development with C++` and leave everything else at default. ![Visual Studio 2019 Install](../images/windows-10-build-instructions/visual-studio-install.jpg) **Boost** (Only needed when building versions before V25.0) Install Boost 1.81.0 binaries for msvc 14.2. Use default settings during install https://sourceforge.net/projects/boost/files/boost-binaries/1.81.0/boost_1_81_0-msvc-14.2-64.exe/download **CMake** Install Cmake windows installer, Latest Release https://cmake.org/download/. Check the option `Add cmake to system path for all users` **Git** Download a git tool of choice such as Github desktop https://desktop.github.com/. Clone the nano node develop branch from Github from URL https://github.com/nanocurrency/nano-node to your preferred path, such as: `C:\Users\YourUser\Documents\GitHub\nano-node`. **Restart Windows** **Setting up the solution** Run CMake GUI - Set `Where is the source code` to your preferred path: `C:\Users\YourUser\Documents\GitHub\nano-node` - Create a directory for the destination files such as: `C:\Users\YourUser\Documents\NanoSolution` and set in `Where to build the binaries` - Click `Configure` and select `Visual Studio 16 2019` as the generator for the project - Set any necessary [CMake variables](#cmake-variables) you need, such as the `ACTIVE_NETWORK` but leave `NANO_GUI` off because this requires QT to be installed - Click `Generate` and close Cmake ![CMake Generator](../images/windows-10-build-instructions/cmake-generator.jpg) **Visual studio** - Open project solution file in `C:\Users\YourUser\Documents\NanoSolution\nano-node-beta.sln` - At the top of the screen select the build type and architecture. `Release` and `x64` are recommended settings ![Build type and architecture](../images/windows-10-build-instructions/debug-arch.jpg) - Go to the build menu and select `Build` - When build has finished you will find the compiled files at `C:\Users\YourUser\Documents\NanoBinaries\` **Optional: Setup debugging** You can setup the node to stop at code breakpoints and then inspect values during runtime. Find the nano_node project in the solution explorer on the right pane. Then right click it and select `Set as startup project` ![Set as startup project](../images/windows-10-build-instructions/startup-project.jpg) Right click the nano_node project again and click `Properties` Go to `Configuration Properties` > `Debugging` and set the `Command Arguments` to `--daemon`, click OK ![Set properties](../images/windows-10-build-instructions/set-properties.jpg) From Visual Studio hit `F5` to start debugging. When a breakpoint is hit, Visual Studio will halt the code and take focus. --- ## Additional build details ### Node #### CMake variables Format: `cmake -D VARNAME=VARVALUE` * `BOOST_ROOT=\[boost\]` (`/usr/local/boost/` if bootstrapped) * `CMAKE_BUILD_TYPE=Release` (default) * `ACTIVE_NETWORK=nano_live_network` (default) * `Qt5_DIR=[qt]lib/cmake/Qt5` (to build GUI wallet) * `NANO_GUI=ON` (to build GUI wallet) * `ENABLE_AVX2=ON`, *optional* `PERMUTE_WITH_GATHER=ON`, *optional* `PERMUTE_WITH_SHUFFLES=ON` (for CPU with AXV2 support, choose fastest method for your CPU with https://github.com/sneves/blake2-avx2/) * `CRYPTOPP_CUSTOM=ON` (more conservative building of Crypto++ for wider range of systems) * `NANO_SIMD_OPTIMIZATIONS=OFF` (Enable CPU-specific SIMD optimization: SSE/AVX or NEON, e.g.) * `NANO_SECURE_RPC=ON` (to build node with TLS) * `NANO_WARN_TO_ERR=ON` (*v20.0+* turn compiler warnings into errors on Linux/Mac) * `NANO_TIMED_LOCKS=50` (*v20.0+* when the number of milliseconds a mutex is held is equal or greater than this output a stacktrace, 0 disables.) * `NANO_STACKTRACE_BACKTRACE=ON` (*v20.0+* use a different configuration of Boost backtrace in stacktraces, attempting to display filenames, function names and line numbers. Needs `libbacktrace` to be installed. Some [workarounds](https://www.boost.org/doc/libs/develop/doc/html/stacktrace/configuration_and_build.html#stacktrace.configuration_and_build.f3) may be necessary depending on system and configuration. Use CLI [`--debug_stacktrace`](/commands/command-line-interface#-debug_stacktrace) to get an example output.) * `CI_BUILD=TRUE` (*v20.0+* if enabled, uses environment variable `TRAVIS_TAG` (required) to modify the locally reported node version; example `TRAVIS_TAG="My Nano Node v20"`) * `NANO_ASIO_HANDLER_TRACKING=10` (Output asio diagnostics for any completion handlers which have taken longer than this in milliseconds. For more information see the description of the PR [#2681](https://github.com/nanocurrency/nano-node/pull/2681)) * `NANO_FUZZER_TEST=ON` (Build the fuzz tests, not available on Windows) #### Building a package === "*nix" `cpack -G "TBZ2"` === "macOS" `cpack -G "DragNDrop"` === "Windows" `cpack -G "NSIS"` #### Network options **Main network** The default build network is the main network. No option needs to be specified. **Test Network** * To run a node on the test network, set CMake variable: `-DACTIVE_NETWORK=nano_test_network` * More information can be found on the [Test Network page](../running-a-node/test-network.md) **Beta Network** * To run a node on the beta network, set CMake variable: `-DACTIVE_NETWORK=nano_beta_network` * More information can be found on the [Beta Network page](../running-a-node/beta-network.md) ## Testing A number of tests binaries can be built when the CMake variable `-DNANO_TEST=ON`. With this variable set, `make` will also build test files, and will produce `core_test`, `rpc_test`, `load_test` and `slow_test` binaries, which can be executed: * `core_test` - Tests the majority of protocol, node and network functionality. * `slow_test` - Tests which operate on a large amount of data and may take a while. Not currently tested by CI. * `rpc_test` - Tests all RPC commands * `load_test` - Launches many nodes and RPC servers, checking sending/receiving blocks with simultaneous calls. Use `./load_test --help` to see the available options ### Running Tests To run all tests in a binary just launch it: ```bash ./core_test ``` To check a specific subset of tests, gtest filtering can be used (with optional wildcards): ```bash ./core_test --gtest_filter=confirmation_height.single ./rpc_test --gtest_filter=rpc.* ``` To run tests multiple times: ```bash ./core_test --gtest_repeat=10 ``` If running on a debugger, add the argument `--gtest_break_on_failure` break at the moment a test fails. ### Environment variables to customize tests * `TEST_KEEP_TMPDIRS=1` - Setting this to anything will prevent the tests deleting any files it creates, useful for debugging log files. * `TEST_USE_ROCKSDB=1` - Use the RocksDB ledger backend for the tests instead of LMDB. The tests must be built with [RocksDB](/running-a-node/rocksdb-ledger-backend/#rocksdb-ledger-backend) support. * `TEST_BASE_PORT=26000` - The base port used in tests, the range of ports used in this case would be 26000 - 26199. This is useful if wanting to run multiple tests at once without port conflicts, the default base port used is 24000. * `NANO_DEFAULT_PEER=peering.nano.org` - Setting this adds its variable contents to `preconfigured_peers` from config-node.toml, & allows manually setting initial peering DNS. Setting it to an unresolvable address will prevent the node from contacting peers (after wiping peer table). ### Sanitizers 3 different CMake sanitizer options are supported: `NANO_ASAN_INT`, `NANO_TSAN` and `NANO_ASAN`. They cannot be used in conjunction with each other. #### Thread Sanitizer Use `-DNANO_TSAN=ON` as an extra CMake option. The following environment variable should also be set: `export TSAN_OPTIONS="suppressions=../tsan_suppressions"` `tsan_suppressions` should be a path to the file in the root nano directory. This suppresses many errors relating to the mdb and rocksdb libraries. #### Address Sanitizer Use the CMake variable `-DNANO_ASAN=ON` or `-DNANO_ASAN_INT=ON` before running an executable. ### Valgrind Valgrind can be used to find other issues such as memory leaks. A valgrind suppressions file is provided to remove some warnings. Valgrind can be run as follows (there are many options available): ```bash valgrind --leak-check=full --track-origins=yes --suppressions=../valgrind.supp ./core_test ``` ================================================ FILE: docs/integration-guides/index.md ================================================ title: Get started integrating Nano description: An introduction to the process of starting a Nano integration # Integrating with Nano If you're looking for details about how to integrate your application or service with Nano, you've come to the right place! There are a variety of ways to do integrations and this documentation is focused on situations requiring custom development. If you are looking for a more plug-and-play option to accept Nano payments or donations, we recommend heading to https://nano.org/accept-nano for some simpler options. ## What is needed to integrate? The most basic integration with Nano will require: 1. Access to make RPC calls to a Nano node 1. A method of doing work generation for any blocks created 1. Some form of a wallet to manage the private/public keys for your accounts But before jumping in to setup, there are a few best practices and concepts you should be familiar with first: ### How transactions work and block specs Transactions function differently in Nano compared to other blockchains due to the block lattice design. The [What is Nano?](../what-is-nano/overview.md) page gives a quick explanation on how send and receive transactions are related in Nano. As you get into your integration, it is best to be familiar with the [block specifications](the-basics.md#blocks-specifications) in order to understand how different block subtypes are built and relate to each other. ### Account, Key, Seed and Wallet IDs Knowing how private and public keys are related to seeds and accounts is critical to building a safe and secure integration. With the internal node wallet, there is also a unique wallet ID that adds further security and must be considered if using that wallet for development/testing (see the wallets section below for details). Review the [Account, Key, Seed and Wallet IDs](the-basics.md#account-key-seed-and-wallet-ids) section for some additional details. If you need to generate or manage seeds or mnemonic phrases, see the [seeds](key-management.md#seeds) section for some key information about options as they may differ from other existing projects and standards. ### Units There are two main units used: nano and raw. The ratio is: $$ 1 nano = 10^{30} raw $$ All [QR code](the-basics.md#uri-and-qr-code-standards) setups and RPC calls use raw for the amounts, while any human interaction with units is done at the Nano level. ### Other concepts The above concepts capture a minimum understanding to begin your integration journey, and although additional resources will be called out further in the various guides, don't be afraid to check out other resources throughout the documentation here. --- ## Accessing RPC calls Most integrations send and receive funds by making RPC calls to a Nano node. This requires either access to a public API or running your own node on one of the available networks. Depending on your goals, both are valid approaches with many options and levels of engagement. ### Running your own node Running a node involves installing, configuring and maintaining software on a server, preferably on a stable cloud service for the best performance and uptime. This approach gives you more control at the cost of additional effort. If going this route, we encourage use of the existing test network for initial integrations. Head over to the [Running a node](../running-a-node/overview.md) guide and make your way through the overview and security pages before stepping through the node setup guide. Make sure you have "Test network" selected in all the example commands. !!! info "Production integration node should be non-voting" When moving to production with a node on the main network, we recommend running dedicated, non-voting node for your integration. If you are interested in running a representative node to help further decentralize the network consensus, please setup a separate node for this purpose to ensure both operate as effectively as possible. See the [Voting as a Representative guide](../running-a-node/voting-as-a-representative.md) for further details. ### Public APIs Access to public APIs for the main network is also available via third-party vendors and community members. These are only available for the main network and are great for quickly testing out a proof-of-concept or prototype using small amounts. If using for production applications caution should be taken when evaluating SLAs and uptime in general. - Community supported public APIs list available at [publicnodes.somenano.com](https://publicnodes.somenano.com/) - [NOWNodes](https://nownodes.io/) offers free and paid access to Nano node RPC calls (does not include work generation) with some [service quality standards](https://nownodes.io/service-quality-standards) --- ## Wallet In order to manage private and public keys, accounts, seeds, etc. you will need wallet software. A few potential options are included below, with more user-focused and backend options listed at [nanowallets.guide](https://nanowallets.guide). ### Node internal wallet --8<-- "warning-node-wallet-not-for-prod-use.md" The official binaries, builds and Docker containers for the Nano node published by the Nano Foundation have an internal wallet available for use in development and testing. This is Qt based wallet with both a GUI and related [RPC commands](../commands/rpc-protocol.md#wallet-rpcs). The following features are available via the GUI: - Import wallet and adhoc keys - Export seed (automatically generated on startup) - Change representatives - Send and automatically receive - Automatic work generation for transactions (via CPU by default) - Manual options for block creation, block processing and initiation of bootstrapping - Various advanced options for viewing the ledger, peers, blocks, accounts and statistics This wallet requires running the node, so after getting your [node setup](../running-a-node/node-setup.md) you can follow the [wallet setup guide](/running-a-node/wallet-setup.md) to get started. If building the node yourself, see the Qt wallet notes on the [build options guide](../integration-guides/build-options.md) for how to build the `nano_wallet` binary in addition to the node. ### Pippin This community built wallet is a production-ready, high performance developer wallet that is setup to be a drop-in replacement for the internal node wallet. Built in Python and optimized for fast response times, this is a good option to explore for any integration. With an open source license, you are encouraged to contribute to its development as well. [![Pippin](https://opengraph.githubassets.com/38565027a4d84e26310588fd4712b3cf836745cbe2b4a20ac44590225da01765/appditto/pippin_nano_wallet){width=50%}](https://github.com/appditto/pippin_nano_wallet) ### Nault This community built wallet is more end-user focused with a robust GUI full of various options. It can be useful in development and testing as it supports setting the custom backend to your own node and can function as a basic account/block explorer. If you use this wallet, it also has an open source license so contributions are encouraged. [![Nault](https://repository-images.githubusercontent.com/274627453/14c0c180-bc4a-11ea-82e9-cc23b8b5a718){width=50%}](https://github.com/Nault/Nault) --- ## Additional tools There are plenty of additional libraries and tools worth exploring to help with your integration. Head over the the [Developer Tools page on nano.org](https://nano.org/tools) for a list of commonly used options. Other resources can be explored at the community built [nanolinks.info](https://nanolinks.info/) site. --- ## Next steps If you've made it this far you may have a node running with a wallet setup and have started playing around on the test network. The next steps from here are understanding more about how to handle the various operations most integration require, such as: - Managing public and private keys: see [Key Management](key-management.md), sending and receiving transactions and handling work generation. - Creating and sending transactions: - External wallet (such as Pippin): see [External Management - Creating transactions](key-management.md#creating-transactions) - Internal node wallet: see [Internal Management](key-management.md#internal-management) - Tracking block confirmations: see [Block Confirmation Tracking guide](block-confirmation-tracking.md) - Performing efficient work generation: see [Work Generation guide](work-generation.md) - Optional WebSocket integration: see [WebSockets guide](websockets.md) ================================================ FILE: docs/integration-guides/ipc-integration.md ================================================ title: IPC Integration Guide description: Learn how to integrate with the nano node using the Interprocess Communication (IPC) interface # IPC Integration The node manages communications using an IPC interface with v1 introduced in V18 (see [IPC v1 Details](#ipc-v1-details)) and upgraded to v2 in V21 to include more robust options. This latest version supports the original RPC v1 endpoint and introduces RPC v2 for completion in future release, along with an authentication system for more granular control of permissioned calls. **Configuration** These configuration options are set in the [`config-node.toml` file](../running-a-node/configuration.md#configuration-file-locations). IPC is configured in the `node.ipc.tcp` and `node.ipc.local` sections: ```toml [node.ipc.local] # If enabled, certain unsafe RPCs can be used. Not recommended for production systems. # type:bool #allow_unsafe = false # Enable or disable IPC via local domain socket. # type:bool #enable = false # Timeout for requests. # type:seconds #io_timeout = 15 # Path to the local domain socket. # type:string #path = "/tmp/nano" [node.ipc.tcp] # Enable or disable IPC via TCP server. # type:bool #enable = false # Timeout for requests. # type:seconds #io_timeout = 15 # Server listening port. # type:uint16 #port = 7077 ``` ## IPC request/response format A client must make requests using the following framing format: ``` REQUEST ::= HEADER PAYLOAD HEADER ::= u8('N') ENCODING u8(0) u8(0) ENCODING ::= u8(1) PAYLOAD ::= ``` Four encodings currently exist: * 1: legacy RPC [_since v18.0_] * 2: legacy RPC allowing unsafe operations if node is configured so [_since v19.0_] * 3: flatbuffers [_since v21.0_] * 4: json over flatbuffers [_since v21.0_] The encoding is followed by two reserved zero-bytes. These allow for future extensions, such as versioning and extended headers. Note that the framing format does not include a length field - this is optionally placed in the respective payloads. The reason is that some encodings might want to be "streamy", sending responses in chunks, or end with a sentinel. ``` LEGACY_RPC_PAYLOAD ::= be32(length) JSON request LEGACY_RPC_RESPONSE ::= be32(length) JSON response ``` In short, JSON requests and responses are 32-bit big-endian length-prefixed. ## RPC Gateway The RPC gateway automatically translates between Flatbuffers and JSON messages over HTTP. The request and response is standard JSON. !!! info "Examples require TLS support" The examples below assumes the node is compiled with TLS support. If not, replace https with http. If using TLS with a self-signed certificate, add --insecure to curl commands. ### Making calls without a message envelope A message envelope is a way to tell the server which message type is sent, as well as other information such as credentials. For HTTP clients, it's convenient to send messages _without_ an envelope. They do so by appending the message name (using uppercase CamelCase) to the path: `POST` to https://www.example.com:7076/api/v2/AccountWeight ``` { "account": "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" } ``` The RPC 1.0 `action` field is thus not necessary. The response message is always wrapped in an envelope. JSON clients use the `message` property to access the message: ```json { "time": 1579736914615, "message_type": "AccountWeightResponse", "message": { "voting_weight": "668657804547735335568510480612620716" } } ``` The `message_type` is always Error if a call fails: ```json { "time": 1579737134595, "message_type": "Error", "message": { "code": 3, "message": "Access denied" } } ``` The `time` property is milliseconds since unix epoch when the message was produced on the server. **Relation to the WebSocket response structure** The `message` and `time` properties of the response envelope is exactly the same as in [WebSockets](/integration-guides/websockets). Instead of `message_type`, WebSockets use `topic`. This structure should help simplify clients using both HTTP and WebSockets. **Headers** When calling without an envelope, credentials and a correlation id can still be set using an HTTP header: `curl --header "Nano-Api-Key:mywalletuser" ...` The correlation header is Nano-Correlation-Id, which can be an arbitrary string. This is usually not useful for request/response JSON clients, but may be valuable if responses from RPCs and WebSocket subscriptions are dealt with in a common message handler on the client. ### Making calls with message envelopes If the message name is missing from the path, an envelope will be expected which tells the node about the message type. `POST` to https://www.example.com:7076/api/v2 ```json { "message_type" : "AccountWeight", "message": { "account": "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" } } ``` The above is similar to using the "action" property in RPC 1.0. The main difference is that the message itself is always placed in a "message" property. The envelope allows additional information to be sent, such as credentials: `POST` to https://www.example.com:7076/api/v2 ```json { "credentials": "mywalletuser", "message_type" : "AccountWeight", "message": { "account": "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" } } ``` **Large requests** While somewhat less convenient, the envelope approach is desirable for very large requests, because the node doesn't need to copy the message into an envelope. --- ### Flatbuffers mapping Here's the corresponding [message definitions](https://github.com/nanocurrency/nano-node/blob/master/api/flatbuffers/nanoapi.fbs) for the AccountWeight request and response types: ``` /** Returns the voting weight for the given account */ table AccountWeight { /** A nano_ address */ account: string (required); } /** Response to AccountWeight */ table AccountWeightResponse { /** Voting weight as a decimal number*/ voting_weight: string (required); } ``` --- ### Parsing errors Any problems with the JSON request will be reported with error details: ```json { "message_type": "Error", "message": { "code": 1, "message": "Invalid message format: 3: 2: error: required field is missing: account in AccountWeight" } } ``` --- ## IPC Authorization !!! warning "Work in progress" Permission settings is a work in progress, and their exact definition and defaults will be part of RPC 2.0 in a future node release. With IPC 2.0, the Nano node offers an authorization system. The configuration is done in `config-access.toml` by defining users and optional roles. Permissions are then assigned to these. The node only checks for permissions, never roles. This way, you can freely structure roles and users the way that suits your situation. There is also a default user with limited default permissions, currently only allowed to use the `AccountWeight` and `IsAlive` calls. This is used when no credentials are given. The permissions of the default user can also be changed in the configuration file. Credentials: * IPC clients set the credentials in the message envelope * HTTP(S) clients either use a message envelope or the HTTP Header `Nano-Api-Key` !!! tip "Layered security highly recommended" While permissions enable node operators to pick what functionality to expose to which users, it is still highly recommended that layered security is used. For instance, a wallet backend should expose only required functionality to clients. The backend can then communicate with the node with credentials for additional security. ### Call example ```bash curl --header "Nano-Api-Key:mywalletuser" --insecure -d \ '{ "account": "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3"}' \ https://www.example.com:7076/api/v2/AccountWeight ``` This uses HTTPS (which the node supports through a build option), and the `--insecure` is there because the node's certificate in this example is self-signed. Using an envelope instead of the `AccountWeight` endpoint: ```json { "credentials": "mywalletuser", "message_type" : "AccountWeight", "message": { "account": "nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" } } ``` `POST` the above to https://www.example.com:7076/api/v2 ### Configuration examples For testing IPC without caring about permissions, this gives access to everything: ```toml [[user]] allow = "unrestricted" ``` A more elaborate sample: !!! warning "Work in progress" Permission settings is a work in progress, and their exact definition and defaults will be part of RPC 2.0 in a future node release. ```toml [[role]] id = "service_admin" allow = "api_service_register, api_service_stop" [[user]] # User id's are typically randomly generated strings which # matches the credentials in API requests. id = "user-2bb818ee-6424-4750-8bdb-db23bab7bc57" # Inherit all the permissions from these roles roles = "service_admin" # Add additional permissions for this specific user allow = "wallet_seed_change, api_topic_confirmation" # A list of specific permissions can be denied as well deny = "api_account_weight" [[user]] id = "history-viewer-e3cf8a09-bd74-4ef2-9b84-e14f3db2bb4b" # Add specific permission for this user allow = "api_account_info, api_account_history" # Do not inherit any default permissions. This is useful # for making users with a explicit set of minimum permissions. # The default user can also be set to bare. That way, a node can be # exposed with a limited set of default permissions. bare = true ``` ### Reload config The access file can be reloaded without restarting the node or wallet. For the node: `killall -SIGHUP nano_node` (actual syntax depends on OS) --- ## IPC V1 Details As of v18, the Nano node exposes a low level IPC interface over which multiple future APIs can be marshalled. Currently, the IPC interface supports the legacy RPC JSON format. The HTTP based RPC server is still available. Because the only IPC encoding is currently "legacy RPC", RPC config options like "enable_control" still apply. **Transports** TCP and unix domain sockets are supported. Named pipes and shared memory may be supported in future releases. **IPC clients** A NodeJS client is available at https://github.com/meltingice/nano-ipc-js A Python client is being developed at https://github.com/guilhermelawless/nano-ipc-py ================================================ FILE: docs/integration-guides/key-management.md ================================================ title: Key Management Guide description: Learn best practices for private key management for the nano protocol # Key Management ## Seeds ### Hex Seed Nano's private key(s) have been traditionally derived from a 64 character, uppercase hexadecimal string (0-9A-F). This is currently the more popular form of seed supported by a variety of services and wallets. Additional details available in [The Basics guide](/integration-guides/the-basics/#seed). ### Mnemonic Seed Wallets that provide mnemonic seeds should use the [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) standard word list and methods for generating the seed. When BIP32 master keys are generated from the seed, the HMAC hash key variation "ed25519 seed" should be used due to nano using [ed25519 for the signing algorithm](../protocol-design/signing-hashing-and-key-derivation.md#signing-algorithm-ed25519) (see [SLIP-0010](https://github.com/satoshilabs/slips/blob/master/slip-0010.md)). A non-standard derivation path is used for nano in the [Ledger Nano implementation](https://github.com/LedgerHQ/app-nano), as well as other popular wallets. With a coin-type of `165'` (`0x800000a5`), this is a partial BIP44 path of `m/44'/165'/[address index]`. Only hardened paths are defined. `m/44'/165'/0'` derives the first private key, `m/44'/165'/1'` derives the second private key, and so on. The partial derivation path is hard-coded in the common verification tool by Ian Coleman: https://iancoleman.io/bip39/ . If using this tool to verify, note that regardless of custom settings on the BIP32 or BIP44 tabs for address generation, the resulting addresses in the table at the bottom will follow `m/44'/165'/[address index]`, even if the path in that table indicates otherwise. To see accurate paths in the Derived Addresses table, on the BIP32 tab set the BIP32 Derivation Path to `m/44'/165'`. #### Demo Examples --8<-- "warning-external-libraries.md" https://github.com/roosmaa/nano-bip39-demo https://github.com/joltwallet/bip-mnemonic #### Implementations https://github.com/numsu/nanocurrency-web-js #### Test Vectors **24-Word Mnemonic** ``` edge defense waste choose enrich upon flee junk siren film clown finish luggage leader kid quick brick print evidence swap drill paddle truly occur ``` Given Passphrase: ``` some password ``` Derived BIP39 Seed: ``` 0dc285fde768f7ff29b66ce7252d56ed92fe003b605907f7a4f683c3dc8586d34a914d3c71fc099bb38ee4a59e5b081a3497b7a323e90cc68f67b5837690310c ``` ??? success "Index 0 (`44'/165'/0'`)" Derived Private Key: ``` 3be4fc2ef3f3b7374e6fc4fb6e7bb153f8a2998b3b3dab50853eabe128024143 ``` Derived Public key: ``` 5b65b0e8173ee0802c2c3e6c9080d1a16b06de1176c938a924f58670904e82c4 ``` Derived Address: ``` nano_1pu7p5n3ghq1i1p4rhmek41f5add1uh34xpb94nkbxe8g4a6x1p69emk8y1d ``` ??? success "Index 1 (`44'/165'/1'`)" Derived Private Key: ``` ce7e429e683d652446261c17a96da9ed1897aea96c8046f2b8036f6b05cb1a83 ``` Derived Public key: ``` d9f7762e9cd4e7ed632481308cdb8f54abf0241332c0a8641f61e92e2fb03c12 ``` Derived Address: ``` nano_3phqgrqbso99xojkb1bijmfryo7dy1k38ep1o3k3yrhb7rqu1h1k47yu78gz ``` ??? success "Index 2 (`44'/165'/2'`)" Derived Private Key: ``` 1257df74609b9c6461a3f4e7fd6e3278f2ddcf2562694f2c3aa0515af4f09e38 ``` Derived Public key: ``` a46da51986e25a14d82e32d765dcee69b9eeccd4405411430d91ddb61b717566 ``` Derived Address: ``` nano_3b5fnnerfrkt4me4wepqeqggwtfsxu8fai4n473iu6gxprfq4xd8pk9gh1dg ``` **12-Word Mnemonic** ``` company public remove bread fashion tortoise ahead shrimp onion prefer waste blade ``` No Passphrase Derived BIP39 Seed: ``` 924a962cae64448812be28a514093ebfeeed537d61a44318eb35f902961d21b2fccd30008d33c8d1d5327a34b9b73281c4b27a0a3d004c1c2e85e8dbb234cba8 ``` ??? success "Index 0 (`44'/165'/0'`)" Derived Private Key: ``` 6f73d61ca0b56fcdb79d69d437f102348ad75ca971433eb92b2b003f8c99b48d ``` Derived Public key: ``` 134d938215f68bcaa3a0e574fde325fc4b1abad9bd3d698bfef95633b54ffb57 ``` Derived Address: ``` nano_16tfkg33dxndscjt3sdnzqjkdz4d5cxfmhbxf87zxycp8gtnzytqmcosi3zr ``` ??? success "Index 1 (`44'/165'/1'`)" Derived Private Key: ``` 7e104389811a0967ef574af1f3f423f23cbf7b614be17844f67fb6fd315f9a7e ``` Derived Public key: ``` 71e6caac915affe836c3e822be6a5b3464f40c74bd2e5459d4e74205c6a7c0df ``` Derived Address: ``` nano_1wh8scpb4pqzx1ue9t34qso7pf56yi89bhbgcjexbst41q5chi8zqtwb74ih ``` ??? success "Index 2 (`44'/165'/2'`)" Derived Private Key: ``` 8b7250869207a277ac37068dbe32782c2ab9fc6a5342f0deabbfdfae1285196a ``` Derived Public key: ``` fcebc6554853ed01c242817abf1b5050b887002f8de8f55d00c7c6b5fe01075d ``` Derived Address: ``` nano_3z9drscninzf193671dtqwfo1n7riw14z5hayogi3jy8pqz143txaghe4gbk ``` ## External Management For larger, more robust systems, external private key management is recommended. In this setup, the node operator generates and stores private keys in an external database and only queries the nano\_node to: 1. Find receivable blocks for an account 2. Sign transactions given a private key. More advanced systems may choose to implement signing themselves. 3. Broadcast the signed transaction to the network. !!! note [WALLET\_IDs](/integration-guides/the-basics/#wallet-id) are not used for External Private Key Management since private keys are not stored in the nano\_node. Much of this section builds off of the [Blocks Specifications](/integration-guides/the-basics/#blocks-specifications) documentation. --- ### External accounting systems In order to properly implement accounting systems external to the Nano node the following best practices should be put into place, which ensure only fully confirmed blocks are used for external tracking of credits, debits, etc. !!! tip "Confirmation and idempotency" The details below expand on this, but the two most important pieces of any integration are: 1. **Always confirm blocks** - make sure to follow the block confirmation tracking recommendations so you are always taking action from confirmed blocks 1. **Guarantee idempotency** - whenever you take action from a block confirmation, it must be idempotent so you don't take the action again if the same block hash is seen through confirmation tracking #### Block confirmation procedures Before crediting funds to an account internally based on a deposit on the network, the block sending the funds must be confirmed. This is done by verifying the network has reached quorum on the block. Details of the recommended verification process can be found in the [block confirmation tracking guide](/integration-guides/block-confirmation-tracking). #### Tracking confirmed balances External accounting systems that track balances arriving to the node must track hashes of blocks that have been received in order to guarantee idempotency. Once confirmation of a block has been validated, the block hash should be recorded for the account along with any credits, debits or other related information. Any attempts to credit or debit accounts external to the node should check that no previous conflicting or duplicate activity was already recorded for that same block hash. #### Transaction order and correctness If you are creating a batch of transactions for a single account, which can be a mix of sending and receiving funds, there is no need to wait for the confirmation of blocks **in that account** to create the next transaction. As long as a transaction is valid, it will be confirmed by the network. The transactions that follow it can only be confirmed if the previous transactions are valid. However, you must always wait for the confirmation of **receivable blocks** before creating the corresponding receive transaction, to ensure it will be confirmed. Always wait for confirmation of transactions that you did not create yourself. --- ### Expanding Private Keys A Nano private key is a 256-bit piece of data produced from a cryptographically secure random number generator. !!! danger "Secure Private Keys" * Generating private keys from an insecure source may result in loss of funds. * Be sure to backup any generated private key; if lost the funds in the account will become inaccessible. !!! example "Step 1: Generate secure private key" The bash command below generates a valid private key from a cryptographically secure random number generator. **Always use a cryptographically secure processes for generating any private keys.** ##### Command Example ```bash cat /dev/urandom | tr -dc '0-9A-F' | head -c${1:-64} ``` ##### Success Result ``` 781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3 ``` !!! example "Step 2: Expand private key" From the private key, a public key can be derived, and the public key can be translated into a Nano Address using the [`key_expand`](/commands/rpc-protocol#key_expand) RPC command. ##### Request Example ```bash curl -d '{ "action": "key_expand", "key": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "private": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3", "public": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039", "account": "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx" } ``` --- ### Creating Transactions Using external keys, transactions are generated in two steps: creation and broadcast. This section will be more heavy on example rather than precise specifications. #### Send Transaction !!! example "Step 1: Get Account Info" To send funds to an account, first call the [`account_info`](/commands/rpc-protocol#account_info) RPC command to gather necessary account information to craft your transaction. Setting `"representative": "true"` makes the nano\_node also return the account's representative address, a necessary piece of data for creating a transaction. ##### Request Example ```bash curl -d '{ "action": "account_info", "representative": "true", "account": "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "frontier": "92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D", "open_block": "B292BFFAAE9013BE630B31144EF15205E986940080687C0441CCFE6EAB67FE53", "representative_block": "B292BFFAAE9013BE630B31144EF15205E986940080687C0441CCFE6EAB67FE53", "balance": "4618869000000000000000000000000", "modified_timestamp": "1524626644", "block_count": "4", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou" } ``` !!! example "Step 2: Build `block_create` request" Using details from the `account_info` call response, along with other information, we can create the [`block_create`](/commands/rpc-protocol#block_create) RPC request. For more details on values, see the [Blocks Specifications](/integration-guides/the-basics/#blocks-specifications) documentation. | Field | Value | | | | | `"json_block"` | always `"true"`, so that the output is JSON-formatted | | `"type"` | always the constant `"state"` | | `"previous"` | `"frontier"` from `account_info` response | | `"account"` | `"account"` address used in the `account_info` call above that the block will be created for | | `"representative"` | `"representative"` address returned in the `account_info` call | | `"balance"` | balance of the account in $raw$ **after** this transaction is completed (decreased if sending, increased if receiving). In this example, we will send 1 $nano$ ($10^{30} raw$) to address `nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p`. | | `"link"` | destination address the funds will move between | | `"key"` | account's private key | ##### Request Example ```bash curl -d '{ "action": "block_create", "json_block": "true", "type": "state", "previous": "92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D", "account": "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", "balance": "3618869000000000000000000000000", "link": "nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p", "key": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "hash": "BB569136FA05F8CBF65CEF2EDE368475B289C4477342976556BA4C0DDF216E45", "block": { "type": "state", "account": "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx", "previous": "92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", "balance": "3618869000000000000000000000000", "link": "5C2FBB148E006A8E8BA7A75DD86C9FE00C83F5FFDBFD76EAA09531071436B6AF", "link_as_account": "nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p", "signature": "74BCC59DBA39A1E34A5F75F96D6DE9154E3477AAD7DE30EA563DFCFE501A804228008F98DDF4A15FD35705102785C50EF76732C3A74B0FEC5B0DD67B574A5900", "work": "fbffed7c73b61367" } } ``` !!! info "Additional details" * The option `json_block`, available since V19.0, makes the RPC call return a non-stringified version of the block, which is easier to parse and always recommended. * [`block_create`](/commands/rpc-protocol#block_create) RPC commands generally take longer than other RPC commands because the nano\_node has to generate the [Proof-of-Work](/integration-guides/the-basics/#proof-of-work) for the transaction. The response block data is already properly formatted to include in the [`process`](/commands/rpc-protocol#process) RPC command. * The nano\_node creating and signing this transaction has no concept of what the transaction amount is, nor network state; all the nano\_node knows is that it is creating a block whose previous block on the account chain has hash `92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D` results in the account having a balance of `3618869000000000000000000000000`. * If the account's balance at block hash `92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D` was actually `5618869000000000000000000000000`, then 2 $nano$ would have been sent to `nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p`. !!! question "What if I receive funds on my account and then broadcast the above crafted send? Would this result in me sending excess funds to the recipient?" If you followed this guide, then the answer is "no". When you issued the [`account_info`](/commands/rpc-protocol#account_info) RPC command, you received the account's balance at a specific blockhash on its account-chain. In your crafted transaction, you specify that hash in the `"previous"` field. If funds were signed into your account, the headblock on your account-chain would change. Since your send no longer refers to the headblock on your account-chain when broadcasted, the network would reject your transaction. !!! warning Since only the resulting balance is recorded, the transaction amount is interpreted as the difference in balance from the previous block on the account-chain and the newly created block. For this reason, it is crucial that you obtain the current account balance and headblock in the same atomic [`account_info`](/commands/rpc-protocol#account_info) RPC command. When not following this guide closely, the following **inappropriate sequence of events could lead to erroneous amounts sent** to a recipient. 1. An account's balance, say 5 $nano$, was obtained using the [`account_balance`](/commands/rpc-protocol#account_balance). This balance is valid as of hypothetical **BLOCK_A**. 1. By another process you control, a receive (**BLOCK_B**) was signed and broadcasted into your account-chain (race-condition). * Lets say this `receive` increased the funds on the account chain by 10 $nano$, resulting in a final balance 15 $nano$. 1. The account's frontier block is obtained by the [`accounts_frontiers`](/commands/rpc-protocol#accounts_frontiers) RPC command, returning the hash of **BLOCK_B**. Other transaction metadata is obtained by other RPC commands. 1. With the collected data, if a send transaction was created for 3 $nano$, the final balance would be computed as $5 - 3$, or 2 $nano$. 1. When this is broadcasted, since it is referring to the current head block on the account, **BLOCK_B**, the network would accept it. But, because the balance as of **BLOCK_B** was actually 15 $nano$, this would result in 12 $nano$ being sent to the recipient. For this reason, **only populate transaction data source from a single [`account_info`](/commands/rpc-protocol#account_info) RPC call**. !!! example "Step 3: Broadcast the transaction" As a result of the command above, the nano\_node will return a signed, but not yet broadcasted transaction. Broadcasting of the signed transaction is covered in the [Broadcasting Transactions](#broadcasting-transactions) section. --- #### Receive Transaction !!! info "Manually receiving first block" The very first transaction on an account-chain, which is always a receive, is slightly special and deserves its own section [First Receive Transaction](#first-receive-transaction). !!! example "Step 1: Get Account Info" Receiving funds is very similar to sending funds outlined in the previous section, starting with calling `account_info` to get block details for the account frontier. The scenario below pretends that our previous example of a send transaction was **not** broadcast and confirmed on the network because the starting `account_info` details are identical. ##### Request Example ```bash curl -d '{ "action": "account_info", "representative": "true", "account": "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "frontier": "92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D", "open_block": "B292BFFAAE9013BE630B31144EF15205E986940080687C0441CCFE6EAB67FE53", "representative_block": "B292BFFAAE9013BE630B31144EF15205E986940080687C0441CCFE6EAB67FE53", "balance": "4618869000000000000000000000000", "modified_timestamp": "1524626644", "block_count": "4", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou" } ``` !!! example "Step 2: Build `block_create` request" Using details from the `account_info` call response, along with other information, we can create the [`block_create`](/commands/rpc-protocol#block_create) RPC request. The two differences between the send transaction are the `"link"` and `"balance"` fields. For more details on values, see the [Blocks Specifications](/integration-guides/the-basics/#blocks-specifications) documentation. | Field | Value | | | | | `"json_block"` | always `"true"`, so that the output is JSON-formatted | | `"type"` | always the constant `"state"` | | `"previous"` | `"frontier"` from `account_info` response, or `0` if first block on new account | | `"account"` | `"account"` address used in the `account_info` call above that the block will be created for | | `"representative"` | `"representative"` address returned in the `account_info` call | | `"balance"` | balance of the account in $raw$ **after** this transaction is completed (decreased if sending, increased if receiving). In this example, we will receive 7 $nano$ ($7 \times 10^{30} raw$) based on the assumed details of the block the `"link"` hash refers to (block contents not shown in this example). | | `"link"` | block hash of its paired send transaction, assumed to be a 7 $nano$ send from block hash `CBC911F57B6827649423C92C88C0C56637A4274FF019E77E24D61D12B5338783` | | `"key"` | account's private key | ##### Request Example ```bash curl -d '{ "action": "block_create", "json_block": "true", "type": "state", "previous": "92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D", "account": "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", "balance": "11618869000000000000000000000000", "link": "CBC911F57B6827649423C92C88C0C56637A4274FF019E77E24D61D12B5338783", "key": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "hash": "350D145570578A36D3D5ADE58DC7465F4CAAF257DD55BD93055FF826057E2CDD", "block": { "type": "state", "account": "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx", "previous": "92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", "balance": "11618869000000000000000000000000", "link": "CBC911F57B6827649423C92C88C0C56637A4274FF019E77E24D61D12B5338783", "link_as_account": "nano_3kyb49tqpt39ekc49kbej51ecsjqnimnzw1swxz4boix4ctm93w517umuiw8", "signature": "EEFFE1EFCCC8F2F6F2F1B79B80ABE855939DD9D6341323186494ADEE775DAADB3B6A6A07A85511F2185F6E739C4A54F1454436E22255A542ED879FD04FEED001", "work": "c5cf86de24b24419" } } ``` !!! info "Additional details" Here the follow scenario occurs: * Previous balance was 4618869000000000000000000000000 $raw$ * Increased our balance by 7000000000000000000000000000000 $raw$ * Final balance becomes 11618869000000000000000000000000 $raw$ !!! example "Step 3: Broadcast the transaction" As a result of the command above, the nano\_node will return a signed, but not yet broadcasted transaction. Broadcasting of the signed transaction is covered in the [Broadcasting Transactions](#broadcasting-transactions) section. --- #### First Receive Transaction The first transaction of an account is crafted in a slightly different way. To open an account, you must have sent some funds to it with a [Send Transaction](#send-transaction) from another account. The funds will be **receivable** on the receiving account. If you already know the hash of the receivable transaction, you can skip Step 1. !!! example "Step 1: Obtain the receivable transaction block hash" Start with obtaining a list of receivable transactions in your unopened account. Limit the response to the highest value transaction by using a combination of `sorting` and `count`. ##### Request Example ```bash curl -d '{ "action": "receivable", "account": "nano_1rawdji18mmcu9psd6h87qath4ta7iqfy8i4rqi89sfdwtbcxn57jm9k3q11", "count": "1", "sorting": "true" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "blocks": { "5B2DA492506339C0459867AA1DA1E7EDAAC4344342FAB0848F43B46D248C8E99": "100" } } ``` !!! example "Step 2: Build `block_create` request" Using the block hash and raw transaction amount from the `receivable` call response, along with other information, we can create the [`block_create`](/commands/rpc-protocol#block_create) RPC request. The only difference between the normal receive transactions is the `"previous"` field. For more details on values, see the [Blocks Specifications](/integration-guides/the-basics/#blocks-specifications) documentation. | Field | Value | | | | | `"json_block"` | always `"true"`, so that the output is JSON-formatted | | `"type"` | always the constant `"state"` | | `"previous"` | always the constant "0" as this request is for the first block of the account | | `"account"` | `"account"` address used in the `account_info` call above that the block will be created for | | `"representative"` | `"representative"` the account address to use as [representative](/integration-guides/the-basics#representatives) for your account. Choose a reliable, trustworthy representative. | | `"balance"` | balance of the account in $raw$ **after** this transaction is completed. In this example, we will receive $100\ raw$, based on the assumed details from the `"receivable"` response above. | | `"link"` | block hash of its paired send transaction, in this case assumed to be the block `5B2DA492506339C0459867AA1DA1E7EDAAC4344342FAB0848F43B46D248C8E99` | | `"key"` | account's private key | ##### Request Example ```bash curl -d '{ "action": "block_create", "json_block": "true", "type": "state", "previous": "0", "account": "nano_1rawdji18mmcu9psd6h87qath4ta7iqfy8i4rqi89sfdwtbcxn57jm9k3q11", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", "balance": "100", "link": "5B2DA492506339C0459867AA1DA1E7EDAAC4344342FAB0848F43B46D248C8E99", "key": "0ED82E6990A16E7AD2375AB5D54BEAABF6C676D09BEC74D9295FCAE35439F694" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "hash": "ED3BE5340CC9D62964B5A5F84375A06078CBEDC45FB5FA2926985D6E27D803BB", "block": { "type": "state", "account": "nano_1rawdji18mmcu9psd6h87qath4ta7iqfy8i4rqi89sfdwtbcxn57jm9k3q11", "previous": "0000000000000000000000000000000000000000000000000000000000000000", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", "balance": "100", "link": "5B2DA492506339C0459867AA1DA1E7EDAAC4344342FAB0848F43B46D248C8E99", "link_as_account": "nano_1psfnkb71rssr34sisxc5piyhufcrit68iqtp44ayixnfnkas5nsiuy58za7", "signature": "903991714A55954D15C91DB75CAE2FBF1DD1A2D6DA5524AA2870F76B50A8FE8B4E3FBB53E46B9E82638104AAB3CFA71CFC36B7D676B3D6CAE84725D04E4C360F", "work": "08d09dc3405d9441" } } ``` !!! example "Step 3: Broadcast the transaction" As a result of the command above, the nano\_node will return a signed, but not yet broadcasted transaction. Broadcasting of the signed transaction is covered in the [Broadcasting Transactions](#broadcasting-transactions) section. --- ### Broadcasting Transactions !!! example "Broadcast using [`process`](/commands/rpc-protocol/#process) RPC command" Common to all of these transactions is the need to broadcast the completed block to the network. This is achieved by the [`process`](/commands/rpc-protocol#process) RPC command which accepts the block as stringified JSON data. If you followed the previous examples, you used the option `json_block` for RPC [`block_create`](/commands/rpc-protocol#block_create), which allows you use the non-stringified version, as long as you include the same option in this RPC call. A successful broadcast will return the broadcasted block's hash. --8<-- "warning-process-sub-type-recommended.md" ##### Request Example ```bash curl -d '{ "action": "process", "json_block": "true", "subtype": "open", "block": { "type": "state", "account": "nano_1rawdji18mmcu9psd6h87qath4ta7iqfy8i4rqi89sfdwtbcxn57jm9k3q11", "previous": "0000000000000000000000000000000000000000000000000000000000000000", "representative": "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", "balance": "100", "link": "5B2DA492506339C0459867AA1DA1E7EDAAC4344342FAB0848F43B46D248C8E99", "link_as_account": "nano_1psfnkb71rssr34sisxc5piyhufcrit68iqtp44ayixnfnkas5nsiuy58za7", "signature": "903991714A55954D15C91DB75CAE2FBF1DD1A2D6DA5524AA2870F76B50A8FE8B4E3FBB53E46B9E82638104AAB3CFA71CFC36B7D676B3D6CAE84725D04E4C360F", "work": "08d09dc3405d9441" } }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "hash": "42A723D2B60462BF7C9A003FE9A70057D3A6355CA5F1D0A57581000000000000" } ``` !!! tip "Block watching and re-work" Since V20.0, blocks processed using [`process`](/commands/rpc-protocol/#process) are placed under observation by the node for re-broadcasting and re-generation of work under certain conditions. If you wish to disable this feature, add `"watch_work": "false"` to the process RPC command. * If a block is not confirmed within a certain amount of time (configuration option `work_watcher_period`, default 5 seconds), an **automatic re-generation of a higher difficulty proof-of-work** may take place. * Re-generation only takes place when the network is unable to confirm transactions quickly (commonly referred as the network being *saturated*) and the higher difficulty proof-of-work is used to help prioritize the block higher in the processing queue of other nodes. * Configuration option `max_work_generate_multiplier` can be used to limit how much effort should be spent in re-generating the proof-of-work. * The target proof-of-work difficulty threshold is obtained internally as the minimum between [`active_difficulty`](/commands/rpc-protocol/#active_difficulty) and `max_work_generate_multiplier` (converted to difficulty). * With a new, [higher difficulty](/integration-guides/the-basics/#difficulty-multiplier) proof-of-work, the block will get higher confirmation priority across the network. !!! info "When a transaction does not confirm" * If a transaction is taking too long to confirm, you may call the [`process`](/commands/rpc-protocol#process) RPC command with the same block data with no risk. * If for some reason a transaction fails to properly broadcast, subsequent transactions on the account-chain after that transaction will not be accepted by the network since the `"previous"` field in the transaction data refers to a non-existant block. * If this situation occurs, rebroadcasting the missing transaction(s) will make the subsequent blocks valid in the network's ledger. --- !!! example "Rebroadcasting blocks for an account-chain" The following command rebroadcasts all hashes on an account-chain **starting** at block hash provided: ##### Request Example ```bash curl -d '{ "action": "republish", "hash": "48006BF3146C18CAD3A53A957BF64EF7C57820B21FCCE373FA637559DA260358" }' http://127.0.0.1:7076 ``` --- ## Internal Management The nano\_node software has a built-in private-key manager that is suitable for smaller operations (<1000 accounts). [External Key Management](/integration-guides/key-management/#external-management) allows more powerful and robust systems at the cost of additional complexity. External Key Management is recommended for larger operations. ### Creating a Wallet To create an account, you first must create a wallet to hold the seed that will subsequently create the account. ##### Request Example ```bash curl -d '{ "action": "wallet_create" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "wallet": "E3E67B1B3FFA46F606240F1D0B964873D42E9C6D0B7A0BF376A2E128541CC446" } ``` The nano\_node responds with the WALLET\_ID. If you lose your WALLET\_ID, it can only be recovered via a CLI command. To reiterate, the **WALLET_ID is not a seed**. The seed can be extracted for backup in [Backing Up Seed](#backing-up-seed). Many of the RPC commands in this guide require the WALLET\_ID. --- ### Recovering WALLET_ID If you lose your WALLET\_ID, you can print out all your WALLET\_IDs and public addresses in those wallets with the [`--wallet_list`](/commands/command-line-interface#-wallet_list) CLI command as follows: ##### Command Format ```bash docker exec ${NANO_NAME} nano_node --wallet_list ``` ##### Success Response ```yaml Wallet_ID: E3E67B1B3FFA46F606240F1D0B964873D42E9C6D0B7A0BF376A2E128541CC446 nano_16odwi933gpzmkgdcy9tt5zef5ka3jcfubc97fwypsokg7sji4mb9n6qtbme Wallet_ID: DB0711484E35A4C75230D898853A86BFAFE9F87FCE99C83A4C2668C39607DD4B ``` In this example, the nano\_node's internal private-key management system contains two wallets, each with a different 256-bit seed. The first wallet has a single account and the second wallet has zero accounts. Account creation will be covered later. --- ### Backing Up Seed The following command will print the seed for a given wallet to stdout. Replace `${WALLET_ID}` with the WALLET\_ID that you would like to display the seed of. ##### Command Format ```bash docker exec ${NANO_NAME:-nano_node_1} nano_node --wallet_decrypt_unsafe --wallet ${WALLET_ID} ``` ##### Success Response ```yaml Seed: D56143E7561D71C1AF4D563C6AF79EECE93E82479818AD8ED88BED1AAE8BE4E5 Pub: nano_16odwi933gpzmkgdcy9tt5zef5ka3jcfubc97fwypsokg7sji4mb9n6qtbme Prv: 1F6FEB5D1E05C10B904E1112F430C3FA93ACC7067206B63AD155199501794E3E ``` !!! info The nano\_node responds with three pieces of information: 1. The seed of the wallet (back this up). 1. The pairing public address 1. The private key (deterministically derived from seed) of accounts within the wallet. Additional notes: * If you change the seed in a wallet, future created accounts will be derived from that seed. * Changing seeds on a wallet that already has accounts can cause accidental loss of funds from improper seed or private key backup. * It is recommended to always create a new wallet when restoring a seed. ##### Error Response ``` Wallet doesn't exist ``` !!! warning If anyone has access to the seed, they can freely access funds, so keep this very secure. Since the above command prints to stdout, it is recommended to wipe stdout afterwards using: ```bash clear && printf '\e[3J' ``` --- ### Restoring/Changing Seed !!! warning Only change the seed of a wallet that contains no accounts. Changing the seed of a wallet that already has accounts may lead to a false sense of security: accounts are generated by the seed that is currently in the wallet. Generating accounts, then switching the seed and backing up the new seed does **not** backup the previously generated accounts. ##### Request Format ```bash curl -d '{ "action": "wallet_change_seed", "wallet": "", "seed": "" }' http://127.0.0.1:7076 ``` ##### Request Example ```bash curl -d '{ "action":"wallet_change_seed", "wallet":"DB0711484E35A4C75230D898853A86BFAFE9F87FCE99C83A4C2668C39607DD4B", "seed":"D56143E7561D71C1AF4D563C6AF79EECE93E82479818AD8ED88BED1AAE8BE4E5" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "success": "" } ``` ##### Error Response Response if the wallet_id isn't found in nano\_node: ```json { "error": "Wallet not found" } ``` Response if the seed field contains non-hexidecimal values or is too long: ```json { "error": "Bad seed" } ``` !!! warning If the hexidecimal seed represents less than 256 bits, the seed will be 0-padded on the left to become 256 bits. --- ### Account Create After creating a wallet, it's corresponding WALLET\_ID, and **backing up the seed (not the wallet\_id)**, the wallet can be populated with accounts. To create a new account in a wallet use the [`account_create`](/commands/rpc-protocol#account_create) RPC command: ##### Request Format ```bash curl -d '{ "action": "account_create", "wallet": "" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "account": "nano_16odwi933gpzmkgdcy9tt5zef5ka3jcfubc97fwypsokg7sji4mb9n6qtbme" } ``` ##### Error Response ```json { "error": "Wallet not found" } ``` --- ### Bulk Account Create To generate many accounts in bulk, it is more efficient to create them all at once using the [`accounts_create`](/commands/rpc-protocol#accounts_create) RPC command: ##### Request Format ```bash curl -d '{ "action": "accounts_create", "wallet": "", "count": "" }' http://127.0.0.1:7076 ``` ##### Request Example ```bash curl -d '{ "action": "accounts_create", "wallet": "DB0711484E35A4C75230D898853A86BFAFE9F87FCE99C83A4C2668C39607DD4B", "count":"5" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "accounts": [ "nano_35kgi43t5hgi64715qnppmz1yb6re1igfcrkfx4ppirkqpfmecnpd1mdmafu", "nano_3t13y6b7h93yn9hehn8p6yqx1yqzrxxs33drhzep8huhymwxamn15pba75oj", "nano_11exxzfoosai96w7gnrjrn7m6i8bodch37ib8jgxsm5k96na6e1wda8np881", "nano_3xbsso8pkemwatwdnkcyn1bfcmrb8dpcg3pit9zqxj9mkxa6ifiankff6m9x", "nano_1q5gpy46moe1csj8md8oq3x57sxqmwskk8mmr7c63q1yebnjcsxg1yib19kn" ] } ``` --- ### Receiving Funds As long as the nano\_node is synced and the node wallet is unlocked (node wallet locking is not covered in this guide), nano\_node automatically creates and signs receive transactions for all accounts in the wallet's internal private-key management system. !!! tip In the event that a receive is not automatically generated, it can be manually generated using the [`receive`](/commands/rpc-protocol#receive) RPC command. #### Semi-Manual Receiving Funds If the nano\_node does not automatically sign in a receivable transaction, transactions can be manually signed in. The easiest way is to explicitly command the nano\_node to check all of the accounts in all of its wallets for receivable blocks. ##### Request Example ```bash curl -d '{ "action": "search_receivable_all" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "success": "" } ``` !!! note As the number of accounts in a nano\_node grows, this command becomes increasingly computationally expensive. --- ### Sending funds The [`send`](/commands/rpc-protocol#send) RPC command sends funds from an account in the specified wallet to a destination address. ##### Request Format ```bash curl -d '{ "action": "send", "wallet": "", "source": "", "destination": "", "amount": "1000000", "id": "7081e2b8fec9146e" }' http://127.0.0.1:7076 ``` | Field | Description | | | | | wallet | WALLET_ID containing the source address | | source | Address you control starting with "nano_" | | destination | Destination address starting with "nano_" | | amount | Amount to send in raw | | id | Any string | --- !!! warning "Important" The `"id"` field is a safety mechanism that prevents issuing a transaction multiple times by repeating the RPC command. * If a transaction is successful, any subsequent [`send`](/commands/rpc-protocol#send) RPC commands with the same identifier will be ignored by the nano\_node. * If the request times out, then the send may or may not have gone through. * Most exchange "double withdraw" issues are caused by naive error-handling routines which re-issue the send request without the `"id"` parameter. * The `"id"` field is local to your nano\_node instance and does not offer protection when sent to different instances of nano\_node that manage the same seed. * As previously mentioned, having a seed loaded in multiple online nano_node is strongly discouraged. * If managing more than 1000 accounts, building a separate system for managing keys and accounts externally is recommended --- Below is a sample command to send 1 $nano$ from `nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000` to `nano_16odwi933gpzmkgdcy9tt5zef5ka3jcfubc97fwypsokg7sji4mb9n6qtbme`. ##### Request Example ```bash curl -d '{ "action": "send", "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", "source": "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", "destination": "nano_16odwi933gpzmkgdcy9tt5zef5ka3jcfubc97fwypsokg7sji4mb9n6qtbme", "amount": "1000000000000000000000000000000", "id": "7081e2b8fec9146e" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "block": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" } ``` On success, the nano\_node returns the hash of the transaction's block. --- ### Republishing Transactions It may take a few seconds for the transaction to appear on the Nano Network. If the transaction fails to appear, you may call the [`republish`](/commands/rpc-protocol#republish) RPC command with the oldest missing transaction's hash. Account-chains must be **continuous and unbroken**. If for some reason a transaction fails to properly broadcast, subsequent transactions on the account-chain will not be accepted by the network since the `"previous"` field in the transaction data refers to a block unknown to to other nodes on the network. !!! tip Republishing the missing transaction(s) will make all the subsequent blocks valid in the network's ledger. Republishing does not create new transactions. The following command rebroadcasts all hashes on an acccount-chain starting at block with hash `${BLOCK_HASH}`: ##### Request Example ```bash curl -d '{ "action": "republish", "hash": "AF9C1D46AAE66CC8F827904ED02D4B3D95AA98B1FF058352BA6B670BEFD40231" }' http://127.0.0.1:7076 ``` ##### Success Response ```json { "success": "", "blocks": [ "AF9C1D46AAE66CC8F827904ED02D4B3D95AA98B1FF058352BA6B670BEFD40231", "C9A111580A21F3E63F2283DAF6450D5178BFAC2A6C38E09B76EEA9CE37EC9CE0" ] } ``` On success, the nano\_node returns the hashes of all republished blocks. ================================================ FILE: docs/integration-guides/the-basics.md ================================================ title: Integration Basics Guide description: Understand some of the core details of the nano protocol including block specifications, accounts, keys, and more # 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 Receive | Receive funds from a given "Send" transaction 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 receivable 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)](/what-is-nano/overview/#representatives-and-voting) 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](#change) (sends no funds), which most wallets support. --- ## 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. !!! danger "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 concatenation and `i` is a 32-bit big-endian 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. It should be noted that Nano reference wallet is using described Blake2b private keys derivation path. However some implementations can use BIP44 deterministic wallets and [mnemonic seed](/integration-guides/key-management/#mnemonic-seed) producing different private keys for given seed and indices. Additionally 24-word mnemonic can be derived from a Nano 64 length hex seed as entropy with clear notice for users that this is not BIP44 seed/entropy. **Code samples** === "Python" Generates a deterministic key: ```python import hashlib seed = b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" # "0000000000000000000000000000000000000000000000000000000000000001" index = 0x00000001.to_bytes(4, 'big') # 1 blake2b_state = hashlib.blake2b(digest_size=32) blake2b_state.update(seed+index) # where `+` means concatenation, not sum: https://docs.python.org/3/library/hashlib.html#hashlib.hash.update # code line above is equal to `blake2b_state.update(seed); blake2b_state.update(index)` PrivK = blake2b_state.digest() print(blake2b_state.hexdigest().upper()) # "1495F2D49159CC2EAAAA97EBB42346418E1268AFF16D7FCA90E6BAD6D0965520" ``` === "Bitcoinjs" Mnemonic words for Blake2b Nano seed using [Bitcoinjs](https://github.com/bitcoinjs/bip39): ```js const bip39 = require('bip39') const mnemonic = bip39.entropyToMnemonic('0000000000000000000000000000000000000000000000000000000000000001') // => abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon diesel bip39.mnemonicToEntropy(mnemonic) // => '0000000000000000000000000000000000000000000000000000000000000001' ``` ### 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-512 as the hash function (instead of SHA-512). Usually account public keys will not be passed around in this form, rather the below address is used. ### Account public address 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 Blake2b-40 checksum of the account public key to aid in discovering typos, also encoded with the same base32 scheme (5 bytes). 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. !!! question "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 $$ !!! warning "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](/protocol-design/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. !!! warning "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](#units)) | | link | (see link table below) | 32 bytes | Multipurpose field - see link table below | | signature | 128 hex-char string | 64 bytes | ED25519+Blake2b 512-bit signature | | work | 16 hex-char string | 8 bytes | [Proof of Work](../glossary.md#proof-of-work-pow) Nonce | Depending on the action each transaction intends to perform, the `"link"` field will have a different value: | Action | RPC Format | Description | | | | | | Change | decimal string | Must be "0" | | Send | 64 hex-char string | Public key for destination account | | Receive | 64 hex-char string | Pairing block's hash (block sending funds) | If using the [block_create](/commands/rpc-protocol#block_create) RPC command the optional fields `"source"` (with the block hash to be received) and `"destination"` (with the target `nano_` address) fields can be used instead of directly defining the `"link"` field. !!! 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) 6. link (32-Bytes) !!! question "What is the preamble?" As of v15.0 **the Nano node only supports state blocks**, but prior versions used block types to distinguish different kinds of transactions. The preamble is a relic of those blocks, and now it is a constant value since all blocks are the same `state` type. The digital signing algorithm (which internally applies another Blake2b hashing) is applied on the resulting digest. !!! warning "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. ### Creating Blocks For details on how to create individual blocks for sending from, receiving to, opening or changing representatives for an account, please see the [Creating Transactions](/integration-guides/key-management/#creating-transactions) section. --- ## URI and QR Code Standards Note: `amount` values should always be in RAW. Note: Please use `nano://` for deep links ### Send to an address nano:nano_[?][amount=][&][label=