Skip to content

Developer guide

C++ projects

Koinos projects that are written in C++ utilize CMake for generating build files. CMake is a flexible pre-build step that allows developers to utilize a variety of Integrated Development Environments (IDE).

Dependencies are handled using the Hunter package manager. Hunter will download the necessary dependencies and compile them on your development machine as well as cache the resulting libraries. Normally, a developer need not be aware of the Hunter mechanism - which is its great advantage. Be aware that the first time you generate a CMake project it will build the dependency cache increasing your build times. Subsequent calls to CMake will leverage the Hunter cache.

Dependencies

You will need a modern C++ compiler as well as CMake to build Koinos C++ projects. This should be easily handled by your operating systems package manager.

macOS

$ brew install cmake

Note: If you have Xcode installed, you will have Apple Clang, which should be sufficient for Koinos projects.

$ brew install cmake clang

Note: If you opt to not use Xcode or its compiler, you may install Clang using brew.

Debian/Ubuntu

$ sudo apt install build-essentials libgmp cmake

Building projects

For this example we will use the Koinos Chain microservice. Let's begin by cloning the repository.

$ git clone --recursive https://github.com/koinos/koinos-chain.git

Koinos makes heavy use of git submodules, so we recommend using --recursive when cloning a repository.

Now let's generate the project. One may opt to create Unix Makefiles, Xcode, or another project type that is supported by CMake (the default project is Unix Makefiles).

You may also choose to build Debug or Release files.

Below find some common CMake incantations.

# Unix Makefile (Release mode)
$ mkdir build
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Release ..
$ make -j
# Unix Makefile (Debug mode)
$ mkdir build
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Debug ..
$ make -j
# Xcode project
$ mkdir build
$ cd build
$ cmake -GXcode ..
$ open koinos_chain.xcodeproj

Running unit tests

Koinos C++ projects use a combination of Boost test and CTest for unit testing. Tests are written in standard Boost test format while CTest allows for running tests in parallel.

After compilation, one may navigate to the tests/ directory and invoke ctest to execute test suites.

# Running the test suite concurrently
$ cd build/tests
$ ctest -j
Test project /Users/sgerbino/Projects/koinos-chain/build/tests
      Start  1: koinos_tests-controller_tests/submission_tests
 1/26 Test  #1: koinos_tests-controller_tests/submission_tests .............   Passed    1.23 sec
      Start  2: koinos_tests-controller_tests/block_irreversibility
 2/26 Test  #2: koinos_tests-controller_tests/block_irreversibility ........   Passed    1.10 sec
      Start  3: koinos_tests-controller_tests/fork_heads
 3/26 Test  #3: koinos_tests-controller_tests/fork_heads ...................   Passed    1.13 sec
      Start  4: koinos_tests-controller_tests/read_contract_tests
 4/26 Test  #4: koinos_tests-controller_tests/read_contract_tests ..........   Passed    1.07 sec
      Start  5: koinos_tests-controller_tests/transaction_reversion_test
 5/26 Test  #5: koinos_tests-controller_tests/transaction_reversion_test ...   Passed    1.09 sec
      Start  6: koinos_tests-statedb_tests/basic_test
 6/26 Test  #6: koinos_tests-statedb_tests/basic_test ......................   Passed    1.04 sec
      Start  7: koinos_tests-statedb_tests/fork_tests
 7/26 Test  #7: koinos_tests-statedb_tests/fork_tests ......................   Passed    1.05 sec
      Start  8: koinos_tests-statedb_tests/merge_iterator
 8/26 Test  #8: koinos_tests-statedb_tests/merge_iterator ..................   Passed    1.10 sec
      Start  9: koinos_tests-statedb_tests/reset_test
 9/26 Test  #9: koinos_tests-statedb_tests/reset_test ......................   Passed    1.08 sec
      Start 10: koinos_tests-statedb_tests/anonymous_node_test
10/26 Test #10: koinos_tests-statedb_tests/anonymous_node_test .............   Passed    1.03 sec
      Start 11: koinos_tests-thunk_tests/db_crud
