def test_peer_table_updated_on_join_command(self): # Network params issue w1 = Wallet() p1 = Network(wallet=w1, socket_base='tcp://127.0.0.1', ctx=self.ctx) w2 = Wallet() d = DiscoveryServer(wallet=w2, socket_id=_socket('tcp://127.0.0.1:19000'), pepper=PEPPER.encode(), ctx=self.ctx, linger=200) # 1. start network # 2. start discovery of other side # 3. send join request # 4. check to see if the data has been added join_message = ['join', (w2.verifying_key().hex(), 'tcp://127.0.0.1')] join_message = json.dumps(join_message).encode() tasks = asyncio.gather( p1.peer_service.serve(), d.serve(), services.get(_socket('tcp://127.0.0.1:10002'), msg=join_message, ctx=self.ctx, timeout=1000), stop_server(p1.peer_service, 0.3), stop_server(d, 0.3)) loop = asyncio.get_event_loop() loop.run_until_complete(tasks) self.assertEqual(p1.peer_service.table[w2.verifying_key().hex()], 'tcp://127.0.0.1')
def test_signature_with_wrong_message_returns_false(self): w = Wallet() message = b'howdy' signature = w.sign(message) self.assertFalse(w.verify(b'hello', signature))
def test_upg_trigger_1_1(self): mns, dls = make_network(1, 1, self.ctx) start_up = make_start_awaitable(mns, dls) candidate = Wallet() stu = Wallet() tx1 = make_tx_packed( processor=mns[1].wallet.verifying_key(), contract_name='upgrade', function_name='init_upgrade', kwargs={ 'pepper': 'peppertest', 'initiator_vk': stu, }, sender=candidate, drivers=[node.driver for node in mns + dls], nonce=0, stamps=1_000_000, ) async def test(): await start_up await asyncio.sleep(3) await send_tx_batch(mns[1], [tx1]) await asyncio.sleep(5) loop = asyncio.get_event_loop() loop.run_until_complete(test()) for node in mns + dls: v = node.driver.get_var(contract='upgrade', variable='upg_lock', arguments=[]) self.assertEqual(v, True)
def test_start_and_stopping_destroys_servers_ipc(self): # Create Network service w1 = Wallet() n1 = NetworkParameters(peer_ipc='peers1', event_ipc='events1', discovery_ipc='discovery1') p1 = Network(wallet=w1, ctx=self.ctx, socket_base='ipc:///tmp', params=n1) # Create Network service w2 = Wallet() n2 = NetworkParameters(peer_ipc='peers2', event_port='events2') p2 = Network(wallet=w2, ctx=self.ctx, socket_base='ipc:///tmp', params=n2) async def stop(n: Network, s): await asyncio.sleep(s) n.peer_service.stop() tasks = asyncio.gather(p1.peer_service.start(), p2.peer_service.start(), stop(p1, 0.3), stop(p2, 0.3)) loop = asyncio.get_event_loop() loop.run_until_complete(tasks)
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)
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)
def test_discover_works_with_ipc_sockets(self): wallet = Wallet() d = DiscoveryServer(_socket('ipc:///tmp/discovery'), wallet, b'CORRECT_PEPPER', ctx=self.ctx) success_task = ping(_socket('ipc:///tmp/discovery'), pepper=b'CORRECT_PEPPER', ctx=self.ctx, timeout=300) failure_task = ping(_socket('tcp://127.0.0.1:20999'), pepper=b'CORRECT_PEPPER', ctx=self.ctx, timeout=300) async def stop_server(timeout): await asyncio.sleep(timeout) d.stop() tasks = asyncio.gather(success_task, failure_task, d.serve(), stop_server(0.3)) loop = asyncio.get_event_loop() results = loop.run_until_complete(tasks) vk_ip1, vk_ip2, _, _ = results _, vk1 = vk_ip1 _, vk2 = vk_ip2 self.assertEqual(vk1.hex(), wallet.verifying_key().hex()) self.assertIsNone(vk2)
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)
def test_discover_nodes_none_found(self): addresses = [_socket('tcp://127.0.0.1:10999'), _socket('tcp://127.0.0.1:11999'), _socket('tcp://127.0.0.1:12999')] addresses_wrong = [_socket('tcp://127.0.0.1:15999'), _socket('tcp://127.0.0.1:14999'), _socket('tcp://127.0.0.1:13999')] wallets = [Wallet(), Wallet(), Wallet()] pepper = b'CORRECT_PEPPER' server_timeout = 1 servers = [DiscoveryServer(addresses[0], wallets[0], pepper, ctx=self.ctx), DiscoveryServer(addresses[1], wallets[1], pepper, ctx=self.ctx), DiscoveryServer(addresses[2], wallets[2], pepper, ctx=self.ctx)] async def stop_server(s, timeout): await asyncio.sleep(timeout) s.stop() tasks = asyncio.gather( servers[0].serve(), servers[1].serve(), servers[2].serve(), stop_server(servers[0], server_timeout), stop_server(servers[1], server_timeout), stop_server(servers[2], server_timeout), discover_nodes(ip_list=addresses_wrong, pepper=pepper, ctx=self.ctx, timeout=500, retries=3) ) loop = asyncio.get_event_loop() results = loop.run_until_complete(tasks) r = results[-1] self.assertIsNone(r.get(str(addresses[0]))) self.assertIsNone(r.get(str(addresses[1]))) self.assertIsNone(r.get(str(addresses[2])))
def setUp(self): self.wallet = Wallet() # Wallets for VKs self.test_wallet_1 = Wallet() self.test_wallet_2 = Wallet() self.peer_table = { self.test_wallet_1.verifying_key().hex(): 'ipc:///tmp/n1', self.test_wallet_2.verifying_key().hex(): 'ipc:///tmp/n2', } self.ctx = zmq.asyncio.Context() self.loop = asyncio.new_event_loop() self.contacts = MockContacts( masters=[self.test_wallet_1.verifying_key().hex()], delegates=[self.test_wallet_2.verifying_key().hex()]) self.paramaters = Parameters(socket_base='tcp://127.0.0.1', wallet=self.wallet, ctx=self.ctx, contacts=self.contacts) self.authenticator = SocketAuthenticator(wallet=self.wallet, contacts=self.contacts, ctx=self.ctx) asyncio.set_event_loop(self.loop)
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)
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)
def make_tx_packed(sender, server, contract_name, function_name, kwargs={}, stamps=10_000): wallet = Wallet(seed=sender) nonce_req = requests.get('{}/nonce/{}'.format( server, wallet.verifying_key().hex())) nonce = nonce_req.json()['nonce'] processor = bytes.fromhex(nonce_req.json()['processor']) batch = TransactionBuilder(sender=wallet.verifying_key(), contract=contract_name, function=function_name, kwargs=kwargs, stamps=stamps, processor=processor, nonce=nonce) batch.sign(sender) b = batch.serialize() return b
def test_signature_with_correct_message_returns_true(self): w = Wallet() message = b'howdy' signature = w.sign(message) self.assertTrue(w.verify(message, signature))
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
def test_sign_bytes_returns_hex_signature(self): w = Wallet() signature = w.sign(b'hello', as_hex=True) self.assertTrue(isinstance(signature, str)) self.assertEqual(len(signature), 128)
def test_sign_bytes_returns_signature(self): w = Wallet() signature = w.sign(b'hello') self.assertTrue(isinstance(signature, bytes)) self.assertEqual(len(signature), 64)
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
def test_discover_works_with_blend_of_tcp_and_ipc(self): addresses = [_socket('ipc:///tmp/discover1'), _socket('tcp://127.0.0.1:11999'), _socket('ipc:///tmp/woohoo')] wallets = [Wallet(), Wallet(), Wallet()] pepper = b'CORRECT_PEPPER' server_timeout = 0.3 servers = [DiscoveryServer(addresses[0], wallets[0], pepper, ctx=self.ctx), DiscoveryServer(addresses[1], wallets[1], pepper, ctx=self.ctx), DiscoveryServer(addresses[2], wallets[2], pepper, ctx=self.ctx)] async def stop_server(s, timeout): await asyncio.sleep(timeout) s.stop() tasks = asyncio.gather( servers[0].serve(), servers[1].serve(), servers[2].serve(), stop_server(servers[0], server_timeout), stop_server(servers[1], server_timeout), stop_server(servers[2], server_timeout), discover_nodes(ip_list=addresses, pepper=pepper, ctx=self.ctx) ) loop = asyncio.get_event_loop() results = loop.run_until_complete(tasks) r = results[-1] self.assertEqual(r[str(addresses[0])], wallets[0].verifying_key().hex()) self.assertEqual(r[str(addresses[1])], wallets[1].verifying_key().hex()) self.assertEqual(r[str(addresses[2])], wallets[2].verifying_key().hex())
def test_start_and_stopping_destroys_servers(self): # Create Network service w1 = Wallet() n1 = NetworkParameters(peer_port=10001, event_port=10002) p1 = Network(wallet=w1, ctx=self.ctx, socket_base='tcp://127.0.0.1', params=n1) # Create Network service w2 = Wallet() n2 = NetworkParameters(peer_port=10003, event_port=10004) p2 = Network(wallet=w2, ctx=self.ctx, socket_base='tcp://127.0.0.1', params=n2) async def stop(n: Network, s): await asyncio.sleep(s) n.peer_service.stop() tasks = asyncio.gather(p1.peer_service.start(), p2.peer_service.start(), stop(p1, 0.3), stop(p2, 0.3)) loop = asyncio.get_event_loop() loop.run_until_complete(tasks)
def test_current_contacts_joins_mn_seed_adds_table_to_joiner(self): n1 = '/tmp/n1' make_ipc(n1) mnw1 = Wallet() mn1 = Network(wallet=mnw1, ctx=self.ctx, socket_base=f'ipc://{n1}') mn1.peer_service.table = {'a': 'b', 'c': 'd', 'e': 'f'} mnw2 = Wallet() n2 = '/tmp/n2' make_ipc(n2) mn2 = Network(wallet=mnw2, ctx=self.ctx, socket_base=f'ipc://{n2}', mn_seed='ipc:///tmp/n1') tasks = asyncio.gather(mn1.peer_service.start(), mn2.discovery_server.serve(), stop_server(mn2.discovery_server, 0.3), stop_server(mn1.peer_service, 0.3), mn2.get_current_contacts()) loop = asyncio.get_event_loop() loop.run_until_complete(tasks) self.assertDictEqual(mn1.peer_service.table, mn2.peer_service.table)
def test_verify_vk_pepper_wrong_vk_pepper_message(self): wallet = Wallet() vk = wallet.verifying_key() pepper = b'TESTING_PEPPER' pepper_msg = vk + wallet.sign(pepper) self.assertFalse(verify_vk_pepper(pepper_msg, b'WRONG_PEPPER'))
def test_verify_vk_pepper_correct_vk_pepper_message(self): wallet = Wallet() vk = wallet.verifying_key() pepper = b'TESTING_PEPPER' pepper_msg = vk + wallet.sign(pepper) self.assertTrue(verify_vk_pepper(pepper_msg, pepper))
def test_event_service_triggered_when_new_node_added_ipc(self): # Create Network service w1 = Wallet() p1 = Network(wallet=w1, ctx=self.ctx, socket_base='ipc:///tmp') n1 = '/tmp/n1' try: os.mkdir('/tmp/n1') except: pass # Create Discovery Server w2 = Wallet() d = DiscoveryServer(wallet=w2, socket_id=_socket('ipc:///tmp/n1/discovery'), pepper=PEPPER.encode(), ctx=self.ctx, poll_timeout=2000, linger=200) # Create raw subscriber subscriber = self.ctx.socket(zmq.SUB) subscriber.setsockopt(zmq.SUBSCRIBE, b'') subscriber.connect('ipc:///tmp/events') # TCP takes a bit longer to bind and is prone to dropping messages... sleep(0.3) # Construct the join RPC message join_message = ['join', (w2.verifying_key().hex(), 'ipc:///tmp/n1')] join_message = json.dumps(join_message).encode() # Wrap recv() in an async async def recv(): msg = await subscriber.recv() return msg tasks = asyncio.gather( p1.peer_service.start( ), # Start the PeerService which will process RPC and emit events d.serve( ), # Start Discovery so PeerService can verify they are online services.get(_socket('ipc:///tmp/peers'), msg=join_message, ctx=self.ctx, timeout=3000), # Push out a join request stop_server(p1.peer_service, 1), stop_server(d, 1), recv() # Collect the subscription result ) loop = asyncio.get_event_loop() res = loop.run_until_complete(tasks) expected_list = ['join', [w2.verifying_key().hex(), 'ipc:///tmp/n1']] got_list = json.loads(res[-1].decode()) self.assertListEqual(expected_list, got_list)
def test_init(self): w = Wallet() TransactionBuilder(sender=w.verifying_key().hex(), stamps=1000000, contract='currency', function='transfer', kwargs={'amount': 'b'}, processor=b'\x00' * 32, nonce=0)
def test_resync_adds_new_contacts(self): p1 = Network(wallet=self.wallet, ctx=self.ctx, socket_base='tcp://127.0.0.1') p1.peer_service.table = self.peer_table p = Peers(wallet=self.wallet, ctx=self.ctx, parameters=self.paramaters, node_type=MN, service_type=ServiceType.INCOMING_WORK) self.authenticator.sync_certs() async def late_refresh(): await asyncio.sleep(0.3) await self.paramaters.refresh() p.sync_sockets() async def stop(): await asyncio.sleep(0.5) p1.stop() tasks = asyncio.gather(p1.start(discover=False), late_refresh(), stop()) self.loop.run_until_complete(tasks) socket_1 = p.sockets.get(self.test_wallet_1.verifying_key().hex()) self.assertIsNotNone(socket_1) new_wallet = Wallet() p1.peer_service.table[ new_wallet.verifying_key().hex()] = 'ipc:///tmp/n3' self.contacts.masternodes.append(new_wallet.verifying_key().hex()) self.authenticator.sync_certs() async def late_refresh(): await asyncio.sleep(0.3) await self.paramaters.refresh() p.sync_sockets() async def stop(): await asyncio.sleep(0.5) p1.stop() tasks = asyncio.gather(p1.start(discover=False), late_refresh(), stop()) self.loop.run_until_complete(tasks) socket_1 = p.sockets.get(new_wallet.verifying_key().hex()) self.assertIsNotNone(socket_1)
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 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)
def test_passing_float_in_contract_kwargs_raises_assertion(self): w = Wallet() with self.assertRaises(AssertionError): TransactionBuilder(sender=w.verifying_key().hex(), stamps=1000000, contract='currency', function='transfer', kwargs={'amount': 123.00}, processor=b'\x00' * 32, nonce=0)
def test_verifying_key_as_bytes(self): w = Wallet() _w = w.verifying_key() self.assertTrue(isinstance(_w, bytes)) _h = w.verifying_key(as_hex=True) self.assertTrue(isinstance(_h, str))