Rust-Core rs: Nimiq — Rust implementation of node

Nimiq Core implementation in Rust (core-rs)

nimiq

Rust implementation of the Nimiq Blockchain Core

Nimiq is a frictionless payment protocol for the web.

This repository is currently in release-candidate phase. If you need a proven stable release to run in a production environment, please use the JavaScript implementation instead. Only use this if you can tolerate bugs and want to help with testing the Nimiq Rust implementation.

The Nimiq Rust client comes without wallet and can currently not be used to send transactions. As a back-bone node it is more performant than the JavaScript implementation though.

Table of Contents

Background

Install

Besides Rust nightly itself, the following packages are required to be able to compile this source code:

  • gcc
  • pkg-config
  • libssl-dev (in Debian/Ubuntu) or openssl-devel (in Fedora/Red Hat)

From crates.io

To download from crates.io, compile and install the client:

cargo +nightly install nimiq-client

The binary will be installed in your Cargo directory, which is usually at $HOME/.cargo/bin, and should be available in your $PATH.

From Git

Compiling the project is achieved through cargo:

git clone https://github.com/nimiq/core-rs
cd core-rs
cargo +nightly build

Note that this will build it in debug mode, which is not as performant. To get the most speed out of the client, build it in release mode:

cargo +nightly build --release

If you want to install the client onto your system (into $HOME/.cargo/bin), run:

cargo +nightly install --path client/

Alternatively you can install directly from git:

cargo +nightly install --git https://github.com/nimiq/core-rs.git

After installing the client you can use it as if you had downloaded it from crates.io.

Usage

After installation, you can run the client directly, like this:

nimiq-client

Configuration

By default the client will look for a configuration file in $HOME/.nimiq/client.config. You need to create this file yourself:

nimiq-client                                                   # Run the client. This will create the example config file.
cp $HOME/.nimiq/client.example.toml $HOME/.nimiq/client.toml   # Create your config from the example.
nano $HOME/.nimiq/client.toml                                  # Edit the config. Explanations are included in the file.

You can also specify your own configuration file:

nimiq-client -c path/to/client.toml

Take a look at client/client.example.toml for all the configuration options.

Contributing

If you'd like to contribute to the development of Nimiq please follow our Code of Conduct and Contributing Guidelines.

Small note: If editing the README, please conform to the standard-readme specification.

License

This project is under the Apache License 2.0.

