Alexander Chepurnoy

The Web of Mind

Cryptocurrency State Representation: Boxes vs Accounts

| Comments

A cryptocurrency is decentralized replicated blockchain-based ledger system. What is ledger? A ledger is a state of a system in some minimal form giving us ability to answer whether a transaction could be valid against it or not. Another question a ledger should answer is whether a transaction is already included in it or not. How could be ledger represented then? There are two popular approaches.

Box Model

First is used in Bitcoin and its successors. A ledger in Bitcoin could be represented as unspent transaction outputs(UTXOs in Bitcoin jargon) list. Given a transaction it is easy to check whether it is valid: all the transaction inputs must be connected to unspent outputs, and also inputs must provide a valid solution(in form of stack machine script) to spending guard condition an UTXO has(in form of stack machine script as well). Also, sum of bitcoins associated with inputs must be not less than sum of bitcoins associated with inputs. Outputs spent are to be removed from ledger and new ones the transaction contains are to be added to it.

Abstracting the Bitcoin-like model, a state could be represented as a list of closed boxes. Each box has a value associated with it. A transaction contains keys to open some boxes and new closed boxes. A transaction is valid if all the keys in it are opening closed boxes in a ledger and sum of new closed box values is no more than sum of values of closed boxes to be open.

It is not hard to see that the second question (whether a transaction was already processed into ledger or not) could be answered trivially in the box model. If transaction was already processed, its boxes are open and so not stored in ledger anymore.

Unfortunately, there are no known box systems other that Bitcoin-like around, but I bet, we’ll see them around some day.

Account Model

While boxes state model is about immutable objects to be only created or destroyed, we can also represent state with mutable accounts. Transaction is involving existing accounts. It modifies them and maybe creates some new accounts. This approach is adopted by Nxt and Ethereum. In a simplest form, it is implemented in Simplest Transactional Module of the Scorex project. Basically the state in Simplest Transactional Module is just map (account -> balance).

While this model could answer pretty well to the question whether a transaction is valid against a state(in the simplest case above, it is just about whether an account has an aprropriate balance), the second question(whether a transaction was already included in included into state or not) becomes tricky. As a possible solution, nonce could be used, and is used in Ethereum. That is, a transaction contains always-increasing nonce(so a next transaction must have a bigger value of nonce field than a current one), and last nonce value used is to be stored into state.

Lagonaki, First Public Testnet on Top of Scorex, Has Been Launched!

| Comments

