def proof_of_work(self, mysql): #Start by verifying all the transactions in the pool verified_transactions = [] cur = mysql.connection.cursor() result = cur.execute("SELECT * FROM blockchain_transactions") transactions = cur.fetchall() #We are going to verify all the transactions in the pool before we add them to the block ..... #then clear the transaction pool by deleting all the transactions in the database .... if result > 0: for transaction in transactions: id = transaction['id'] data = json.loads(transaction['transaction']) signature_string = transaction['signature'] string_transaction = json.dumps(data, sort_keys = True).encode() signature = eval(signature_string) public, key2 = keys.get_public_keys_from_sig(signature, string_transaction, curve=curve.secp256k1, hashfunc=ecdsa.sha256) is_valid = ecdsa.verify(signature, string_transaction, public, curve.secp256k1, ecdsa.sha256) if is_valid is True: verified_transactions.append(data) cur.execute("DELETE from blockchain_transactions WHERE id=%s", [id]) mysql.connection.commit() #Now we add the transactions to the new block the_time = datetime.now() prev_hash = ''
def is_valid(self): if self.signature is None: return True if len(self.signature) == 0 and self.to_address is None: return False hash_tx = self.calculate_hash() pubkey = keys.get_public_keys_from_sig(self.signature, hash_tx, curve=curve.P256, hashfunc=sha256) valid = ecdsa.verify(self.signature, hash_tx, pubkey[0], hashfunc=sha256) return valid
def test(): data = { "fullNames": 'Bertha Matshidiso Kgokong', "practiceNumber": '1234567890', "notes": 'I believe, we will make it to the moon and we will do it in this century' } private, public = import_key('/home/zatosh/keys/secp256k1.key') transaction = account.create_transaction(data) string_transaction = json.dumps(transaction, sort_keys=True).encode() signature = ecdsa.sign(string_transaction, private, curve=curve.secp256k1, hashfunc=ecdsa.sha256) ##----------------------------------------- #Assume we are now - publishing the transaction transaction['signature'] = json.dumps(signature) to_send = json.dumps(transaction, sort_keys=True) #Now Let us See of This code will work . . . . trans_result = to_send transaction1 = json.loads(trans_result) #Add the Transaction to the pool string_signature1 = transaction1['signature'] signature1 = eval(string_signature1) transaction1.pop('signature') string_transaction1 = json.dumps(transaction1, sort_keys=True).encode() key1, key2 = keys.get_public_keys_from_sig(signature1, string_transaction1, curve=curve.secp256k1, hashfunc=ecdsa.sha256) is_valid = ecdsa.verify(signature1, string_transaction1, key1, curve.secp256k1, ecdsa.sha256) print( 'Just received transaction broadcast {}: and added it to transaction pool' .format(transaction1)) return "<h3>If this is true, the signatures did match - or else. ---> {}</h3>".format( is_valid)
def extract_secp256r1_public_keys(r, s, message): """Extract the public keys from r, s, message which generated by secp256r1 :param str r: The r part of signature :param str s: The s part of signature :param str message: The message for signature :rtype: list :return: The public keys """ public_key_point = keys.get_public_keys_from_sig((int(r, 16), int(s, 16)), message, curve.P256, hashfunc=keccak_256) public_key_list = [] for i in public_key_point: x = str(hex(i.x)[2:]) y = str(hex(i.y)[2:]) if len(x) < 64: x = '0' * (64 - len(x)) + x if len(y) < 64: y = '0' * (64 - len(y)) + y public_key = '0x' + x + y public_key_list.append(public_key) return public_key_list
def awaiting_transaction_broadcast(): while True: trans_result = transaction_subscriber.recv_json() transaction = json.loads(trans_result) if 'signature' in transaction: #Add the Transaction to the pool string_signature = transaction['signature'] signature = eval(string_signature) transaction.pop('signature') string_transaction = json.dumps(transaction, sort_keys=True).encode() key1, key2 = keys.get_public_keys_from_sig(signature, string_transaction, curve=curve.secp256k1, hashfunc=ecdsa.sha256) blockchain.add_transaction(key1, transaction, signature, transaction['transaction_id'], mysql) print( 'Just received transaction broadcast {}: and added it to transaction pool' .format(transaction))
def awaiting_chain_broadcast(): while True: chain_result = chain_subscriber.recv_json() new_chain = json.loads(chain_result) print('We just received a new chain \n {}'.format(new_chain)) if not 'signature' in new_chain: #Get our chain from the database cur = mysql.connection.cursor() result = cur.execute("SELECT * FROM blockchain_chain") chain = cur.fetchall() if chain == []: #The chain table is empty ..... save this chain to our database for new_block in new_chain: block = new_block['block'] nonce = new_block['nonce'] hash = new_block['hash'] prev_hash = new_block['prev_hash'] timestamp = new_block['timestamp'] data = new_block['data'] cur.execute( "INSERT INTO blockchain_chain(block, nonce, hash, prev_hash, timestamp, data) VALUES(%s, %s, %s, %s, %s, %s)", (block, nonce, hash, prev_hash, timestamp, data)) mysql.connection.commit() cur.close() pass else: cur.close() if len(new_chain) > len(chain): #We already have a chain table in our database saved - we just need to confirm chain is valid if blockchain.is_chain_valid(new_chain, mysql): #The received chain is valid - genesis blocks match and all block hashes and nonces also match new_transactions = new_chain[len(new_chain) - 1]['data'] verified_transactions = [] for transaction in new_transactions: id = transaction['id'] data = json.loads(transaction['transaction']) signature_string = transaction['signature'] string_transaction = json.dumps( data, sort_keys=True).encode() signature = eval(signature_string) public, key2 = keys.get_public_keys_from_sig( signature, string_transaction, curve=curve.secp256k1, hashfunc=ecdsa.sha256) is_transaction_valid = ecdsa.verify( signature, string_transaction, public, curve.secp256k1, ecdsa.sha256) if is_transaction_valid: verified_transactions.append(data) print('Valid Transaction -> {}'.format(data)) else: print( 'The following transaction is not valid, cannot accept this new chain: {}' .format(transaction)) pass #Replace our chain with new chain - if chain is valid and all transactions in the last block are also valid cur = mysql.connection.cursor() #Start by deleting the current chain from database cur.execute("DELETE from blockchain_chain") mysql.connection.commit() #We also need to delete everything from the transaction table - because the transactions have been mined in this block. cur.execute("DELETE from blockchain_transactions") mysql.connection.commit() #then save new blockchain in to our database for new_block in new_chain: block = new_block['block'] nonce = new_block['nonce'] hash = new_block['hash'] prev_hash = new_block['prev_hash'] timestamp = new_block['timestamp'] data = new_block['data'] cur.execute( "INSERT INTO blockchain_chain(block, nonce, hash, prev_hash, timestamp, data) VALUES(%s, %s, %s, %s, %s, %s)", (block, nonce, hash, prev_hash, timestamp, data)) mysql.connection.commit() cur.close() else: #Received chain is not valid print('Received chain is not valid --> DISCARD') pass else: print( 'Received chain is shorter than or equal to the chain we already have -- > DISCARD' ) pass else: #This is a transaction - transaction function will handle . . . . pass