Scorex: A Modular Blockchain, Scala Framework

Reading Time: 5 minutes

Scorex is an open-source project written in Scala with loosely coupled and pluggable components. Scorex provides many abstractions for which you have to provide concrete implementations to make the Blockchain as per your requirements on the top of Scorex. It is backed by IOHK, a technology company based in Hong Kong. Scorex is still experimental and raw. It appears to be in an early stage of development. All the information that I provide here is as per my understanding of the framework.

With the help of Scorex you can choose and combine various consensus and transactional protocols with a networking infrastructure provided by Scorex itself. Scorex code is compact and functional, build on Scala language that runs on JVM. Scorex provides an Asynchronous network layer on top of TCP. Cryptographic primitives of Scorex are externalized into a separate Scrypto framework. I have come across two out-of-box running applications based on Scorex – Lagonaki and Twinscoin. Their official website describes two main reasons for building Scorex.

  1. Bitcoin Core source code has more 100K lines of code, Nxt Blockchain has more than 45K lines of Java code. In contrast, Scorex has less than 4K lines of Scala code.
  2. New coins are trying to make money immediately, often having just one or two pretty controversial features. Scorex is the free and open tool aiming to make other systems development easier.

Cryptocurrency Architecture:

Basically, every Cryptocurrency implementation has following parts:

  1. Network Protocol :
    P2P (peer to peer) network is a core of every cryptocurrency. In Scorex, it is implemented by an asynchronous exchange of messages using Akka actors-based messaging framework. All the network and node settings of P2P network are done in settings.conf file.
  2. Consensus Protocol:
    In a Blockchain system, consensus protocol checks whether a block is generated by a right party in a right way or not. 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 the majority, the right kind of history a user can rely on. Consensus protocol aims to solve this problem.
  3. Transaction Protocol:
    A block contains transactions. A transaction is the global state modifier. In the simplest case, it modifies the balance of an account. As there’s no central party, each node needs to have the same state (Minimal State) as others. So each node processes all the transactions coming within blocks and applies validity rules.
  4. Internal State:
    Every node must maintain some internal state in order to verify the transactions.
    Internal state can be represented in two ways: Box representation (Immutable and locked by a proposition) or Account representation(mutable).

Let’s have a look at a few abstractions of Scorex and their use cases:

Common Abstractions in Scorex:

1. A Node View

A node view stores some minimal state as other honest nodes and local information derived from history and state stored locally in the node itself. It is a mechanism to store the instantaneous state of a node in the Blockchain system. It updates the view of a node after processing transactions. NodeViewHolder is a trait in Scorex that manages the node view of the node. It holds:

  1. MinimalState – It is also an abstract component(trait) which holds at least some state that tells whether a transaction initiated by the sender is valid or not. The apply function of this trait returns an updated state in case of a successful transaction or failure if the transaction is not applicable. In bitcoin, minimal state is maintained by Unspent Transaction Output Set (UTXO).
  2. History – It is a generic trait in Scorex. It contains a persistent log of previous transactions in the Blockchain system. An example of this is the Blockchain itself. History of a Blockchain system is in fact, some Blocktree, where the longest chain is being considered as canonical one, containing right kind of history.
  3. Memory pool – It is an unconfirmed transaction’s pool.
  4. Vault – It contains node-specific information like public keys, private keys, and addresses of accounts in the wallet.

Below is the code snippet of NodeViewHolder Trait in Scorex 2.0.



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


trait NodeViewHolder[P <: Proposition, TX <: Transaction[P], PMOD <: PersistentNodeViewModifier]
extends Actor with ScorexLogging {
type SI <: SyncInfo
type HIS <: History[PMOD, SI, HIS]
type MS <: MinimalState[PMOD, MS]
type VL <: Vault[P, TX, PMOD, VL]
type MP <: MemoryPool[TX, MP]
}

2. Node View Modifiers

A Node View (state of the node) can be modified by applying a Node View Modifier to it. There are two kinds of node modifier:

  1. Off-chain Transaction – It is not part of any history log and is processed only by using memory pool and wallet.
  2.  Persistent Node View Modifier – It is appended in the Blockchain using some consensus protocol like Proof of Work or Proof of Stake. All modifiers have identifiers of the same length which is to be set in application.conf  file (default length = 32 bytes).

3. Propositions and Proofs

Basically, an object for e.g. a box is protected by a proposition and a proof for that proposition is needed in order to modify (create or destroy ) that object.

In Scorex Blockchain is thought of as a mechanism to control access to some protected object (such as a box or unspent transaction output). The object is protected by proposition and some proof is required to modify that object. A proposition is just another abstract component in Scorex which can be serialized into bytes.
A proof is also a trait in Scorex which could satisfy a proposition given an additional input namely, message. It is a general abstraction of a fact a node can provide i.e a non-interactive proof to open a box or to modify an account.

