Skip to content

Commit 407792b

Browse files
committed
Review markups for chapter 2.2
1 parent 9010e18 commit 407792b

File tree

2 files changed

+19
-13
lines changed

2 files changed

+19
-13
lines changed

2.2-taptweak.ipynb

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"outputs": [],
88
"source": [
99
"import random\n",
10+
"from io import BytesIO\n",
1011
"\n",
1112
"import util\n",
1213
"from test_framework.address import program_to_witness\n",
@@ -22,11 +23,11 @@
2223
"source": [
2324
"# 2.2 TapTweak\n",
2425
"\n",
25-
"* Part 1: Tweaking the public key and commitment schemes with tweaks\n",
26+
"* Part 1: Tweaking the public key; commitment schemes with tweaks\n",
2627
"* Part 2: Spending a (tweaked) taproot output along the key path\n",
27-
"* Part 3 (Case Study): Contract commitments\n",
28+
"* Part 3 (Case Study): contract commitments\n",
2829
"\n",
29-
"The linear property of bip-schnorr means that we can encode a commitment into a public key, and then reveal that commitment when signing with the private key. We do that by _tweaking_ the private key with the commitment, and using the associated _tweaked_ pubkey. When signing, we can reveal that the original private key was tweaked by the commitment.\n",
30+
"The linear property of bip-schnorr means that we can encode a commitment into a public key, and then reveal that commitment when signing with the private key. We do that by _tweaking_ the private key with the commitment, and using the associated _tweaked_ pubkey. When signing, we can reveal that the original keys were tweaked by the commitment.\n",
3031
"\n",
3132
"In part 1, we'll learn about how private/public key pairs can be tweaked, and how we can use that to create a secure commitment scheme. In part 2, we'll create a segwit v1 output and spend it along the key path, using a tweaked private and public key. Part 3 of this chapter is a case study, showing how pay-to-contract with tweaked keys can be used instead of OP_RETURN outputs to create timestamped commitments."
3233
]
@@ -77,9 +78,9 @@
7778
"\n",
7879
"print(\"Private key: {}\\nPublic key: {}\\n\".format(privkey.secret, pubkey.get_bytes().hex()))\n",
7980
"\n",
80-
"# Generate a random tweak 0 < t < SECP256K1_ORDER and its associated point\n",
81+
"# Generate a random tweak scalar 0 < t < SECP256K1_ORDER and derive its associated tweak point\n",
8182
"tweak = random.randrange(1, SECP256K1_ORDER)\n",
82-
"tweak_private = ECKey().set(tweak, True)\n",
83+
"tweak_private = ECKey().set(tweak)\n",
8384
"tweak_point = tweak_private.get_pubkey()\n",
8485
"print(\"Tweak scalar: {}\\nTweak point: {}\\n\".format(tweak_private.secret, tweak_point.get_bytes().hex()))\n",
8586
"\n",
@@ -103,7 +104,7 @@
103104
"\n",
104105
"In this exercise, we tweak an MuSig aggregate pubkey, and then sign for it using the individual participant keys. The MuSig pubkey aggregation step is done for you.\n",
105106
"\n",
106-
"_Question: Which participant(s) need to tweak their private keys?_"
107+
"_Question: How is the tweak incorporated into the final signature?_"
107108
]
108109
},
109110
{
@@ -172,7 +173,7 @@
172173
"source": [
173174
"#### Example 2.2.3: Tweaking a public key Q with commitment data\n",
174175
"\n",
175-
"In this example we demonstrate an insecure commitment scheme. The committed value `c` can be trivially modified to `c'`. The public key point equation `Q = x'G + c'G` still holds and is equal to the same point Q. An alternative secret `x` can also be solved for.\n",
176+
"In this example we demonstrate an insecure commitment scheme. The committed value `c` can be trivially modified to `c'`, and by setting `x'` to `x + c - c'`, the public key point equation `Q = x'G + c'G` still holds.\n",
176177
"\n",
177178
"First, we commit a contract between Alice and Bob and then demonstrate how this unsafe commitment can be changed.\n",
178179
"\n",
@@ -340,7 +341,7 @@
340341
"outputs": [],
341342
"source": [
342343
"# Example key pair\n",
343-
"privkey = ECKey().set(102118636618570133408735518698955378316807974995033705330357303547139065928052, True)\n",
344+
"privkey = ECKey().set(102118636618570133408735518698955378316807974995033705330357303547139065928052)\n",
344345
"internal_pubkey = privkey.get_pubkey()\n",
345346
"\n",
346347
"# Example tweak\n",
@@ -513,7 +514,9 @@
513514
"\n",
514515
"# Fetch the oldest unspent outpoint in the Bitcoin Core wallet\n",
515516
"unspent_txid = node.listunspent(1)[-1][\"txid\"]\n",
516-
"unspent_outpoint = COutPoint(int(unspent_txid,16), 0)"
517+
"unspent_outpoint = COutPoint(int(unspent_txid,16), 0)\n",
518+
"\n",
519+
"print(\"Unspent coin: txid:{}, n:{}\".format(unspent_outpoint.hash, unspent_outpoint.n))"
517520
]
518521
},
519522
{
@@ -522,7 +525,7 @@
522525
"source": [
523526
"#### Example 2.2.12: Create and broadcast a transaction with an OP_RETURN output\n",
524527
"\n",
525-
"We now construct a OP_RETURN output which contains the commitment data of Alice's contract with Bob, and then add it to a transaction with a regular P2WPKH output. This way, the commitment can be done more efficiently, by sharing transaction data with another spendable output."
528+
"We now construct a zero-value OP_RETURN output which contains the commitment data of Alice's contract with Bob. We also add a regular P2WPKH output back to Alice to return the funds from the transaction input (less the transaction fee)."
526529
]
527530
},
528531
{
@@ -538,10 +541,10 @@
538541
"op_return_tx_in = CTxIn(outpoint=unspent_outpoint, nSequence=0)\n",
539542
"op_return_tx.vin = [op_return_tx_in]\n",
540543
"\n",
541-
"# Output 0) Alice's destination address\n",
544+
"# Output 0) Alice's change address\n",
542545
"address_alice = node.getnewaddress(address_type=\"bech32\")\n",
543546
"p2wpkh_output_script = bytes.fromhex(node.getaddressinfo(address_alice)['scriptPubKey'])\n",
544-
"p2wpkh_output_amount_sat = 100_000_000\n",
547+
"p2wpkh_output_amount_sat = 4_950_000_000 # remove transaction fee from output amount\n",
545548
"p2wpkh_output = CTxOut(nValue=p2wpkh_output_amount_sat, scriptPubKey=p2wpkh_output_script)\n",
546549
"\n",
547550
"# Output 1) OP_RETURN with Alice's commitment\n",
@@ -562,6 +565,7 @@
562565
"print(\"The total transaction weight is: {}\\n\".format(op_return_tx_decoded['weight']))\n",
563566
"\n",
564567
"# Test mempool acceptance\n",
568+
"print(node.testmempoolaccept(rawtxs=[op_return_tx_hex_signed], maxfeerate=0))\n",
565569
"assert node.testmempoolaccept(rawtxs=[op_return_tx_hex_signed], maxfeerate=0)[0]['allowed']\n",
566570
"print(\"Success!\")"
567571
]

solutions/2.2-taptweak-solutions.ipynb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
"# needs to be added to the list of partial signatures\n",
5151
"# Method: sign_musig(private_key, nonce_key, nonce_point, public_key, msg)\n",
5252
"# Method: aggregate_musig_signatures(partial_signature_list, aggregate nonce)\n",
53+
"# Note: The tweak multiplied by the musig_digest is added to the partial signature list.\n",
54+
"# This is equivalent to tweaking the private key for a single signer.\n",
5355
"e = musig_digest(R_agg, agg_pubkey_tweaked, msg)\n",
5456
"s1 = sign_musig(privkey1_c, k1, R_agg, agg_pubkey_tweaked, msg)\n",
5557
"s2 = sign_musig(privkey2_c, k2, R_agg, agg_pubkey_tweaked, msg)\n",
@@ -73,7 +75,7 @@
7375
"outputs": [],
7476
"source": [
7577
"# Example key pair\n",
76-
"privkey = ECKey().set(102118636618570133408735518698955378316807974995033705330357303547139065928052, True)\n",
78+
"privkey = ECKey().set(102118636618570133408735518698955378316807974995033705330357303547139065928052)\n",
7779
"internal_pubkey = privkey.get_pubkey()\n",
7880
"\n",
7981
"# Example tweak\n",

0 commit comments

Comments
 (0)