コード例 #1
0
    def test_signing_key_as_bytes(self):
        w = Wallet()

        _w = w.signing_key()

        self.assertTrue(isinstance(_w, bytes))

        _h = w.signing_key(as_hex=True)

        self.assertTrue(isinstance(_h, str))
コード例 #2
0
    def test_nonce_minus_pending_nonce_equal_tx_per_block_fails(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        self.nonce_manager.set_nonce(processor=expected_processor, sender=w.verifying_key(), nonce=1)
        self.nonce_manager.set_pending_nonce(processor=expected_processor, sender=w.verifying_key(), nonce=16)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=16)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionTooManyPendingException):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)
コード例 #3
0
    def test_submission_prepended_with_con_succeeds(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='submission',
                                function='submit_contract',
                                kwargs={'name': 'con_bad_name', 'code': 'blah'},
                                stamps=3000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)
コード例 #4
0
def make_tx(processor, contract_name, function_name, kwargs={}):
    w = Wallet()
    batch = TransactionBuilder(sender=w.verifying_key(),
                               contract=contract_name,
                               function=function_name,
                               kwargs=kwargs,
                               stamps=10000,
                               processor=processor,
                               nonce=0)

    batch.sign(w.signing_key())
    b = batch.serialize()

    tx = transaction_capnp.Transaction.from_bytes_packed(b)

    currency_contract = 'currency'
    balances_hash = 'balances'

    balances_key = '{}{}{}{}{}'.format(currency_contract,
                                       config.INDEX_SEPARATOR, balances_hash,
                                       config.DELIMITER,
                                       w.verifying_key().hex())

    driver = ContractDriver()
    driver.set(balances_key, 1_000_000)
    driver.commit()

    return tx
コード例 #5
0
    def test_all_valid_with_stamps_when_balance_is_set(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           tx.payload.sender.hex())

        self.nonce_manager.set(balances_key, 500000)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)
        balance = self.nonce_manager.get(balances_key) or 0

        self.assertEqual(balance, 500000)
コード例 #6
0
    def test_processor_and_nonce_correct_but_not_enough_stamps_returns_false(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionSenderTooFewStamps):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           tx.payload.sender.hex())

        balance = self.nonce_manager.get(balances_key) or 0

        self.assertEqual(balance, 0)
コード例 #7
0
    def test_init_wallet_with_seed_returns_deterministic_wallet(self):
        w = Wallet()

        a = Wallet(seed=w.signing_key())

        self.assertEqual(w.vk, a.vk)
        self.assertEqual(w.sk, a.sk)
コード例 #8
0
def random_packed_tx(nonce=0, processor=None, give_stamps=False):
    w = Wallet()

    processor = secrets.token_bytes(32) if processor is None else processor
    stamps = random.randint(100_000, 1_000_000)

    if give_stamps:
        balances_key = '{}{}{}{}{}'.format('currency', config.INDEX_SEPARATOR,
                                           'balances', config.DELIMITER,
                                           w.verifying_key().hex())

        N.set(balances_key, stamps + 1000)

    tx = TransactionBuilder(
        w.verifying_key(),
        contract=secrets.token_hex(8),
        function=secrets.token_hex(8),
        kwargs={secrets.token_hex(8): secrets.token_hex(8)},
        stamps=stamps,
        processor=processor,
        nonce=nonce)

    tx.sign(w.signing_key())

    #tx.proof = b'\x00' * 32
    #tx.proof_generated = True

    packed_tx = transaction_capnp.Transaction.from_bytes_packed(tx.serialize())
    return packed_tx
コード例 #9
0
    def test_sending_transfer_of_most_money_doesnt_fail_if_enough_stamps(self):
        self.nonce_manager.set_var('stamp_cost', 'S', ['value'], value=3000)

        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)
        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 499990, 'to': 'jeff'},
                                stamps=3000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)
