diff --git a/README.md b/README.md deleted file mode 100644 index 8d1b6d3..0000000 --- a/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# Summer of Bitcoin 2024: Mine your first block - -## Overview -In this challenge, you are tasked with the simulation of mining process of a block, which includes validating and including transactions from a given set of transactions. -The repository contains a folder `mempool` which contains JSON files. -These files represent individual transactions, some of which may be invalid. Your goal is to successfully mine a block by including only the valid transactions, following the specific requirements outlined below. - -## Objective -Your primary objective is to write a script that processes a series of transactions, validates them, and then mines them into a block. The output of your script should be a file named `output.txt` that follows a specific format. - -## Requirements -### Input -- You are provided with a folder named `mempool` containing several JSON files. Each file represents a transaction that includes all necessary information for validation. -- Among these transactions, some are invalid. Your script should be able to discern valid transactions from invalid ones. - -### Output -Your script must generate an output file named `output.txt` with the following structure: -- First line: The block header. -- Second line: The serialized coinbase transaction. -- Following lines: The transaction IDs (txids) of the transactions mined in the block, in order. The first txid should be that of the coinbase transaction - -### Difficulty Target -The difficulty target is `0000ffff00000000000000000000000000000000000000000000000000000000`. This is the value that the block hash must be less than for the block to be successfully mined. - -## Execution -- Create a file named `run.sh` that contains the command to execute your script. This file should ideally contain a single command like `python main.py` or `node index.js`. -- Your script should autonomously perform all tasks when `run.sh` is executed, without requiring any manual intervention. - -## Evaluation Criteria -Your submission will be evaluated based on the following criteria: - -- **Score**: Your code output will be scored bases on the fee collected and the amount of available block space utilised. **You must score at least 60 points to pass the challenge.** -- **Correctness**: The `output.txt` file must be correctly formatted in the manner described above. -- **Code Quality**: Your code should be well-organized, commented, and follow best practices. -- **Efficiency**: Your solution should process transactions and mine the block efficiently. - -## Document your work - -Apart from the code, you must also publish a `SOLUTION.md` file explaining your solution in the following format: -- **Design Approach:** Describe the approach you took to design your block construction program, explain all the key concepts of creating a valid block. -- **Implementation Details:** Provide pseudo code of your implementation, including sequence of logic, algorithms and variables used etc. -- **Results and Performance:** Present the results of your solution, and analyze the efficiency of your solution. -- **Conclusion:** Discuss any insights gained from solving the problem, and outline potential areas for future improvement or research. Include a list of references or resources consulted during the problem-solving process. - -## What NOT to Do - -In this challenge, it's crucial to understand and adhere to the following restrictions. These are put in place to ensure that you engage with the core concepts of bitcoin and apply your problem-solving skills to implement the solution from first principles. - -- **Do Not Use Bitcoin Libraries for Transaction Validation:** You must not use any Bitcoin-specific libraries or frameworks that automate transaction validation processes. The intent of this challenge is for you to understand and implement the validation logic manually. -- **Permissible Libraries:** The use of standard cryptographic libraries, such as secp256k1 for elliptic curve cryptography, and standard hashing libraries (e.g., for SHA-256) is allowed and encouraged. These libraries are essential for implementing the cryptographic underpinnings of bitcoin without reinventing the wheel. - - **Implement the Mining Algorithm Yourself:** You are required to implement the mining algorithm on your own. This includes creating a way to correctly form a block header, calculate the hash, and meet the challenge of finding a hash below a certain target. - -### Plagiarism Policy: -Our plagiarism detection checker thoroughly identifies any instances of copying or cheating. Participants are required to publish their solutions in the designated repository, which is private and accessible only to the individual and the administrator. Solutions should not be shared publicly or with peers. In case of plagiarism, both parties involved will be directly disqualified to maintain fairness and integrity. - -### AI Usage Disclaimer: -You may use AI tools like ChatGPT to gather information and explore alternative approaches, but avoid relying solely on AI for complete solutions. Verify and validate any insights obtained and maintain a balance between AI assistance and independent problem-solving. - -## Why These Restrictions? -These restrictions are designed to deepen your understanding of bitcoin technicals. -By completing this assignment, you will gain hands-on experience with the technology that make bitcoin secure and trustless. -Remember, the goal of this challenge is not just to produce a working solution but to engage critically with the fundamental components of bitcoin. This is an opportunity to showcase your problem-solving skills and your ability to implement complex algorithms from scratch. - -## Additional Information -- This challenge is designed to test your understanding of bitcoin fundamentals, including transaction validation and block mining processes. -- While the challenge focuses on the simulation of these processes, you are encouraged to implement your solution in a way that demonstrates depth of understanding and creativity. diff --git a/main.go b/main.go new file mode 100644 index 0000000..087e3d2 --- /dev/null +++ b/main.go @@ -0,0 +1,192 @@ +package main + +import ( + "encoding/hex" + "encoding/json" + "encoding/binary" + "crypto/sha256" + "os" + "fmt" + "time" + +) + + var blockHeader = BlockHeader{ + Version: 7, + PrevBlockHash: "0000000000000000000000000000000000000000000000000000000000000000", + MerkleRoot: "", + Time: time.Now().Unix(), + Bits: 0x1f00ffff, + Nonce: 0, + } + +// // MineBlock mines a new block and writes its data to an output file +// func MineBlock() { +// // Obtain network reward, transaction IDs, and other data +// } + +type BlockHeader struct { + Version uint32 + PrevBlockHash string + MerkleRoot string + Time int64 + Bits uint32 + Nonce uint32 +} + +type Input struct { + TxID string `json:"txid"` + Vout uint32 `json:"vout"` + Prevout Prevout `json:"prevout"` + Scriptsig string `json:"scriptsig"` + ScriptsigAsm string `json:"scriptsig_asm"` + IsCoinbase bool `json:"is_coinbase"` +} + +type Prevout struct { + Scriptpubkey string `json:"scriptpubkey"` + ScriptpubkeyAsm string `json:"scriptpubkey_asm"` + ScriptpubkeyType string `json:"scriptpubkey_type"` + ScriptpubkeyAddress string `json:"scriptpubkey_address"` + Value uint64 `json:"value"` +} + +type Transaction struct { + Version uint32 `json:"version"` + Locktime uint32 `json:"locktime"` + Vin []Input `json:"vin"` + Vout []Prevout `json:"vout"` +} + +type TxInfo struct { + TxID string + WTxID string + Fee uint64 + Weight uint64 +} +type TxWeight struct { + BaseSize int `json:"base_size"` // Size of non-witness data in bytes + WitnessSize int `json:"witness_size"` // Size of witness data in bytes + Weight int `json:"weight"` // Total weight in weight units +} + + +// TargetValue represents the target value for proof-of-work mining +const TargetValue string = "0000ffff00000000000000000000000000000000000000000000000000000000" + +// arrayVector compares two byte arrays lexicographically +func arrayVector(a, b []byte) int { + minLength := len(a) + if len(b) < minLength { + minLength = len(b) + } + + for i := 0; i < minLength; i++ { + if a[i] < b[i] { + return -1 + } else if a[i] > b[i] { + return 1 + } + } + +// for i := range a { +// if a[i] < b[i] { +// return -1 +// } else if a[i] > b[i] { +// return 1 +// } +// } + + if len(a) < len(b) { + return -1 + } else if len(a) > len(b) { + return 1 + } + + return 0 +} + +// ProofOfWork performs the proof-of-work mining process for a given block header +func ProofOfWork(blockHeader *BlockHeader) bool { + targetBytes, _ := hex.DecodeString(TargetValue) + + for { + serzHeader := SerializeBlockHeader(blockHeader) + hash := ReverseBytes(To_sha(To_sha(serzHeader))) + + if blockHeader.Nonce < 0 || blockHeader.Nonce > 0xffffffff { + return false + } + + blockHeader.Nonce++ + } +} + +func CreateCoinbase(netReward uint64) *Transaction { + witnessCommitment := CreateWitnessMerkle() + coinbaseTx := Transaction{ + Version: 1, + Vin: []Input{ + { + TxID: "0000000000000000000000000000000000000000000000000000000000000000", + Vout: 0xffffffff, + Prevout: Prevout{ + Scriptpubkey: "0014df4bf9f3621073202be59ae590f55f42879a21a0", + ScriptpubkeyAsm: "0014df4bf9f3621073202be59ae590f55f42879a21a0", + ScriptpubkeyType: "p2pkh", + ScriptpubkeyAddress: "bc1qma9lnumzzpejq2l9ntjepa2lg2re5gdqn3nf0c", + Value: uint64(netReward), + }, + IsCoinbase: true, + Sequence: 0xffffffff, + Scriptsig: "03951a0604f15ccf5609013803062b9b5a0100072f425443432f20", + Witness: []string{"0000000000000000000000000000000000000000000000000000000000000000"}, + }, + }, + Vout: []Prevout{ + { + Scriptpubkey: "0014df4bf9f3621073202be59ae590f55f42879a21a0", + ScriptpubkeyAsm: "0014df4bf9f3621073202be59ae590f55f42879a21a0", + ScriptpubkeyType: "p2pkh", + ScriptpubkeyAddress: "bc1qma9lnumzzpejq2l9ntjepa2lg2re5gdqn3nf0c", + Value: uint64(netReward), + }, + { + Scriptpubkey: "6a24" + "aa21a9ed" + witnessCommitment, //OPRETURN +OP_PUSHBYTES_36+ commitment header + witnessCommitment + ScriptpubkeyAsm: "OP_RETURN" + "OP_PUSHBYTES_36" + "aa21a9ed" + witnessCommitment, + ScriptpubkeyType: "op_return", + ScriptpubkeyAddress: "bc1qma9lnumzzpejq2l9ntjepa2lg2re5gdqn3nf0c", + Value: uint64(0), + }, + }, + Locktime: 0, + } + return &coinbaseTx +} + + + +func main() { + networkReward, transactionIDs, _ := Prioritize() + + // Create a coinbase transaction for the network reward + coinbaseTx := CreateCoinbase(networkReward) + serializedCoinbaseTx, _ := SerializeTransaction(coinbaseTx) + + // Perform proof-of-work mining + if ProofOfWork(&blockHeader) { + // Create an output file and write block data + outputFile, _ := os.Create("output.txt") + defer outputFile.Close() + + serializedBlockHeader := SerializeBlockHeader(&blockHeader) + segWitCoinbaseTx, _ := SegWitSerialize(coinbaseTx) + + outputFile.WriteString(hex.EncodeToString(serializedBlockHeader) + "\n") + outputFile.WriteString(hex.EncodeToString(segWitCoinbaseTx) + "\n") + + for _, txID := range transactionIDs { + outputFile.WriteString(txID + "\n") + } + } +} diff --git a/output.txt b/output.txt new file mode 100644 index 0000000..e69de29 diff --git a/run.sh b/run.sh index 721aeb2..e34332b 100644 --- a/run.sh +++ b/run.sh @@ -1 +1 @@ -# Update this file to run your own code \ No newline at end of file +go run main.go \ No newline at end of file diff --git a/test.sh b/test.sh deleted file mode 100644 index 75433fd..0000000 --- a/test.sh +++ /dev/null @@ -1,4 +0,0 @@ -cd ./grader || exit -npm install - -npm run verify-block \ No newline at end of file