def premine(self): random.seed(time()) privkey = [get_new_private_key() for i in range(3)] publkey = [get_public_key(privkey[i]) for i in range(3)] addr = [get_public_address(privkey[i]) for i in range(3)] for i in range(len(privkey)): item = privkey[i] with open('premine' + str(i), 'w+') as f: f.write(convert_to_wif(item)) for i in range(len(addr)): bl = self.create_gen_block('premine' + str(i)) if bl: if len(self.blocks) > 0: bl.previous_hash = self.blocks[len(self.blocks) - 1].hash bl.heigth = len(self.blocks) bl.previous_hash = self.last_hash bl.target = self.target self.mine(bl) self.blocks.append(bl) self.last_hash = bl.hash utxo = [] for i in self.blocks: trans = Deserializer.deserialize_raw(i.transactions[0]) utxo_add(utxo, trans) for x in range(3): for ind in range(len(addr)): for jnd in range(len(addr)): i = addr[ind] j = addr[jnd] if i != j: amount = random.randint(6, 15) if not self.muted: print (i, j, amount) inputs = utxo_select_inputs(utxo_get(utxo, i), 5, amount) outputs = utxo_create_outputs(i, j, amount, 5, inputs) if len(inputs) == 0: continue tr = Transaction(i, j, amount, {'inp': inputs, 'oup': outputs, 'locktime':0, 'version': 1}) tr_serial = Serializer.serialize_raw(tr, privkey[ind], publkey[ind]) tr_des = Deserializer.deserialize_raw(tr_serial.hex()) utxo_add(utxo, tr_des) bl = Block(time(), 0, self.last_hash, [tr_serial.hex()]) bl.target = self.target self.mine(bl) bl.heigth = len(self.blocks) self.blocks.append(bl) self.last_hash = bl.hash #deleting premine files '''
def update_unspend_pool(self): if self.key_pair == 0: raise Exception("Haven`t key pair") rq = requests.post(self.server_ip + '/utxo/get_uout', data=self.key_pair.get_address()) utxo = json.loads(rq.text) self.unspend_pool =[(tx, vout, Deserializer.deserialize_output(o)[0]) for tx, vout, o in utxo] self.unspend_pool.sort(key=lambda outp: outp[-1].value)
def assept(ser): trx = Deserializer(ser).trx if validate(trx): add_to_mem(ser) return True else: return False
def get_chain(): h = request.args.get('len') try: if (int(h) <= 0) or int(h) > len(data['blocks']): h = len(data['blocks']) except ValueError: h = len(data['blocks']) h = int(h) for bl in data['blocks'][-h:]: raw_txes_bl = [] for i in range(len(bl["transactions"])): x = Deserializer.deserialize_raw(bl["transactions"][i]) jst = {} jst['version'] = x.version jst['inp'] = x.inputs jst['oup'] = x.outputs jst['locktime'] = x.timelock jst['tr_hash'] = x.tr_hash.hex() raw_txes_bl.append(jst) bl['jsoni'] = raw_txes_bl bl['ti'] = strftime("%a, %d %b %Y %H:%M:%S", gmtime(bl['timestamp'])) return render_template('blockchain.html', title='Blockchain', data=data['blocks'][-h:]), 201
def get_address_info(): a = request.args.get('addr') if (len(a) == 0): return jsonify({'error': 'Empty field'}), 404 result = [] for bl in data['blocks']: for tr in bl['transactions']: x = Deserializer.deserialize_raw(tr) for elem in x.outputs: if elem['address'] == a: jst = {} jst['timer'] = strftime("%a, %d %b %Y %H:%M:%S", gmtime(bl['timestamp'])) jst['version'] = x.version jst['inp'] = [] for i in x.inputs: s = utxo_get_trans_output(data['blocks'], i['tx_prev_hash'], i['tx_prev_index']) jst['inp'].append(s if s else {'address': 'Coinbase'}) jst['oup'] = x.outputs for i in range(len(jst['oup'])): jst['oup'][i]['spent'] = utxo_spent( data['utxo'], x.tr_hash.hex(), i) jst['locktime'] = x.timelock jst['tr_hash'] = x.tr_hash.hex() result.append(jst) if len(result) == 0: return jsonify({'error': 'Address is invalid'}), 404 return render_template('address.html', title='Address Info', data=result), 201
def mine_block(self): txs = pending_pool.get_last_tx() for tx in txs: try: dec_tx = Deserializer.deserialize(tx) prev_outputs = [] for i in dec_tx.inputs: txid, vout, out = self.utxop.find_out(txid=i.txid, vout=i.vout) prev_outputs.append((txid, vout, out)) if not check_tx(dec_tx, prev_outputs): print("Non_valid input") raise Exception("Non valid input") except Exception as e: txs.remove(tx) print(f'Error: invalid tx {dec_tx.txid()[::-1].hex()}[{e}]') fee = 25 txs.insert(0, self.coinbase_tx(fee)) timestamp = time_ns() previus_block_hash = self.chain[-1].get_hash().hex() new_block = Block(timestamp=timestamp, previous_hash=previus_block_hash, transactions=txs) new_block.height = self.chain[-1].height + 1 new_block = self.find_nonce(new_block) return new_block
def blockHashCalc(self, genesis): if self.txValidator(self.transactions): root = merkle_root(self.transactions) # print('self.timestamp = ', type(self.timestamp), '\nself.nonce = ', self.nonce, # '\nself.previous_hash = ', type(self.previous_hash), '\nroot = ', type(root)) __preHash = str(self.timestamp) + str(self.nonce) + str(self.previous_hash) + str(root) # print('__prehash = ', __preHash) blockHash = hashlib.sha256(hashlib.sha256(__preHash.encode()).digest()).hexdigest() self.blockhash = blockHash self.block_root = root return blockHash, root elif genesis == 1: tx = Deserializer.deserialize(Deserializer, self.transactions[0]) tx.sender = '00000000000000000000000000000000' # print('txHash = ', tx.txHashCalc().encode('utf-8'), '\ntxpubkey = ', tx.pubkey, '\nsignature = ', tx.signature) if (Validator.addrVal(Validator, tx.recipient)) and Validator.signatureVal(Validator, tx.txHashCalc().encode('utf-8'), tx.pubkey, tx.signature): root = merkle_root(self.transactions) # print('root = ', root) __preHash = str(self.timestamp) + str(self.nonce) + str(self.previous_hash) + str(root) # print('pre hash = ', __preHash.encode()) blockHash = hashlib.sha256(hashlib.sha256(__preHash.encode()).digest()).hexdigest() # print('blockHash = ', blockHash) self.blockhash = blockHash self.block_root = root return blockHash, root else: return False else: print('one or more transactions are compromised') return False
def get_block(): h = request.args.get('block_height') if not h: if not request.is_json: return jsonify({'error': 'no height parameter passed'}), 202 else: h = request.get_json()['index'] try: if (int(h) <= 0): raise ValueError if int(h) > len(data['blocks']): return jsonify({'error': 'height exceeds blockchain length'}), 202 except ValueError: return jsonify( {'error': 'height parameter must be a positive integer'}), 202 raw_txes = [] for i in range(len(data['blocks'][int(h) - 1]["transactions"])): x = Deserializer.deserialize_raw(data['blocks'][int(h) - 1]["transactions"][i]) jst = {} jst['version'] = x.version jst['inp'] = x.inputs jst['oup'] = x.outputs jst['locktime'] = x.timelock jst['tr_hash'] = x.tr_hash.hex() raw_txes.append(jst) ti = strftime("%a, %d %b %Y %H:%M:%S", gmtime(data['blocks'][int(h) - 1]['timestamp'])) return render_template('block_index.html', title='Block', data=[data['blocks'][int(h) - 1], raw_txes, ti]), 201
def pending_pool(tx, serialized_line, vk, primeval_hash): deserializer = Deserializer() amount, sender_address, recipient_address, \ sender_public_key, signed_hash = deserializer.get_all(tx.get__serialize_line()) check = check_availiability_address(sender_address) if check is True: check = check_availiability_address(recipient_address) if check is True: check = check_ratio_public_and_address(sender_public_key, sender_address.encode("utf-8"), False) if check is True: check = check_validity_signature(signed_hash, primeval_hash, vk) if check is False: return False # save_results_to_file(serialized_line) return serialized_line
def tx_new(): serialized_tx = request.data.decode()[1:-1] deserial = Deserializer().deserialize(serialized_tx) if Serializer().serialize(deserial) != serialized_tx: print("Cant append invalid transactoiin to pending pool") pending_pool.get_tx(serialized_tx) print("Serialized transaction: " + str(serialized_tx) + " was added to the pending pool.") return ""
def tx_pending(): pending = [] try: with open("mempool.dat", "r") as f: lines = f.read().splitlines() for st in lines: pending.append(Deserializer().deserialize(st).toJSON()) except: return "There are no transactions in mempool" return jsonify(pending)
def utxo_get_trans_output(utxo, tx_id, tx_index): for bl in utxo: for x in bl['transactions']: elem = Deserializer.deserialize_raw(x) if elem.tr_hash.hex() == tx_id: item = elem.outputs return { 'address': item[tx_index]['address'], 'value': item[tx_index]['value'] }
def utxo_init(data): data['utxo'] = [] blocks = data['blocks'] for block in blocks: print(block['hash']) for trans in block['transactions']: x = Deserializer.deserialize_raw(trans) utxo_add(data['utxo'], x) # x.display_raw() '''
def validate_transactions(self): if self.transactions: for transaction in self.transactions: deserialized = Deserializer.deserialize(transaction) tsx = Transaction(deserialized['sender_addr'], deserialized['recepient_addr'], deserialized['num_of_coins']) tsx_hash = tsx.transaction_hash() transaction_validation(transaction, tsx_hash)
def add_transaction_to_pool(self, serialized_transaction): deserialized = Deserializer.deserialize(serialized_transaction) transaction = Transaction(deserialized['sender_addr'], deserialized['recepient_addr'], deserialized['num_of_coins']) transaction_hash = transaction.transaction_hash() is_valid = transaction_validation(deserialized, transaction_hash) if not is_valid: return is_valid self.transaction_pool.append(serialized_transaction) return True
def is_valid_chain(self, blocks): p_hash = '0' * 64 for block in blocks: if block['previous_hash'] != p_hash: return False p_hash = block['hash_rez'] transactions = block['transactions'] for trx in transactions: trx = Deserializer(trx).trx if validate(trx) == False: return False return True
def testing_forming(): privkey = wallet.gen_privkey() wif = wallet.privkey_to_wif(privkey) sender = wallet.gen_address(wallet.get_pubkey_str(privkey)) recipient = wallet.gen_address(wallet.get_pubkey_str(wallet.gen_privkey())) utxo_obj = Utxos() g_miner_reward = 50 coinbase_tx = form_coinbase(recipient, wif, g_miner_reward) print(coinbase_tx.toJSON()) serial_coinbase = Serializer().serialize(coinbase_tx) deserial_coinbase = Deserializer().deserialize(serial_coinbase)
def do_history(self, addr): print("\033[0;37;40m") "Display history of all transactions made by passed address." my_scriptPubKey = script.get_scriptPubKey(addr) for i in range(self.chain.height()): b = block_from_JSON(i) for tx in b.txs: tx_d = Deserializer().deserialize(tx) for o in tx_d.outputs: if o.scriptPubKey == my_scriptPubKey: print( f'\033[1;32;40mTransaction:\033[0;37;40m {tx_d.toJSON()}' )
def txValidator(self, transactions): for stx in transactions: tx = Deserializer.deserialize(Deserializer, stx) if stx[4:40] == '0' * 36 and not Validator.addrVal(Validator, tx.recipient): return True elif not Validator.addrVal(Validator, tx.sender) or not Validator.addrVal(Validator, tx.recipient) or not Validator.senderAddrVal(Validator, tx.pubkey, tx.sender): break elif not Validator.signatureVal(Validator, tx.txHashCalc().encode('utf-8'), tx.pubkey, tx.signature): break else: return True return False
def validate(self, prev_blocks, utxo): if (len(prev_blocks) > 0): ts_avg = 0 for i in prev_blocks: ts_avg += i.timestamp ts_avg = ts_avg / len(prev_blocks) if (self.timestamp < ts_avg): print ('Invalid timestamp') return False for item in self.transactions: x = Deserializer.deserialize_raw(item) if not validate_raw(utxo, x): return False return True
def chain_balance(self, addr): bal = 0 senders = [] recipients = [] for block in self.blocks: for trans in block.transactions: x = Deserializer.deserialize(trans) if x.sender == addr: senders.append(x.amount) if x.recipient == addr: recipients.append(x.amount) for i in recipients: bal += i for i in senders: bal -= i return bal
def update_pool(self, txs): for serial_tx in txs: tx = Deserializer().deserialize(serial_tx) for j in range(tx.inp_counter): query_hash = Query() res_q = self.utxo_db.search(query_hash.hash == '{:8x}'.format(tx.inputs[j].vout) + tx.inputs[j].txid) if res_q: self.utxo_db.remove(query_hash.hash == '{:8x}'.format(tx.inputs[j].vout) + tx.inputs[j].txid) for i in range(tx.outp_counter): hash = sha256( sha256( bytes(Serializer().serialize(tx), "utf-8" ) ).digest() ).hexdigest() self.utxo_db.insert({'hash': '{:8x}'.format(i) + hash,\ 'output': tx.outputs[i].toJSON()}) db_len = len(self.utxo_db) db_list = self.utxo_db.all() for i in range(0, db_len): outp_json = db_list[i] self.pool[ outp_json['hash'] ] = output_json_decoder(outp_json['output'])
def get_mempool(): a = request.args.get('id') print(a) for bl in data['blocks']: for tr in bl['transactions']: x = Deserializer.deserialize_raw(tr) if (x.tr_hash.hex() == a): jst = {} jst['version'] = x.version jst['inp'] = x.inputs jst['oup'] = x.outputs for i in range(len(jst['oup'])): jst['oup'][i]['spent'] = utxo_spent(data['utxo'], a, i) jst['locktime'] = x.timelock jst['tr_hash'] = x.tr_hash.hex() return render_template('transaction.html', title='Transaction', data=[bl, jst, a]), 201 return jsonify({'error': 'Transaction ID is invalid'}), 404
def InitNewBlock(prev_hash, comp=2): block = Block(prev_hash) dec_txs = [] try: with open("address", 'r') as add: coinbase = tx.CoinBaseTransaction(add.readline()) # new_tx. coinbase.CalcHash() except IOError: print("Could not read 'address' file") return (0) dec_txs.append(coinbase) fresh_txs = pool.GetThreeTxFromFile("last") if (fresh_txs == None): return (None) for element in fresh_txs: dec_txs.append(deser.deserialize(element)) block.txs = dec_txs block.GetMerkleRoot() block.MineBlock(comp) return (block)
def update_pool(self, block: Block): for tx in block.transactions: tx_obj = Deserializer.deserialize(tx) txid = tx_obj.txid().hex() for tx_in in tx_obj.inputs: if tx_in.txid.hex() == 64 * '0': pass elif (tx_in.txid.hex() in self.pool) and (tx_in.vout in self.pool[tx_in.txid.hex()]): del self.pool[tx_in.txid.hex()][tx_in.vout] if len(self.pool[tx_in.txid.hex()]) == 0: del self.pool[tx_in.txid.hex()] else: pass # raise Exception("non valid input") i = 0 for tx_out in tx_obj.outputs: if txid in self.pool: self.pool[txid][i] = tx_out else: self.pool[txid] = {i: tx_out} i += 1
def get_tx(tx_str): Deserializer().deserialize(tx_str) save_to_mempool(tx_str) return get_last3()
def run(): print("====================================================") print("| TEST 1 |") print("|init new private key, make public key and address |") print("====================================================") wallet = wc.Wallet() wallet.do_new("") print("====================================================") print("| TEST 2 |") print("| save information to files address and minerkey |") print("====================================================") wallet.do_save("") f = open('address', 'r') print("file 'address': ", f.readline()) f = open('minerkey', 'r') print("file 'minerkey': ", f.readline()) print("====================================================") print("| TEST 3 |") print("| import minerkey to wallet |") print("====================================================") wallet.do_import("minerkey") print("====================================================") print("| TEST 4 |") print("| check balance (must be 0!) |") print("====================================================") wallet.do_balance("") print("====================================================") print("| TEST 5 |") print("| lets mine some coins! |") print("====================================================") miner = mc.Miner() print("\n hash of mined block is:\n") miner.do_mine("") print("\n and block loocks like this:\n") blocks = requests.get(URL + '/chain') blocks = json.loads(blocks.text)['blocks'] print(blocks[-1]) print("\n and your transaction:\n") trx = Deserializer(blocks[-1]["transactions"][0]).trx print(trx, "\n\n Congratulations!!! Your balance in satoshies is:\n") print(trx['outputs'][0]['value']) print("====================================================") print("| TEST 6 |") print("| check balance againe! |") print("====================================================") print("\nYour current ballance from UTXO (in satoshies) is:\n") wallet.do_balance("") print("====================================================") print("| TEST 7 |") print("|Now it's time to send some pitcoins to your friend|") print("====================================================") print( "Form transaction to adress, for example: \n1Bh7Pn4kBGkNza9oBEHa4t3LiDan8REUzQ" ) print("let's send 10000 satoshies. First form transaction. Serialized tx:") wallet.do_send("1Bh7Pn4kBGkNza9oBEHa4t3LiDan8REUzQ 10000") print("Deserialized tx:") print( Deserializer(binascii.hexlify(wallet.tr.real_tx).decode('utf-8')).trx) print("then, let's broadcast it...") wallet.do_broadcast(binascii.hexlify(wallet.tr.real_tx).decode('utf-8')) print("and check mempool...") print(show_mem()) print("====================================================") print("| TEST 8 |") print("| Next, mine block with your transaction |") print("====================================================") print("mined block hash is:") miner.do_mine("") print("mempool (empty, really??):") print(show_mem()) print("Your ballance is:") wallet.do_balance("") print("And balance 1Bh7Pn4kBGkNza9oBEHa4t3LiDan8REUzQ is:") wallet.do_balance("1Bh7Pn4kBGkNza9oBEHa4t3LiDan8REUzQ") print("full UTXO you can see in browser: http://127.0.0.1:5000/utxo")
def add_trans(plain): x = Deserializer.deserialize(plain) save_to_mem(plain) if verification(x) else print( 'Error, serialization of transaction failed')
def tx_validator(self): for t in self.txs: Deserializer().deserialize(t) return True
def add_tx(s): t = Deserializer.deserialize(s) tx_valiadtor.check_tx(t) with open((os.path.abspath(".") + "/mempool"), 'a+') as f: f.write(f"{s}\n") f.close()