def create_transaction(self, to, amount, fee, prev_hash): self.check_peers() transaction = Transaction(self.get_public_key(), to, amount, fee, prev_hash=prev_hash) transaction.sign(self.get_private_key()) return self.api_client.broadcast_transaction(transaction)
def get_transaction_by_hash(self, transaction_hash, branch=0): sql = "SELECT * FROM transactions WHERE hash='{}' AND branch={}".format(transaction_hash, branch) with sqlite3.connect(self.CHAIN_DB) as conn: cursor = conn.cursor() cursor.execute(sql) transaction = cursor.fetchone() return Transaction(transaction[1], transaction[2], transaction[3], transaction[4], tx_type=transaction[7], timestamp=transaction[5], tx_hash=transaction[0], signature=transaction[6], asset=transaction[8], data=transaction[9])
def get_transactions_by_block_hash(self, block_hash): transactions = [] sql = "SELECT * FROM transactions WHERE blockHash='{}' ORDER BY hash ASC".format(block_hash) with sqlite3.connect(self.CHAIN_DB) as conn: cursor = conn.cursor() cursor.execute(sql) for transaction in cursor: transactions.append(Transaction(transaction[1], transaction[2], transaction[3], transaction[4], tx_type=transaction[7], timestamp=transaction[5], tx_hash=transaction[0], signature=transaction[6], asset=transaction[9], data=transaction[10], prev_hash=transaction[12])) return transactions
def get_all_unconfirmed_transactions_iter(self): sql = 'SELECT * FROM unconfirmed_transactions' with sqlite3.connect(self.POOL_DB) as conn: cursor = conn.cursor() cursor.execute(sql) for transaction in cursor: yield Transaction(transaction[1], transaction[2], transaction[3], transaction[4], transaction[10], transaction[7], transaction[5], transaction[0], transaction[8], transaction[9], transaction[6])
def get_transaction_history(self, address, branch=0): # TODO: convert this to return a generator transactions = [] sql = "SELECT * FROM transactions WHERE (src='{}' OR dest='{}') AND branch={}".format(address, address, branch) with sqlite3.connect(self.CHAIN_DB) as conn: cursor = conn.cursor() cursor.execute(sql) for transaction in cursor: transactions.append(Transaction(transaction[1], transaction[2], transaction[3], transaction[4], tx_type=transaction[7], timestamp=transaction[5], tx_hash=transaction[0], signature=transaction[6], asset=transaction[9], data=transaction[10], prev_hash=transaction[12])) return transactions
def get_unconfirmed_transaction(self, tx_hash): sql = "SELECT * FROM unconfirmed_transactions WHERE hash='{}'".format( tx_hash) with sqlite3.connect(self.POOL_DB) as conn: cursor = conn.cursor() cursor.execute(sql) data = cursor.fetchone() if data is None: return None transaction = data[0] return Transaction(transaction[1], transaction[2], transaction[3], transaction[4], transaction[10], transaction[7], transaction[5], transaction[0], transaction[8], transaction[9], transaction[6])
def get_unconfirmed_transactions_chunk(self, chunk_size=None): sql = 'SELECT * FROM unconfirmed_transactions ORDER BY fee DESC LIMIT {}'.format( chunk_size) transactions = [] with sqlite3.connect(self.POOL_DB) as conn: cursor = conn.cursor() cursor.execute(sql) for transaction in cursor: transactions.append( Transaction(transaction[1], transaction[2], transaction[3], transaction[4], transaction[10], transaction[7], transaction[5], transaction[0], transaction[8], transaction[9], transaction[6])) return transactions
def mine_block(self): latest_block = self.blockchain.get_tallest_block_header() if latest_block is not None: latest_block_header = latest_block[0] latest_block_height = latest_block[2] new_block_height = latest_block_height + 1 previous_hash = latest_block_header.hash else: new_block_height = 1 previous_hash = "" transactions = self.mempool.get_unconfirmed_transactions_chunk( self.MAX_TRANSACTIONS_PER_BLOCK) if transactions is None or len(transactions) == 0: fees = 0 else: fees = sum(t.fee for t in transactions) coinbase_prev_hash = "0" if new_block_height == 1 \ else self.blockchain.get_coinbase_hash_by_block_hash(previous_hash) # coinbase coinbase = Transaction("0", self.REWARD_ADDRESS, self.blockchain.get_reward(new_block_height) + fees, 0, prev_hash=coinbase_prev_hash, tx_type=TransactionType.COINBASE.value, signature="") transactions.insert(0, coinbase) timestamp = int(time.time()) i = 0 block = Block(new_block_height, transactions, previous_hash, timestamp) while block.block_header.hash_difficulty < self.blockchain.calculate_hash_difficulty( ): latest_block = self.blockchain.get_tallest_block_header() if latest_block is not None: latest_block_header = latest_block[0] latest_block_height = latest_block[2] if latest_block_height >= new_block_height or latest_block_header.hash != previous_hash: # Next block in sequence was mined by another node. Stop mining current block. return None i += 1 block.block_header.nonce = i return block
def post_transactions(): mempool = Mempool() validator = Validator() body = request.json transaction = Transaction.from_dict(body['transaction']) if transaction.tx_hash != body['transaction']['tx_hash']: logger.info("Invalid transaction hash: {} should be {}".format( body['transaction']['tx_hash'], transaction.tx_hash)) response.status = 406 return json.dumps({'message': 'Invalid transaction hash'}) if mempool.get_unconfirmed_transaction(transaction.tx_hash) is None \ and validator.validate_transaction(transaction) \ and mempool.push_unconfirmed_transaction(transaction): response.status = 200 return json.dumps({'success': True, 'tx_hash': transaction.tx_hash}) response.status = 406 return json.dumps({'success': False, 'reason': 'Invalid transaction'})