logo

Introduction

This is becoming the main documentation resource for Encointer. It is work in progress.

For more detailed information refer to the whitepaper

Economics

This chapter shall be an opinionated interpretation of the status quo and what we expect to acheive with Encointer.

The Cantillon Effect

Richard Cantillon is known for his analysis on the effects of a change in money supply in a state on inequality. Around the year 1730 he wrote in his Essay sur la nature du commerce en général:

If the increase in actual money comes from the state's gold and silver mines, the mines' owner, the entrepreneurs, the smelters, the refiners and generally all those who work in them will increase their expenditure in line with their gains. At home they will consume more meat and wine or beer than they used to, and they will become accustomed to having better clothes, finer linen, and more ornate houses and other sought-after commodities. Consequently they will give employment to some craftsmen who hitherto had not as much work and who, for the same reason will increase their expenditure. All if this increased expenditure on meat, wine, wool, and the like will necessarily reduce the share of other people in the state who are not the initial beneficiaries from the wealth of the mines in question. The bargaining in the market, with the demand for meat, wine, wool and the like being stronger than usual, will not fail to increase their prices.

Nowadays, money supply isn't affected by mining gold and silver. It's the banks that issue money as credit - out of nothing. Translating Cantillon into our time, we should replace miner by banker. The rest of the story still applies. However, in spite of quantitative easing we don't see much price inflation for essential goods. This effect can be explained by observing that all this newly issued money never reaches the masses.

Encointer aims at inverting the Cantillon Effect. Instead of issuing money at the top, as credit to businesses and creditworthy individuals, we issue money at the bottom. Every individual gets a universal basic income: freshly issued money.

Universal Basic Income

A universal basic income (UBI) is a modest amount of money paid unconditionally to individuals on a regular basis (Standing). Most advocates of UBI aim at introducing it at a national level, as a monthly income to all legal (fiscal) residents and paid out in cash (denominated in national currency). Usually, a UBI is suggested to be financed by some form of taxation. As Van Parijs & Vanderborght explain, a national UBI may lead to justice among thieves (achieving more equality within a wealthy nation while there’s staggering inequality globally). They therefore argue for a global UBI, as do WBI or GBI.

Encointer aims at providing a global UBI in terms of units of cryptocurrency created on a regular basis and distributed to individuals (almost) unconditionally. Let’s examine the characteristics of such an encointer-UBI:

universal

Encointer is paid out to every human being able and willing to attend encointer meetus every 41 days and in posession of a smartphone. This unfortunately excludes persons with certain disabilities as well as those without a smartphone. Also, the need to travel to meetups comes at varying cost, depending on local population densities – a disadvantage to people living in remote areas. While this is not exactly unconditional, we think it is less exclusive on a global scale than introducing national UBI schemes in few wealthy nations. Moreover, encointer might promote the concept of UBI and pave the way for institutionalized national or global UBI.

basic

Nothing in the definition of UBI defines a specific amount. However, it is often understood to be sufficient to cover basic needs and therefore provide economic security to its beneficiaries. In order to do so, it should also be stable. Encointer is a new cryptocurrency with algorithmically defined monetary supply. Only the (global) market can define its purchasing power. global vs local currency

Cryptocurrencies based on public unpermissioned blockchains are global by nature. Encointer is such a cryptocurrency – with the important added feature of allowing local currencies to be issued, as will be discussed below. Encointer is paid out in equal nominal amounts to every individual. Technically, there is no decentralized way of doing otherwise as the P2P network has no awareness of national borders or the cost of living. As a means for UBI this is a mixed blessing. If UBI is expected to be suffient to cover basic needs there is no way to achieve this goal with a global currency. Purchasing power of one unit of global currency would vary hugely among different regions. The upside being that the UBI’s purchasing power is in that case expected to be higher in weaker economies, therefore reducing global inequality.

Because Encointer issuance involves meetups with known geolocation, it is technically feasible to issue local currencies which are algorithmically bound to high-interaction communities (though ignorant of national borders). This would allow the UBI to be denominated in a currency which is meant to be used within local ecosystems yet freely tradable globally. real value

The purchasing power of a unit of local encointer currency is market-based. It isn’t backed by gold or trust in some nations central bank. It’s value is determined by its usefulness as a store of value, medium of transfer or unit of account. Depending on national circumstances, the usefulness of encointer can vary. Where large parts of the populations are unbanked, encointer could complement national currency because it is accessible to everyone and more convenient to use and store than cash.

Another angle from which to define value could be international development aid. Encointer would allow to distribute aid to individuals living in a specified area directly by buying their local currency. It would even be possible to buy such local currency at fixed rates, thereby ensuring a stable value of that local currency. Administrative cost and misappropriation of development aid could be reduced significantly.

income

Encointer delivers an income in a fixed nominal amount of digital currency, paid (or issued) in regular intervals (for every ceremony meetup attended, happening in fixed intervals of 41 days) to all participating individuals. This income is obligation free and is given to the rich and the poor alike.

This income is paid for by issuing money and therefore by nominal inflation of encointer currency. The absolute nominal inflation rate depends on the number of ceremony meetup participants. And there is a correcting factor: Demurrage!

Literature

Demurrage

Encointer currencies feature nominal demurrage: All balances get devalued over time. The funds you’re holding lose 7% of their nominal value every month. Think of this devaluation like a payment to a solidarity fund that pays for the UBI. This way, Encointer can issue monthly UBI and still maintain stable money supply as shown by the simulation in the figure below. Another advantage of demurrage has been described by Silvio Gesell when he proposed Freigeld in 1916: Demurrage increases money velocity, which in turn fuels the local economy.

demurrage

Money supply for a stationary economy with a demurrage fee of 7% per month and a population of 10’000 participants. After an initial phase, the UBI of 1 token per ceremony maintains a constant ratio to the total money supply and therefore maintains a constant real value.

Comparison

Demurrage is mainly known as a means to increase money velocity. Known local currencies have chosen demurrage to be in the range of 2-8% per year.

Due to technical limitations, demurrage is often charged linearly, like 2% of the face value per quarter as in the case Chiemgauer, where demurrage is applied by stamping paper bills. Encointer has more technical freedom and charges compound demurrage, as a percentage of its current value. The difference between linear and compound demurrage becomes clear after 50 quarters: Your 100 Chiemgauer have cost 100€ in demurrage fees. With compound demurrage, your 100 Chiemgauer would still be worth

100€ * (1-0.02)^50 = 36.42€

Local Currencies

Cryptocurrencies are fundamentally global in nature. Their networks are decentralized and agnostic to national borders. But global currencies have a severe disadvantage: Their purchase value can evolve very differently in different regions. The Euro is such an example, which is the official currency in many european countries with distinct fiscal policies and economic development. While there are political reasons to favor such a unifying currency, many economists doubt the concept. States with less economic growth have no option of devaluing their national currency. They can only get into debt - and then get forced into austerity, further weakening their economy.

Local currencies on the other hand are mainly affected by local economy.

Classification

Known examples of local currencies can be divided into mutual credit, local fiat currencies and time banks.

Mutual Credit

Mutual credit is a membership based, cashless currency created by clearing positive and negative balances between members when they trade. Usually, the accounts are denominated in national currency. If Alice provides a service worth 100$ to Bob, Alices balance will be +100$, Bob's will be -100$. Alice can later spend her 100$ balance in a trade with Charlie, who may be interested in a service Bob provides. Businesses are often allowed to have negative balances in the order of their usual turnover for a few months. These schemes rely on a local authority that performs due diligence when accepting new members and bans defaulters.

Examples are barter networks like Talent or business exchange networks like WIR, RES.

Mutual credit usually comes with high transaction costs. You might not always find the product you are looking for and it may be challenging to accept such currency for payment if you don't know where to spend it later.

In an economic environment of deflation, when there is a shortage of money because banks are reluctant to issue credits, mutual credit has shown to be of great value [1]. But when there's an abundance of money, these networks are unattractive and they generally don't further Encointer's goal of reducing inequality.

Local Fiat Currencies

Currencies like Wörgl's AB Schein, Chiemgauer or Berkshares are denominated in national currency. Often they have circulating paper bills, sometimes featuring demurrage. What they all have in common: They are only circulating within a local community and are worthless elsewhere. Often, they are redeemable for national currency, sometimes subject to a small fee. Sometimes redemption is restricted to businesses.

On the bottom line, such currencies can be understood as a loyalty programme promoting local spending, sometimes incentivized with discounts. They are successful in strenghtening the spirit of local community [1] and they can mitigate unemployment in an environment of deflation (Wörgl). However, due to globalization, local goods are often more expensive than imported ones. Therefore, these currencies are not attractive for poorer members of the community if they have to buy the local currency with national currency in the first place.

Grassroots Economics' Sarafu Credit in Kenya is a very innovative approach that shows significant social impact by empowering poor neighbourhoods by issuing money to local businesses directly. However, their concept introduces complexity, as money supply and distribution so far relies on careful engineering by experts from outside the community, for each community specifically. Moreover, Sarafu Credit is backed by donation money. While this may resemble a cash-transfer scheme, it actually isn't: Foreign capital is used as a fractional reserve for the local currency by applying bonding curves.

Time Banks

A very egalitarian category of local currencies are time banks. They proclaim that one hour's worth of service by one human has equal value to one hour's work by any other. Mostly, they work like mutual credit currencies, with the difference that the denomination is hours instead of national currency.

Examples are Blaengarw Time Centre, Dane County Time Bank

While the concept of time banks has shown to increase social capital [1], in practise they feature high transaction cost and liquid matchmaking showed to be challenging. The main benefactors end up to be the same individuals that also perform well on a free market based on national money. If your service is in high demand, you will be able collect more hours than you'll be able to spend on services you desire.

Examples

AB-Schein Wörgl

During the great depression, the austrian village of Wörgl attempted a monetary experiment to fight deflation: A complementary local currency.

denominationSchilling (1:1 national currency)
issuanceby the muncipality, as partial salary for infrastructure work
backing(full?) reserve in Schilling, provided by wealthy individuals
demurrage12% / year linear pro rata
reimbursement fee2%
date1932 until prohibited in 1933

Observed Impact:

  • lower unemployment (-16% while elsewhere +19% in 1933)
  • 8-10x money velocity
  • improved infrastructure: bridge, ski-jump, streets

source

Chiemgauer

denominationEuro (1:1 national currency)
issuanceby Chiemgau association, in exchange for Euro
backingfull reserve in Euro
demurrage8% / year linear pro rata
reimbursement fee5% (of which 3% go to local associations chosen by buyers of Chiemgauer)
date2003 until now

WIR

WIR is rather a reciprocal exchange network (barter ring) - but it is an official currency (CHW). It is only open to businesses, not private persons.

denominationCHF (1:1 national currency)
issuanceby WIR bank as credit (with low interest rate)
backingmixed-asset backed
demurragenone
reimbursement feereimbursement prohibited, you have to spend it
date1934 until now

source

Blaengarw Time Centre

denominationhours of work
issuancereward for community work
backingcommunity events that can be attended with time credits
demurragenone
reimbursement feeno reimbursement
date2006 until now

References

[1] People Money: The Promise of Regional Currencies, Margrit Kennedy, Bernard Lietaer, John Rogers, ISBN-13: 978-1908009760, 2012

On Saving, Loans and Interest

If you ask me what is the worst thing in the world, I will say it is compound interest

said Olusegun Obasanjo, president of Nigeria, in August 2000 after the G8 Okinawa summit.

All that we had borrowed up to 1985 or 1986 was around $5 billion and we have paid about $16 billion yet we are still being told that we owe about $28 billion. That $28 billion came about because of the injustice in the foreign creditors’ interest rates.

Compound interest makes debt grow exponentially, but nothing in nature grows exponentially forever. Sooner or later there will always be a saturation effect (usually modeled with an S-curve).

Even worse, our national money is created by commercial banks as credit, bearing compound interest. A priviledge for wealthy shareholders, which results in constantly growing debt and growth imperative, an unsustainable way to design our economy.

Compound interest is also a major cause of inequality [1]. It ensures that rich are getting richer while the poor are getting poorer.

Alternatives

A lender usually charges interest from the borrower. Besides giving the lender an income, interest also covers opportunity costs and compensates for the risk of the borrower defaulting on the loan.

It is beneficial to society if members with capital they can spare for a limited period of time provide their assets to members who need capital to build a business or suffer a temporary shortage.

In a society with a lot of social capital, lenders often provide their assets without a monetary incentive (or do you charge interest when borrowing money to a friend?). But this way of social lending does not scale well to larger loans.

Mutual credit is a way to better scale social credit beyond bilateral agreements (See WIR, LETS, RES). Interest-free credit is issued by clearing positive and negative balances when members trade, denominated in national currency. (See local currencies)

Saving Is No Virtue

One of the main reasons we're saving is the fear that we might not be able to cover for our needs at some point in the future. UBI addresses this fear by promising a minimal unconditional income until our death. Insurance is another answer to this fear.

The act of accumulating capital is considered a main reason for the growth imperative by [2].

Saving is also motivated by the desire to become wealthy and better off than others. This desire conflicts with Encointer's goals of reducing inequality.

For all these reasons, the design of Encointer disincentivizes saving in favor of spending or investing locally.

Encointer's Approach

Holding Encointer currencies comes at high opportunity costs because of demurrage. This is an incentive to spend or lend money at no interest. However, it may appear more attractive to exchange all perishable money you don't immediately need for other assets outside the encointer ecosystem (national currency, shares, bonds, crypto assets). This investor flight would decrease the real value of encointer currencies.

Encointer allows businesses the issuance of vouchers that are not subject to demurrage. Vouchers are a transferrable promise to deliver goods or services sometime in the future. If they are transferrable, vouchers are nothing less than self-issued money. Vouchers can be valid after a certain date and therefore become credit. This credit is paid back by goods and services, not by money.

The story of the Deli Dollar tells us how vouchers can be credit:

Frank Tortoriello runs a deli in Great Barrington, Massachusetts. In 1989 he wanted to move to larger premises but the bank would not lend him the $4,500 he needed, so he simply printed his own money. He did not forge dollar bills - he launched "deli dollars" which customers could buy for $8 and, at phased periods, cash in for $10 of food. He sold the lot in a month and raised $5,000.

DeliDollar Bill With these vouchers, investors pay 8$ today instead of 10$ at some defined point in the future. This discount pleases the human time preference. While this discount can be viewed as interest, it certainly isn't compound interest. It only applies once and its value is fixed. Still, it gives the investor an incentive to invest.

References

1 Biondi et al, Inequality, mobility and the financial accumulation process: a computational economic analysis, Journal of Economic Interaction and Coordination, 2019

