예제 #1
0
class TestMasterStorage(TestCase):
    def setUp(self):
        self.db = BlockStorage()

    def tearDown(self):
        self.db.drop_collections()

    def test_init(self):
        self.assertTrue(self.db)

    def test_q_num(self):
        q = self.db.q(1)

        self.assertEqual(q, {'number': 1})

    def test_q_hash(self):
        q = self.db.q('1')

        self.assertEqual(q, {'hash': '1'})

    def test_put_block(self):
        block = {'hash': 'a', 'number': 1, 'data': 'woop'}

        _id = self.db.put(block)

        self.assertTrue(_id)

    def test_get_block(self):
        block = {'hash': 'a', 'number': 1, 'data': 'woop'}

        _id = self.db.put(block)

        self.assertTrue(_id)

        got_block = self.db.get_block(1)

        self.assertEqual(block, got_block)

    def test_get_block_hash(self):
        block = {'hash': 'a', 'number': 1, 'data': 'woop'}

        _id = self.db.put(block)

        self.assertTrue(_id)

        got_block = self.db.get_block('a')

        self.assertEqual(block, got_block)

    def test_get_none_block(self):
        block = {'hash': 'a', 'number': 1, 'data': 'woop'}

        _id = self.db.put(block)

        self.assertTrue(_id)

        got_block = self.db.get_block('b')

        self.assertIsNone(got_block)

    def test_got_none_block_num(self):
        block = {'hash': 'a', 'number': 1, 'data': 'woop'}

        _id = self.db.put(block)

        self.assertTrue(_id)

        got_block = self.db.get_block(2)

        self.assertIsNone(got_block)

    def test_drop_collections_block(self):
        block = {'hash': 'a', 'number': 1, 'data': 'woop'}

        _id = self.db.put(block)

        self.assertTrue(_id)

        self.db.drop_collections()

        got_block = self.db.get_block(1)

        self.assertIsNone(got_block)

    def test_put_other(self):
        index = {'hash': 'a', 'number': 1, 'blockOwners': 'stu'}

        _id = self.db.put(index, 999)

        self.assertFalse(_id)

    def test_get_last_n_blocks(self):
        blocks = []

        blocks.append({'hash': 'a', 'number': 1, 'data': 'woop'})
        blocks.append({'hash': 'a', 'number': 2, 'data': 'woop'})
        blocks.append({'hash': 'a', 'number': 3, 'data': 'woop'})
        blocks.append({'hash': 'a', 'number': 4, 'data': 'woop'})
        blocks.append({'hash': 'a', 'number': 5, 'data': 'woop'})

        for block in blocks:
            self.db.put(block)

        got_blocks = self.db.get_last_n(3, BlockStorage.BLOCK)

        nums = [b['number'] for b in got_blocks]

        self.assertEqual(nums, [5, 4, 3])

    def test_get_last_n_index(self):
        blocks = []

        blocks.append({'hash': 'a', 'number': 1, 'data': 'woop'})
        blocks.append({'hash': 'a', 'number': 2, 'data': 'woop'})
        blocks.append({'hash': 'a', 'number': 3, 'data': 'woop'})
        blocks.append({'hash': 'a', 'number': 4, 'data': 'woop'})
        blocks.append({'hash': 'a', 'number': 5, 'data': 'woop'})

        for block in blocks:
            self.db.put(block, BlockStorage.BLOCK)

        got_blocks = self.db.get_last_n(3, BlockStorage.BLOCK)

        nums = [b['number'] for b in got_blocks]

        self.assertEqual(nums, [5, 4, 3])

    def test_get_none_from_wrong_n_collection(self):
        blocks = []

        blocks.append({'hash': 'a', 'number': 1, 'data': 'woop'})
        blocks.append({'hash': 'a', 'number': 2, 'data': 'woop'})
        blocks.append({'hash': 'a', 'number': 3, 'data': 'woop'})
        blocks.append({'hash': 'a', 'number': 4, 'data': 'woop'})
        blocks.append({'hash': 'a', 'number': 5, 'data': 'woop'})

        for block in blocks:
            self.db.put(block, BlockStorage.BLOCK)

        got_blocks = self.db.get_last_n(3, 5)

        self.assertIsNone(got_blocks)

    def test_store_and_get_tx(self):
        tx = {'hash': 'something', 'key': 'value'}

        self.db.put(tx, BlockStorage.TX)

        tx_got = self.db.get_tx(h='something')

        self.assertDictEqual(tx, tx_got)

    def test_get_non_existant_tx_returns_none(self):
        tx_got = self.db.get_tx(h='something')

        self.assertIsNone(tx_got)

    def test_store_txs_from_block_adds_all_txs(self):
        tx_1 = {'hash': 'something1', 'key': '1'}

        tx_2 = {'hash': 'something2', 'key': '2'}

        tx_3 = {'hash': 'something3', 'key': '3'}

        block = {'subblocks': [{'transactions': [tx_1, tx_2, tx_3]}]}

        self.db.store_txs(block)

        got_1 = self.db.get_tx(h='something1')
        got_2 = self.db.get_tx(h='something2')
        got_3 = self.db.get_tx(h='something3')

        self.assertDictEqual(tx_1, got_1)
        self.assertDictEqual(tx_2, got_2)
        self.assertDictEqual(tx_3, got_3)

    def test_store_block_stores_txs_and_block(self):
        tx_1 = {'hash': 'something1', 'key': '1'}

        tx_2 = {'hash': 'something2', 'key': '2'}

        tx_3 = {'hash': 'something3', 'key': '3'}

        block = {
            'hash': 'hello',
            'subblocks': [{
                'transactions': [tx_1, tx_2, tx_3]
            }]
        }

        self.db.store_block(block)

        got_1 = self.db.get_tx(h='something1')
        got_2 = self.db.get_tx(h='something2')
        got_3 = self.db.get_tx(h='something3')

        self.assertDictEqual(tx_1, got_1)
        self.assertDictEqual(tx_2, got_2)
        self.assertDictEqual(tx_3, got_3)

        got_block = self.db.get_block('hello')

        self.assertDictEqual(block, got_block)

    def test_get_block_v_none_returns_none(self):
        self.assertIsNone(self.db.get_block())

    def test_delete_tx(self):
        t = self.db.get_tx(h='something')

        self.assertIsNone(t)

        tx = {'hash': 'something', 'key': 'value'}

        self.db.put(tx, BlockStorage.TX)

        t = self.db.get_tx(h='something')

        self.assertIsNotNone(t)

        self.db.delete_tx(h='something')

        t = self.db.get_tx(h='something')

        self.assertIsNone(t)

    def test_return_id_noid_false_block(self):
        block = {'hash': 'a', 'number': 1, 'data': 'woop'}

        self.db.put(block)

        b = self.db.get_block('a', no_id=False)

        self.assertIsNotNone(b.get('_id'))

        b = self.db.get_block('a')

        self.assertIsNone(b.get('_id'))

    def test_return_id_noid_false_tx(self):
        tx = {'hash': 'something', 'key': 'value'}

        self.db.put(tx, BlockStorage.TX)

        t = self.db.get_tx(h='something', no_id=False)

        self.assertIsNotNone(t.get('_id'))

        t = self.db.get_tx(h='something', no_id=True)

        self.assertIsNone(t.get('_id'))

    def test_delete_block_deletes_block(self):
        tx_1 = {'hash': 'something1', 'key': '1'}

        tx_2 = {'hash': 'something2', 'key': '2'}

        tx_3 = {'hash': 'something3', 'key': '3'}

        block = {
            'hash': 'hello',
            'subblocks': [{
                'transactions': [tx_1, tx_2, tx_3]
            }]
        }

        self.db.store_block(block)

        got_1 = self.db.get_tx(h='something1')
        got_2 = self.db.get_tx(h='something2')
        got_3 = self.db.get_tx(h='something3')

        self.assertDictEqual(tx_1, got_1)
        self.assertDictEqual(tx_2, got_2)
        self.assertDictEqual(tx_3, got_3)

        got_block = self.db.get_block('hello')

        self.assertDictEqual(block, got_block)

        self.db.delete_block(v='hello')

        self.assertIsNone(self.db.get_block(v='hello'))

    def test_delete_block_deletes_txs(self):
        tx_1 = {'hash': 'something1', 'key': '1'}

        tx_2 = {'hash': 'something2', 'key': '2'}

        tx_3 = {'hash': 'something3', 'key': '3'}

        block = {
            'hash': 'hello',
            'subblocks': [{
                'transactions': [tx_1, tx_2, tx_3]
            }]
        }

        self.db.store_block(block)

        got_1 = self.db.get_tx(h='something1')
        got_2 = self.db.get_tx(h='something2')
        got_3 = self.db.get_tx(h='something3')

        self.assertDictEqual(tx_1, got_1)
        self.assertDictEqual(tx_2, got_2)
        self.assertDictEqual(tx_3, got_3)

        got_block = self.db.get_block('hello')

        self.assertDictEqual(block, got_block)

        self.db.delete_block(v='hello')

        got_1 = self.db.get_tx(h='something1')
        got_2 = self.db.get_tx(h='something2')
        got_3 = self.db.get_tx(h='something3')

        self.assertIsNone(got_1)
        self.assertIsNone(got_2)
        self.assertIsNone(got_3)