コード例 #10
0
def build_nodes(num_nodes=1) -> list:
    nodes = []
    for i in range(num_nodes):
        i = Wallet()
        nodes.append({
            'sk': i.signing_key(as_hex=True),
            'vk': i.verifying_key(as_hex=True)
        })

    print(nodes)
コード例 #11
0
    def test_non_strict_fails_if_same_nonce(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager,
                             strict=False)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionNonceInvalid):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager,
                                 strict=False)
コード例 #12
0
def get_tx_batch():
    w = Wallet()
    tx = TransactionBuilder(
        sender='stu',
        contract='testing',
        function='set',
        kwargs={'var': 'howdy'},
        stamps=100_000,
        processor=b'\x00' * 32,
        nonce=0
    )
    tx.sign(w.signing_key())
    tx.serialize()

    currency_contract = 'currency'
    balances_hash = 'balances'

    balances_key = '{}{}{}{}{}'.format(currency_contract,
                                       config.INDEX_SEPARATOR,
                                       balances_hash,
                                       config.DELIMITER,
                                       w.verifying_key().hex())

    driver = BlockchainDriver()
    driver.set(balances_key, 1_000_000)
    driver.commit()

    w = Wallet()
    tx2 = TransactionBuilder(
        sender='stu',
        contract='testing',
        function='get',
        kwargs={},
        stamps=100_000,
        processor=b'\x00' * 32,
        nonce=0
    )
    tx2.sign(Wallet().signing_key())
    tx2.serialize()

    currency_contract = 'currency'
    balances_hash = 'balances'

    balances_key = '{}{}{}{}{}'.format(currency_contract,
                                       config.INDEX_SEPARATOR,
                                       balances_hash,
                                       config.DELIMITER,
                                       w.verifying_key().hex())

    driver = BlockchainDriver()
    driver.set(balances_key, 1_000_000)
    driver.commit()

    return transaction_list_to_transaction_batch([tx.struct, tx2.struct], wallet=Wallet())
コード例 #13
0
    def test_serialize_returns_bytes(self):
        w = Wallet()
        tx = TransactionBuilder(sender=w.verifying_key().hex(),
                                stamps=1000000,
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 'b'},
                                processor=b'\x00'*32,
                                nonce=0)

        tx.sign(w.signing_key())

        tx_packed = tx.serialize()

        self.assertTrue(verify_packed_tx(w.verifying_key(), tx_packed))
コード例 #14
0
    def test_signing_flips_true(self):
        w = Wallet()
        tx = TransactionBuilder(sender=w.verifying_key().hex(),
                                stamps=1000000,
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 'b'},
                                processor=b'\x00'*32,
                                nonce=0)

        self.assertFalse(tx.tx_signed)

        tx.sign(w.signing_key())

        self.assertTrue(tx.tx_signed)
コード例 #15
0
    def setUp(self):
        #m, d = sync.get_masternodes_and_delegates_from_constitution()
        self.client = ContractingClient()
        self.client.flush()
        sync.submit_from_genesis_json_file(cilantro_ee.contracts.__path__[0] +
                                           '/genesis.json',
                                           client=self.client)
        sync.submit_node_election_contracts(
            initial_masternodes=Wallet().verifying_key().hex(),
            boot_mns=1,
            initial_delegates=Wallet().verifying_key().hex(),
            boot_dels=1,
            client=self.client)

        w = Wallet()
        sk, vk = w.signing_key(), w.verifying_key()
        self.db = DistributedMasterStorage(key=sk,
                                           vkbook=VKBook(self.client, 1, 1))
コード例 #16
0
    def test_processor_is_expected_but_nonce_is_incorrect_returns_false(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=1)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionNonceInvalid):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)