2 Binswanger, Mathias (2019). Der Wachstumszwang: Warum die Volkswirtschaft immer weiterwachsen muss, selbst wenn wir genug haben. Wiley-CVH. p. 275. ISBN 978-3-527-50975-1.

Self-Sovereign Identity and Digital Personhood

With self-sovereign identity (SSI) the individual identity holders can fully create and control their credentials, without being forced to request permission of an intermediary or centralised authority and gives control over how their personal data is shared and used. Wikipedia

SSI is a key building block for any decentralized ecosystem. To establish trust online, we need to be able to present verifyable credentials to any counterparty of our choice. With SSI we can prove our name, residence, citizenship, diplomas online.

While identity is about distinguishing one person from another through attributes or affiliations, personhood is about giving all real people inalienable digital participation rights independent of identity, including protection against erosion of their democratic rights through identity loss, theft, coercion, or fakery

Ford2020

Digital Personhood

The Encointer protocol provides a decentralized sybil-defense mechanism. Because each human can only be in one place at one time, Encointer provides each human with a singular proof of attendance for every ceremony attended. We call this a unique-proof-of-personhood (uPoP). This uPoP is used for sybil-attack mitigation for Encointer's universal basic income, but can also be useful for other use cases as described below.

Privacy Considerations

With Encointer, users may maintain different identities on different platforms. The Encointer uPoP can be used to ensure one human only maintains one ID on one specific platform with a high degree of anonymity.

Sybil-Defense for Social Media

Let's assume a decentralized social media platform like subsocial enforces all its users to maintain only one account per human and prevents sybil attack with Encointer uPoP.

Alice Smith registers on subsocial with an alter ego of Sophie Summers because she doesn't want her presence on subsocial to be easily linkable to her physical world identity. Upon registration, subsocial would send a challenge to Alice to provide a uPoP. This challenge includes

  • a platform token identifying subsocial (must be unique for subsocial)
  • a timestamp (or at least a ceremony index)
  • a confidence threshold (like: must prove attendance for N of the last M encointer ceremonies)
  • a list of trusted community identifers (can be restricted to a region to also provide plausibility of location of residence) Encointer will itself attempt to maintain a web-of-trust score for communities which can be referenced instead.

Alice now requests her uPoP for subsocial from the Encointer platform. Encointer maintains a registry of attested attendance for all recent ceremonies. Alice is represented in this registry by changing pseudonyms for every ceremony. These pseudonyms are public keys and she now has to provide evidence that she knows all private keys for all pseudonyms she claims.

Given that Alice can prove attendance of the requested N of the last M ceremonies, Encointer provides a uPoP to be sent to subsocial in the form of a verifiable credential signed by one encointer-worker enclave's signing-key. Encointer then stores the subsocial platform token along with Alice's ceremony attendance attestations. Should Alice attempt to claim the same ceremony attendances again for another account on subsocial, Encointer would deny to provide a uPoP.

uPoPs need to be renewed over time because an adversary could register an additional account every few months otherwise.

Now imagine Sophie Summers becomes a victim of cyberbullying and Alice wants to drop that identity and create a new one under the name of Maria Gonzales. She will have to attend a few encointer ceremonies without claiming the attendance with subsocial. After a few months, she can register a new account on subsocial because she has collected enough unlinked evidence.

Community Web of Trust

The Encointer protocol builds communities based on trusted setups involving well-known people in every community. On a community level, this trusted setup is the root of trust. On a global level, these people may not be known nor trusted and communities will not trust each other blindly. Adversaries might maintain bot communities in the middle of the pacific.

Encointer can leverage an economic incentive to build a web-of-trust (WoT) among communities: Encointer issues local currencies. Communities that trade with each other will exchange their local currencies frequently in both directions on a decentralized exchange (DEX). Based on a few trusted seed communities that act as a root of trust (one per country, continent, world), the whole world may become linkable in a single WoT given geographically dense adoption of Encointer.

Polkadot Parachain Personhood Service

Should Encointer become a common good parachain of Polkadot, it could provide proofs of digital personhood to other parachains through cross-chain communication. As uPoP will be signed by SGX enclaves, a client parachain needs a trustelss way to query the enclave registry to verify a uPoP.

XCMP can be used to verify a certain enclave is registered as an encointer-worker and has passed remote attestation on the encointer platform.

Please see our sybil-defense demo video to learn how sybil defense works within the Polkadot ecosystem of parachains.

Encointer Protocol

The Encointer protocol is what ensures that

  • only humans get a UBI
  • every human can only get it once

We call the result of this protocol a unique proof of personhood.

Encointer leverages the fact that every person can only be in one place at one time. Every 10 days, participants are requested to attend physical key-signing meetups with small groups of random people. Because all meetups happen as one global ceremony all on the same day at the same local time, no one can attend two meetups.

The formal definition of the protocol can be found in our whitepaper

The Encointer Ceremony Cycle

Encointer's proof-of-personhood protocol demands in-person participation in regular ceremony meetups.

Ceremony Phases

The perpetual ceremony cycle is divided into three phases:

Ceremony Phase Cycle

Registering

During this phase, community members can register for the upcoming ceremony.

It is also possible to register new communities or new meetup locations ONLY during this phase

If ceremony rewards have not already been claimed during Attesting phase, this can still be done now.

Registering is usually the longest phase in the cycle

Assigning

At the beginning of this phase, the chain will close registrations and pick a random seed for meetup assignments.

Now it is time to check your Encointer Wallet app if you have been assigned to the upgoming ceremony (making you an assigninee) and where you'll have to physically be present with your mobile at what precise time.

Assigning lasts for 24h to give people enough lead time between the moment when they know if the were assigned and where and the moment when they have to physically attend.

Attesting

During this 48h phase, the ceremony meetups will be performed all around the world around local noon (high sun, actually).

Assignees will physically meet at their assigned locations and times and mutually attest their personhood and attendance (attendees). They send their attestations to the chain. In the happy flow, ceremony rewards (community issued income) can be claimed immediately after the last attendee has sent their attestations.

Timing

On mainnet, the ceremonies currently happen in intervals of 10d. This interval is expected to be prolonged in the future, once the protocol has been tested enough.

On our testnets, the timing may be different and may change over time to allow for different test setups or public demos.

Ceremony Phase Timing

Encointer Personhood Reputation

Successful attendance at Encointer ceremonies gives you personhood reputation.

The more frequently you attend ceremonies, the higher your reputation.

Reputation Lifetime

Reputation has limited lifetime, currently set to 5 ceremonies on mainnet. The reasoning is that personhood reputation should not benefit early adopters as they are not more human than late adopers. The upside is also that identity loss has limited impact. You just start all over with a new account in case you lost your phone and did not backup your account.

Reputation Ratio

We refer to reputation as number of attended ceremonies during the last N ceremonies, i.e. 3/5 will prove that you are not maintaining 2 or more accounts with that reputation, because you can only attend one meetup per ceremony.

User Journey

Newbie

Usually, you will start with zero reputation as a newbie. You will need a tiny bit of your community's currency from someone else in your community or around 0.001 KSM (for Encointer Mainnet) to get started. You may register for a ceremony, but your assignment is not guaranteed because our threat model assumes an honest majority. As anyone can register as a newbie, we need to limit the number of newbies per meetup.

Endorsement

If you know the bootstrappers of your community currency, you can ask them for an endorsement. They can endorse you as a trusted contact and you get a guaranteed assignment for the upcoming ceremony.

Reputable

Once you have attended at least one ceremony successfully, your status is reputable and as long as you attend at least one ceremony within the reputation lifetime you will always have a guaranteed assignemnt as long as there are enough other participants.

No-Show Punishment

Every time you register as reputable, you actually spend you reputation on your guaranteed slot. If you successfully attend the ceremony, you'll get a fresh repuatation. However, if you do not show up although you have registered, your reputation will not refresh and you fall back to newbie status.

Spent reputation still counts for your reputation ratio, but you can't use it again to register for a ceremony.

Bootstrappers

Bootstrappers are the first few pre-defined participants in the first ceremony of a community. They build the trusted setup as they are the ones who initate a new community.

The bootstrapper status is immortal. Bootstrappers are always guaranteed an assignment if they register in time, irrespective of their recent reputation. The reasoning for this is that the entire community relies on the trusted setup and their special status allows a community to recover in case of an interruption or failure of an entire ceremony.

Bootstrappers are also granted the right to endorse newbies to accelerate community growth based on interpersonal trust. Bootstrappers should only endorse people who they have met physically in their community area and should not rely on some online message asking them for endorsement.

Community Identifiers

Community Identifiers are a short string identifying a particular community. The format is based on a geohash of the community's location combined with a hash of the list of all bootstrapper accounts.

Example: The Leu.Zuerich community has the cid u0qj9QqA2Q

js api

Unfortunatrely, Polkadot js/apps does not support our cid type natively, so the above example appears as

  {
    geohash: u0qj9
    digest: 0x1012ea85
  }

If you'd like to use javascript, please consider using our npm library encointer-js which adds support for all our types

Democracy V0.1

Democracy is live on mainnet since runtime 1003003

The democracy module brings decentralized governance to Encointer, facilitating participants to take decisions. Such a universal human suffrage (one person one vote) governance shall render the current Encointer council or any other centralized body obsolete. Examples of such decisions are the addition of new meetup locations to a community, an adjustment of the Demurrage rate or changes in the ceremony schedule.

The decision-making process should follow the subsidiarity principle, meaning that decisions should be taken on the lowest possible level by the individuals affect by it. For example, if a community wants to extend their region by adding some new meetup locations, only community members should be allowed to participate in the vote.

Proposals

There is a set of predefined proposal actions that can be proposed and voted on. Everyone can start a proposal on any action (ie. set basic income to 48 LEU) at any time. There can even be multiple proposals ongoing in parallel.

Every member of the community can use their personhood reputation to vote on each proposal. A proposal gets approved if it has enough Aye votes continuously for a long enough time period.

Practical Examples

Let's assume a proposal has been submitted at the end of the last registering phase. During the first day, the proposal doesn't reach the minimal turnout yet, but on day two it enters the passing state and the confirmation period starts. More people make up their mind and vote Nay, so the proposal drops out of confirming state before the end of the confirmation period. Over time, more Aye votes are coming in and the approval threshold is surpassed. This time, the proposal stays in the passing state during the entire confirmation period gets approved. Any community member can call the lazy evaluation and the proposal action will be scheduled for enaction at the start of the upcoming registering phase.

lifetime approved

Another example shows a proposal with insufficient approval. After an initial boost, it stays in the failing state until the the end of its lifetime. Any community member can request lazy evaluation and the proposal will be cancelled.

lifetime rejected

Voting

Eligible Reputations

Each successful cycle attendance for a set of eligible cycles gives you one vote. We currently allow only reputations older than the previous cycle but younger than the reputation lifetime (relative to proposal submission) to participate in the vote. This is because the count of those reputations is not subject to change anymore. We need a reliable count of all eligible reputations in order to determine the maximum amount of possible votes (the electorate), which is required for Adaptive Quorum Biasing (AQB) and to determine the minimum turnout.

electorate

Your own voting power depends on the number of cycles you have attended during the eligible period. The more cycles you have attended during this period, the more voting power you have. This is a sybil-resilient approximation of universal suffrage which rewards your dedication to participate in community cycles regularly. Thanks to the reputation lifetime, however, there is no undue bias towards longtime community members as only recent reputation is eligible for voting.

Adaptive Quorum Biasing (AQB) and Minimum Approval

In order to determine if a proposal is passing, we use positive turnout bias. The approval threshold follows the formula: \(thrs = \frac{1}{1+\sqrt{turnout}}\) where \(turnout \in [0, 1]\) and \(thrs \in [0, 1]\)

In addition we enforce a minimum turnout of 5%.

The goal of AQB is to ensure proposals can be approved even if turnout is low. Especially noncontroversial proposals may suffer from low turnout as they fail to mobilize the crowd. However, low turnout should require a higher approval rate to pass.

AQB

The blue trace depicts a possible turnout over time. It can be expected that the initiators of a proposal will immediately vote Aye, leading to very high approval at start. Nevertheless, as long as less than 5% of the elecorate have cast their vote, the proposal is in failing state. Over time, more people will make up their mind and the proposal may flip between passing and failing state several times before eventually staying in the passing state for the confirmation period. The end of the confirmation period is depicted by the blue dot.

Tutorial

For a tutorial about hands-on testing the democracy module, please see the Democracy Tutorial

Deep Dive

Scope of Democracy

This section describes the powers of Encointer's onchain democracy (post-V0.1) and at what level decisions are to be made.

Protocol Changes

Changes to the Encointer protocol are out of scope because they need to be decided by Kusama Relay-Chain Governance as Encointer is a common good parachain. Upgrades to the Encointer Protocol must pass a public referendum on Kusama, where KSM token holders decide.

For a vision of how Encointer could execute global democratic protocol governance in the future, we refer to this research blog post

Global Actions

These actions can only be decided upon by the quorum of all encointer communities globally

Community Actions

These actions can be decided per community for themselves

Petitions

Petitions are votes on matters that cannot automatically be enforced by the Encointer protocol. Therefore, they are non-binding for the network. They can have global or local scope. Petitions can be used to signal the network or community leaders about the will of the community.

Detailed Proposal States and Lifetime

Let's look a bit closer at more complex cases:

There can be multiple proposals up for vote simultaneously, even on the same action

When a proposal gets approved, all other proposals on the same action get cancelled, to avoid conflicts

When a proposal A gets approved, its enactment will be scheduled to the beginning of the next ceremony cycle.

Proposal state machine

Proposal Lifetime

The following examples will describe examples of how proposals change their state over time based on a changing number of votes and on other proposals.

Let

  • Confirmation Period = 3 units,
  • Proposal Lifetime = 12 units,
  • X/Y denote X aye votes and Y total votes,
  • O = Ongoing,
  • C = Confirming,
  • A = Approved,
  • X = Cancelled.

For the sake of simplicity, we assume that just a simple majority is needed for a proposal to pass and there is no minimum vote required.

In the case of multiple proposals, all proposals shall be of the same action.

Democracy Voting

Threat Model

Actor Profiles

We categorize users into the following psychological profiles for later scenario analysis:

Honest

Will comply with the rules

Greedy

Will try to cheat the system for his/her own benefit. Will collude with others

Strategies:

  • Get reward without showing up
  • Sign sybil id's to collect more rewards

Saboteur

Will try to hurt the system, even if this comes at a cost. Will collude with others

Strategies:

  • turn meetups invalid
  • demoralize other participants by preventing them to get reward

More Roles

