Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chapter 7, Exercise 4: Confused on the Solution #249

Open
vvronskyFX opened this issue Aug 5, 2022 · 9 comments
Open

Chapter 7, Exercise 4: Confused on the Solution #249

vvronskyFX opened this issue Aug 5, 2022 · 9 comments

Comments

@vvronskyFX
Copy link

vvronskyFX commented Aug 5, 2022

I'm working through this exercise and it's been some time. I want to move forwards to Ch 8 but I really want to get this solution to work.

First thing that stands out here is the the instruction to "Create a testnet transaction that sends 60% of a single UTXO to mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv The remaining amount minus fees should go back to your own change address. This should be a one-input, two-output transaction."

However, in the solution, the target_address is 'miKegze5FQNCnGw6PKyqUbYUeBa4x2hFeM'

Next is we need to include a fee in there but I don't see how I can set up a fee.

Next is the fact that we want 60% of the UTXO to be sent to the target address. I just put in a target_amount of 0.0002

All in all, i get a Hex code but when i run >>> print(tx_obj.sign_input(0, priv)) I get a FALSE output.

Here's the solution screenshot:
image

Here's my code within Exercise 4:
image

I couldn't find any solution online. Has anyone passed this exercise here?

@vvronskyFX
Copy link
Author

How can we get fees in there? I've broadcasted the last transaction but it's having difficulty confirming. See this bitcoin testnet transaction: https://live.blockcypher.com/btc-testnet/tx/2946d9b34eb63575898fc881ec0e157154f9afd24ed3d371f83616f097c9043e/

No fees. Would be nice to get them in there. I'll play around with it and post updates here.

@vvronskyFX
Copy link
Author

UPDATE:

I've been able to resolve the FALSE output. Let's look at the "priv" variable.

I changed priv = PrivateKey(secret=secret) to
priv = PrivateKey(secret)

@alexbarron
Copy link

The fees are not explicitly set in a transaction. They must be implicitly set based on this formula: fee = input_amount - target amount - change_amount

Just reduce the target_amount or change_amount in your code to automatically include a fee. I calculated it by doing this:

input_amount = 0.0005690
target_amount = input_amount * 0.6
change_amount = input_amount * 0.36

This is a rather generous fee. Apparently I overpaid by 912%!

@vvronskyFX
Copy link
Author

The fees are not explicitly set in a transaction. They must be implicitly set based on this formula: fee = input_amount - target amount - change_amount

Just reduce the target_amount or change_amount in your code to automatically include a fee. I calculated it by doing this:

input_amount = 0.0005690
target_amount = input_amount * 0.6
change_amount = input_amount * 0.36

This is a rather generous fee. Apparently I overpaid by 912%!

@alexbarron Thanks so much for sharing this! I'm just about wrapped up with Ch 12 and Ch 13. Once I wrap those up, I'll revisit Ch 4 and implement this again. Cheers!

@asteryeyo
Copy link

asteryeyo commented Oct 17, 2022

Hello all,
I tried to run Example 4 but I was not able to broadcast the transaction on https://live.blockcypher.com/btc/pushtx/
gives me an error
Error validating transaction: witness script detected in tx without witness data.

My code:

from ecc import PrivateKey
from helper import decode_base58, SIGHASH_ALL
from script import p2pkh_script, Script
from tx import TxIn, TxOut, Tx
prev_tx = bytes.fromhex('c4c34a8d9a705a1a7e4bd753314e25697f82622f5cbf25ea4dbb2b6f48ce719a')
prev_index = 1
target_address = 'mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv'
change_address = 'mtjfgktYZdoEt8XgU5gM7BRx4yrHsqY1yG'
input_amount = 0.0002
target_amount = input_amount * 0.6
change_amount = input_amount * 0.36
#secret = 8675309
priv = PrivateKey(secret)
tx_ins = []
tx_ins.append(TxIn(prev_tx, prev_index))
tx_outs = []
h160 = decode_base58(target_address)
script_pubkey = p2pkh_script(h160)
target_satoshis = int(target_amount100000000)
tx_outs.append(TxOut(target_satoshis, script_pubkey))
h160 = decode_base58(change_address)
script_pubkey = p2pkh_script(h160)
change_satoshis = int(change_amount
100000000)
tx_outs.append(TxOut(change_satoshis, script_pubkey))
tx_obj = Tx(1, tx_ins, tx_outs, 0, testnet=True)
print(tx_obj.sign_input(0, priv))
print(tx_obj.serialize().hex())
print(secret)


I created secret as
from ecc import PrivateKey
from helper import hash256, little_endian_to_int
secret = little_endian_to_int(hash256(b'Hashir secret'))
private_key = PrivateKey(secret)
print(private_key.point.address(testnet=True))
print(secret)

