<p>Fixed it, the main problem is that:</p>
<pre><code># Sending wallet creation
sendPrivKeyParsed1 = ECKey().set(int('SENDING PRIVATE KEY IN INTEGER'))
sendPubKeyObj = sendPrivKeyParsed1.get_pubkey()
recPubKeyBytes = sendPubKeyObj.get_bytes()  
</code></pre>
<p>Was supposed to be this:</p>
<pre><code># Sending wallet creation
sendPrivKeyParsed1 = ECKey().set(int('SENDING PRIVATE KEY IN INTEGER'))
sendPubKeyObj = sendPrivKeyParsed1.get_pubkey()
sendPubKeyBytes = sendPubKeyObj.get_bytes()
</code></pre>
<p>The scriptPubKey needs to be calculated for both the sending and receiving addresses. In my original code, I did this to calculate the receiving address's scriptPubKey:</p>
<pre><code>hrp = &quot;bc&quot;
witver, witprog = decode(hrp, address)
if witver is None:
    hrp = &quot;tb&quot;
    witver, witprog = decode(hrp, address)
scriptpubkey = segwit_scriptpubkey(witver, witprog)
print(&quot;the scriptPublicKey is: {}&quot;.format(scriptpubkey.hex()))  
</code></pre>
<p>So instead of <code>scriptpubkey</code>, you have <code>scriptpubkeyRec</code> and <code>scriptpubkeySend</code>. Maybe put the above code into a function that returns <code>scriptpubkey</code> and run it once for the sending address and once for the receiving address. If you write such a function called <code>get_scriptPubKey()</code>, the scriptPubKey generation would look like this:</p>
<pre><code># Derive the bech32 address
# Use program_to_witness(version_int, pubkey_bytes)
addressSend = program_to_witness_testnet(0x01, sendPubKeyBytes)
addressRec = program_to_witness_testnet(0x01, taproot_pubkey_b)

scriptpubkeySend = get_scriptPubKey1(addressSend)
scriptpubkeyRec = get_scriptPubKey1(addressRec)
</code></pre>
<p>Use <code>scriptpubkeyRec</code> here:</p>
<pre><code># Create a spending transaction
spending_tx = create_spending_transaction_nonode(txid='3f75f413db8ba76d7e26a9e93b9fe94990d58922cd0aaba09eac4b46b74437c2', scriptpubkey=scriptpubkeyRec, amount_c=0.00032134)  
</code></pre>
<p>Use <code>scriptpubkeySend</code> here:</p>
<pre><code>txout1 = CTxOut(nValue=36134, scriptPubKey=scriptpubkeySend)  
</code></pre>
<p>The last problem is that you need to sign with the sending key like this:</p>
<pre><code>sig = sendPrivKeyParsed1.sign_schnorr(sighash)  
</code></pre>
<p>After I made these changes the transaction worked <a href="https://blockstream.info/testnet/tx/55d8281e28240aa84f23026f335128d0c4e0c8868617cb65bc92a1ddc9c1f322" rel="nofollow noreferrer">https://blockstream.info/testnet/tx/55d8281e28240aa84f23026f335128d0c4e0c8868617cb65bc92a1ddc9c1f322</a></p>

CC BY-SA 4.0
2023-05-05T06:13:20.810Z
2023-05-05T06:13:20.810Z
ChristianOConnor
<p>I have 0.00036134 testnet bitcoin at the segwit v1 address: tb1p3au39skpdd8suuhunr4ymp6ca6akv9keq20v5twuagpmyqntqaasl22f4w</p>
<p>I wrote this script to achieve 2 things: archive a hash in a transaction and send the money in tb1p3au39skpdd8suuhunr4ymp6ca6akv9keq20v5twuagpmyqntqaasl22f4w to a new address.</p>
<pre><code>import random
from io import BytesIO

from util import CTxInWitness, CTxOut, create_spending_transaction_nonode
from helpers.address import program_to_witness_testnet
from helpers.key import ECKey, generate_key_pair, generate_bip340_key_pair, generate_schnorr_nonce, int_or_bytes
from helpers.segwit_addr2 import Encoding, decode, encode, segwit_scriptpubkey, bech32_decode
from helpers.script import CScript, CTransaction, OP_RETURN, SIGHASH_ALL, SIGHASH_ALL_TAPROOT, TaprootSignatureHash, tagged_hash


# Sending wallet creation
sendPrivKeyParsed1 = ECKey().set(int('SENDING PRIVATE KEY IN INTEGER'))
sendPubKeyObj = sendPrivKeyParsed1.get_pubkey()
recPubKeyBytes = sendPubKeyObj.get_bytes()

if sendPubKeyObj.get_y()%2 != 0:
    sendPrivKeyParsed1.negate()
    sendPubKeyObj.negate()

# Receiving wallet creation
recPrivKeyParsed1 = ECKey().set(int('RECEIVING ADDRESS PRIVATE KEY IN INTEGER'))
recPubKeyObj = recPrivKeyParsed1.get_pubkey()
recPubKeyBytes = recPubKeyObj.get_bytes()

