var img = document.createElement('img'); img.src = "https://terradocs.matomo.cloud//piwik.php?idsite=2&rec=1&url=https://feather.terra.money" + location.pathname; img.style = "border:0"; img.alt = "tracker"; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(img,s);
Skip to main content

Understanding Feather

Project structure​

The Feather repo is a monorepo with the following directories:

  • cli: the Feather CLI, written in Go
  • coordinator: the Coordinator CosmWasm smart contract, written in Rust
  • docs: this very docs site
  • landing: the landing site for Feather

For the rest of this guide, it will only focus on the cli which powers most of Feather's functionalities. The cli directory largely follows the Go Standard Project Layout.

Test data​

Note

Test data refers to static data files which are read and used during testing, not *_test.go files!

Test data is stored in the /test directory, in accordance with the Go Standard Project Layout. Test data stored in /test should mirror the /internal directory, with additional directories used to differentiate between different test files in the same package. These additional directories may be omitted if it is clear which *_test.go file they belong to, e.g. only one set of files exist in the package.

For example:


.
├── internal
│ ├── app
│ │ └── feather
│ │ └── validator
│ │ └── daemon
│ │ └── genesis
│ │ ├── genesis.go
│ │ ├── genesis_test.go
│ │ ├── override.go
│ │ └── override_test.go
│ └── pkg
│ └── jsonmerge
│ ├── jsonmerge.go
│ └── jsonmerge_test.go
└── test
├── app
│ └── feather
│ └── validator
│ └── daemon
│ └── genesis
│ └── override
│ ├── file1.json
│ └── file2.json
└── pkg
└── jsonmerge
├── 1
│ ├── file1.json
│ ├── file2.json
│ └── file3.json
└── 2
├── file1.json
├── file2.json
└── file3.json

Architecture​

The following diagram shows the overall architecture of Feather:

Overall Architecture

Daemon​

The following diagram shows the Feather daemon architecture:

Daemon Architecture

Crash recovery​

Note

A necessary invariant for crash recovery to work: Feather daemon launch handling logic currently must be idempotent, since HandleLaunch is simply re-run for a given launch to restore it.

This is a feature of Feather daemon which persists daemon state, preventing Feather from losing subscribed chains and queued launch tasks during crashes.

Crash Recovery Architecture

If Feather Daemon is a state machine, with nodes as states at a point in time and edges as chain subscriptions (this is simplified), the action_log table saves edges and the checkpoints table saves individual nodes. Therefore to recover state, a checkpoint is restored and all actions from the checkpoint's timestamp are replayed.

Launch phases​

A chain launch has a few (currently implicit) phases meant to aid understanding what Feather daemon does at each stage:

  1. Pre-publish - the chain deployer has cloned the feather-core template to their local machine, but has not pushed it to Github as a public repo or broadcast that the chain is ready to be picked up by a validator deployer running Feather Daemon with
  2. Coordinating - the chain has been published to the Coordinator smart contract, but chain launch time has not been reached; validators can request to join these chains and chain deployers can approve the validators
  3. Admin - the chain deployer does not want to approve any more validators and can proceed to sign transactions distributing initial stake/balance among approved validators; the transactions are submitted to the Coordinator smart contract
  4. Blackout - nothing may edit the chain launch (as stored in the Coordinator smart contract), which prevents inconsistencies in each validator's genesis.json due to last-minute changes
  5. Chain launch - the chain launch time is reached and Feather daemon proceeds to build a Docker image containing the chain binary, pushes it to Docker Hub, and tells Kubernetes to use the Docker Hub image to start the chain

Launch Phases Architecture