The client is a UI-based application that handles the following activities:
- Creation and Submission of Transactions
- Creation of Blocks
- Mining and Submission of Blocks
These three can further be subdivided into many more sub-categories, such as: UTxO Viewing, CoinBase Addition, Blockchain Status, etc.
The next few topics discuss how the client app works and how to use it correctly.
This is the first dialog you will come across when launching the application. It is the entrypoint of the client workspace, and where you must either first add a wallet or select an already added one.
You cannot create a wallet in the application. Instead you must generate one yourself using third-party applications.
A wallet is in essence is just a public/private key pair. You can generate a pair for yourself on free online sites. A good site I use myself is:
https://emn178.github.io/online-tools/ecdsa/key-generator/
Make sure you generate a SECP256K1 Key in Hex. If you are confused as to what that is, it means that your key-pair must look something like this:Private Key: 4c847b1984be5e3339c9386fa026c596bb799c121dea73a30d6cb28fe44414c9 Public Key: 04eeee76c4535c4c48f64c5c6cf7811ddb67c4b6dbee22d3b313f124deea127339a212a791ca1ac11dfe00b26b9edac53fb43c6c4d28bbecc3460a676f510428baRemember, the public key is always longer than the private key.
The public key generated is now your identity in the coin world. Any payments made will be made to this sequence of characters. The private key, on the other hand, is the password that gives you access to use the public key. Always keep this key safe, secure and, most importantly, hidden from others. Since everyone already knows your public key (hence the name), all that stands between your wallet and the world is your private key.
Once you have a wallet to add, you can fill the details into the fields and click on add wallet.
Naming your wallets is optional, but it is best practice to do so as it soon becomes very difficult to differentiate between multiple wallets based on their key sequences.
Once you've added a wallet, you can click on it in the wallets list to select it, and login using the login button.
The first thing you see after logging in to your wallet is the My Wallet tab. This is where you create transactions and view your UTxOs.
The UI may seem daunting at first but there are just four main elements that you need to understand to use your wallet:
- Output Transactions: The list of all transactions you make out (send coins to others)
- Input Transactions: The list of all transactions that were made out to you, and you haven't spent (UTxOs)
- Create Transaction Output: The form where you fill out the output details
- Transaction Data: The totals of your outputs, inputs and their remainder
Transactions in crypto work a little bit differently than in traditional banking systems. Instead of a balance that exists as a number under your account name, in crypto there are Unspent Transaction Outputs (UTxO).
Anytime someone pays somebody else, they create an output (think of it as them outputting coins). That output exists on the blockchain as an Unspent Transaction Output. This means that the person who recieved those coins in the output, can use this output to pay others.
They can do that by adding this UTxO as an 'input' to their own transaction. After that, they can create new outputs to other people, using these inputs as a backing.
Once they've used an UTxO as an input, they can never use it again, and it becomes 'spent'. Here's a quick example:Mei's Transaction: Inputs: 1. Some UTxO (Assume) Outputs: 1. Pay Chen, 20 DsCChen now has one UTxO to his name (you can say he has 20 DsC to his name). He can now use it to pay someone else by using it as an input:
Chen's Transaction: Inputs: 1. Mei's Transaction, Output no. 1, 20 DsC (the UTxO) Outputs: 1. Pay for Lobotomy, 20 DsCChen can not use the UTxO again now. He can also never output a higher amount than his input.
Additionally, Chen can also add multiple inputs from different senders to create a larger output:Chen's Transaction (redo): Inputs: 1. Mei's Transaction, Output no. 1, 20 DsC 2. Dad's Transaction, Output no. 3, 20 DsC (Assume) 3. Mom's Transaction, Output no. 2, 80 dSc (Assume) Outputs: 1. Pay for Better Lobotomy, 120 DsCIf Chen outputs less than his inputs total to, the remainder gets paid to Block Miners as fees (more on this later). If his inputs don't amount exactly to his outputs, he can add an output to himself for that amount.
Chen's Transaction (redo 2): Inputs: 1. Mei's Transaction, Output no. 1, 20 DsC 2. Dad's Transaction, Output no. 3, 20 DsC (Assume) 3. Mom's Transaction, Output no. 2, 80 dSc (Assume) Outputs: 1. Pay Lobotomy Cancellation Fees, 110 DsC 2. Pay Chen, 10 DsC (remainder)To create a transaction, you must create your outputs. This is where you specify who you wish to pay, and how much. You may add as many outputs to as many people as you wish, but you must have sufficient inputs to back them up.
Enter the details of your output in the form to create an output:
- Recipient's address (their public key)
- Amount (in DsC)
- Output name (optional, but best practice)
You can now view your output in the outputs list.
Next, you must add the necessary inputs to back your outputs. First refresh the inputs list to get your latest UTxOs:
IMPORTANT: You must be connected to a node in order to load your latest UTxOs.
Next, select the checkbox on the UTxOs you want to select. You can use the Select All button to select all UTxOs if you don't have that many (if you're broke).
You can also see the total of all selected UTxOs below the list.
The Transaction data below shows you the totals of your outputs and inputs. It also shows the remainder. If remainder is negative, you must add more inputs, or your transaction is invalid.
If you wish to pay off the remainder as fees to the miner, you may submit the transaction as is. However, if you want your money back, you can click on the Add Remainder button to create an output that pays yourself the amount.
Once everything is confirmed, you can finally sign and submit the transaction to the blockchain by clicking on the Submit button.
IMPORTANT: You must be connected to a node to submit transactions.
Apart from being able to create transactions, the client can also be used to create and mine blocks. Depending on the reward set for a mined block submission by the blockchain, mining can be a good way of earning DsCoin. The Mine Blocks tab provides you what you need to begin.
Mining is proof of work. Blockchains implement mining in order to safeguard the chain against malicious brute force block additions and excessive forking. Any block that is valid can get added onto the chain. As a result, sometimes blockchains may recieve multiple blocks trying to append to the same location on the chain.
This causes forks to form in the chain. Multiple, parallel, competing forks can make the chain very confusing and unreliable. To lower the possiblity of such clashes in submissions, the blockchain only accepts mined blocks. These are blocks that must have a very specific hash (one that falls within a certain threshold) in order to be accepted. Obtaining such a hash takes computational work and time, known as mining, and ensures that a natural buffer period arises between block submissions.
In DsCoin, the mining algorithm continuously increments a sequence known as the mine sequence, that is part of the block's hash data, till a block hash is obtained with a certain number of leading zeroes (called the difficulty). For example, an acceptable hash within a difficulty requirement of 5 would be:
0000035351c47b1151ab611d180e575a3b97e550aebb09193846baa829613acb
The first step to mining a block, is to create a block. This can be done by clicking on the Create Block button near the top right corner.
Once you try to create a block, you will be prompted to enter the block's header details. These are important details that decide the design and limitations of the block:
- Block Name (optional)
- Previous Block: The hash of the previous block, or the block that your block will append to on the chain. This should almost always be the surface block on the chain.
- Reward: The reward that you, the miner, will recieve for submitting the mined block. (set by chain)
- Difficulty: The difficulty of the block mining process. The higher this number, the longer and harder the block is to mine. (set by chain)
- Tx Limit: The maximum number of transactions the block will accept in its body. (set by chain)
Be careful when entering the details yourself: The blockchain is particular about block details, and will reject ones that don't match its specifications.
A safe way to enter details is to load them from the node, by using the Load Details from Node button at the top right. This automatically fetches chain specifications and enters them for you. It also enters the surface block's hash into the previous block field. Click Save once done.
Now that your block is created, you can view its entire structure and contents in the block preview pane. You may notice a transaction under the CBTx section. This is the mine reward that is made out to the currently active wallet in the client.
Since the block hasn't been mined yet, you may also notice that the status below says Not Mined. We will see how to change that shortly.
If ever you are unsatisfied with the block you have created, or you want to create a new one, you can delete the block by pressing the Delete Block button at the bottom left corner.
The purpose of a block is to host and store transactions on the chain. To add transactions to your block, you can do so by selecting them from the mempool.
It is the collection of all unconfirmed transactions that have still not been taken in by any blocks and put on the chain.
If you accidently add transactions that have already been confirmed, your block will get rejected. This is why it is very important to refresh the mempool list to get the latest unconfirmed transactions.
Press the refresh icon to get the latest list. You can also automatically select all the transactions you are allowed to add to your block (the Tx Limit) by pressing the Select Limit button.
When you select a transaction from the mempool list, they will automatically be added to your block and you you'll be able to see them inside the block preview. The transactions will be displayed under the Tx section, and their corresponding transaction fees under the CBTx section.
Coin base additions are additions that create new coins. These require a password that is set by the chain. In real decentralized blockchains, coin base additions are only used for testing or initiation and disabled after the chains becomes fully functional.
To add a coin base addition, fill the details, along with the password, in the Coin Base form and click on Add Coins. The addition will show up under the CBTx section of the block preview.
Once you have confirmed the contents of your block, you can begin the mining process. To do so, simply click on the Mine Block button and let the block mine. This may take some time depending on the difficulty.
The default preset is Medium, which calculates in batches of 20,000 hashes. If you wish to increase or decrease the load on your system, you may select another preset accordingly from the preset drop down menu.
You will need to briefly stop/cancel the mining in order to change your preset if you have already started mining.
If you want to stop mining, you can do so by pressing the Cancel button. This will not delete your mining progress, but rather pause it until you choose to mine again. The mining will continue from the sequence it left off at.
Once the algorithm acquires a hash that falls within the acceptable threshold, it will stop mining and display the block status as Mined.
You can verify if the block is truly mined by checking if the displayed block hash has the same (or more) number of leading zeroes as your set difficulty.
The only step left to do after mining the block, is to submit the block. Make sure you submit the block as soon as possible to avoid losing your place on the chain to someone else. Click the Submit button to submit your block to the node.
Once the chain accepts your block, your rewards and fees will be accessible to you in the form of UTxOs (if you're on the main chain).
This is how the coin works behind the scenes, from transaction handling to block mining and blockchain management. You can use the modules mentioned below to test it out for yourself.
The transactions and blocks module exists in the common\ directory, and the blockchain module itself lives in the node\ directory.
This is the naming convention used by my throughout my code:
Public Key = pk
Private Key = sk
Sender = sndr
Reciever = rcvr
Amount = amt
Transaction: Tx
Transaction Input: TxI
Transaction Output: TxO
Unspent Transaction: UTxO
Coin Base Transaction: CBTx (sometimes CBTxO)
Block Hash = blockh
Transaction Hash = txh
Transaction Output Hash = txoh
Knowing about hashes and hash infos is a prerequisite to understanding how hashes are used in this project. This is a brief overview of that
Hashes are the strings generated by the
SHA256algorithm from another string of data that was passed to it. The usefulness of hashes comes from the fact that every unique string has a unique hash, i.e. no two different strings can have the same hash.
Hashes cannot be reconstructed back into the orignal string that was used. This ensures anonymity and privacy when these hashes are passed around as a means of representing an unique object, all without revealing what its unique features are.
In summary, every object can theoretically have its own unique hash that depends on its contents, but the contents can never be ascertained using the hash. One can determine if the object has been tampered with (if its hash changes) all without knowing what exactly changed and how.
Understanding hashes raises the question: How do we use hashing algorithms such as
SHA256, for python objects?
The answer is to take all the unique, identifying attributes and data the object posseses and wrap it all neatly inside a formatted string. This string will then get passed to the hashing function and it is called the object's Hash Info.
Every attribute or child object, no matter its type, can be associated with its unique representation in string form, and be integrated into the Hash Info string. My modules use Hash Info functions extensively to generate unique strings that are fingerprints of the objects passed, before ultimately hashing those strings for privacy.
This is what the
hash_info()function for aTxOreturns on calling.
As can be seen, it integrates all the uniquely identifying features of theTxO, such as itsnonce, sender, reciever, and amount, into a formatted string that can then be hashed to hide this sensitive information.return f"nonce: {TxO.nonce}||sndr: {TxO.sndr.to_string().hex()}||rcvr: {TxO.rcvr.to_string().hex()}||amt: {TxO.amt} DSC"Hashing this then yields a hash string, which for example's sake can be assumed to be the following:
0d1cb9f83863a5d7e8c5fce2e121f3ea953059976dc1bc47b48df53d05b6d6e4
Even a small change in any protected value, for example a change of 0.1 DsCoins in the amount, will now yield a completely different hash:
3dd07561391db635561ba2c30030f79de8d0e36bd2458db2361e5379b859bb17
Hence it becomes apparent to any third-party observer that theTxOwas tampered with, without knowing what exactly was changed.
Sometimes blocks or blockchains may recieve transactions that display a valid hash and are signed (the hash is signed usually, implying that the hashed info beneath is authorized), but actually hold different attributes internally.
These are malicious objects that impersonate the real class objects and lie about their hash and signature.
As an example, aTxmay display a valid hash signed by Fang, but contain attributes declaring a payment from Lianhua to Haoyun, all without Lianhua's consent. If just a simple hash existence check, and signature verification were implemented, such a malicious transaction would pass.
Therefore, it is imperative that an independent (not under the control of the object) and incorruptible (not able to be manipulated by external inputs) function is created to read all the attributes of the object, compile its hash info, hash that info, and finally compare it with the hash the object claims.
Fundamental unit of a
Tx. It can be automatically created within aTxby using the.create_output()method.
sndr: Public key of the user sending the amountrcvr: Public key of the user recieving the amountamt: The total amount being transferred (in DsCoins)name(optional): Name of the output (default: "unnamed_output")
None
from transactions import TxO
import ecdsa
#Generate Private Keys
sk1 = ecdsa.SigningKey.generate(ecdsa.curves.SECP256k1)
sk2 = ecdsa.SigningKey.generate(ecdsa.curves.SECP256k1)
#Generate Public Keys
pk1 = sk1.get_verifying_key()
pk2 = sk2.get_verifying_key()
#Create the TxO (pk1 pays pk2 64 DsCoins)
pk1_pk2_64 = TxO(pk1, pk2, 64)The
Txitself that contains all the Inputs and Outputs (+ a Tx fee)
sndr: Public key of the user initiating the Txname(optional): Name of theTx(default: "unnamed_tx")
.add_input( TxO ): Adds an UTxO (an output made to the initiator in previous confirmed Tx's).create_output( rcvr, amt ): Creates a TxO with the initiator as the sender andrcvras recipient, with an amount equal toamt..sign( sk ): Signs the Tx using a Private Keysk.
#---Continuation of previous code block---
from transactions import Tx
#Create a Tx in pk2's name
tx = Tx(pk2)
#Add the output made out to pk2 earlier as an input
tx.add_input(pk1_pk2_64)
#pk2 may now use this input to justify an output to pk1
#Create an output made out to pk1 for an amount of 32 DsCoins
tx.create_output(pk1, 32)
#Sign the Tx with pk2's private key sk2
tx.sign(sk2)As you may have noticed, the inputs and outputs are unbalanced (a remainder of 32 DsCoins remains). We will approach this in the blocks module demo by the addition of Tx fees.
A general Tx verification tool that is trusted/utilised by both the host block and the blockchain. It verifies the following properties of the the Tx:
1. Hash Honesty: Whether the Tx, and all the TxOs contained within, are presenting the correct hash in their hash attribute, or if they are malicious objects, impersonating those classes and lying about their true hash identity. This prevents Tx, TxO class impersonators from hiding unauthorized data behind false hashes.
2. Equilibrium: Whether or not the inputs and outputs of the Tx are balanced (after accounting for any Tx fees), i.e. inputs = outputs + fees
3. Signature: Whether the initiator of the Tx (pk) is the signee of its contents, or if someone else has signed it.
A coin base Tx is a transaction that is signed by no-one but is authorized by the chain to add new coins, pay transaction fees, and pay the rewards for mining a block.
rcvr: Public key of the user recieving the amountamt: The total amount being transferred (in DsCoins)type: Type of CBTx (addition (default), reward, fee)name(optional): Name of theCBTx(default: "unnamed_cbtx")
#---Continuation of previous code block---
from blocks import CBTx
#Create a CBTx paid to pk2 in form of an addition of 16 new coins
cbtx = CBTx(pk2, 16, type="addition")Addition is the only type of
CBTxcreated manually. Other types ofCBTx's (such as fees and rewards), are handled by the blocks.
The
Blockclass handles the hosting/storing ofTx's, calculation of fees in the event of unequilibrium between outputs and inputs, and the mining of theBlock's contents to obtain an acceptable hash.
previous_hash: The hash of the block that this block will append to in the chain.miner_pk: Public key of the individual mining the block. Mining rewards and transaction fees will be created for this key.miner_reward: The reward amount that the block will add to itself in the miner's name (default: 64)Tx_limit: The amount of Tx's a block may add to itself (default: 5)difficulty: The difficulty of the hash that is to be obtained through mining. It corresponds to the number of zeroes the block's hash must lead with (default: 3)name(optional): Name of theBlock(default: "unnamed_block")
.add_Tx( Tx ): Adds aTxto the block. ReturnsTrueif it is accepted andFalseotherwise..add_CBTx( CBTx ): Adds a CBTx to the block. ReturnsTrueif it is accepted andFalseotherwise..isMined(): ReturnsTrueorFalsedepending on whether or not the block is mined, i.e. the block hash meets the difficulty criteria..mine(): Mines the block as per the set difficulty level, returning the mined hash on completion. Also adds aCBTxin name of the miner as the mining reward.
The block contains an attribute known as the mine sequence (
mine_seq), which is a part of the block's hash info. This sequence is incremented by one and hash of the block is computed.
If the hash is acceptable, the block is considered mined, otherwise the sequence is incremented and the cycle repeats.
Depending on the difficulty, the sequences can sometimes take very long times to determine.
#---Continuation of previous code block---
from transactions import Block
#Create a block with no previous and pk1 as the miner
b1 = Block(None, pk1, name="b1")
#Add the Tx we created to the block
b1.add_Tx(tx)
#The block will automatically calculate the difference between the inputs and outputs as being 32 DsCoins and add that as a transaction fee to pk1
#Mine the block
b1_hash = b1.mine() #Returns the final block hash
print(b1_hash)Behind the scenes, pk1 obtains 64 DsCoins as miner reward and a futher 32 DsCoins as fee from the remainder of the
Tx.
A general block verification tool that is trusted/utilised by the blockchain. It verifies the following properties of the the
Block:
1. Hash Honesty: Whether the Block, and all its child objects are presenting the correct hash in their hash attribute, or if they are malicious objects, impersonating those classes and lying about their true hash identity. This prevents impersonators from hiding unauthorized data behind false hashes.
2. Effort: Whether or not the block put in the necessary effort to obtain an acceptable hash that follows the difficulty specified (passed to the function as a parameter).
3. Authorized Rewarding: Whether or not the CBTx's in the block that are labelled as rewards do not exceed the miner reward specified (passed to the function as a parameter).
In addition the above, the function also calls the
verify_Tx()method on everyTxin the block to verify them.
1- Add CoinBase maturity: miner rewards can only be used after 10 blocks or more are appended to that block
2- Add auto snapshot at every n blocks feature
3- Display copy of blockchain through a visual GUI in clients
4- Create a chain verification tool that scans and verifies entire specified segment of chain.























