LedgerHQ / lib-ledger-core

MIT License
79 stars 83 forks source link

Ledger Core Library

Core library which will be used by Ledger applications.

This project is considered "legacy", and no new coin support will arrive in the repo; only updates related to currently supported protocols.

Clone project

git clone --recurse-submodules https://github.com/LedgerHQ/lib-ledger-core.git

If you had already forked / cloned the repository before issuing that command, it’s okay. You can initiate the submodules with the following commands:

cd lib-ledger-core
git submodule init
git submodule update

Dependencies

You can skip this dependencies step if you have nix installed.

Build

This project is based on cmake as a build system so you should install it before starting (at least version 3.7).

External dependencies:

Build of C++ library

Nix build

If you have remote builders you can use them with the nix derivation bundled in the repo

Architecture

Utilities/Libraries
Shells
Local development

Using nix-shell

The repository provides a default.nix that allows to get into an environment ready for build. A hook sets the CMAKE_LIBCORE_FLAGS environment variable in the shell that has all the CMake flags you need to build libcore

# To be able to run tests
nix-shell --arg runTests true --arg jni false
# To be able to build a JAR from your local build
nix-shell

mkdir _build
cd _build
cmake .. $CMAKE_LIBCORE_FLAGS
make
ctest

Using nix-build

If you just need the artifact you can build the derivation directly

nix-build

Otherwise to run tests locally against your changes

nix-build --arg runTests true --arg jni false

Building a JAR locally

You can always build the JAR using this command

nix-shell --run "bash nix/scripts/build_jar.sh" nix/libcore-jar.nix --arg useLibcoreDerivation true

Non nix builds

cmake is building out of source, you should create a build directory (e.g. lib-ledger-core-build):

.                           # Directory where clone command was launched
├── lib-ledger-core         # Source files directory
├── lib-ledger-core-build   # Build directory

If you respect this folder structure (and naming), after cd lib-ledger-core-build, you can build the library by running:

cmake -DSYS_OPENSSL=ON -DOPENSSL_ROOT_DIR=<path-to-openssl-root-dir>  -DOPENSSL_INCLUDE_DIR=<path-to-openssl-include-files>  -DOPENSSL_SSL_LIBRARIES=<path-to-openssl-libraries> -DOPENSSL_USE_STATIC_LIBS=TRUE ../lib-ledger-core && make

NB. if you want to build on Windows with Visual Studio by adding the argument -G "Visual Studio 16 2019" in the above cmake command, instead of using make to build the project, you should open the 'ledger-core.sln' solution file with Visual Studio and build the solution with it

If you struggle with how openssl is installed, for example, on macOSX, openssl can be installed with

brew install openssl

you can then use the argument -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl in the above cmake command "DOPENSSL_INCLUDE_DIR" and "DOPENSSL_SSL_LIBRARIES" are not necessary on mac.

On Linux,

apt-get install libssl-dev

you can then use the argument -DOPENSSL_SSL_LIBRARIES=/usr/lib/x86_64-linux-gnu -DOPENSSL_INCLUDE_DIR=/usr/include/openssl in the above cmake command "DOPENSSL_ROOT_DIR" is not necessary on linux.

On Windows, Openssl can be downloaded and installed from https://slproweb.com/products/Win32OpenSSL.html "DOPENSSL_ROOT_DIR" is then the installed path of Openssl in the above cmake command "DOPENSSL_INCLUDE_DIR" and "DOPENSSL_SSL_LIBRARIES" are not necessary on windows.

Several CMake arguments might interest you there:

Building for JNI

Building with JNI (Java Native Interface), allows you to use the library with Java based software. In order to enable JNI mode use

cmake -DTARGET_JNI=ON

This will add JNI files to the library compilation and remove tests. You need at least a JDK 7 to build for JNI (OpenJDK or Oracle JDK)

Build library with PostgreSQL

Dependencies

Make sure that your have PostgreSQL installed on your machine, otherwise the CMake command find_package(PostgreSQL REQUIRED) will fail during configuration.

All Nix builds currently build with Postgres support by default.

Build

You need to add -DPostgreSQL_INCLUDE_DIR=path/to/include/dir in your configuration as a hint for headers' location (e.g. /usr/include/postgresql).

All Nix builds currently build with Postgres support by default.

Wallet Pool Configuration

To use with libcore, simply set value of the key api::PoolConfiguration::DATABASE_NAME to the database's URL connection and set it in the pool's configuration.

It is also possible to configure the size of the connection pool and read-only connection pool when instantiating the PostgreSQL DatabaseBackend : api::DatabaseBackend::getPostgreSQLBackend(int32_t connectionPoolSize, int32_t readonlyConnectionPoolSize).

Local testing

Make sure to have a running PostgreSQL server or PostgreSQL docker container. As an example, if you are running it on localhost:5432 and test_db as database name, database's name forwarded to the pool (through configuration key api::PoolConfiguration::DATABASE_NAME) should look like : postgres://localhost:5432/test_db . In order to run local tests

cd lib-ledger-core-build

On Linux or macOSX,

ctest

On Windows,

ctest -C Debug -VV