Sybil

An identity that has no bijectively exclusive relationship with a participant. It can however have a bijectively exclusive relationship with a person who doesn't attend any meetup.

Manipulable

An honest person that can be convinced to break the rules by social pressure. Will not strive for economic benefit.

Collusion Organizations

evil.corp

An organization of the greedy or saboteur participants.

Strategies:

  • undermining randomization by sharing information and key pairs to allow collusion attacks at meetups

Assumptions

We assume

  1. The majority of ceremony participants with reputation sending their signed claims to the blockchain location is honest.

Reputation here means having attended at least one of the last two ceremonies and having been rewarded.

Rule Design

When designing rules there's a tradeoff beween preventing either the greedy or the saboteur's success. We can introduce very restrictive rules that will successfully prevent sybil attacks by the greedy, but these will make it very easy for the saboteur to demoralize participants by turning meetups invalid deliberately.

Rules

TODO: This is work in progress....

Meetup Assignment

  1. A meetup has at least 3 assigned participants
  2. A meetup has at most 12 assigned participants
  3. Only 1/4 of assigned participants may have zero reputation (be newcomers)
    • this rule directly impacts the maximum adoption rate. A population of 1M will take at least log(1M/12)/log(4/3) <= 40 ceremonies

Meetup validation

  1. (NEEDED?) The signature reciprocity is at least X
  2. (NEEDED?) The reciprocal edge connectedness is at least M-2, where M is the number of participants with at least one signature by another party.
  3. (OK) At least two participants signed each other mutually
  4. (OK) Disqualify a participant if her vote is not equal to the number of participants signed by her.

UBI/Reward Issuance

In order to receive a UBI, a participant

  1. (OK) must be registered and assigned to the meetup
  2. (OK) the meetup must be valid
  3. (TODO: ARGUE THRESHOLD) must have her claim signed by at least 1/3 of registered participants
  4. (OK) must have signed the participants that are necessary to fulfill rule above in return

Remote Attacks

Flooding Attack

An adversary could register large numbers of fake participants who will never show up. This could prevent legit persons to participate.

Mitigation:

  • Limit the number of assigned participants with no reputation

Non-Protocol Threats

Aggression, Detention

If meetup locations are publicly known, participants could face aggression from saboteurs or they could be detained if participation is suddenly judged illegal.

Mitigation:

  • The set of possible meetup locations has to be significantly larger than the need in order to host all participants.

Abduction

If celebrity meetup participants can be linked to their names and meetup locations in advance, they might get kidnapped

Mitigation:

  • Make sure meetup assignments are kept confidential at least until the meetup has passed.

Behavioural Meetup Scenario Analysis

The scenario analysis is structured by the number of participants who were assigned to a meetup

3 Registered Participants

Happy Flow

All participants only sign for persons present at meetup location.

reciprocity = 1.0
reciprocal edge connectedness = 2

Noshow of one is treated with mercy for attendees

reciprocity = 1.0
reciprocal edge connectedness = 1

Attacks

Social Engineering

Adversary B talks A into signing his sybil ID

reciprocity = 1.0
reciprocal edge connectedness = 2

As there is no honest participant in this meetup, this attack is out of scope of our threat model.

Mitigation

  • randomized meetups should reduce the chance that someone could be assigned with his sybil to the same meetup. In weakly populated areas, this can happen easily though

this scenario violates threat model assumptions

Exclusion

Adversary B refuses to sign A and signs C instead

A variant of this would be that B isn't even present at the meetup

reciprocity = 0.5 (1.0)
reciprocal edge connectedness = 1

Mitigation none

  • randomized meetups should reduce the chance that someone could be assigned with his sybil to the same meetup. In weakly populated areas, this can happen easily though. evil.corp could also increase chances.
  • Only allow meetups with more participants (>=4?) in order to reduce the impact of a single participant on outcome.

this scenario violates threat model assumptions

4 Registered Participants

Oversigning

Variant:

  • B and C are not present at meetup, removing the reciprocal edges to A
reciprocity = 1.0
reciprocal edge connectedness = 2

Mitigation:

  1. (NOK) Introduce Reputation (previous attendance to successful meetups)
  2. (NOK) Introduce Rule "lowest vote with reputation wins" * This rule, however, will cause B, C, and D to vote "3" showups and to refuse to sign A. Reputation doesn't help because B and C could have reputation as well.
  3. (NEEDED?) quarantine non-consistent meetups

At this meetup, 3/4 of registered participants are malicious.

this scenario violates threat model assumptions

Oversigning light

reciprocity = 1.0
reciprocal edge connectedness = 1

Mitigation

  • only accept subgraph with recipr. edge connectedness of M-2 for M=4 here. This will cut off D.

Location Spoofing

C and D could pretend to be at the meetup location. The ceremony validation has no way to know if A-B is legit or C-D.

Variants:

  • D could be a real person colluding with C

Probability:

  • low because of randomization if number of meetups assigned is high
    • evil.corp could redistribute sybil id's after meeting assignments, undermining randomization

Mitigation:

  1. (NOK) track participant locations and require plausible movement trajectories before meetup. not sound because it is easy for C+D to spoof realistic trajectories
  2. (NEEDED?) Quarantine: The validator can detect that the meetup is split and therefore not consistent. Issuance could be conditional to future ceremony attendance
  3. (OK) The pair with higher reputation wins, the other doesn't get a reward issued.
  4. (NOK) invalidate non-consistent meetups, preventing 2 illegit rewards while demoralizing 2 honest participants.

At this meetup, 1/2 of registered participants are malicious.

5 Registered Participants

Mitigation:

  • Disqualify participant if vote != number of peers she signed

Mitigation:

  • none, if C,E,D all have reputation. the majority can always win.

This violates threat model assumption 1

Conclusion

As long as the threat model assumptions are held, we can find a set of rules that prevents:

  • issuing more rewards than there are honest participants (while there is no guarantee that every honest participant will get a reward in face of malicious behaviour)

The probability that you as a participant experience a meetup with evil majority follows the poisson cumulative distribution function:

Given the overall proportion of malicious actors , the probability that you (being an honest actor) will suffer from malicious behaviour at one specific meetup depending on the number of participants in your meetup n is

code

Decentralization

Decentralization can mean very different things and is never black and white but rather a goal that can never be fully achieved. Encointer aims at

  • architectural decentralization: avoid a single point of failure through redundancy (different machines in different geographic locations)
  • political decentralization: distribute control among many individuals and organizations
  • logical decentralization: ensure that the system can continue to exist if it is divided into arbitrary subgroups

The first two are common for blockchains. Logical decentralization, however, isn't a feature of global blockchains. There may only be one truth globally. Encointer, on the other hand, can be split into its shards of local communities and continue to exist - with restrictions on finality and interoperability. This way, Encointer could even continue to exist in countries that eclipse their citizens from the internet or selective parts of it. At least temporarily.

Over all, resilience is what we aim for.

Blockchain

Why does Encointer need a blockchain? All the economic aspects could be implemented with a central server as well.

We develop the Encointer software with altruistic intentions. Still, Encointer may likely be judged as unlawful in certain juristictions and repression may follow. If a trusted entity would operate Encointer as a service, that system would be very vulnerable to states or other economically powerful entities.

P2P systems, including blockchains, have proven to be very resilient versus state intervention.

Consensus and Security

On Blockchains, code is law. This law needs to be secured against malicious attacks. While the security of the bitcoin blockchain is measured in mining hashpower, the security of PoS chains like Polkadot is measured in staked capital. Both approaches boild down to the simple rule: the "biggest" blockchain is the most secure.

As Encointer is no business case or speculative asset by design, it needs to rely on other things than capital or hashpower for security of consensus.

Thanks to its proof-of-personhood, Encointer could apply democratic consensus like described in PoPcoin. However, a web of trust would have to be established first.

Polkadot is a heterogeneous multi-chain system with shared security. While this approach reduces the amount of capital Encointer would have to bind for equal security, it still is a profoundly capitalistic system and competition around parachain slots may make it impossible for Encointer to become a Polkadot parachain.

While the final solution is yet to be discovered, Encointer will start off as a proof-of-authority (PoA) chain which is initially operated by trusted entities. The worker registry, however, will be permissionless. Anyone with a suitable TEE will be able to operate workers for communities of their choice.

Once possible, Encointer will attempt to become a parachain of Polakdot or Kusama by means of crowdfunding.

Should this fail, it can still get finality for its PoA consensus by running as a parathread instead.

Governance

Encointer is no static system. It shall evolve over time and different communities shall be able to adjust their local rules independently. Such a foederalistic governance is possible thanks to Encointers' self-sovereign identity (SSI) features. Encointer's proof-of-personhood allows to have democratic voting. Its proof-of-location ensures that people can only vote on matters concerning their local community. This local governance shall rule over the parameters of individual community currencies, such as defining meetup locations, changing the demurrage rate, changing the UBI amount or the name of their currency.

Global governance shall leverage the web-of-trust among communities. Democratic votes are thus weighted with the trust score of each community. Global governance shall decide on updates to the blockchain logic and global parameter such as the ceremony period, the set of trusted TEE manufacturers or the distribution of fees.

Privacy