コード例 #17
0
ファイル: test_processor.py プロジェクト: qiygan/mockchain
class TestProcessor(TestCase):
    def setUp(self):
        self.wallet = Wallet()
        self.client = ContractingClient()
        sync.submit_from_genesis_json_file(cilantro_ee.contracts.__path__[0] +
                                           '/genesis.json',
                                           client=ContractingClient())

        processor.mint(self.wallet.vk.encode().hex(), 1000000000)
        self.currency = self.client.get_contract('currency')

        bal = self.currency.quick_read(variable='balances',
                                       key=self.wallet.vk.encode().hex())
        self.assertEqual(bal, 1000000000)

    def tearDown(self):
        self.client.flush()

    def test_process_good_tx(self):
        txb = TransactionBuilder(self.wallet.verifying_key(),
                                 contract='currency',
                                 function='transfer',
                                 kwargs={
                                     'to': 'jeff',
                                     'amount': 10000
                                 },
                                 stamps=100000,
                                 processor=b'\x00' * 32,
                                 nonce=0)

        txb.sign(self.wallet.signing_key())
        tx_bytes = txb.serialize()

        tx = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)
        print(tx)

        results = processor.process_transaction(tx)

        balance_from = results['state_changes']['currency.balances:{}'.format(
            self.wallet.vk.encode().hex())]
        balance_jeff = results['state_changes']['currency.balances:jeff']

        self.assertEqual(float(balance_from), 1000000000 - 10000)
        self.assertEqual(float(balance_jeff), 10000)
コード例 #18
0
def make_good_tx(processor):
    w = Wallet()
    balances_key = '{}{}{}{}{}'.format('currency', config.INDEX_SEPARATOR,
                                       'balances', config.DELIMITER,
                                       w.verifying_key().hex())
    n.set(balances_key, 500000)
    tx = TransactionBuilder(w.verifying_key(),
                            contract='currency',
                            function='transfer',
                            kwargs={
                                'amount': 10,
                                'to': 'jeff'
                            },
                            stamps=500000,
                            processor=processor,
                            nonce=0)

    tx.sign(w.signing_key())
    tx_bytes = tx.serialize()
    return tx_bytes
コード例 #19
0
def make_bad_tx():
    w = Wallet()
    balances_key = '{}{}{}{}{}'.format('currency', config.INDEX_SEPARATOR,
                                       'balances', config.DELIMITER,
                                       w.verifying_key().hex())
    n.set(balances_key, 500000)
    tx = TransactionBuilder(w.verifying_key(),
                            contract='currency',
                            function='transfer',
                            kwargs={
                                'amount': 10,
                                'to': 'jeff'
                            },
                            stamps=500000,
                            processor=b'\x00' * 32,
                            nonce=0)

    tx.sign(w.signing_key())
    tx_bytes = tx.serialize()
    #tx_struct = transaction_capnp.Transaction.from_bytes_packed(tx_bytes)
    return tx_bytes
