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.
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.
- You are provided with a folder named
mempoolcontaining 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.
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
The difficulty target is 0000ffff00000000000000000000000000000000000000000000000000000000. This is the value that the block hash must be less than for the block to be successfully mined.
- At first the mempool is itreated and transactions are verified on the basis of their script types (
p2trtransactions are added in block with only basic checks like sufficient gas-fees) and inserted in the valid-mempool. - Transactions with gas fees less than 1500 sats are rejected.
- Then a map of all valid-transaction which includes
txid,transaction,wtxid,tx_weightandfeesis created for each of them. - Then the wtxid commintment is created from all the wtxids of the valid transactions as mentioned in learn me a bitcoin.
- Then the coinbase transaction is hard-coded.
- Then the merkel root is created using the txids of all valid transactions withtthe txid if coinbase at the top.
- Then a valid-block-header is created by implementing the POW algorithm by continuously increasing the nonce once on each failure.
- Finally the valid-block header is created and, coinbase tx and all txids are inserted in the output.txt.
The code is divided into two main parts block_mine and validation_checks.
The core verification logic of p2pkh, p2sh, p2wpkh, p2wsh transactions are implemented here.
- In
input_verification_p2pkh, the script_sig_asm and script_pubkey_asm are extracted from the input of the transaction being verified and then passedscript_execution HASH160ofPublic keyinscript_sig_asmis verified withpubkeyhashin the script_pub_key- Now the
signatureandpublic_keyare pushed in the stack and the opcodes in the script_sig_asm are executed in sequence. - The
verify_ecdsafunction is then used to verify the signature against the pubic key and the message created from the transaction as per the consensus rules. - I refered to this repository for
trimmed_txcreation for signature verification.
There are 3 types of p2sh transactions: native p2sh, p2sh-p2wpkh, p2sh-p2wsh
- The scripts are executed in a stack.
- Sequence of script execution:
script_sig,script_pub_key,inner_redeem_script. - The logic for all opcodes present in scripts are implemented in
p2sh.rs - The
trimmed_txcreation is same as thep2pkhjust instead ofscript_sig_asm,inner_redeem_scriptis used.
- Scripts are executed in the stack.
- All relevant
opcodeslogic implementation are inp2sh.rs. script_sigandscript_pub_keyare executed in the same way.- Here instead of
inner_redeem_script, witness is executed. signatureandpublic keyare pushed in the stack.- Now
OP_DUP,OP_HASH160are executed implicitely.All relevantopcodeslogic implementation are inp2sh.rs. - Now
inner_redeem_scriptopcodes are executed. - Again
OP_EQUALVERIFYandOP_CHECKSIGare excuted implicitely.
- Scripts are executed in the stack.
- All relevant
opcodeslogic implementation are inp2sh.rs. script_sigandscript_pub_keyare executed in the same way.- Here also instead of
inner_redeem_script, witness is executed. - All the elements except the last element in the
witnessare pushed in the stack. - Now the
witness-scriptis executed which is the last element in the witness. - Each opcode is iterated and executed, the final result is procured.
SIGNATURE verification for segwit p2sh transactions are refrenced from BIP143.
- This verification is not implemented using stack.
- The
signatureandpublic keyare extracted from the witness as there are only two elements in allp2wpkhtransactions. HASH160ofpublic keyis verified against thepubkeyhashinscript_pub_key.- Now the
signatureis verified against themessageandpublic keyusingverify_ecdsafunction.
- Scripts are executed in the stack.
- All relevant
opcodeslogic implementation are inp2wsh.rs. - All elements in the
witnessexcept the last element which is thewitness scriptare pushed in the stack. - Now the
witness-programwhich is the last element is thescript_pub_keyis cross-verified with theSHA256ofwitness-script. - Now after this verfication all the opcodes in the
witness-scriptis executed in the sequence and the final result is procured.
- Logic of
OP_CHECKSIGandOP_MULTICHECKSIG. verify_txmethod which redirects transctions on the basis of their types.all_transaction_verificationiterates through the mempool and executesverify_txfor each transaction while also checking for double spends.
The core logic of block mining is implemented here.
- The transactions which are valid under the consensus rules are put in the valid-mempool directory.
- Now in
create_txid_tx_mapthevalid-mempooldirectory is iterated and each valid transaction is seriliased into raw transactions. - Now as the transactions are iterated in the valid-mempool, their
txid,transaction,wtxid,tx_weightandfeesis insert in a vector in the descending order of theirgas-fees/tx-weight. - Method to serialise a transaction into its raw transaction format is referenced from learnmeabitcoin.
- The
merkel_rootandcoinbase_transactionlogic is implemented here.
- Here a
valid_block_headeris created using POW against the block_header_hash and the target bits.
At the end the valid_block_header, raw coinbase_tx , txids are inserted in the output.txt.
A valid block is created with:
- BLOCK WEIGHT := 3994072
- FEE := 21619204
- SCORE: 101
- NUMBER OF TRANSACTIONS: 4453
Effieciency of my solution could have been improved from the following changes:
- Making a single
opcoderegistry for all transaction types and not implementing theopcodelogic in each tx verification file. - Could not include
p2shtransactions inoutput.txtbecause of some bugs at the last moment.
- Github repo - p2pkh verification
- BIP143 - for signature verification of segwit transactions.
- Learn me a bitcoin - for block-header and coinbase transaction composition