def test_get_difficulty(self): difficulty = 8 ek = self._create_keysauth(difficulty) # first 8 bits of digest must be 0 assert sha2(ek.public_key).to_bytes(256, 'big')[0] == 0 assert KeysAuth.get_difficulty(ek.key_id) >= difficulty assert KeysAuth.is_pubkey_difficult(ek.public_key, difficulty) assert KeysAuth.is_pubkey_difficult(ek.key_id, difficulty)
def test_react_to_hello(self): conn = MagicMock() conf = MagicMock() conf.opt_peer_num = 10 node = Node(node_name='node', key='ffffffff') keys_auth = KeysAuth(self.path) keys_auth.key = node.key keys_auth.key_id = node.key peer_session = PeerSession(conn) peer_session.p2p_service = P2PService(node, conf, keys_auth, False) peer_session.p2p_service.metadata_manager = MagicMock() peer_session.send = MagicMock() peer_session.disconnect = MagicMock() peer_session._solve_challenge = MagicMock() def create_verify(value): def verify(*args): return value return verify key_id = 'deadbeef' peer_info = MagicMock() peer_info.key = key_id msg = MessageHello(port=1, node_name='node2', client_key_id=key_id, node_info=peer_info, proto_id=-1) peer_session.verify = create_verify(False) peer_session._react_to_hello(msg) peer_session.disconnect.assert_called_with(PeerSession.DCRUnverified) peer_session.verify = create_verify(True) peer_session._react_to_hello(msg) peer_session.disconnect.assert_called_with( PeerSession.DCRProtocolVersion) msg.proto_id = P2P_PROTOCOL_ID peer_session._react_to_hello(msg) assert key_id in peer_session.p2p_service.peers assert peer_session.p2p_service.peers[key_id] peer_session.p2p_service.peers[key_id] = MagicMock() conn.opened = True peer_session.key_id = None peer_session._react_to_hello(msg) peer_session.disconnect.assert_called_with( PeerSession.DCRDuplicatePeers)
def _react_to_hello(self, msg): if self.verified: logger.error("Received unexpected Hello message, ignoring") return # Check if sender is a seed/bootstrap node port = getattr(msg, 'port', None) if (self.address, port) in self.p2p_service.seeds: compare_version(getattr(msg, 'client_ver', None)) if not self.conn.opened: return proto_id = getattr(msg, 'proto_id', None) if proto_id != variables.PROTOCOL_CONST.ID: logger.info( "P2P protocol version mismatch %r vs %r (local)" " for node %r:%r", proto_id, variables.PROTOCOL_CONST.ID, self.address, self.port) self.disconnect(message.base.Disconnect.REASON.ProtocolVersion) return self.node_info = Node.from_dict(msg.node_info) if not KeysAuth.is_pubkey_difficult(self.node_info.key, self.p2p_service.key_difficulty): logger.info( "Key from %r (%s:%d) is not difficult enough (%d < %d).", self.node_info.node_name, self.address, self.port, KeysAuth.get_difficulty(self.node_info.key), self.p2p_service.key_difficulty) self.disconnect(message.base.Disconnect.REASON.KeyNotDifficult) return self.node_name = msg.node_name self.client_ver = msg.client_ver self.listen_port = msg.port self.key_id = msg.client_key_id self.metadata = msg.metadata solve_challenge = msg.solve_challenge challenge = msg.challenge difficulty = msg.difficulty if not self.__should_init_handshake(): self.__send_hello() if solve_challenge: self._solve_challenge(challenge, difficulty) else: self.send(message.base.RandVal(rand_val=msg.rand_val))
def test_react_to_stop_gossip(self): conn = MagicMock() conf = MagicMock() conf.opt_peer_num = 10 node = Node(node_name='node', key='ffffffff') keys_auth = KeysAuth(self.path) keys_auth.key = node.key keys_auth.key_id = node.key peer_session = PeerSession(conn) peer_session.p2p_service = P2PService(node, conf, keys_auth, False) peer_session.key_id = "NEW KEY_ID" peer_session._react_to_stop_gossip(MessageStopGossip())
def create_client(datadir): # executed in a subprocess from golem.network.stun import pystun pystun.get_ip_info = override_ip_info from golem.client import Client app_config = AppConfig.load_config(datadir) config_desc = ClientConfigDescriptor() config_desc.init_from_app_config(app_config) config_desc.key_difficulty = 0 config_desc.use_upnp = False from golem.core.keysauth import KeysAuth with mock.patch.dict('ethereum.keys.PBKDF2_CONSTANTS', {'c': 1}): keys_auth = KeysAuth( datadir=datadir, private_key_name=faker.Faker().pystr(), password='******', difficulty=config_desc.key_difficulty, ) database = Database( db, fields=DB_FIELDS, models=DB_MODELS, db_dir=datadir) ets = _make_mock_ets() return Client(datadir=datadir, app_config=app_config, config_desc=config_desc, keys_auth=keys_auth, database=database, transaction_system=ets, use_monitor=False, connect_to_known_hosts=False, use_docker_manager=False)
def test_add_task_header(self, *_): keys_auth_2 = KeysAuth( os.path.join(self.path, "2"), 'priv_key', 'password', ) ts = self.ts task_header = get_example_task_header(keys_auth_2.public_key) with self.assertRaises(Exception) as raised: ts.add_task_header(task_header) self.assertEqual(raised.exception.message, "Invalid signature") self.assertEqual(len(ts.get_others_tasks_headers()), 0) task_header["signature"] = keys_auth_2.sign( TaskHeader.dict_to_binary(task_header)) self.assertTrue(ts.add_task_header(task_header)) self.assertEqual(len(ts.get_others_tasks_headers()), 1) task_header = get_example_task_header(keys_auth_2.public_key) task_id2 = task_header["fixed_header"]["task_id"] task_header["signature"] = keys_auth_2.sign( TaskHeader.dict_to_binary(task_header)) self.assertTrue(ts.add_task_header(task_header)) self.assertEqual(len(ts.get_others_tasks_headers()), 2) self.assertTrue(ts.add_task_header(task_header)) self.assertEqual(len(ts.get_others_tasks_headers()), 2) new_header = dict(task_header) new_header["fixed_header"]["task_owner"]["pub_port"] = 9999 new_header["signature"] = keys_auth_2.sign( TaskHeader.dict_to_binary(new_header)) # An attempt to update fixed header should *not* succeed self.assertFalse(ts.add_task_header(new_header)) self.assertEqual(len(ts.get_others_tasks_headers()), 2) saved_task = next(th for th in ts.get_others_tasks_headers() if th["fixed_header"]["task_id"] == task_id2) self.assertEqual(saved_task["signature"], task_header["signature"])
def setUp(self): super().setUp() self.keys_auth = KeysAuth(self.path, 'priv_key', 'password') self.service = P2PService( node=None, config_desc=ClientConfigDescriptor(), keys_auth=self.keys_auth, connect_to_known_hosts=False, ) self.service.seeds = set()
def setUp(self): super(TestP2PService, self).setUp() random.seed() # Mock saving keys as it takes long to compute and isn't needed here KeysAuth._save_private_key = mock.Mock() self.keys_auth = KeysAuth(self.path, 'priv_key', 'password') self.service = P2PService(None, ClientConfigDescriptor(), self.keys_auth, connect_to_known_hosts=False)
def test_save_keys(self): # given keys_dir = KeysAuth._get_or_create_keys_dir(self.path) assert os.listdir(keys_dir) == [] # empty dir key_name = 'priv' # when self._create_keysauth(key_name=key_name) # then self.assertCountEqual(os.listdir(keys_dir), [key_name])
def _gen_data_for_test_react_to_remove_task(self): keys_auth = KeysAuth(self.path, 'priv_key', 'password') previous_ka = self.peer_session.p2p_service.keys_auth self.peer_session.p2p_service.keys_auth = keys_auth # Unknown task owner client = MagicMock() client.datadir = self.path with patch('golem.network.concent.handlers_library.HandlersLibrary' '.register_handler',): task_server = task_server_factory.TaskServer(client=client,) self.peer_session.p2p_service.task_server = task_server peer_mock = MagicMock() self.peer_session.p2p_service.peers["ABC"] = peer_mock task_id = "test_{}".format(uuid.uuid4()) msg = message.p2p.RemoveTask(task_id=task_id) msg.serialize(sign_as=keys_auth._private_key) assert keys_auth.verify(msg.sig, msg.get_short_hash(), keys_auth.key_id) return msg, task_id, previous_ka
def _create_keysauth(self, difficulty=0, key_name=None, password='') -> KeysAuth: if key_name is None: key_name = str(random()) return KeysAuth( datadir=self.path, private_key_name=key_name, password=password, difficulty=difficulty, )
def test_react_to_hello(self): conn = MagicMock() node = Node(node_name='node', key='ffffffff') keys_auth = KeysAuth(self.path) keys_auth.key = node.key keys_auth.key_id = node.key ts = TaskSession(conn) ts.task_server = Mock() ts.disconnect = Mock() ts.send = Mock() def create_verify(value): def verify(*args): return value return verify key_id = 'deadbeef' peer_info = MagicMock() peer_info.key = key_id msg = MessageHello(port=1, node_name='node2', client_key_id=key_id, node_info=peer_info, proto_id=-1) ts.verify = create_verify(False) ts._react_to_hello(msg) ts.disconnect.assert_called_with(TaskSession.DCRUnverified) ts.verify = create_verify(True) ts._react_to_hello(msg) ts.disconnect.assert_called_with(TaskSession.DCRProtocolVersion) msg.proto_id = TASK_PROTOCOL_ID ts._react_to_hello(msg) assert ts.send.called
def test_exception_difficulty(self): # given lower_difficulty = 0 req_difficulty = 7 priv_key = str(random())[2:] assert lower_difficulty < req_difficulty # just in case keys_dir = KeysAuth._get_or_create_keys_dir(self.path) # create key that has difficulty lower than req_difficulty while True: ka = self._create_keysauth(lower_difficulty, priv_key) if not ka.is_difficult(req_difficulty): break shutil.rmtree(keys_dir) # to enable keys regeneration assert KeysAuth.get_difficulty(ka.key_id) >= lower_difficulty assert KeysAuth.get_difficulty(ka.key_id) < req_difficulty # then with self.assertRaisesRegex(Exception, "Loaded key is not difficult enough"): self._create_keysauth(difficulty=req_difficulty, key_name=priv_key)
def test_send_results(self, trust, *_): ccd = ClientConfigDescriptor() ccd.min_price = 11 keys_auth = KeysAuth(self.path, 'priv_key', '') task_header = get_example_task_header(keys_auth.public_key) n = Node.from_dict(task_header["fixed_header"]['task_owner']) ts = self.ts ts._is_address_accessible = Mock(return_value=True) ts.verify_header_sig = lambda x: True ts.client.get_suggested_addr.return_value = "10.10.10.10" ts.client.get_requesting_trust.return_value = ts.max_trust fd, result_file = tempfile.mkstemp() os.close(fd) results = {"data": [result_file]} task_header = get_example_task_header(keys_auth.public_key) task_id = task_header["fixed_header"]["task_id"] assert ts.add_task_header(task_header) assert ts.request_task() subtask_id = idgenerator.generate_new_id_from_id(task_id) subtask_id2 = idgenerator.generate_new_id_from_id(task_id) self.assertTrue(ts.send_results(subtask_id, task_id, results)) self.assertTrue(ts.send_results(subtask_id2, task_id, results)) wtr = ts.results_to_send[subtask_id] self.assertIsInstance(wtr, WaitingTaskResult) self.assertEqual(wtr.subtask_id, subtask_id) self.assertEqual(wtr.result, [result_file]) self.assertEqual(wtr.last_sending_trial, 0) self.assertEqual(wtr.delay_time, 0) self.assertEqual(wtr.owner, n) self.assertEqual(wtr.already_sending, False) self.assertIsNotNone(ts.task_keeper.task_headers.get(task_id)) ctd = ComputeTaskDef() ctd['task_id'] = task_id ctd['subtask_id'] = subtask_id ttc = msg_factories.tasks.TaskToComputeFactory(price=1) ttc.compute_task_def = ctd ts.task_manager.comp_task_keeper.receive_subtask(ttc) prev_call_count = trust.PAYMENT.increase.call_count ts.increase_trust_payment("xyz") self.assertGreater(trust.PAYMENT.increase.call_count, prev_call_count) prev_call_count = trust.PAYMENT.decrease.call_count ts.decrease_trust_payment("xyz") self.assertGreater(trust.PAYMENT.decrease.call_count, prev_call_count) os.remove(result_file)
def test_request_task_concent_required(self, *_): self.ts.client.concent_service.enabled = True self.ts.task_archiver = Mock() keys_auth = KeysAuth(self.path, 'prv_key', '') task_dict = get_example_task_header(keys_auth.public_key) task_dict['fixed_header']['concent_enabled'] = False self.ts.add_task_header(task_dict) self.assertIsNone(self.ts.request_task()) self.ts.task_archiver.add_support_status.assert_called_once_with( task_dict['fixed_header']['task_id'], SupportStatus( False, {UnsupportReason.CONCENT_REQUIRED: True}, ), )
def setUp(self): super().setUp() random.seed() self.peer_session = PeerSession(MagicMock()) node = p2p_factories.Node() keys_auth = KeysAuth(self.path, 'priv_key', 'password') self.peer_session.conn.server = \ self.peer_session.p2p_service = P2PService( node=node, config_desc=clientconfigdescriptor.ClientConfigDescriptor(), keys_auth=keys_auth, connect_to_known_hosts=False, ) client = MagicMock() client.datadir = self.path with patch( 'golem.network.concent.handlers_library.HandlersLibrary' '.register_handler',): self.peer_session.p2p_service.task_server = \ task_server_factory.TaskServer(client=client)
def set_password(self, password: str) -> bool: logger.info("Got password") try: self._keys_auth = KeysAuth( datadir=self._datadir, private_key_name=PRIVATE_KEY, password=password, difficulty=self._config_desc.key_difficulty, ) # When Golem is ready to use different Ethereum account for # payments and identity this should be called only when # idendity was not just created above for the first time. self._ets.backwards_compatibility_privkey( self._keys_auth._private_key, # noqa pylint: disable=protected-access password, ) self._ets.set_password(password) except WrongPassword: logger.info("Password incorrect") return False return True
def key_gen(d: int): return KeysAuth._generate_keys(difficulty=d)
def key_exists(self) -> bool: return KeysAuth.key_exists(self._datadir, PRIVATE_KEY)
def test_request(self, tar, *_): ccd = ClientConfigDescriptor() ccd.min_price = 10 n = NodeFactory() ts = TaskServer( node=n, config_desc=ccd, client=self.client, use_docker_manager=False, task_archiver=tar, ) ts.verify_header_sig = lambda x: True self.ts = ts ts._is_address_accessible = Mock(return_value=True) ts.client.get_suggested_addr.return_value = "10.10.10.10" ts.client.get_suggested_conn_reverse.return_value = False ts.client.get_requesting_trust.return_value = 0.3 self.assertIsInstance(ts, TaskServer) self.assertIsNone(ts.request_task()) keys_auth = KeysAuth(self.path, 'prv_key', '') task_header = get_example_task_header(keys_auth.public_key) task_id = task_header["fixed_header"]["task_id"] ts.add_task_header(task_header) self.assertEqual(ts.request_task(), task_id) assert ts.remove_task_header(task_id) task_header = get_example_task_header(keys_auth.public_key) task_header["fixed_header"]["task_owner"]["pub_port"] = 0 task_id2 = task_header["fixed_header"]["task_id"] self.assertTrue(ts.add_task_header(task_header)) self.assertIsNotNone(ts.task_keeper.task_headers[task_id2]) # FIXME FIx this test # self.assertIsNone(ts.request_task()) # self.assertIsNone(ts.task_keeper.task_headers.get(task_id2)) # assert not ts.remove_task_header(task_id2) # FIXME remove me ts.remove_task_header(task_id2) # Task can be rejected for 3 reasons at this stage; in all cases # the task should be reported TaskArchiver listed as unsupported: # 1. Requestor's trust level is too low tar.reset_mock() ts.config_desc.requesting_trust = 0.5 task_header = get_example_task_header(keys_auth.public_key) task_id3 = task_header["fixed_header"]["task_id"] ts.add_task_header(task_header) self.assertIsNone(ts.request_task()) tar.add_support_status.assert_called_with( task_id3, SupportStatus(False, {UnsupportReason.REQUESTOR_TRUST: 0.3})) assert ts.remove_task_header(task_id3) # 2. Task's max price is too low tar.reset_mock() ts.config_desc.requesting_trust = 0.0 task_header = get_example_task_header(keys_auth.public_key) task_id4 = task_header["fixed_header"]["task_id"] task_header["fixed_header"]["max_price"] = 1 ts.add_task_header(task_header) self.assertIsNone(ts.request_task()) tar.add_support_status.assert_called_with( task_id4, SupportStatus(False, {UnsupportReason.MAX_PRICE: 1})) assert ts.remove_task_header(task_id4) # 3. Requestor is on a black list. tar.reset_mock() ts.acl.disallow(keys_auth.key_id) task_header = get_example_task_header(keys_auth.public_key) task_id5 = task_header["fixed_header"]["task_id"] ts.add_task_header(task_header) self.assertIsNone(ts.request_task()) tar.add_support_status.assert_called_with( task_id5, SupportStatus(False, {UnsupportReason.DENY_LIST: keys_auth.key_id})) assert ts.remove_task_header(task_id5)
def test_difficulty(self): difficulty = 5 ek = self._create_keysauth(difficulty) assert difficulty <= ek.difficulty assert ek.difficulty == KeysAuth.get_difficulty(ek.key_id)