if you want to run only one specific unit test. (e.g. the test case BitcoinLikeWalletSynchronization.MediumXpubSynchronization in the test project ledger-core-integration-tests)

./core/test/integration/build/ledger-core-integration-tests "--gtest_filter=BitcoinLikeWalletSynchronization.MediumXpubSynchronization"

Publish libcore JAR into local repository

First you need to build the libcore with JNI enabled

mkdir build_lib_jni
cd build_lib_jni
cmake .. -DSYS_OPENSSL=ON -DOPENSSL_USE_STATIC_LIBS=TRUE -DTARGET_JNI=ON -DPG_SUPPORT=ON
cmake --build . --parallel

Then you can build & publish the jar with sbt publishLocal. A tool script wraps it:

./tools/publish-jar-local.sh ./lib_build_dir_jni

It will publish a maven artifact (available at ~/.ivy2/local/co.ledger/ledger-lib-core_2.12/local-SNAPSHOT) that can be used by any third party

Build production-like version of the library

To build the production-like version of the library use script tools/prod-like-build.sh. This script requires Docker. It starts from building Docker image with required versions of the dependencies. Next it starts the Docker container with that image and the lib-ledger-core source code from the current directory. The resulting ledger-lib-core.jar will be copied from the container to the artifacts sub-directory of the current directory. By default the Release versions of the lib-ledger-core is created. To specify the required build type add it to the command line: ./tools/prod-like-build.sh Debug.

Documentation

You can generate the Doxygen documentation by running the doc target (for instance, make doc with makefiles).

Use Code Coverage

:warning: Only available on Linux for now (with gcc).

  1. Make sure to have lcov installed
    sudo apt-get install -y lcov
  2. Set the CODE_COVERAGE cmake option to ON
  3. Compute the coverage, in build directory:
    • Based on unit tests only: cmake --build . --config Debug --target coverage_unit
    • Based on all tests: cmake --build . --config Debug --target coverage_all
  4. Open the report: ./coverage/index.html

Use optional compilation checks

Use optional compilation optimization

Binding to node.js

The library can be compiled and integrated as an node module in a pretty straightforward way. You will be interested in either using it, or making a new version of the node module.

Using the node module

The lib-ledger-core-node-bindings repository contains the node.js bindings you will need to interface with lib-ledger-core. You can either clone the git repository or simply install from npm directly:

npm i @ledgerhq/ledger-core

Generating a new node module for your system

Generating bindings is a several steps process:

  1. First, you need to make some changes to lib-ledger-core and generate a fresh version of lib-ledger-core.
  2. Clone lib-ledger-core-node-bindings and edit the package.json file in order to remove or comment the "preinstall" line in "scripts".
  3. In the folder of lib-ledger-core, run the tools/generateBindings.sh script by giving it the path to the bindings (i.e. where you cloned lib-ledger-core-node-bindings) and as second argument the path to the directory where you built the lib-ledger-core — it should be something like $(your-lib-ledger-core-dir)/../lib-ledger-core-build or $(your-lib-ledger-core-dir)/build.
    • This script requires an up-to-date djinni. To ensure it’s correctly up to date, go into lib-ledger-core/djinni and run get fetch origin --prune && git rebase origin/master.
    • You will need sbt and java8 for a complete, working install.
    • The script will generate files in both projects. You’re advised to remove the ones created in lib-ledger-core — if any — with a git checkout . and/or git reset ..
  4. cd into lib-ledger-core-bindings and run yarn to generate the bindings.
  5. You will have the module in build/Release/ledgerapp_nodejs.node in the bindings project.
  6. npm i should install your own version.

Support

Libcore:

Libcore can be built for following OSes:

Developement guidelines

Local tests

The best way to run tests locally is to use Nix:

nix-build --arg runTests true --arg jni false

If you don't want to, you can also provision the postgres test database if necessary, and then run ctest.

Code formating

We use clang-format >= 14, not available by default on ubuntu 20.04

Install

sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-14 main'
wget https://apt.llvm.org/llvm-snapshot.gpg.key
sudo apt-key add llvm-snapshot.gpg.key
sudo apt update
sudo apt install clang-format-14

CI

Rebasing

Rebasing is done easily. If your PR wants to merge feature/stuff -> develop, you can do something like this — assuming you have cloned the repository with a correctly set origin remote:

git checkout feature/stuff
git rebase -i origin/develop

Change the pick to r or reword at the beginning of each lines without changing the text of the commits — this has no effect. Save the file and quit. You will be prompted to change the commits’ messages one by one, allowing you to remove the [skip ci] tag from all commits.

Release process

To release the libcore, a Github action automates everything:

It will automatically:

Q/A and troubleshooting

I have updated an include file and test code doesn’t see the changes!

Currently, interface files (headers, .hpp) are not linked by copied directly into the test directory. That means that every time you make a change in the interface that is tested by any code in core/test/, you need to update the copy.

Just run this command:

cd $your_build_folder
rm -rf CMakeFiles CMakeCache.txt

I have upgraded my macOSX system and now I can’t compile anymore.

Especially if you’ve upgraded to Mojave for which there are some breaking changes, you will need to perform some manual tasks — here, for macOSX Mojave:

xcode-select --install
open /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg