naeural-client 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. naeural_client/__init__.py +13 -0
  2. naeural_client/_ver.py +13 -0
  3. naeural_client/base/__init__.py +6 -0
  4. naeural_client/base/distributed_custom_code_presets.py +44 -0
  5. naeural_client/base/generic_session.py +1763 -0
  6. naeural_client/base/instance.py +616 -0
  7. naeural_client/base/payload/__init__.py +1 -0
  8. naeural_client/base/payload/payload.py +66 -0
  9. naeural_client/base/pipeline.py +1499 -0
  10. naeural_client/base/plugin_template.py +5209 -0
  11. naeural_client/base/responses.py +209 -0
  12. naeural_client/base/transaction.py +157 -0
  13. naeural_client/base_decentra_object.py +143 -0
  14. naeural_client/bc/__init__.py +3 -0
  15. naeural_client/bc/base.py +1046 -0
  16. naeural_client/bc/chain.py +0 -0
  17. naeural_client/bc/ec.py +324 -0
  18. naeural_client/certs/__init__.py +0 -0
  19. naeural_client/certs/r9092118.ala.eu-central-1.emqxsl.com.crt +22 -0
  20. naeural_client/code_cheker/__init__.py +1 -0
  21. naeural_client/code_cheker/base.py +520 -0
  22. naeural_client/code_cheker/checker.py +294 -0
  23. naeural_client/comm/__init__.py +2 -0
  24. naeural_client/comm/amqp_wrapper.py +338 -0
  25. naeural_client/comm/mqtt_wrapper.py +539 -0
  26. naeural_client/const/README.md +3 -0
  27. naeural_client/const/__init__.py +9 -0
  28. naeural_client/const/base.py +101 -0
  29. naeural_client/const/comms.py +80 -0
  30. naeural_client/const/environment.py +26 -0
  31. naeural_client/const/formatter.py +7 -0
  32. naeural_client/const/heartbeat.py +111 -0
  33. naeural_client/const/misc.py +20 -0
  34. naeural_client/const/payload.py +190 -0
  35. naeural_client/default/__init__.py +1 -0
  36. naeural_client/default/instance/__init__.py +4 -0
  37. naeural_client/default/instance/chain_dist_custom_job_01_plugin.py +54 -0
  38. naeural_client/default/instance/custom_web_app_01_plugin.py +118 -0
  39. naeural_client/default/instance/net_mon_01_plugin.py +45 -0
  40. naeural_client/default/instance/view_scene_01_plugin.py +28 -0
  41. naeural_client/default/session/mqtt_session.py +72 -0
  42. naeural_client/io_formatter/__init__.py +2 -0
  43. naeural_client/io_formatter/base/__init__.py +1 -0
  44. naeural_client/io_formatter/base/base_formatter.py +80 -0
  45. naeural_client/io_formatter/default/__init__.py +3 -0
  46. naeural_client/io_formatter/default/a_dummy.py +51 -0
  47. naeural_client/io_formatter/default/aixp1.py +113 -0
  48. naeural_client/io_formatter/default/default.py +22 -0
  49. naeural_client/io_formatter/io_formatter_manager.py +96 -0
  50. naeural_client/logging/__init__.py +1 -0
  51. naeural_client/logging/base_logger.py +2056 -0
  52. naeural_client/logging/logger_mixins/__init__.py +12 -0
  53. naeural_client/logging/logger_mixins/class_instance_mixin.py +92 -0
  54. naeural_client/logging/logger_mixins/computer_vision_mixin.py +443 -0
  55. naeural_client/logging/logger_mixins/datetime_mixin.py +344 -0
  56. naeural_client/logging/logger_mixins/download_mixin.py +421 -0
  57. naeural_client/logging/logger_mixins/general_serialization_mixin.py +242 -0
  58. naeural_client/logging/logger_mixins/json_serialization_mixin.py +481 -0
  59. naeural_client/logging/logger_mixins/pickle_serialization_mixin.py +301 -0
  60. naeural_client/logging/logger_mixins/process_mixin.py +63 -0
  61. naeural_client/logging/logger_mixins/resource_size_mixin.py +81 -0
  62. naeural_client/logging/logger_mixins/timers_mixin.py +501 -0
  63. naeural_client/logging/logger_mixins/upload_mixin.py +260 -0
  64. naeural_client/logging/logger_mixins/utils_mixin.py +675 -0
  65. naeural_client/logging/small_logger.py +93 -0
  66. naeural_client/logging/tzlocal/__init__.py +20 -0
  67. naeural_client/logging/tzlocal/unix.py +231 -0
  68. naeural_client/logging/tzlocal/utils.py +113 -0
  69. naeural_client/logging/tzlocal/win32.py +151 -0
  70. naeural_client/logging/tzlocal/windows_tz.py +718 -0
  71. naeural_client/plugins_manager_mixin.py +273 -0
  72. naeural_client/utils/__init__.py +2 -0
  73. naeural_client/utils/comm_utils.py +44 -0
  74. naeural_client/utils/dotenv.py +75 -0
  75. naeural_client-2.0.0.dist-info/METADATA +365 -0
  76. naeural_client-2.0.0.dist-info/RECORD +78 -0
  77. naeural_client-2.0.0.dist-info/WHEEL +4 -0
  78. naeural_client-2.0.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,209 @@
