def make_keys(master): # master will be the master frame for this view, the key_fram from the F3_Frame Clas keys_array = [] for i in range(5): try: # generate the random private key as 32 bytes private_key_bytes_generated = os.urandom(32) # make the random 32 bytes into an integer private_key_int = int.from_bytes(private_key_bytes_generated, byteorder='big', signed=False) # create the private/public key object key_object = PrivateKey(private_key_int) # make the private key into 32 bytes from the key object private key (.secret) as an integer private_key_bytes = key_object.secret.to_bytes(32, byteorder='big', signed=False) # make the public key in compressed sec format public_key_bytes = key_object.point.sec() keys_array.append((private_key_bytes, public_key_bytes)) except ValueError: pass print(keys_array) wallet = MyDatabase("wallet") wallet.insert_keys(keys_array)
def sign_all_inputs(self, utxo_array): print("In sign_all_inputs") for i in range(len(self.tx_ins)): # get the private/public keys from the wallet database keys table_name # that point to the utxo database id. wallet = MyDatabase("wallet") # keys_list is a list of tuples: (keys_id, private_key, public_key) utxo_db_id = utxo_array[i].id print("Retrieving keys for the utxo") keys_list = wallet.retrieve_keys_for_utxo_db_id(utxo_db_id) private_keys = [] for pair in keys_list: private_key_bytes = pair[1] private_key_int = int.from_bytes(private_key_bytes, byteorder='big', signed=False) private_keys.append(private_key_int) # private_keys is a list of private keys as integers that are associated with the # applicable utxo. # For now: assuming only one private key is associated with a utxo. # Revision Note: Will need to change the above assumption to allow for mutlisig. private_key = PrivateKey( private_keys[0] ) #private_key in the tx.sign_input is a private_key object self.sign_input(input_index=i, private_key=private_key)
def update_utxo_for_spent(pushed_tx): tx_inputs = pushed_tx['tx'][ 'inputs'] # array of JSON for certain input values see above example input_update_arg = [] for input in tx_inputs: input_update_arg.append( (bytes.fromhex(input['prev_hash']), input['output_index'])) MyDatabase.update_db_utxo_table_spent(input_update_arg)
def show_keys(master): # master will be the master frame for this view, the key_frame from the F3_Frame Class wallet = MyDatabase("wallet") # key_pairs is an array of tuples...(private_key, public_key) # private_key is a blob in wif format, public_key is a blob in sec key_pairs = wallet.retrieve_keys() print(key_pairs) f3_view.show_keys_view(master, key_pairs)
def create_table(self): print("Creating table") column_info_array = [] for col in self.column_info_list: print("%s, %s" % (col.column_name.get(), col.column_type.get())) column_info_array.append( (col.column_name.get(), col.column_type.get())) db = MyDatabase(self.db_name.get()) db.create_table(self.table_name.get(), column_info_array)
def grab_address(id): """ Returns the Base58 with checksum address for the public key calculated from the private key stored in the wallet database Arguments: :id None right now--but will need to give the database id to tell which private key to retrieve Return: :str Base58 address """ # # Get the private and public keys from the database given the id # wallet = MyDatabase("wallet") # key_pairs is an array of tuples...(private_key, public_key) # private_key is a blob in wif format, public_key is a blob in sec #### ! #### ! right now hardwiring in the id=1, but will need to make that user specifiable #### ! id = id # key_pairs is a private, public key tuple key_pairs = wallet.keys(id) # private_key is a bytes object that should be interpreted as an big endian integer # public_key is a bytes object that of the compressed sec public point. private_key_bytes, public_key_bytes = key_pairs private_key_int = int.from_bytes(private_key_bytes, byteorder='big', signed=False) # # generate the public key from the private key retrieved in the database # key_object = PrivateKey(private_key_int) # produce the public key address public_key_address = key_object.point.address(testnet=True) print("address: {}".format(public_key_address)) return public_key_address
def __init__(self, master): # master is a.app # self is a.app.notebook super().__init__(master) self.pack(fill=tk.BOTH, expand=tk.YES) #self.grid(column=0, row=0, sticky=(tk.N,tk.W,tk.E,tk.S)) #self.db_ops_frame = F1Frame(self) self.master = master self.wallet = MyDatabase('wallet') print("Notebook wallet: {}".format(self.wallet.amount)) self.f2 = F2Frame( self) # making the master of a.app.notebook.f2 as a.app.notebook self.f3 = F3Frame(self) self.f4 = F4Frame(self) #self.add(self.db_ops_frame, text ='Database Operations') self.add(self.f2, text='Transaction Info') self.add(self.f3, text='Generate Keys') self.add(self.f4, text='Generate Tx')
import sys sys.path.append('./programming_bitcoin_song/') from programming_bitcoin_song.tx import Tx, TxIn, TxOut, Connection, TxFetcher from programming_bitcoin_song.ecc import PrivateKey from programming_bitcoin_song.helper import encode_base58_checksum, hash160 from io import BytesIO import os # # Get the private and public keys from the database given the id # wallet = MyDatabase("wallet") # key_pairs is an array of tuples...(private_key, public_key) # private_key is a blob in wif format, public_key is a blob in sec id = 1 # key_pairs is a private, public key tuple key_pairs = wallet.keys(id) # private_key is a bytes object that should be interpreted as an big endian integer # public_key is a bytes object that of the compressed sec public point. private_key_bytes, public_key_bytes = key_pairs private_key_int = int.from_bytes(private_key_bytes, byteorder='big', signed=False) # Generate the address--from the public-key in database and from the private_key # Check that those two paths result in the same address
def create_factory_input_array(self): """ Arguments: Return: :list of utxo factory objects that will be used to create the TxIn list. Potential Revision Note: :Further Revisions: Will need to revise this method to accommodate the witness field if the input is a segwit. But maybe that won't be required until input is signed. """ # # Will need to retrive the utxo info from the database and then fetch the transaction # # Get the utxo info from the database # wallet = MyDatabase("wallet") # # get all wallet rows that could be potential utxos to spend, i.e. those with status="utxo" wallet_rows = wallet.get_utxo_rows( ) #array of tupples (id, utxo_hash, out_index, amount, status) print("utxos: {}".format(wallet_rows)) pruned_wallet_rows = [ ] # this is the new list formed with just enough utxos to pay the total_paid_amount and fee for utxo in wallet_rows: if self.total_input_amount <= self.total_paid_amount + 100000: #assuming not more than 100000 sats for fee pruned_wallet_rows.append(utxo) self.total_input_amount += utxo[3] else: break if self.total_input_amount < self.total_paid_amount + 100000: return "Error! Not enough Bitcoin" for u in pruned_wallet_rows: # u is a tuple housing the row from the database: # u[0]: database id # u[1]: utxo_hash # u[2]: out_index # u[3]: amount # u[4]: status utxo_db_id, utxo_hash, out_index, amount, status = u utxo_hash_hex = utxo_hash.hex() # tx hash for input in hex utxo_tx = TxFetcher.fetch(utxo_hash_hex, testnet=True, fresh=False) print(utxo_tx) ################################# Moved functionaity to tx.py sign_all_inputs########## # # get the private/public keys from the wallet database keys table_name # # that point to the utxo database id. # # wallet = MyDatabase("wallet") # # keys_list is a list of tuples: (keys_id, private_key, public_key) # keys_list = wallet.retrieve_keys_for_utxo_db_id(utxo_db_id) # private_keys = [] # for pair in keys_list: # private_key_bytes = pair[1] # private_key_int = int.from_bytes(private_key_bytes, byteorder='big', signed=False) # private_keys.append(private_key_int) ################################# Moved functionaity to tx.py sign_all_inputs########## # get the script pubkey of the utxo of interest utxo_script_pubkey = utxo_tx.tx_outs[out_index].script_pubkey # determine the script pubkey type utxo_script_pubkey_type = utxo_script_pubkey.determine_script_pubkey_type( ) print("utxo script pubkey type: " + utxo_script_pubkey_type) #make a utxo factory object from the fetched tx_object ### # Assuming for now that only one private key is needed # Will need to accommodate mutiple keys to sign a utxo later ### #ut =Utxo(prev_tx=utxo_hash, output_index=out_index, private_key=private_keys[0], amount=amount, id=utxo_db_id) ut = Utxo(prev_tx=utxo_hash, output_index=out_index, amount=amount, id=utxo_db_id) # add the utxo factory object to the factory utxo_array self.utxo_array.append(ut) # # Revision for multi-sig: # Each index entry in utxo_array is associated with an input transaction. # For multisig transactions, we'll need to make an index entry itself an array, # holding all the utxos that will make the multisig input. return self
def calculate_wallet_amount(): wallet_amount = MyDatabase.wallet_amount() return (wallet_amount)
def update_db_keys_utxos(keys_update_input): MyDatabase.update_keys_for_utxos(keys_update_input)
def update_db_for_utxo(pushed_tx): t = sort_pushed_tx_for_utxo_update(pushed_tx) update_utxo_for_utxo = MyDatabase.update_utxo_for_utxo(t) return update_utxo_for_utxo
# produce the public key address ### # Update Note: The public key address will depend on what type of ScriptPubkey # will be used. Assume for now p2pkh--which would require the Base58 of the # hash160 of the public key. p2sh would require the Base58 of the hash160 # of the Redeem script. ### # get the compressed sec public key compressed = True compressed_public_key_address = key_object.point.sec(compressed) ## # Update Note: Maybe a verification that the public_key_address just created from the # private key is the same address that results from the database public_key. # Would need to take that public_key--take it from bytes to dar [?] to base58 [?] ## # create array of tuples (db_id associated with private_key that make the public_key_address, public_key-address) n_addresses.append((key[0], compressed_public_key_address)) # Return info to the view # uncomment when used in the app--comment for temp__run1 #f4_view.show_possible_payees(frame_object, possible_payee_addresses) return n_addresses wallet = MyDatabase('wallet') n = 4 addresses = get_n_public_addresses(wallet, n) print(addresses) print(len(addresses))