Exemple #1
0
    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)
Exemple #2
0
    def test_add_block(self):
        bc = BlockChain()

        # Can add block when previous has been proven
        b = bc.new_block(self.tx)
        mine(b)
        self.assertTrue(bc.discard_block(b))

        self.assertTrue(bc.get_block_from_index(1).validate_proof())
        self.assertEqual(bc.get_block_from_index(0).index, 0)
        self.assertEqual(len(bc.chain), 2)
        self.assertNotEqual(
            bc.get_block_from_index(0).get_hash(),
            bc.get_block_from_index(-1).get_hash())
Exemple #3
0
    def test_search_block(self):
        bc = BlockChain()
        for i in range(5):
            cbtx = WalletHelper.generate_coinbase_with_unused_wallet()
            b = bc.new_block(cbtx)
            mine(b)
            self.assertTrue(bc.discard_block(b))

        for i in range(6):
            h = bc.get_block_from_index(i).get_hash()
            self.assertEqual(bc.get_block_from_hash(h),
                             bc.get_block_from_index(i))

        self.assertFalse(bc.get_block_from_hash("abc"))
Exemple #4
0
    def test_blockchain_serialize(self):
        bc = BlockChain()

        b = bc.new_block(self.tx)
        mine(b)
        self.assertTrue(bc.discard_block(b))

        bc2 = BlockChain.from_json(bc.to_json())
        self.assertEqual(
            bc.get_block_from_index(-1).get_hash(),
            bc2.get_block_from_index(-1).get_hash())
        self.assertEqual(
            bc.get_block_from_index(0).get_hash(),
            bc2.get_block_from_index(0).get_hash())
Exemple #5
0
    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)
Exemple #6
0
    def test_file_save(self):
        test_dir = tempfile.mkdtemp()
        test_file = path.join(test_dir, "blockchain.json")

        bc = BlockChain()
        b = bc.new_block(self.tx)
        mine(b)
        bc.discard_block(b)
        self.assertTrue(bc.save_to_file(test_file))
        self.assertIsInstance(BlockChain.load_from_file(test_file), BlockChain)

        shutil.rmtree(test_dir)
Exemple #7
0
    def test_create_chain(self):
        bc = BlockChain()
        self.assertIsInstance(bc.new_block(), Block)
        self.assertEqual(len(bc.chain), 1)

        self.assertFalse(bc.get_block_from_index(1337))

        # Cannot add block when previous has not been proven
        b = bc.new_block()
        self.assertFalse(bc.discard_block(b))
Exemple #8
0
    def test_block_chaining(self):
        bc = BlockChain()
        for i in range(5):
            cbtx = WalletHelper.generate_coinbase_with_unused_wallet()
            b = bc.new_block(cbtx)
            mine(b)
            self.assertTrue(bc.discard_block(b))

        self.assertEqual(len(bc.chain), 6)
        for i in range(6):
            self.assertEqual(bc.get_block_from_index(i).index, i)
        for i in range(1, 6):
            self.assertEqual(
                bc.get_block_from_index(i - 1).get_hash(),
                bc.get_block_from_index(i).prevhash)
Exemple #9
0
 def prepare_app(self):
     # setup app.p2p.bc
     p2p = ClientAPITest.DummyP2p()
     bc = BlockChain()
     p2p.bc = bc
     app.p2p = p2p
Exemple #10
0
    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)
Exemple #11
0
    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)
