def test_update_with_block_sets_hash_and_height(self): _hash = storage.get_latest_block_hash(self.driver) num = storage.get_latest_block_height(self.driver) self.assertEqual(_hash, '0' * 64) self.assertEqual(num, 0) storage.update_state_with_block(block=block, driver=self.driver, nonces=self.nonces) _hash = storage.get_latest_block_hash(self.driver) num = storage.get_latest_block_height(self.driver) self.assertEqual(_hash, 'f' * 64) self.assertEqual(num, 555)
def update_state(self, block): self.driver.clear_pending_state() # Check if the block is valid if self.should_process(block): self.log.info('Storing new block.') # Commit the state changes and nonces to the database storage.update_state_with_block( block=block, driver=self.driver, nonces=self.nonces ) self.log.info('Issuing rewards.') # Calculate and issue the rewards for the governance nodes self.reward_manager.issue_rewards( block=block, client=self.client ) self.log.info('Updating metadata.') self.current_height = storage.get_latest_block_height(self.driver) self.current_hash = storage.get_latest_block_hash(self.driver) self.new_block_processor.clean(self.current_height)
async def get_latest_block_number(self, request): self.driver.clear_pending_state() num = storage.get_latest_block_height(self.driver) return response.json({'latest_block_number': num}, headers={'Access-Control-Allow-Origin': '*'})
async def get_latest_block_number(self, request): return response.json( { 'latest_block_number': storage.get_latest_block_height( self.driver) }, headers={'Access-Control-Allow-Origin': '*'})
def test_generate_environment_creates_block_num(self): timestamp = time.time() exe = execution.SerialExecutor(executor=self.client.executor) e = exe.generate_environment(self.client.raw_driver, timestamp, 'A' * 64) self.assertEqual(e['block_num'], storage.get_latest_block_height(self.client.raw_driver) + 1)
async def get_latest_block(self, request): self.driver.clear_pending_state() num = storage.get_latest_block_height(self.driver) block = await self.blocks.get_block(int(num)) return response.json(block, dumps=NonceEncoder().encode, headers={'Access-Control-Allow-Origin': '*'})
async def gather_subblocks(self, total_contacts, current_height=0, current_hash='0' * 64, quorum_ratio=0.66, adequate_ratio=0.5, expected_subblocks=4): self.sbc_inbox.expected_subblocks = expected_subblocks block = storage.get_latest_block_height(self.driver) self.log.info( f'Expecting {expected_subblocks} subblocks from {total_contacts} delegates.' ) contenders = BlockContender(total_contacts=total_contacts, required_consensus=quorum_ratio, total_subblocks=expected_subblocks, acceptable_consensus=adequate_ratio) # Add timeout condition. started = time.time() last_log = started while (not contenders.block_has_consensus() and contenders.responses < contenders.total_contacts) and \ time.time() - started < self.seconds_to_timeout: if self.sbc_inbox.has_sbc(): sbcs = await self.sbc_inbox.receive_sbc( ) # Can probably make this raw sync code self.log.info('Pop it in there.') contenders.add_sbcs(sbcs) if time.time() - last_log > 5: self.log.error( f'Waiting for contenders for {int(time.time() - started)}s.' ) last_log = time.time() await asyncio.sleep(0) if time.time() - started > self.seconds_to_timeout: self.log.error( f'Block timeout. Too many delegates are offline! Kick out the non-responsive ones! {block}' ) self.log.info('Done aggregating new block.') block = contenders.get_current_best_block() self.log.error(block) self.sbc_inbox.q.clear() # self.log.info(f'Best block: {block}') return block_from_subblocks(block, previous_hash=current_hash, block_num=current_height + 1)
async def process_message(self, msg): response = None mn_logger.debug('Got a msg') if primatives.dict_has_keys(msg, keys={'name', 'arg'}): if msg['name'] == base.GET_BLOCK: response = self.get_block(msg) elif msg['name'] == base.GET_HEIGHT: response = get_latest_block_height(self.driver) return response
def test_catchup_with_nbn_added(self): driver = ContractDriver(driver=InMemDriver()) mn_bootnode = 'tcp://127.0.0.1:18001' mn_wallet = Wallet() mn_router = router.Router(socket_id=mn_bootnode, ctx=self.ctx, secure=True, wallet=mn_wallet) mn_router.add_service(base.BLOCK_SERVICE, self.b) nw = Wallet() dlw = Wallet() node = base.Node(socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=nw, constitution={ 'masternodes': [mn_wallet.verifying_key], 'delegates': [dlw.verifying_key] }, driver=driver) self.authenticator.add_verifying_key(mn_wallet.verifying_key) self.authenticator.add_verifying_key(nw.verifying_key) self.authenticator.add_verifying_key(dlw.verifying_key) self.authenticator.configure() blocks = generate_blocks(4) self.blocks.store_block(blocks[0]) self.blocks.store_block(blocks[1]) self.blocks.store_block(blocks[2]) storage.set_latest_block_height(3, self.driver) node.new_block_processor.q.append(blocks[3]) tasks = asyncio.gather( mn_router.serve(), node.catchup('tcp://127.0.0.1:18001', mn_wallet.verifying_key), stop_server(mn_router, 1)) self.loop.run_until_complete(tasks) self.assertEqual(storage.get_latest_block_height(node.driver), 4)
def test_process_new_block_updates_state(self): block = canonical.block_from_subblocks(subblocks=[], previous_hash='0' * 64, block_num=1) driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=Wallet(), constitution={ 'masternodes': [Wallet().verifying_key], 'delegates': [Wallet().verifying_key] }, driver=driver) node.process_new_block(block) self.assertEqual(storage.get_latest_block_height(node.driver), 1) self.assertEqual(storage.get_latest_block_hash(node.driver), block['hash'])
def __init__(self, socket_base, ctx: zmq.asyncio.Context, wallet, constitution: dict, bootnodes={}, blocks=storage.BlockStorage(), driver=ContractDriver(), debug=True, store=False, seed=None, bypass_catchup=False, node_type=None, genesis_path=lamden.contracts.__path__[0], reward_manager=rewards.RewardManager(), nonces=storage.NonceStorage()): self.driver = driver self.nonces = nonces self.store = store self.seed = seed self.blocks = blocks self.event_writer = EventWriter() self.log = get_logger('Base') self.log.propagate = debug self.socket_base = socket_base self.wallet = wallet self.ctx = ctx self.genesis_path = genesis_path self.client = ContractingClient(driver=self.driver, submission_filename=genesis_path + '/submission.s.py') self.bootnodes = bootnodes self.constitution = constitution self.seed_genesis_contracts() self.socket_authenticator = authentication.SocketAuthenticator( bootnodes=self.bootnodes, ctx=self.ctx, client=self.client) self.upgrade_manager = upgrade.UpgradeManager(client=self.client, wallet=self.wallet, node_type=node_type) self.router = router.Router(socket_id=socket_base, ctx=self.ctx, wallet=wallet, secure=True) self.network = network.Network(wallet=wallet, ip_string=socket_base, ctx=self.ctx, router=self.router) self.new_block_processor = NewBlock(driver=self.driver) self.router.add_service( NEW_BLOCK_SERVICE, self.new_block_processor) # Add this after catch up? self.running = False self.upgrade = False self.reward_manager = reward_manager self.current_height = storage.get_latest_block_height(self.driver) self.current_hash = storage.get_latest_block_hash(self.driver) self.bypass_catchup = bypass_catchup
async def get_latest_block(self, request): num = storage.get_latest_block_height(self.driver) block = self.blocks.get_block(int(num)) return response.json(block, dumps=ByteEncoder().encode, headers={'Access-Control-Allow-Origin': '*'})
def test_masternode_delegate_single_loop_updates_block_num(self): ips = [ 'tcp://127.0.0.1:18001', 'tcp://127.0.0.1:18002' ] dw = Wallet() mw = Wallet() self.authenticator.add_verifying_key(mw.verifying_key) self.authenticator.add_verifying_key(dw.verifying_key) self.authenticator.configure() mnd = ContractDriver(driver=InMemDriver()) mn = masternode.Masternode( socket_base=ips[0], ctx=self.ctx, wallet=mw, constitution={ 'masternodes': [mw.verifying_key], 'delegates': [dw.verifying_key] }, driver=mnd ) sender = Wallet() mnd.set_var(contract='currency', variable='balances', arguments=[sender.verifying_key], value=1_000_000) dld = ContractDriver(driver=InMemDriver()) dld.set_var(contract='currency', variable='balances', arguments=[sender.verifying_key], value=1_000_000) dl = delegate.Delegate( socket_base=ips[1], ctx=self.ctx, wallet=dw, constitution={ 'masternodes': [mw.verifying_key], 'delegates': [dw.verifying_key] }, driver=dld ) tx = transaction.build_transaction( wallet=sender, contract='currency', function='transfer', kwargs={ 'amount': 1338, 'to': 'jeff' }, stamps=5000, nonce=0, processor=mw.verifying_key ) tx_decoded = decode(tx) mn.tx_batcher.queue.append(tx_decoded) peers = { mw.verifying_key: ips[0], dw.verifying_key: ips[1] } mn.network.peers = peers dl.network.peers = peers tasks = asyncio.gather( mn.router.serve(), dl.router.serve(), mn.loop(), dl.loop(), stop_server(mn.router, 1), stop_server(dl.router, 1), ) self.loop.run_until_complete(tasks) dh = storage.get_latest_block_height(dld) mh = storage.get_latest_block_height(mnd) self.assertEqual(dh, 1) self.assertEqual(mh, 1)
def test_get_latest_block_height_correct_after_set(self): storage.set_latest_block_height(123, self.driver) h = storage.get_latest_block_height(self.driver) self.assertEqual(h, 123)
def test_get_latest_block_height_0_if_none(self): h = storage.get_latest_block_height(self.driver) self.assertEqual(h, 0)
def test_start_boots_up_normally(self): # This MN will also provide 'catch up' services mn_bootnode = 'tcp://127.0.0.1:18001' mn_wallet = Wallet() mn_router = router.Router(socket_id=mn_bootnode, ctx=self.ctx, secure=True, wallet=mn_wallet) mn_network = network.Network(wallet=mn_wallet, ip_string=mn_bootnode, ctx=self.ctx, router=mn_router) blocks = generate_blocks(4) self.blocks.store_block(blocks[0]) self.blocks.store_block(blocks[1]) self.blocks.store_block(blocks[2]) storage.set_latest_block_height(3, self.driver) mn_router.add_service( base.BLOCK_SERVICE, masternode.BlockService(self.blocks, self.driver)) dl_bootnode = 'tcp://127.0.0.1:18002' dl_wallet = Wallet() dl_router = router.Router(socket_id=dl_bootnode, ctx=self.ctx, secure=True, wallet=dl_wallet) dl_network = network.Network(wallet=dl_wallet, ip_string=dl_bootnode, ctx=self.ctx, router=dl_router) constitution = { 'masternodes': [mn_wallet.verifying_key], 'delegates': [dl_wallet.verifying_key] } bootnodes = { mn_wallet.verifying_key: mn_bootnode, dl_wallet.verifying_key: dl_bootnode } node_w = Wallet() driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18003', ctx=self.ctx, wallet=node_w, constitution=constitution, driver=driver, store=False, bootnodes=bootnodes) self.authenticator.add_verifying_key(mn_wallet.verifying_key) self.authenticator.add_verifying_key(dl_wallet.verifying_key) self.authenticator.add_verifying_key(node_w.verifying_key) self.authenticator.configure() vks = [mn_wallet.verifying_key, dl_wallet.verifying_key] tasks = asyncio.gather( mn_router.serve(), dl_router.serve(), mn_network.start(bootnodes, vks), dl_network.start(bootnodes, vks), stop_server(mn_router, 0.2), stop_server(dl_router, 0.2), ) self.loop.run_until_complete(tasks) tasks = asyncio.gather(mn_router.serve(), dl_router.serve(), node.start(), stop_server(mn_router, 1), stop_server(dl_router, 1), stop_server(node.router, 1)) self.loop.run_until_complete(tasks) self.assertEqual(storage.get_latest_block_height(node.driver), 3) self.assertEqual(storage.get_latest_block_hash(node.driver), blocks[2]['hash'])