コード例 #20
0
    def test_processor_and_nonce_correct_increments_pending_nonce_by_one(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=10000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        pending_nonce = self.nonce_manager.get_pending_nonce(expected_processor, w.verifying_key())

        self.assertEqual(pending_nonce, 1)
コード例 #21
0
    def test_send_to_delegates_doesnt_hang_if_one_is_not_online(self):
        bootnodes = ['ipc:///tmp/n2', 'ipc:///tmp/n3']

        mnw1 = Wallet()
        mnw2 = Wallet()

        dw1 = Wallet()
        dw2 = Wallet()
        dw3 = Wallet()
        dw4 = Wallet()

        constitution = {
            "masternodes": {
                "vk_list": [
                    mnw1.verifying_key().hex(),
                    mnw2.verifying_key().hex()
                ],
                "min_quorum": 1
            },
            "delegates": {
                "vk_list": [
                    dw1.verifying_key().hex(),
                    dw2.verifying_key().hex(),
                    dw3.verifying_key().hex(),
                    dw4.verifying_key().hex()
                ],
                "min_quorum": 1
            },
            "witnesses": {},
            "schedulers": {},
            "notifiers": {},
            "enable_stamps": False,
            "enable_nonces": False
        }

        n1 = '/tmp/n1'
        make_ipc(n1)
        mn1 = Masternode(wallet=mnw1, ctx=self.ctx, socket_base=f'ipc://{n1}', bootnodes=bootnodes,
                         constitution=constitution, webserver_port=8080, overwrite=True)

        masternodes = [mnw1.verifying_key().hex(), mnw2.verifying_key().hex()]
        delegates = [dw1.verifying_key().hex(), dw2.verifying_key().hex(), dw3.verifying_key().hex(),
                     dw4.verifying_key().hex()]

        contacts = MockContacts(
            masters=masternodes,
            delegates=delegates
        )

        d1 = '/tmp/d1'
        make_ipc(d1)
        wi1 = WorkInbox(socket_id=_socket(f'ipc://{d1}/incoming_work'), ctx=self.ctx, contacts=contacts, verify=False)

        d2 = '/tmp/d2'
        make_ipc(d2)
        wi2 = WorkInbox(socket_id=_socket(f'ipc://{d2}/incoming_work'), ctx=self.ctx, contacts=contacts, verify=False)

        d3 = '/tmp/d3'
        make_ipc(d3)
        #wi3 = WorkInbox(socket_id=_socket(f'ipc://{d3}/incoming_work'), ctx=self.ctx, contacts=contacts, verify=False)

        d4 = '/tmp/d4'
        make_ipc(d4)
        wi4 = WorkInbox(socket_id=_socket(f'ipc://{d4}/incoming_work'), ctx=self.ctx, contacts=contacts, verify=False)

        w = Wallet()
        batch = TransactionBuilder(
            sender=w.verifying_key(),
            contract='test',
            function='testing',
            kwargs={},
            stamps=1_000_000,
            processor=mnw1.verifying_key(),
            nonce=0
        )

        batch.sign(w.signing_key())
        b = batch.serialize()

        tx = transaction_capnp.Transaction.from_bytes_packed(b)

        currency_contract = 'currency'
        balances_hash = 'balances'

        balances_key = '{}{}{}{}{}'.format(currency_contract,
                                           config.INDEX_SEPARATOR,
                                           balances_hash,
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        driver = BlockchainDriver()
        driver.set(balances_key, 1_000_000)
        driver.commit()

        mn1.tx_batcher.queue.append(tx)

        mn1.network.peer_service.table.peers = {
            dw1.verifying_key().hex(): f'ipc://{d1}',
            dw2.verifying_key().hex(): f'ipc://{d2}',
            dw3.verifying_key().hex(): f'ipc://{d3}',
            dw4.verifying_key().hex(): f'ipc://{d4}'
        }

        async def late_send():
            await asyncio.sleep(0.3)
            await mn1.parameters.refresh()
            return await mn1.send_batch_to_delegates()

        async def stop():
            await asyncio.sleep(0.5)
            wi1.stop()
            wi2.stop()
            wi4.stop()
            mn1.network.stop()

        tasks = asyncio.gather(
            mn1.network.start(False),
            wi1.serve(),
            wi2.serve(),
            wi4.serve(),
            late_send(),
            stop()
        )

        _, _, _, _, r, _ = self.loop.run_until_complete(tasks)

        # Make sure the right socket failed
        for rr in r:
            if not rr[0]:
                self.assertEqual(rr[1], f'ipc://{d3}/incoming_work')

        self.assertTrue(wi1.work[mnw1.verifying_key().hex()])
        self.assertTrue(wi2.work[mnw1.verifying_key().hex()])
        self.assertTrue(wi4.work[mnw1.verifying_key().hex()])
コード例 #22
0
 def setUp(self):
     w = Wallet()
     self.sk, self.vk = w.signing_key(), w.verifying_key()
     self.db = MasterStorage()
コード例 #23
0
    def test_multiple_nonces_in_sequence_all_verify(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=1)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=2)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=3)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)
コード例 #24
0
class DistributedMasterStorage(MasterStorage):
    def __init__(self,
                 key,
                 distribute_writes=False,
                 config_path=cilantro_ee.__path__[0],
                 vkbook=None):
        super().__init__(config_path=config_path)

        self.distribute_writes = distribute_writes
        self.vkbook = vkbook

        self.wallet = Wallet(seed=key)

        self.sk = self.wallet.signing_key()
        self.vk = self.wallet.verifying_key()

        self.test_hook = False
        self.mn_id = 1
        self.rep_factor = 3
        self.active_masters = 12
        self.quorum_needed = 3

    def get_master_set(self):
        if self.test_hook is True:
            return self.active_masters
        else:
            self.active_masters = len(self.vkbook.masternodes)
            return self.active_masters

    def set_mn_id(self, vk):
        if self.test_hook is True:
            return self.mn_id

        # this should be rewritten to just pull from Phonebook because it's dynamic now

        for i in range(self.get_master_set()):
            if self.vkbook.masternodes[i] == vk:
                self.mn_id = i
                return True
            else:
                self.mn_id = -1
                return False

    def rep_pool_sz(self):
        if self.active_masters < self.rep_factor:
            return -1

        self.active_masters = self.get_master_set()
        pool_sz = round(self.active_masters / self.rep_factor)
        return pool_sz

    def build_wr_list(self, curr_node_idx=0, jump_idx=1):
        # Use slices to make this a one liner
        tot_mn = len(self.vkbook.masternodes)
        mn_list = []

        # if quorum req not met jump_idx is 0 wr on all active nodes
        if jump_idx == 0:
            return self.vkbook.masternodes

        while curr_node_idx < tot_mn:
            mn_list.append(self.vkbook.masternodes[curr_node_idx])
            curr_node_idx += jump_idx

        return mn_list

    @staticmethod
    def index_from_block(b, nodes=[]):
        assert len(nodes) > 0, 'Must have at least one block owner!'

        index = {
            'blockNum': b.get('blockNum'),
            'hash': b.get('hash'),
            'blockOwners': nodes
        }

        assert index['hash'] is not None and index['blockNum'] is not None, 'Block hash and number' \
                                                                                 'must be provided!'

        return index

    def evaluate_wr(self, entry=None, node_id=None):
        """
        Function is used to check if currently node is suppose to write given entry
        :param entry: given block input to be stored
        :param node_id: master id None is default current master, if specified is for catch up case
        :return:
        """

        if entry is None:
            return False

        pool_sz = self.rep_pool_sz()
        mn_idx = self.mn_id % pool_sz
        writers = entry.get('blockNum') % pool_sz

        # TODO
        # need gov here to check if given node is voted out

        if node_id is not None:
            mn_idx = node_id % pool_sz  # overwriting mn_idx
            if mn_idx == writers:
                return True
            else:
                return False

        # always write if active master bellow threshold

        if self.active_masters < self.quorum_needed:
            self.put(entry, self.BLOCK)
            mn_list = self.build_wr_list(curr_node_idx=self.mn_id, jump_idx=0)
            index = self.index_from_block(entry, nodes=mn_list)
            return self.put(index, self.INDEX)

        if mn_idx == writers:
            self.put(entry, self.BLOCK)

        # build list of mn_sign of master nodes updating index db
        mn_list = self.build_wr_list(curr_node_idx=writers, jump_idx=pool_sz)
        assert len(
            mn_list
        ) > 0, "block owner list cannot be empty - dumping list -> {}".format(
            mn_list)

        # create index records and update entry
        index = self.index_from_block(entry, nodes=mn_list)
        return self.put(index, self.INDEX)

    def update_index(self, block, nodes):
        index = self.index_from_block(block, nodes=nodes)
        return self.put(index, MasterStorage.INDEX)

    def put(self, data, collection=MasterStorage.BLOCK):
        super().put(data=data, collection=collection)