1212
1313
1414def calculate_wtxid (tx_hex ):
15+ # note: normal transaction id's do not include the witness data
16+ # unlike witness transaction id's which include the witness data
1517 tx_binary = bytes .fromhex (tx_hex )
1618 hash_once = hashlib .sha256 (tx_binary ).digest ()
1719 hash_twice = hashlib .sha256 (hash_once ).digest ()
@@ -33,7 +35,7 @@ def calculate_merkle_root(txid_list):
3335
3436 # Convert each txid from big-endian hex to little-endian bytes.
3537 current_layer = [bytes .fromhex (txid )[::- 1 ] for txid in txid_list ]
36-
38+
3739 while len (current_layer ) > 1 :
3840 next_layer = []
3941 for i in range (0 , len (current_layer ), 2 ):
@@ -113,11 +115,11 @@ def create_block(coinbase_tx, tx1):
113115 prev_block_hash = bytes .fromhex (
114116 "0000000000000000000000000000000000000000000000000000000000000000"
115117 )
116-
117- version = "20000000 "
118+ # version https://learnmeabitcoin.com/technical/block/version/
119+ version = "40000000 "
118120 version = int .from_bytes (bytes .fromhex (version ), byteorder = "little" )
119121 timestamp = int (time .time ())
120- # resource: learn me a bitcoin's target to bit converter.
122+ # resource: https://learnmeabitcoin.com/technical/block/bits/
121123 bits = "1f00ffff"
122124 bits = int .from_bytes (bytes .fromhex (bits ), byteorder = "big" )
123125
@@ -184,7 +186,8 @@ def mine_block(block_header_bytes, target_hex):
184186
185187def main ():
186188
187- #mock transaction details
189+ # mock transaction details, this transaction would be the first transaction
190+ # of the block after the coinbase transaction
188191 tx_details = {
189192 "txid" : "00000a2d1a9e29116b539b85b6e893213b1ed95a08b7526a8d59a4b088fc6571" ,
190193 "version" : 1 ,
@@ -239,30 +242,37 @@ def main():
239242
240243
241244 setup ("mainnet" )
242-
245+ # mock requirements
243246 from_txid = "0000000000000000000000000000000000000000000000000000000000000000"
244247 to_addr = "bc1pvh7n6s375348q5zjfrde38nnq2lmhhtyaeqe8hv6t8mf398smeyqnug47s"
245248 to_addr = P2trAddress (to_addr )
246249
247- # create a coinbase transaction
250+ # First create a coinbase transaction which is the first transaction of the block
251+ # The witness reserved value is a 32-byte value that is reserved for future use.
252+ # and the coinbase transaction must have it in its input's witness
248253 witness_reserved_value = (
249254 "0000000000000000000000000000000000000000000000000000000000000000"
250255 )
251- witness_root_hash = ""
252256
253- # The commitment is constructed as:
254- # commitment = "6a24aa21a9ed" + doublesha256(witness_root_hash, witness_reserved_value)
257+ # Constructing the coinbase transaction
255258 tx1 = Transaction ()
256259 tx1 = tx1 .from_raw (tx_details ["hex" ])
257260 txinp = TxInput (
258261 txid = from_txid ,
259262 txout_index = 0 ,
260263 script_sig = Script ([witness_reserved_value ]),
261264 )
265+
266+ # Witness stack contains the list of witness data for the transaction
267+ # learn more: https://learnmeabitcoin.com/technical/upgrades/segregated-witness/
262268 witness_stack = [witness_reserved_value ]
263269
270+ # wtxid is different from txid
264271 wtxid = calculate_wtxid (tx_details ["hex" ])
265272 print ("Wtx id :" , wtxid )
273+
274+ # Coinbase wtxid must be set to all zeros to avoid circular reference
275+ # Learn more: https://learnmeabitcoin.com/technical/transaction/wtxid/
266276 coinbase_wtxid = "0" * 64
267277
268278 witness_root_hash = calculate_witness_root_hash ([coinbase_wtxid , wtxid ])
@@ -274,13 +284,27 @@ def main():
274284 witness_root_hash , witness_reserved_value
275285 )
276286
277- # Prepending the witness commitment header
287+ # The commitment is constructed as:
288+ # commitment = "6a24aa21a9ed" + doublesha256(witness_root_hash, witness_reserved_value)
289+ # where commitment is made of (source BIP 141):
290+ # 1-byte - OP_RETURN (0x6a)
291+ # 1-byte - Push the following 36 bytes (0x24)
292+ # 4-byte - Commitment header (0xaa21a9ed)
293+ # 32-byte - Commitment hash: Double-SHA256(witness root hash|witness reserved value)
278294 commitment = "6a24aa21a9ed" + witness_commitment_hash
279295
280296 print ("Witness Commitment :" , commitment )
281297 # note: to_addr defined at the top. Taken from the first transaction
282- txout1 = TxOutput (to_satoshis (0.001 ), to_addr .to_script_pub_key ())
283- witness_commitment_script = Script ([])
298+ # coinbase transactions must contain at least two outputs
299+ # the first output is the block reward and the second output is the commitment
300+ # The block reward is reward for the miner for mining the block + fees
301+ # block reward = block subsidy (currently 3.125 BTC) + transaction fees
302+ # Learn more: https://learnmeabitcoin.com/technical/mining/block-reward/
303+ txout1 = TxOutput (to_satoshis (3.125 + 0.01 ), to_addr .to_script_pub_key ())
304+
305+ # The commitment script is described above
306+ # and is added to the second output of the coinbase transaction
307+ witness_commitment_script = Script ([])
284308 witness_commitment_script = witness_commitment_script .from_raw (commitment )
285309 print ("witness commitment script : " , witness_commitment_script )
286310 txout2 = TxOutput (to_satoshis (0 ), witness_commitment_script )
@@ -290,21 +314,29 @@ def main():
290314 has_segwit = True ,
291315 witnesses = [TxWitnessInput (witness_stack )],
292316 )
293- # example difficulty target
317+ # Example difficulty target
318+ # learn more: https://learnmeabitcoin.com/technical/mining/target/
319+ # Note, this is even higher then the genesis block example
320+ # to prevent the mining process from running for a long time
294321 difficulty_target = (
295322 "0000ffff00000000000000000000000000000000000000000000000000000000"
296323 )
297324 # Creating a block that includes the coinbase transaction and tx1.
298325 block = create_block (coinbase_tx , tx1 )
326+
299327 print ("block header: " , block .header )
300328 # getting the block header bytes
301-
329+ # Note: only the header is hashed and compared to the difficulty in mining
302330 serialized_header = block .header .serialize_header ()
303331 print ("Serialized header : " , serialized_header )
304332
305- # mining the block
333+ # mining the block using mine_block returns the nonce
334+ # nonce is the value in the header that can be changed iteratively
335+ # to get a hash that is less than the target
306336 nonce , mined_hash = mine_block (serialized_header , difficulty_target )
307337 print ("NONCE: " , nonce )
338+
339+ # Replace the last 4 bytes of the header with the current nonce in little-endian format.
308340 serialized_header = serialized_header [:- 4 ] + nonce .to_bytes (4 , byteorder = "little" )
309341
310342 print ("hex of serialized header " , serialized_header .hex ())
0 commit comments