# Dissecting Algorand

By [Satoshi Fan Club](https://paragraph.com/@satoshifanclub) · 2023-10-26

---

Popular Solutions using Algorand
================================

A few standup apps that use Algorand are Republic, Securitize, El Salvador’s blockchain infrastructure, Marshall Island’s digital currency, Orion Protocol, and DUST Identity.

![](https://storage.googleapis.com/papyrus_images/b7813a3ebc4086ecae8de3bd93782c9b.webp)

Consensus — Pure Proof of Stake
===============================

Pure Proof of Stake uses verifiable random function (VRF) as a weighted lottery where the weight is dependent on the number of ALGO’s someone owns.

VRF (Verifiable Random Function)
--------------------------------

VRF performs cryptographic sortition to select committees to run the consensus protocol. There are three parts to VRF, keygen, evaluate, and verify.

![](https://storage.googleapis.com/papyrus_images/84297e0cafe823d735750dc1e236f13b.webp)

Y, our random string is unique and pseudorandom, it looks random, but with the proof, you can verify it with the verification algorithm.

In Algorand, each user (Algo holder online) runs through the steps above. They hold a secret key SK (secret key) and VK (verification key), the VK is known publicly, all handled out of band. If these users want to participate in the committee to run the consensus, then they need to do the following:

1.  Compute _Evaluate(SK, Qr) → (Y, ⍴)_. Here, _Qr_ is a “magic” seed string available to everyone in the system.
    
2.  Check that _Y_ falls within a specific range _\[0, P\]_ that depends on the user’s stake in the system.
    

Algorand shared their VRF algorithm with Libsodium, check out the implementation below:

[https://github.com/algorand/libsodium/tree/draft-irtf-cfrg-vrf-03/src/libsodium/crypto\_vrf?source=post\_page-----e962f48f8c72--------------------------------](https://github.com/algorand/libsodium/tree/draft-irtf-cfrg-vrf-03/src/libsodium/crypto_vrf?source=post_page-----e962f48f8c72--------------------------------)

Below is the standardization on VRF by Sharon Goldberg, Moni Naor, Dimitris Papadopoulos, Leonid Reyzin, and Jan Včelák:

[

Verifiable Random Functions (VRFs)
----------------------------------

A Verifiable Random Function (VRF) is the public-key version of a keyed cryptographic hash. Only the holder of the private key can compute the hash, but anyone with public key can verify the correctness of the hash. VRFs are useful for preventing enumeration of hash-based data structures.

https://datatracker.ietf.org

![](https://storage.googleapis.com/papyrus_images/23920901f62a18c11e9545cb3953218a.png)

](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-03?source=post_page-----e962f48f8c72--------------------------------)

Don’t Fork With Me!
-------------------

An interesting feature of Algorand is that it’s not forkable.

![](https://storage.googleapis.com/papyrus_images/5e2fe96a71042f767ea50a71a9fba9c7.jpg)

**Side Note on Forking**

> Forking happens if two nodes get a valid block simulataneously and different users can’t agree on which block to take or an upgrade can’t be decided on. In these scenarios the chain splits in two and as new blocks are added to the chain one of them will get longer than the other. Eventually the longest one will stay and the shortest one will die off. When the shortest chain dies off, all the blocks in it, along with all the transactions will be considered invalid.

**Forking is not a bad thing.**

Algorand is built to prevent forks. It isn’t necessarily a positive feature, just another way of tackling the CAP theorem (Consistency, Availability, and Partition Tolerant). With blockchain networks like Solana, forks are created to rotate leaders quickly. Forking allows the network to process transactions quickly and keep moving when there are disagreements but sacrifices consistency in the process.

The benefit around this is there’s an assurance that transactions reach finality once they are complete (~5 seconds). In forkable networks, you need to wait after a certain amount of blocks (6 blocks is recommended in Bitcoin, which could be an hour) are added on top of the block to know your transaction is in and it’s finalized.

**How is Algorand Unforkable**

Algorand is unforkable because two blocks can never be propagated to the chain at once because only one block can have the required threshold of committee votes.

Below are the steps in the Algorand Consensus Protocol:

1.  **Proposal Phase**
    

Every node loops through online accounts with valid participation keys and selects an account. Now an account is selected, the other nodes verify the account was selected.

![](https://storage.googleapis.com/papyrus_images/d606e54c043c66fdfabb40205f30bffd.png)

**2\. Soft Vote Phase**

The number of proposals are narrowed down, and the nodes verify the signed messages and validate the selection using a VRF proof. The account with the lowest VRF hash is chosen to propose the next block.

![](https://storage.googleapis.com/papyrus_images/70598a563d958ad3ae2751cc8b0d9f79.png)

**3\. Certify Vote Phase**

A committee of 1,000 verifiers is pseudorandomly selected to receive information about the new block. Their job is to verify the block and mark it as valid or invalid. If the quorum is reached, the block is added to the blockchain.

> **If Quorum Not Reached — Network enters recovery mode but doesn’t fork**
> 
> The network would never fork instead it will enter the recover mode. In recovery mode recovery messages are sent out. Nodes will send these messages to signal to the network that it should either continue processing the last known block proposal or to propose a new block.
> 
> When a quorum of votes is received for either one of these messages, the system will revert to normal operation.
> 
> In the case of malicious behavior, the protocol may select a new leader. In the case of network outage, the current block will continue to be processed or a new block might be proposed.

Check out the video below to learn more about Pure Proof of Stake.

[![](https://paragraph.xyz/editor/youtube/play.png)](https://www.youtube.com/watch?v=u0ExeqpKJd0)

Or check out the white paper on the protocol:

[https://www.algorand.com/Algorand%20Protocol.pdf](https://www.algorand.com/Algorand%20Protocol.pdf)

Storage
=======

Internal Data Store in Nodes — SQLite
-------------------------------------

The ledger uses SQLite database as its internal store. This is where the algod process writes and reads data.

SQLite was chosen as it provides excellent storage performance, is embedded, lightweight, and fault-tolerant. Other databases might provide better indexing features — but these are not required for an algorand node.

A drawback behind using SQLite is the lack of control from a database standpoint. For instance, your flexibility would be limited if you wanted to optimize the database like add indexes, etc. It’s not a deal-breaker but something to ponder if you’re considering Algorand for government or financial projects where the organization has its database management strategies.

Relational databases are rare in the blockchain space. The norm is key-value databases (i.e., Bitcoin & Ethereum uses LevelDB, Solana & Polkadot uses RocksDB). These databases are lightweight and easy to scale out horizontally. The only other platform that uses relational databases is Corda R3.

Standalone REST API Data Store — PostgresSQL
--------------------------------------------

Indexer is a separate binary outside the Algorand node that acts as a REST API interface. It retrieves the blockchain data from a PostgresSQL database and is connected using an Algod process running on an Archival Algorand node.

![](https://storage.googleapis.com/papyrus_images/feaafaa8c8dd51bbba587050876a236c.png)

Below is an example of a query where we return the last 1000 transactions that exceeded ten microAlgos:

    #/indexer/python/search_transactions_min_amount.pyresponse = myindexer.search_transactions(min_amount=10)# Pretty Printing JSON string
    print(json.dumps(response, indent=2, sort_keys=True))

P2P Communication
=================

Relay Nodes
-----------

Accounts do not exchange messages directly; instead, they propagate their messages to a relay node. The relay node is untrustworthy, so to work around that, we use an encoding. One thing to keep in mind is that the relay nodes are permissioned nodes. They are registered with the Algorand foundation’s SRV records. This nudges Algorand towards a more centralized approach.

Serialization — MessagePack
---------------------------

All messages in Algorand are encoded using MessagePack, a binary serialization format that allows exchanges in languages like JSON.

[https://msgpack.org/?source=post\_page-----e962f48f8c72--------------------------------](https://msgpack.org/?source=post_page-----e962f48f8c72--------------------------------)

Communication Technology
------------------------

The network operates in a mesh network using WebSockets over HTTP (TCP). Algorand probably chose TCP because it’s commonly supported and can handle tasks like prioritizing queued messages.

Transaction Pools
=================

The transaction pool, also called the mempool in other networks, is where the transactions are held in memory and added into a block proposal.

A transaction pool prepares valid blocks for proposals and caches validated transaction groups.

At all times, the transaction pool maintains a queue of transaction groups slated for proposal. It checks that the transactions are properly-signed, the fees meet the minimum, and the state changes are consistent with the prior transactions in the queue. It does all of this work within a deadline; if it doesn’t finish by the deadline, it gets a buffer period it puts together an empty or partial block.

Fees
====

With every transaction, there’s a minimum transaction fee of 1,000 microAlgos or .001 Algos. On top of that, there is a fee per byte based on the estimated size of the transaction in bytes. If this fee is less than the minimum fee, it defaults to the minimum fee. To better understand the fees, you can use the SDK method suggested fee per byte (fee).

![](https://storage.googleapis.com/papyrus_images/2713ed57f908826a06bc646b47f8ffa2.png)

Check out the fee documentation below for details:

[https://developer.algorand.org/docs/get-details/transactions/?from\_query=fee&source=post\_page-----e962f48f8c72--------------------------------#fees](https://developer.algorand.org/docs/get-details/transactions/?from_query=fee&source=post_page-----e962f48f8c72--------------------------------#fees)

Minimum balance on Accounts
---------------------------

In Algorand, there is a required minimum balance of 100,000 microAlgos (today that’s ~$0.092373). If your transaction gets the balance below this minimum, it will fail.

FeeSink and RewardsPool
-----------------------

FeeSink is where all fees from transactions are sent. The FeeSink can only be spent towards the RewardsPool account. The RewardsPool account holds the Algos that need to be distributed as rewards to Algorand accounts in the protocol. As you can see in the code below, there’s a logic that only allows the FeeSink to send to the RewardPool.

![](https://storage.googleapis.com/papyrus_images/ce9bf0e48ec18ca8d2daf3bca8ec71e4.png)

Code from [https://github.com/algorand/go-algorand/blob/0e9cc6b0c2ddc43c3cfa751d61c1321d8707c0da/data/transactions/payment.go#L45](https://github.com/algorand/go-algorand/blob/0e9cc6b0c2ddc43c3cfa751d61c1321d8707c0da/data/transactions/payment.go#L45)

This approach is slightly centralized, the reward pool is just one address on the Algorand network. Below is the reward pool for mainnet:

![](https://storage.googleapis.com/papyrus_images/18576e16056a63bf264fcf41958a42a2.png)

Processes for Nodes
===================

There are two processes in Algorand, there’s KMD and Algod.

**KMD (Key Manager Daemon)** handles all interactions with spending keys, including signing transactions. Signing can also be standalone.

**Algod** is responsible for processing the protocol and interacting with SQLite to write records and implement REST API for reads.

![](https://storage.googleapis.com/papyrus_images/c7cc7cd16fd5ca2b75e30e55612d719c.png)

Algorand’s Smart Contract Language
==================================

Algorand uses TEAL (Transaction Execution Approval Language) and REACH.

Algorand smart contracts like Ethereum smart contracts have an Algorand address and can hold Algorand Assets (ASA’s) and Algos.

Refer to the docs to learn more about smart contracts:

[

Overview - Algorand Developer Portal
------------------------------------

Algorand Developer Docs, SDKs, REST APIs, CLI tools, ecosystem projects, metrics dashboard and sample code, how-tos, and news from the Algorand developer community

https://developer.algorand.org

![](https://storage.googleapis.com/papyrus_images/a233b7ce496aa107ed369bd36745cdfa.png)

](https://developer.algorand.org/docs/get-details/dapps/smart-contracts/apps/?source=post_page-----e962f48f8c72--------------------------------)

TEAL & PyTEAL
-------------

TEAL is an assembly-like language that’s processed in AVM (Algorand Virtual Machines). It’s a Turing-complete language that supports looping and subroutines has guardrails that limit the contract’s execution time using a **dynamic opcode cost evaluation algorithm**. You can either write TEAL or use pyTEAL to generate TEAL code.

In pyTEAL and TEAL programs, there are always two programs: the **Approval Program** and the other is the **Clear Program**. The approval program contains most of the business logic, and the clear program handles closing the account(s).

All communication with Algorand smart contracts is achieved through **application transactions.** Below are the six application transaction subtypes.

![](https://storage.googleapis.com/papyrus_images/6c5609f3e22a3fbf3f597d01fb47af1b.png)

**Approval Program**

As you can see in the NFT smart contract example below, all the meat sits in the approval program.

    from pyteal import *
    
    def approval_program():
        """
        This smart contract implements a Non Fungible Token
        Each NFT is an (ID, ref_data, hash) triple.
        NFT ID is the total count of NFT's in asc.
        ref-data is represented as "https://nft-name/<total>/nft-ref"
        hash is an hash of the external resources data.
        Commands:
            create    Creates a new NFT. Expects 2 additional arguments:
                        * nft-ref: a reference data (usually a URL or CID)
                        * nft-ref-hash: a hash of the underlying reference data
                        Only creator can create new NFTs.
            transfer  Transfers an NFT between two accounts. Expects one additional arg: NFT_ID.
                        Additionally, two Accounts(from, to) must also be passed to the smart contract.
        """
    
        var_total = Bytes("total")
        var_1 = Int(1)
    
        # Check to see that the application ID is not set, indicating this is a creation call.
        # Store the creator address to global state.
        # Set total nft count to 0
        on_deployment = Seq([
            App.globalPut(Bytes("creator"), Txn.sender()),
            Assert(Txn.application_args.length() == Int(0)),
            App.globalPut(var_total, Int(0)),
            Return(var_1)
        ])
    
        # Always verify that the RekeyTo property of any transaction is set to the ZeroAddress
        # unless the contract is specifically involved ina rekeying operation.
        no_rekey_addr = Txn.rekey_to() == Global.zero_address()
    
        # Checks whether the sender is creator.
        is_creator = Txn.sender() == App.globalGet(Bytes("creator"))
    
        # Get total amount of NFT's from global storage
        create_nft_id = Itob(App.globalGet(var_total))
    
        # create transaction parameters
        data_ref = Txn.application_args[1]
        data_hash = Txn.application_args[2]
    
        # var to store id_h
        id_h = ScratchVar(TealType.bytes)
    
        # Verifies if the creater is making this request
        # Verifies three arguments are passed to this transaction ("create", nft-name, nft-ref)
        # Increment Global NFT count by 1
        # Assign data_ref to NFT ID (= total)
        # Assign hash of nft-ref to ID_h
        # Add above two keys to global and creator's local storage
        create_nft = Seq([
            Assert(And(
                Txn.application_args.length() == Int(3),
                is_creator,
                no_rekey_addr
            )),
    
            App.globalPut(var_total, App.globalGet(var_total) + var_1),
    
            id_h.store(Concat(create_nft_id, Bytes("_h"))), # store id_h in scratchVar
            App.globalPut(create_nft_id, data_ref),
            App.globalPut(id_h.load() , data_hash),
    
            App.localPut(Int(0), create_nft_id, var_1),  # Int(0) represents the address of caller
            Return(is_creator)
        ])
    
        transfer_nft_id = Txn.application_args[1]  # this is only in the transfer condition
    
        # Verify two arguments are passed
        # Verify NFT_ID is present in global storage
        # Add nft to account_2's local storage
        # Remove nft from account_1's local storage
        transfer_nft = Seq([
            Assert(And(
                Txn.application_args.length() == Int(2),
                no_rekey_addr,
                # assert that a account_1 holds the NFT
                App.localGet(var_1, transfer_nft_id) == var_1
            )),
    
            App.localDel(var_1, transfer_nft_id),
            App.localPut(Int(2), transfer_nft_id, var_1),
            Return(var_1)
        ])
    
        # Verfies that the application_id is 0, jumps to on_deployment.
        # Verifies that DeleteApplication is used and verifies that sender is creator.
        # Verifies that UpdateApplication is used and blocks that call (unsafe for production use).
        # Verifies that closeOut is used and jumps to on_closeout.
        # Verifies that the account has opted in and jumps to on_register.
        # Verifies that first argument is "vote" and jumps to on_vote.
        program = Cond(
            [Txn.application_id() == Int(0), on_deployment],
            [Txn.on_completion() == OnComplete.UpdateApplication, Return(Int(0))], #block update
            [Txn.on_completion() == OnComplete.DeleteApplication, Return(is_creator)],
            [Txn.on_completion() == OnComplete.CloseOut, Return(var_1)],
            [Txn.on_completion() == OnComplete.OptIn, Return(var_1)],
            [Txn.application_args[0] == Bytes("create"), create_nft],
            [Txn.application_args[0] == Bytes("transfer"), transfer_nft]
        )
    
        return program
    
    if __name__ == "__main__":
        print(compileTeal(approval_program(), Mode.Application, version = 4))

**Clear State**

    from pyteal import *
    
    def clear_state_program():
        return Return(Int(1))
    
    if __name__ == "__main__":
        print(compileTeal(clear_state_program(), Mode.Application, version = 4))

I pulled the smart contract above from Algo-Builder’s smart contract template:

[

algo-builder/examples at master · scale-it/algo-builder
-------------------------------------------------------

Framework to automate development of Algorand Assets and Smart Contracts. - algo-builder/examples at master · scale-it/algo-builder

https://github.com

![](https://storage.googleapis.com/papyrus_images/9590c566e4b1a5d08ca4040891a201da.png)

](https://github.com/scale-it/algo-builder/tree/master/examples?source=post_page-----e962f48f8c72--------------------------------)

Reach (.rsh)
------------

Reach is a DApp framework that works with Algorand and Ethereum, most commonly used with Algorand. Reach aims at handling the whole experience, frontend, and backend. The backend is dealt with a file like index.rsh and the frontend in an index.mjs.

Get your hands dirty with Reach by running through the tutorial below:

[https://developer.algorand.org/docs/get-started/dapps/reach/?source=post\_page-----e962f48f8c72--------------------------------](https://developer.algorand.org/docs/get-started/dapps/reach/?source=post_page-----e962f48f8c72--------------------------------)

Where does it sit in the Blockchain Trilemma
============================================

Decentralization
----------------

Standing up an Algorand is quite simple. You can even get away running on your laptop. Making it easier for several people to start running their Algorand nodes. Surprisingly, there aren’t many nodes running today, as of today, 1/31/21, there are only 1,427 nodes running. Giving that number some context, today, 1/31/21, there are 2,052 nodes running with Ethereum.

The relay nodes have to be registered with Algorand. In a truly decentralized blockchain, everyone and their mom should be able to run any node. Even though all these Relay Node participants are from different companies and countries, there is a point of centralization because they are all approved by the same organization.

Algorand has no minimum to participate in proof of stake, which allows anyone to participate in proof of stake. Every Algo token in Pure Proof of Stake (PPoS) (the consensus algorithm) is considered a lottery ticket. There’s a chance that the consensus would choose you with just one Algo, but the chances of being chosen increase with more “lottery” or Algos you have.

Scalable
--------

With Algorand’s no-fork design and its use of SQLite, I don’t see how it can scale. This approach of approving one block at a time, transactions could pile up if there isn’t a consensus on what’s proposed, stalling the network.

Security
--------

Because Algorand is unforkable, it’s highly secure, and transaction finality is everything regarding government and financial records.

The way they separate the processors, algod and kmd, makes the reads and writes secure. Key management should always be handled separately from other blockchain duties.

Algorand’s approach of not using spending keys to participate in consensus keeps the network secure. Instead, participants use a participation key and a collection of ephemeral keys to sign off on consensus activities like block proposals, votes, etc. This approach prevents double signing and protects spending keys from ever being jeopardized in the case of a compromised node.

![](https://storage.googleapis.com/papyrus_images/8e5de7b9241fff12eefc13b5b443dff9.png)

Notes on Speed
==============

![](https://storage.googleapis.com/papyrus_images/84236a28647f2a21386a4f9e43984223.jpg)

Photo by [paolo candelo](https://unsplash.com/@paolocandelo?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com/?utm_source=medium&utm_medium=referral)

Algorand is currently at around ~1,000 TPS, faster than Bitcoin and Ethereum, but not as fast as other 3rd generation blockchain networks like Solana. Algorand has proposed in their performance report that with block pipelining, they can reach 46,000 TPS, but we’ll need to wait for that implementation to deploy onto mainnet.

In terms of finality, Algorand wins; they have a finality of 2.5 seconds because it’s finalized as soon as the transaction completes. We don’t have to wait for additional blocks to be added to know it’s truly final because of its no forking design.

The Algorand Foundation pulled these performance metrics from their 2021 performance report:

[https://drive.google.com/viewerng/viewer?url=https://www.algorand.com/120720-Algorand%25202021%2520Performance.pdf](https://drive.google.com/viewerng/viewer?url=https://www.algorand.com/120720-Algorand%25202021%2520Performance.pdf)

If you’re obsessed now, dive in with these resources.
=====================================================

**Official Repo**

[

GitHub - algorand/go-algorand: Algorand's official implementation in Go.
------------------------------------------------------------------------

Algorand's official implementation in Go. . Contribute to algorand/go-algorand development by creating an account on GitHub.

https://github.com

![](https://storage.googleapis.com/papyrus_images/f7a0c39f99cede4dc3da645691b308a6.png)

](https://github.com/algorand/go-algorand?source=post_page-----e962f48f8c72--------------------------------)

**Algorand Metrics Dashboard**

[

Algorand
--------

The AlgoGlobal Community works towards the goal of building a secure, scalable, decentralized network to serve as trusted public infrastructure for the common good.

https://forum.algorand.org

![](https://storage.googleapis.com/papyrus_images/508826ee68be4f6ed75287bee6ade9e7.png)

](https://forum.algorand.org/?source=post_page-----e962f48f8c72--------------------------------)

**Official Algorand Forum**

[

Algorand
--------

The AlgoGlobal Community works towards the goal of building a secure, scalable, decentralized network to serve as trusted public infrastructure for the common good.

https://forum.algorand.org

![](https://storage.googleapis.com/papyrus_images/f11df586be795b3bf441b8984fed85e9.png)

](https://forum.algorand.org/?source=post_page-----e962f48f8c72--------------------------------)

**CoMakery Algorand Security Token**

[

GitHub - CoMakery/algorand-security-token: Open Source security token compatible with CoMakery, authored in collaboration with the Algorand Foundation team
-----------------------------------------------------------------------------------------------------------------------------------------------------------

Open Source security token compatible with CoMakery, authored in collaboration with the Algorand Foundation team - CoMakery/algorand-security-token

https://github.com

![](https://storage.googleapis.com/papyrus_images/ca58a7ca89bfbdf9d980f86f449db453.png)

](https://github.com/CoMakery/algorand-security-token?source=post_page-----e962f48f8c72--------------------------------)

**Algorand Smart Contract Architecture**

[![](https://paragraph.xyz/editor/youtube/play.png)](https://www.youtube.com/watch?v=9EpGKexKeMk)

**Tutorial on Atomic Transfers on Android**

[

GitHub - gconnect/AlgorandPayrollContract: This is an android app developed on the Algorand Blockchain
------------------------------------------------------------------------------------------------------

This is an android app developed on the Algorand Blockchain - gconnect/AlgorandPayrollContract

https://github.com

![](https://storage.googleapis.com/papyrus_images/91caa5712b97d716320675ea1e18d0ca.png)

](https://github.com/gconnect/AlgorandPayrollContract?source=post_page-----e962f48f8c72--------------------------------)

---

*Originally published on [Satoshi Fan Club](https://paragraph.com/@satoshifanclub/dissecting-algorand)*
