Skip to content

Commit

Permalink
Merge pull request #60 from input-output-hk/develop
Browse files Browse the repository at this point in the history
Release 0.1.0
  • Loading branch information
aakoshh authored Jul 13, 2021
2 parents a750c9d + 768d2cd commit 4f231d6
Show file tree
Hide file tree
Showing 146 changed files with 16,649 additions and 2 deletions.
90 changes: 90 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
version: 2.1
jobs:
build:
docker:
- image: circleci/openjdk:11-jdk

working_directory: ~/repo

environment:
JVM_OPTS: -Xmx3200m
TERM: dumb

steps:
- checkout

# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "build.sc" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-

# https://circleci.com/docs/2.0/env-vars/#using-bash_env-to-set-environment-variables
- run:
name: install coursier
command: |
curl -fLo cs https://git.io/coursier-cli-"$(uname | tr LD ld)"
chmod +x cs
./cs install cs
rm cs
echo "export PATH=$PATH:/home/circleci/.local/share/coursier/bin" >> $BASH_ENV
- run:
name: install scalafmt
command: cs install scalafmt

- run:
name: install mill
command: |
mkdir -p ~/.local/bin
(echo "#!/usr/bin/env sh" && curl -L https://github.com/lihaoyi/mill/releases/download/0.8.0/0.8.0) > ~/.local/bin/mill
chmod +x ~/.local/bin/mill
- run:
name: check that the code is formatted properly
command: scalafmt --test

# For some reason if I try to separate compile and test, then the subsequent test step does nothing.
- run:
name: compile and test
command: mill __.test

- save_cache:
paths:
- ~/.ivy2
- ~/.cache
key: v1-dependencies--{{ checksum "build.sc" }}

- when:
condition:
or:
- equal: [ master, << pipeline.git.branch >> ]
- equal: [ develop, << pipeline.git.branch >> ]
steps:
- run:
name: install gpg2
# GPG in docker needs to be run with some additional flags
# and we are not able to change how mill uses it
# this is why we're creating wrapper that adds the flags
command: |
sudo apt update
sudo apt install -y gnupg2
sudo mv /usr/bin/gpg /usr/bin/gpg-vanilla
sudo sh -c "echo '#!/bin/sh\n\n/usr/bin/gpg-vanilla --no-tty --pinentry loopback \$@' > /usr/bin/gpg"
sudo chmod 755 /usr/bin/gpg
cat /usr/bin/gpg
- run:
name: install base64
command: sudo apt update && sudo apt install -y cl-base64

- run:
name: publish
command: .circleci/publish.sh
no_output_timeout: 30m

workflows:
build_and_publish:
jobs:
- build
31 changes: 31 additions & 0 deletions .circleci/publish.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env bash

set -euv

echo $GPG_KEY | base64 --decode | gpg --batch --import

gpg --passphrase $GPG_PASSPHRASE --batch --yes -a -b LICENSE

if [[ "$CIRCLE_BRANCH" == "develop" ]]; then

mill mill.scalalib.PublishModule/publishAll \
__.publishArtifacts \
"$OSS_USERNAME":"$OSS_PASSWORD" \
--gpgArgs --passphrase="$GPG_PASSPHRASE",--batch,--yes,-a,-b

elif [[ "$CIRCLE_BRANCH" == "master" ]]; then

mill versionFile.setReleaseVersion
mill mill.scalalib.PublishModule/publishAll \
__.publishArtifacts \
"$OSS_USERNAME":"$OSS_PASSWORD" \
--gpgArgs --passphrase="$GPG_PASSPHRASE",--batch,--yes,-a,-b \
--readTimeout 600000 \
--awaitTimeout 600000 \
--release true

else

echo "Skipping publish step"

fi
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
*.class
*.log
.bloop
.metals
.vscode
out/
*.iml
/.idea*
1 change: 1 addition & 0 deletions .mill-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.8.0
3 changes: 3 additions & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
version = "2.7.4"
maxColumn = 80
align.preset = more
88 changes: 86 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,86 @@
# metronome
Checkpointing PoW blockchains with HotStuff BFT
# Metronome

Metronome is a checkpointing component for Proof-of-Work blockchains, using the [HotStuff BFT](https://arxiv.org/pdf/1803.05069.pdf) algorithm.

## Overview
Checkpointing provides finality to blockchains by attesting to the hash of well-embedded blocks. A proper checkpointing system can secure the blockchain even against an adversary with super-majority mining power.

The Metronome checkpointing system consists of a generic BFT Service (preferably HotStuff), a Checkpoint-assisted Blockchain, and a Checkpointing Interpreter that bridges the two. This structure enables many features, including flexible BFT choices, multi-chain support, plug-and-play forensic monitoring platform via the BFT service, and the capability of bridging trust between two different blockchains.

### Architecture

BFT Service: A committee-based BFT service with a simple and generic interface. It takes consensus candidates (e.g., checkpoint candidates) as input and generates certificates for the elected ones.

Checkpoint-assisted Blockchain: Maintains the main blockchain that accepts and applies checkpointing results. The checkpointing logic is delegated to the checkpointing interpreter below.

Checkpointing Interpreter: Maintains checkpointing logic, including the creation and validation (via blockchain) of checkpointing candidates, as well as checkpoint-related validation of new blockchain blocks.

Each of these modules can be developed independently with only minor data structure changes required for compatibility. This independence allows flexibility with the choice of BFT algorithm (e.g., variants of OBFT or Hotstuff) and checkpointing interpreter (e.g., simple checkpoints or Advocate).

The architecture also enables a convenient forensic monitoring module. By simply connecting to the BFT service, the forensics module can download the stream of consensus data and detect illegal behaviors such as collusion, and identify the offenders.

![Architecture diagram](docs/architecture.png)

![Component diagram](docs/components.png)

### BFT Algorithm

The BFT service delegates checkpoint proposal and candidate validation to the Checkpointing Interpreter using 2-way communication to allow asynchronous responses as and when the data becomes available.

![Algorithm diagram](docs/master-based.png)

When a winner is elected, a Checkpoint Certificate is compiled, comprising the checkpointed data (a block identity, or something more complex) and a witness for the BFT agreement, which proves that the decision is final and cannot be rolled back. Because of the need for this proof, low latency BFT algorithms such as HotStuff are preferred.


## Build

The project is built using [Mill](https://github.com/com-lihaoyi/mill), which works fine with [Metals](https://scalameta.org/metals/docs/build-tools/mill.html).

To compile everything, use the `__` wildcard:

```console
mill __.compile
```

The project is set up to cross build to all Scala versions for downstream projects that need to import the libraries. To build any specific version, put them in square brackets:

```console
mill metronome[2.12.10].checkpointing.app.compile
```

To run tests, use the wild cards again and the `.test` postix:

```console
mill __.test
mill --watch metronome[2.13.4].rocksdb.test
```

To run a single test class, use the `.single` method with the full path to the spec:

```console
mill __.storage.test.single io.iohk.metronome.storage.KVStoreStateSpec
```

To experiment with the code, start an interactive session:

```console
mill -i metronome[2.13.4].hotstuff.consensus.console
```

### Formatting the codebase

Please configure your editor to use `scalafmt` on save. CI will be configured to check formatting.


## Publishing

We're using the [VersionFile](https://com-lihaoyi.github.io/mill/page/contrib-modules.html#version-file) plugin to manage versions.

The initial version has been written to the file without newlines:
```console
echo -n "0.1.0-SNAPSHOT" > versionFile/version
```

Builds on `develop` will publish the snapshot version to Sonatype, which can be overwritten if the version number is not updated.

During [publishing](https://com-lihaoyi.github.io/mill/page/common-project-layouts.html#publishing) on `master` we will use `mill versionFile.setReleaseVersion` to remove the `-SNAPSHOT` postfix and make a release. After that the version number should be bumped on `develop`, e.g. `mill versionFile.setNextVersion --bump minor`.
Loading

0 comments on commit 4f231d6

Please sign in to comment.