def decode_tx_output(dictionary): return TransactionOutput( transaction_output_id=dictionary['transaction_output_id'], amount=dictionary['amount'], locking_script=dictionary['locking_script'], sender_address=dictionary['sender_address'], recipient_address=dictionary['recipient_address'])
def _create_transaction_to_miner(cls): transaction_inputs = list(map( lambda tx_o: tx_o.to_input(''), TransactionOutput.list_unspent(COINBASE_ADDRESS) )) transaction_input_amounts = list(map(lambda tx_i: tx_i.transaction_output.amount, transaction_inputs)) if len(transaction_inputs) == 0: transaction_input_amount_sum = Decimal(0) else: transaction_input_amount_sum = Decimal(reduce((lambda x, y: x + y), transaction_input_amounts)) transaction = Transaction.build( block_id = None, locktime = 0, timestamp = datetime.now().timestamp() ) transaction_output_to_miner = TransactionOutput.build( transaction_id = transaction.transaction_id, amount = transaction_input_amount_sum * Decimal(0.99), sender_address = COINBASE_ADDRESS, recipient_address = cls.MINER_ADDRESS, timestamp = datetime.now().timestamp() ) transaction_output_to_coinbase = TransactionOutput.build( transaction_id = transaction.transaction_id, amount = transaction_input_amount_sum * Decimal(0.99), sender_address = COINBASE_ADDRESS, recipient_address = COINBASE_ADDRESS, timestamp = datetime.now().timestamp() ) transaction.transaction_inputs = transaction_inputs transaction.transaction_outputs = [transaction_output_to_miner, transaction_output_to_coinbase] UnconfirmedTransactionPool.transactions.append(transaction) return transaction
def seed(cls): timestamp = 0 block = Block.build(block_number=1, version='1', previous_block_hash='1', timestamp=1, merkle_root='', difficulty_target=10, nonce=1) transaction = Transaction.build(block_id='1', locktime=0, timestamp=timestamp) transaction_output = TransactionOutput.build( transaction_id='1', amount=10000000000000000000, sender_address='coinbase', recipient_address= '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAznjoHvzCJtQcIYd3yj7v\ngwaPlyiG6U/Qlw1G89n0bNt5anvRe+e2eKzvpy98aj6ShGu7hARE9SxAFA9bIHCB\nqdAyPnrUaw7qGkeZNPHBByHe9prJSn0ZwBtfySOSbzdetO5aAwvLj5qMudW2PDz1\n5mP2taGOvXqNnbcH78ZHQLvF6G+SbwuLHU5LEDSZlcy+CnvPqD67cg+QmJLneVmQ\nfOBtbFHz3yDQghNrHWa+UCspUMHVGsDG6OEK7MSpPieY6TzBEYQWsikosQ+V0zBN\nrSCADe3GBcJ7XzafM/gb+gzJ1eP78F1sA6Ja4ZtqInqN406PwerAXaUJa2twW652\n9wIDAQAB\n-----END PUBLIC KEY-----', timestamp=timestamp) db.session.add(block) db.session.add(transaction) db.session.add(transaction_output) db.session.commit()
return list( map( lambda tx_o: { 'transaction_output_id': tx_o.transaction_output_id, 'unlocking_script': sign(SECRET_KEY_STR, tx_o.transaction_output_id) }, tx_outputs)) if __name__ == '__main__': if sys.argv is not None and sys.argv[1] is not None: amount = int(sys.argv[1]) recipient_address = sys.argv[2] utxo = fetch_utxo() target_utxo = TransactionOutput.fetch_tx_outputs_over_amount( amount, utxo) tx_input_requests = create_tx_input_requests(target_utxo) request = { 'sender_address': PUBLIC_KEY_STR, 'recipient_address': recipient_address, 'amount': amount, 'timestamp': datetime.now().timestamp(), 'tx_input_requests': tx_input_requests } res = requests.post(URL + 'transactions', data=json.dumps(request), headers=HEADERS) print(res)
def create_transaction(cls, request): transaction_input_dicts = request['transaction_inputs'] sender_address = request['sender_address'] recipient_address = request['recipient_address'] request_amount = request['amount'] timestamp = request['timestamp'] unspent_transaction_outputs = list( filter( lambda tx_output: tx_output['tx_o'] is not None, list( map( lambda tx_input: { 'tx_o': TransactionOutput.find_unspent(tx_input[ 'transaction_output_id']), 'unlocking_script': tx_input['unlocking_script'] }, transaction_input_dicts)))) transaction_inputs = list( map( lambda tx_output: tx_output['tx_o'].to_input(tx_output[ 'unlocking_script']), unspent_transaction_outputs)) verify_results = list( map(lambda input: input.verify(sender_address), transaction_inputs)) if False in verify_results: raise Exception('error.cant_verify_input') if len(transaction_inputs) == 0: raise Exception('error.not_enough_input_amount') transaction_input_amounts = list( map(lambda input: input.transaction_output.amount, transaction_inputs)) transaction_input_amount_sum = reduce((lambda x, y: x + y), transaction_input_amounts) if request_amount > transaction_input_amount_sum: raise Exception('error.not_enough_input_amount') to_sender_amount = request_amount * 0.99 transaction = Transaction.build(block_id=None, locktime=0, timestamp=timestamp) to_sender_transaction_output = TransactionOutput.build( transaction_id=transaction.transaction_id, amount=to_sender_amount, sender_address=sender_address, recipient_address=recipient_address, timestamp=timestamp) to_coinbase_amount = TransactionOutput.build( transaction_id=transaction.transaction_id, amount=request_amount - to_sender_amount, sender_address=sender_address, recipient_address=COINBASE_ADDRESS, timestamp=timestamp) to_recipient_amount = TransactionOutput.build( transaction_id=transaction.transaction_id, amount=transaction_input_amount_sum - request_amount, sender_address=sender_address, recipient_address=sender_address, timestamp=timestamp) transaction_outputs = [ to_sender_transaction_output, to_coinbase_amount, to_recipient_amount ] transaction.transaction_outputs = transaction_outputs transaction.transaction_inputs = transaction_inputs UnconfirmedTransactionPool.transactions.append(transaction) return transaction
class Blockchain: blocks = [ Block.build( block_number=1, previous_block_hash="1", timestamp=0, merkle_root="", difficulty_target=20, nonce=0, transactions=[ Transaction.build( timestamp=1, tx_inputs=[], tx_outputs=[ TransactionOutput.build( amount=1000000000, sender_address=COINBASE_ADDRESS, recipient_address= "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAznjoHvzCJtQcIYd3yj7vgwaPlyiG6U/Qlw1G89n0bNt5anvRe+e2eKzvpy98aj6ShGu7hARE9SxAFA9bIHCBqdAyPnrUaw7qGkeZNPHBByHe9prJSn0ZwBtfySOSbzdetO5aAwvLj5qMudW2PDz15mP2taGOvXqNnbcH78ZHQLvF6G+SbwuLHU5LEDSZlcy+CnvPqD67cg+QmJLneVmQfOBtbFHz3yDQghNrHWa+UCspUMHVGsDG6OEK7MSpPieY6TzBEYQWsikosQ+V0zBNrSCADe3GBcJ7XzafM/gb+gzJ1eP78F1sA6Ja4ZtqInqN406PwerAXaUJa2twW6529wIDAQAB", timestamp=1) ]), Transaction.build( timestamp=1, tx_inputs=[], tx_outputs=[ TransactionOutput.build( amount=200000000, sender_address=COINBASE_ADDRESS, recipient_address= "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAznjoHvzCJtQcIYd3yj7vgwaPlyiG6U/Qlw1G89n0bNt5anvRe+e2eKzvpy98aj6ShGu7hARE9SxAFA9bIHCBqdAyPnrUaw7qGkeZNPHBByHe9prJSn0ZwBtfySOSbzdetO5aAwvLj5qMudW2PDz15mP2taGOvXqNnbcH78ZHQLvF6G+SbwuLHU5LEDSZlcy+CnvPqD67cg+QmJLneVmQfOBtbFHz3yDQghNrHWa+UCspUMHVGsDG6OEK7MSpPieY6TzBEYQWsikosQ+V0zBNrSCADe3GBcJ7XzafM/gb+gzJ1eP78F1sA6Ja4ZtqInqN406PwerAXaUJa2twW6529wIDAQAB", timestamp=1) ]), Transaction.build( timestamp=1, tx_inputs=[], tx_outputs=[ TransactionOutput.build( amount=300003, sender_address=COINBASE_ADDRESS, recipient_address= "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAznjoHvzCJtQcIYd3yj7vgwaPlyiG6U/Qlw1G89n0bNt5anvRe+e2eKzvpy98aj6ShGu7hARE9SxAFA9bIHCBqdAyPnrUaw7qGkeZNPHBByHe9prJSn0ZwBtfySOSbzdetO5aAwvLj5qMudW2PDz15mP2taGOvXqNnbcH78ZHQLvF6G+SbwuLHU5LEDSZlcy+CnvPqD67cg+QmJLneVmQfOBtbFHz3yDQghNrHWa+UCspUMHVGsDG6OEK7MSpPieY6TzBEYQWsikosQ+V0zBNrSCADe3GBcJ7XzafM/gb+gzJ1eP78F1sA6Ja4ZtqInqN406PwerAXaUJa2twW6529wIDAQAB", timestamp=1) ]), ]) ] @classmethod def fetch_all_blocks(cls): return cls.blocks @classmethod def fetch_block_count(cls): return len(cls.blocks) @classmethod def fetch_last_block(cls): return cls.blocks[-1] @classmethod def fetch_unspent_tx_outputs_by_tx_output_ids(cls, tx_output_ids): blocks = cls.blocks if len(blocks) == 0: return [] transactions = reduce( add, list(map(lambda block: block.transactions, blocks))) if len(transactions) == 0: return [] tx_outputs = reduce(add, list(map(lambda tx: tx.tx_outputs, transactions))) tx_inputs = reduce(add, list(map(lambda tx: tx.tx_inputs, transactions))) spent_tx_output_ids = list( map(lambda tx_i: tx_i.transaction_output_id, tx_inputs)) unspent_tx_outputs = list( filter( lambda tx_o: tx_o.transaction_output_id not in spent_tx_output_ids, tx_outputs)) return list( filter(lambda tx_o: tx_o.transaction_output_id in tx_output_ids, unspent_tx_outputs)) @classmethod def fetch_unspent_tx_outputs_by_address(cls, address): blocks = cls.blocks if len(blocks) == 0: return [] transactions = reduce( add, list(map(lambda block: block.transactions, blocks))) if len(transactions) == 0: return [] tx_outputs = reduce(add, list(map(lambda tx: tx.tx_outputs, transactions))) tx_inputs = reduce(add, list(map(lambda tx: tx.tx_inputs, transactions))) spent_tx_output_ids = list( map(lambda tx_i: tx_i.transaction_output_id, tx_inputs)) return list( filter( lambda tx_o: tx_o.recipient_address == address and tx_o. transaction_output_id not in spent_tx_output_ids, tx_outputs)) @classmethod def create_block(cls, block): cls.blocks.append(block) @classmethod def search_new_transactions(cls, transactions): transactions_in_chain = reduce( add, list(map(lambda block: block.transactions, cls.blocks))) return list( filter(lambda tx: tx not in transactions_in_chain, transactions)) @classmethod def delete_block(cls, deleting_block): cls.blocks.remove(deleting_block) @classmethod def find_block(cls, block_id): blocks = list( filter(lambda block: block.block_id == block_id, cls.blocks)) if len(blocks) == 0: return None return blocks[0]