예제 #2
0
class TestClassWebserver(TestCase):
    def setUp(self):
        self.w = Wallet()

        self.blocks = BlockStorage()
        # self.block_writer = BlockStorage()
        self.driver = ContractDriver()

        self.ws = WebServer(wallet=self.w,
                            contracting_client=ContractingClient(),
                            blocks=self.blocks,
                            driver=n)

        self.ws.client.flush()
        self.blocks.flush()
        self.ws.driver.flush()
        self.loop = asyncio.get_event_loop()

    def tearDown(self):
        self.ws.client.flush()
        self.blocks.flush()
        self.ws.driver.flush()

    def test_ping(self):
        _, response = self.ws.app.test_client.get('/ping')
        self.assertDictEqual(response.json, {'status': 'online'})

    def test_get_id(self):
        _, response = self.ws.app.test_client.get('/id')
        self.assertDictEqual(response.json,
                             {'verifying_key': self.w.verifying_key})

    def test_get_nonce_pending_nonce_is_none_returns_0(self):
        w2 = Wallet()
        _, response = self.ws.app.test_client.get('/nonce/{}'.format(
            w2.verifying_key))

        expected = {
            'nonce': 0,
            'processor': self.w.verifying_key,
            'sender': w2.verifying_key
        }

        self.assertDictEqual(response.json, expected)

    def test_get_nonce_pending_nonce_is_not_none_returns_pending_nonce(self):
        w2 = Wallet()

        self.ws.nonces.set_pending_nonce(sender=w2.verifying_key,
                                         processor=self.w.verifying_key,
                                         value=123)

        _, response = self.ws.app.test_client.get('/nonce/{}'.format(
            w2.verifying_key))

        expected = {
            'nonce': 123,
            'processor': self.w.verifying_key,
            'sender': w2.verifying_key
        }

        self.assertDictEqual(response.json, expected)

    def test_get_nonce_pending_nonce_is_none_but_nonce_is_not_returns_nonce(
            self):
        w2 = Wallet()

        self.ws.nonces.set_nonce(processor=self.w.verifying_key,
                                 sender=w2.verifying_key,
                                 value=555)

        _, response = self.ws.app.test_client.get('/nonce/{}'.format(
            w2.verifying_key))

        expected = {
            'nonce': 555,
            'processor': self.w.verifying_key,
            'sender': w2.verifying_key
        }

        self.assertDictEqual(response.json, expected)

    def test_get_contracts_returns_list_of_contracts(self):
        _, response = self.ws.app.test_client.get('/contracts')

        self.assertDictEqual(response.json, {'contracts': ['submission']})

    def test_get_contract_returns_contract_code(self):
        _, response = self.ws.app.test_client.get('/contracts/submission')

        f = open(self.ws.client.submission_filename)
        code = f.read()
        f.close()

        expected = {'name': 'submission', 'code': code}

        self.assertDictEqual(response.json, expected)

    def test_get_contract_that_does_not_exist_returns_error(self):
        _, response = self.ws.app.test_client.get('/contracts/blah')

        self.assertDictEqual(response.json, {'error': 'blah does not exist'})

    def test_get_contract_methods_returns_all_methods(self):
        _, response = self.ws.app.test_client.get(
            '/contracts/submission/methods')

        self.assertDictEqual(
            response.json, {
                'methods': [{
                    'name':
                    'submit_contract',
                    'arguments': [{
                        'name': 'name',
                        'type': 'str'
                    }, {
                        'name': 'code',
                        'type': 'str'
                    }, {
                        'name': 'owner',
                        'type': 'Any'
                    }, {
                        'name': 'constructor_args',
                        'type': 'dict'
                    }]
                }]
            })

    def test_get_contract_method_returns_error_if_does_not_exist(self):
        _, response = self.ws.app.test_client.get('/contracts/blah/methods')

        self.assertDictEqual(response.json, {'error': 'blah does not exist'})

    def test_get_variable_returns_value_if_it_exists(self):
        code = '''
v = Variable()

@construct
def seed():
    v.set(12345)

@export
def get():
    return v.get()
        '''

        self.ws.client.submit(f=code, name='testing')

        _, response = self.ws.app.test_client.get('/contracts/testing/v')

        self.assertDictEqual(response.json, {'value': 12345})

    def test_get_variables_returns_variable_list(self):
        code = '''
v = Variable()
howdy = Variable()
h = Hash()
hash2 = Hash()

@construct
def seed():
    a = 123
    v.set(12345)

@export
def get():
    return v.get()
        '''

        self.ws.client.submit(f=code, name='testing')

        _, response = self.ws.app.test_client.get(
            '/contracts/testing/variables')

        expected = {'variables': ['v', 'howdy'], 'hashes': ['h', 'hash2']}

        self.assertDictEqual(response.json, expected)

    def test_get_variables_returns_error_if_contract_does_not_exist(self):
        _, response = self.ws.app.test_client.get('/contracts/blah/variables')

        self.assertDictEqual(response.json, {'error': 'blah does not exist'})

    def test_get_variable_returns_error_if_contract_does_not_exist(self):
        _, response = self.ws.app.test_client.get('/contracts/blah/v')

        self.assertDictEqual(response.json, {'error': 'blah does not exist'})

    def test_get_variable_returns_none_if_variable_does_not_exist(self):
        code = '''
v = Variable()

@construct
def seed():
    v.set(12345)

@export
def get():
    return v.get()
        '''

        self.ws.client.submit(f=code, name='testing')

        _, response = self.ws.app.test_client.get('/contracts/testing/x')

        self.assertDictEqual(response.json, {'value': None})

    def test_get_variable_works_for_single_key(self):
        code = '''
h = Hash()

@construct
def seed():
    h['stu'] = 99999

@export
def get():
    return h['stu']
        '''

        self.ws.client.submit(f=code, name='testing')

        _, response = self.ws.app.test_client.get(
            '/contracts/testing/h?key=stu')

        self.assertDictEqual(response.json, {'value': 99999})

    def test_get_variable_works_for_multihashes(self):
        code = '''
h = Hash()

@construct
def seed():
    h['stu'] = 99999
    h['stu', 'hello', 'jabroni'] = 77777

@export
def get():
    return h['stu']
        '''

        self.ws.client.submit(f=code, name='testing')

        _, response = self.ws.app.test_client.get(
            '/contracts/testing/h?key=stu,hello,jabroni')

        self.assertDictEqual(response.json, {'value': 77777})

    def test_get_variable_multihash_returns_none(self):
        code = '''
h = Hash()

@construct
def seed():
    h['stu'] = 99999
    h['stu', 'hello', 'jabroni'] = 77777

@export
def get():
    return h['stu']
        '''

        self.ws.client.submit(f=code, name='testing')

        _, response = self.ws.app.test_client.get(
            '/contracts/testing/h?key=notstu,hello,jabroni')

        self.assertDictEqual(response.json, {'value': None})

        _, response = self.ws.app.test_client.get(
            '/contracts/testing/h?key=notstu')

        self.assertDictEqual(response.json, {'value': None})

    def test_get_latest_block(self):
        block = {'hash': 'a', 'number': 1, 'data': 'woop'}

        self.blocks.put(block)

        block2 = {'hash': 'abb', 'number': 1000, 'data': 'woop2'}

        self.blocks.put(block2)

        _, response = self.ws.app.test_client.get('/latest_block')
        self.assertDictEqual(response.json, {
            'hash': 'abb',
            'number': 1000,
            'data': 'woop2'
        })

    def test_get_latest_block_num(self):
        storage.set_latest_block_height(1234, self.ws.driver)

        _, response = self.ws.app.test_client.get('/latest_block_num')
        self.assertDictEqual(response.json, {'latest_block_number': 1234})

    def test_get_latest_block_hash(self):
        h = '0' * 64
        storage.set_latest_block_hash(h, self.ws.driver)

        _, response = self.ws.app.test_client.get('/latest_block_hash')

        self.assertDictEqual(response.json, {'latest_block_hash': h})

    def test_get_block_by_num_that_exists(self):
        block = {'hash': '1234', 'number': 1, 'data': 'woop'}

        self.blocks.put(block)

        _, response = self.ws.app.test_client.get('/blocks?num=1')

        self.assertDictEqual(response.json, block)

    def test_get_block_by_num_that_doesnt_exist_returns_error(self):
        _, response = self.ws.app.test_client.get('/blocks?num=1000')

        self.assertDictEqual(response.json, {'error': 'Block not found.'})

    def test_get_block_by_hash_that_exists(self):
        h = '1234'

        block = {'hash': h, 'blockNum': 1, 'data': 'woop'}

        self.blocks.put(block)

        expected = {'hash': h, 'blockNum': 1, 'data': 'woop'}

        _, response = self.ws.app.test_client.get(f'/blocks?hash={h}')
        self.assertDictEqual(response.json, expected)

    def test_get_block_by_hash_that_doesnt_exist_returns_error(self):
        _, response = self.ws.app.test_client.get('/blocks?hash=zzz')
        self.assertDictEqual(response.json, {'error': 'Block not found.'})

    def test_get_block_no_args_returns_error(self):
        _, response = self.ws.app.test_client.get('/blocks')
        self.assertDictEqual(response.json,
                             {'error': 'No number or hash provided.'})

    def test_bad_transaction_returns_a_TransactionException(self):
        tx = build_transaction(wallet=Wallet(),
                               processor='b' * 64,
                               stamps=123,
                               nonce=0,
                               contract='currency',
                               function='transfer',
                               kwargs={
                                   'amount': 123,
                                   'to': 'jeff'
                               })
        _, response = self.ws.app.test_client.post('/', data=tx)
        self.assertDictEqual(response.json, {
            'error':
            'Transaction processor does not match expected processor.'
        })

    def test_good_transaction_is_put_into_queue(self):
        self.assertEqual(len(self.ws.queue), 0)

        w = Wallet()

        self.ws.client.set_var(contract='currency',
                               variable='balances',
                               arguments=[w.verifying_key],
                               value=1_000_000)

        self.ws.client.set_var(contract='stamp_cost',
                               variable='S',
                               arguments=['value'],
                               value=1_000_000)

        tx = build_transaction(wallet=w,
                               processor=self.ws.wallet.verifying_key,
                               stamps=6000,
                               nonce=0,
                               contract='currency',
                               function='transfer',
                               kwargs={
                                   'amount': 123,
                                   'to': 'jeff'
                               })

        _, response = self.ws.app.test_client.post('/', data=tx)

        self.assertEqual(len(self.ws.queue), 1)

    def test_fixed_objects_do_not_fail_signature(self):
        self.assertEqual(len(self.ws.queue), 0)

        w = Wallet()

        self.ws.client.set_var(contract='currency',
                               variable='balances',
                               arguments=[w.verifying_key],
                               value=1_000_000)

        self.ws.client.set_var(contract='stamp_cost',
                               variable='S',
                               arguments=['value'],
                               value=1_000_000)

        tx = build_transaction(wallet=w,
                               processor=self.ws.wallet.verifying_key,
                               stamps=6000,
                               nonce=0,
                               contract='currency',
                               function='transfer',
                               kwargs={
                                   'amount': {
                                       '__fixed__': '1.0'
                                   },
                                   'to': 'jeff'
                               })

        _, response = self.ws.app.test_client.post('/', data=tx)

        self.assertEqual(len(self.ws.queue), 1)

    def test_submit_transaction_error_if_queue_full(self):
        self.ws.queue.extend(range(10_000))

        tx = build_transaction(wallet=Wallet(),
                               processor=self.ws.wallet.verifying_key,
                               stamps=123,
                               nonce=0,
                               contract='currency',
                               function='transfer',
                               kwargs={
                                   'amount': 123,
                                   'to': 'jeff'
                               })

        _, response = self.ws.app.test_client.post('/', data=tx)

        self.assertDictEqual(response.json,
                             {'error': 'Queue full. Resubmit shortly.'})

        self.ws.queue.clear()

    def test_get_tx_by_hash_if_it_exists(self):
        b = '0' * 64

        tx = {'hash': b, 'some': 'data'}

        expected = {'hash': b, 'some': 'data'}

        self.blocks.put(tx, collection=self.ws.blocks.TX)

        _, response = self.ws.app.test_client.get(f'/tx?hash={b}')
        self.assertDictEqual(response.json, expected)

    def test_malformed_tx_returns_error(self):
        tx = b'"df:'

        _, response = self.ws.app.test_client.post('/', data=tx)

        self.assertDictEqual(response.json,
                             {'error': 'Malformed request body.'})

    def test_tx_with_error_returns_exception(self):
        tx = build_transaction(wallet=Wallet(),
                               processor=self.ws.wallet.verifying_key,
                               stamps=123,
                               nonce=0,
                               contract='currency',
                               function='transfer',
                               kwargs={
                                   'amount': 123,
                                   'to': 'jeff'
                               })

        tx = decode(tx)
        tx['payload']['stamps_supplied'] = -123
        tx = encode(tx)

        _, response = self.ws.app.test_client.post('/', data=tx)

        self.assertDictEqual(
            response.json, {'error': 'Transaction is not formatted properly.'})

    def test_get_constitution_returns_correct_state(self):
        self.ws.client.set_var(contract='masternodes',
                               variable='S',
                               arguments=['members'],
                               value=['1', '2', '3'])

        self.ws.client.set_var(contract='delegates',
                               variable='S',
                               arguments=['members'],
                               value=['4', '5', '6'])

        self.ws.client.raw_driver.commit()

        _, response = self.ws.app.test_client.get('/constitution')

        self.assertDictEqual(response.json, {
            'masternodes': ['1', '2', '3'],
            'delegates': ['4', '5', '6'],
        })

    def test_error_returned_if_tx_hash_not_provided(self):
        _, response = self.ws.app.test_client.get('/tx')

        self.assertDictEqual(response.json, {'error': 'No tx hash provided.'})

    def test_error_returned_if_tx_hash_malformed(self):
        _, response = self.ws.app.test_client.get('/tx?hash=hello')

        self.assertDictEqual(response.json, {'error': 'Malformed hash.'})

    def test_error_returned_if_no_tx_hash(self):
        _, response = self.ws.app.test_client.get('/tx?hash=' + 'a' * 64)

        self.assertDictEqual(response.json,
                             {'error': 'Transaction not found.'})

    def test_js_encoded_tx_works(self):
        pass