1
+ from ..const.payload import NOTIFICATION_CODES, PAYLOAD_DATA
2
+
3
+
4
+ class Response():
5
+ def __init__(self) -> None:
6
+ self.__is_solved = False
7
+ self.__is_good = None
8
+ self.__log = None
9
+
10
+ self.__fail_reason = None
11
+ return
12
+
13
+ def __repr__(self) -> str:
14
+ return f"<Response: {self.__class__.__name__}>"
15
+
16
+ def set_logger(self, log) -> None:
17
+ self.__log = log
18
+
19
+ def P(self, *args, **kwargs):
20
+ if self.__log is None:
21
+ print(*args, **kwargs)
22
+ self.__log.P(*args, **kwargs)
23
+
24
+ def D(self, *args, **kwargs):
25
+ if self.__log is None:
26
+ print(*args, **kwargs)
27
+ self.__log.D(*args, **kwargs)
28
+
29
+ def fail(self, fail_reason: str) -> None:
30
+ self.__is_solved = True
31
+ self.__is_good = False
32
+ self.__fail_reason = fail_reason
33
+ return
34
+
35
+ def success(self) -> None:
36
+ self.__is_good = True
37
+ self.__is_solved = True
38
+ return
39
+
40
+ def is_solved(self) -> bool:
41
+ return self.__is_solved
42
+
43
+ @property
44
+ def fail_reason(self) -> str:
45
+ return self.__fail_reason
46
+
47
+ def is_good_response(self) -> bool:
48
+ return self.__is_good
49
+
50
+ def handle_payload(self, payload: dict) -> None:
51
+ # Implement this method and call self.success() or self.fail(fail_reason) if expected message is received
52
+ return
53
+
54
+ def handle_notification(self, notification: dict) -> None:
55
+ # Implement this method and call self.success() or self.fail(fail_reason) if expected message is received
56
+ return
57
+
58
+ def handle_heartbeat(self, heartbeat) -> None:
59
+ # Implement this method and call self.success() or self.fail(fail_reason) if expected message is received
60
+ return
61
+
62
+
63
+ class PipelineGenericNotificationResponse(Response):
64
+ def __init__(self, node, pipeline_name, success_code, fail_code) -> None:
65
+ super(PipelineGenericNotificationResponse, self).__init__()
66
+
67
+ self.node = node
68
+ self.pipeline_name = pipeline_name
69
+
70
+ self.success_code = success_code
71
+ self.fail_code = fail_code
72
+ return
73
+
74
+ def handle_notification(self, notification: dict) -> None:
75
+ if self.is_solved():
76
+ return
77
+
78
+ session_id = notification.get(PAYLOAD_DATA.SESSION_ID)
79
+ payload_path = notification.get(PAYLOAD_DATA.EE_PAYLOAD_PATH)
80
+ notification_code = notification.get("NOTIFICATION_CODE") # TODO
81
+ notification_message = notification.get(PAYLOAD_DATA.NOTIFICATION)
82
+ node = payload_path[0]
83
+ pipeline = payload_path[1]
84
+
85
+ # ignore session_id for now, until we decide on the behavior of the EE
86
+ same_node = node == self.node
87
+ same_pipeline = pipeline == self.pipeline_name
88
+ notification_code_ok = notification_code == self.success_code
89
+ notification_code_failed = notification_code == self.fail_code
90
+
91
+ if same_node and same_pipeline:
92
+ self.D("Received notification CODE={} for <{}: {}>. Message: {}".format(
93
+ notification_code, node, pipeline, notification_message))
94
+ if notification_code_ok:
95
+ self.success()
96
+ elif notification_code_failed:
97
+ self.fail(notification_message)
98
+ return
99
+
100
+
101
+ class InstanceGenericNotificationResponse(Response):
102
+ def __init__(self, node, pipeline_name, signature, instance_id, success_code, fail_code) -> None:
103
+ super(InstanceGenericNotificationResponse, self).__init__()
104
+
105
+ self.node = node
106
+ self.pipeline_name = pipeline_name
107
+ if signature is not None:
108
+ self.signature = signature.upper()
109
+ self.instance_id = instance_id
110
+
111
+ self.success_code = success_code
112
+ self.fail_code = fail_code
113
+
114
+ return
115
+
116
+ def handle_notification(self, notification: dict) -> None:
117
+ if self.is_solved():
118
+ return
119
+
120
+ session_id = notification.get(PAYLOAD_DATA.SESSION_ID)
121
+ payload_path = notification.get(PAYLOAD_DATA.EE_PAYLOAD_PATH)
122
+ notification_code = notification.get("NOTIFICATION_CODE") # TODO
123
+ notification_message = notification.get(PAYLOAD_DATA.NOTIFICATION)
124
+ notification_info = notification.get(PAYLOAD_DATA.INFO)
125
+ node = payload_path[0]
126
+ pipeline = payload_path[1]
127
+ signature = payload_path[2]
128
+ if signature is not None:
129
+ signature = signature.upper()
130
+ instance_id = payload_path[3]
131
+
132
+ # ignore session_id for now, until we decide on the behavior of the EE
133
+ same_node = node == self.node
134
+ same_pipeline = pipeline == self.pipeline_name
135
+ same_signature = signature == self.signature
136
+ same_instance_id = instance_id == self.instance_id
137
+ notification_code_ok = notification_code == self.success_code
138
+ notification_code_failed = notification_code == self.fail_code
139
+
140
+ if same_node and same_pipeline and same_signature and same_instance_id:
141
+ self.D("Received notification CODE={} for <{}: {}/{}/{}>. Message: {}\nInfo: {}".format(
142
+ notification_code, node, pipeline, signature, instance_id,
143
+ notification_message, notification_info))
144
+ if notification_code_ok:
145
+ self.success()
146
+ elif notification_code_failed:
147
+ self.fail(notification_info)
148
+ return
149
+
150
+
151
+ class PipelineOKResponse(PipelineGenericNotificationResponse):
152
+ def __init__(self, node, pipeline_name) -> None:
153
+ super(PipelineOKResponse, self).__init__(
154
+ node=node,
155
+ pipeline_name=pipeline_name,
156
+ success_code=NOTIFICATION_CODES.PIPELINE_OK,
157
+ fail_code=NOTIFICATION_CODES.PIPELINE_FAILED
158
+ )
159
+ return
160
+
161
+
162
+ class PipelineArchiveResponse(PipelineGenericNotificationResponse):
163
+ def __init__(self, node, pipeline_name) -> None:
164
+ super(PipelineArchiveResponse, self).__init__(
165
+ node=node,
166
+ pipeline_name=pipeline_name,
167
+ success_code=NOTIFICATION_CODES.PIPELINE_ARCHIVE_OK,
168
+ fail_code=NOTIFICATION_CODES.PIPELINE_ARCHIVE_FAILED
169
+ )
170
+ return
171
+
172
+
173
+ class PluginConfigInPauseOKResponse(InstanceGenericNotificationResponse):
174
+ def __init__(self, node, pipeline_name, signature, instance_id) -> None:
175
+ super(PluginConfigInPauseOKResponse, self).__init__(
176
+ node=node,
177
+ pipeline_name=pipeline_name,
178
+ signature=signature,
179
+ instance_id=instance_id,
180
+ success_code=NOTIFICATION_CODES.PLUGIN_CONFIG_IN_PAUSE_OK,
181
+ fail_code=NOTIFICATION_CODES.PLUGIN_CONFIG_IN_PAUSE_FAILED
182
+ )
183
+ return
184
+
185
+
186
+ class PluginConfigOKResponse(InstanceGenericNotificationResponse):
187
+ def __init__(self, node, pipeline_name, signature, instance_id) -> None:
188
+ super(PluginConfigOKResponse, self).__init__(
189
+ node=node,
190
+ pipeline_name=pipeline_name,
191
+ signature=signature,
192
+ instance_id=instance_id,
193
+ success_code=NOTIFICATION_CODES.PLUGIN_CONFIG_OK,
194
+ fail_code=NOTIFICATION_CODES.PLUGIN_CONFIG_FAILED
195
+ )
196
+ return
197
+
198
+
199
+ class PluginInstanceCommandOKResponse(InstanceGenericNotificationResponse):
200
+ def __init__(self, node, pipeline_name, signature, instance_id) -> None:
201
+ super(PluginInstanceCommandOKResponse, self).__init__(
202
+ node=node,
203
+ pipeline_name=pipeline_name,
204
+ signature=signature,
205
+ instance_id=instance_id,
206
+ success_code=NOTIFICATION_CODES.PLUGIN_INSTANCE_COMMAND_OK,
207
+ fail_code=NOTIFICATION_CODES.PLUGIN_INSTANCE_COMMAND_FAILED
208
+ )
209
+ return
@@ -0,0 +1,157 @@
1
+ from PyE2.base.responses import Response
2
+ # from .responses import Response
3
+ from time import time, sleep
4
+
5
+
6
+ class Transaction():
7
+ def __init__(self, log, session_id: str, *, lst_required_responses: list[Response] = None, timeout: int = 0, on_success_callback: callable = None, on_failure_callback: callable = None) -> None:
8
+ self.log = log
9
+ self.session_id = session_id
10
+ self.lst_required_responses = lst_required_responses
11
+ self.timeout = timeout
12
+
13
+ self.on_success_callback = on_success_callback
14
+ self.on_failure_callback = on_failure_callback
15
+
16
+ self.resolved_callback = None
17
+ self.__is_solved = False
18
+ self.__is_finished = False
19
+
20
+ self.start_time = time()
21
+ for response in self.lst_required_responses:
22
+ response.set_logger(log)
23
+
24
+ return
25
+
26
+ def get_unsolved_responses(self) -> list[Response]:
27
+ """
28
+ Returns a list of unsolved responses in the transaction.
29
+
30
+ Returns
31
+ -------
32
+ list[Response]
33
+ List of unsolved responses in the transaction.
34
+ """
35
+ return [response for response in self.lst_required_responses if not response.is_solved()]
36
+
37
+ def is_solved(self) -> bool:
38
+ """
39
+ Returns whether the transaction is solved or not.
40
+ If the transaction is solved in this call, the resolved_callback is set to the appropriate callback function.
41
+
42
+ Returns
43
+ -------
44
+ bool
45
+ Whether the transaction is solved or not.
46
+ """
47
+
48
+ # if the transaction is already solved, return True
49
+ if self.__is_solved:
50
+ return True
51
+
52
+ # first check if all responses are solved
53
+ all_responses_solved = all([response.is_solved() for response in self.lst_required_responses])
54
+ if all_responses_solved:
55
+ self.__is_solved = True
56
+
57
+ all_responses_good = all([response.is_good_response() for response in self.lst_required_responses])
58
+ if all_responses_good:
59
+ self.resolved_callback = self.on_success_callback
60
+ else:
61
+ if not self.on_failure_callback:
62
+ self.resolved_callback = lambda: self.log.P("Transaction failed")
63
+ else:
64
+ fail_reasons = [
65
+ response.fail_reason for response in self.lst_required_responses if not response.is_good_response()]
66
+ self.resolved_callback = lambda: self.on_failure_callback(fail_reasons)
67
+ # endif computing resolved_callback for failure
68
+ # endif computing resolved_callback
69
+ return True
70
+ # endif all responses solved
71
+
72
+ # if the transaction is not solved, check if the transaction has timed out
73
+ elapsed_time = time() - self.start_time
74
+ if self.timeout > 0 and elapsed_time > self.timeout:
75
+ # Timeout occurred
76
+ self.__is_solved = True
77
+
78
+ fail_reason = f"Transaction timeout ({self.timeout}s). Responses not received: "
79
+ fail_reason += ", ".join([str(response) for response in self.lst_required_responses if not response.is_solved()])
80
+
81
+ if not self.on_failure_callback:
82
+ self.resolved_callback = lambda: self.log.P(fail_reason)
83
+ else:
84
+ self.resolved_callback = lambda: self.on_failure_callback([fail_reason])
85
+ return True
86
+
87
+ return False
88
+
89
+ def is_finished(self) -> bool:
90
+ """
91
+ Returns whether the transaction is finished or not.
92
+ A transaction finishes when the callback is called.
93
+
94
+ Returns
95
+ -------
96
+ bool
97
+ Whether the transaction is finished or not.
98
+ """
99
+ return self.__is_finished
100
+
101
+ def handle_payload(self, payload: dict) -> None:
102
+ """
103
+ This method is called when a payload is received from the server.
104
+ This method calls `handle_payload()` method of all the unsolved responses in the `lst_required_responses`.
105
+
106
+ Parameters
107
+ ----------
108
+ payload : dict
109
+ The payload received from the server.
110
+ """
111
+ unsolved_responses = self.get_unsolved_responses()
112
+
113
+ for response in unsolved_responses:
114
+ response.handle_payload(payload)
115
+ return
116
+
117
+ def handle_notification(self, notification: dict) -> None:
118
+ """
119
+ This method is called when a notification is received from the server.
120
+ This method calls `handle_notification()` method of all the unsolved responses in the `lst_required_responses`.
121
+
122
+ Parameters
123
+ ----------
124
+ notification : dict
125
+ The notification received from the server.
126
+ """
127
+ unsolved_responses = self.get_unsolved_responses()
128
+
129
+ for response in unsolved_responses:
130
+ response.handle_notification(notification)
131
+ return
132
+
133
+ def handle_heartbeat(self, heartbeat) -> None:
134
+ """
135
+ This method is called when a heartbeat is received from the server.
136
+ This method calls `handle_heartbeat()` method of all the unsolved responses in the `lst_required_responses`.
137
+
138
+ Parameters
139
+ ----------
140
+ heartbeat : dict
141
+ The heartbeat received from the server.
142
+ """
143
+ unsolved_responses = self.get_unsolved_responses()
144
+
145
+ for response in unsolved_responses:
146
+ response.handle_heartbeat(heartbeat)
147
+ return
148
+
149
+ def callback(self):
150
+ """
151
+ Calls the resolved_callback only if the transaction is solved.
152
+ """
153
+ if self.__is_solved:
154
+ if self.resolved_callback:
155
+ self.resolved_callback()
156
+ self.__is_finished = True
157
+ return
@@ -0,0 +1,143 @@
1
+ from .logging import Logger
2
+
3
+
4
+ class BaseDecentrAIObject(object):
5
+ """
6
+ Generic class
7
+
8
+ Instructions:
9
+
10
+ 1. use `super().__init__(**kwargs)` at the end of child `__init__`
11
+ 2. define `startup(self)` method for the child class and call
12
+ `super().startup()` at beginning of `startup()` method
13
+
14
+ OR
15
+
16
+ use `super().__init__(**kwargs)` at beginning of child `__init__` and then
17
+ you can safely proceed with other initilization
18
+
19
+ """
20
+
21
+ def __init__(self, log: Logger,
22
+ create_logger=False,
23
+ DEBUG=False,
24
+ show_prefixes=False,
25
+ prefix_log=None,
26
+ log_at_startup=False,
27
+ **kwargs):
28
+
29
+ super(BaseDecentrAIObject, self).__init__()
30
+
31
+ if (log is None) or not hasattr(log, '_logger'):
32
+ if not create_logger:
33
+ raise ValueError("Logger object is invalid: {}".format(log))
34
+ else:
35
+ log = Logger(DEBUG=DEBUG, base_folder='.', app_folder='_local_cache')
36
+ # endif
37
+
38
+ self.log = log
39
+ self.show_prefixes = show_prefixes
40
+ self.prefix_log = prefix_log
41
+ self.config_data = self.log.config_data
42
+ self.DEBUG = DEBUG
43
+ self.log_at_startup = log_at_startup
44
+
45
+ if not hasattr(self, '__name__'):
46
+ self.__name__ = self.__class__.__name__
47
+ self.startup()
48
+
49
+ return
50
+
51
+ def startup(self):
52
+ self.log.set_nice_prints()
53
+ ver = ''
54
+ if hasattr(self, '__version__'):
55
+ ver = 'v.' + self.__version__
56
+ if hasattr(self, 'version'):
57
+ ver = 'v.' + self.version
58
+
59
+ if self.log_at_startup:
60
+ self.P("{}{} startup.".format(self.__class__.__name__, ' ' + ver if ver != '' else ''))
61
+ return
62
+
63
+ def shutdown(self):
64
+ self.P("Shutdown in progress...")
65
+ _VARS = ['sess', 'session']
66
+ for var_name in _VARS:
67
+ if vars(self).get(var_name, None) is not None:
68
+ self.P("Warning: {} property {} still not none before closing".format(
69
+ self.__class__.__name__, var_name), color='r')
70
+ return
71
+
72
+ def P(self, s, t=False, color=None, prefix=False, **kwargs):
73
+ if self.show_prefixes or prefix:
74
+ msg = "[{}] {}".format(self.__name__, s)
75
+ else:
76
+ if self.prefix_log is None:
77
+ msg = "{}".format(s)
78
+ else:
79
+ msg = "{} {}".format(self.prefix_log, s)
80
+ # endif
81
+ # endif
82
+
83
+ _r = self.log.P(msg, show_time=t, color=color, **kwargs)
84
+ return _r
85
+
86
+ def D(self, s, t=False, color=None, prefix=False, **kwargs):
87
+ _r = -1
88
+ if self.DEBUG:
89
+ if self.show_prefixes:
90
+ msg = "[DEBUG] {}: {}".format(self.__name__, s)
91
+ else:
92
+ if self.prefix_log is None:
93
+ msg = "[DEBUG] {}".format(s)
94
+ else:
95
+ msg = "[DEBUG]{} {}".format(self.prefix_log, s)
96
+ # endif
97
+ # endif
98
+ _r = self.log.P(msg, show_time=t, color=color, prefix=prefix, **kwargs)
99
+ # endif
100
+ return _r
101
+
102
+ def start_timer(self, tmr_id):
103
+ if hasattr(self, '_timers_section'):
104
+ return self.log.start_timer(tmr_id, section=self._timers_section)
105
+ else:
106
+ return self.log.start_timer(sname=self.__name__ + '_' + tmr_id)
107
+
108
+ def end_timer(self, tmr_id, skip_first_timing=True, **kwargs):
109
+ if hasattr(self, '_timers_section'):
110
+ return self.log.end_timer(tmr_id, section=self._timers_section)
111
+ else:
112
+ return self.log.end_timer(
113
+ sname=self.__name__ + '_' + tmr_id,
114
+ skip_first_timing=skip_first_timing,
115
+ **kwargs
116
+ )
117
+
118
+ def raise_error(self, error_text):
119
+ """
120
+ logs the error and raises it
121
+ """
122
+ self.P("{}: {}".format(self.__class__.__name__, error_text))
123
+ raise ValueError(error_text)
124
+
125
+ def timer_name(self, name=''):
126
+ tn = ''
127
+ if name == '':
128
+ tn = self.__class__.__name__
129
+ else:
130
+ tn = '{}__{}'.format(self.__class__.__name__, name)
131
+ return tn
132
+
133
+ def __repr__(self):
134
+ # Get the name of the class
135
+ class_name = self.__class__.__name__
136
+
137
+ # Get public properties (those not starting with "_")
138
+ public_properties = {k: v for k, v in self.__dict__.items() if not k.startswith("_")}
139
+
140
+ # Convert properties to a string representation
141
+ properties_str = ", ".join(f"{k}={v!r}" for k, v in public_properties.items())
142
+
143
+ return f"{class_name}({properties_str})"
@@ -0,0 +1,3 @@
1
+ from .ec import BaseBCEllipticCurveEngine
2
+ from .base import BCct, _DotDict, _ComplexJsonEncoder, VerifyMessage
3
+ DefaultBlockEngine = BaseBCEllipticCurveEngine