if recPubKeyObj.get_y()%2 != 0:
    recPrivKeyParsed1.negate()
    recPubKeyObj.negate()

# Example tweak
taptweak = bytes.fromhex('3e75c57bb5493f932d418f8ff604f96a5d0565a056c0f0f6a9c1c07f25e2a403')

# Tweak the private key
# Method: ECKey.add()
tweaked_privkey = recPrivKeyParsed1.add(taptweak)

# Tweak the public key
# Method: use tweak_add()
taproot_pubkey = recPubKeyObj.tweak_add(taptweak)
taproot_pubkey_b = taproot_pubkey.get_bytes()

# Derive the bech32 address
# Use program_to_witness(version_int, pubkey_bytes)
address = program_to_witness_testnet(0x01, taproot_pubkey_b)

hrp = &quot;bc&quot;
witver, witprog = decode(hrp, address)
if witver is None:
    hrp = &quot;tb&quot;
    witver, witprog = decode(hrp, address)
scriptpubkey = segwit_scriptpubkey(witver, witprog)
print(&quot;the scriptPublicKey is: {}&quot;.format(scriptpubkey.hex()))

# Create a spending transaction
spending_tx = create_spending_transaction_nonode(txid='3f75f413db8ba76d7e26a9e93b9fe94990d58922cd0aaba09eac4b46b74437c2', scriptpubkey=scriptpubkey, amount_c=0.00032134)
print(&quot;Spending transaction:\n{}&quot;.format(spending_tx))

# Sign transaction with tweaked private key
# Method: TaprootSignatureHash(tx, output_list, hash_type=int, input_index=int, scriptpath=bool)
txout1 = CTxOut(nValue=36134, scriptPubKey=scriptpubkey)
sighash = TaprootSignatureHash(spending_tx, [txout1], SIGHASH_ALL, 0, False)
sig = sendPrivKeyParsed1.sign_schnorr(sighash)

# Add witness to transaction
spending_tx.wit.vtxinwit.append(CTxInWitness([sig]))
print(spending_tx.serialize().hex())

print(&quot;Success!&quot;)
</code></pre>
<p>I got this when trying to broadcast the transaction:</p>
<pre><code>sendrawtransaction RPC error: {&quot;code&quot;:-26,&quot;message&quot;:&quot;non-mandatory-script-verify-flag (Invalid Schnorr signature)&quot;}  
</code></pre>
<p>So why won't the network accept this transaction and how do I modify this transaction so it is accepted?</p>

CC BY-SA 4.0
2023-05-05T10:10:15.440Z
Hi @ChristianOConnor, your question is great and in-line with the scope of our site. Thank you for also answering it, after you found the solution. Please feel free to disregard the above comments, they are not in line with our community policies.—I’ll be removing them shortly.
Murch
CC BY-SA 4.0
2023-05-05T10:18:40.990Z
Oh nice! Haha thank you!
ChristianOConnor
<segregated-witness><taproot><p2tr><key-tweaking>
I get an Invalid Schnorr signature when trying to broadcast a taproot transaction
ChristianOConnor
# I get an Invalid Schnorr signature when trying to broadcast a taproot transaction

(Asked by: username_0 on 2023-05-05)

I have 0.00036134 testnet bitcoin at the segwit v1 address: tb1p3au39skpdd8suuhunr4ymp6ca6akv9keq20v5twuagpmyqntqaasl22f4w

I wrote this script to achieve 2 things: archive a hash in a transaction and send the money in tb1p3au39skpdd8suuhunr4ymp6ca6akv9keq20v5twuagpmyqntqaasl22f4w to a new address.

