Creating Simple Cryptocurrency using .NET and C# — Part 2. Database
In the previous post, I created a simple blockchain application, which can make transactions, enter transactions into blocks, and insert blocks into the blockchain. The block collection already forms a chain, where the block has the hash of the previous block and the hash of the current block.
Requirement
.NET SDK 5.0
Visual Studio Community Edition
In this post, I will continue to develop the application. I will add two things to the application: menu and database.
The Menu
With the menu, users can interact with applications interactively.
I designed the menu to have items that are common in crypto applications, such as checking balances, sending coins, seeing the genesis block, seeing the last block, and viewing the entire blockchain content.
- Genesis Block — to get the first block in the blockchain
- The last Block — to get the last block in the blockchain.
- Send Coin — to send coins from sender to recipient, it will ask amount and transaction fee.
- Create Block — to make a block. Once the user adds some transaction in the pool the transaction will be included in the block and the block will be added to the blockchain.
- Check Balance — To check the balance of the user.
- Transaction history — to get the transaction history of a user.
- Blockchain Explorer — to display all blocks in the blockchain.
- Exit — to close the application.
Once the application runs, it will ask the user to select one of the menus. To achieve this goal I created a Menu class and placed it in the client folder.
To integrate the menu into the application, it is necessary to make changes to the Program class.
Database
We need a database to store data permanently. Most blockchain applications use standalone databases such as LevelDB, SQLite, H2, etc. Here I will use LiteDB https://www.litedb.org, a small library, fast enough when doing CRUD, documentation is quite complete.
Adding LiteDB to Project
To add LiteDB to our project, on the Visual Studio menu select “Project -> Manage NuGet Packages …” then search for LiteDB in the search box and press the Add Package button.
Create Database Initialisation
To use LiteDB in our application I create a new class DbAccess.cs inside the DB folder. When the application starts, first will execute the Initialize method and a new database example node.DB will be created in the root folder from which the application was started.
using LiteDB;
using Models;namespace DB
{
public class DbAccess
{ public static LiteDatabase DB { set; get; }
public const string DB_NAME = @"node.db";
public const string TBL_BLOCKS = "tbl_blocks";
public const string TBL_TRANSACTION_POOL =
"tbl_transaction_pool";
public const string TBL_TRANSACTIONS = "tbl_transactions"; /**
create db with name node.db
**/
public static void Initialize()
{
DB = new LiteDatabase(DB_NAME);
} /**
Delete all rows for all table
**/
public static void ClearDB()
{
var coll = DB.GetCollection<Block>(TBL_BLOCKS);
coll.DeleteAll(); var coll2 = DB.GetCollection<Transaction
(TBL_TRANSACTION_POOL);
coll2.DeleteAll(); var coll3 = DB.GetCollection<Transaction
(TBL_TRANSACTIONS);
coll3.DeleteAll();
} /**
* Close database when app closed
**/
public static void CloseDB()
{
DB.Dispose();
} }
}
There are 3 tables right now, tbl_blocks, tbl_transactions and tbl_transactions_pool.
- tbl_transactions_pool — to store all unconfirmed transactions. The contents of this table will be deleted after the block is created.
- tbl_blocks — to store all created blocks.
- tbl_transactions — to store all confirmed transactions.
Blockchain Class
With the use of databases, it is necessary to make changes to the Blockchain class which was previously designed to only use collection variables.
Here I will briefly describe each method in the Blockchain class.
Initialize
This method will check if there is no block in the blockchain, it will create a genesis block and transaction for the genesis account.
private static void Initialize(){ //get all block
var blocks = GetBlocks(); if (blocks.Count() < 1)
{
// Create genesis block
var gnsBlock = Block.Genesis();
blocks.Insert(gnsBlock); // create genesis transaction
CreateGenesisTransction();
}}
GetGenesisBlock
This method will get the first block on the blockchain, to do that is easy in LiteDB. What is genesis block?
var genesisBlock = blockchain.FindOne(Query.All(Query.Ascending));
GetLastBlock
The method will get the last block on the blockchain, so to do that is also easy in LiteDB. Why do we need the last block?
var lastBlock = blockchain.FindOne(Query.All(Query.Descending));
CreateGenesisTransaction
Blockchains that use Proof of Stake Consensus have one or more genesis accounts and each account has an opening balance. The genesis account will be embedded into the database when the application is executed for the first time.
For this post, I use an assumption that our blockchain has 2 genesis account with account name ‘ga1’ and ‘ga2’ each have an opening balance of 1.000.000 and 2.000.000.
public static void CreateGenesisTransction()
{
var newTrx = new Transaction()
{
TimeStamp = DateTime.Now.Ticks,
Sender = "system",
Recipient = "ga1",
Amount = 1000000,
Fee = 0
}; Transaction.AddToPool(newTrx); newTrx = new Transaction()
{
TimeStamp = DateTime.Now.Ticks,
Sender = "system",
Recipient = "ga2",
Amount = 2000000,
Fee = 0
}; Transaction.AddToPool(newTrx); // .....
}
AddBlock
This method is used to add a block to the blockchain
public static void AddBlock(Block block)
{
var blocks = GetBlocks(); //get block collection
blocks.Insert(block);
}
I have one question for you, why is there no method for Editing and Removing Blocks in blockchain applications?
The answer is Blockchain does not allow you to delete or edit blocks
Generally, once data is stored on the blockchain it can’t be manipulated or altered — it’s immutable.
The complete source code for the Blockchain class is here.
Transaction class
The Transaction class is a class that is responsible for transaction activities, such as adding a transaction to the pool, calculating balance, and getting transaction history.
AddToPool
This method will add transactions to the transaction pool. What is a transaction pool? The transaction pool is a temporary place for all transactions that are not merged into a block.
/**
* Add transaction to pool
**/
public static void AddToPool(Transaction transaction)
{
var trxPool = GetPool();
trxPool.Insert(transaction);
}
GetBalance
This method will give the balance to the user. The code will create a query in the transaction table and find the sender or recipient that is equal to the given name. This function will calculate the balance for the user using a formula.
// if send coin
spending = trx.Amount + trx.Fee;// if receive coin
income = trx.Amount;// calculate balance
balance = income - spending
The code snippet for GetBalance looks like this:
/**
* Get balance by name
*/
public static double GetBalance(string name)
{
double balance = 0;
double spending = 0;
double income = 0; var collection = GetAll();
var transactions = collection.Find(x =>
x.Sender == name || x.Recipient == name); foreach (var trx in transactions)
{
var sender = trx.Sender;
var recipient = trx.Recipient; if (name.ToLower().Equals(sender.ToLower()))
{
spending += trx.Amount + trx.Fee;
} if (name.ToLower().Equals(recipient.ToLower()))
{
income += trx.Amount;
} balance = income - spending;
} return balance;
}
GetHistory
This method will return all transactions that have a sender or recipient that equals a given name.
/**
* get transaction list by name
*/
public static IEnumerable<Transaction> GetHistory(string name)
{
var coll = DbAccess.DB.GetCollection<Transaction.
(DbAccess.TBL_TRANSACTIONS);
var transactions = coll.Find(x => x.Sender == name
|| x.Recipient == name); return transactions;
}
Testing the Application
Showtime to install and run the application, follow the steps below:
> mkdir ANY_FOLDER
> cd ANY_FOLDER
> git clone https://github.com/jhonkus/UbudKusCoin.git
> cd UbudKusCoin
> git checkout part_2b_database
> dotnet restore
> cd UbudKusCoin
> dotnet run
Steps to use this application:
- Send coins from ga1 to john
- Create block, must do this step otherwise john balance will still be 0
- Check balance for john
- Check transaction history for john
- Blockchain explorer
The Screenshot
Here are some screenshots of the application.
You can also watch the video tutorial on how to install and use UbudKusCoin here: https://youtu.be/TYM55x7I8us
What's Next?
I know that my application is still a long way from reaching a crypto application, take it easy, I will continue to work on this crypto application and write the steps here.
In the next post, I will add a Wallet and Keypair.
On the real blockchain, each account does not use a name as an identity but uses an address, public key, and private key.
Thank you for reading my post. If this post is helpful please give me a bunch of claps.
Post List:
Source code for this post:
https://github.com/jhonkus/UbudKusCoin/tree/part_2b_database