Encointer protects its users' privacy by design:

  • transfers of local community currencies are private by default. No one learns who sends how much to whom.
  • account balances of local community currencies are private (while aggregated values such as a community's total issuance and turnover are public)
  • ceremony meetup assignments are processed confidentially because that strenghtens the Encointer protocol by hindering collusion.

Philosophy

Privacy can also be a threat to communities. There is a good reason why most nation states enforce anti money laundering (AML) laws. Encointer aims to follow a simple rule: The smaller the amounts, the higher the privacy should be. And vice versa - the higher the amounts, the higher the transparency should be. This - unfortunately - is pretty much the opposite of what we experience in today's reality as big capital and gains can easily be offshored and obscured while everyday purchases are traced down to the penny.

As encointer is made up of many small communities - none of which will have a significant market capitalization on a global scale - it will never be easy to move great amounts of capital through these local currencies unnoticed. That's why Encointer simply is not an attractive channel for laundering money.

Governance

Subsidiarity

The Encointer Network is governed on multiple levels. The design paradigm is subsidiarity: issues should be dealt with at the most immediate (or local) level that is consistent with their resolution.

Global Protocol Scope

Encointer is a common-good parachain of the Kusama Network. The Kusama Network provides its security to Encointer, but requires that Encointer protocol updates are decided by KSM holders who granted the common-good slot in the first place and have to evaluate if the update is sound and still complies with common-good criteria.

Global Operative Scope

The Encointer protocol defines certain global parameters which are common to all communities. Changing such parameters requires a global decision

Local Community Scope

Each community can decide on parameters that only concern itself. Such parameters are demurrage, nominal income per ceremony and community metadata like Logo, Name

Council

Encointer aims at democratic governance based on one-person-one-vote. However, democracy requires a representative number of users and communities to be meaningful and legitimate. Therefore, governance is delegated to a council until the community deems to be ready for democracy.

The council currently consists of 7 members of the Encointer Association. Each local community may elect a representative which shall join the council.

Powers of Council

The council currently governs the Global Operative Scope and the Local Community Scope. Through propsals, it can execute the following actions:

In the beginning, onboarding of new communites will be permissioned, subject to the council's approval. The team sees no other way to avoid bot communities squatting the earth's surface. Over time, a web-of-trust will build and new communities can be onboarded by endorsement of other communites.

Testnets

Encointer maintains two testnets: Gesell and Cantillon.

The networks differ in their goals and designs:

Gesell

Aimed at automated testing of the protocol and our mobile phone app.

  • Time-warping allows to script bot populations and hold ceremonies every 30min.
  • Complete transparency of all registries and balances. Everything happens on-chain.
  • experimenting with real ceremony meetups, physically meeting people.

Cantillon

The main purpose of Cantillon is privacy enhancement through Trusted Execution environments (with enclaves still in development mode, so privacy is not guaranteed before we move to production mode)

Watch our demo video on bootstrapping a bot community

Outlook on Mainnet

The mainnet is planned to become a parachain of Kusama, the canary network of Polkadot. The chain security will depend on Kusama relay chain.

Time Warping for Testnets

In order to understand the different timing on our networks, we offer the following figure:

Phase Timing

  • Temporarily, we will apply 30min ceremony cycle to both Gesell and Cantillon*

Testnet Gesell

Gesell is our first testnet. It allows you to bootstrap new local currencies and perform regular proof-of-personhood ceremonies that give participants a universal basic income. This network is meant for testing with bot populations in order to audit and stress-test the protocol. Gesell does not give you the privacy that later networks will provide. We do not expect real physical meetups to happen on this network except occasional demo meetups.

Design

Gesell is based on substrate and its nodes consist of four pallets

Gesell

Scheduler

Keeps track of time and maintains the ceremony state-machine phase changes.

Currencies

Registry for all local currencies with their properties and meetup locations

Balances

The individual's account balances in all currencies, featuring demurrage.

Ceremonies

Where participants register for ceremonies. Assignment of meetups and issuance of UBI upon proof-of-personhood.

Testnet Cantillon

** DISCONTINUED **

Cantillon was the testnet to showcase the privacy features using trusted execution environments with Integritee technology

It is still on our roadmap to include these features, but currently, the focus lies on running a common good parachain on Kusama

Design

Cantillon uses the same pallets as Gesell, but the privacy-sensitive ones will be executed off-chain, inside a trusted execution environment (TEE). SubstraTEE will be the framework that isolates sensitive information inside Intel SGX enclaves (Alternative TEE technologies are being evaluated)

Cantillon

Encointer Kusama Parachain

Encointer's productive mainnet is planned run as a common good parachain on Kusama.

More info coming...

Bazaar

What is a local currency without the possibility to spend it on desired goods and services? How can you find businesses that accept the local Encointer currency? Encointer features a builtin classifieds system for advertizing businesses and offerings we call bazaar.

Anyone can register businesses and offerings to be advertized within their local community. All metadata and images for classifieds are stored on ipfs. The ownership of classifieds is registered on the Encointer blockchain.

Vouchers

Every business may issue their own transferrable vouchers and can therefore issue their own loyalty money or acquire loans from the community. As businesses are owned by real people whose digital personhood has been attested at Encointer ceremonies, these vouchers come with a sybil-defense and the credit rating of businesses is immutably recorded.

Encointer Wallet App

The Encointer app is all that users need to participate in a local community. It serves as a wallet and lets you participate in Encointer ceremonies.

Install

Android

Get it on F-Droid

Get it on Google Play

iOS

Download on the App Store

Feature Phones: KaiOS

Feature phone support planned in the future

Dumb Phones: USSD

For the most simple category of phones we plan support in the future by using a USSD gateway

Usage

Our preliminary instructions:

Acknowledgements

Encointer Wallet is based on previous work by polkawallet.io

Select Community

This section shows you how to select a community on a specific network.

Select Network

By default, the Encointer Wallet App connects to mainnet on Kusama. This is fine for most users and you likely can skip this section. In order to test on our Testnets, you'll need to configure the app to use another network endpoint.

  1. Enable developer mode: Profile -> tick developer mode checkbox
  2. Tap "Change Network: nctr-k"
  3. In the left column, tap the desired network:
  • NCTR-GSL: Testnet Gesell
  • NCTR-R: Testnet Lietaer on Rococo
  • NCTR-K: Mainnet on Kusama
  • NCTR-GSL-DEV: Local solochain using ws://10.0.2.2:9944 for an emulator setup
  1. Tap on one of your account names (not the identicon)
  2. Wait until you see a green tick besides (current: nctr-gsl) on the profile page
  3. Disable developer mode

Select Community

Once your app is connected to the right network where you registered your new community, you can now switch the app to your community:

  1. On the top of the home screen, tap the community symbol with your account identicon
  2. Switch Community -> (+) Add community
  3. On the world map, browse for your community and tap the pin
  4. tap again the popped-up name of your community

Register for a ceremony

Assuming you have previously

  1. installed the Encointer Wallet app
  2. selected you community

you can now check when the next ceremony will take place. If you would like to attend the upcoming ceremony, you can tap the register button. You will need a tiny bit of inital funding to pay transaction fees. Either you get community currency from someone in your community, or you get KSM, the native token of the Encointer mainnet on Kusama.

According to the ceremony cycle you will have to await the assigning phase until the app shows you if you have been assigned and when you have to be in which location.

On the day of the meetup, be on time at the right location and perform a ceremony meetup with your fellow attendees you will hopefully encounter there.

Perfrom a Ceremony Meetup

Assuming you have previously

  1. installed the Encointer Wallet app
  2. selected you community
  3. Registered for the current ceremony
  4. You have been assigned to a meetup
  5. You are now physically on time in the right location together with a few fellow ceremony attendees

Voting

The meetup starts with tapping the button "start meetup" on the Encointer Wallet app home screen. As a first human confirmation, you'll have to vote on how many attendees are present, including yourself.

Once everyone has voted, no further attendees can join. If the group decides to include a latecomer, the entire meetup has to be started from the beginning.

Attesting Personhood

After voting on the number of attendees, your app shows a QR code which is your claim of attendance which has to be signed by everyone else to prove your personhood and attendance.

Procedure

The following procedure is just a suggestion, but has shown to cause minimal duration and confusion.

  1. The group of attendees forms a C-shape and everyone holds the phone upright with the QR code screen facing to the center to minimize reflections from the sky or the sun
  2. The person at one end of the C shape starts scanning on after the other and when finished, waits at the other end of the C-shape showing her QR code.
  3. As soon as the scanning person has successfully scanned the first two attendees, the next outermost attendee can start scanning, but should not overtake the previous scanner
  4. as soon as everyone has scanned everyone (i.e. scanned 8/8 if the vote was 9 attendees), the meetup can be closed

Closing the meetup should only be done after confirming that all attendees have scanned everyone. After closing the meetup, the app suggests to submit attestations. If you are online, you can directly submit the attestations and ensure you get notified of success. Should you not have internet connection at the time, you can still submit within the following 24h.

Reward Issuance

Ceremony rewards, (AKA community issued income, CII) can be claimed for each performed meetup. The amount of CII is defined per community.

Your Encointer Wallet app will claim automatically as soon as possible, but you can trigger the process manually.

Immediate Claim

If all attendees are online and were able to submit their attestations, the rewards can be claimed immediately, under the condition that the majority of assignees has show up and has been attested.

Late Claim

Should the above not be the case, attendees have to await the beginning of the registering phase before claiming their CII.

Social Contract

It is up to every community to define what they understand as puntuality and as human.

Each community is just as strong as their social contract compliance. If you allow latecomers, you may risk to allow them to attend two different meetups and claim a community issued income twice. Same if you allow an attendee to bring and use two or more phones because their friend alledgedly is sick or otherwise incapable of attending. We suggest to apply rather stric rules as this strengthens the trust in your community by its members - and also by members of other communities globally.

The Encointer protocol has no notion of personhood itself. We expect communities to attribute personhood to all humans, irrespective of age, gender, race, citizenship, sexual identity and preferences, social status, criminal history or any other attributes of identity.

Explorer

The explorer is a Web UI tool to visualize chain data such as the communities and bootstrappers, the phases and ceremonies around the world. A working example can be visited at explorer.encointer.org.

Checkout the explorer repository.
In the terminal, go to the the root directory of the repo and enter:

git clone https://github.com/encointer/explorer
cd explorer
yarn install
yarn start

Then you should be able to view the explorer in your browser at http://localhost:8000/.
At the bottom, the registered chain is displayed. You can click on it and change between the local and remote chain. You can also set the rpc address via the query paramter, for example:
localhost:8000?rpc=ws://127.0.0.1:9945 will connect to the chain on localhost with port 9945.
The registered community should be visible in the explorer.

Basic CLI usage

The Encointer CLI is a low-level tool to interact with an Encointer chain. It allows to query state and to send extrinsics.

Setup

We suggest you run the following in an Ubuntu 22.04 environment

Download the CLI for our latest release:

wget https://github.com/encointer/encointer-node/releases/latest/download/encointer-client-notee
chmod +x encointer-client-notee

# Testnet Gesell node endpoint
NURL=wss://gesell.encointer.org
NPORT=443
alias nctr-gsl="./encointer-client-notee -u $NURL -p $NPORT"

# Testnet Lietaer (on Rococo) node endpoint
NURL=wss://rococo.api.encointer.org
NPORT=443
alias nctr-r="./encointer-client-notee -u $NURL -p $NPORT"

# Encointer Mainnet (on Kusama) endpoint
NURL=wss://kusama.api.encointer.org
NPORT=443
alias nctr-k="./encointer-client-notee -u $NURL -p $NPORT"

# local dev node
alias nctr-dev="./encointer-client-notee"

In the following, we will show usage with testnet Gesell, using our alias nctr-gsl. But You can use any of the aliases above to interact with the other chains in the same way (caveat: deployed versions of the CLI API can vary)

Get Ceremony Phase

nctr-gsl get-phase

This will return any of

  • Registering: you can register participants, communities, locations
  • Assigning: ceremony meetup assignments can be queried
  • Attesting: ceremony meetups can be performed

List Communities

nctr-gsl list-communities

will yield something like

number of communities:  5
e5dvt5mjcem: bot-tugs locations: 9
u0qj94fxxJ6: EdisonPaula locations: 3
srcq45PYNyD: Adriana locations: 5
u33e0719fDB: Decoded Berlin locations: 3
69y7j4ZEXmy: Decoded Buenos Aires locations: 8

Each community is shown with

  • its community identifier (cid) which is a 11-character string
  • its Name, given by community lead
  • its number of ceremony meetup locations

You can also explore communities for our different networks using our explorer

Manage Account Keystore

The CLI offers very basic wallet functionality, managing a keystore in a local subfolder my_keystore where account secrets are stored in plaintext. Do not use in production!

Create a New Account

nctr-gsl new-account

The printed result will be your new account address

List Accounts in Keystore

nctr-gsl list-accounts

Query Account Balances

nctr-gsl balance 5CSLXnYZQeVDvNmanYEJn4YXXhgFLKYwp2f216NsDehR8mVU

you can add a cid to query the balance for a specific community

nctr-gsl balance 5ChwkE8kd2qagyiCikP2Ns2T6vWh7dbURx54gXcPKw8NotNp --cid srcq45PYNyD

or get all balances (first, the native token balance, then all community balances)

nctr-gsl balance 5ChwkE8kd2qagyiCikP2Ns2T6vWh7dbURx54gXcPKw8NotNp --all

Faucet

Testnet Gesell features a faucet, so you can pre-fund your new account

nctr-gsl faucet <Account>

How to Register an Encointer Community (manually)

We assume you have set up the CLI client previously

This tutorial will guide you through the process of setting up a new community on any of our networks

If you haven't done so, please learn about the ceremony cycle of the Encointer Protocol

Set Up Bootstrappers

As Encointer is all about proof of personhood, you will need people to get started. We suggest to pick 10 diverse, dependable and trustworthy members of your community for a trusted setup. This first group of people performing the very first ceremony of a new community we call Bootstrappers.

If you want to test all by yourself, we suggest you create 3 bootstrapper accounts using 3 phones and register your community on Testnet Gesell. In the following, we will assume you're just testing yourself, but the process is very similar if the accounts are for real bootstrappers.

All the bootstrappers need to install the mobile app and set up a new account. You can then collect all the bootstrapper accounts by sharing them from within the app by going to profile -> tap account -> share account -> send link

The bootstrapper accounts need initial funding. On our testnets, you can use the faucet, on Mainnet, you can supply KSM or any other existing community currency

nctr-gsl faucet 5D5V3couq7o42FYkLG4vVhaqQPrfk4NT3kWzZJH66ZeHr3iG 5HB4kbo67Hgv846DNMRnt7i1xNMum66LLBFkqtghKsNwRknM 5GxWKwbrPL88uH3Zv7zAiz6ozdpSFHzSfK1aXhVxDcNQYU8t

Note: the displayed account addresses will differ from yours when you follow the tutorial. They are just provided for readabiltiy. Use your account addresses instead of the ones used in the tutorial.

To register a community, you need to create a specfile.json containing details about the community and an account with funds to the chain client.

Define Ceremony Meetup Locations

We need to define in what region the community shall be issued. For this we use the geojson standard to define a set of meetup places and add some meta-information about the community. You can use geojson.io to select meetup places on a map (define a few "Points"). Make sure that you select places that are >100m apart. You also need to keep this minimal distance from other registered communities.

If you want to be sure which location will be the bootstrapping location, please specify only a single location and register more locations after the bootstrapping ceremony.

The number of locations that you should define depends on the size of the population N you'd like to bootstrap. As a rule of thumb, there should be at least N/12 locations but the more locations, the better.

Specfile

The specfile defines the set of bootstrappers, the initial set of ceremony locations as well as metadata like name, symbol and icons stored on IPFS.

An example of the specfile.json is shown below with one meetup locations:

{
  "type": "FeatureCollection",
  "community": {
    "meta": {
      "name": "Mediterranea",
      "symbol": "MTA",
      "assets": "QmVmew4gZHyCK2Fv4UBgsvfLdf1Q6UiF9MD6wsfPCuNVQp",
      "url": "",
      "announcementSigner": null,
      "rules": "loCoFlex"
    },
    "bootstrappers": [
      "5D5V3couq7o42FYkLG4vVhaqQPrfk4NT3kWzZJH66ZeHr3iG",
      "5HB4kbo67Hgv846DNMRnt7i1xNMum66LLBFkqtghKsNwRknM",
      "5GxWKwbrPL88uH3Zv7zAiz6ozdpSFHzSfK1aXhVxDcNQYU8t"
    ],
    "demurrage_halving_blocks": 2628000,
    "ceremony_income": 100
  },
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [
          -28.102619,
          31.141935
        ]
      },
      "properties": {}
    }
  ]
}
  • replace the account addresses in "bootstrappers" with the ones you have created and add additional meetup locations.
  • demurrage_halving_blocks of 2'628'000 corresponds to 1 year if block time is 12 seconds
  • ceremony_income in this example is set to 100.00 MTA

ADVANCED

ceremony income and demurrage rate are stored as a fixpoint type (I64F64 - or 64 signed integer bits before the decimal point and 64 bit thereafter). That is why the raw numbers in js/apps can be confusing. An income of 100.00 MTA will be represented as

>>> 100*2**64
1844674407370955161600

demurrage halving blocks will first be translated to an exponential function coefficient:

>>> int(-1*np.log(0.5)*2**64/2628000)
4865414248555

Applying demmurage of one block then becomes: balance * exp(-demurrage_rate). In the case of a balance of 100.0 demurrage for one block would decrease the balance to

>>> 100.0*np.exp(-1*4865414248555/2**64)
99.99997362453999

explanatory code is provided in python syntax

Use Your Own Community Icon

The example specfile features a dummy icon. You may want to brand your community with its own icon. You'll need a circular icon in SVG format.

Place your icon into its own folder, i.e. ./leu.rococo/community-icon.svg

Make sure your SVG community icon doesn't include <style> attributes

cargo install svgcleaner
svgcleaner community_icon.svg community_icon.svg

Upload the entire folder to ipfs:

  1. using your own ipfs server
ipfs add -rw --pin ./leu.rococo
  1. using infura's client:
ipfs-upload-client --id <your infura id> --secret <your infura secret> --pin ./leu.rococo 

test if you can fetch the cid through the encointer gateway which will be used by the app

wget http://ipfs.encointer.org:8080/api/v0/object/get?arg=QmXydp7gdTGwxkCn24vEtvtSXbR7wSAGBDLQpc8buF6T92/community_icon.svg

It may take a while to sync from the server you used for uploading and pinning. IPFS routing isn't very reliable nor fast yet, unfortunately.

Once you can fetch your icon, replace the IPFS cid in the community specfile with the cid of your icon folder

Register your new community

Register your new community with the specfile.json. Signer should be an account in your keystore which is able to pay fees:

caveat: The following step is possible to perform by anyone on out testnet Gesell. But on our mainnet you'll need to pass our onboarding process to be able to register your new community

nctr-dev new-community specfile.json --signer 5D5V3couq7o42FYkLG4vVhaqQPrfk4NT3kWzZJH66ZeHr3iG

Your community has been registered and the return value is your community-identifier (cid). Let's check the registry again:

nctr-dev list-communities

Congratulations! You are ready to select your community in the Encointer Wallet app perform your first Ceremony with your bootstrappers.

Perform a Testnet Cycle

This tutorial takes you through the process of performing a cycle using the CLI (without mobile app) on our testnet Gesell. If you'd like to test the same using the app, please see Perform a cycle meetup (with app). This tutorial can be performed as a a single person, as we will use bot accounts. The tutorial will take an entire cycle, ~30min on Gesell.

We assume you already have

Throughout this tutorial, we will use the Adriana community with cid srcq45PYNyD. Among its bootstrappers, we will work with 3 accounts: 5F77sGnUhpjdFnzruhurGZgqPFtvdECXTGgX4Bgy2zGavbEw, 5FyWbcwN1TGPdyzRzoEeem3MUcc7jXRs7ZoftZkAQLV47nS7, 5CMVLJCC4Jn7QmLsFRkLWkm2w4LJswpZo1V2nd1tp64iVnCR