11/26 Test #11: koinos_tests-thunk_tests/db_crud ...........................   Passed    1.05 sec
      Start 12: koinos_tests-thunk_tests/contract_tests
12/26 Test #12: koinos_tests-thunk_tests/contract_tests ....................   Passed    1.06 sec
      Start 13: koinos_tests-thunk_tests/override_tests
13/26 Test #13: koinos_tests-thunk_tests/override_tests ....................   Passed    1.04 sec
      Start 14: koinos_tests-thunk_tests/thunk_test
14/26 Test #14: koinos_tests-thunk_tests/thunk_test ........................   Passed    1.03 sec
      Start 15: koinos_tests-thunk_tests/system_call_test
15/26 Test #15: koinos_tests-thunk_tests/system_call_test ..................   Passed    1.05 sec
      Start 16: koinos_tests-thunk_tests/chain_thunks_test
16/26 Test #16: koinos_tests-thunk_tests/chain_thunks_test .................   Passed    1.05 sec
      Start 17: koinos_tests-thunk_tests/hash_thunk_test
17/26 Test #17: koinos_tests-thunk_tests/hash_thunk_test ...................   Passed    1.05 sec
      Start 18: koinos_tests-thunk_tests/privileged_calls
18/26 Test #18: koinos_tests-thunk_tests/privileged_calls ..................   Passed    1.06 sec
      Start 19: koinos_tests-thunk_tests/last_irreversible_block_test
19/26 Test #19: koinos_tests-thunk_tests/last_irreversible_block_test ......   Passed    1.05 sec
      Start 20: koinos_tests-thunk_tests/stack_tests
20/26 Test #20: koinos_tests-thunk_tests/stack_tests .......................   Passed    1.04 sec
      Start 21: koinos_tests-thunk_tests/require_authority
21/26 Test #21: koinos_tests-thunk_tests/require_authority .................   Passed    1.04 sec
      Start 22: koinos_tests-thunk_tests/transaction_nonce_test
22/26 Test #22: koinos_tests-thunk_tests/transaction_nonce_test ............   Passed    1.06 sec
      Start 23: koinos_tests-thunk_tests/get_contract_id_test
23/26 Test #23: koinos_tests-thunk_tests/get_contract_id_test ..............   Passed    1.05 sec
      Start 24: koinos_tests-thunk_tests/token_tests
24/26 Test #24: koinos_tests-thunk_tests/token_tests .......................   Passed    1.17 sec
      Start 25: koinos_tests-thunk_tests/get_head_block_time
25/26 Test #25: koinos_tests-thunk_tests/get_head_block_time ...............   Passed    1.05 sec
      Start 26: koinos_tests-thunk_tests/tick_limit
26/26 Test #26: koinos_tests-thunk_tests/tick_limit ........................   Passed    1.12 sec

100% tests passed, 0 tests failed out of 26

Total Test time (real) =  27.92 sec

It may be useful to re-run a particular test and test suite during iterative development. To achieve this we can invoke individual tests.

$ ./koinos_tests -t statedb_tests/basic_test -l message
Running 1 test case...
Creating book
Modifying book
Erasing book

*** No errors detected

It may be useful to start a test but have it wait for the debugger to be attached. Boost provides this feature, you can leverage it by adding --wait_for_debugger to the test binary invocation.

./koinos_tests -t statedb_tests/basic_test -l message --wait_for_debugger
Press any key to continue...

Continuing...
Running 1 test case...
Creating book
Modifying book
Erasing book

*** No errors detected

Golang projects

Koinos projects using Golang leverage the built-in language facilities where possible. Retrieving dependencies and version management is handled by the language itself. Koinos projects require Golang v1.16 or better.

Building projects

For this example we will use the Koinos Block Store microservice. Let's begin by cloning the repository.

$ git clone --recursive https://github.com/koinos/koinos-block-store.git

Note: Koinos makes heavy use of git submodules, so we recommend using --recursive when cloning a repository.

Now that we have the code, let's grab all the necessary dependencies of the project.

$ go get ./...

Keeping with our build/ convention, we can compile the Golang binary.

