Implementing a Hypothetical Currency Application on EOS

Today we are excited to share with you the first sneak peak of how EOS works and how developers build applications.

High Level Introduction

EOS is structured like a group of people and/or scripts (bots) that are exchanging messages between them. It could be thought of as an email system where every user or bot has an account.

Like email, messages have a sender, receiver, and potentially a couple of accounts that are copied on the message. Also like email, messages are not guaranteed to be delivered just because they were sent. Delivering a message implies that the receiver accepted the message and processed it according to the receivers code.

Unlike e-mail, the recipient and any accounts copied on the message have the ability to reject the message in which case the message will not be delivered to them.

The EOS blockchain is a transparent and permanent log of all messages that were successfully delivered to all addressed accounts, but may also include outgoing messages generated by a bot.

Publish Code not Binary

When we describe "bots" we are referring to self-executing source code published on the blockchain. An account (aka application or smart contract) is a set of message handlers that can read/store state and/or generate new messages that are dispatched asynchronously to other accounts. Messages can be processed by different accounts in parallel because every account's state is private and inaccessible from other accounts.

Structure of an Application

Every account (aka application) has its own private database in which it can define any number of tables with a number of sorted indices per table. These database tables are used to store the state of your application. This state is described by a schema which makes it possible for general purpose block explorers to represent the state of all contracts in a meaningful way.

Every account can define any number of types, aka structs. These structs define the binary serialization of messages and enable anyone to convert the binary representations to and from canonical human readable JSON representations. This keeps the blockchain transparent for all while having efficient binary encodings.

Lastly every account can define what actions it wants to take when it is copied on a message delivered to any other account. For example, an exchange needs to process deposits when a Transfer message is delivered to a currency application and the exchange application is the recipient.

Example Currency Application

One of the simplest applications is a currency. This example will walk through how a currency application could be structured on EOS.

Disclaimer

The following example code is for conceptual purposes only and final implementation details will certainly be different.

Basic Currency Contract

When writing an application you start by asking yourself what actions are taken by the actors (aka accounts), then you define the database schema which stores and indexes data derived from these actions. After you have defined these things you specify the logic that transforms database state based upon an incoming action. Lastly, you (optionally) group message handlers into permission groups.

Let's look at a simple high-level application that implements a currency. A currency can be represented as a table mapping the owner to their balance. It allows the owner of the balance to transfer funds to another account and will create a new balance entry for that account if one does not exist. It must prohibit sending money to yourself and require that the amount transferred is greater than 0. Initially all the money is owned by the contracts own account. Any time a balance reaches 0, the account's balance record should be deleted.

struct Transfer
  to      AccountName
  from    AccountName
  amount  UInt64

struct Init

table Balance
  owner   AccountName
  balance UInt64

on Init action
   precondition:
     eos.requireAuthority( eos.thisAccount() )
     eos.require( !Balance.find( eos.thisAccount() ) ) /// only call once

   apply:
     self         = Balance.new()
     self.owner   = eos.thisAccount()
     self.balance = 100000  /// maximum currency supply
     Balance.save(self)


on Transfer action
   validate:
     // static validation, verifies action is internally consistent
     // no access to database tables
     eos.require( action.amount > 0 ) 
     eos.require( action.to != action.from ) 
     eos.requireNotify( action.to ) 

   precondition:
     // identify possible precondition check that can 
     // be executed with readonly access
     eos.require( Balance[action.from].balance >= action.amount )
     eos.requireAuthority( action.from )

   apply:
     // assuming all prior steps pass, perform the state transition
     // that updates balances and/or creates a new account for receiver
     var from = Balance[message.from]
     var to   = Balance.find( action.to )

     if( !to ) {
        to         = Balance.new()
        to.owner   = action.to
     }

     from.balance = from.balance - action.amount
     to.balance   = to.balance   + action.amount

    Balance.save(to)

    if( from.balance > 0 )
        Balance.save(from)
    else if( from != eos.thisAccount() ) 
        Balance.delete(from)

Things to Notice

Event handlers are divided into three sections: validate, precondition, and apply. These different sections separate out processing into distinctly different phases which enables performance optimizations and parallelism. The validate, and precondition checks are all read-only which means they can be processed in parallel.

The apply step is the only part that needs to be performed to regenerate the current database state from the history of pre-verified actions. This is critical because it is much cheaper to process calculations in validate and precondition than it is in apply. Once a block is deemed irreversible validate and precondition never have to execute again whereas apply must be executed to generate the deterministic state every time the blockchain is synchronized.

Stay Tuned

Stay tuned for more information on how decentralized applications communicate on EOS. Also, don't forget to signup to our mailing list at http://eos.io.

H2
H3
H4
3 columns
2 columns
1 column
47 Comments