Your cid and bootstrapper accounts will differ.

Import Test Accounts

In order to give the CLI access to your test bootstrapper accounts, please import them into the local keystore (unencrypted! don't use in production). If this is the first cycle for your community, you can only use bootstrapper accounts.

nctr-gsl new-account "<mnemonic 12 words>”
nctr-gsl list-accounts

Register Participants

Registering participants can only happen during Registering phase. You may have to wait max 20 min for the next Registering phase on Gesell.

nctr-gsl get-phase

nctr-gsl register-participant 5F77sGnUhpjdFnzruhurGZgqPFtvdECXTGgX4Bgy2zGavbEw --cid srcq45PYNyD
nctr-gsl register-participant 5FyWbcwN1TGPdyzRzoEeem3MUcc7jXRs7ZoftZkAQLV47nS7 --cid srcq45PYNyD
nctr-gsl register-participant 5CMVLJCC4Jn7QmLsFRkLWkm2w4LJswpZo1V2nd1tp64iVnCR --cid srcq45PYNyD
nctr-gsl list-participants --cid srcq45PYNyD

The last command should confirm your 3 accounts have been registered. As the testnet is public and participation is unpermissioned, it could happen that someone else has registered as well.

Check Assignments

As soon as the phase changed to Assigning, you can verify that your accounts have been assigned:

nctr-gsl list-meetups --cid srcq45PYNyD

Perform Cycle Gathering

As soon as the phase changed to Attesting, we can move on. This is the moment where we pretend to be 3 different people who gather at the right time in the right location as assigned by the protocol and attest each others' personhood.

nctr-gsl attest-attendees 5F77sGnUhpjdFnzruhurGZgqPFtvdECXTGgX4Bgy2zGavbEw 5FyWbcwN1TGPdyzRzoEeem3MUcc7jXRs7ZoftZkAQLV47nS7 5CMVLJCC4Jn7QmLsFRkLWkm2w4LJswpZo1V2nd1tp64iVnCR --cid srcq45PYNyD
nctr-gsl attest-attendees 5FyWbcwN1TGPdyzRzoEeem3MUcc7jXRs7ZoftZkAQLV47nS7 5CMVLJCC4Jn7QmLsFRkLWkm2w4LJswpZo1V2nd1tp64iVnCR 5F77sGnUhpjdFnzruhurGZgqPFtvdECXTGgX4Bgy2zGavbEw --cid srcq45PYNyD
nctr-gsl attest-attendees 5CMVLJCC4Jn7QmLsFRkLWkm2w4LJswpZo1V2nd1tp64iVnCR 5F77sGnUhpjdFnzruhurGZgqPFtvdECXTGgX4Bgy2zGavbEw 5FyWbcwN1TGPdyzRzoEeem3MUcc7jXRs7ZoftZkAQLV47nS7 --cid srcq45PYNyD
# verify attestations after next block
nctr-gsl list-attestees --cid srcq45PYNyD

Claim Rewards

If the majority of assigned participants submitted attestations, you can already claim during Attesting phase, right after the gathering happened. Should only a minority have attended, you need to wait for the next Registering phase before you can claim.

Any participant assigned to the same gathering can trigger reqrd issuance for all attestees

nctr-gsl claim-reward --signer 5F77sGnUhpjdFnzruhurGZgqPFtvdECXTGgX4Bgy2zGavbEw --cid srcq45PYNyD

Has the community income been issued?

nctr-gsl balance 5F77sGnUhpjdFnzruhurGZgqPFtvdECXTGgX4Bgy2zGavbEw  --cid srcq45PYNyD

Verify reputation

nctr-gsl reputation 5F77sGnUhpjdFnzruhurGZgqPFtvdECXTGgX4Bgy2zGavbEw

This command will list one row per cycle attendance with a few details which are out of scope here.

Next Steps

Beyond getting income, reputation can now be used to

Register new meetup locations

Once your community starts to grow, you'll have to make sure there are enough meetup locations. Otherwise less people will be assigned to ceremonies and your community will stall.

As a rule of thumb, you should always have at least one location for every 8 ceremony participants.

selecting locations

Meetup locations should be selected carefully. They should fulfill the following requirements:

accessibility

Locations should be outside and publicly accessible at all times. Also for people in wheelchairs. Moreover, think about how people from around town will travel to a location.

easy discoverability

Landmarks like crossroads, squares or monuments are helpful to discover the location if given just a pin on openstreetmaps

enough space

Imagine 10 people standing in a circle. That's how much space your location should provide without hindering any traffic

medium crowdedness

Don't force people to meet at a very secluded or remote place where no other people would ever go. This could frighten participants who are about to meet other people they don't know yet.

Don't pick very busy locations neither, as this could disturb smooth meetup performance

shelter

In regions where rain is likely, consider picking locations that offer shelter nearby.

Also, shade is a good feature for hot days. Moreover, bright sunlight may degrade QR code scanning performance

identity-shaping

Think about what your community stands for and consider locations that have a meaning

close to acceptance points

What a magic moment if you can attend your first ceremony and spend your income right away in a store nearby!

specify locations

We assume you have set up your environment along basic cli usage. Like you did when registering your community, you can use geojson.io to define a geojson file with all the new locations you'd like to register

Let's define 4 new locations for the Adriana community on Gesell:

newlocations.json

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          13.151750564575195,
          44.67957825832565
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          13.127632141113281,
          44.680249583587546
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          13.127717971801758,
          44.69733524402991
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          13.151750564575195,
          44.69721322146929
        ]
      }
    }
  ]
}

register locations

Registering locations is only possible during the registering phase of the ceremony cycle. Check the current phase with

nctr-gsl get-phase

Register locations with

nctr-gsl add-locations newlocations.json --cid srcq45PYNyD --signer 5D5V3couq7o42FYkLG4vVhaqQPrfk4NT3kWzZJH66ZeHr3iG

You should see encointerCommunities.LocationAdded events for each of your added locations

If you now visit explorer.encointer.org you should see the new locations if you zoom the adriatic sea.

how to add locations on mainnet

On Encointer's production network, no single person is allowed to register new locations. At the current state, Encointer council has to approve new communities and locations

In order to prepare a proposal for council, you can use

nctr-k add-locations newlocations.json --cid u0qj944rhWE  --dryrun

The --dryrun flag will disable sending the extrinsic but will print the encoded call to stdout instead

like this:

0x32020c2800103e017530716a3977f79df70000d0943ad7f8ad2c00000000000000000000000020d9260d000000000000003e017530716a3977f79df700004aa032d624ae2c000000000000000080ffffff7fac200d000000000000003e017530716a3977f79df70000e674039084b22c00000000000000000000000020b2200d000000000000003e017530716a3977f79df70000a68cd0907cb22c00000000000000000000000020d9260d00000000000000cd02

Create vouchers

Vouchers are a nice way to spread your community currency. This tutorial will show you how to create unique QR codes and fund them such that the vouchers can be claimed by anymone using the Encointer Wallet app

We have prepared a very simple python script for you to generate a number of paperwallets and generate QR codes that are understood by the Encointer Wallet app.

setup

wget https://github.com/encointer/encointer-node/blob/master/client/voucher.py
chmod +x voucher.py

pip install pillow qrcode click secrets base58

generate

./voucher.py --network nctr-k --cid u0qj944rhWE --issuer pestalozzi -n 10

this will create a batch of 10 vouchers

generating QR vouchers for batch_token: RtdpYnvFpkz
generating voucher 0: //RtdpYnvFpkz/Cpe3M7ai85cRhcqUk9aJx7x2YZJqjMini
generating voucher 1: //RtdpYnvFpkz/DVXYfVkDPPTdE7pbEUd7ChveApu5ZdoWm
generating voucher 2: //RtdpYnvFpkz/3RiUvgXSvVKCqVuaL49yANm6WdgXn3Xm9
generating voucher 3: //RtdpYnvFpkz/GaVVAgvL7Bn4iPStxe6UeKHFtwitVm4nJ
generating voucher 4: //RtdpYnvFpkz/NRrpFR2sWxzJjHVs86eW67Th8XCfc2xHS
generating voucher 5: //RtdpYnvFpkz/MgKraRVsE2pTMLL5K9TqnUJ4CJ98R3xb5
generating voucher 6: //RtdpYnvFpkz/7sGZntwV5jKXVMcZfWnGKpBdjCKTTDCP
generating voucher 7: //RtdpYnvFpkz/EnU7qpbWjHhYHAr9tSxEhPto6q4wsL7Vv
generating voucher 8: //RtdpYnvFpkz/BiqKLkevGhF7dLC3XjgAJg7iiYLS8uDQa
generating voucher 9: //RtdpYnvFpkz/7TMLTVU6wtBF7EJoJkg3jpuTCv19ktATM

The identifiers of these vouchers are private key seeds. do not share them with anyone!

In your working dir you'll find

voucher-RtdpYnvFpkz-3RiUvgXSvVKCqVuaL49yANm6WdgXn3Xm9.png
voucher-RtdpYnvFpkz-7sGZntwV5jKXVMcZfWnGKpBdjCKTTDCP.png
voucher-RtdpYnvFpkz-7TMLTVU6wtBF7EJoJkg3jpuTCv19ktATM.png
voucher-RtdpYnvFpkz-BiqKLkevGhF7dLC3XjgAJg7iiYLS8uDQa.png
voucher-RtdpYnvFpkz-Cpe3M7ai85cRhcqUk9aJx7x2YZJqjMini.png
voucher-RtdpYnvFpkz-DVXYfVkDPPTdE7pbEUd7ChveApu5ZdoWm.png
voucher-RtdpYnvFpkz-EnU7qpbWjHhYHAr9tSxEhPto6q4wsL7Vv.png
voucher-RtdpYnvFpkz-GaVVAgvL7Bn4iPStxe6UeKHFtwitVm4nJ.png
voucher-RtdpYnvFpkz-MgKraRVsE2pTMLL5K9TqnUJ4CJ98R3xb5.png
voucher-RtdpYnvFpkz-NRrpFR2sWxzJjHVs86eW67Th8XCfc2xHS.png
voucher-RtdpYnvFpkz.secrets

funding

You can fund the vouchers one by one using the mobile app.

  1. select the correct community and sending account in your app
  2. tap "send" on home screen
  3. tap scanner symbol and scan one voucher
  4. send funds

design

You can now design nice vouchers including the QR codes generated.

auto-config

One nice features of these vouchers is that they automatically configure the app with the correct network and community upon scanning the QR code. this is especially helpful if using for demos on testnets

Acceptance Point Setup

In order to accept Encointer community currency (CC) at an outlet, the vendor may set up an account like anyone else. No approval is necessary, anyone can start accepting CC in a matter of minutes.

security

Make sure you backup your account

collect-only setup

Once you have created your store account, it is possible to set up the app as a receiving payment terminal only, such that employees can only collect payments but not transfer funds. If this is what you want, do the following steps on a new device:

  1. Set up at least one default account
  2. Profile -> enable developer mode
  3. Address Book -> (+) add contact
  4. Enter the public address of your store account, like 5EkhjbRksfjG3GjCTveDicmSy2q87eTpNu6fKN8VDAYsKBvk
  5. enter the name of your store, i.e. SuperLocalStore
  6. tick the observation checkbox
  7. save
  8. Profile -> disable developer Mode
  9. Home -> tap logo to select account SuperLocalStore (Observation)
  10. You should now see your store's balance
  11. tap receive and enter amount
  12. your client can now scan the QR code and send funds

QR code for self-service checkout

You can prepare and print QR codes for display. This is useful for self-checkout scenarios where your customers scan and pay without interaction by your personel. Such QR codes act like an unpersonalized invoice, either with a fixed amount or with an undefined amount

The format for QR code payload is:

encointer-invoice
v1.0
<ACCOUNT>>
<CID>
<AMOUNT>
<LABEL>

So, If we have a fixed-price product for 5.0 Leu, we can print a QR code with the following payload:

encointer-invoice
v1.0
5DkVGErvJLPTgec4C73Xk7boEVTKXJYDuCro2kPHkB3XGARh
u0qj944rhWE
5.0
Encointer Association

Store the above content in payload.txt

On Linux, we can create a QR code using qrencode.

Caveat: with the current version we need to make sure there's no newline at the end of the last line. So we just truncate the last byte of the file in the following example command

head -c -1 payload.txt | qrencode -o test.png

