Hi all. From the very beginning of my programming path, I was interested in networks and cryptography. And consequently, from the beginning of my journey, I studied C and I read Satoshi Nakamoto’s documentation. Then I started to learn Sharp. As soon as I saw a contest related to cryptocurrencies, I decided to participate.
Why did I choose that particular topic?
Searching the web, I found almost no meaningful information. Videos of the type “download the source code and change the name to your own” I am not satisfied. On this
I began to search and study this topic more diligently.
What language shall we write in?
The first thing to decide was what language to write in Immediately I thought about the pluses. But after searching for ready-made network libraries, I found nothing interesting for me personally. Therefore I realized that ideally suits Goland (Go). I even had a detailed documentation with the writing of ready-made libraries. But since experience with the above language I did not have, and to lose time, I did not want to choose #, because I had time to learn it well enough, and the experience of networking, especially peer-to-peer, it, I did not have. In general, the language was determined.
The basic concepts of cryptocurrencies.
Yes, we know what a cryptocurrency is, without a doubt. It is a set of nodes in a peer-to-peer decentralized network (Not to be confused with distributed), which send some packets. Often this is a pseudo-anonymous network, where the anonymity factor determines the number of intermediary nodes. This means that when doing any action, e.g. a transaction, the network address of the sender is not hidden, it is located in the network and is masked by the cryptographic address. In other words the destination node knows the address of the primary sender. Not the intermediary node but the sender. And if this node will be a controlled node, it will really know who the sender of the transaction is.
Regarding the blockchain, we know that it is a chain of blocks that contains the hash of the previous block and a list of transactions. At the end of each validated block, i.e. the one that was read and written to the blockchain, the miner (the one who read the block) will be rewarded.
And here appears the first problem of the bitcoin cryptocurrency, namely with its example we are going to write a blockchain, if more than 50% of network capacity is concentrated in one hands, then transaction can be forged (duplicated). Our powers start to mine and run the transaction through a grey tunnel, while we send a normal transaction to the network, it is confirmed while the grey one is confirmed too. Then main network rechecks counterfeit block and notices the discrepancy it returns the funds. As far as I understand it is almost never checked, although in 2013 a Chinese mining farm owned 55% of the capacity, I do not remember the name.
And another basic concept or notion is the complexity of the network. What is it? The hashing time of a block. For example every block in bitcoin must be confirmed in 10 minutes on average, so that no inflation could happen in the network and all bitcoins would not be mined before time. So it is regulated every 2016 blocks or 14 days respectively.
Regarding the structure of the balance is simple. This is good to see in the code. The only thing I would add is that there is no physical translation of the bits. What you see in the mempool is just a transfer of rights or hashing part of your bits with someone else’s key. The process is not complicated. Each subject has a private key and a public key (think of it as a lock). The transaction algorithm is simple. The recipient sends the public key (the lock), the sender takes his private key, opens and removes his lock from his coins, puts the recipient’s lock on some of his bits that he wants to send and latches it. Now they can open only the recipient. In general, the concepts are solved, let’s move on.
When we have decided on the language and know what we need to program, we just need to implement it. I will be writing in Visual Studio with version 9 of Sharp, .Net Core, a console application.
Here we go,
This is our main. This is where we are going to do all the necessary manipulations. We connect JSON, to output the blockchain.
Initialize fields and class instances. Create our first empty block, it will differ from the others only by the fact that it will not contain a pointer to the previous block. Next, we open our server, as the network is peer-to-peer, the node can both receive and send packets. The menu itself by default I have made using the switch.
using Newtonsoft.Json;
using System;
namespace BlockchainCore
{
class Program
{
public static int Port = 334;
private static P2PServer _server;
private static readonly P2PClient Client = new P2PClient();
public static Blockchain Coin = new Blockchain();
private static string _name = “2”;
static void Main(string[] args)
{
Coin.InitializeChain();
if (args.Length >= 1)
Port = int.Parse(args[0]);
if (args.Length >= 2)
_name = args[1];
Console.Clear();
if (Port > 0)
{
_server = new P2PServer();
_server.Start();
}
if (_name != “Unkown”)
{
Console.WriteLine($ “Current user name {_name}”);
}
Console.WriteLine(“=========================”);
Console.WriteLine(“1. Connect to the server”);
Console.WriteLine(“2. Add transaction”);
Console.WriteLine(“3. Print blockchain”);
Console.WriteLine(“3. Print balance”);
Console.WriteLine(“5. Exit”);
Console.WriteLine(“=========================”);
int selection = 0;
while (selection != 5)
{
switch (selection)
{
case 1:
Console.WriteLine(“Enter the server URL”);
string serverUrl = Console.ReadLine();
Client.Connect($”{serverUrl}/Blockchain”);
break;
case 2:
Console.WriteLine(“Enter recipient address: “);
string receiverName = Console.ReadLine();
Console.WriteLine(“Enter the amount to send: “);
string amount = Console.ReadLine();
Console.WriteLine(“Enter comment: “);
string comment = Console.ReadLine();
Coin.CreateTransaction(new Transaction(_name, receiverName, int.Parse(amount),comment));
Coin.ProcessPendingTransactions(_name);
Client.Broadcast(JsonConvert.SerializeObject(Coin));
break;
case 3:
Console.WriteLine(“Blockchain”);
Coin.GetBalance(null) ;
Console.WriteLine(JsonConvert.SerializeObject(Coin, Formatting.Indented));
break;
case 4:
Console.WriteLine(“Balance ” + Coin.GetBalance(_name));
;
break;
}
Console.WriteLine(“Choose action “);
string action = Console.ReadLine();
selection = int.Parse(action);
}
Client.Close();
}
}
}
Now in detail point by point.
First point.
This is the connection to the node. Here the Connect method takes the node address as an argument
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using WebSocketSharp;
namespace BlockchainCore
{
public class P2PClient
{
IDictionary
public void Connect(string url)
{
if (!wsDict.ContainsKey(url))
{
WebSocket ws = new WebSocket(url);
ws.OnMessage += (sender, e) =>
{
if (e.Data == “Hi Client”)
{
Console.WriteLine(e.Data);
}
else
{
var newChain = JsonConvert.DeserializeObject
if (!newChain.IsValid() || newChain.Chain.Count <= Program.Coin.Chain.Count) return;
var newTransactions = new List
newTransactions.AddRange(newChain.PendingTransactions);
newTransactions.AddRange(Program.Coin.PendingTransactions;)
newChain.PendingTransactions = newTransactions;
Program.Coin = newChain;
}
};
ws.Connect();
ws.Send(“Hi Server”);
ws.Send(JsonConvert.SerializeObject(Program.Coin));
wsDict.Add(url, ws);
}
}
public void Send(string url, string data)
{
foreach (var item in wsDict)
{
if (item.Key == url)
{
item.Value.Send(data);
}
}
}
public void Broadcast(string data)
{
foreach (var item in wsDict)
{
item.Value.Send(data);
}
}
public IList
{
IList
foreach (var item in wsDict)
{
servers.Add(item.Key);
}
return servers;
}
public void Close()
{
foreach (var item in wsDict)
{
item.Value.Close();
}
}
}
}
Let’s break it down. The method is written based on the Websock library. To be honest, I stole this part. But I can say that we accept the network blockchain, if it is bigger than our own, we initialize the connection and send a verification message to the server. The methods below are needed to manage the added blockchain and close the socket that sends.
And of course the methods of creating transactions are used. Read about them below.
And so let’s proceed directly to the creation of the transaction. This is item 2 of our menu.
Here we specify the recipient, the amount and the comment.
We use 2 methods from the blockchain class, namely CreateTransaction and ProcessPendingTransactions.
Consider the Blockchain class and their implementation.
using System;
using System.Collections.Generic;
namespace BlockchainCore
{
public class Blockchain
{
public IList
public IList
private int Difficulty { set; get; } = 2;
private int _reward = 5; //5 cryptocurrency
private string comment = null;
public void InitializeChain()
{
Chain = new List
AddGenesisBlock();
}
private Block CreateGenesisBlock()
{
Block block = new Block(DateTime.Now, null, PendingTransactions);
block.Mine(Difficulty);
PendingTransactions = new List
return block;
}
private void AddGenesisBlock()
{
Chain.Add(CreateGenesisBlock());
}
private Block GetLatestBlock()
{
return Chain[Chain.Count – 1];
}
public void CreateTransaction(Transaction transaction)
{
PendingTransactions.Add(transaction);
}
public void ProcessPendingTransactions(string minerAddress)
{
Block block = new Block(DateTime.Now, GetLatestBlock().Hash, PendingTransactions);
AddBlock(block);
PendingTransactions = new List
CreateTransaction(new Transaction(null, minerAddress, _reward,comment))
}
private void AddBlock(Block block block)
{
Block latestBlock = GetLatestBlock();
block.Index = latestBlock.Index + 1;
block.PreviousHash = latestBlock.Hash;
block.Hash = block.CalculateHash();
block.Mine(Difficulty);
Chain.Add(block);
}
public bool IsValid()
{
for (int i = 1; i < Chain.Count; i++)
{
Block currentBlock = Chain[i];
Block previousBlock = Chain[i – 1];
if (currentBlock.Hash != currentBlock.CalculateHash())
{
return false;
}
if (currentBlock.PreviousHash != previousBlock.Hash)
{
return false;
}
}
return true;
}
public int GetBalance(string address)
{
int balance = 0;
for (int i = 0; i < Chain.Count; i++)
{
for (int j = 0; j < Chain[i].Transactions.Count; j++)
{
var transaction = Chain[i].Transactions[j];
if (transaction.FromAddress == address)
{
balance -= transaction.Amount;
}
if (transaction.ToAddress == address)
{
balance += transaction.Amount;
}
}
}
return balance;
}
}
}
Again we initialize fields, transaction array, accessors, reward size. Don’t forget about encapsulation of fields, we don’t want anyone to change award size.
Let me remind you that method we need is CreateTransaction, it takes our transaction. And adds it to the list.
namespace BlockchainCore
{
public class Transaction
{
public string FromAddress { get; set; }
public string ToAddress { get; set; }
public int Amount { get; set; }
public string Comment { get; set; }
public Transaction(string fromAddress, string toAddress, int amount,string comment)
{
FromAddress = fromAddress;
ToAddress = toAddress;
Amount = amount;
Comment = comment;
}
}
}
Next comes the transaction payment method ProcessPendingTransactions , which in turn takes the address of the miner or in our case the sender. The point is that our network is very small and I didn’t want to separate nodes as miners and users. I didn’t want to divide nodes into miners and users. That’s why the sender will confirm his transaction and get the rewards.
AddBlock adds the transaction to the block and creates it. Consider the class of the block.
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
namespace BlockchainCore
{
public class Block
{
public int Index { get; set; }
private DateTime TimeStamp { get; set; }
public string PreviousHash { get; set; }
public string Hash { get; set; }
public IList
private int Nonce { get; set; }
public Block(DateTime timeStamp, string previousHash, IList
{
Index = 0;
TimeStamp = timeStamp;
PreviousHash = previousHash;
Transactions = transactions;
}
public string CalculateHash()
{
var sha256 = SHA256.Create();
var inputBytes = Encoding.ASCII.GetBytes($”{TimeStamp}-{PreviousHash ? “}-{JsonConvert.SerializeObject(Transactions)}-{Nonce}”);
var outputBytes = sha256.ComputeHash(inputBytes);
Console.WriteLine(Convert.ToBase64String(outputBytes));
return Convert.ToBase64String(outputBytes);
}
public void Mine(int difficulty)
{
var leadingZeros = new string(‘0’, difficulty);
while (Hash == null || Hash.Substring(0, difficulty) != leadingZeros)
{
Nonce++;
Hash = CalculateHash();
}
}
}
}
private void AddBlock(Block block)
{
Block latestBlock = GetLatestBlock(); // Gets the number of the previous block
block.Index = latestBlock.Index + 1; // Indicates the number of the current block being created
block.PreviousHash = latestBlock.Hash; // Specifies the hash of the previous block
block.Hash = block.CalculateHash(); // Hash the current block
block.Mine(Difficulty); // calls hash method and tells how many
// zeros needed for the hash to be valid.
Chain.Add(block); // Add block to the blockchain
}
The methods implementation is described above in the Block.
The third point . Doesn’t need any explanation. With the help of standard items we output the blockchain to the console.
The fourth point. Find out the balance.
public int GetBalance(string address)
{
int balance = 0;
for (int i = 0; i < Chain.Count; i++)
{
for (int j = 0; j < Chain[i].Transactions.Count; j++)
{
var transaction = Chain[i].Transactions[j];
if (transaction.FromAddress == address)
{
balance -= transaction.Amount;
}
if (transaction.ToAddress == address)
{
balance += transaction.Amount;
}
}
}
return balance;
}
Nothing complicated. It’s as simple as a broom. We collect and summarize all incoming transactions, except for those that were sent to themselves. Later I will comment out this part, because I can not create a network of at least two nodes, and for the sake of visualization. The logic of the program will be affected to a minimum.
Oh yes, I almost forgot. Remember at the beginning I wrote that the network is peer-to-peer and the node is both sender and receiver. We need one more class to bring up the server on the node.
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using WebSocketSharp;
using WebSocketSharp.Server;
namespace BlockchainCore
{
public class P2PServer: WebSocketBehavior
{
private bool _chainSynched;
private WebSocketServer _wss;
public void Start()
{
_wss = new WebSocketServer($”ws://127.0.0.1:{Program.Port}”);
_wss.AddWebSocketService
_wss.Start();
Console.WriteLine($”Started server at ws://127.0.0.1:{Program.Port}”);
}
protected override void OnMessage(MessageEventArgs e)
{
if (e.Data == “Hi Server”)
{
Console.WriteLine(e.Data);
Send(“Hi Client”);
}
else
{
Blockchain newChain = JsonConvert.DeserializeObject
if (newChain.IsValid() && newChain.Chain.Count > Program.Coin.Chain.Count)
{
List
newTransactions.AddRange(newChain.PendingTransactions);
newTransactions.AddRange(Program.Coin.PendingTransactions;)
newChain.PendingTransactions = newTransactions;
Program.Coin = newChain;
}
if (!_chainSynched)
{
Send(JsonConvert.SerializeObject(Program.Coin));
_chainSynched = true;
}
}
}
}
}
Logic is not complicated, something similar to the client. Raise the server, in my case on the local, and receive or send motions, and insure against errors.
Screenshots of work.
1. Start the node and connect to the same.
image.png.5aced90234fcc50255dc560fc0ec6f87.png
Create transaction. Write the recipient (ourselves)
image.png.6cd0f3a1ecf9b007b917f48fda9fdd47.png
Amount and comment
The mining process begins, I will not show it in full because there are so many combinations.
Next, we print our Blockchain. It still has 2 blocks and 1 transaction.
1. The “2” on the miner’s header is labeled, i.e. we are
2. 0 block
3. Our block and transaction to ourselves of 100 coins.
Our block contains 2 transactions after which we create a new one.
image.png.42a40dff9ae4bae1dfdc23fb5de827b1.png
And so, if you put it all together, we get a working blockchain, which was written in an hour. All the concepts and original logic of cryptocurrencies were followed. And now we know how cryptocurrencies work. I want to say and warn you right away: I am not a guru and master, I started to study crypto so low-level not so long ago, and in my article there may be errors, if you found them write, I will try to correct them. Also I want to remind you that this is not super ready crypto-project, but just a simple layout, which will help you in the beginning of the study of network programming and cryptography. Do not be biased, I understand that now a lot of interesting projects, which use complete anonymity with polymorphism of packets and sending them to all nodes of the network. Just look at CHIA, with their new concept of Proof of Space. Maybe in the future I’ll write an article about what it is and how it works. But for now I have everything.
Learn programming and thank you for reading and evaluating my article!