Comments

  • Argon2 native CPU module selection
    Argon2 native CPU module selection

    Dec 14, 2018

    Like in https://github.com/nimiq-network/core/pull/440 of core-js, I think it's useful to have a native module selection for packaged builds, and I'd like to take on this.

    My idea is to statically link the different versions of libargon2 into the same binary, giving the function names a suffix of the target via a C macro. We'd then have argon2d_hash_raw_avx2, argon2d_hash_raw_sse2 and so on built from the same source.

    Like in https://github.com/nimiq-network/core/pull/456, a $PACKAGING environment variable should be introduced, that will trigger a native build if it's false instead of the avx2, sse2… versions.

    On startup, Rust then would set up function pointers to the native module and use rust-cupid to initialize them with the correct implementations.

    I also filed https://github.com/nimiq/core-rs/pull/1 to reduce the number of functions so the module is easier to work with.

    The alternative would be to dynamically load the implementations like the .node libraries in Node.js but that'd be more difficult and inconvenient, in my opinion.

    enhancement crate:libargon2-sys 
    Reply
  • WebAssembly build target
    WebAssembly build target

    Feb 8, 2019

    Question or Feature Request

    Nimiq is the web-based currency. Why not compile the Rust core to Wasm then?

    Useful resources:

    • https://www.rust-lang.org/what/wasm
    • https://rustwasm.github.io/book/
    • https://webassembly.org/
    • https://developer.mozilla.org/en-US/docs/WebAssembly

    I'll do some research on what's required to compile to the new target.

    enhancement target:web-assembly 
    Reply
  • Checklist for 1.0 release
    Checklist for 1.0 release

    Sep 5, 2019

    This is the checklist of pending items/bugs/tasks that need to be addressed in order to release a 1.0 version:

    • [x] Looking into networking layer improvements in albatross and backporting anything that makes sense
    • [x] Make sure TLS termination works properly with our current mainnet infrastructure setup
    • [x] Backport the updated GitLab CI config from albatross
    • [x] Fix bug where incomplete AccountsProof are sent
    • [x] Code cleanup (warnings during compilation, etc.)
    • [ ] Support https for the metrics server
    • [ ] Make sure the name of metrics in Rust match those in JavaScript
    Reply
  • Support loading PEM formatted certificates directly
    Support loading PEM formatted certificates directly

    Nov 8, 2019

    Currently, we only support loading certificates (and private key) from a PKCS#12 file, but most certificate providers (including Let's Encrypt) issue their certificates in separate non-encrypted PEM formatted files, so it makes sense for us to support loading certificates this way too.

    Reply
  • Backport checklist from Albatross
    Backport checklist from Albatross

    Nov 10, 2019

    This issue is a meta issue with the information of all the features that should/could be backported from Albatross after the stable release:

    • [ ] Client API support
    • [ ] Build genesis block data from config file
    • [ ] Move paths of dependencies to root crate
    Reply
  • Build fails on ARM-based system
    Build fails on ARM-based system

    Nov 16, 2019

    New issue checklist

    General information

    • Library version(s): 0.2
    • Browser version(s): N/A
    • Devices/Simulators/Machine affected: Linux aarch64
    • Reproducible in the testnet? (Yes/No): N/A
    • Related issues:

    Bug report

    Expected behavior

    Build doesn't fail

    Actual behavior

    Build fails

    Steps to reproduce

    cargo +nightly build --release

    Crash log? Screenshots? Videos? Sample project?

    error: failed to run custom build command for `libargon2-sys v0.2.0 (/home/ubuntu/nimiq/libargon2-sys)`
    
    Caused by:
      process didn't exit successfully: `/home/ubuntu/nimiq/target/release/build/libargon2-sys-66ab85cb0894a5ef/build-script-build` (exit code: 1)
    --- stdout
    TARGET = Some("aarch64-unknown-linux-gnu")
    HOST = Some("aarch64-unknown-linux-gnu")
    CC_aarch64-unknown-linux-gnu = None
    CC_aarch64_unknown_linux_gnu = None
    HOST_CC = None
    CC = None
    CFLAGS_aarch64-unknown-linux-gnu = None
    CFLAGS_aarch64_unknown_linux_gnu = None
    HOST_CFLAGS = None
    CFLAGS = None
    CRATE_CC_NO_DEFAULTS = None
    DEBUG = Some("false")
    CARGO_CFG_TARGET_FEATURE = Some("fp,neon")
    running: "cc" "-O2" "-ffunction-sections" "-fdata-sections" "-fPIC" "-I" "native" "-Wall" "-Wextra" "-DARGON2_NO_THREADS" "-o" "/home/ubuntu/nimiq/target/release/build/libargon2-sys-1a40ba79533982af/out/native/argon2.o" "-c" "native/argon2.c"
    exit code: 0
    running: "cc" "-O2" "-ffunction-sections" "-fdata-sections" "-fPIC" "-I" "native" "-Wall" "-Wextra" "-DARGON2_NO_THREADS" "-o" "/home/ubuntu/nimiq/target/release/build/libargon2-sys-1a40ba79533982af/out/native/core.o" "-c" "native/core.c"
    exit code: 0
    running: "cc" "-O2" "-ffunction-sections" "-fdata-sections" "-fPIC" "-I" "native" "-Wall" "-Wextra" "-DARGON2_NO_THREADS" "-o" "/home/ubuntu/nimiq/target/release/build/libargon2-sys-1a40ba79533982af/out/native/blake2/blake2b.o" "-c" "native/blake2/blake2b.c"
    exit code: 0
    running: "cc" "-O2" "-ffunction-sections" "-fdata-sections" "-fPIC" "-I" "native" "-Wall" "-Wextra" "-DARGON2_NO_THREADS" "-o" "/home/ubuntu/nimiq/target/release/build/libargon2-sys-1a40ba79533982af/out/native/opt.o" "-c" "native/opt.c"
    cargo:warning=In file included from native/opt.c:26:0:
    cargo:warning=native/blake2/blamka-round-opt.h:23:10: fatal error: emmintrin.h: No such file or directory
    cargo:warning= #include <emmintrin.h>
    cargo:warning=          ^~~~~~~~~~~~~
    cargo:warning=compilation terminated.
    exit code: 1
    
    --- stderr
    
    
    error occurred: Command "cc" "-O2" "-ffunction-sections" "-fdata-sections" "-fPIC" "-I" "native" "-Wall" "-Wextra" "-DARGON2_NO_THREADS" "-o" "/home/ubuntu/nimiq/target/release/build/libargon2-sys-1a40ba79533982af/out/native/opt.o" "-c" "native/opt.c" with args "cc" did not execute successfully (status code exit code: 1).
    
    crate:libargon2-sys target:arm 
    Reply
  • error: linking with `cc` failed: exit code: 1
    error: linking with `cc` failed: exit code: 1

    Nov 29, 2019

    New issue checklist

    Tried to build core-rs from source by cloning from Github. I switched to nightly build with rustup default nightly. As soon as I started building with cargo +nightly build the compiling stopped with the following error: error: linking with `cc` failed: exit code: 1

    The README of core-rs states that besides rust nightly you need gcc, pkg-config and libssl-dev, which I installed through apt.

    Solution

    Install gcc-multilib as well and it started compiling with no issues.

    Reply
  • Add minimum RAM to README
    Add minimum RAM to README

    Dec 1, 2019

    Pull request checklist

    • (n/a) All tests pass. Demo project builds and runs.
    • [x] I have resolved any merge conflicts.

    What's in this pull request?

    Adds that one needs 2GB of RAM to build. I tried to build this with 1GB of RAM, and it didn't work until I went up to 2GB.

    Reply
  • Backport ffe290e and f8357d8 from albatross
    Backport ffe290e and f8357d8 from albatross

    Jan 29, 2020

    Backports this and this commits from the albatross codebase.

    Reply
  • Backport 377ebd8 from albatross
    Backport 377ebd8 from albatross

    Jan 30, 2020

    Backports this commit from the albatross codebase.

    Reply
  • [Albatross] Fix warnings & tests
    [Albatross] Fix warnings & tests

    May 28, 2019

    • [ ] Fix all tests
    • [ ] Move all tests from src to tests directories
    • [ ] Get rid of all compile warnings
    Reply
  • Remember block producers
    Remember block producers

    Jul 6, 2019

    Currently, only producers of micro blocks during the latest two epochs are known. The slot data should be included in ChainInfo to persist the producer info of historic blocks.

    albatross 
    Reply
  • config.example.toml suggests unavailable options
    config.example.toml suggests unavailable options

    Aug 16, 2019

    The example config file includes many "available settings" that are not actually available, such as the dumb mode, light and nano consensus etc.

    These should be removed from the example config file for release.

    Reply
  • error[E0554]: #![feature] may not be used on the stable release channel
    error[E0554]: #![feature] may not be used on the stable release channel

    Apr 27, 2019

    error[E0554]: #![feature] may not be used on the stable release channel --> collections/src/lib.rs:2:1 | 2 | #![feature(box_into_raw_non_null)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    error[E0554]: #![feature] may not be used on the stable release channel --> collections/src/lib.rs:3:1 | 3 | #![feature(specialization)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^

    error[E0554]: #![feature] may not be used on the stable release channel --> collections/src/lib.rs:4:1 | 4 | #![feature(map_get_key_value)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    Compiling indexmap v1.0.2 error: aborting due to 3 previous errors

    For more information about this error, try rustc --explain E0554. error: Could not compile nimiq-collections. warning: build failed, waiting for other jobs to finish... error: build failed

    wontfix 
    Reply
  • `AddressParseError`doesn't implement `std::fmt::Display`
    `AddressParseError`doesn't implement `std::fmt::Display`

    May 10, 2019

    I ran into this multiple times, but never got the time to fix it. So here is the issue open for anyone to fix. Or I will fix it, once I got some spare time.

    error[E0277]: `keys::AddressParseError` doesn't implement `std::fmt::Display`
      --> src/config.rs:52:53
       |
    52 |     Address::from_user_friendly_address(&s).map_err(Error::custom)
       |                                                     ^^^^^^^^^^^^^ `keys::AddressParseError` cannot be formatted with the default formatter
       |
       = help: the trait `std::fmt::Display` is not implemented for `keys::AddressParseError`
       = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
       = note: required by `config::_IMPL_DESERIALIZE_FOR_GenesisConfig::_serde::de::Error::custom`
    

    Since keys::AddressParseError is an error, we should also implement the necessary traits.

    good first issue crate:keys 
    Reply
  • Validator creates block with invalid justification
    Validator creates block with invalid justification

    Jul 6, 2019

    • Branch terorie/albatross devnet
    • Sometimes, when crate validator produces a block, it gets rejected by crate blockchain
    • Failing check:
    if !intended_slot_owner.verify(&micro_block.header, &justification) {
                    warn!("Rejecting block - invalid justification for intended slot owner");
    
    • Log:
     INFO nimiq_validator::validator                 > Produced block: block_number=73529, view_number=0, hash=73e7f9e...                                                                                                                   
     INFO nimiq_consensus::consensus                 > Now at block #73529                                                                                         
     TRACE nimiq_validator::validator                 > Next block producer: CompressedPublicKey(ae88f18...)
     TRACE nimiq_validator::validator                 > Push result: Ok(Extended)                                                                                  
     INFO nimiq_validator::validator                 > Produced block: block_number=73530, view_number=0, hash=186435...
     WARN nimiq_blockchain_albatross::blockchain     > Rejecting block - invalid justification for intended slot owner                                             
     DEBUG nimiq_blockchain_albatross::blockchain     > Intended slot owner: CompressedPublicKey(ae88f18...)
     ERROR nimiq_validator::validator                 > Failed to push produced micro block to blockchain: InvalidBlock(InvalidJustification)                                                                                                                                                     
    
    bug albatross 
    Reply
  • Fixed panic in `Mempool::push_transaction` and head hash update in `Blockchain::rebranch`
    Fixed panic in `Mempool::push_transaction` and head hash update in `Blockchain::rebranch`

    Apr 6, 2019

    Pull request checklist

    • [X] All tests pass. Demo project builds and runs.
    • [X] I have resolved any merge conflicts.

    What's in this pull request?

    On block 488308 a fork happened that was resolved at block 488309. After rebranching a transaction was pushed to the mempool which crashed the node. Somehow the sender balance was out of funds. It is possible for a transaction to be verified, but later when all transactions for the sender address are being rechecked, that the sender is out of funds. It is unclear if this caused the crash. The log looks like the transaction was received after the block was processed, but maybe the other transactions with the same sender address weren't removed from the mempool yet. I will check this later. I fixed this, by rejecting a transaction during rechecking if the sender is out of funds, as this should be the intended behavior. Another possible fix is to synchronize the whole Mempool::push_transaction over the Blockchain or Accounts.

    After the crash the node didn't restart, because the rebranching code didn't update the head hash in the ChainStore, which caused the head's accounts tree hash to be incorrect. I fixed this by updating the ChainStore's head hash before commiting the rebranching transaction.

    Reply
  • More sub-crates
    More sub-crates

    Jan 16, 2019

    Currently, it is very cumbersome to use/debug only parts of the implementation. The main reason for that is almost all code residing in the main project source.

    I propose to make use of more sub-crates (similar to parity-bitcoin). This also helps cleaning up unwanted dependencies. Currently, for example, our consensus module has dependencies on the network module. It also speeds up compilation and testing, when only some parts were changed. Finally, it allows us to compile relevant parts of it to WebAssembly.

    As there are many ways to divide the current code into sub-crates, this issue is meant for discussion about how to structure those.

    My proposal would be something like:

    • db (database layer) ✅
    • hash (hashes, non-key related cryptography) ✅
    • keys (private keys, signatures, address,...) ✅
    • primitives (Target, Coin, Compact, everything related to blocks and transactions, contracts and basic accounts,...) ✅
    • datastructures (Accounts, Blockchain, ChainStore and other concrete db stores) ✅
    • consensus (Consensus, ConsensusAgent, Mempool) ✅
    • mnemonic (mnemonics) ✅
    • key-derivation (key derivation) ✅
    • network (all networking) ✅
    • network-primitives (primitives used in multiple locations) ✅
    • core (putting things together, but no binary) (currently in main folder ✅)
    • rpc (JSON-RPC) (to be merged)
    • utils (most utils, configurable via feature flags) ✅
    • Separate binary crate ✅ (by @jgraef)

    Note: I just quickly wrote down this as a starting point. Looking forward to your ideas. :) Those that I already created are marked with ✅. Those that are currently in progress are marked with ☑️.

    Reply
  • No such file or directory (os error 2) nimiq-client
    No such file or directory (os error 2) nimiq-client

    Apr 28, 2019

                                                                                                                                                                                                           
    Reply
  • Cannot build project on Mac
    Cannot build project on Mac

    Apr 14, 2019

    Bug report

    Expected behavior

    The project should build on Mac

    Actual behavior

    The project fails to build

    Steps to reproduce

    Clone repository. Run 'cargo build'

    Crash log? Screenshots? Videos? Sample project?

    error: suffixes on a tuple index are invalid
      --> primitives/block/src/target.rs:12:64
       |
    12 | #[derive(Default, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
       |                                                                ^^^^^^^^^ invalid suffix `i32`
    
    error: proc-macro derive produced unparseable tokens
      --> primitives/block/src/target.rs:12:64
       |
    12 | #[derive(Default, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
       |                                                                ^^^^^^^^^
    
    error: aborting due to 2 previous errors
    
    error: Could not compile `nimiq-block`.
    warning: build failed, waiting for other jobs to finish...
    error: build failed
    
    Reply