Alternatively, you can use web services that help you generate a QR code, like this one (select "Text" mode and make sure there's no line at the end)

Now, you can insert test.png into a design of your choice. For Leu we use this pdf form

Bazaar

THIS IS WORK IN PROGRESS recommended for developers only

setup ipfs uploads

In order to make our helper scripts work on our testnet, we need to upload metadata and assets to a public IPFS gateway. In this example we use infura.

export IPFS_ADD_URL=https://ipfs.infura.io:5001/api/v0/add
export IPFS_API_KEY=<KEY>:<SECRET>

create a pure proxy business account

In the future, we will recommend that businesses create pure proxy accounts for their business accounts. This way, control over the account can be distributed, revoked and multisiged

create a business entry for Bazaar

save the following as my_business.json

{
  "name": "Kueche Edison",
  "description": "bei uns gibt es köstlichen Kaffe",
  "category": "food",
  "address": "Technoparkstrasse 1, 8005 Zürich",
  "telephone": null,
  "email": null,
  "longitude": "8.515962660312653",
  "latitude": "47.390349148891545",
  "openingHours": "Mon-Fri 8h-18h",
  "logo": "QmUH7W2eAWTfHRYYV1YitZaz54sTjEwv6udjZjh7Tg47Xv",
  "photos": ""
}

The owner of this business can no register the business entry with the follwoing comman

./bazaar.py -u wss://gesell.encointer.org -p 443 --cid u0qj94fxxJ6 --bizaccount //Alice register-business ./my_busyness.json 

This helper script will upload your json to IPFS and register its ipfs url on testnet gesell

verify on-chain registry with

./bazaar.py -u wss://gesell.encointer.org -p 443 --cid u0qj94fxxJ6 list-businesses

register an offering

An offering is a product with a price, so let's define the product:

save the following as my_product.json

{
	"name": "Kaffee",
	"description": "Köstlicher Kaffe",
	"category": "food",
	"image": "QmZzkgNe6B6M9Y3UeGgugwEB56v5qBm35bcPTPnZFNtY7d",
	"itemCondition": null
}

Let's register this offering with product and price

./bazaar.py --client "../target/release/encointer-client-notee -u wss://gesell.encointer.org" --cid sqm1v79dF6b --bizaccount //Alice register-offering my_product.json --price 42

This helper script will upload your json to IPFS and register its ipfs url on testnet gesell

verify

/bazaar.py -u wss://gesell.encointer.org -p 443 --cid u0qj94fxxJ6 list-offerings

Why IPFS?

While IPFS isn't very reliable in terms of discovery and availability, it represents the only content distribution method currently available which has a potential of working in decentralized setups. It is also content-addressed which guarantees that the correct content is delivered in untampered state.

Bazaar-web

You can visit bazaar.encointer.org and browse you newly created businesses and offerings

Faucets

The Encointer faucet is a dispenser of arbitrary tokens. Every human is eligible to receive a small amount of tokens for every attendance in the Encointer protocol. This can be seen as an additional benefit of participating in the encointer protocol and as an onboarding route for new tokens.

Currently, the faucet MVP only supports the native ERT token on our testnet Gesell and will support KSM as soon as deployed on our mainnet. Our final product will support any fungible token which can be transferred via XCM to the Encointer parachain, including stablecoins

Testnet Usage

Drip

We assume you have set up the CLI client previously and you have bootstrapped your own community with a few bootstrapper accounts

We assume one of your community member accounts (can be a bootstrapper or reputable) is 5HdLw7t5LjjZ9vSeFiYRbcJf6uFX9xqzv3QappFBy9P8pR9e

Let's learn how you can request to receive ERT.

First, let's check what faucets exist on Gesell already:

> nctr-gsl list-faucets -v
address: 5Dq3XugU1atZM8QGHxg2KfZahm2CzuBUDp8XyxL9wn8Q8Yx3
name: FaucetNumberOne
creator: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
balance: 100000000000000
drip amount: 1000000000000
whitelist: None

In our example, two faucets exist and they have the following properties:

  • an address which holds the funds
  • a drip amount specifying how much ERT you can get for one cycle attendance
  • an optional whitelist of communities which are eligible for this faucet

Let's now check our reputation

> nctr-gsl reputation 5HdLw7t5LjjZ9vSeFiYRbcJf6uFX9xqzv3QappFBy9P8pR9e | sort
....
1744, e5dvt5mjcem, Reputation::VerifiedUnlinked

It looks like we have valid reputation for cycle 1744, so let's drip:

> nctr-gsl drip-faucet 5HdLw7t5LjjZ9vSeFiYRbcJf6uFX9xqzv3QappFBy9P8pR9e 5Dq3XugU1atZM8QGHxg2KfZahm2CzuBUDp8XyxL9wn8Q8Yx3 1744 --cid e5dvt5mjcem
Faucet dripped to 5HdLw7t5LjjZ9vSeFiYRbcJf6uFX9xqzv3QappFBy9P8pR9e

Our account now has received 1 ERT. If we try to drip again with the same reputation, this will fail:

> nctr-gsl drip-faucet 5HdLw7t5LjjZ9vSeFiYRbcJf6uFX9xqzv3QappFBy9P8pR9e 5Dq3XugU1atZM8QGHxg2KfZahm2CzuBUDp8XyxL9wn8Q8Yx3 1744 --cid e5dvt5mjcem
[+] Couldn't execute the extrinsic due to Dispatch(Module(ModuleError { pallet: "EncointerReputationCommitments", error: "AlreadyCommited", description: ["Participant already commited their reputation for this purpose"], error_data: ModuleErrorData { pallet_index: 65, error: [0, 0, 0, 0] } }))

Therefore, we need to attend another cycle before we can drip again.

Replenish a Faucet

If the faucet runs dry, anyone can send ERT to the faucet's address to fill it up again

> nctr-gsl transfer //Sponsor 5Dq3XugU1atZM8QGHxg2KfZahm2CzuBUDp8XyxL9wn8Q8Yx3 30000000000000

Create a new faucet

If you want to donate tokens to a specific set of communities, you can create your own faucet with an opional whitelist

> nctr-gsl create-faucet 5HdLw7t5LjjZ9vSeFiYRbcJf6uFX9xqzv3QappFBy9P8pR9e FaucetForMyBuddies 100000000000000 5000000000000 e5dvt5mjcem,dpcm5272THU
5CTxhG3NJjhwti8kQRR9FYTT53Jq41We3MHdoJZa4RymAKhq

This command creates a faucet with name FaucetForMyBuddies and sends funds from to the new faucet account and configures the drip amount. The return value is the faucet's account If you do not specify a whitelist, every community will be eligible to drip.

Be aware that registering a faucet requires you to reserve a deposit of 100 ERT. please check encointerFaucet.reserveAmount to verify the amount to be reserved. The reserved amount will be freed upon closing the faucet. Closing the faucet is only possible once the faucet is dry.

The new faucet will now appear in the global list of faucets:

> nctr-gsl list-faucets -v
address: 5CTxhG3NJjhwti8kQRR9FYTT53Jq41We3MHdoJZa4RymAKhq
name: FaucetForMyBuddies
creator: 5HdLw7t5LjjZ9vSeFiYRbcJf6uFX9xqzv3QappFBy9P8pR9e
balance: 100000000000000
drip amount: 5000000000000
whitelist:
e5dvt5mjcem
dpcm5272THU

address: 5Dq3XugU1atZM8QGHxg2KfZahm2CzuBUDp8XyxL9wn8Q8Yx3
name: FaucetNumberOne
creator: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
balance: 99000000000000
drip amount: 1000000000000
whitelist: None

Now, another reputable member of a whitelisted community (e5dvt5mjcem or dpcm5272THU) community could drip 5 ERT from the new faucet

Mainnet Faucets

You can use the same tools and commands as explained above, but here we'll describe more accessible ways as an altrernative

create faucet

Create a faucet called "PioneerPot" with 10 KSM initial balance and 100mKSM drip per cycle attendance. Another 10 KSM will be reserved as a deposit for the faucet and will be returned upon dissolving the faucet once it's empty

create faucet using js/apps

This will yield an Event encointerFaucet.FaucetCreated which also mentions the faucet's account holding the funds:

PioneerPot: GDcRrT5id2uFsYaE8NgfpnUkNKJpBWU4C2f5EFZQZiVZb9c

Drip Faucet

Use our Encointer Wallet app to drip.

  1. Go to profile -> your account
  2. find PioneerPot below benefits
  3. If you have personhood reputation and unclaimed allowance, the claim button will be enabled. tap it
  4. 100 mKSM will be dripped to your account
  5. the wallet will show your new KSM balance

The Encointer Wallet does not provide functionality to use KSM for other purposes than paying fees. If you'd like to use your KSM, please export your account and import it into one oif the popular wallets out there:

  1. See Backing up and restoring account
  2. Import into a Polkadot wallet
  3. Find your KSM balance and use your dripped KSM!

Refill

Simply send KSM to the faucet's address.

Monitor Usage

Of course, we'd like to know how many people are using the faucets and from which communities. You can fetch this information as follows:

First, we need to look up the purpose id of the faucet we're interested in

nctr-k list-purposes
# 0: ectrfct0PioneerPot

On mainnet, there's a single faucet right now with index 0

nctr-k list-commitments 0 --cid u0qj944rhWE
# u0qj944rhWE, 68, 0, 5EZHGkM4NZhbR9AxnWsc9tmzNNMLQJntx1874Y7RSXKw6crw, None
# u0qj944rhWE, 68, 0, 5FLbYHux2SUmo1EB3qtmLMvdicDff4yWDZPgriJU8qqyNWVR, None
# u0qj944rhWE, 69, 0, 5Cm38saAbnwrxvnGCp4Pqff5K3rKy4awYQnrdqDeHfvW2ZUM, None
# u0qj944rhWE, 69, 0, 5EZHGkM4NZhbR9AxnWsc9tmzNNMLQJntx1874Y7RSXKw6crw, None
# u0qj944rhWE, 71, 0, 5C7ru3m9eWEEZgcYghYa5uRhUrG5EiWoRgcR2JuBLmUnKr4w, None
# u0qj944rhWE, 71, 0, 5CV1NRrFvpoma3NRDG8iZCYnTcTCuAJSUnT4ym5Wc8fL86aD, None
# u0qj944rhWE, 72, 0, 5FLbYHux2SUmo1EB3qtmLMvdicDff4yWDZPgriJU8qqyNWVR, None

this will only list the drips which happened within the current reputation lifetime. To query older drips, add the --at <block hash> argument. When interpreting the results, be aware that drips can happen up to reputation lifetime later than the reputation being committed.

If you want to know how many accounts have use the faucet how many times, use this:

nctr-k list-commitments 0 --cid kygch5kVGq7 | awk -F',' '{print $4}' | sort | uniq -c | sort -nr | tee >(wc -l | awk '{print "Total unique accounts:", $1}')
#      5  5G7AsczRMrV1kSv2btw9FSh7CwoRzaYdjaadHHZU4cFKTcfN
#      4  5GhKkMhoTHtsoxD3muqhug795znXCsiu4Tq4iBiWfpKX6e4g
#      4  5G3dA2sc4ytrW2NE7FLz1JTdzveXAmXii4ryiYQhTVyBAuuf
#      4  5F6amYgeXNWQ7QYjvAjdiFsn2dCZ77XLp5MAFoH4GF9QacWN
#      3  5FnxT7z3mCzcNV95fEi73y6pduZzfMQ1dbBRamvWP8NfcHMi
#      3  5Eqm2XfZ5F18tjbDM523kTUhLrqJiXTaLsDGjKgSkrQeaU7M
#      2  5FHEfaNVa82BdMDXm7NUKecy3VPThCPHycSCTqBBK9HG5nNT
#      2  5FgcVajvdogedL4kiq4iFZ9x7Cx3ZcdCtf61qWB8fV7UP8qN
#      2  5EhLWoCguV193dDQYnTYWG21nAnYZA5R1Heedd7ejGoStBgr
#      2  5DceiYnUBdRx2bPjPFN2EjYm7VvaVnCB6Sp4qSjuYP4Qbd65
#      1  5Hmi6Xr4kPeZMjRWz2aeCawdZ7riJ4Lf46VRxv8iqAwcHdNm
#      1  5FhB9k35bqpjc8dYrkKnMtkTVfBg9nKjgPirZWGZEZA31jQw
#      1  5FcVT8yqHcsR59kq6fLREm4HV1Qv9hNTvDMPaWPeSJ4bCE3A
#      1  5EU4mJ2tKfADXutnoJ3FsEBFsf3XxjmxLXM1xhvyGWAXh94F
#      1  5Dhb315DK5T5f5Y59CsfCApv5HBb1CFzCv4zPMfsvW1t52JF
#      1  5CXuNeCvhb3qbPw2TjcKYdghamJcfkq6SavKmN5fQ1beUDH5
#Total unique accounts: 16

Democracy Tutorial

Encointer is about distribution of power - both economically and in terms of governance. Therefore, communities can govern their own protocol parameters with an approximation of universal suffrance. This tutorial takes you through the process of proposing a change and voting on proposals.

We assume you already have

What can you vote on?

Please read our democracy documentation to learn the details. In this tutorial, we will focus on local community governance, like changinging the community income amount issued per cycle.

Who can vote

Every reputable can vote on matters in the community where they have repuation. The current implementation grants reputables one vote per cycle attendance. This is a sybil-resilient approximation of universal suffrance and it gives those more voting power who engage more in cycles.

In the following, we will assume that one person only maintains one account. The protocol is sybil-resilient even if that's not the case, but the tutorial will be easier to follow with this assumption.

Quorum

Let's find out how many votes can maximally be cast for our community

First, how many different accounts have reputation?

nctr-gsl list-reputables
# Listing the number of attested attendees for each community and ceremony for cycles [4607:4943]
# ...
# Community ID: srcq45PYNyD
# ...
# Cycle ID 4942: Total attested attendees: 3 (noshows: 0)
# Cycle ID 4943: Total attested attendees: 3 (noshows: 1)
# ...
# Reputables in srcq45PYNyD (unique accounts with at least one attendance) 4

Our test community has 4 reputable members who are eligible to vote. The quorum of votes will be the sum of attested attendances, in this case 6. Two accounts will have a voting power of 2, because they attended both cycles 4942 and 4943. Another two accounts have a voting power of 1

Reputation becomes eligible for voting with 1 cycle delay. If you came here straight after the previous tutorial, you may need to wait for one cycle (30min on Gesell) for your fresh reputation to become eligible.

Reputation loses its voting power after ReputationLifetime

For later reference, we list the 4 reputables here with their eligible votes:

  • 5F77sGnUhpjdFnzruhurGZgqPFtvdECXTGgX4Bgy2zGavbEw (bootstrapper with 1 vote)
  • 5FyWbcwN1TGPdyzRzoEeem3MUcc7jXRs7ZoftZkAQLV47nS7 (bootstrapper with 2 votes)
  • 5CMVLJCC4Jn7QmLsFRkLWkm2w4LJswpZo1V2nd1tp64iVnCR (bootstrapper with 2 votes)
  • 5FH44YdjmxbXJCAn9DuwpXuz5h2S8zLn752Vn5CyDa3quwEs (reputable with 1 vote)

Submit Proposals

Anyone can submit a proposal anytime. See the docs to learn about conflict resolution among proposals.

nctr-gsl submit-update-nominal-income-proposal 5FH44YdjmxbXJCAn9DuwpXuz5h2S8zLn752Vn5CyDa3quwEs 3.14 --cid srcq45PYNyD
nctr-gsl list-proposals
# id: 3 (reputation commitment purpose id: 3)
# action: ProposalAction::UpdateNominalIncome(srcq45PYNyD, 3.14000000000000012434)
# started at: 2024-03-24 15:58:48 UTC
# ends after: 2024-03-24 16:18:48 UTC
# start cindex: 4954
# current electorate estimate: 6
# state: ProposalState::Ongoing

So now we have at most 30min time to vote.

Vote

Let's check our voting power:

nctr-gsl reputation 5FH44YdjmxbXJCAn9DuwpXuz5h2S8zLn752Vn5CyDa3quwEs
# 4943, srcq45PYNyD, Reputation::VerifiedUnlinked

We have one vote in community srcq45PYNyD with our reputation from cindex 4943. We need this information to cast our vote:

nctr-gsl vote 5FH44YdjmxbXJCAn9DuwpXuz5h2S8zLn752Vn5CyDa3quwEs 3 aye srcq45PYNyD_4943
nctr-gsl list-proposals
# id: 3 (reputation commitment purpose id: 3)
# action: ProposalAction::UpdateNominalIncome(srcq45PYNyD, 3.14000000000000012434)
# started at: 2024-03-24 15:58:48 UTC
# ends after: 2024-03-24 16:18:48 UTC
# start cindex: 4954
# current electorate estimate: 6
# state: ProposalState::Confirming { since: 1711296000000 }
# confirming since: 2024-03-24 16:00:00 UTC until 2024-03-24 16:00:00 UTC

The proposal will immediately enter the confirming phase which lasts 5min

If no one else votes, it will be approved because in this case our vote is already more than 5% of the electorate. Please check our docs on adaptive quorum biasing

Proposals are lazily evaluated. after the end of the confirming phase you can call

nctr-gsl update-proposal-state 5FH44YdjmxbXJCAn9DuwpXuz5h2S8zLn752Vn5CyDa3quwEs 3
nctr-gsl list-proposals
# id: 3 (reputation commitment purpose id: 3)
# action: ProposalAction::UpdateNominalIncome(srcq45PYNyD, 3.14000000000000012434)
# started at: 2024-03-24 15:58:48 UTC
# ends after: 2024-03-24 16:18:48 UTC
# start cindex: 4954
# current electorate estimate: 6
# state: ProposalState::Approved

All approved proposals will be enacted automatically at the start of the next Registering phase. Let's check the enactment queue:

nctr-gsl list-enactment-queue
# 3

This returns all proposal id's which will be enacted. Please be aware that even approved proposals can be cancelled before enactment if another proposal for the same action passes before enactment. However, after the first proposal for an action type has been approved, submitting new proposals will fail with encointerDemocracy.ProposalWaitingForEnactment until the approved proposal has been enacted.

After the start of the next Registering phase, let's verify the enactment:

nctr-gsl list-proposals
# id: 3 (reputation commitment purpose id: 3)
# action: ProposalAction::UpdateNominalIncome(srcq45PYNyD, 3.14000000000000012434)
# started at: 2024-03-24 15:58:48 UTC
# ends after: 2024-03-24 16:18:48 UTC
# start cindex: 4954
# current electorate estimate: 6
# state: ProposalState::Enacted

And the community income has indeed changed:

nctr-gsl list-communities
# ...
# srcq45PYNyD: Adriana, locations: 5, nominal income: 3.14000000000000012434 ADR, demurrage: 0/block, CommunityRules::LoCo

Vote Using the Mobile App

We have implemented a first mininimum viable product in the Encointer Wallet app.

To access this beta feature, you need to enable developer mode and connect to testnet Gesell or your local instance which you could populate with bot-communities.

vote in mobile app

Deep Dive

How do we ensure that every cycle attendance can only be used once for voting on a proposal but the same reputation can be used to vote on other proposals?

We solve this using commitments for purposes. Every proposal is its own purpose. Let's check purposes on Gesell:

nctr-gsl list-purposes
# 0: ectrfct0GesellPioneerPot
# 1: democracyProposal1
# 2: democracyProposal2
# 3: democracyProposal3
# 4: democracyProposal4

As you can see, proposals are not the only possible purposes. Each faucet is its own purpose too. Any use case that requires sybil-resilience can use these commitments. See our article on more use cases for social media.

If we want to learn more about the commitments for a specific purpose like our proposal above, we need to know its purpose index. we can use list-proposalsand it will tell us each proposals' purpose_id: Proposal id: 3 (reputation commitment purpose id: 3)

nctr-gsl list-commitments 3 --cid srcq45PYNyD
# srcq45PYNyD, 4943, 3, 5FH44YdjmxbXJCAn9DuwpXuz5h2S8zLn752Vn5CyDa3quwEs, None

This should list your previous vote(s) and those of anyone else who voted on the same proposal. As you see, voting is not private (yet) because your pseudonymous account is visible to anyone.

Community Treasury Spending Tutorial

Encointer Communities can manage common funds in community treasuries and decide on spending proposals democratically.

We assume you already have

What is a Community Treasury?

A community treasury is a technical account which isn't controlled by a private key held by a person or entity. Every Encointer community has their own treasury account and can decide on spending proposals democratically - the electorate being the reputables of that community.

Where does the money come from?

In the future, community treasuries will receive a share of network fees and faucet drips. However, it will take quite large populations to generate significant income from these sources.

Initially, treasuries are intended for grants and donations. Donors can transfer funds directly to Encointer communities and rest assured that the funds will be spent according to the community's democratic decision without trusting any intermediaries.

Testnet Gesell Tutorial

fund the treasury

First, we need to find out the treasury account address of our community. This is the account that will receive the funds. Please replace the CID with your community's CID.

nctr-gsl get-treasury --cid sqm1v79dF6b
# 5CWoc3mGF9VEnuZzBbPWxhKPvY743AGwxUbvkYQHS8yWZbem
nctr-gsl transfer //Alice 5CWoc3mGF9VEnuZzBbPWxhKPvY743AGwxUbvkYQHS8yWZbem 1000000000000
nctr-gsl balance 5CWoc3mGF9VEnuZzBbPWxhKPvY743AGwxUbvkYQHS8yWZbem
# 1000000000000

submit a spending proposal

We will let Alice propose a spend of 0.123 ERT to Bob. Replace Alice and Bob with accounts you control.

nctr-dev submit-spend-native-proposal //Alice //Bob 123456789012 --cid sqm1v79dF6b
nctr-dev list-proposals

Verify that your proposal is listed and the electorate is correct. Remember that reputation is only counted for the electorate after one full cycle has passed.

Please remember your proposal ID for later reference.

vote on a spending proposal

This is best done with the mobile app because it is much easier. For cli enthusiasts, here's how to vote with the cli:

Alice will vote Aye with her reputation from cycle index 1 attendance in community sqm1v79dF6b.

nctr-gsl vote //Alice 1 aye sqm1v79dF6b_1

For more details how to obtain your reputation information, see the democracy tutorial.

update the proposal

As Encointer democracy is evaluated lazily, we need to trigger vote tallying manually. This is done by updating the proposal.

nctr-gsl update-proposal-state //Alice 1
nctr-gsl list-proposals

If the proposal has been accepted, the enactment will be scheduled for the upcoming assigning phase.

verify enactment of the proposal

After the proposal has been enacted, the funds will be transferred to Bob's account.

The treasury balance should have gone down and the beneficaries account should have gone up

nctr-gsl balance 5CWoc3mGF9VEnuZzBbPWxhKPvY743AGwxUbvkYQHS8yWZbem
nctr-gsl balance //Bob

Developers

This chapter includes information for developers who want to test the tech locally on their machines

Gesell local setup

Note: You can find more detailed instructions on how to build and run the node and cli client on the encointer-node repository.

Build node

Clone the encointer-node repository and cd into it:

git clone https://github.com/encointer/encointer-node.git
cd encointer-node

Install Rust:

curl https://sh.rustup.rs -sSf | sh

Build the node:

cargo build --release

Launch Gesell node

Run dev node locally

./target/release/encointer-node-notee --dev --tmp --enable-offchain-indexing true --rpc-methods unsafe

--dev sets up a developer node chain specification
--tmp saves all active data for the node (keys, blockchain database, networking info, ...) and is deleted as soon as you properly terminate your node.
--offchain-indexing is needed for the custom rpc call communities_getAll
--rpc-methods unsafe is needed for the bazaar's business and offering aggregation rpcs.
The node is by default listening on port 9944, but you can add the option --ws-port xxxx to configure the node to listen to port xxxx.

CLI Client

After the node is running, try out the client (from the root folder of the encointer-node repository):

./target/release/encointer-client-notee -h

This should output all possible client commands.

If you want to use the client to communicate with the remote chain, add the chain url and specify the port. The following command will get the current phase from the remote chain.

./target/release/encointer-client-notee -u wss://gesell.encointer.org -p 443 get-phase

Bot Communities

Bot communities are helpful to test the Encointer protocol and all the surrounding applications, apps and UI's

To simplify the registration of a community, a python script was written to wrap up the chain client commands and automate the bootstrapping. We will go through the process step by step.

If you'd rather learn how to register communities manually, visit this section

Setup

install all requirements for the python scripts (you'll need pip3 for that):

apt update
pip3 install --upgrade pip
pip3 install randomwords geojson pyproj flask

Local Testing

Setup the chain and client locally according to the local setup.

Run a faucet. Go to the client folder and run the faucet service in a seperate terminal which will be used to drip funds to the bootstrapping accounts later on:

cd client
./faucet.py

The faucet service is a flask app which runs on localhost and listens on port 5000 to incoming faucet requests.

In a local setup, we don't want to wait for the ceremony phase to change in fixed intervals. Instead, we use the phase service to watch extrinsic activity and forward the ceremony phase when the chain blocks are empty for a while indicating idleness.

cd client
./phase.py

By default, the scripts register your community on the local node listening on websocket port 9944. you can change that by adding the --port 9945 argument

./bot-community.py init
./bot-community.py benchmark

The benchmark command will watch for ceremony phase to change and act upon the new phase automatically. This command will run forever.

Branding on IPFS

Community branding information is stored on IPFS. You can save the community icons to a IPFS node by passing the -l or --ipfs-local flag to the init function.

ipfs init
ipfs daemon
./bot-community.py --port 9945 init -l

Create Dummy Bazaar Businesses and Offerings and Save the data on an IPFS node

After a community is initialized, we can register businesses with offerings on the chain. Run the following script to create and register some random businesses and offerings:

./register-businesses.py -l

You can save the businesses and offerings descriptions on the local IPFS node by passing the -l or --ipfs-local flag to the script. Otherwise, the data will be saved on a remote IPFS node.

The businesses and offerings are stored in:

  • ./client/test-data/bazaar/businesses*
  • ./client/test-data/bazaar/offerings*

You can check the registered businesses and offerings using the client:

./target/release/encointer-client-notee list-businesses --cid COMMUNITY_IDENTIFIER 
./target/release/encointer-client-notee list-offerings --cid COMMUNITY_IDENTIFIER 

The business offerings can be obtained with the option --cid and arg Account, which is the owner of the business. In this case we used the account //Alice:

./target/release/encointer-node-notee list-business-offerings --cid COMMUNITY_IDENTIFIER //Alice

Note: the cid option needs to be entered in the base58 format.

Testnet Gesell Bot Communities

As community branding must be stored on IPFS, you'll need to specify credentials for a public IPFS gateway to be used to deploy content. For Infura, use:

export IPFS_ADD_URL=https://ipfs.infura.io:5001/api/v0/add
export IPFS_API_KEY=<project-id:password>

To work with testnet Gesell you need to specify the node-url as follows:

./bot-community.py --node-url wss://gesell.encointer.org init

Note: the port 443 is automatically set when working with a remote chain using wss://

On Gesell, ceremony phases change every 10min. In order to continuously grow a bot community, run the following command every 10min

./bot-community.py --node-url wss://gesell.encointer.org run

Explanations

Let's look at what is happening in the init function:

  1. Bootstrapper accounts are created. They can be seen in the ./my_keystore folder.
  2. Funds are transfered to the bootstrappers via the faucet. As with other blockchains, funds are necessary in order to pay fees.
  3. A specfile is created with a community name, a symbol, the icon of the community, the list of bootstrappers and several random meetup locations around a specified point. You can see the community specfile in the client folder. It is a geojson file with the name of the community as filename. The specfile is needed to register a community.
  4. A new community is registered by passing the specfile and one of the bootstrappers (with funds) to the "new_community" function.

Note:

  • Make sure, the faucet script is running in the background while running the bot-community script to enable the faucet.
  • As you can read in our whitepaper, we'll avoid the faucet as an entry barrier in the future.
  • Should the faucet be exhausted, please post a message to our element channel and friendly request some topup. Please be patient.

To check if a community is registered on the chain, you can use the client with the command "list-communities":

./target/release/encointer-node-notee list-communities

The benchmark function calls the run function in an infinite loop, where the run function is responsible to handle the specific task depending on the phase.

At REGISTERING, it registers participants on the chain. Additionally to registering participants, bootstrappers can endorse other accounts to speed up registration. After participants are registered for a ceremony, the participatns can be verified in a seperate shell by calling:

./target/release/encointer-node-notee list-participants

At ASSIGNING, the blockchain assigns all participants to randomized groups that will have to meet at a random meetup location at a specific time. Participants can learn their assignment with:

./target/release/encointer-node-notee list-meetups

At ATTESTING, the run function performs the meetup by getting each participants claims and attesting eachother.

To know in what phase the chain is, you can call:

./target/release/encointer-node-notee get-phase

You should see either REGISTERING, ASSIGNING or ATTESTING.

A phase is ~10 min long so one whole cycle is 30 min. You can jump to the next phase on the local chain by running:

./target/release/encointer-node-notee next-phase

Another way is to run the phase script in a seperate shell which switches phase every 10 blocks. You can add the option: --node_url wss://gesell.encointer.org to the phase script if you are working with the remote chain.

To define in what region the community shall be issued, we use the geojson standard to define a set of meetup places and add some meta-information about the community. You can use geojson.io to select meetup places on a map (define a few "Points"). Make sure that you select places that are >100m apart. You also need to keep this minimal distance from other registered communities.

The number of locations that you should define depends on the size of the population N you'd like to bootstrap. As a rule of thumb, there should be at least N locations in order to guarantee reasonable randomization. As a maximum of 12 people can attend the same meetup the hard lower limit is N/12.

Every local community needs a trusted setup. A trustworthy group of 3-12 local people will hold the bootstrapping ceremony publicly. These bootstrappers need to be defined in the metadata block of the specfile.

At every subsequent ceremony you can add a few participants more but it is important to maintain reputation. At least 3/4 of all participants need to have attended the previous ceremony. So you can only grow your population at a pace that allows to build reputation.

An encointer ceremony happens at high sun on the same day all over the world. This way, no single person can attend more than one meetup. At each meetup, participants attest each others personhood. For this testnet, however, we don't care about real time or physical presence as we're testing with bot communities. See Time Warping to learn how the timing maps between mainnet and Gesell.

Your new community has a very special property called demurrage. This means that the nominal value of your holdings decreases over time. Currently it is halving every year. You can observe this by waiting for a few blocks and checking your balance again. Think of this demurrage like a solidarity fee that you pay to the decentralized "state" that takes care of redistributing wealth among the local population at every ceremony as newly issued basic income.

See Activity in Explorer

Visit explorer.encointer.org to observe the growth of the community or run the explorer locally according to the explorer section.

Browse Bazaar Businesses and Offernings

See Bazaar-web repo and follow README to launch a web service that lists all businesses and offerings for a specified community

Gesell local dockerized benchmark

Follow the instruction on docker-tutorial to get the docker image and required yml files.

Launch local docker environment with Gesell node and comminities

After the docker-compose file is set-up, you can start the docker containers with

docker-compose up -d

This will start a gesell node, 3 bot communities that will grow, a faucet script to ensure funds for transactions and a phase shifting script that changes every 10 blocks to the next phase (REGISTERING, ASSIGNING, ATTESTING).

Watch communities grow on explorer

Open up explorer.encointer.org in your browser and configure the node to be your dockerized gesell node with the predefined port.
Alternatively, you can also start your local explorer as shown in the explorer section.

Watch performance metrics (prometheus/grafana)

According to the docker-tutorial, grafana and prometheus should be set-up. Now, visit localhost:3000 and view the preformance metrics in your dashboard.

Local TEEproxy setup

TEEproxy is the variant of Encointer that protects privacy. It has been deployed to testnet Cantillon

You can run an entire Demo locally on any properly set up SGX machine. This is for advanced users or developers. The instructions assume that you are able to build substrate blockchains. If you do not have an SGX machine to test, please check our dockerized demo in SW mode

Build client and worker

along the substraTEE-worker instructions. With the following differences:

git clone https://github.com/encointer/encointer-worker.git
cd encointer-worker
./ci/install-rust.sh
make

Because the enclave cannot yet be built deterministically, you'll have to use our build if you intend to serve the same shards that we do (feel free to start new currencies on your own shard with different MRENCLAVE, but you won't be able to process the state of our/other shards):

cd bin
wget https://github.com/encointer/encointer-worker/releases/download/v0.6.12-sub2.0.0/enclave-0.6.12.signed.so
rm enclave.signed.so
ln -s enclave-0.6.12-devsgx02.signed.so enclave.signed.so

Moreover, you will need to provision secrets (the shielding key and the state encryption key) to the enclave. In the future, this will be done by workers automatically mutually, as demonstrated in SubstraTEE M3.

# still inside ./bin
# get our symmetric state encryption key
wget https://github.com/encointer/encointer-worker/releases/download/v0.6.10-sub2.0.0-alpha.7/aes_key_sealed.bin
# get our RSA shielding key
wget https://github.com/encointer/encointer-worker/releases/download/v0.6.10-sub2.0.0-alpha.7/rsa3072_key_sealed.bin

Build node

along the substraTEE-node instructions. With the following differences:

git clone https://github.com/encointer/encointer-node.git
cd encointer-node
git checkout sgx-master
cargo build --release

Run dev node locally

..encointer-node# ./target/release/encointer-node-teeproxy --dev --ws-port 9979

Run dev worker with a few insightful logs locally

cd encointer-worker/bin
./encointer-worker init-shard
./encointer-worker shielding-key
./encointer-worker signing-key
export RUST_LOG=info,substrate_api_client=warn,sp_io=warn,ws=warn,encointer_worker=info,substratee_worker_enclave=debug,sp_io::misc=debug,runtime=debug,substratee_worker_enclave::state=warn,substratee_stf::sgx=debug
./encointer-worker -p 9979 run

Docker Demo

To avoid the need for an SGX machine, we provide a dockerized demo in SW mode as well (with emulated SGX)

mkdir test
cd test
docker pull scssubstratee/substratee_dev:1804-2.12-1.1.3-001

docker run -it -v $(pwd):/root/work -p 9979:9944 -p 2079:2000 -p 3079:3443 scssubstratee/substratee_dev:1804-2.12-1.1.3-001 /bin/bash

cd work

Please observe that we are mapping the api ports to the host system. this way, you can expose the encointer demo to your home network and access it with our mobile app too.

We suggest to use tmux in docker to split your docker bash into 3 terminals. minimal cheatsheet:

  • Ctrl-B " to split into one more terminal
  • Ctrl-B <arrows> to switch focus to another terminal
  • Ctrl-B d detatch session. re-attach with tmux a

building

in terminal 1 do

git clone https://github.com/encointer/encointer-node.git
cd encointer-node
git checkout sgx-master
cargo build --release
export RUST_LOG=INFO,parity_ws=WARN,encointer=debug
./target/release/encointer-node-teeproxy --dev --ws-external -lencointer=debug,runtime=debug

Your chain should now start producing blocks.

in terminal 2 do

git clone https://github.com/encointer/encointer-worker.git
cd encointer-worker
SGX_MODE=SW make
cd bin
./encointer-worker signing-key
./encointer-worker shielding-key
./encointer-worker init-shard
./encointer-worker mrenclave > ~/mrenclave.b58
export RUST_LOG=debug,substrate_api_client=warn,sp_io=warn,ws=warn,encointer_worker=info,substratee_worker_enclave=info,sp_io::misc=debug,runtime=debug,substratee_worker_enclave::state=warn,substratee_stf::sgx=info,chain_relay=warn,rustls=warn,encointer=debug
touch spid.txt key.txt
./encointer-worker --ws-external run --skip-ra 

Your worker should sync blocks now.

Now you have a running local Encointer system.

run a bot community

in terminal 3 do

cd encointer-worker/client/
MRENCLAVE=$(cat ~/mrenclave.b58)
nano bot-community.py

now edit the following lines to match your setup

cli = ["./encointer-client"]
...
MRENCLAVE = "<your mrenclave here>"

save and exit with Ctrl-X

apt update
apt install python3-geojson python3-pyproj
./bot-community.py init
./bot-community.py benchmark

now you can see how your bots register for ceremonies and get a UBI. More and more bots join the community for every ceremony.

Infrastructure

Encointer needs IT infrastructure to operate. All infrastructure can be run by anyone, thereby contributing to the network availability and decentralization.

Full Node Setup

This document describes how to set up a full Encointer node. A full node is a node that validates the entire blockchain history. Interacting with a full node you run yourself is the most secure and most privacy-preserving way to interact with the Encointer network.

HW requirements

Full nodes can be run on very affordable HW. The minimum requirements are

  • 1TB NVMe SSD
  • 16GB RAM (8GB currently works, but is not recommended)
  • CPU won't matter much, but go for maximum single-core performance rather than many cores.

OS requirements

In the following, we'll assume you're using ubuntu 22.04

Install dependencies

The recommended way to setup a full node is to start with the ansible setup provided by w3f.

Should you wish to do it manually, we'll redirect you to the polkadot docs

systemd service

We assume you'd like to use your node for rpc queries from outside and monitor it with prometheus

[Unit]
Description=Encointer Kusama Collator

[Service]
User=encointer
Group=collators

ExecStart=/home/encointer/encointer-kusama/encointer-collator \
  --rpc-cors all \
  --name <a name that will appear in telemetry>> \
  --telemetry-url 'wss://telemetry.polkadot.io/submit 1' \
  --base-path <your large volume> \
  --state-pruning archive \
  --blocks-pruning archive \
  --chain=encointer-kusama \
  --rpc-methods=Unsafe \
  --prometheus-external \
  --enable-offchain-indexing true \
    -- \
  --sync=warp \
  --chain kusama \
  --prometheus-external \
  --base-path <your large volume> \

Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target

Collator Setup

Collators are parachain full nodes which additionally collect pending transactions, order them and propose new blocks on Encointer Network. Their operation is critical for availability, but not for security. The latter is provided by the validators of the Kusama relay chain.

Who can run collators?

Encointer’s aura consensus is based on a quasi-static set of authorities which can be mutated every 6 hours. This collator set consists of permanent, invulnerable nodes and a dynamic, unpermissioned set of nodes. Invulnerables are currently run by the Encointer Association and partners. Anyone can join the set of unpermissioned collators by submitting a candidacy and bonding some stake in KSM. Candidates are selected based on their stake until the desired set is full.

Requirements

  • a full node running with high availability
  • 5 KSM to bond

Incentives

As Encointer is a systemchain on Kusama, collator operators can request compensation from Kusama Bounty 20 and get rewarded from the Kusama Treasury, subject to multiple conditions.

Moreover, collators collect extrinsic fees on the network. On Encointer, fees are paid in either KSM or any of the community currencies. As a collator you will, therefore, also receive community currencies from all around the world.

We encourage members of Encointer communities to run their own collators to ensure the network is decentralized and censorship-resistant. Communities who don't run their own collators rely on others to do so who could in theory de-prioritize, delay or even censor transactions for a particular community. Collecting fees in their own community currency is added benefit.

Run a Collator Node

See the above chapter on how to run a full node. There is only one difference: The parachain CLI (the part before the --) needs the --collator flag.

Generate an Authority Key

Collators need to manage two types of keys:

  • A session key which is used to sign blocks. this key must always be online and is therefore not considered highly secure. It should be rotated regularly.
  • An authority key which used to submit candidacy, bond funds and change session keys. This key isn't needed very often and should be kept secure.

To generate an authority key, please choose a polkadot wallet and follow the steps to generate and secure a new account. In the following, we assume that you use a browser extension to keep your authority key safe.

Rotate Session Key

The best way to rotate session keys is to let the collator itself do this. The author_rotateKeys rpc call will generate a new key and print the public key. On your collator machine, run the following command:

curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "author_rotateKeys", "params":[]}' http://localhost:9944

