Skip to content

Commit

Permalink
Merge pull request #23 from pred695/finalpush
Browse files Browse the repository at this point in the history
final push, lets hope for the best
  • Loading branch information
pred695 authored Apr 30, 2024
2 parents eba9b4e + 15c71fd commit 604668d
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 2 deletions.
58 changes: 58 additions & 0 deletions Solution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# **Code Challenge 2024 Solution**
## **Author - pred695**

### Design Approach - Steps I took to create a valid block

### Code Structure:
All the structs used in the implementation are stored in the `Structs` package in the file `struct.go` file.
All the functions used throughout the implementation are stored in the `Utils` package under relevant files stated below.
The `coinbase.go` file contains the generation of the coinbase transaction.
The `merkle.go` file contains the code for the generation of Merkle root for the whole block and as well as the witness merkle.
The `prioritize.go` file contains the code that implements the sorting algorithm which sorts transactions according to their `fee/weight` ratio.
The `weight.go` file contains the code for calculating the weight of the transactions in the mempool.
The `util.go` file contains the basic utility functions used throughout the implementation.
The `Validation` package contains the address validation implementation for various locking scripts.
The `Blockchain` package contains the code that runs the proof of work for the whole block in `pow.go` and the block mining code is there in `mine.go` file. This code generates the `output.txt` file.

### Steps taken for generating the mined block.

#### a) Serialization:
There are two types of serialization used in my implementation. One is segwit serialization and the other is non segwit serialization.
1) `func SerializeTransaction(tx *Structs.Transaction) ([]byte, error)`-> Returns the serialized transaction without including the witness data.
2) `func SegWitSerialize(tx *Structs.Transaction) ([]byte, error)` -> Returns the serialized transaction including the witness data.
3) `func SerializeBlockHeader(bh *Structs.BlockHeader) []byte ` -> Returns the serialized block header.

### b) Generation of TxIDs:
1) TxIDs are generated by the non segwit serialized data if the output is double hashed with sha256 algorithm.
An example from code: `txid := to_sha(to_sha(serialized))` where `to_sha` function implements sha256 algorithm on a stream of bytes. and the `serialized` variable is the output of the non segwit serialization.
This txid generated is in the big endian format. It is transformed into the little-endian format by using the `ReverseBytes` function defined in the `serialize.go` file in `Utils` package.

The txids generated are used further for calculation of Merkle Root of the included transactions.
2) WTxIDs are generated by the segwit serialized data if the output is double hashed with sha256 algorithm.
An example from code: `wtxid := to_sha(to_sha(segserialized))` where segserialized is the segwit serialized data of the transactions. The WTxIDs for a non segwit transaction is same as that of the segwit transaction because of the absence of the witness data.
The coinbase transaction in our case is a segwit transaction as the mempool contains many segwit transactions and I am also including many segwit transaction in my block.

### c) Construction of Merkle Root and Witness Commitment:
1) The function `func NewMerkleTree(leaves []string) *Structs.MerkleNode` is used for creating the merklee tree. It returns the merkle root of all the transactions which is of the type `MerkleNode` defined in the `Structs` package. The `leaves` are the TxIDs in string format.
2) The function `func CreateWitnessMerkle() string` is used for creating the witness merkle of the block to be constructed. It returns the witness commitment which is included in the Coinbase Transaction. Code snippet of witness commitment generation
`commitment_string := hex.EncodeToString(merkleRoot.Data) + "0000000000000000000000000000000000000000000000000000000000000000"`.

### d) Construction of Blockheader:
1) The blockheader is constructed in the `mine.go` function in the `Blockchain` package. It is of the type `BlockHeader` defined in `struct.go` file in the `Structs` package.
2) This blockheader is put in the first line of `output.txt` in the serialized form. The serialization function of the Blockheader is `func SerializeBlockHeader(bh *Structs.BlockHeader) []byte`.

### e) Proof of Work Algorithm:
This is implemented in the `pow.go` file in the `Blockchain` package.

### f) Construction of Coinbase Transaction:
The coinbase transaction is constructed in the `coinbase.go` in the `Utils` package.

### g) Fractional Knapsack Algorithm:
The algorithm to gain the maximum fee by including the transactions which had relatively higher `fee/weight` ratio is implemented in the `prioritize.go` file in the `Utils` package. It sorts the transactions in the decreasing order of the fee to weight ratio and keep including them one by one until the Block weight reaches close to the maximum of `4000000`including the coinbase transaction which came out be 660 wu in my case.

### Flow:
Serialize transactions -> Generate Transaction IDs -> Perform Address Validation -> Generate Witness Transaction IDs -> Pick up transactions according to the Fractional Knapsack Algorithm in a greedy manner -> Construct the witness commitment for the Coinbase Tx -> Create a Valid Coinbase transaction -> Construct the Merkle Root of the included transactions -> Run the proof of work algorithm -> Generate the output.txt file once the block is mined.




2 changes: 1 addition & 1 deletion Structs/struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,4 @@ type MerkleNode struct {

type MerkleTree struct {
MerkleRoot *MerkleNode
}
}
4 changes: 3 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package main

import "github.com/pred695/code-challenge-2024-pred695/Blockchain"
import (
"github.com/pred695/code-challenge-2024-pred695/Blockchain"
)

func main() {
Blockchain.MineBlock()
Expand Down

0 comments on commit 604668d

Please sign in to comment.