def test_run_single_block_mock(self): b = Delegate(socket_base='ipc:///tmp/n2', wallet=Wallet(), ctx=self.ctx, bootnodes=bootnodes, constitution=constitution) gb = canonical.get_genesis_block() gb = canonical.dict_to_capnp_block(gb) # Put the genesis block in here so we start immediately b.nbn_inbox.q.append(gb) b.running = True # Add a single peer that we control b.parameters.sockets = {mnw1.verifying_key().hex(): 'ipc:///tmp/n1'} put_test_contract(self.client) b.work_inbox.work[mnw1.verifying_key().hex()] = get_tx_batch() async def stop(): await asyncio.sleep(1) b.running = False b.nbn_inbox.q.append(gb) loop = asyncio.get_event_loop() tasks = asyncio.gather(b.run(), stop()) loop.run_until_complete(tasks)
def test_acquire_work_if_no_one_connected_returns(self): d = Delegate(ctx=self.ctx, socket_base='ipc:///tmp/n1', constitution=constitution, wallet=dw1, overwrite=True) self.loop.run_until_complete(d.acquire_work())
def test_did_sign_block_false_if_no_pending_sbcs(self): b = Delegate(socket_base='tcp://127.0.0.1', wallet=Wallet(), ctx=self.ctx, bootnodes=bootnodes, constitution=constitution) self.assertFalse(b.did_sign_block(None))
def test_execute_multiple_tx_in_batch_returns_correct_sbc(self): test_contract = ''' v = Variable() @construct def seed(): v.set('hello') @export def set(var): v.set(var) @export def get(): return v.get() ''' self.client.submit(test_contract, name='testing') tx = TransactionBuilder(sender='stu', contract='testing', function='set', kwargs={'var': 'howdy'}, stamps=100_000, processor=b'\x00' * 32, nonce=0) tx.sign(Wallet().signing_key()) tx.serialize() 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() tx_batch = transaction_list_to_transaction_batch( [tx.struct, tx2.struct], wallet=Wallet()) w = Wallet() b = Delegate(socket_base='tcp://127.0.0.1', wallet=w, ctx=self.ctx) results = b.execute_work([(tx_batch.timestamp, tx_batch)]) # Test that there is a state change on the 1st tx tx = results[0].transactions[0] self.assertEqual(tx.state[0].key, b'testing.v') self.assertEqual(tx.state[0].value, b'"howdy"') self.assertEqual(results[0].inputHash, tx_batch.inputHash) self.assertEqual(results[0].prevBlockHash, b'\x00' * 32) self.assertEqual(results[0].signer, w.verifying_key())
def test_block_number_increments_properly(self): mock_master = ComplexMockMasternode( ctx=self.ctx, delegate_nbn='ipc:///tmp/n1/block_notifications', delegate_work='ipc:///tmp/n1/incoming_work', wallet=mnw1) d = Delegate(ctx=self.ctx, socket_base='ipc:///tmp/n1', constitution=constitution, wallet=dw1, overwrite=True) # d.nbn_inbox.verify = False d.work_inbox.verify = False d.running = True d.parameters.sockets = {mnw1.verifying_key().hex(): 'ipc:///tmp/n2'} async def run(): await asyncio.sleep(0.3) self.assertEqual(d.driver.latest_block_num, 0) await mock_master.send_new_block_to_socket() # Assert Block num 1 await asyncio.sleep(0.3) self.assertEqual(d.driver.latest_block_num, 1) await mock_master.send_to_work_socket() w = await mock_master.mn_agg.recv_multipart() b = canonical.get_genesis_block() b['blockNum'] = 2 await mock_master.send_new_block_to_socket(b) # Assert Block num 2 await asyncio.sleep(0.3) self.assertEqual(d.driver.latest_block_num, 2) d.nbn_inbox.stop() d.work_inbox.stop() d.stop() self.loop.stop() tasks = asyncio.gather(d.work_inbox.serve(), d.nbn_inbox.serve(), d.run(), run()) with suppress(RuntimeError): self.loop.run_until_complete(tasks)
def test_did_sign_block_false_if_missing_any_merkle_roots(self): b = Delegate(socket_base='tcp://127.0.0.1', wallet=Wallet(), ctx=self.ctx, bootnodes=bootnodes, constitution=constitution) block = random_block() # Add one root but not the other b.pending_sbcs.add(block.subBlocks[0].merkleRoot) self.assertFalse(b.did_sign_block(block))
def test_environment_variables_are_working_as_they_should(self): test_contract = ''' a = Variable() b = Variable() c = Variable() @export def capture(): a.set(block_hash) b.set(block_num) c.set(now) ''' self.client.submit(test_contract, name='testing') tx = TransactionBuilder(sender='stu', contract='testing', function='capture', kwargs={}, stamps=100_000, processor=b'\x00' * 32, nonce=0) tx.sign(Wallet().signing_key()) tx.serialize() tx_batch = transaction_list_to_transaction_batch([tx.struct], wallet=Wallet()) w = Wallet() b = Delegate(socket_base='tcp://127.0.0.1', wallet=w, ctx=self.ctx) now = Datetime._from_datetime( datetime.utcfromtimestamp(tx_batch.timestamp)) results = b.execute_work([(tx_batch.timestamp, tx_batch)]) tx = results[0].transactions[0] a, b, c = tx.state self.assertEqual(a.key, b'testing.a') self.assertEqual( a.value, b'"0000000000000000000000000000000000000000000000000000000000000000"' ) self.assertEqual(b.key, b'testing.b') self.assertEqual(b.value, b'0') self.assertEqual(c.key, b'testing.c') self.assertEqual(c.value, encode(now).encode())
def test_process_nbn_updates_state_with_block_if_did_not_sign_block(self): b = Delegate(socket_base='tcp://127.0.0.1', wallet=Wallet(), ctx=self.ctx, bootnodes=bootnodes, constitution=constitution) block = random_block() k = block.subBlocks[0].transactions[0].state[0].key v = block.subBlocks[0].transactions[0].state[0].value self.assertIsNone(b.client.raw_driver.get_direct(k)) b.process_block(block) self.assertEqual(b.client.raw_driver.get_direct(k), v)
def make_network(masternodes, delegates, ctx, mn_min_quorum=2, del_min_quorum=2): mn_wallets = [Wallet() for _ in range(masternodes)] dl_wallets = [Wallet() for _ in range(delegates)] constitution = { 'masternodes': [mn.verifying_key().hex() for mn in mn_wallets], 'delegates': [dl.verifying_key().hex() for dl in dl_wallets], 'masternode_min_quorum': mn_min_quorum, 'delegate_min_quorum': del_min_quorum, } mns = [] dls = [] bootnodes = None node_count = 0 for wallet in mn_wallets: driver = BlockchainDriver(driver=InMemDriver()) # driver = IsolatedDriver() ipc = f'/tmp/n{node_count}' make_ipc(ipc) if bootnodes is None: bootnodes = [f'ipc://{ipc}'] mn = Masternode(wallet=wallet, ctx=ctx, socket_base=f'ipc://{ipc}', bootnodes=bootnodes, constitution=deepcopy(constitution), webserver_port=18080 + node_count, driver=driver) mns.append(mn) node_count += 1 for wallet in dl_wallets: driver = BlockchainDriver(driver=InMemDriver()) # driver = IsolatedDriver() ipc = f'/tmp/n{node_count}' make_ipc(ipc) dl = Delegate(wallet=wallet, ctx=ctx, socket_base=f'ipc://{ipc}', constitution=deepcopy(constitution), bootnodes=bootnodes, driver=driver) dls.append(dl) node_count += 1 return mns, dls
def test_process_nbn_commits_changes_if_did_sign_block(self): b = Delegate(socket_base='tcp://127.0.0.1', wallet=Wallet(), ctx=self.ctx, bootnodes=bootnodes, constitution=constitution) block = random_block() # Add one root but not the other b.pending_sbcs.add(block.subBlocks[0].merkleRoot) b.pending_sbcs.add(block.subBlocks[1].merkleRoot) b.client.raw_driver.set('A', 'B') self.assertIsNone(b.client.raw_driver.get_direct('A')) b.process_block(block) self.assertEqual(b.client.raw_driver.get(b'A'), 'B')
def test_execute_work_single_transaction(self): test_contract = ''' v = Variable() @construct def seed(): v.set('hello') @export def set(var): v.set(var) @export def get(): return v.get() ''' self.client.submit(test_contract, name='testing') tx = TransactionBuilder(sender='stu', contract='testing', function='set', kwargs={'var': 'jeff'}, stamps=100_000, processor=b'\x00' * 32, nonce=0) tx.sign(Wallet().signing_key()) tx.serialize() tx_batch = transaction_list_to_transaction_batch([tx.struct], wallet=Wallet()) b = Delegate(socket_base='tcp://127.0.0.1', wallet=Wallet(), ctx=self.ctx, bootnodes=bootnodes, constitution=constitution) b.execute_work([(1, tx_batch)])
def test_acquire_work_for_one_master_returns_a_single_tx_batch(self): mock_master = ComplexMockMasternode( ctx=self.ctx, delegate_nbn='ipc:///tmp/n1/block_notifications', delegate_work='ipc:///tmp/n1/incoming_work', wallet=mnw1) d = Delegate(ctx=self.ctx, socket_base='ipc:///tmp/n1', constitution=constitution, wallet=dw1, overwrite=True) d.running = True d.parameters.sockets = {mnw1.verifying_key().hex(): 'ipc:///tmp/n2'} args_1 = ('hi', 'hello') args_2 = ('howdy', 'yo') args_3 = ('yeehaw', 'p') mock_master.tx_batcher.queue.extend([ make_tx(mnw1.verifying_key(), *args_1), make_tx(mnw1.verifying_key(), *args_2), make_tx(mnw1.verifying_key(), *args_3), ]) async def stop(): await asyncio.sleep(0.3) d.work_inbox.stop() tasks = asyncio.gather(d.work_inbox.serve(), mock_master.send_to_work_socket(), d.acquire_work(), stop()) _, _, r, _ = self.loop.run_until_complete(tasks) print(r)
def join_network(args): assert args.node_type == 'masternode' or args.node_type == 'delegate', \ 'Provide node type as "masternode" or "delegate"' sk = bytes.fromhex(args.key) wallet = Wallet(seed=sk) const = resolve_constitution(args.constitution) mn_seed = f'tcp://{args.mn_seed}' ip_str = requests.get('http://api.ipify.org').text socket_base = f'tcp://{ip_str}' # Setup Environment # CURR_DIR = pathlib.Path(os.getcwd()) # os.environ['PKG_ROOT'] = str(CURR_DIR.parent) # os.environ['CIL_PATH'] = os.getenv('PKG_ROOT') + '/cilantro_ee' if args.node_type == 'masternode': # Start mongo start_mongo() n = Masternode(wallet=wallet, ctx=zmq.asyncio.Context(), socket_base=socket_base, constitution=const, webserver_port=args.webserver_port, mn_seed=mn_seed) elif args.node_type == 'delegate': start_mongo() n = Delegate(wallet=wallet, ctx=zmq.asyncio.Context(), socket_base=socket_base, constitution=const, mn_seed=mn_seed) loop = asyncio.get_event_loop() asyncio. async (n.start()) loop.run_forever()
def test_build_sbc_from_work_results(self): test_contract = ''' v = Variable() @construct def seed(): v.set('hello') @export def set(var): v.set(var) @export def get(): return v.get() ''' print('ok') self.client.submit(test_contract, name='testing') print('here') tx = TransactionBuilder(sender='stu', contract='testing', function='set', kwargs={'var': 'jeff'}, stamps=100_000, processor=b'\x00' * 32, nonce=0) tx.sign(Wallet().signing_key()) tx.serialize() tx_batch = transaction_list_to_transaction_batch([tx.struct], wallet=Wallet()) b = Delegate(socket_base='tcp://127.0.0.1', wallet=Wallet(), ctx=self.ctx, constitution=constitution) print(sbc)
def test_acquire_work_returns_empty_self_signed_tx_batches_if_timeout_hit( self): mock_master = ComplexMockMasternode( ctx=self.ctx, delegate_nbn='ipc:///tmp/n1/block_notifications', delegate_work='ipc:///tmp/n1/incoming_work', wallet=mnw1) mock_master_2 = ComplexMockMasternode( ctx=self.ctx, delegate_nbn='ipc:///tmp/n1/block_notifications', delegate_work='ipc:///tmp/n1/incoming_work', wallet=mnw2, ipc='n3') d = Delegate(ctx=self.ctx, socket_base='ipc:///tmp/n1', constitution=constitution2, wallet=dw1, overwrite=True) d.running = True d.parameters.sockets = { mnw1.verifying_key().hex(): 'ipc:///tmp/n2', mnw2.verifying_key().hex(): 'ipc:///tmp/n3', mnw3.verifying_key().hex(): 'ipc:///' } args_1 = ('hi', 'hello') args_2 = ('howdy', 'yo') args_3 = ('yeehaw', 'p') mock_master.tx_batcher.queue.extend([ make_tx(mnw1.verifying_key(), *args_1), make_tx(mnw1.verifying_key(), *args_2), make_tx(mnw1.verifying_key(), *args_3), ]) ### TXS for master 2 args_4 = ('aaa', 'bbb') args_5 = ('123', 'xxx') args_6 = ('456', 'zzz') mock_master_2.tx_batcher.queue.extend([ make_tx(mnw2.verifying_key(), *args_4), make_tx(mnw2.verifying_key(), *args_5), make_tx(mnw2.verifying_key(), *args_6), ]) async def stop(): await asyncio.sleep(0.3) d.work_inbox.stop() tasks = asyncio.gather(d.work_inbox.serve(), mock_master.send_to_work_socket(), mock_master_2.send_to_work_socket(), d.acquire_work(), stop()) _, _, _, r, _ = self.loop.run_until_complete(tasks) print(r[0]) print(r[1]) print(r[2])
def setup_node(): node_type = '' while node_type not in ['M', 'D']: node_type = input('(M)asternode or (D)elegate: ').upper() while True: sk = getpass('Signing Key in Hex Format: ') try: wallet = Wallet(seed=bytes.fromhex(sk)) break except: print('Invalid format! Try again.') join_or_start = '' while join_or_start not in ['J', 'S']: join_or_start = input('(J)oin or (S)tart: ').upper() bootnodes = [] mn_seed = None if join_or_start == 'S': bootnode = '' while len(bootnodes) < 1 or bootnode != '': bootnode = input( 'Enter bootnodes as IP string. Press Enter twice to continue: ' ) if is_valid_ip(bootnode): print(f'Added {bootnode}.') bootnodes.append(bootnode) elif bootnode != '': print(f'Invalid IP string: {bootnode}') else: while mn_seed is None: mn_ip = input('Enter masternode as IP string: ') if is_valid_ip(mn_ip): mn_seed = mn_ip else: print(f'Invalid IP string: {mn_seed}') ip_str = requests.get('http://api.ipify.org').text socket_base = f'tcp://{ip_str}' mn_seed_str = f'tcp://{mn_seed}' const_url = input('URL of constitution: ') c = requests.get(const_url) const = resolve_raw_constitution(c.text) # start_rocks() if node_type == 'M': # Start mongo start_mongo() n = Masternode(wallet=wallet, ctx=zmq.asyncio.Context(), socket_base=socket_base, bootnodes=bootnodes, constitution=const, webserver_port=18080, mn_seed=mn_seed_str) elif node_type == 'D': n = Delegate(wallet=wallet, ctx=zmq.asyncio.Context(), socket_base=socket_base, bootnodes=bootnodes, constitution=const, mn_seed=mn_seed_str) loop = asyncio.get_event_loop() asyncio. async (n.start()) loop.run_forever()
def start_node(args): # sleep for restart module for ppid to be killed time.sleep(5) assert args.node_type == 'masternode' or args.node_type == 'delegate', \ 'Provide node type as "masternode" or "delegate"' sk = bytes.fromhex(args.key) wallet = Wallet(seed=sk) bootnodes = [] for node in args.boot_nodes: assert is_valid_ip( node), 'Invalid IP string provided to boot node argument.' bootnodes.append(f'tcp://{node}') assert len(bootnodes) > 0, 'Must provide at least one bootnode.' const = resolve_constitution(args.constitution) ip_str = requests.get('http://api.ipify.org').text socket_base = f'tcp://{ip_str}' # Setup Environment copyfile('/root/cilantro-enterprise/scripts/cil.service', '/etc/systemd/system/cil.service') # Enable Auto Restart # key, config = read_cfg() #use restart logic to start the node again # if key is None or config is None: # # booting for 1st time # enable = ask(question='Authorize auto restart for cilantro') # # if enable: # validate_key(restart=enable, key = args.key) # else: # print("Auto Restart is disabled manual intervention to restart CIL") if args.node_type == 'masternode': # Start mongo start_mongo() n = Masternode( wallet=wallet, ctx=zmq.asyncio.Context(), socket_base=socket_base, bootnodes=bootnodes, constitution=const, webserver_port=args.webserver_port, ) elif args.node_type == 'delegate': n = Delegate( wallet=wallet, ctx=zmq.asyncio.Context(), socket_base=socket_base, bootnodes=bootnodes, constitution=const, ) loop = asyncio.get_event_loop() asyncio. async (n.start()) loop.run_forever()
def test_init(self): b = Delegate(socket_base='tcp://127.0.0.1', wallet=Wallet(), ctx=self.ctx, bootnodes=bootnodes, constitution=constitution)