Take note of the fresh public key in hex format which is returned returned as json response.

Register Session Key

Use the session.setKeys call to register your key.

  • keys: your session key in hex format with 0x prefix
  • proof: not needed. just put 0x

Submit Candidacy

Use your authority key to call collatorSelection.registerAsCandidate. This will bond 5 KSM. Please make sure your free balance is higher than that.

Your collator should appear on the collator dashboard. In any case, you'll need to wait for the next session (up to 6 hours)

When there are more candidates than desired nodes, preference will be given to the candidates with highest bonds. If you wish to update your bond, please call collatorSelection.updateBond

Should you be selected into the set of active collators, any downtime can lead to degraded block times. Should your node fail to propose blocks, you may be removed for the upcoming session.

Public Rpc Setup

Multiple frontends for Encointer rely on public RPC nodes to query the blockchain state and history. This document describes how to set up a public RPC node for Encointer.

We will assume that you have a full node running already.

The standard config we provide for full node already assumes that you want to expose your rpc service. Please make sure you set --enable-offchain-indexing true. Then, all you need to do is make port 9944 accessible to the public. As the procedure to expose your service varies a lot depending on your setup, we can't provide a one-size-fits-all recipie here.

Test

The following example tests the public rpc and also verifies that offchain indexing is enabled

curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "encointer_getLocations", "params": [{ "geohash": "0x7530716A39", "digest": "0x77f79df7" }] }' https://kusama.api.encointer.org
# {"jsonrpc":"2.0","result":[{"lat":"47.3860442609734562325","lon":"8.5167555883526802063"},{"lat":"47.3863389067466229676","lon":"8.5233766213059425354"},{"lat":"47.3869987892637922755","lon":"8.51989746093749822364"},{"lat":"47.3885922795468204072","lon":"8.51957626640796661377"},{"lat":"47.3891715535333091225","lon":"8.5129961371421813965"},{"lat":"47.3895923857361651699","lon":"8.5164836794137954712"},{"lat":"47.3896700146103739826","lon":"8.52360427379608154297"},{"lat":"47.39043449402448260344","lon":"8.51080611348152160645"},{"lat":"47.3922230783101596785","lon":"8.51907670497894109474"},{"lat":"47.39408059955918872674","lon":"8.5130444169044494629"},{"lat":"47.38784547884539222196","lon":"8.52683097124099731445"}],"id":1}

Announcing Your Public RPC

If you'd like to support the Encointer Network, the world should know about your rpc node. The best way to publish it is through Polkadot js apps. Please submit a PR on their Github repo like this one

Indexer

If you run your own node, you may want to run your own indexer for better privacy and autonomy.

LiteScan

Encointer uses a very simple low-level indexer called LiteScan and extends it with its own types.

Setup

We assume you're running your node on the same ubuntu 22.04 machine. We want to run the indexer as a service, feeding into a mongodb database.

sudo apt install -y mongodb-org curl

To run a node program as a service, install PM2

sudo npm install pm2 -g

Install nvm and node >=20

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
nvm install 20
git clone https://github.com/brenzi/litescan.git
cd litescan
git checkout encointer
npm install

MongoDB

We encourage you to pick strong passwords in the following steps. We will create the admin user and litescanwith r/w permission as well as encointerwith read permission for queries

sudo service mongod start
mongosh
use admin
db.createUser( { user: "admin", pwd: "*****", roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] } )
use encointer-kusama
db.createUser({user: "litescan", pwd: "******", roles: [{ role: "readWrite", db: "encointer-kusama" }]})
db.createUser({user: "encointer", pwd: "*******", roles: [{ role: "read", db: "encointer-kusama" }]})

Test Indexer

Now we need to configure the indexer. Create a .env file in the repo root. Make sure to adjust according to your setup.

DB_URL=mongodb://litescan:*******@localhost:27017/?authSource=encointer-kusama
NUM_CONCURRENT_JOBS=1000
START_BLOCK=508439
DB_NAME=encointer-kusama
RPC_NODE=ws://127.0.0.1:9944

Now you can run the indexer

node index.js

you should see block sync happening

Run as Service

To make sure the indexer is always up, we run it as a service.

pm2 start index.js --name encointer-indexer
pm2 save
pm2 startup

And execute the suggested command to make the service start on boot.

Querying

You can now run any MongoDB Query against the database.

We recommend mongodb compass to browse the database

As a simple cli example, let's query the highest indexed block:

mongosh --username encointer --eval "db.blocks.find().sort({height: -1}).limit(1)" encointer-kusama

Support Us

The Encointer Association is a Swiss non-profit association. Please learn about our constitution

There are plenty of ways how you can support us. The best way is by getting active and engaging with your local community

But we can also offer you more passive ways to support our mission:

  • Donations if you want to give
  • Nominations if you want to earn staking rewards while helping us earn as well.

For donations, please reach out to us: info@encointer.org

Nominate

Easy: Nominate with our Pools

Starting from 1 DOT or 1.66 mKSM you can earn staking rewards by joining our nomination pools.

Stake DOT on Polkadot:

Stake KSM on Kusama:

You will earn staking rewards and by doing so, you support Encointer's validators and those of friends who supported Encointer in the past with their votes or otherwise.

Nominate our Validators Directly

If you are lucky to own substantial amounts of DOT or KSM, we encourage you to selectively nominate our validators directly:

Kusama Validators:

  • HQGpmN3FNykmM131vDkuvukLq7g1bDud96H5vvGcUsF4WiU ENCOINTER/KV1
  • D9EKgv21LBMMzkrLZWMrGLhQPsQhwEeV2tVhwwow6W9ZCbx ENCOINTER/KV2

Polkadot Validators:

  • 165NJXk1HKxeFPbNK3ZEsgRPoGTkxMU9DyteK3cE7AGt7xrJ ENCOINTER/PV1