def test_post_transaction(self): self.prepare_app() # prepare a valid transaction w = Wallet() w.create_keys() tx = Transaction("0", w.get_address(), 1) w.sign_transaction(tx) client = app.test_client() response = client.post("/block/new", data=tx.to_json()) self.assertEqual(response.status_code, 201) b = Block.from_json(response.get_data()) mine(b) response = client.post("/block", data=b.to_json()) self.assertEqual(response.status_code, 201) tx = Transaction(w.get_address(), 1, 0.5) # test without signature response = client.post("/transaction", data=tx.to_json()) self.assertEqual(response.status_code, 400) # test with signature w.sign_transaction(tx) response = client.post("/transaction", data=tx.to_json()) self.assertEqual(response.status_code, 201)
def test_use_pool(self): bc = BlockChain() w = Wallet() w.create_keys() # make some cash tx0 = Transaction("0", w.get_address(), 1) b = bc.new_block(tx0) mine(b) self.assertTrue(bc.discard_block(b)) self.assertEqual(bc.get_wallet_balance(w.get_address()), 1) tx_count = 10 for i in range(tx_count): t = Transaction(w.get_address(), 1, 1 / 100) w.sign_transaction(t) self.assertTrue(bc.add_transaction(t)) self.assertEqual(len(bc.transaction_pool), tx_count) b = bc.new_block(self.tx) max_txs_in_block = 2**Tree.MAX_DEPTH self.assertEqual(len(list(b.get_transactions())), min(max_txs_in_block, tx_count + 1)) # Transactions in new block are removed from tx pool when new block is successfully discarded to chain b = bc.new_block(self.tx) # coinbase tx mine(b) bc.discard_block(b) expected_txs_in_tx_pool = max(0, tx_count - (max_txs_in_block - 1)) self.assertEqual(len(bc.transaction_pool), expected_txs_in_tx_pool) leftover_count = min(max_txs_in_block - 1, expected_txs_in_tx_pool) self.assertEqual(len(list(bc.new_block(self.tx).get_transactions())), 1 + leftover_count)
def test_block_serialize(self): a = Block(0, 1, datetime.datetime.utcnow().timestamp()) t1 = Transaction(0, 1, 2) a.add_transaction(t1) t2 = Transaction(0, 1, 2) a.add_transaction(t2) b = Block.from_json(a.to_json()) self.assertEqual(a.get_hash(), b.get_hash())
def test_walk_transactions(self): b = Block(0, 0, 0) t = Transaction(0, 1, 2) b.add_transaction(t) self.assertEqual(len(list(b.get_transactions())), 1) t = Transaction(0, 1, 2) b.add_transaction(t) self.assertEqual(len(list(b.get_transactions())), 2) for x in b.get_transactions(): self.assertIsInstance(x, Transaction)
def test_locate_transaction(self): t = Tree() trans1 = Transaction(0, 1, 2) self.assertTrue(t.add_transaction(trans1)) trans2 = Transaction(1, 2, 3) self.assertTrue(t.add_transaction(trans2)) self.assertEqual(t.depth, 1) self.assertTrue(t.is_present(trans1)) trans3 = Transaction(0, 1, 2) self.assertFalse(t.is_present(trans3))
def post(self): key = self.request.GET['key'] try: category = self.request.get("category", "none") quantity = float(self.request.get("quantity", 0)) type = self.request.get("type", "none") description = self.request.get("description", "none") date = self.request.get("date", "none") date_format = datetime.datetime.strptime(date, "%Y-%m-%d") except ValueError: url = "/viewAccount?key=" + str( key) + ";msg_error=Formato de campo incorrecto" self.redirect(url) return account_key = ndb.Key(urlsafe=key) #Store the answer new_transaction = Transaction(category=category, quantity=quantity, type=type, description=description, date=date_format, account=account_key) new_transaction.put() time.sleep(1) url = "/viewAccount?key=" + str(key) self.redirect(url)
def generate_wallet_and_coinbase(): w = Wallet() w.create_keys() tx = Transaction("0", w.get_address(), 1) # coinbase w.sign_transaction(tx) return w, tx
def test_transaction(self): """One tree node can contain only one transaction""" n = TreeNode() t = Transaction(0, 1, 1) self.assertTrue(n.add_child(t)) n1 = TreeNode() self.assertFalse(n.add_child(n1))
def test_tree_serialize(self): t = Tree() u = Tree.from_json(t.to_json()) self.assertEqual(t.root.get_hash(), u.root.get_hash()) trans1 = Transaction(0, 1, 2) self.assertTrue(t.add_transaction(trans1)) trans2 = Transaction(1, 2, 3) self.assertTrue(t.add_transaction(trans2)) trans3 = Transaction(2, 3, 4) self.assertTrue(t.add_transaction(trans3)) u = Tree.from_json(t.to_json()) self.assertEqual(t.root._child_1.get_hash(), u.root._child_1.get_hash()) self.assertEqual(t.root.get_hash(), u.root.get_hash())
def withdrawal(self, date, description, amount): tx = Transaction(date=date, description=description, amount=amount * -1, tx_type='W', account_number=self.number) self.transactions.append(tx) return tx
def deposit(self, date, description, amount): tx = Transaction(date=date, description=description, amount=amount, tx_type='D', account_number=self.number) self.transactions.append(tx) return tx
def make_transaction(self, data: dict) -> Transaction: """ Método disparado quando efetuado a chamada de um .load(object).data onde efetua o retorno de uma instancia de um dataclass de uma transação :param data: payload que irá ser transformado :return: Instancia dataclass de umma transação. """ return Transaction(**data)
def test_transaction_serialize(self): t1 = Transaction(0, 1, 2) t2 = Transaction(0, 1, 2) self.assertNotEqual(t1.get_hash(), t2.get_hash()) t3 = Transaction.from_json(t1.to_json()) self.assertEqual(t1.get_hash(), t3.get_hash()) self.assertEqual(t1.src, t3.src) self.assertEqual(t1.dst, t3.dst) self.assertEqual(t1.qty, t3.qty) w = Wallet() w.create_keys() w.sign_transaction(t1) t4 = Transaction.from_json(t1.to_json()) self.assertEqual(t1.get_hash(), t4.get_hash())
def test_inf_nan_balance(self): bc = BlockChain() tx = Transaction("src", "dst", math.inf) is_found = False balance, is_found = bc.update_balance("src", math.inf, tx, is_found) self.assertEqual(is_found, True) self.assertEqual(balance, math.inf)
def test_verify_foreign_transaction(self): w = Wallet() w.create_keys() t = Transaction(w.get_address(), 1, 1) w.sign_transaction(t) # Create different keypair w.create_keys() self.assertTrue(w.verify_transaction(t))
def enrich_wallet_coinbase(cls): w = Wallet() w.create_keys() tx = Transaction("0", w.get_address(), 1) # coinbase w.sign_transaction(tx) cls.w = w cls.tx = tx return w, tx
def test_secure_wallet_balance(self): bc = BlockChain() w1 = Wallet() w1.create_keys() addr1 = w1.get_address() tx0 = Transaction("0", addr1, 1) b = bc.new_block(tx0) mine(b) bc.discard_block(b) balance = bc.get_secure_wallet_balance(addr1) self.assertEqual(balance, None) tx1 = Transaction(addr1, "toto", 1) w1.sign_transaction(tx1) cbtx = WalletHelper.generate_coinbase_with_unused_wallet() b1 = bc.new_block(cbtx) b1.add_transaction(tx1) mine(b1) bc.discard_block(b1) self.assertEqual(bc.get_secure_wallet_balance("toto"), None) for i in range(5): tx0 = Transaction("0", addr1, 1) b = bc.new_block(tx0) mine(b) bc.discard_block(b) # only 5 confirmations so far, tx is not there yet for secure balance self.assertEqual(bc.get_secure_wallet_balance("toto"), None) cbtx = WalletHelper.generate_coinbase_with_unused_wallet() b6 = bc.new_block(cbtx) mine(b6) bc.discard_block(b6) # tx appears after 6 confirmations only self.assertEqual(bc.get_secure_wallet_balance("toto"), 1)
def to_object(self, row): if len(row) > 0: return (Transaction(id_=int(row[0]), account_number=int(row[1]), date=datetime.strptime(row[2], '%Y/%m/%d %H:%M:%S'), tx_type=row[3], description=row[4], amount=row[5])) return None
def test_import_transactions(self): b = Block(0, 0) w = Wallet() w.create_keys() t = Transaction(w.get_address(), 1, 1) w.sign_transaction(t) b.add_transaction(t) tp = TransactionPool() self.assertTrue(tp.import_transactions(b)) self.assertEqual(len(tp), 1) t2 = tp.pull_transaction() self.assertEqual(t.get_hash(), t2.get_hash()) # Importing unsigned transactions returns False tp = TransactionPool() t2 = Transaction(0, 1, 1) b.add_transaction(t2) self.assertFalse(tp.import_transactions(b))
def insertTransactions(self, transactions): for t in transactions['transactions']: try: newTransaction = Transaction(tid=t['id'], iban=t['originIban'], transaction=t) self.session.merge(newTransaction) self.session.commit() except: self.session.rollback() print("transaction already exists") pass
def test_create_block(self): b = Block(0, 0, 0) self.assertIsInstance(b, Block) t = Transaction(0, 1, 2) self.assertTrue(b.add_transaction(t)) header = b.get_header() header = json.loads(header) self.assertIsInstance(header, dict) self.assertIsInstance(header["trans_tree"], str)
def test_add_transactions(self): t = Tree() trans1 = Transaction(0, 1, 2) self.assertTrue(t.add_transaction(trans1)) self.assertEqual(t.depth, 0) trans2 = Transaction(1, 2, 3) self.assertTrue(t.add_transaction(trans2)) self.assertEqual(t.depth, 1) trans3 = Transaction(2, 3, 4) self.assertTrue(t.add_transaction(trans3)) self.assertEqual(t.depth, 2) trans4 = Transaction(3, 4, 5) self.assertTrue(t.add_transaction(trans4)) self.assertEqual(t.depth, 2) self.assertEqual(len(list(Tree.walk(t.root))), 7) expected_remaining_transactions_before_failure = 2**Tree.MAX_DEPTH - 4 for i in range(expected_remaining_transactions_before_failure): tx = Transaction(0, 0, 1) t.add_transaction(tx) # Cannot add a fifth transaction, since the MAX_DEPTH equals to 2 trans5 = Transaction(4, 5, 6) self.assertFalse(t.add_transaction(trans5)) self.assertEqual(t.depth, Tree.MAX_DEPTH)
def save_transaction(self, account, detail): trading_date = self.convert_trading_date(detail[0].text) if trading_date is None: return 0 description = detail[1].text account_id = account.get_account_id() balance = float(detail[2].text.replace(',', '')) reference_number = self.convert_reference_number(description) transaction = Transaction(account_id, reference_number, trading_date, balance, description) if transaction.save() == 1: self.total_transactions = self.total_transactions + 1 self.email_transport.send_transaction_email(account, transaction)
def test_sign_transaction(self): w = Wallet() w.create_keys() t = Transaction(w.get_address(), 1, 1) th = t.get_hash() self.assertIsNone(t.signature) self.assertTrue(w.sign_transaction(t)) self.assertIsNotNone(t.signature) self.assertEqual(t.get_hash(), th) self.assertTrue(w.verify_transaction(t))
def send_tx(self, destination, quantity, p2p): """Perform a transaction.""" w = self.get_active_wallet() magic = p2p.bc.magic tx = Transaction(w.get_address(), destination, quantity, magic=magic) w.sign_transaction(tx) success = p2p.bc.add_transaction(tx) if success: # broadcast transaction to p2p network p2p.broadcast_tx(tx) return True else: logging.debug("Failed to add transaction.") return False
def save_transaction(self, account, detail): trading_date = self.convert_trading_date( detail[0].find_element_by_xpath("div[contains(@class,'list-info-txt-sub')]").text) description = detail[0].find_element_by_xpath("div[contains(@class,'list-info-txt-main')]").text account_id = account.get_account_id() reference_number = detail[1].find_element_by_xpath("div[contains(@class,'list-info-txt-sub')]").text.replace( 'Số tham chiếu: ', '') balance = float( detail[1].find_element_by_xpath("div[contains(@class,'list-info-txt-main')]").text.replace(',', '').replace( ' ', '')) transaction = Transaction(account_id, reference_number, trading_date, balance, description) print(reference_number) if transaction.save() == 1: self.total_transactions = self.total_transactions + 1 self.email_transport.send_transaction_email(account, transaction)
def save_transaction(self, account, detail): trading_date = self.convert_trading_date(detail[0].text) reference_number = detail[1].text description = detail[3].text account_id = account.get_account_id() if detail[4].text is not '': balance = float(detail[4].text.replace(',', '').replace(' ', '')) else: balance = float(detail[5].text.replace(',', '').replace(' ', '')) transaction = Transaction(account_id, reference_number, trading_date, balance, description) if transaction.save() == 1: self.total_transactions = self.total_transactions + 1 self.email_transport.send_transaction_email(account, transaction)
def test_post_new_block(self): self.prepare_app() # prepare a valid transaction w = Wallet() w.create_keys() tx = Transaction(0, w.get_address(), 1) w.sign_transaction(tx) client = app.test_client() response = client.post("/block/new", data=tx.to_json()) self.assertEqual(response.status_code, 201) b = Block.from_json(response.get_data()) self.assertTrue(type(b) == Block)
def save_transaction(self, account, history): trading_date = self.convert_trading_date(history['transferDate']) trading_time = history['transferTime'] description = history['remark'] if description is None: description = 'None' account_id = account.get_account_id() balance = float(history['amount']) if history['dcSign'] == 'D': balance = -balance reference_number = self.code.generate_code(description + history['transferDate']) created_at = trading_date + ' ' + trading_time transaction = Transaction(account_id, reference_number, trading_date, balance, description, created_at) if transaction.save() == 1: self.total_transactions = self.total_transactions + 1 self.email_transport.send_transaction_email(account, transaction)
def test_post_block(self): p2p = ClientAPITest.DummyP2p() bc = BlockChain() p2p.bc = bc app.p2p = p2p # make some cash first w, cbtx = WalletHelper.generate_wallet_and_coinbase() cash_block = bc.new_block(cbtx) mine(cash_block) bc.discard_block(cash_block) txs = [] for i in range(4): tx = Transaction(w.get_address(), i, 0.1) w.sign_transaction(tx) txs.append(tx) # mine current block cbtx = WalletHelper.generate_coinbase_with_unused_wallet() current_block = bc.new_block(cbtx) mine(current_block) # put current block in chain and create new block bc.discard_block(current_block) # create new block cbtx = WalletHelper.generate_coinbase_with_unused_wallet() b = bc.new_block(cbtx) for tx in txs: b.add_transaction(tx) client = app.test_client() # POST new UN-mined block (should fail and return 400 bad request) response = client.post("/block", data=b.to_json()) self.assertEqual(response.status_code, 400) # mine new block mine(b) # POST new mined block (should work this time) response = client.post("/block", data=b.to_json()) self.assertEqual(response.status_code, 201)