Notes:
I sent some coins 0.0006 to my address
mtjfgktYZdoEt8XgU5gM7BRx4yrHsqY1yG
I use the prev transaction from here: https://live.blockcypher.com/btc-testnet/address/mtjfgktYZdoEt8XgU5gM7BRx4yrHsqY1yG/
but I am unable to broadcast the transaction

@marteaga76
Copy link

@asteryeyo @vvronskyFX
FYI, I was getting a similar error and finally got to the bottom of it.
In my case the issue was that in Chapter 4 Exercise 9 where you are asked to create an address the book does not specify compressed vs. uncompressed format. I chose uncompressed, which led to pain, as in the Chapter 7, the Tx.sign_input method assumes compressed when creating the script_sig.

def sign_input(self, input_index, private_key):
    # get the signature hash (z)
    # get der signature of z from private key
    # append the SIGHASH_ALL to der (use SIGHASH_ALL.to_bytes(1, 'big'))
    # calculate the sec
    # initialize a new script with [sig, sec] as the cmds
    # change input's script_sig to new script
    # return whether sig is valid using self.verify_input
    #raise NotImplementedErro
    z=self.sig_hash(input_index)
    sig=private_key.sign(z).der()
    sig+=SIGHASH_ALL.to_bytes(1, 'big')
    sec = private_key.point.sec(compressed=False)  #<-- this fixed it for me
    script=Script([sig, sec])
    self.tx_ins[input_index].script_sig=script
    return self.verify_input(input_index)

@MolekoManyanye
Copy link

I'm working through this exercise and it's been some time. I want to move forwards to Ch 8 but I really want to get this solution to work.

First thing that stands out here is the the instruction to "Create a testnet transaction that sends 60% of a single UTXO to mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv The remaining amount minus fees should go back to your own change address. This should be a one-input, two-output transaction."

However, in the solution, the target_address is 'miKegze5FQNCnGw6PKyqUbYUeBa4x2hFeM'

Next is we need to include a fee in there but I don't see how I can set up a fee.

Next is the fact that we want 60% of the UTXO to be sent to the target address. I just put in a target_amount of 0.0002

All in all, i get a Hex code but when i run >>> print(tx_obj.sign_input(0, priv)) I get a FALSE output.

Here's the solution screenshot: image

Here's my code within Exercise 4: image

I couldn't find any solution online. Has anyone passed this exercise here?

response regarding the fees: i constructed my transaction with zero fees and after all the signing , i calculated the serialized txn hash . i then set my fees to 1*transaction length, that is paying 1 Satoshi per byte

@MolekoManyanye
Copy link

i meant the serialized txn length not length of its hash

@MolekoManyanye
Copy link

Hello all, I tried to run Example 4 but I was not able to broadcast the transaction on https://live.blockcypher.com/btc/pushtx/ gives me an error Error validating transaction: witness script detected in tx without witness data.

My code:

from ecc import PrivateKey from helper import decode_base58, SIGHASH_ALL from script import p2pkh_script, Script from tx import TxIn, TxOut, Tx prev_tx = bytes.fromhex('c4c34a8d9a705a1a7e4bd753314e25697f82622f5cbf25ea4dbb2b6f48ce719a') prev_index = 1 target_address = 'mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv' change_address = 'mtjfgktYZdoEt8XgU5gM7BRx4yrHsqY1yG' input_amount = 0.0002 target_amount = input_amount * 0.6 change_amount = input_amount * 0.36 #secret = 8675309 priv = PrivateKey(secret) tx_ins = [] tx_ins.append(TxIn(prev_tx, prev_index)) tx_outs = [] h160 = decode_base58(target_address) script_pubkey = p2pkh_script(h160) target_satoshis = int(target_amount_100000000) tx_outs.append(TxOut(target_satoshis, script_pubkey)) h160 = decode_base58(change_address) script_pubkey = p2pkh_script(h160) change_satoshis = int(change_amount_100000000) tx_outs.append(TxOut(change_satoshis, script_pubkey)) tx_obj = Tx(1, tx_ins, tx_outs, 0, testnet=True) print(tx_obj.sign_input(0, priv)) print(tx_obj.serialize().hex()) print(secret)

I created secret as from ecc import PrivateKey from helper import hash256, little_endian_to_int secret = little_endian_to_int(hash256(b'Hashir secret')) private_key = PrivateKey(secret) print(private_key.point.address(testnet=True)) print(secret)

Notes: I sent some coins 0.0006 to my address mtjfgktYZdoEt8XgU5gM7BRx4yrHsqY1yG I use the prev transaction from here: https://live.blockcypher.com/btc-testnet/address/mtjfgktYZdoEt8XgU5gM7BRx4yrHsqY1yG/ but I am unable to broadcast the transaction

some one apparently has 345 tBTC. Looks like you have the wrong index. prev_index has to be a 0 not 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants