Andromeda Consensus

Published on 2018 Oct 23 00:00:02
Last Updated on 2018 Oct 25 16:36:40


In this document we will explore Lucidity's on-chain Proof-of-Stake consensus called Andromeda. It is meant to be a tool to build Sidechains with Generalized State Transitions.


Andromeda is an on-chain Proof-of-Stake consensus mechanism. Andromeda derives consensus by allowing a set of verifiers to vote on what the consensus should be at any given time.

Consensus Overview

Voting happens in phases via a commit-reveal mechanism. The on-chain consensus is fully decentralized and does not require central management.

There is a Verifier Registry which can be owned, managed, federated, etc. Within the Verifier Registry, verifiers are able to deposit and set tokens at stake.

Andromeda then connects to the specified Verifier Registry and counts each of the verifier's votes based on the number of tokens they have at stake.

The Andromeda smart contract does not enforce what constitutes as valid consensus, (e.g. it does not extend a consensus round if 2/3rd of the verifiers didn't vote.)

Building Sidechain Apps

The core purpose of Andromeda is to make it easy and simple to build decentralized sidechain applications. The idea is that an entity may build their sidechain application using any language on any platform, as long as the app can derive its state in a deterministic way.


The point of memorializing a sidechain app's state on the rootchain is to enable Proof-of-Stake plasma sidechains such as those used in Plasma MVP, Plasma Cash, and Lucidity's Plasma Bank.

How it Works


  1. Make election independent from commissioner or any other participants.
  2. Make it easy to use, so verifiers do not need to wonder about closing or opening election.

Election cycle

Election cycle is made of two phases:

  1. proposal phase - where verifier makes blind proposal
  2. revealing (and calculating) phase - when verifier reveals its proposal and all revealed data are counted

Propose phase

Verifier provides its blind proposal. Contract save in blocks at blockHeigh index.

Revealing phase

Verifier reveals its vote. Contract count (this is PoS, so weight of vote is base on verifier balance) it and save real-time results.

Cycle rules

  1. Time frame for each phase is calculated base on block numbers not timestamp.
  2. Duration of phases are set when deploy and can't be change
  3. There is no gap between phases.
  4. You can miss any phase and nothing bad will happen.
  5. In case all verifiers miss all two phases, there will be empty block at blockHeight identifier.
  6. In case verifier proposed but did not reveal in current cycle, this proposal will be ignored, but information about proposal will be present on blockchain.
  7. There is no way to reveal "old" proposals.


Methods (transactions)

Name Param(s) Description
propose bytes32 ** blindedProposal Only for verifier
reveal bytes32 proposal; bytes32 secret Only for verifier
updateRegistryAddress address registryAddress Only for owner

Public variables

Name Type
blocksPerPhase uint8


Name Param(s) Return
getCurrentElectionCycleBlock - uint256 - current block number with reference to whole cycle
getFirstCycleBlock - uint256 - first block number (blockchain block) of current cycle
getBlockRoot uint256 blockHeight, uint256 shard bytes32 root
getBlockVoter uint256 blockHeight, address voter bytes32 blindedProposal, uint256 shard; bytes32 proposal, uint256 balance
getBlockMaxVotes uint256 blockHeight, uint256 shard uint256 maxVotes
getBlockCount uint256 blockHeight, uint256 shard, bytes32 proposal uint256 - number of votes
getBlockAddressCount uint256 blockHeight uint256 - number of addresses
getBlockAddress uint256 blockHeight, uint256 i address


Event Name Arguments
LogPropose address sender; uint256 blockHeight; bytes32 blindedProposal; uint256 shard; uint256 balance
LogReveal address sender; uint256 blockHeight; bytes32 ** proposal;
LogBlocksPerPhase uint16 blocksPerPhase
LogUpdateCounters address sender; uint256 blockHeight; uint256 shard; bytes32 proposal; uint256 counts; uint256 balance; bool newWinner;


Contract is designed in a way, that every verifier should be able to use it by executing propose() and reveal() once per cycle. Other data like duration of phases can be easily collected by watching events.

In general, this is how the perfect cycle should looks like:

  1. Verifier makes proposal
  2. Verifier calculate block number (base on LogBlocksPerPhase event) and wait until reveal phase starts.
  3. Verifier reveals its vote.

The Calculations

It is very simple to calculate and figure out, what is the current phase. When you are watching LogBlocksPerPhase event (or you can directly call for duration value) you already know the value of duration variable:

cycleDuration = (blocksPerPhase * 2 )

Now you khow how many blocks it takes to do whole cycle. You can calculate current phase base on blockchain block number:

currentBlockPhase = blockchain.blockNumber % cycleDuration

Value of currentBlockPhase tells us, what is the current phase of cycle i.e: if each phase will take 5 blocks (whole cycle will be 0…9), current block on blockchain is 5789 then current phase block will be:

5789 % (5 * 2) = 9

means we are at the last block of reveal phase, that is last block for a whole cycle.


The smart contracts are still in development and we are releasing them as open-source to receive feedback on our concepts, ideas, and code. There is still work to be done to add things like delegation, locking of tokens, etc. Please review the code and reach out to us with any comments or questions!