```
import random
from io import BytesIO

from util import CTxInWitness, CTxOut, create_spending_transaction_nonode
from helpers.address import program_to_witness_testnet
from helpers.key import ECKey, generate_key_pair, generate_bip340_key_pair, generate_schnorr_nonce, int_or_bytes
from helpers.segwit_addr2 import Encoding, decode, encode, segwit_scriptpubkey, bech32_decode
from helpers.script import CScript, CTransaction, OP_RETURN, SIGHASH_ALL, SIGHASH_ALL_TAPROOT, TaprootSignatureHash, tagged_hash

# Sending wallet creation
sendPrivKeyParsed1 = ECKey().set(int('SENDING PRIVATE KEY IN INTEGER'))
sendPubKeyObj = sendPrivKeyParsed1.get_pubkey()
recPubKeyBytes = sendPubKeyObj.get_bytes()

if sendPubKeyObj.get_y()%2 != 0:
    sendPrivKeyParsed1.negate()
    sendPubKeyObj.negate()

# Receiving wallet creation
recPrivKeyParsed1 = ECKey().set(int('RECEIVING ADDRESS PRIVATE KEY IN INTEGER'))
recPubKeyObj = recPrivKeyParsed1.get_pubkey()
recPubKeyBytes = recPubKeyObj.get_bytes()

if recPubKeyObj.get_y()%2 != 0:
    recPrivKeyParsed1.negate()
    recPubKeyObj.negate()

# Example tweak
taptweak = bytes.fromhex('3e75c57bb5493f932d418f8ff604f96a5d0565a056c0f0f6a9c1c07f25e2a403')

# Tweak the private key
# Method: ECKey.add()
tweaked_privkey = recPrivKeyParsed1.add(taptweak)

# Tweak the public key
# Method: use tweak_add()
taproot_pubkey = recPubKeyObj.tweak_add(taptweak)
taproot_pubkey_b = taproot_pubkey.get_bytes()

# Derive the bech32 address
# Use program_to_witness(version_int, pubkey_bytes)
address = program_to_witness_testnet(0x01, taproot_pubkey_b)

hrp = "bc"
witver, witprog = decode(hrp, address)
if witver is None:
    hrp = "tb"
    witver, witprog = decode(hrp, address)
scriptpubkey = segwit_scriptpubkey(witver, witprog)
print("the scriptPublicKey is: {}".format(scriptpubkey.hex()))

# Create a spending transaction
spending_tx = create_spending_transaction_nonode(txid='3f75f413db8ba76d7e26a9e93b9fe94990d58922cd0aaba09eac4b46b74437c2', scriptpubkey=scriptpubkey, amount_c=0.00032134)
print("Spending transaction:\n{}".format(spending_tx))

# Sign transaction with tweaked private key
# Method: TaprootSignatureHash(tx, output_list, hash_type=int, input_index=int, scriptpath=bool)
txout1 = CTxOut(nValue=36134, scriptPubKey=scriptpubkey)
sighash = TaprootSignatureHash(spending_tx, [txout1], SIGHASH_ALL, 0, False)
sig = sendPrivKeyParsed1.sign_schnorr(sighash)

# Add witness to transaction
spending_tx.wit.vtxinwit.append(CTxInWitness([sig]))
print(spending_tx.serialize().hex())

print("Success!")

```

I got this when trying to broadcast the transaction:

```
sendrawtransaction RPC error: {"code":-26,"message":"non-mandatory-script-verify-flag (Invalid Schnorr signature)"}  

```

So why won't the network accept this transaction and how do I modify this transaction so it is accepted?

**Tags:** segregated-witness, taproot, p2tr, key-tweaking

> **Comments:**
> **username_1**: Hi @username_0, your question is great and in-line with the scope of our site. Thank you for also answering it, after you found the solution. Please feel free to disregard the above comments, they are not in line with our community policies.—I’ll be removing them shortly.  
> **username_0**: Oh nice! Haha thank you!  

---

## 1 answers

### Answer by username_0 on 2023-05-05. Score: 1 | Accepted answer

Fixed it, the main problem is that:

```
# Sending wallet creation
sendPrivKeyParsed1 = ECKey().set(int('SENDING PRIVATE KEY IN INTEGER'))
sendPubKeyObj = sendPrivKeyParsed1.get_pubkey()
recPubKeyBytes = sendPubKeyObj.get_bytes()  

```

Was supposed to be this:

```
# Sending wallet creation
sendPrivKeyParsed1 = ECKey().set(int('SENDING PRIVATE KEY IN INTEGER'))
sendPubKeyObj = sendPrivKeyParsed1.get_pubkey()
sendPubKeyBytes = sendPubKeyObj.get_bytes()

```

The scriptPubKey needs to be calculated for both the sending and receiving addresses. In my original code, I did this to calculate the receiving address's scriptPubKey:

```
hrp = "bc"
witver, witprog = decode(hrp, address)
if witver is None:
    hrp = "tb"
    witver, witprog = decode(hrp, address)
scriptpubkey = segwit_scriptpubkey(witver, witprog)
print("the scriptPublicKey is: {}".format(scriptpubkey.hex()))  

```

So instead of `scriptpubkey`, you have `scriptpubkeyRec` and `scriptpubkeySend`. Maybe put the above code into a function that returns `scriptpubkey` and run it once for the sending address and once for the receiving address. If you write such a function called `get_scriptPubKey()`, the scriptPubKey generation would look like this:

```
# Derive the bech32 address
# Use program_to_witness(version_int, pubkey_bytes)
addressSend = program_to_witness_testnet(0x01, sendPubKeyBytes)
addressRec = program_to_witness_testnet(0x01, taproot_pubkey_b)

scriptpubkeySend = get_scriptPubKey1(addressSend)
scriptpubkeyRec = get_scriptPubKey1(addressRec)

```

Use `scriptpubkeyRec` here:

```
# Create a spending transaction
spending_tx = create_spending_transaction_nonode(txid='3f75f413db8ba76d7e26a9e93b9fe94990d58922cd0aaba09eac4b46b74437c2', scriptpubkey=scriptpubkeyRec, amount_c=0.00032134)  

```

Use `scriptpubkeySend` here:

```
txout1 = CTxOut(nValue=36134, scriptPubKey=scriptpubkeySend)  

```

The last problem is that you need to sign with the sending key like this:

```
sig = sendPrivKeyParsed1.sign_schnorr(sighash)  

```

After I made these changes the transaction worked <https://blockstream.info/testnet/tx/55d8281e28240aa84f23026f335128d0c4e0c8868617cb65bc92a1ddc9c1f322>


---