$ mkdir build
$ go build -o build/koinos_block_store cmd/koinos-block-store/main.go

Running unit tests

Because Golang provides us with built-in unit test facilities, running tests is a simple invocation.

$ go test -v ./...
?       github.com/koinos/koinos-block-store/cmd/koinos-block-store [no test files]
=== RUN   TestBadgerBackendBasic
badger 2021/07/15 16:14:05 INFO: All 0 tables opened in 0s
badger 2021/07/15 16:14:05 INFO: DropAll called. Blocking writes...
badger 2021/07/15 16:14:05 INFO: Writes flushed. Stopping compactions now...
badger 2021/07/15 16:14:05 INFO: Deleted 0 SSTables. Now deleting value logs...
badger 2021/07/15 16:14:05 INFO: Value logs deleted. Creating value log file: 0
badger 2021/07/15 16:14:05 INFO: Deleted 1 value log files. DropAll done.
badger 2021/07/15 16:14:05 INFO: Resuming writes
badger 2021/07/15 16:14:05 INFO: Got compaction priority: {level:0 score:1.73 dropPrefixes:[]}
--- PASS: TestBadgerBackendBasic (0.04s)
=== RUN   TestMapBackendBasic
--- PASS: TestMapBackendBasic (0.00s)
=== RUN   TestHandleReservedRequest
badger 2021/07/15 16:14:05 INFO: All 0 tables opened in 0s
badger 2021/07/15 16:14:05 INFO: Got compaction priority: {level:0 score:1.73 dropPrefixes:[]}
--- PASS: TestHandleReservedRequest (0.06s)
=== RUN   TestGetPreviousHeights
--- PASS: TestGetPreviousHeights (0.00s)
=== RUN   TestAddBlocks
badger 2021/07/15 16:14:05 INFO: All 0 tables opened in 0s
badger 2021/07/15 16:14:05 DEBUG: Storing value log head: {Fid:0 Len:43 Offset:18776}
badger 2021/07/15 16:14:05 INFO: Got compaction priority: {level:0 score:1.73 dropPrefixes:[]}
badger 2021/07/15 16:14:05 INFO: Running for level: 0
badger 2021/07/15 16:14:05 DEBUG: LOG Compact. Added 21 keys. Skipped 41 keys. Iteration took: 194.809µs
badger 2021/07/15 16:14:05 DEBUG: Discard stats: map[0:10893]
badger 2021/07/15 16:14:05 INFO: LOG Compact 0->1, del 1 tables, add 1 tables, took 17.488282ms
badger 2021/07/15 16:14:05 INFO: Compaction for level: 0 DONE
badger 2021/07/15 16:14:05 INFO: Force compaction on level 0 done
badger 2021/07/15 16:14:05 INFO: All 0 tables opened in 0s
badger 2021/07/15 16:14:06 DEBUG: Storing value log head: {Fid:0 Len:43 Offset:19054}
badger 2021/07/15 16:14:06 INFO: Got compaction priority: {level:0 score:1.73 dropPrefixes:[]}
badger 2021/07/15 16:14:06 INFO: Running for level: 0
badger 2021/07/15 16:14:06 DEBUG: LOG Compact. Added 22 keys. Skipped 41 keys. Iteration took: 202.153µs
badger 2021/07/15 16:14:06 DEBUG: Discard stats: map[0:10893]
badger 2021/07/15 16:14:06 INFO: LOG Compact 0->1, del 1 tables, add 1 tables, took 13.421024ms
badger 2021/07/15 16:14:06 INFO: Compaction for level: 0 DONE
badger 2021/07/15 16:14:06 INFO: Force compaction on level 0 done
--- PASS: TestAddBlocks (0.44s)
=== RUN   TestGetBlocksByID
--- PASS: TestGetBlocksByID (0.01s)
=== RUN   TestGetHighestBlock
badger 2021/07/15 16:14:06 INFO: All 0 tables opened in 0s
--- PASS: TestGetHighestBlock (0.03s)
=== RUN   TestInternalError
--- PASS: TestInternalError (0.00s)
PASS
ok      github.com/koinos/koinos-block-store/internal/bstore    0.955s