4. Box

A box is a minimal state for e.g, an unspent output in bitcoin is a box. Basically, a box has some tokens associated with it and some proposition which protects the box. The tokens that the box hold can be spent only by someone who knows how to satisfy the proposition. In short, a box is a state element locked by some proposition.

Below is the code snippet of a Box in Scorex 2.0.



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


trait Box[P <: Proposition] extends BytesSerializable {
val value: Box.Amount
val proposition: P
val id: ADKey
}
object Box {
type Amount = Long
}
view raw

Box.scala

hosted with ❤ by GitHub

5. History

At the very basic level, Scorex doesn’t even have a notion of a Blockchain. This is done to support Blocktrees. In all global Blockchain networks, collisions are possible i.e two blocks referring to the same parent. So, in reality, the immutable ledger is not a Blockchain, in fact, it’s a Blocktree, where the chain with the highest score (e.g cumulative difficulty) is considered the canonical one that is the one containing the right history.

So Scorex has an abstract concept of history to log transactions in a Blockchain system, infinitely and is defined by the trait, History. It’s code snippet is given below:



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


trait History[PM <: PersistentNodeViewModifier, SI <: SyncInfo, HT <: History[PM, SI, HT]] extends HistoryReader[PM, SI] {
def append(modifier: PM): Try[(HT, ProgressInfo[PM])]
def reportModifierIsValid(modifier: PM): HT
def reportModifierIsInvalid(modifier: PM, progressInfo: ProgressInfo[PM]): (HT, ProgressInfo[PM])
def getReader: HistoryReader[PM, SI] = this
}
view raw

History.scala

hosted with ❤ by GitHub

6. SyncInfo Trait

Now in a peer to peer network, the node continuously tries to get alternative (possibly better) histories from the network around and also feed nodes with less developed history. To provide information on how much local history is developed, there is an abstract type SyncInfo. SyncInfo also provides information about starting points that this node recommends others to start synchronization from.



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


trait SyncInfo extends BytesSerializable {
def startingPoints: History.ModifierIds
}
view raw

SyncInfo.scala

hosted with ❤ by GitHub

7. Block

A block is an atomic piece of data that network participants agree on. A block has:

  1. Transactional data – A sequence of transactions. Some metadata is possible as well (transactions Merkle tree root, state Merkle tree root etc).
  2.  Consensus data – To check whether the block was generated by a right party in a right way. E.g. baseTarget and generatorSignature fields in an Nxt block structure, nonce and difficulty in a Bitcoin block structure.
  3.  Signature – It is a cryptographic signature, signing the block data.
  4. Additional data – Some additional data like Version Number, Timestamp etc. could also be a part of the block structure.



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


trait Block[P <: Proposition, TX <: Transaction[P]]
extends TransactionsCarryingPersistentNodeViewModifier[P, TX] {
def version: Version
def timestamp: Timestamp
}
object Block {
type BlockId = ModifierId
type Timestamp = Long
type Version = Byte
val BlockIdLength: Int = NodeViewModifier.ModifierIdSize
}
trait BlockCompanion[P <: Proposition, TX <: Transaction[P], B <: Block[P, TX]]
extends Serializer[B] {
def isValid(block: B): Boolean
def producers(block: B, history: History[B, _, _]): Seq[P]
}
view raw

Block.scala

hosted with ❤ by GitHub

Although being in an early stage of development and yet not production ready but the kind of research which is behind its development will surely make Scorex a successful modular framework written in Scala for Blockchain systems.

Thanks for reading. I hope this blog was helpful. 🙂

References:

  1. https://iohk.io/projects/scorex/
  2. http://chepurnoy.org/blog/2016/03/cryptocurrency-minimal-state-representation-boxes-vs-accounts/
  3. http://chepurnoy.org/blog/archives
  4. https://github.com/ScorexFoundation/ScorexTutorial/blob/master/scorex.pdf
  5. https://underscore.io/blog/posts/2017/12/14/scorex.html
  6. https://github.com/ScorexFoundation/Scorex
  7. https://www.slideshare.net/AlexChepurnoy/proofofstake-its-improvements-san-francisco-bitcoin-devs-hackathon

knoldus-advt-sticker

Written by 

Manjot Kaur is a software consultant, having more than 0.5 years of experience. She likes to explore new technologies and trends in the IT world. Her hobbies include Travelling, watching movies and running. She is currently working on Technologies like scala with maven, dynamoDb, Akka-Http.

1 thought on “Scorex: A Modular Blockchain, Scala Framework7 min read

Comments are closed.

Discover more from Knoldus Blogs

Subscribe now to keep reading and get access to the full archive.

Continue reading