Scorex is fully open (open-sourced under public domain license) modular blockchain framework (GitHub) . Modular means you can swap a consensus or transactional part of a blockchain system or add a new p2p protocol as easy as possible. The project is supported by IOHK company (http://iohk.io/).

To prove that the framework is indeed modular we have implemented few modules: Proof-of-Stake consensus, Permacoin implementation, and simplest transactional module with just tokens transfers from one pubkey to another(the only one kind of transactional modules unfortunately).

Permacoin is a consensus protocol based on non-interactive Proof-of-Retrievability scheme for a static dataset. Paper is made by Miller/Shi/Juels/Katz/Parno: http://cs.umd.edu/~amiller/permacoin.pdf .

We are launching first testnet release called Lagonaki. Lagonaki = Scorex + Permacoin + SimplestTransactions

Lagonaki Debian package and sources: https://github.com/ScorexProject/Lagonaki Testnet seed node API is opened there: http://23.94.190.226:9081/

You can also run Lagonaki in a Docker(set wallet seed & wallet password in settings.json). Readme is in the Scorex repository(you can temporarily run Lagonaki from there).

I’m filling wiki pages at the moment.

Please contribute by testing! We are also looking for contributors. In particular, it would be amazing to see Bitcoin and Ethereum-like transactional modules (possible by reusing BitcoinJ/EthereumJ code I guess). And please join developers maillist.

On Private Blockchains, Technically

| Comments

Introduction

The concept of private blockchains is very popular these days. All the discussions I’ve seen were about general and economic aspects of them. I suppose it is the good time to start a
technical discussion around the concept I’ve been thinking a lot since mid-2014 when I raised “industrial blockchains” term in private conversations.

Private blockchains could have different requirements and so design. Five banks exchanging tens of millions of records per day is different story than 10,000 art galleries submitting just 5,000 common ledger updates daily.

A blockchain-based system could be seen as a set of protocols. I am going to reason how consensus and transactions protocols could be implemented in a private blockchain.

Consensus

Consensus in the global Bitcoin p2p network is based on solving moderately hard computational puzzles, also known as “Proof-of-Work”. I suppose Proof-of-Work is not an appropriate choice for a private blockchain due to at least following reasons:

  • An adversary can take a control over a network easily by outsourcing computations to Bitcoin miners(it would be cheap for a network not protected by a bunch of special hardware).

  • A private blockchain solutions provider can unlikely substantiate a need for a customer to spend a ton of money on a datacenter full of ASICs in addition to software to be run on computers.

How to determine a next block generator in absence of computational puzzles? Few options are known:

  • Proof-of-Stake. Good and flexible solution for network with big number of participants. The method is suitable for non-monetary blockchain systems, in this case tokens called generation rights could be created in a genesis block. A big business can get bigger share of generation right so has bigger probability to generate a block.

  • By using a trusted blockchain as a random beacon. “On Bitcoin as a public randomness source” paper shows that Bitcoin block header could be used as the source of 32-68 random bits. Similarly, the generator signature field in an Nxt block header could be used as the source of 32 random bits. If network participants are known then a block generator could be chosen by using those random bits. There are some drawback of this approach: each node in a private blockchain should include Bitcoin SPV client(or NRS in case of Nxt), block generation delays are determined by a trusted public blockchain(so 10 minutes in average for Bitcoin, 2 minutes for Nxt).

  • By using a known Byzantine fault tolerant solution to a distributed commit problem. As this is a lonely toy of CS researchers there are a lot of possible algorithms described in papers. BFT solutions are better suitable for small networks.

Transactional Model

There are many aspects in designing transactions carrying valuable business data, in particular:

  • In some cases blocks are not really needed (if transactions ordering is important, [DAG] (http://188.138.57.93/tangle.pdf) could be used).

  • If Proof-of-Stake is used for consensus, special kinds of transactions could be introduced
    to create, transfer and destroy generation rights.

  • A Bitcoin-like transaction with multiple inputs and outputs and scripts attached to both sides isn’t a good solution for most non-monetary use cases probably. Even more, this choice could lead to very inefficient and heavy processing. For example, if a system is about multiple assets tracking, it’s better to take Nxt assets-related transactions(while removing others).

  • While in Bitcoin no information about a state is stored in a block header, in many cases it’s practical to include state-related information into blocks(as Ethereum includes Merkle-Patricia Trie root hash).

A Private Blockchain Design

Since the introduction section of the article I am implicitly stating one thought to be directly stated now: One size doesn’t fit all.. I saw many trends in data storage and processing, and after working with few “silver bullets” in the past I would like to say: there is no silver bullet ever found in this area. Always think about your data and requirements around them then choose or design a tool to work with. When we are talking about such a specific data storage as blockchain some questions should be answered in prior. Here is example list:

* How many participants will be in a network? Are they equal? Are all of them are allowed 
 to change a global state(so to generate blocks)? 

* What load is planned? E.g. how many transactions per hour or day.                  

* Data model for global state(ledger) should be considered. Please note blockchain 
is replicated data structure, and there is no known work on how to shard it yet.

* Could be state designed in a way to allow some form of pruning? 

* Transaction model should be considered. How many bytes an average transaction is about? 

* What are security requirements regarding consensus? What could be tolerated?

* What are privacy requirements? Should be all the data is visible for all? 

Conclusion

At now we already know how to build public blockchains(with significant and sometimes critical lack of formalization though). Private blockchains banks and financial institutions are so excited about at the moment are unknown beasts we need to formulate precise questions and then provide answers yet. This article is trying to stimulate work in this direction.

Appendix 1. The Scorex Project

I am the author of the Scorex project, minimalistic blockchain engine for research purposes. I think Scorex would be useful for experiments with private blockchains.

Vandalizing on Ethereum Blockchain

| Comments

If you are already full of excitement because you can write a Turing-complete script into the Ethereum blockchain, I’m going to excite you even more - it’s possible to write any garbage instead of a contract code. Example of such a transaction is https://etherscan.io/tx/0x4bb32548d3b28d8bbdbe969888dff6285a0404bb314b7a8e5d81a61a313781eb . It starts with the invalid instruction code then some random crap. The fee is minimal, as nothing was executed. So I put around 1kb into the blockchain(and few thousand nodes hard drives) forever for just 4.5 Finney ($.002 at the moment). Can’t say about bigger amount of data, as my geth client got deadly broken when I tried to submit transaction of about 60Kb.

And possibility to submit invalid data as contract code couldnt' be eliminated probably by code analysis as the EVM language has arbitrary JUMP instruction.

Towards a New Frontier of the Smart Contracts: Hawk and Enigma

| Comments

Introduction

After the AT Project(incorporated into Burst and Qora) and then Ethereum launch we got the ability to store programmable logic of potentially arbitrary complexity on the blockchain and then execute it on an each node. The “world computer” approach has some very obvious problems though:

  • scalability - executing a code on an each node in a network is just impractical. With tens (or hundreds) of companies planning to build something atop of the Ethereum, the reality is all those projects can’t fit into a single blockchain probably

  • privacy - in many real-world scenarios contractors are not willing to disclose some of data or code details to the public. Current smart contracts solutions are not preserving privacy in any way

Research units around the world are trying to solve the issues. In this review first two well-known approaches, namely Hawk and Enigma will be covered.

Language-Based Approach

Both projects offer the same approach to develop contracts, a language to be compiled into a privacy-preserving onchain + offchain cryptographic protocol.

Scalability

In both projects a contract is executed as on-chain + off-chain protocol so only reasonable minimum of data is going into a blockchain. Probably time will define a special kind transactional design for a blockchain better suited for storing a lot of certain factual information. At the moment both papers don’t imply blockchain implementation details.

Privacy

Approach to preserve privacy is different. Enigma uses [secure multi-party computations] (https://en.wikipedia.org/wiki/Secure_multi-party_computation)(SMC) based on Shamir’s secret sharing with MACs and commitments stored on the blockchain. A Hawk contract requires minimally trusted manager which cannot change outcome of a contract and also cannot aborts a protocol without losing its security deposit(but it can disclose private information involved).

Enigma vs. Hawk

Pretty short and concise Enigma whitepaper describes a platform concept consisting of blockchain, DHT(acting as general-purpose database) & SMC. Some practical aspects of the system e.g. fees & deposits are not well described yet though.

In contrast, much bigger Hawk paper isn’t about platform description mostly, but about a solid and proven approach to construct a compiler translating high-level programs written within ideal world model into real-world cryptographic protocol. I hope a whitepaper with a platform description will be released as well. From the paper, they have working compiler already at least.

Conclusion

It seems Enigma team is going to release more or less concrete smart contracts platform aiming to solve the most painful problems of nowaday solutions, namely scalability and privacy. Hawk team is going to open-source the framework, though it’s not clear at the moment what will be there except of a compiler.

Both projects are very exciting and will move us to a next frontier in building a decentralized economies. So have luck both of the teams!

White Papers:

  1. Hawk: The Blockchain Model of Cryptography and Privacy-Preserving Smart Contracts. Available online at https://eprint.iacr.org/2015/675.pdf.

  2. Enigma: Decentralized Computation Platform with Guaranteed Privacy. Available online at http://enigma.media.mit.edu/enigma_full.pdf.

On the Way to a Modular Cryptocurrency, Part 2: Stackable API

| Comments

Introduction

The previous chapter, Generic Block Structure described how to split a blockchain-related core design of a cryptocurrency into two separate modules to wire concrete implementations in an application then.

A cryptocurrency core application provides some API for its user. In this chapter I will show how to split API implementation into pieces to wire it in an application then. The code is being used in the Scorex project, compact cryptocurrency core implementation for experiments.

Gluing Things Together

In the first place, some wrapper for Spray route is needed:

trait ApiRoute {
   val route: spray.routing.Route
}

Then an actor composing routes:

class CompositeHttpServiceActor(val routes: ApiRoute*) extends Actor with HttpService {

  override def actorRefFactory = context

  override def receive = runRoute(routes.map(_.route).reduce(_ ~ _))
}

And then to create a new piece of API, instance of ApiRoute overriding route value is needed, see “Longer Example” in spray-routing documentation for example of a route definition(or Scorex Lagonaki sources, scorex.api.http package).

Then to glue all things together, we just create concrete actor implementation and bind it to a port. Example from Scorex Lagonaki:

lazy val routes = Seq(
  AddressApiRoute()(wallet, storedState),
  BlocksApiRoute()(blockchainImpl, wallet),
  TransactionsApiRoute(storedState),
  WalletApiRoute()(wallet),
  PaymentApiRoute(this),
  PaymentApiRoute(this),
  ScorexApiRoute(this),
  SeedApiRoute
)

lazy val apiActor = actorSystem.actorOf(Props(classOf[CompositeHttpServiceActor], routes), "api")      

IO(Http) ! Http.Bind(apiActor, interface = "0.0.0.0", port = settings.rpcPort)       

On the Way to a Modular Cryptocurrency, Part 1: Generic Block Structure

| Comments

The Protocols Mess Problem

In a code of a today’s cryptocurrency logical parts are very couply tied making codebase hard to understand and change. This series of articles shows how the problem could be solved by introducing separate inter-changeable injectable modules. Preliminary article “The Architecture Of A Cryptocurrency” describes possible modules in a cryptocurrency design.

This article, the first in the series describes how a block structure and a block-related functionality could be defined agnostic to implementation details of two separate modules, consensus-related and transaction-related. Code snippets using Scala language are provided. The code is being used in the Scorex project, compact cryptocurrency core implementation for experiments.

Generic Block Structure

A block consists of:

  1. Pointer to previous block
  2. Consensus-related data, e.g. nonce & difficulty target for Bitcoin, generation signature & base target for Nxt.
  3. Transactions, the most valuable part of a block for users. Some transactions- or state-related data could be also included(e.g. Merkle tree root hash for transactions or whole state after block application)
  4. Additional useful information: block structure version, timestamp etc
  5. Signature(s)

(Please note in Bitcoin there’s no a signature of a block, while we’re going to add it to make things more generic)

Making a new cryptocurrency usually means to replace (2) or (3) or both with something new. So to have an ability to make experiments fast we need to introduce some flexible and modular approach to a block structure and corresponding functions.

In the first place, we are going to introduce generic block field concept wrapping any kind of data with a possibility of serialization into json & binary form:

abstract class BlockField[T] {
  val name: String
  val value: T

  def json: JsObject
  def bytes: Array[Byte]
} 

Then we can stack up blockfields into block, also introducing abstract ConsensusDataType & TransactionDataType types as well as abstract references to ConsensusModule & TransactionModule modules, where a module is a functional interface to be replaced with a concrete implementation then:

trait Block {
  type ConsensusDataType
  type TransactionDataType

  implicit val consensusModule: ConsensusModule[ConsensusDataType]
  implicit val transactionModule: TransactionModule[TransactionDataType]

  val consensusDataField: BlockField[ConsensusDataType]
  val transactionDataField: BlockField[TransactionDataType]

  val versionField: ByteBlockField
  val timestampField: LongBlockField
  val referenceField: BlockIdField
  val signerDataField: SignerDataBlockField
  ...

What both modules could have in common? Well, they are parsing data of a type they are parametrized with, producing a blockfield based on data and providing genesis block data details. Let’s extract this functionality into the common concept:

trait BlockProcessingModule[BlockPartDataType] {
   def parseBlockData(bytes: Array[Byte]): BlockField[BlockPartDataType]
   def formBlockData(data: BlockPartDataType): BlockField[BlockPartDataType]
   def genesisData: BlockField[BlockPartDataType]
}

Having this common ground, let’s define consensus and transaction interfaces.

Consensus Module

What can we do with consensus-related data from a block?

  • check whether a block is valid from module’s point of view, i.e. whether a block was generated by a right kind of participant in a right way

  • get block generator(s)(let’s not forget about multiple generators possibility, see e.g. Meni Rosenfeld’s Proof-of-Activity proposal http://eprint.iacr.org/2014/452.pdf)

  • calculate block generators rewards

  • get a score of a block. Score equals to 1 in case of longest chain rule or some calculated value relative to difficulty in case of cumulative difficulty to be used to select best blockchain out of many possible options

Also, we can add a function to generate a block here, taking private key owner(to sign a block) and transaction module (to form transactional part of a block) as parameters

Considering all the functions, we can encode the interface now:

trait ConsensusModule[ConsensusBlockData] extends BlockProcessingModule[ConsensusBlockData]{
  def isValid[TT](block: Block, history: History, state: State)(implicit transactionModule: TransactionModule[TT]): Boolean
  def generators(block: Block): Seq[Account]
  def feesDistribution(block: Block): Map[Account, Long]        
  def blockScore(block: Block, history: History)(implicit transactionModule: TransactionModule[_]): BigInt
  def generateNextBlock[TT](account: PrivateKeyAccount)(implicit transactionModule: TransactionModule[TT]): Future[Option[Block]]
}

Transaction Module

We are going to consider a transactional part of a cryptocurrency, the most useful for an end user. An user isn’t using blockchain directly, querying some state instead:

  • There’s some initial state of the world stated in the first block of a chain( genesis block )
  • Then each block carries transactions which are atomic world state modifiers

Probably State monad could be helpful here, but for start(as we are rewriting existing project not using a true functional approach) the state interface is:

trait State {
  def processBlock(block: Block, reversal: Boolean): Unit
}

Please note no any querying functions are listed in the basic trait, as we are going to make state design stackable. For example, if it’s possible for a cryptocurrency to support balance querying for an arbitrary account following trait could be mixed with the basic one:

trait BalanceSheet {
  def balance(address: String, confirmations: Int): Long
}       

to have a concrete interface to be implemented by a cryptocurrency like

trait LagonakiState extends State with BalanceSheet with AccountTransactionsHistory

In addition to state a history is to be stored as well(to send it to another peer for a reconstruction of a state, at least). Please note, history could be in a different form than the blockchain, for example, a blocktree could be explicitly stored, or blockchain with addition of block uncles as Ethereum does. I’m not going to provide History interface code here, but you can find it online.

So a transactional module contains references to concrete implementations of state and history, and few functions able to:

  • check whether a block is valid from module’s point of view(so whether all transactions within a block and transactions metadata e.g. Merkle tree root hash are valid)
  • extract transactions from a block
  • get transactions from unconfirmed pool and add corresponding metadata(on forming a new block)
  • clear duplicates from unconfirmed pool(on getting a block from the network)

The code reflecting requirements above is:

trait TransactionModule[TransactionBlockData] extends BlockProcessingModule[TransactionBlockData]{

  val state: State
  val history: History

  def isValid(block: Block): Boolean   
  def transactions(block: Block): Seq[Transaction]            
  def packUnconfirmed(): TransactionBlockData   
  def clearFromUnconfirmed(data: TransactionBlockData): Unit  
  ... 

The Concrete Implementation

To develop a concrete blockchain-powered product a developer needs to provide concrete implementations of state, history, consensus & transactions modules to glue them together then in an application.

To see how that’s done in Scorex Lagonaki, take a look into LagonakiApplication.scala. While Scorex is the name of an abstract framework, Lagonaki is the name of concrete implementation wiring together:

  • SimpleTransactionModule operating with just a sequence of simplest token transfer transactions without any metadata
  • Two 100% Proof-of-Stake consensus module implementations, one is Nxt-like, other is Qora-like. It’s possible to replace one consensus algorithm with another with just a single setting in application.conf.

Further Work

The resulting application wiring together modules is much leaner than before. Some work could be done further though:

A Cryptocurrency Architecture

| Comments

Though we have thousands cryptocurrencies buzzing around at the moment, all of them share the same implementation design. Basically every cryptocurrency implementation has following parts:

  • Network Protocol
  • Consensus Protocol
  • Transaction Protocol
  • Internal State

Network Protocol

P2P network is the core of a cryptocurrency, and the core is following some network protocol. It is pretty simple usually. For example, p2p network of a cryptocurency could be implemented with asynchronous exchange of the following messages:

  • M1: Serialized unconfirmed transaction
  • M2: Serialized block
  • M3: Blockchain quality score request(e.g. height for the Bitcoin, cumulative difficulty for the NXT).
  • M4: Blockchain quality score response
  • M5: Get known peers request
  • M6: Get known peers response
  • M7: Request a block for a certain height(or with a certain parent)

The minimalistic set is pretty similar to Scorex message types. Bitcoin has more complicated protocol for sure(https://en.bitcoin.it/wiki/Protocol_documentation#Message_types) as well as NXT.

Let’s consider an example of a blockchain downloading with messages types given above if peer A knows only peer B and has genesis block only. So possible interaction of A and outer world where A -> (B, M2) means (peer A sends an instance of message kind M2 to peer B):

  1. A asks B for peers: A -> (B, M5)
  2. A asks B for a B’s blockchain height: A -> (B, M3)
  3. B replies for the first message with known peers C & D: B -> (A, M6)
  4. B replies for the second message with it’s height H(B): B -> (A, M4)
  5. A asks C for its blockchain height: A -> (C, M3)
  6. A asks D for its blockchain height: A -> (D, M3)
  7. C replies with its blockchain height H©: C -> (A, M4)
  8. D replies with its blockchain height H(D): D -> (A, M4)

So A have 3 known heights H(B), H©, H(D) and a bigger height means better chain(for a Proof-of-Work cryptocurrency), so A chooses peer with a best chain, e.g. D. Then it’s going to download a chain from D with a following cycle:

  1. A asks D for a block with height (2,3,…,H(D)): A -> (D, M7)
  2. D replies with a block requested serialized into a binary form: D -> (A, M2)

Any real trace is much more complicated than this example :)

Consensus Protocol

By using network protocol a node can download one chain or another or even multiple chains(as different peers can have different chains). Then the question is what is the canonical chain shared by majority, the right kind of history an user can rely on. Consensus protocol aims to solve the problem.

A node follow rules to determine canonical chain like these:

  1. Every block in a chain must be valid as well as its signature

  2. Every block must have a valid reference to its parent with first block having reference to a genesis block which is constant for an each node

  3. Every block must be generated by a party having a right to produce it

  4. From multiple chains, one having maximum score is the canonical. If few chains have the same score first seen or a random one could be chosen

Some notes about the rules:

  • Block validity fact could be changed with a new software release. Most known example of that is Bitcoin network splitting caused by 0.8 release

  • In proof-of-work cryptocurrencies a party has a right to generate block if hash of its contents
    conforms to some condition(its cheap to calculate a hash and compare it with some value while it’s hard to iterate over nonce bytes to find such a hash). In proof-of-stake cryptocurrencies a party has verifiable right to generate a block if some pseudo-random value hit is less than stake-dependent target. It’s harder to design safe Proof-of-Stake cryptocurrency, for example, majority of such currencies are vulnerable to grinding attack(Nxt is not).

  • In Bitcoin “longest chain rule” being applied while in Nxt there’s another blockchain score function called “cumulative difficulty”

  • More details on the Nxt algo: http://chepurnoy.org/blog/2014/10/inside-a-proof-of-stake-cryptocurrency-part-2/

Transaction Protocol

A block contains transactions. A transaction is the global state modifier. In simplest case it modifies balance sheet. As there’s no central party, each node need to have the same state as others(for the same block height). So each node executes all the transactions coming within blocks, and validity rules must be same for each network participant.

A transaction could be implemented in different ways depends on goals:

  • In Bitcoin, transaction has multiple inputs and outputs with a script attached to every pin.

  • Ethereum has two transaction types, contract creation and message call. See the Yellow Paper for details: http://gavwood.com/Paper.pdf.

  • In Nxt, transaction has some money amount and attachments. There are some rules on attachments processing, e.g. some kind of attachment means plain or encrypted message while other means order on decentralized exchange. Such an implementation provides maximum performance for features but has own disadvantages(complicated code, hardforks on each software update).

Internal State

In Bitcoin node a can store no any state at all or use different formats for it, e.g. UTXO list or some indexes in addition. In contrast, Ethereum has state hash stored into each block, so each node must comply with state representation interface given in the Yellow Paper to check block validity. There’s also interesting proposal from Bill White(coming along with Coq theory) about using special kind of Merkle tree and storing its root into block for scalability’s sake: [http://qeditas.org/gitweb/?p=ledgertheory.git;a=blob_plain;f=lightcrypto.pdf;hb=HEAD] (http://qeditas.org/gitweb/?p=ledgertheory.git;a=blob_plain;f=lightcrypto.pdf;hb=HEAD).

The Protocols Mess Problem

The real problem of cryptocurrency development process is the mess of all the parts described above. The most known example, even simple change in software validation(so in Transaction Protocol) could causes
hardforking.

Phasing Transactions in Nxt Part 1: Introduction, Phasing-Safety

| Comments

Two-Phased Transactions are similar a bit to Bitcoin’s multisig transactions implementation in Nxt but different in many aspects as well.

Simplest example: Alice starts a Two-Phased transaction. In the first stage a transaction is included in a blockchain but it isn’t processed immediately and has the status of ‘pending’. For it to be processed, Bob has to complete the second phase of the transaction by approving it. This has to be done before the deadline set by Alice has elapsed.

Please note the biggest difference from Bitcoin’s multisig: phased transaction is going to be included into blockchain immediately.

Use cases

  • Bob approving a transaction of Alice
  • Shareholders voting whether to send another 1M Nxt to a marketing service or not
  • Multisig wallet protected from a hacker(think about BTER case etc) (needs Account Control)
  • Trustless escrows
  • Conditional or unconditional transaction happening in some certain moment in future

Features

  • most types of transaction could be 2-phased (but not all, see “Phasing-Safe Transactions” section)!
  • different consensus types: M-of-N account consensus,shareholders voting with assets, currency holders voting with a Monetary System currency units
  • possible vote threshold setting(e.g. only accounts holding 100+ assets could vote)
  • whitelist of voters
  • transaction could be released only prior to finishHeight(or at the height exactly )

Consensus(Voting) models

  • None - synthetic mode, used for unconditional transaction execution at some height in future
  • By account - 1 account is 1 vote
  • By balance - 1 nqt is 1 vote
  • By asset - 1 qnt(asset’s quant, so non-divisible part) is 1 vote
  • By MS currency - 1 unit is 1 vote
  • By transaction - phasing transaction becomes approved if there are transactions in blockchain with hashes set in phasing transaction
  • By hash - another synthetic mode, used for pay-with-secret

Phasing-safe transactions

Not all transaction types are phaseable, so some of them couldn’t be phased at all. Some phasing transactions are phaseable but not phasing-safe, means they doesn’t make sense as phasing transactions(e.g. message could be phased, but you can read it immediately) or there’s a risk a transaction couldn’t be applied at finish height due to some changes in the outer world’s state. Following table shows phaseable & safe transaction types. Please note unsafe phasing transaction could be pretty safe in some practical case, but that’s not guaranteed by the core.


Transaction Type Is Phaseable ? Is Safe ?
Payment Yes Yes
Arbitrary Message Yes No
Alias Assignment Yes No
Alias Sell Yes No
Alias Buy Yes No
Alias Delete Yes No
Poll Creation Yes No
Vote Casting Yes No
Phasing Vote Casting Yes Yes
Hub Announcement Yes Yes
Account Info Yes Yes
Asset Issuance Yes Yes
Asset Transfer Yes Yes
Ask/Bid Order Placement Yes Yes
Order Cancellation Yes Yes
Dividend Payment Yes Yes
DGS Listing / Delisting Yes Yes
DGS Price Change Yes No
DGS Quantity Change Yes No
DGS Purchase Yes No
DGS Delivery Yes No
DGS Feedback Yes No
DGS Refund Yes No
Forging Balance Leasing Yes Yes
Tagged Data Upload No -
Tagged Data Extend No -

Voting System Guide for Developers & Experienced Users

| Comments

This blogpost describes voting system presented in NRS(Nxt Reference Software) 1.5 for application developers & experienced users. For simple use cases, wallet’s UI is self-explanatory and enough.

Features

  • Different voting models supported: voting by account(1 account = 1 vote), balance(1 Nqt = 1 vote), asset balance(1 Qnt = 1 vote), or Monetary System token balance(1 currency unit = 1 vote)

  • Voting has finite predefined duration(finish block height, to say precisely)

  • Poll has minimum and maximum number of options to provide opinion for. E.g. choose from 2 to 5 options out of 8

  • Range is the vote parameter. E.g. give a rate from 0 to 10.

  • By combining number of options & range a lot of specific poll types could be done. E.g. binary poll is poll where range is from 0 to 1 (i.e. no or yes). UI can handles some ranges in such a meaningful way.

  • Anonymous voting ( https://bitbucket.org/JeanLucPicard/nxt/issue/176/private-polls ) is not implemented. It could be implemented with e.g. Blind signatures(https://en.wikipedia.org/wiki/Blind_signature) but it’s not known how to implement that on top of the blockchain. So it seems an anonymous voting could be implemented by trusted 3rd party services only.

Parameters

Voting models

Four voting models exist:

  • By account, 1 account = 1 Vote

  • By balance, 1 Nqt = 1 Vote (nqt, not nxt!)

  • By asset, 1 Asset Qnt = 1 Vote

  • By Monetary System token, 1 curency unit = 1 Vote

All the models could be enhanced by additional parameter, describing min balance in units(nqt/qnt/currency units).

Counting

Counting happens at the finish block height set during poll creation. And a vote being counted only if it satisfies poll parameters(min balance etc) at that finish height. Please note, a voter could vote with balance < min balance needed to vote(at height where vote has been sent), and that’s valid, but a vote will be counted only if balance >= threshold balance at poll finish height.

Mandatory Parameters

name - a poll’s title, no more than 100 characters

description - detailed poll description, no more than 1000 characters

options - possible options titles to choose from and give a rate to. Minimum one option, maximum 100.

votingModel - four possible values for by-account, by-balance, by-asset, by-token voting

finishHeight - block height in future poll is finishing and counting taking at. Minimum 1 block since inclusion height(so set current height + 2 at least), maximum 14*1440 blocks = 20160 blocks since inclusion height

minNumberOfOptions , maxNumberOfOptions - minimum and maximum number of options a voter can choose

minRangeValue , maxRangeValue - a vote’s value is within this range

minBalance - 0 by default. A vote is counted only if account balance @ finishing height (in nqts/qnts/MS tokens) >= minBalance. Mandatory for by-account voting (i.e. should be more than 0 in case of by-account voting)

minBalanceModel - used in by-account voting to distinguish which kind of units used for minbalance, nqt balance / assets / currency units. For last two options holdingId parameter is also required

Optional parameters

  • holdingId - for voting by assets or MS tokens, also used for minBalance in by-account voting

Notes

  • Voting by asset could be started by anyone, not just asset/currency issuer or even owner

HTTP API

  • Create poll

Use POST request to createPoll API call to create a new poll. Example with curl:

1
curl -d 'name=cryptos&description=rate+cryptos+you+like&finishHeight=300000&votingModel=1&minNumberOfOptions=1&maxNumberOfOptions=2&minRangeValue=-5&maxRangeValue=5&secretPhrase=very+secret+phrase&deadline=1000&feeNQT=1000000000&option00=nxt&option01=btc' http://localhost:6876/nxt?requestType=createPoll

Parameters:

name - mandatory - poll title, not longer than 100 chars

description - mandatory - detailed poll description, max 1000 chars

finishHeight - mandatory - height of block when voting will be finished i.e. counted(should be > current one)

votingModel - mandatory - by-asset, by-account, or by-balance. see corresponding numeric value below

minBalance - mandatory for by-account voting, optional for other types - min amount of money or assets to vote, in nxt or qnt. by default 0(if skipped)

minBalanceModel - mandatory for by-account voting - what kind of tokens to use for vote threshold, nqt/qnt/ms token. See below for possible field values.

minNumberOfOptions - mandatory - min number of options to choose

maxNumberOfOptions - mandatory - max number of options to choose

minRangeValue - mandatory - min vote value possible, no more than 100

maxRangeValue - mandatory - max vote value possible, no less than -100

holdingId - mandatory in case of by-asset voting, could be also usedin addition with minBalance in by-account voting - asset or ms token id in unsigned form

option00,option01,option02,option03,…option99 - titles of corresponding options, please note parameter is always with two digits, starting with 00

Use following numerical values to set voting model:

1
2
3
4
VotingModel.ACCOUNT = 0;
VotingModel.NQT = 1;
VotingModel.ASSET = 2;
VotingModel.CURRENCY = 3;   //MS Token

Use following numerical values to set voting minBalanceModel:

1
2
3
4
MinBalanceModel.NONE = 0;
MinBalanceModel.NQT = 1;
MinBalanceModel.ASSET = 2;
MinBalanceModel.CURRENCY = 3; //MS Token
  • Vote casting

Use POST request to castVote API call to send your vote to the NRS. Example:

1
curl -d 'poll=12528572507118413418&secretPhrase=secret+phrase&deadline=1000&feeNQT=100000000&vote00=1&vote00=0' http://localhost:6876/nxt?requestType=castVote

Parameters are pretty straightforward. Use poll’s transaction id as poll parameter value, use vote00..vote99 to provide weights for option00..option99 options.

Please note, poll should be included into the blockchain to vote on it.

  • Get poll data

Use GET request getPoll to get poll data, e.g.

1
http://localhost:6876/nxt?requestType=getPoll&poll=12528572507118413418 

could returns something like

1
{"minRangeValue":-5,"votingModel":1,"description":"rate cryptos you like","finished":false,"poll":"4555214309048629195","requestProcessingTime":1,"minNumberOfOptions":1,"minBalance":"0","accountRS":"NXT-DV37-DD8K-3Q74-8LE2W","name":"cryptos","options":["nxt","btc"],"finishHeight":300000,"maxNumberOfOptions":2,"minBalanceModel":1,"account":"7926777737834261541","maxRangeValue":5,"timestamp":45731391}
  • Get poll results

Use GET request getPollResult to get poll results, e.g.

1
http://localhost:6876/nxt?requestType=getPollResult&poll=12528572507118413418

example result:

1
{"votingModel":1,"minBalance":"0","options":["nxt","btc"],"finished":false,"poll":"4555214309048629195","requestProcessingTime":1,"minBalanceModel":1,"results":[{"result":"1942320000000","weight":"1942320000000"},{"result":"","weight":"0"}]}

“finished” value is false, so voting still happens!

The request accepts some interesting parameters: votingModel , holding , minBalance , minBalanceModel - you can play with these parameters to see how results could be different depending on polls' input parameters(with the same set of voters).

  • Get polls

Use POST request to getPolls :

1
curl -d 'account=7926777737834261541&firstIndex=0&lastIndex=5&includeFinished=true'  http://localhost:6876/nxt?requestType=getPolls

There’s additional includeFinished parameter(self-explanatory). If account=0, all limited by indexes polls in the chain (active only if includeFinished=false) will be returned.

  • Get vote(s) details

There’re two API calls to get vote details, getPollVote & getPollVotes . First one accepts poll & account parameters, while second accepts just poll (& firstIndex, lastIndex).

  • Search polls

Use searchPoll to find relevant polls by text query. Example query with all the four parameters possible.

curl -d ‘query=cryptos&firstIndex=0&lastIndex=5&includeFinished=true’ http://localhost:6876/nxt?requestType=searchPolls

Fees

If poll contains less than 20 options, fee for it’s creation is 10 Nxt, otherwise each additional option costs 1 Nxt as well.

Vote fee is 1 Nxt.

Settings

There’s only one setting at the moment which could be overriden in nxt.properties:

1
2
3
# If disabled, polls are not processed at finish height and results are not stored in the database.
# When requested, poll results will be calculated on-the-fly, if the votes are still available.
nxt.processPolls=true

Set the value to false if you run a lean node & don’t need for results of all the polls in the chain to be calculated & stored.

Use Cases & Application Ideas

Out of the scope of simple voting, there are a lot of possibilities Voting System provides:

  • Distributed shareholders meetings (using assets as voting rights)
  • Publicly verifiable community decisions (using e.g. Monetary System tokens as community currency)
  • Building consensus protocols on top of the blockchain with strong evidence of a consensus

  • (to be continued)

Internal details (for developers)

This section is for developers working with core, studying the NRS code, or writing apps working closely with the core(so using low-level Java API not HTTP, though that way isn’t recommended unless a developer knows why he’s doing that).

Attachments

There are two kinds of attachments related to voting system: MessagingPollCreation & MessagingVoteCasting. Also please take a look PollBuilder helper implementing Builder pattern to create MessagingPollCreation objects:

1
2
3
4
5
6
7
8
9
10
11
12
val pb = new PollBuilder(question, desc, options, finishBlockHeight, votingModel,
      minNumberOfChoices, maxNumberOfChoices, minRangeValue, maxRangeValue)

minBalanceOpt.map { mb =>
    minBalanceModelOpt match {
      case Some(minBalanceModel) => pb.minBalance(minBalanceModel, mb)
      case None => pb.minBalance(mb)
    }
}
holdingIdOpt.map(hi => pb.holdingId(hi))

issueTx(phrase, pb.build())

Transaction types

There are two transaction types related to VS: Messaging.POLL_CREATION and Messaging.VOTE_CASTING.

Getting data

Take a look to static methods of the Poll class to get data you want. E.g. getPoll(long id) returns poll by its id, getPollsByAccount returns polls created by an account specified etc.