# Smithing - ## Description Smithing is a process by which a node produces a block to be offered to the network as the next state of the blockchain. There are various types of consensus mechanisms to decide whose block should be accepted as the next blocks. A few of the popular ones are: Proof of Work, Proof of Stake, Proof of Authority etc. In case of ZooBc, we are using a different consensus mechanism of our very own called `Proof of Participation`. * ## Process The smithing turn in `Proof of Participation` is adjusted in such a way that all the participants of the network have same and equal opportunity to smith/produce a block. The process are as follows: 1. Every constant time, a thread will run a calculation (in each individual nodes) to know whether it's time for it to create a block. 2. Time to create block for a blocksmith is calculated as follow: if `previousBlock.SkippedBlocksmith < 1`: ``` blocksmith[0] = previousBlock.Timestamp + smithingPeriod blocksmith[n] = blocksmith[0] + (blocksmithTimeGap * n) ``` if `previousBlock.SkippedBlocksmiths > 0`, we'll set the start time to `lastSkippedBlocksmith.ExpireTime` ``` lastSkippedBlocksmithExpireTime = previousBlock.Timestamp - blocksmithTimeGap + SmithingBlockCreationTime + SmithingNetworkTolerance blocksmith[0] = lastSkippedBlocksmithExpireTime + smithingPeriod blocksmith[n] = blocksmith[0] + (blocksmithTimeGap * n) ``` We can see that from above calculation, the smith time of blocksmiths will look something like: ![blocksmiht smith time](./images/blocksmith_smith_time.png) The smith time of blocksmith will be repeated, meaning if all blocksmiths has pass their expiration time of creating a block, we'll go back to the very first blocksmith again and repeat the same order (given the same previous block). note: ``` blocksmithTimeGap = 10 seconds smithingPeriod = 15 seconds SmithingBlockCreationTime = 30 seconds ``` 3. When it's the node time to create block, it will generate block, and push it into the block pool. 4. BlockPool BlockPool is the temporary place to store pending blocks. Any block that is not produced by the first place blocksmith, will be pushed to `BlockPool`. Block in the `BlockPool` is valid and have been run on `PushBlock()` function without commiting to the database. Every 5 seconds the node will run a check to see if any block in it is legal to be persisted to the chain (call [PushBlock()](##Block-Push)). The conditions are: ``` // beginTime will be calculated in point (1). expireTime = beginTime + SmithingBlockCreationTime + SmithingNetworkTolerance // valid condition beginTime < currentTime < expireTime ``` However for the non-first blocksmith block, the valid condition for the block to be persisted is: ``` previousBlocksmithExpireTime < currentTime < currentBlocksmithExpireTime ``` The time window for block to be persisted is their `blocksmithTimeGap` (10 seconds). In the case where every blocksmith have expired we'll choose the block with highest cummulative difficulty in the `BlockPool` to be persisted. example: ``` blockA { begin: 15, expire: 60, } blockB { begin: 25, expire: 70, } blockC { begin: 35, expire: 80, } The valid persist time for blockB (in case blockA expire) is 60 - 70 second window. If we are running 3 nodes network, and currentTime = 81 (meaning every block has expired), But we got blockA in the blockPool, we'll persist blockA. ``` ![blocksmiht persist time visual](./images/blocksmith_persist_time.png) The dark block represent a valid persist time for that blocksmith. Valid persist time will always be the previous blocksmith's expired + blocksmith gap time, except for the first blocksmith, that'll have its whole smith time to persist. - ## Block Push `BlockPush` is a generalized operation that will push a block as a new state for the blockchain. The operations that it performs is as follows: 1. It fetches all of the mempool transactions to be placed inside a block, and sort them ascending order based on their `FeePerByte` then their `ArrivalTimestamp`, and place them inside the block instance. 2. It fetches the [Receipt](https://github.com/zoobc/zoobc-core/wiki/Receipt) that are to be included to the block, and place them inside the block instance. 3. It starts a DB transaction. 4. It adds the block data into DB. 5. It executes the transactions's `UndoApplyUnconfirmed` and `ApplyConfirmed` to make sure the effect of each transactions is added to the DB. 6. It process the receipts of the block to calculate the change of the current node. 7. It calculates the skipped blocksmiths. The skipped blocksmiths will have their scores reduced. 8. It distributes the coinbase to a constant number of nodes evenly. 9. It checks whether any node satisfies the condition to be expelled (his score reaches 0), if yes kick them from the node registry. 10. It builds the `ScrambledNodes` if needed. 11. It finalizes the data and commit the DB transaction, making it written to the DB. 12. It emits event `observer.BlockPushed` that will broadcast the block to its peers. 13. It emits event `observer.ExpiringEscrowTransactions` that will mark expired escrow transactions in the * ## Block Broadcast "Block broadcast" is a process where a block produced/accepted by a node is re-transmitted to other participants in the network, which would result synchronized state of all the participants (nodes) accross the network. - ### Block Broadcast Process The process of broadcast of a block is started by a node smithing a block or accepting a block broadcasted by other nodes. The Block broadcasted would not have the transactions, but just the Ids of the transactions. This mechanism to lighten the transmission of a block, because (another) node upon receiving a block will do basic validation of the block, and if that node thinks that the block is not valid he does not need to fetch the transcations of the block. This will save quite some amount of bandwith. The process graphically can be drawn as the flow diagram below: [[/images/blockbroadcast.png]] It can be explained as this: - Imagine there are 2 nodes in this case. Node A as the block receiver, and Node B as the sender of the block. - 1.1. Node A receives a block broadcast from Node B 1. The block is validated to see whether it's a valid block for Node A's blockchain state. 2. If it's valid, it will check whther the recipient node (Node A) has all the transactions of the incoming block. If yes, the block is sent to the `Completed Block Pool` which then to be processed to be included to the blockchain. If no, it will be sent to the `Waiting-transaction Block Pool`. - 1.2. Node A send a request for the transactions needed to complete the blocks in the `Waiting-transaction Block Pool` asynchronously. 1. Node B upon receiving the request will get the transactions required from his: transactions table, mempool, and blocks in the `Completed Block Pool`. 2. When they all are ready, Node B will send the transactions to Node A. - 1.3. Node A receives the transactions from Node B 1. Node A validates all of the transactions from B. 2. Node A will send receipts to Node B for all of the transactions that he thinks are valid. 3. With the tranactions Node A got from Node B, Node A then tries to complete the blocks in his `Waiting-transaction Block Pool`. 4. If any of the blocks from `Waiting-transaction Block Pool` is completed, it will be sent to the `Completed Block Pool`. - 2.1. There's a thread running every constant time that push the blocks inside `Completed Block Pool` to the blockchain 1. It iterates the blocks inside of the `Completed Block Pool`. 2. If a block is found is to be pushed in the current time window, [Block Push](##Block-Push) will be performed on the block. 3. Upon the the successful pushing of the block, the `Completed Block Pool` will be cleared.