Exemple #12
0
    def test_wallet_balance(self):
        bc = BlockChain()

        w1 = Wallet()
        w1.create_keys()
        addr1 = w1.get_address()

        w2 = Wallet()
        w2.create_keys()
        addr2 = w2.get_address()

        w3 = Wallet()
        w3.create_keys()
        addr3 = w3.get_address()

        tx0 = Transaction("0", addr1, 1)
        b = bc.new_block(tx0)
        mine(b)
        bc.discard_block(b)

        balance = bc.get_wallet_balance(addr1)
        self.assertEqual(balance, 1)

        tx1 = Transaction(addr1, addr2, 0.1)
        tx2 = Transaction(addr1, addr3, 0.2)
        tx3 = Transaction(addr2, addr3, 133)

        w1.sign_transaction(tx1)
        w1.sign_transaction(tx2)
        w2.sign_transaction(tx3)

        self.assertTrue(bc.add_transaction(tx1))
        self.assertTrue(bc.add_transaction(tx2))
        self.assertFalse(bc.add_transaction(tx3))

        tx4 = Transaction(addr1, addr2, 1)
        w1.sign_transaction(tx4)
        self.assertFalse(bc.add_transaction(tx4))

        balance = bc.get_wallet_balance(addr1)
        self.assertEqual(balance, 0.7)

        balance = bc.get_wallet_balance(addr2)
        self.assertEqual(balance, 0.1)

        balance = bc.get_wallet_balance(addr3)
        self.assertEqual(balance, 0.2)

        w4 = Wallet()
        w4.create_keys()
        addr4 = w4.get_address()

        cbtx4 = Transaction("0", addr4, 1)
        b4 = bc.new_block(cbtx4)
        mine(b4)
        bc.discard_block(b4)
        self.assertTrue(bc.get_wallet_balance(addr4), 1)

        ntx4 = Transaction(addr4, "toto", 1, magic=bc.magic)
        w4.sign_transaction(ntx4)
        self.assertTrue(bc.add_transaction(ntx4))
        coinbase4 = Transaction("0", addr4, 1)
        nb4 = bc.new_block(
            coinbase4
        )  # new block nb4 is filled with coinbase4 and ntx4 (fill_block() was called)
        mine(nb4)  # mine block before adding to chain
        logger.debug("DISCARDING...")
        discarded = bc.discard_block(nb4)
        logger.debug("END DISCARD")
        self.assertTrue(discarded)
Exemple #13
0
    def test_block_since(self):
        bc = BlockChain()

        cbtx = WalletHelper.generate_coinbase_with_unused_wallet()
        b = bc.new_block(cbtx)
        mine(b)
        bc.discard_block(b)

        cbtx = WalletHelper.generate_coinbase_with_unused_wallet()
        b2 = bc.new_block(cbtx)
        mine(b2)
        bc.discard_block(b2)

        cbtx = WalletHelper.generate_coinbase_with_unused_wallet()
        b3 = bc.new_block(cbtx)

        self.assertEqual(len(bc.get_blocks_since(b.get_hash())), 1)
        self.assertEqual(len(bc.get_blocks_since(b2.get_hash())), 0)

        # Block b3 is not in the blockchain
        self.assertIsNone(bc.get_blocks_since(b3.get_hash()))
Exemple #14
0
    def test_discard_block(self):
        bc = BlockChain()

        cbtx = WalletHelper.generate_coinbase_with_unused_wallet()
        b = bc.new_block(cbtx)
        mine(b)
        self.assertTrue(bc.discard_block(b))

        b = Block(1337, bc.get_block_from_index(1).get_hash())
        cbtx = WalletHelper.generate_coinbase_with_unused_wallet()
        b.add_transaction(cbtx)
        mine(b)
        self.assertFalse(bc.discard_block(b))
        self.assertEqual(len(bc.chain), 2)

        b = Block(bc.get_block_from_index(-1).index, "obviously_fake_hash")
        cbtx = WalletHelper.generate_coinbase_with_unused_wallet()
        b.add_transaction(cbtx)
        mine(b)
        self.assertFalse(bc.discard_block(b))
        self.assertEqual(len(bc.chain), 2)

        b = Block(
            bc.get_block_from_index(1).index + 1,
            bc.get_block_from_index(1).get_hash())
        cbtx = WalletHelper.generate_coinbase_with_unused_wallet()
        b.add_transaction(cbtx)  # coinbase
        mine(b)
        self.assertTrue(bc.discard_block(b))
        self.assertEqual(len(bc.chain), 3)
Exemple #15
0
from uuid import uuid4
from flask import Flask, jsonify, request

from model.blockchain import BlockChain

app = Flask(__name__)

node_id = str(uuid4()).replace('-', '')  # このノードのグローバルにユニークなアドレスを作る
bc = BlockChain()  # ブロックチェーンクラスを初期化


@app.route('/transactions/new', methods=['POST'])
def post_new_transactions():
    values = request.get_json()

    # POSTされたデータに必要なデータがあるかを確認
    required = ['sender', 'recipient', 'amount']
    if not all(k in values for k in required):
        return 'Missing values', 400

    # 新しいトランザクションを作る
    index = bc.new_transaction(values['sender'], values['recipient'],
                               values['amount'])

    res = {
        'message': f'トランザクションはブロック {index} に追加されました',
    }
    return jsonify(res), 201


@app.route('/mine')