def form_transaction(sender, recipient, amount, utxo_obj, wif): outputs = [] inputs = [] spendable_utxo = utxo_obj.get_outputs_to_spend(sender, int(amount) + tx_fee) if len(spendable_utxo) == 0: raise Exception( "Address " + sender + " has not enough spendable outputs, can't form transaction") utxo_sum = 0 for v in spendable_utxo: utxo_sum += v.output.nVal outputs.append(Output(int(amount), recipient)) if utxo_sum - int(amount) - tx_fee > 0: outputs.append(Output(utxo_sum - int(amount) - tx_fee, sender)) inputs_outpoint_dict = {} # {spendable_output : input} for outs in spendable_utxo: inputs_outpoint_dict[outs] = Input(outs.txid, int(outs.vout, 16), "", 0xffffffff) # forming scriptSig for all inputs scripts = {} # {spendable_output : scriptSig} for spendable_output in inputs_outpoint_dict.keys(): scripts[spendable_output] = get_signed_scriptSig( spendable_output, inputs_outpoint_dict.copy(), outputs, wif) for k in scripts.keys(): inputs.append(Input(k.txid, int(k.vout, 16), scripts[k], 0xffffffff)) return Transaction(1, inputs, outputs, 0)
def do_send(self, args): if self.key_pair == 0: print("Haven`t key pair") return False split = args.strip().split(' ') if (not args or len(split) != 2): print("Please input [Recipient Address] [Amount]") return False t_recip, t_amount = split if t_recip == '-s': self.transactions.append(t_amount) return False t_amount = int(t_amount) try: # if True: self.update_unspend_pool() sum_of_inp, prev_outputs = self.get_outputs(t_amount) inputs = [Input(txid=bytearray.fromhex(txid), vout=vout) for txid, vout, o in prev_outputs] outputs = [Output(recipient=t_recip, value=t_amount)] if sum_of_inp - t_amount > FEE: change = sum_of_inp - t_amount - FEE outputs.append(Output(self.key_pair.get_address(), value=(change))) tx = Transaction(inputs, outputs) tx.sign_tx(prev_outputs, self.key_pair) s_tx = Serializer.serialize(tx) print(s_tx) self.transactions.append(s_tx) except Exception as identifier: print (f'Error:[{identifier}]') return False
def create_transaction(self, amount, recipient_address): """ the functions creates transaction which contains the amount of coins to send the recipient address, the function implements the transaction in the block chain :param amount: the amount to send :param recipient_address: the address to send the coins to :returns: true if there is enough money to the transaction and false otherwise """ # updates the balance self.update_balance() # checks weather there is enough money # to the transaction if amount > self.balance: self.logger.info(self.address + '- not enough money to send') return False # creates the new transaction new_transaction = Transaction([], []) sending_amount = 0 for unspent_output in self.unspent_outputs: # creating the proof data_to_sign = unspent_output.transaction_id data_to_sign += recipient_address data_to_sign = self.hash(data_to_sign).hexdigest() data_to_sign += str(amount) data_to_sign = self.hash(data_to_sign) signature = self.sign(data_to_sign) proof = (signature, self.public_key) new_transaction.add_input( Input(unspent_output.transaction_id, unspent_output.output_index, proof)) sending_amount += unspent_output.output.value if sending_amount >= amount: break new_transaction.add_output(Output(sending_amount, recipient_address)) # add change if it is needed if sending_amount > amount: change = sending_amount - amount new_transaction.add_output(Output(change, self.address)) # distributes the transaction self.logger.info(self.address + " is sending " + str(amount) + "LPC to " + recipient_address) self.distribute_transaction(new_transaction) return True
def from_dict(cls, config, mongo, txn): try: relationship = Relationship(**txn.get('relationship', '')) except: relationship = txn.get('relationship', '') return cls(config=config, mongo=mongo, transaction_signature=txn.get('id'), rid=txn.get('rid', ''), relationship=relationship, public_key=txn.get('public_key'), dh_public_key=txn.get('dh_public_key', ''), fee=float(txn.get('fee')), requester_rid=txn.get('requester_rid', ''), requested_rid=txn.get('requested_rid', ''), txn_hash=txn.get('hash', ''), inputs=[ Input.from_dict(input_txn) for input_txn in txn.get('inputs', '') ], outputs=[ Output.from_dict(output_txn) for output_txn in txn.get('outputs', '') ], coinbase=txn.get('coinbase', ''), signatures=txn.get('signatures', ''))
def run(cls, config, mongo, to, value): Peers.init(config, mongo, config.network) try: transaction = TransactionFactory( config, mongo, fee=0.01, public_key=config.public_key, private_key=config.private_key, outputs=[Output(to=to, value=value)]) except NotEnoughMoneyException as e: print "not enough money yet" return except: raise try: transaction.transaction.verify() except: print 'transaction failed' TU.save(transaction.transaction) print 'Transaction generated successfully. Sending:', value, 'To:', to for peer in Peers.peers: try: socketIO = SocketIO(peer.host, peer.port, wait_for_connection=False) chat_namespace = socketIO.define(ChatNamespace, '/chat') chat_namespace.emit('newtransaction', transaction.transaction.to_dict()) socketIO.disconnect() print 'Sent to:', peer.host, peer.port except Exception as e: print e
def deserialize_output(s): 'return output and it`s n chars' padd = 0 r_o = Output() r_o.value = int.from_bytes(bytearray.fromhex(s[0:16]), byteorder='little') #? value padd += 16 s = s[16:] r_o.script_pub_key_size, v_int = var_int.varint_to_int( s) #? script pub_key size padd += v_int s = s[v_int:] r_o.script_pub_key = s[0:r_o.script_pub_key_size * 2] #? script pub_key padd += r_o.script_pub_key_size * 2 return (r_o, padd)
def add_new_block(self, miner_address): """ the function adds new block to the chain and rewards the miner :param miner_address: the miner address to reward """ number = len(self.chain) # handle genesis block if number == 0: prev = '0' * 32 else: prev = self.chain[-1].hash_code # transaction that rewards the miner # the input proof is arbitrary transaction_input = Input(str(len(self.chain)), -1, (miner_address, '')) transaction_output = Output(REWORD, miner_address) new_transaction = Transaction([transaction_input], [transaction_output]) self.add_transaction(new_transaction) # create the block block = Block.new_block(number, prev, self.transactions_pool) self.logger.info('Mining new block') block.mine_block() # set the block chain self.chain.append(block) self.transactions_pool = [] self.logger.info('The new block was added to the block chain')
def form_coinbase(miner_address, wif, g_miner_reward): outputs = [Output(g_miner_reward, miner_address)] inputs = [] scriptSig = script.get_scriptSig( wif, "tanya works better") # it can contain any data i like :) inputs.append(Input(coinbase_txid, 0xffffffff, scriptSig, 0xffffffff)) return CoinbaseTransaction(1, inputs, outputs, 0)
def input_listener(request): nonlocal bc request_data = json.loads(request.data) candidate_input = Output.from_dict(request_data) status = bc.get_output_status(candidate_input) payload = {'Status': status} return Response(json.dumps(payload), mimetype='application/json')
def run(cls, config, mongo): used_inputs = [] new_inputs = [] for x in mongo.site_db.faucet.find({'active': True}): balance = BU.get_wallet_balance(config, mongo, x['address']) if balance >= 25: mongo.site_db.faucet.update({'_id': x['_id']}, { 'active': False, 'address': x['address'] }) continue last_id_in_blockchain = x.get('last_id') if last_id_in_blockchain and not mongo.db.blocks.find({ 'transactions.id': last_id_in_blockchain }).count(): continue try: transaction = TransactionFactory( config, mongo, block_height=BU.get_latest_block(config, mongo)['index'], fee=0.01, public_key=config.public_key, private_key=config.private_key, outputs=[Output(to=x['address'], value=5)]) except NotEnoughMoneyException as e: print "not enough money yet" return except Exception as e: print x try: transaction.transaction.verify() except: mongo.site_db.failed_faucet_transactions.insert( transaction.transaction.to_dict()) print 'faucet transaction failed' TU.save(config, mongo, transaction.transaction) x['last_id'] = transaction.transaction.transaction_signature mongo.site_db.faucet.update({'_id': x['_id']}, x) print 'saved. sending...', x['address'] for peer in Peers.peers: try: socketIO = SocketIO(peer.host, peer.port, wait_for_connection=False) chat_namespace = socketIO.define(ChatNamespace, '/chat') chat_namespace.emit('newtransaction', transaction.transaction.to_dict()) socketIO.disconnect() except Exception as e: print e
def __init__( self, config, mongo, block_height, time='', rid='', transaction_signature='', relationship='', public_key='', dh_public_key='', fee=0.0, requester_rid='', requested_rid='', txn_hash='', inputs='', outputs='', coinbase=False, signatures=None, extra_blocks=None ): self.config = config self.mongo = mongo self.block_height = block_height self.time = time self.rid = rid self.transaction_signature = transaction_signature self.relationship = relationship self.public_key = public_key self.dh_public_key = dh_public_key self.fee = fee self.requester_rid = requester_rid self.requested_rid = requested_rid self.hash = txn_hash self.outputs = [] self.extra_blocks = extra_blocks for x in outputs: self.outputs.append(Output.from_dict(x)) self.inputs = [] for x in inputs: if 'signature' in x and 'public_key' in x: self.inputs.append(ExternalInput.from_dict(self.config, self.mongo, x)) else: self.inputs.append(Input.from_dict(x)) self.coinbase = coinbase if not signatures: signatures = [] self.signatures = [] for signature in signatures: if isinstance(signature, FastGraphSignature): self.signatures.append(signature) else: self.signatures.append(FastGraphSignature(signature))
def deserialize_output(self, serial): nVal = int(little_endian(serial[:16]), 16) serial = serial[16:] slen, shift1 = get_script_length(serial) serial = serial[shift1:] scriptPubKey = serial[:slen] serial = serial[slen:] shift = 16 + slen + shift1 return (shift, Output(nVal, wallet.pubkey_hash_to_address(scriptPubKey[6:-4])))
def __create_create_coin(self): # Create coin transaction inputs = [] outputs = [ Output(50, utils.get_public_key(self.user)), ] unsigned = UnsignedTransaction(CREATECOINS_TYPE, inputs, outputs) to_sign = unsigned.DataForSigs() sigs = {} sigs[self.scrooge.export_key(format='DER')] = sign(to_sign, 'privatekeyScrooge.pem') transaction = Transaction(unsigned, sigs) return transaction
def deserialize_output_json(j_output): o = Output() o.value = int(j_output['value']) o.recipient_address = bytearray.fromhex(j_output['recipient']) o.script_pub_key = j_output['script_pub_key'] o.script_pub_key_size = int(j_output['script_pub_key_size']) return o
def get_outputs_to_spend(self, sender, amount): utxos_to_spend = [] utxos_amount = 0 for key in self.pool: if sender == pubkey_hash_to_address(self.pool[key].scriptPubKey[6:-4]): txid = key[8:] vout = key[:8] nVal = self.pool[key].nVal recipient = pubkey_hash_to_address(self.pool[key].scriptPubKey[6:-4]) utxos_to_spend.append(OutPoint(vout, txid, Output(nVal, recipient))) utxos_amount += self.pool[key].nVal if utxos_amount > amount: break return utxos_to_spend
def generate_random_outputs(property_addr=None, input_value=100): """Generates 1-2 random outputs. If address is given, use that for outputs. Otherwise, address will be generated randomly.""" output_list = list() num_outputs = randint(1, 2) if property_addr is None: property_addr = FAKE.address().replace('\n', ', ') if num_outputs == 1: output_value = input_value else: output_value = randint(1, input_value - 1) for idx in range(num_outputs): output = Output.make_random_output(idx, output_value, property_addr) output_list.append(output) output_value = input_value - output_value return output_list
def deserialize_output(s): padd = 0 r_o = Output() r_o.value = int.from_bytes(bytearray.fromhex(s[0:16]), byteorder='little') #? value padd += 16 s = s[16:] r_o.script_pub_key_size, v_int = var_int.varint_to_int(s) #? script pub_key size padd += v_int s = s[v_int:] r_o.script_pub_key = s[0:r_o.script_pub_key_size * 2] #? script pub_key padd += r_o.script_pub_key_size * 2 a_len , v_int = var_int.varint_to_int(r_o.script_pub_key[5:7]) r_o.recipient_address = r_o.script_pub_key[5 + v_int: a_len] #? p2pkh getting addres from return (r_o, padd)
def create_property(bc, host='registrar'): """Creates property on demand""" headers = {'content-type': 'application/json'} registrar_txn_url = 'http://{}:58336/jsonrpc'.format(host) input_list = [choice(list(DATABASE_WALLETS.keys()))] property_addr = input('New property address?') num_outputs = int(input('Number of new owners?')) total_value = 0 output_list = list() btc_txn_hash = None for idx in range(num_outputs): value_i = int(input('Value to owner #' + str(idx + 1) + '?')) wallet_addr = input('Wallet address of owner #' + str(idx + 1) + '?') script = make_random_string() if value_i <= 0: print('Non-positive value invalid') raise ValueError('Non-positive value invalid') total_value += value_i output = Output(wallet_addr, property_addr, value_i, idx, script) output_list.append(output) if total_value != 100: print('Total value not equal 100, try again') raise ValueError('Total value not equal 100, try again') # create transaction new_transaction = Transaction(input_list, output_list, 'propGen', btc_txn_hash) print('Transaction hash (own chain):') print(new_transaction.transaction_hash) # send transaction to registrar payload = new_transaction.to_dict() requests.post(registrar_txn_url, data=json.dumps(payload), headers=headers) print('Property creation request sent to registrar: ' + property_addr)
def __init__(self, chain, unspent_output_dict, max_txns=10, difficulty=0x1e200000): """__init__ method for Blockchain class. Args: chain (dict): Dictionary object to contain blocks. unspent_output_dict (dict): Dictionary object to contain unspent transactions. max_txns (int, optional): Maximum number of transactions for an individual block. Defaults to 10. difficulty (int, optional): Difficulty target for blockchain. Defaults to 0x1e200000. """ self.chain = chain self.max_txns = max_txns self.difficulty = difficulty self.unspent_output_dict = unspent_output_dict genesis_hash = '0000000000000000000000000000000000000000000000000000000000000000' genesis_input = ['a'] genesis_output = [Output('That has', 'such people', 100, 0, 'in \'t')] genesis_tx = Transaction(genesis_input, genesis_output, txn_type='propGen') genesis_block = Block([genesis_tx], genesis_hash, timestamp=1231006505) self.add_new_block(genesis_block, genesis=True)
def do_payout_for_block(self, block): # check if we already paid out already_used = self.already_used(block.get_coinbase()) if already_used: return existing = self.mongo.db.share_payout.find_one({'index': block.index}) if existing: pending = self.mongo.db.miner_transactions.find_one({'inputs.id': block.get_coinbase().transaction_signature}) if pending: return else: # rebroadcast transaction = Transaction.from_dict(self.config, self.mongo, existing['txn']) TU.save(self.config, self.mongo, transaction) self.broadcast_transaction(transaction) return try: shares = self.get_share_list_for_height(block.index) except: return total_reward = block.get_coinbase() if total_reward.outputs[0].to != self.config.address: return pool_take = 0.01 total_pool_take = total_reward.outputs[0].value * pool_take total_payout = total_reward.outputs[0].value - total_pool_take outputs = [] for address, x in shares.iteritems(): exists = self.mongo.db.share_payout.find_one({'index': block.index, 'txn.outputs.to': address}) if exists: raise PartialPayoutException('this index has been partially paid out.') payout = total_payout * x['payout_share'] outputs.append(Output(to=address, value=payout)) try: transaction = TransactionFactory( self.config, self.mongo, fee=0.0001, public_key=self.config.public_key, private_key=self.config.private_key, inputs=[Input(total_reward.transaction_signature)], outputs=outputs ) except NotEnoughMoneyException as e: print "not enough money yet" return except Exception as e: print e try: transaction.transaction.verify() except: raise print 'faucet transaction failed' TU.save(self.config, self.mongo, transaction.transaction) self.mongo.db.share_payout.insert({'index': block.index, 'txn': transaction.transaction.to_dict()}) self.broadcast_transaction(transaction.transaction)
def transact_property(bc, host='registrar'): """Transacts property on demand""" headers = {'content-type': 'application/json'} registrar_input_url = 'http://{}:58335/jsonrpc'.format(host) registrar_txn_url = 'http://{}:58336/jsonrpc'.format(host) wallet_privkeys = [ 'cPZa7oEsR6GBuyrUH1s64meMZB31nxxPbhCVc4HZot55kgFGhWUg', 'cQ8RV14JvX8X9sNg2VAp98tGT1kG4BaG1NBy75T3jNeX8YYGAWUf', 'cQ6PpZDZQmffjo9X1PAriUCX7asMog8kM8t8tBf1WoqLwomkvkh9', 'cV88fZveSBQjcGZkfnDbY8akcBPEM3L1CCLehb8D4Kc8dHNLmzTG' ] input_hash = input('Hash of input to spend?') candidate_input = bc.unspent_output_dict[input_hash][0] payload = candidate_input.to_dict() return_data = requests.post(registrar_input_url, data=json.dumps(payload), headers=headers).json() if return_data['Status'] != 'Unspent': print('Attempted to create propTx with invalid input') raise ValueError('Attempted to create propTx with invalid input') input_list = [candidate_input] # generate random number of outputs property_addr = candidate_input.property_addr input_value = candidate_input.value print('Input value to spend: ' + str(input_value)) num_outputs = int(input('Number of new owners?')) output_list = list() total_value = 0 for idx in range(num_outputs): wallet_addr = input('Wallet address of owner #' + str(idx + 1) + '?') value_i = int(input('Value to owner #' + str(idx + 1) + '?')) script = make_random_string() if value_i <= 0: print('Non-positive value invalid') raise ValueError('Non-positive value invalid') total_value += value_i output = Output(wallet_addr, property_addr, value_i, idx, script) output_list.append(output) if total_value != input_value: print('Total output value not equal intput value, try again') raise ValueError('Total output value not equal input value, try again') testnet = Bitcoin(testnet=True) print('Testnet privkey options:') for wallet_privkey in wallet_privkeys: print(wallet_privkey) payor_privkey = input('Payor privkey?') recip_privkey = input('Recipient privkey?') if payor_privkey not in wallet_privkeys or recip_privkey not in wallet_privkeys: print('testnet privkeys invalid') raise ValueError('testnet privkeys invalid') satoshis = int(input('How many satoshis to send?')) recip_address = testnet.privtoaddr(recip_privkey) tx_dump = testnet.send(payor_privkey, recip_address, satoshis, fee=400000) try: if tx_dump['status'] == 'success': tx_data = tx_dump['data'] btc_txn_hash = tx_data['txid'] else: print('Testnet transaction failed') raise ValueError('Testnet transaction failed') except TypeError: raise ValueError('TypeError') new_transaction = Transaction(input_list, output_list, 'propTx', btc_txn_hash) print('Submitted transaction to Testnet. Hash:') print(btc_txn_hash) print('Transaction hash (own chain):') print(new_transaction.transaction_hash) # send transaction to registrar payload = new_transaction.to_dict() requests.post(registrar_txn_url, data=json.dumps(payload), headers=headers) print('Property transaction request sent to registrar: ' + property_addr)
def create_and_send_tx(client_socket: socket.socket, user): sender = utils.get_public_key(user) command = gui_metadata(TX_COMMAND) client_socket.send(command) inputs = [] N_inputs = int.from_bytes(client_socket.recv(4), 'little') for _ in range(N_inputs): input_data = client_socket.recv(159) inputs.append(utils.decode_input(input_data)) input_choices = [ { 'name': f'txID: {input.where_created} value: {input.value}', } for index, input in enumerate(inputs) ] recipient_choices = [ { 'name': 'Alice', }, { 'name': 'Bob', }, { 'name': 'Charlie', }, { 'name': 'No more pays', }, ] actions = [{ 'type': 'checkbox', 'name': INPUT_INDEX, 'message': 'Selecciona los inputs a ingresar en la transacción', 'choices': input_choices, }] recipient_actions = [{ 'type': 'list', 'name': 'recipient', 'message': 'Selecciona a la persona que le pagarás', 'choices': recipient_choices, }] value_actions = [{ 'type': 'input', 'name': 'value', 'message': '¿Cuánto le vas a pagar?', }] answers = prompt(actions) inputs_selected = answers.get(INPUT_INDEX) inputs_to_pay = [] for inputs_selected in inputs_selected: index = input_choices.index({'name': inputs_selected}) inputs_to_pay.append(inputs[index]) outputs = [] while True: answers = prompt(recipient_actions) answer = answers['recipient'] if answer == 'No more pays': break recipient = utils.get_public_key(answer) answers = prompt(value_actions) value = int(answers['value']) output = Output(value, recipient) outputs.append(output) unsigned = UnsignedTransaction(PAYCOINS_TYPE, inputs_to_pay, outputs) to_sign = unsigned.DataForSigs() signs = {} signs[sender.export_key(format='DER')] = sign(to_sign, utils.get_private_key(user)) transaction = Transaction(unsigned, signs) client_socket.send(transaction.serialize())
def serialize_output_json(o: Output) -> str: o.script_pub_key = o.script_pub_key return json.dumps(o.__dict__)
def decode_output(payload): value = int.from_bytes(payload[:4], 'little') recipient = ECC.import_key(payload[4:]) return Output(value, recipient)
def __init__(self, transactions, public_key, private_key, version, index=None, force_time=None): self.version = version if force_time: self.time = str(int(force_time)) else: self.time = str(int(time.time())) blocks = BU.get_blocks() self.index = index if self.index == 0: self.prev_hash = '' else: self.prev_hash = blocks[blocks.count()-1]['hash'] self.public_key = public_key self.private_key = private_key transaction_objs = [] fee_sum = 0.0 unspent_indexed = {} used_sigs = [] for txn in transactions: if isinstance(txn, Transaction): transaction_obj = txn else: transaction_obj = Transaction.from_dict(txn) if transaction_obj.transaction_signature in used_sigs: print 'duplicate transaction found and removed' continue used_sigs.append(transaction_obj.transaction_signature) transaction_obj.verify() #check double spend address = str(P2PKHBitcoinAddress.from_pubkey(transaction_obj.public_key.decode('hex'))) if address in unspent_indexed: unspent_ids = unspent_indexed[address] else: res = BU.get_wallet_unspent_transactions(address) unspent_ids = [x['id'] for x in res] unspent_indexed[address] = unspent_ids failed = False used_ids_in_this_txn = [] for x in transaction_obj.inputs: if x.id not in unspent_ids: failed = True if x.id in used_ids_in_this_txn: failed = True used_ids_in_this_txn.append(x.id) if not failed: transaction_objs.append(transaction_obj) fee_sum += float(transaction_obj.fee) block_reward = BU.get_block_reward() coinbase_txn_fctry = TransactionFactory( public_key=self.public_key, private_key=self.private_key, outputs=[Output( value=block_reward + float(fee_sum), to=str(P2PKHBitcoinAddress.from_pubkey(self.public_key.decode('hex'))) )], coinbase=True ) coinbase_txn = coinbase_txn_fctry.generate_transaction() transaction_objs.append(coinbase_txn) self.transactions = transaction_objs txn_hashes = self.get_transaction_hashes() self.set_merkle_root(txn_hashes) self.block = Block( version=self.version, block_time=self.time, block_index=self.index, prev_hash=self.prev_hash, transactions=self.transactions, merkle_root=self.merkle_root, public_key=self.public_key )
def __init__(self, config, mongo, transactions, public_key, private_key, version, index=None, force_time=None): self.config = config self.mongo = mongo self.version = BU.get_version_for_height(index) if force_time: self.time = str(int(force_time)) else: self.time = str(int(time.time())) blocks = BU.get_blocks(self.config, self.mongo) self.index = index if self.index == 0: self.prev_hash = '' else: self.prev_hash = BU.get_latest_block(self.config, self.mongo)['hash'] self.public_key = public_key self.private_key = private_key transaction_objs = [] fee_sum = 0.0 unspent_indexed = {} unspent_fastgraph_indexed = {} used_sigs = [] for txn in transactions: try: if isinstance(txn, Transaction): transaction_obj = txn else: transaction_obj = Transaction.from_dict( self.config, self.mongo, txn) if transaction_obj.transaction_signature in used_sigs: print 'duplicate transaction found and removed' continue used_sigs.append(transaction_obj.transaction_signature) transaction_obj.verify() if not isinstance(transaction_obj, FastGraph) and transaction_obj.rid: for input_id in transaction_obj.inputs: input_block = BU.get_transaction_by_id(self.config, self.mongo, input_id.id, give_block=True) if input_block['index'] > (BU.get_latest_block( self.config, self.mongo)['index'] - 2016): continue except: try: if isinstance(txn, FastGraph): transaction_obj = txn else: transaction_obj = FastGraph(**txn) if transaction_obj.transaction.transaction_signature in used_sigs: print 'duplicate transaction found and removed' continue used_sigs.append( transaction_obj.transaction.transaction_signature) if not transaction_obj.verify(): raise InvalidTransactionException( "invalid transactions") transaction_obj = transaction_obj.transaction except: raise InvalidTransactionException("invalid transactions") address = str( P2PKHBitcoinAddress.from_pubkey( transaction_obj.public_key.decode('hex'))) #check double spend if address in unspent_indexed: unspent_ids = unspent_indexed[address] else: res = BU.get_wallet_unspent_transactions( self.config, self.mongo, address) unspent_ids = [x['id'] for x in res] unspent_indexed[address] = unspent_ids if address in unspent_fastgraph_indexed: unspent_fastgraph_ids = unspent_fastgraph_indexed[address] else: res = BU.get_wallet_unspent_fastgraph_transactions( self.config, self.mongo, address) unspent_fastgraph_ids = [x['id'] for x in res] unspent_fastgraph_indexed[address] = unspent_fastgraph_ids failed = False used_ids_in_this_txn = [] for x in transaction_obj.inputs: if x.id not in unspent_ids: failed = True if x.id in used_ids_in_this_txn: failed = True used_ids_in_this_txn.append(x.id) if not failed: transaction_objs.append(transaction_obj) fee_sum += float(transaction_obj.fee) block_reward = BU.get_block_reward(self.config, self.mongo) coinbase_txn_fctry = TransactionFactory( config, mongo, public_key=self.public_key, private_key=self.private_key, outputs=[ Output(value=block_reward + float(fee_sum), to=str( P2PKHBitcoinAddress.from_pubkey( self.public_key.decode('hex')))) ], coinbase=True) coinbase_txn = coinbase_txn_fctry.generate_transaction() transaction_objs.append(coinbase_txn) self.transactions = transaction_objs txn_hashes = self.get_transaction_hashes() self.set_merkle_root(txn_hashes) self.block = Block(self.config, self.mongo, version=self.version, block_time=self.time, block_index=self.index, prev_hash=self.prev_hash, transactions=self.transactions, merkle_root=self.merkle_root, public_key=self.public_key)
def gui_handler(self, client_socket: socket.socket): self.send_verack_handler(client_socket) keep_open = True while keep_open: command_metadata = client_socket.recv(31) command = command_metadata[:12].decode('utf-8') if command == TX_COMMAND: payload = len(self.txs_handler.UTXO_pool).to_bytes(4, 'little') for input_inst in self.txs_handler.UTXO_pool.values(): payload += input_inst.serialize() client_socket.send(payload) tx = utils.receive_tx_data(client_socket) self.add_tx(tx) elif command == CREATE_BLOCK_COMMAND: # number_of_txs = len(self.outstanding_txs_pool).to_bytes(4, 'little') # client_socket.send(number_of_txs) # payload = b'' # for tx in self.outstanding_txs_pool: # tx_id, tx_value = tx.data['uniqueID'], tx.data['value'] # payload += tx_id.to_bytes(4, 'little') # payload += tx_value.to_bytes(4, 'little') # client_socket.send(payload) # command_metadata = client_socket.recv(31) # command = command_metadata[:12].decode('utf-8') # if command != BLOCK_COMMAND: # self.__update_events('Did not receive block command') # client_socket.close() # return # metadata_new_block = client_socket.recv(4) # number_of_txs_in_block = int.from_bytes(metadata_new_block, 'little') # txs = [] # for _ in range(number_of_txs_in_block): # tx_metadata = client_socket.recv(8) # tx_id = int.from_bytes(tx_metadata[:4], 'little') # tx_value = int.from_bytes(tx_metadata[4:], 'little') # txs.append((tx_id, tx_value)) # self.add_block(txs) self.generate_new_block() elif command == CREATE_CONNECTION: connection_metadata = client_socket.recv(19) connection = connection_metadata[:15].decode('utf-8').strip(), int.from_bytes(connection_metadata[15:], 'little') self.send_conexion_handler(connection) if connection in self.peers: self.send_getblocks_handler(connection) elif command == DEFAULT_DATA_COMMAND: addressA = load_pk('publickeyAlice.pem') addressB = load_pk('publickeyBob.pem') addressC = load_pk('publickeyCharlie.pem') scrooge = load_pk('publickeyScrooge.pem') transactions = [] # Create coin transaction inputs = [] outputs = [ Output(11, addressA), # Alice has 10 scrooge coins Output(10, addressB), # Alice has 10 scrooge coins ] unsigned = UnsignedTransaction(CREATECOINS_TYPE, inputs, outputs) to_sign = unsigned.DataForSigs() sigs = {} sigs[scrooge.export_key(format='DER')] = sign(to_sign, 'privatekeyScrooge.pem') transaction = Transaction(unsigned, sigs) self.add_tx(transaction) transactions.append(transaction) # Create block block = utils.create_block( transactions, self.blockchain.head_block_hash, ) time.sleep(1) self.add_block(block) continue transactions = [] # Pay coins transaction inputs = [ Input(transaction.txID, 10, addressA), Input(transaction.txID, 10, addressB), # Both spend their 10 scrooge coins ] outputs = [ Output(5, addressA), # Alice has 5 scrooge coins Output(15, addressB), # Bob has 15 scrooge coins ] unsigned = UnsignedTransaction(PAYCOINS_TYPE, inputs, outputs) to_sign = unsigned.DataForSigs() sigs = {} sigs[addressA.export_key(format='DER')] = sign(to_sign, 'privatekeyAlice.pem') sigs[addressB.export_key(format='DER')] = sign(to_sign, 'privatekeyBob.pem') transaction = Transaction(unsigned, sigs) self.add_tx(transaction) transactions.append(transaction) # Create block block = utils.create_block( transactions, self.blockchain.head_block_hash, ) self.add_block(block) elif command == GUICLOSE_COMMAND: keep_open = False client_socket.close()