def test_transaction_creation(self): # Create transaction and check if used ordered dict t = Transaction("1234", "4567") o_dict = OrderedDict({"addr_from": "1234"}) o_dict["addr_to"] = "4567" self.assertTrue(type(t.get_json()) == type(o_dict)) self.assertDictEqual(t.get_json(), o_dict)
def get_by_account_id(self, account_id: str, parent: str = None) -> List[Transaction]: coll_ref = self.collection_ref if parent: coll_ref = db.collection(parent + '/' + self.collection_name) transactions = coll_ref.where('account_id', '==', account_id).stream() return [Transaction(**doc.to_dict()) for doc in transactions if doc.to_dict()]
def validate_transaction(self, transaction): """ Validate that a transaction signature corresponds to the provided data """ t_sig = b64decode(transaction["signature"].encode()) pubkey = b64decode(transaction["pubkey"].encode()) verifier = PKCS1_v1_5.new(RSA.importKey(pubkey)) digest = SHA256.new() t = Transaction(transaction["addr_from"], transaction["addr_to"]) digest.update(str(t.get_json()).encode()) verified = verifier.verify(digest, t_sig) if verified: return True else: logger.info("Signature is invalid") return False
def _create_tx_to_miner(cls, block, miner_address): tx_amount_to_miner = block.get_tx_amount_to_miner() transaction = Transaction.build_for_miner( timestamp=datetime.now().timestamp(), amount=tx_amount_to_miner, miner_address=miner_address) UnconfirmedTxPool.create_transaction(transaction) return transaction
def get(self, id: UUID) -> Transaction: doc_ref = self.collection_ref.document(str(id)) doc = doc_ref.get() if doc.exists: return Transaction(**doc.to_dict()) return None
def list(): """ Show all transactions on a list. """ return render_template( "transaction/list.html", transactions = Transaction.get_all_for_list() )
def decode_transaction(dictionary): return Transaction(transaction_id=dictionary['transaction_id'], tx_inputs=list( map(lambda tx_i: decode_tx_input(tx_i), dictionary['tx_inputs'])), tx_outputs=list( map(lambda tx_o: decode_tx_output(tx_o), dictionary['tx_outputs'])))
def test_block_creation(self): # Create genesis transaction transaction = Transaction("Genesis Addr", "Genesis Block") key = RSA.generate(1024) miner_id = "1234" # Create genesis block with genesis transaction, signing it genesis = Block("Genesis Block", 0, [transaction.get_signed_json(key)], miner_id) self.assertDictEqual( genesis.get_json(), { "miner": miner_id, "hash": "", "prevHash": "Genesis Block", "height": 0, "nonce": 0, "data": [transaction.get_signed_json(key)] })
async def create(*, transaction: TransactionSchemaCreate): crud.wallet.get(id=transaction.wallet_id, error_out=True) crud.category.get(id=transaction.category_id, error_out=True) date_tran = datetime.strptime(transaction.date_tran, '%d/%m/%Y').date() db_transaction = Transaction(amount=transaction.amount, description=transaction.description, date_tran=date_tran, category_id=transaction.category_id, wallet_id=transaction.wallet_id) db_transaction = crud.transaction.create(obj_in=db_transaction) return {"data": db_transaction}
def update_transaction(cls, user_id, symbol, volume, price, total, txttype): transaction = Transaction(user_id=user_id, symbol=symbol, volume=volume, stock_price=price, total_price=total, datetime=datetime.now(), txntype=txttype) db.session.add(transaction) db.session.commit()
def create_and_add_transaction(self, addr_to): """ Used to make a transaction from current node to another """ logger.info("Add transaction to pool") if self.has_to_vote(): if self.check_valid_address(addr_to): transaction = Transaction(self.miner_id, addr_to) self.blockchain.add_transaction_to_pool( transaction.get_signed_json(self.private_key)) self.propagate_transaction( transaction.get_signed_json(self.private_key)) if len(self.sched.get_jobs()) == 0: logger.info("Start block schedule") self.sched.add_job(self.create_and_add_block, 'date', run_date=datetime.now() + timedelta(seconds=5)) else: logger.error("Cannot vote for this ledger, check the address")
def details(id): """ Show basic information of one transaction. """ transaction = Transaction.get_transaction_details(id) if not transaction: abort(404) return render_template( "transaction/details.html", transaction = transaction )
def test_block_validation(self): chain = Blockchain() private_key = RSA.generate(1024) miner_id = "1234" chain.create_genesis_block(private_key, miner_id) prevBlock = chain.storage[0] t = Transaction("1234", "4567") # Create Block with dummy transaction block = Block(prevBlock["hash"], prevBlock["height"] + 1, [t.get_signed_json(private_key)], miner_id) block.mine() # Check block validation is ok self.assertTrue(chain.validate_block(block.get_json(), prevBlock)) # Mess with blockchain structure block.block["prevHash"] = "00012345" self.assertFalse(chain.validate_block(block.get_json(), prevBlock)) # Mess with height block.block["prevHash"] = prevBlock["hash"] block.block["height"] = 5 self.assertFalse(chain.validate_block(block.get_json(), prevBlock)) # Mess with PoW block.block["height"] = 2 block.block["hash"] = "0111111111" self.assertFalse(chain.validate_block(block.get_json(), prevBlock)) # Mess with hash but keep PoW block.block["hash"] = "0001111111" self.assertFalse(chain.validate_block(block.get_json(), prevBlock)) # Mess with transaction integrity t.signature = "L7TBH0ahox4GOAdF8om2ijbNVPcO3Ys6+KdvfFhvfX/SysetaJw+0rlU6VMuzwB0rQ/X2+ioAdtXcstutSeRAfZTYP+utaNFL1nP48as/C6mca4sp+ya39AWWLIUuZeGMit9kSUavx6uX5cSAuqXB4tcK/bUSVghtMC9vG4JyC8=" block = Block(prevBlock["prevHash"], prevBlock["height"] + 1, [t.get_signed_json(private_key)], miner_id) block.mine() self.assertFalse(chain.validate_block(block.get_json(), prevBlock))
def decode_transaction(dictionary): if dictionary['transaction_outputs'] is not None: transaction_outputs = decode_transaction_outputs(dictionary['transaction_outputs']) else: transaction_outputs = None if dictionary['transaction_inputs'] is not None: transaction_inputs = decode_transaction_inputs(dictionary['transaction_inputs']) else: transaction_inputs = None return Transaction( transaction_id = dictionary['transaction_id'], block_id = dictionary['block_id'], locktime = dictionary['locktime'], transaction_inputs = transaction_inputs, transaction_outputs = transaction_outputs )
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 test_transaction_signature(self): # Create transaction t = Transaction("1234", "4567") # Create Private Key key = RSA.generate(1024) # Sign transaction and recover complete transaction JSON signed_json = t.get_signed_json(key) # Verify signature and public key match t_sig = b64decode(signed_json["signature"].encode()) pubkey = b64decode(signed_json["pubkey"].encode()) verifier = PKCS1_v1_5.new(RSA.importKey(pubkey)) digest = SHA256.new() t = Transaction(signed_json["addr_from"], signed_json["addr_to"]) digest.update(str(t.get_json()).encode()) self.assertTrue(verifier.verify(digest, t_sig))
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()
def create_transaction(cls, tx_request): # 使用としているトランザクションアウトプットIDが既に未承認のトランザクションアウトプットIDに含まれていたら例外を投げる spent_tx_output_ids_in_unconfirmed_tx_pool = UnconfirmedTxPool.list_spent_tx_output_ids() tx_request.assert_unspent_tx_output_ids(spent_tx_output_ids_in_unconfirmed_tx_pool) unspent_tx_outputs_in_blockchain = Blockchain.fetch_unspent_tx_outputs_by_tx_output_ids( tx_request.get_requesting_tx_output_ids()) # 今回使用しようとしているトランザクションインプットを算出 tx_inputs = tx_request.get_tx_inputs(unspent_tx_outputs_in_blockchain) TransactionInput.verify_tx_inputs(tx_inputs, tx_request.sender_address) transaction = Transaction.build_with_tx_outputs( timestamp = tx_request.timestamp, tx_inputs = tx_inputs, request_amount = tx_request.amount, sender_address = tx_request.sender_address, recipient_address = tx_request.recipient_address ) UnconfirmedTxPool.transactions.append(transaction) return transaction
def transfer(id): """ Depending on request type, either (1) show form for recording a transaction, or (2) create new transaction, and update 'current owner' field on the certificate. Refuse to do anything if the certificate in question already has been canceled. """ c = Certificate.query.get_or_404(id) if c.canceled_on: notify.is_already_canceled("certificate") return redirect(url_for("certificate.details", id=id)) f = TransactionForm(request.form) f.buyer_id.choices = Shareholder.get_dropdown_options() if f.validate_on_submit(): t = Transaction() f.populate_obj(t) c.owner_id = f.buyer_id.data t.price = int(100 * t.price) t.price_per_share = int(t.price / c.share_count) t.save_or_update() notify.create_ok("transaction") return redirect(url_for("certificate.details", id=id)) elif request.method == "POST": notify.invalid_input() else: f.certificate_id.data = id f.shares.data = c.get_title() f.seller_id.data = c.owner_id f.seller.data = Certificate.get_current_owner(id).get("name") f.last_transaction.data = Certificate.get_last_transaction_date(id) \ or c.issued_on return render_template("transaction/form.html", form=f)
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
def setUp(self): self.transaction = Transaction("Sainsbury's", "Groceries", 4.59)
def list(self) -> List[Transaction]: todos_ref = self.collection_ref return [Transaction(**doc.get().to_dict()) for doc in todos_ref.list_documents() if doc.get().to_dict()]
else: log.debug("{}-db schema up to date".format(table.name)) data_base.metadata.create_all(engine) if reset_blocks: data_db().query(Block).delete() return data_db def check_table_ddl_against_model(database, table) -> bool: if database.bind.name == "sqlite": db_table_ddl = database().execute( "select sql from sqlite_master where type = 'table' and name = '{}'" .format(table.name)).scalar() else: raise Exception("Unsupported database dialect:{}".format( database.bind.name)) return str.strip(CreateTable(table).compile( database.bind).string) == str.strip(db_table_ddl or '') if __name__ == '__main__': import app.helpers app.helpers.init_logging() init_profile_db() init_data_db() for t in Transaction.select(): print(t)
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]