Skip to content

Commit 54ce4a6

Browse files
committed
Improved code explanation
1 parent 7daa88b commit 54ce4a6

1 file changed

Lines changed: 48 additions & 16 deletions

File tree

examples/create_block_from_json.py

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313

1414
def 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

185187
def 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

Comments
 (0)