def wait_timer_from_serialized(cls, serialized_timer, signature): """ Takes wait timer that has been serialized to JSON and reconstitutes into an EnclaveWaitTimer object. Args: serialized_timer (str): JSON serialized wait timer signature (str): Signature over serialized timer Returns: An EnclaveWaitTimer object """ deserialized_timer = json2dict(serialized_timer) timer = \ EnclaveWaitTimer( duration=float(deserialized_timer.get( 'duration')), previous_certificate_id=str(deserialized_timer.get( 'previous_certificate_id')), local_mean=float(deserialized_timer.get( 'local_mean')), signature=signature, serialized_timer=serialized_timer) timer.request_time = float(deserialized_timer.get('request_time')) return timer
def wait_timer_from_serialized(cls, serialized_timer, signature): """ Takes wait timer that has been serialized to JSON and reconstitutes into an EnclaveWaitTimer object. Args: serialized_timer (str): JSON serialized wait timer signature (str): Signature over serialized timer Returns: An EnclaveWaitTimer object """ deserialized_timer = json2dict(serialized_timer) timer = \ EnclaveWaitTimer( validator_address=str(deserialized_timer.get( 'validator_address')), duration=float(deserialized_timer.get( 'duration')), previous_certificate_id=str(deserialized_timer.get( 'previous_certificate_id')), local_mean=float(deserialized_timer.get( 'local_mean')), signature=signature, serialized_timer=serialized_timer) timer.request_time = float(deserialized_timer.get('request_time')) return timer
def wait_certificate_from_serialized(cls, serialized_certificate, signature): """ Takes wait certificate that has been serialized to JSON and reconstitutes into an EnclaveWaitCertificate object. Args: serialized_certificate (str): JSON serialized wait certificate signature (str): Signature over serialized certificate Returns: An EnclaveWaitCertificate object """ deserialized_certificate = json2dict(serialized_certificate) certificate = \ EnclaveWaitCertificate( duration=float(deserialized_certificate.get('duration')), previous_certificate_id=str( deserialized_certificate.get('previous_certificate_id')), local_mean=float(deserialized_certificate.get('local_mean')), request_time=float( deserialized_certificate.get('request_time')), nonce=str(deserialized_certificate.get('nonce')), block_digest=str(deserialized_certificate.get( 'block_digest')), signature=signature, serialized_certificate=serialized_certificate) return certificate
def signup_info_from_serialized(cls, serialized_signup_info): """ Takes signup information that has been serialized to JSON and reconstitutes into an EnclaveSignupInfo object. Args: serialized_signup_info: JSON serialized signup info Returns: An EnclaveSignupInfo object with sealed signup info data stripped out as serialized signup info doesn't contain it. """ deserialized_signup_info = json2dict(serialized_signup_info) # Note - serialized signup info shouldn't have sealed signup # data. signup_info = \ EnclaveSignupInfo( poet_public_key=deserialized_signup_info.get( 'poet_public_key'), proof_data=deserialized_signup_info.get( 'proof_data'), anti_sybil_id=deserialized_signup_info.get( 'anti_sybil_id'), serialized_signup_info=serialized_signup_info) return signup_info
def wait_certificate_from_serialized(cls, serialized_certificate, signature): """ Takes wait certificate that has been serialized to JSON and reconstitutes into an EnclaveWaitCertificate object. Args: serialized_certificate (str): JSON serialized wait certificate signature (str): Signature over serialized certificate Returns: An EnclaveWaitCertificate object """ deserialized_certificate = json2dict(serialized_certificate) certificate = \ EnclaveWaitCertificate( duration=float(deserialized_certificate.get('duration')), previous_certificate_id=str( deserialized_certificate.get('previous_certificate_id')), local_mean=float(deserialized_certificate.get('local_mean')), request_time=float( deserialized_certificate.get('request_time')), nonce=str(deserialized_certificate.get('nonce')), block_digest=str(deserialized_certificate.get( 'block_digest'))) certificate.signature = signature return certificate
def unseal_signup_data(cls, sealed_signup_data): """ Args: sealed_signup_data: Sealed signup data that was returned previously in a EnclaveSignupInfo object from a call to create_signup_info Returns: A string The hex encoded PoET public key that was extracted from the sealed data """ # Reverse the process we used in creating "sealed" signup info. # Specifically, we will do a base 32 decode, which gives us json # we can convert back to a dictionary we can use to get the # data we need signup_data = \ json2dict(pybitcointools.base64.b32decode(sealed_signup_data)) with cls._lock: cls._poet_public_key = \ pybitcointools.decode_pubkey( signup_data.get('poet_public_key'), 'hex') cls._poet_private_key = \ pybitcointools.decode_privkey( signup_data.get('poet_public_key'), 'hex') cls._active_wait_timer = None return signup_data.get('poet_public_key')
def unseal_signup_data(cls, sealed_signup_data): """ Args: sealed_signup_data: Sealed signup data that was returned previously in a EnclaveSignupInfo object from a call to create_signup_info Returns: A string The hex encoded PoET public key that was extracted from the sealed data """ # Reverse the process we used in creating "sealed" signup info. # Specifically, we will do a base 32 decode, which gives us json # we can convert back to a dictionary we can use to get the # data we need signup_data = \ json2dict(base64.b64decode(sealed_signup_data)) with cls._lock: cls._poet_public_key = \ signing.decode_pubkey( signup_data.get('poet_public_key'), 'hex') cls._poet_private_key = \ signing.decode_privkey( signup_data.get('poet_private_key'), 'hex') cls._active_wait_timer = None return signup_data.get('poet_public_key')
def signup_info_from_serialized(cls, serialized): deserialized = json2dict(serialized) return \ SignupInfo( anti_sybil_id=deserialized.get('anti_sybil_id'), poet_public_key=deserialized.get('poet_public_key'), proof_data=deserialized.get('proof_data'))
def _parse(self, lines): cpattern = re.compile('##.*$') text = "" for line in lines: text += re.sub(cpattern, '', line) + ' ' json_dict = json2dict(text) self.update(json_dict)
def verify_signup_info(cls, signup_info, originator_public_key_hash, most_recent_wait_certificate_id): # Verify the attestation verification report signature proof_data = json2dict(signup_info.proof_data) verification_report = proof_data.get('verification_report') if verification_report is None: raise \ SignupInfoError( 'Verification report is missing from proof data') if not pybitcointools.ecdsa_verify(verification_report, proof_data.get('signature'), cls._report_public_key): raise \ SignupInfoError('Verification report signature is invalid') # Verify that the report data field in the report contains the SHA256 # digest of the originator's public key SHA 256 digest and the PoET # public key. verification_report_dict = json2dict(verification_report) enclave_quote = verification_report_dict.get('enclave_quote') if enclave_quote is None: raise \ SignupInfoError( 'Verification report does not contain an enclave quote') report = json2dict(pybitcointools.base64.b64decode(enclave_quote)) report_data = report.get('report_data') if report_data is None: raise \ SignupInfoError('Enclave quote does not contain report data') target_report_data = { 'originator_public_key_hash': originator_public_key_hash.upper(), 'poet_public_key': signup_info.poet_public_key.upper() } target_report_data_digest = \ pybitcointools.sha256(dict2json(target_report_data)) if report_data != target_report_data_digest: raise SignupInfoError('Enclave quote report data is invalid')
def postmsg(self, msgtype, info): """ Post a transaction message to the validator, parse the returning CBOR and return the corresponding dictionary. """ logger.debug(dict2json(info)) data = dict2cbor(info) datalen = len(data) url = self.BaseURL + msgtype logger.debug( 'post transaction to %s with DATALEN=%d, ' 'base64(DATA)=<%s>', url, datalen, base64.b64encode(data)) try: request = urllib2.Request(url, data, { 'Content-Type': 'application/cbor', 'Content-Length': datalen }) opener = urllib2.build_opener(self.ProxyHandler) response = opener.open(request, timeout=10) except urllib2.HTTPError as err: logger.warn('operation failed with response: %s', err.code) raise MessageException( 'operation failed with response: {0}'.format(err.code)) except urllib2.URLError as err: logger.warn('operation failed: %s', err.reason) raise MessageException('operation failed: {0}'.format(err.reason)) except: logger.warn('no response from server') raise MessageException('no response from server') content = response.read() headers = response.info() response.close() encoding = headers.get('Content-Type') if encoding == 'application/json': value = json2dict(content) elif encoding == 'application/cbor': value = cbor2dict(content) else: logger.info('server responds with message %s of type %s', content, encoding) return None logger.debug(pretty_print_dict(value)) return value
def parse_configuration_file(filename): cpattern = re.compile('##.*$') with open(filename) as fp: lines = fp.readlines() text = "" for line in lines: text += re.sub(cpattern, '', line) + ' ' return json2dict(text)
def postmsg(self, msgtype, info): """ Post a transaction message to the validator, parse the returning CBOR and return the corresponding dictionary. """ logger.debug(dict2json(info)) data = dict2cbor(info) datalen = len(data) url = self.BaseURL + msgtype logger.debug('post transaction to %s with DATALEN=%d, ' 'base64(DATA)=<%s>', url, datalen, base64.b64encode(data)) try: request = urllib2.Request(url, data, {'Content-Type': 'application/cbor', 'Content-Length': datalen}) opener = urllib2.build_opener(self.ProxyHandler) response = opener.open(request, timeout=10) except urllib2.HTTPError as err: logger.warn('operation failed with response: %s', err.code) raise MessageException( 'operation failed with response: {0}'.format(err.code)) except urllib2.URLError as err: logger.warn('operation failed: %s', err.reason) raise MessageException('operation failed: {0}'.format(err.reason)) except: logger.warn('no response from server') raise MessageException('no response from server') content = response.read() headers = response.info() response.close() encoding = headers.get('Content-Type') if encoding == 'application/json': value = json2dict(content) elif encoding == 'application/cbor': value = cbor2dict(content) else: logger.info('server responds with message %s of type %s', content, encoding) return None logger.debug(pretty_print_dict(value)) return value
def render_post(self, request, components, msg): """ Process validator control commands """ encoding = request.getHeader('Content-Type') data = request.content.getvalue() try: if encoding == 'application/json': minfo = json2dict(data) else: raise Error( "", 'unknown message' ' encoding: {0}'.format(encoding)) except Error as e: LOGGER.info('exception while decoding http request %s; %s', request.path, traceback.format_exc(20)) raise Error(http.BAD_REQUEST, 'unable to decode incoming request {0}'.format(str(e))) # process /command try: if minfo['action'] == 'start': if self.Validator.delaystart is True: self.Validator.delaystart = False LOGGER.info("command received : %s", minfo['action']) minfo['action'] = 'started' else: LOGGER.warn("validator startup not delayed") minfo['action'] = 'running' else: LOGGER.warn("unknown command received") minfo['action'] = 'startup failed' request.responseHeaders.addRawHeader("content-type", encoding) result = dict2json(minfo) return result except Error as e: raise Error( int(e.status), 'exception while processing' ' request {0}; {1}'.format(request.path, str(e))) except: LOGGER.info('exception while processing http request %s; %s', request.path, traceback.format_exc(20)) raise Error( http.BAD_REQUEST, 'error processing http request' ' {0}'.format(request.path)) return msg
def getmsg(self, path): """ Send an HTTP get request to the validator. If the resulting content is in JSON form, parse it & return the corresponding dictionary. """ url = "{0}/{1}".format(self.BaseURL, path.strip('/')) logger.debug('get content from url <%s>', url) try: request = urllib2.Request(url, headers=self.GET_HEADER) opener = urllib2.build_opener(self.ProxyHandler) if path == '/prevalidation': if self._cookie: request.add_header('cookie', self._cookie) response = opener.open(request, timeout=10) except urllib2.HTTPError as err: logger.warn('operation failed with response: %s', err.code) self._print_error_information_from_server(err) raise MessageException( 'operation failed with response: {0}'.format(err.code)) except urllib2.URLError as err: logger.warn('operation failed: %s', err.reason) raise MessageException('operation failed: {0}'.format(err.reason)) except: logger.warn('no response from server') raise MessageException('no response from server') content = response.read() headers = response.info() response.close() encoding = headers.get('Content-Type') if encoding == 'application/json': value = json2dict(content) elif encoding == 'application/cbor': value = cbor2dict(content) else: logger.debug('get content <%s> from url <%s>', content, url) return content logger.debug(pretty_print_dict(value)) return value
def render_post(self, request, components, msg): """ Process validator control commands """ encoding = request.getHeader('Content-Type') data = request.content.getvalue() try: if encoding == 'application/json': minfo = json2dict(data) else: raise Error("", 'unknown message' ' encoding: {0}'.format(encoding)) except Error as e: LOGGER.info('exception while decoding http request %s; %s', request.path, traceback.format_exc(20)) raise Error(http.BAD_REQUEST, 'unable to decode incoming request {0}'.format(str(e))) # process /command try: if minfo['action'] == 'start': if self.Validator.delaystart is True: self.Validator.delaystart = False LOGGER.info("command received : %s", minfo['action']) minfo['action'] = 'started' else: LOGGER.warn("validator startup not delayed") minfo['action'] = 'running' else: LOGGER.warn("unknown command received") minfo['action'] = 'startup failed' request.responseHeaders.addRawHeader("content-type", encoding) result = dict2json(minfo) return result except Error as e: raise Error(int(e.status), 'exception while processing' ' request {0}; {1}'.format(request.path, str(e))) except: LOGGER.info('exception while processing http request %s; %s', request.path, traceback.format_exc(20)) raise Error(http.BAD_REQUEST, 'error processing http request' ' {0}'.format(request.path)) return msg
def _geturl(self, url, verbose=True, timeout=30): """ Send an HTTP get request to the validator. If the resulting content is in JSON or CBOR form, parse it & return the corresponding dictionary. """ if verbose: LOGGER.debug('get content from url <%s>', url) try: request = urllib2.Request(url, headers=self.GET_HEADER) opener = urllib2.build_opener(self.proxy_handler) response = opener.open(request, timeout=timeout) except urllib2.HTTPError as err: if verbose: LOGGER.error( 'peer operation on url %s failed ' 'with response: %d', url, err.code) raise MessageException('operation failed ' 'with response: {0}'.format(err.code)) except urllib2.URLError as err: if verbose: LOGGER.error('peer operation on url %s failed: %s', url, err.reason) raise MessageException('operation failed: {0}'.format(err.reason)) except: if verbose: LOGGER.error('no response from peer server for url %s; %s', url, sys.exc_info()[0]) raise MessageException('no response from server') content = response.read() headers = response.info() response.close() encoding = headers.get('Content-Type') if encoding == 'application/json': return json2dict(content) elif encoding == 'application/cbor': return cbor2dict(content) else: return content
def _geturl(self, url, verbose=True, timeout=30): """ Send an HTTP get request to the validator. If the resulting content is in JSON or CBOR form, parse it & return the corresponding dictionary. """ if verbose: LOGGER.debug('get content from url <%s>', url) try: request = urllib2.Request(url, headers=self.GET_HEADER) opener = urllib2.build_opener(self.proxy_handler) response = opener.open(request, timeout=timeout) except urllib2.HTTPError as err: if verbose: LOGGER.error('peer operation on url %s failed ' 'with response: %d', url, err.code) raise MessageException('operation failed ' 'with response: {0}'.format(err.code)) except urllib2.URLError as err: if verbose: LOGGER.error('peer operation on url %s failed: %s', url, err.reason) raise MessageException('operation failed: {0}'.format(err.reason)) except: if verbose: LOGGER.error('no response from peer server for url %s; %s', url, sys.exc_info()[0]) raise MessageException('no response from server') content = response.read() headers = response.info() response.close() encoding = headers.get('Content-Type') if encoding == 'application/json': return json2dict(content) elif encoding == 'application/cbor': return cbor2dict(content) else: return content
def _get_message(self, request): encoding = request.getHeader('Content-Type') data = request.content.getvalue() if encoding == 'application/json': minfo = json2dict(data) elif encoding == 'application/cbor': minfo = cbor2dict(data) else: return self._encode_error_response( request, http.BAD_REQUEST, 'unknown message' ' encoding: {0}'.format(encoding)) typename = minfo.get('__TYPE__', '**UNSPECIFIED**') if typename not in self.Ledger.gossip.MessageHandlerMap: return self._encode_error_response( request, http.NOT_FOUND, 'received request for unknown message' ' type, {0}'.format(typename)) return self.Ledger.gossip.MessageHandlerMap[typename][0](minfo)
def getmsg(self, path, timeout=10): """ Send an HTTP get request to the validator. If the resulting content is in JSON form, parse it & return the corresponding dictionary. """ url = urlparse.urljoin(self._base_url, path) LOGGER.debug('get content from url <%s>', url) try: request = urllib2.Request(url) opener = urllib2.build_opener(self._proxy_handler) response = opener.open(request, timeout=timeout) except urllib2.HTTPError as err: LOGGER.warn('operation failed with response: %s', err.code) self._print_error_information_from_server(err) raise MessageException( 'operation failed with response: {0}'.format(err.code)) except urllib2.URLError as err: LOGGER.warn('operation failed: %s', err.reason) raise MessageException('operation failed: {0}'.format(err.reason)) except: LOGGER.warn('no response from server') raise MessageException('no response from server') content = response.read() headers = response.info() response.close() encoding = headers.get('Content-Type') if encoding == 'application/json': return json2dict(content) elif encoding == 'application/cbor': return cbor2dict(content) else: return content
def ParseConfigurationFile(filename, variable_map): """ Parse a configuration file expanding variable references using the Python Template library (variables are $var format) :param string filename: name of the configuration file :param dict variable_map: dictionary of expansions to use :returns dict: dictionary of configuration information """ cpattern = re.compile('##.*$') with open(filename) as fp: lines = fp.readlines() text = "" for line in lines: text += re.sub(cpattern, '', line) + ' ' if variable_map: text = Template(text).substitute(variable_map) return json2dict(text)
def _get_message(self, request): encoding = request.getHeader('Content-Type') data = request.content.getvalue() if encoding == 'application/json': minfo = json2dict(data) elif encoding == 'application/cbor': minfo = cbor2dict(data) else: return self._encode_error_response( request, http.BAD_REQUEST, 'unknown message' ' encoding: {0}'.format(encoding)) typename = minfo.get('__TYPE__', '**UNSPECIFIED**') if not self.validator.gossip.dispatcher.has_message_handler(typename): return self._encode_error_response( request, http.NOT_FOUND, 'received request for unknown message' ' type, {0}'.format(typename)) return self.validator.gossip.dispatcher.unpack_message(typename, minfo)
def _get_message(self, request): encoding = request.getHeader('Content-Type') data = request.content.getvalue() if encoding == 'application/json': minfo = json2dict(data) elif encoding == 'application/cbor': minfo = cbor2dict(data) else: return self._encode_error_response( request, http.BAD_REQUEST, 'unknown message' ' encoding: {0}'.format(encoding)) typename = minfo.get('__TYPE__', '**UNSPECIFIED**') if typename not in self.Ledger.MessageHandlerMap: return self._encode_error_response( request, http.NOT_FOUND, 'received request for unknown message' ' type, {0}'.format(typename)) return self.Ledger.MessageHandlerMap[typename][0](minfo)
def signup_info_from_serialized(cls, serialized_signup_info): """ Takes signup information that has been serialized to JSON and reconstitutes into an EnclaveSignupInfo object. Args: serialized_signup_info: JSON serialized signup info Returns: An EnclaveSignupInfo object """ deserialized_signup_info = json2dict(serialized_signup_info) return \ EnclaveSignupInfo( anti_sybil_id=deserialized_signup_info.get( 'anti_sybil_id'), poet_public_key=deserialized_signup_info.get( 'poet_public_key'), proof_data=deserialized_signup_info.get( 'proof_data'), sealed_signup_data=deserialized_signup_info.get( 'sealed_signup_data'))
def _posturl(self, url, info, encoding='application/cbor'): """ Post a transaction message to the validator, parse the returning CBOR and return the corresponding dictionary. """ if encoding == 'application/json': data = dict2json(info) elif encoding == 'application/cbor': data = dict2cbor(info) else: LOGGER.error('unknown request encoding %s', encoding) return None datalen = len(data) LOGGER.debug('post transaction to %s with DATALEN=%d, DATA=<%s>', url, datalen, data) try: request = urllib2.Request(url, data, { 'Content-Type': 'application/cbor', 'Content-Length': datalen }) opener = urllib2.build_opener(self.proxy_handler) response = opener.open(request, timeout=10) except urllib2.HTTPError as err: LOGGER.error('peer operation on url %s failed with response: %d', url, err.code) raise MessageException( 'operation failed with response: {0}'.format(err.code)) except urllib2.URLError as err: LOGGER.error('peer operation on url %s failed: %s', url, err.reason) raise MessageException('operation failed: {0}'.format(err.reason)) except NameError as err: LOGGER.error('name error %s', err) raise MessageException('operation failed: {0}'.format(url)) except: LOGGER.error('no response from peer server for url %s; %s', url, sys.exc_info()[0]) raise MessageException('no response from server') content = response.read() headers = response.info() response.close() encoding = headers.get('Content-Type') if encoding == 'application/json': value = json2dict(content) elif encoding == 'application/cbor': value = cbor2dict(content) else: LOGGER.info('server responds with message %s of unknown type %s', content, encoding) value = OrderedDict() return value
def _posturl(self, url, info, encoding='application/cbor'): """ Post a transaction message to the validator, parse the returning CBOR and return the corresponding dictionary. """ if encoding == 'application/json': data = dict2json(info) elif encoding == 'application/cbor': data = dict2cbor(info) else: LOGGER.error('unknown request encoding %s', encoding) return None datalen = len(data) LOGGER.debug('post transaction to %s with DATALEN=%d, DATA=<%s>', url, datalen, data) try: request = urllib2.Request(url, data, {'Content-Type': 'application/cbor', 'Content-Length': datalen}) opener = urllib2.build_opener(self.proxy_handler) response = opener.open(request, timeout=10) except urllib2.HTTPError as err: LOGGER.error('peer operation on url %s failed with response: %d', url, err.code) raise MessageException('operation failed with resonse: {0}'.format( err.code)) except urllib2.URLError as err: LOGGER.error('peer operation on url %s failed: %s', url, err.reason) raise MessageException('operation failed: {0}'.format(err.reason)) except NameError as err: LOGGER.error('name error %s', err) raise MessageException('operation failed: {0}'.format(url)) except: LOGGER.error('no response from peer server for url %s; %s', url, sys.exc_info()[0]) raise MessageException('no response from server') content = response.read() headers = response.info() response.close() encoding = headers.get('Content-Type') if encoding == 'application/json': value = json2dict(content) elif encoding == 'application/cbor': value = cbor2dict(content) else: LOGGER.info('server responds with message %s of unknown type %s', content, encoding) value = OrderedDict() return value
def render_POST(self, request): """ Handle a POST request on the HTTP interface. All message on the POST interface are gossip messages that should be relayed into the gossip network as is. """ # pylint: disable=invalid-name # break the path into its component parts components = request.path.split('/') while components and components[0] == '': components.pop(0) prefix = components.pop(0) if components else 'error' if prefix not in self.PostPageMap: prefix = 'default' # process the message encoding encoding = request.getHeader('Content-Type') data = request.content.getvalue() try: if encoding == 'application/json': minfo = json2dict(data) elif encoding == 'application/cbor': minfo = cbor2dict(data) else: return self.error_response(request, http.BAD_REQUEST, 'unknown message encoding, {0}', encoding) typename = minfo.get('__TYPE__', '**UNSPECIFIED**') if typename not in self.Ledger.MessageHandlerMap: return self.error_response( request, http.BAD_REQUEST, 'received request for unknown message type, {0}', typename) msg = self.Ledger.MessageHandlerMap[typename][0](minfo) except: logger.info('exception while decoding http request %s; %s', request.path, traceback.format_exc(20)) return self.error_response( request, http.BAD_REQUEST, 'unabled to decode incoming request {0}', data) # and finally execute the associated method and send back the results try: response = self.PostPageMap[prefix](request, components, msg) request.responseHeaders.addRawHeader("content-type", encoding) if encoding == 'application/json': result = dict2json(response.dump()) else: result = dict2cbor(response.dump()) return result except Error as e: return self.error_response( request, int(e.status), 'exception while processing request {0}; {1}', request.path, str(e)) except: logger.info('exception while processing http request %s; %s', request.path, traceback.format_exc(20)) return self.error_response(request, http.BAD_REQUEST, 'error processing http request {0}', request.path)
def postmsg(self, msgtype, info): """ Post a transaction message to the validator, parse the returning CBOR and return the corresponding dictionary. """ data = dict2cbor(info) datalen = len(data) url = urlparse.urljoin(self._base_url, msgtype) LOGGER.debug('post transaction to %s with DATALEN=%d, DATA=<%s>', url, datalen, data) try: request = urllib2.Request(url, data, {'Content-Type': 'application/cbor', 'Content-Length': datalen}) if self._cookie: request.add_header('cookie', self._cookie) opener = urllib2.build_opener(self._proxy_handler) response = opener.open(request, timeout=10) if not self._cookie: self._cookie = response.headers.get('Set-Cookie') except urllib2.HTTPError as err: content = err.read() if content is not None: headers = err.info() encoding = headers.get('Content-Type') if encoding == 'application/json': value = json2dict(content) elif encoding == 'application/cbor': value = cbor2dict(content) else: LOGGER.warn('operation failed with response: %s', err.code) raise MessageException( 'operation failed with response: {0}'.format(err.code)) LOGGER.warn('operation failed with response: %s %s', err.code, str(value)) if "errorType" in value: if value['errorType'] == "InvalidTransactionError": raise InvalidTransactionError( value['error'] if 'error' in value else value) else: raise MessageException(str(value)) else: raise MessageException( 'operation failed with response: {0}'.format(err.code)) except urllib2.URLError as err: LOGGER.warn('operation failed: %s', err.reason) raise MessageException('operation failed: {0}'.format(err.reason)) except: LOGGER.warn('no response from server') raise MessageException('no response from server') content = response.read() headers = response.info() response.close() encoding = headers.get('Content-Type') if encoding == 'application/json': value = json2dict(content) elif encoding == 'application/cbor': value = cbor2dict(content) else: LOGGER.info('server responds with message %s of type %s', content, encoding) return None LOGGER.debug(pretty_print_dict(value)) return value
def render_post(self, request, components, msg): """ Forward a signed message through the gossip network. """ encoding = request.getHeader('Content-Type') data = request.content.getvalue() try: if encoding == 'application/json': minfo = json2dict(data) elif encoding == 'application/cbor': minfo = cbor2dict(data) else: raise Error("", 'unknown message' ' encoding: {0}'.format(encoding)) typename = minfo.get('__TYPE__', '**UNSPECIFIED**') if typename not in self.Ledger.MessageHandlerMap: raise Error("", 'received request for unknown message' ' type, {0}'.format(typename)) msg = self.Ledger.MessageHandlerMap[typename][0](minfo) except Error as e: LOGGER.info('exception while decoding http request %s; %s', request.path, traceback.format_exc(20)) raise Error(http.BAD_REQUEST, 'unable to decode incoming request: {0}'.format(e)) if self.Validator.Config.get("LocalValidation", True): # determine if the message contains a valid transaction before # we send the message to the network # we need to start with a copy of the message due to cases # where side effects of the validity check may impact objects # related to msg mymsg = copy.deepcopy(msg) if hasattr(mymsg, 'Transaction') and mymsg.Transaction is not None: mytxn = mymsg.Transaction LOGGER.info('starting local validation ' 'for txn id: %s type: %s', mytxn.Identifier, mytxn.TransactionTypeName) block_id = self.Ledger.MostRecentCommittedBlockID real_store_map = self.Ledger.GlobalStoreMap.get_block_store( block_id) temp_store_map = \ global_store_manager.BlockStore(real_store_map) if not temp_store_map: LOGGER.info('no store map for block %s', block_id) raise Error(http.BAD_REQUEST, 'unable to validate enclosed' ' transaction {0}'.format(data)) transaction_type = mytxn.TransactionTypeName if transaction_type not in temp_store_map.TransactionStores: LOGGER.info('transaction type %s not in global store map', transaction_type) raise Error(http.BAD_REQUEST, 'unable to validate enclosed' ' transaction {0}'.format(data)) # clone a copy of the ledger's message queue so we can # temporarily play forward all locally submitted yet # uncommitted transactions my_queue = copy.deepcopy(self.Ledger.MessageQueue) # apply any enqueued messages while len(my_queue) > 0: qmsg = my_queue.pop() if qmsg and \ qmsg.MessageType in self.Ledger.MessageHandlerMap: if (hasattr(qmsg, 'Transaction') and qmsg.Transaction is not None): my_store = temp_store_map.get_transaction_store( qmsg.Transaction.TransactionTypeName) if qmsg.Transaction.is_valid(my_store): myqtxn = copy.copy(qmsg.Transaction) myqtxn.apply(my_store) # apply any local pending transactions for txn_id in self.Ledger.PendingTransactions.iterkeys(): pend_txn = self.Ledger.TransactionStore[txn_id] my_store = temp_store_map.get_transaction_store( pend_txn.TransactionTypeName) if pend_txn and pend_txn.is_valid(my_store): my_pend_txn = copy.copy(pend_txn) my_pend_txn.apply(my_store) # determine validity of the POSTed transaction against our # new temporary state my_store = temp_store_map.get_transaction_store( mytxn.TransactionTypeName) try: mytxn.check_valid(my_store) except InvalidTransactionError as e: LOGGER.info('submitted transaction fails transaction ' 'family validation check: %s; %s', request.path, mymsg.dump()) raise Error(http.BAD_REQUEST, "enclosed transaction failed transaction " "family validation check: {}".format(str(e))) except: LOGGER.info('submitted transaction is ' 'not valid %s; %s; %s', request.path, mymsg.dump(), traceback.format_exc(20)) raise Error(http.BAD_REQUEST, "enclosed transaction is not" " valid {}".format(data)) LOGGER.info('transaction %s is valid', msg.Transaction.Identifier) # and finally execute the associated method # and send back the results self.Ledger.handle_message(msg) return msg
key_file = os.path.join(key_dir, key_name + '.wif') if not os.path.exists(key_file): raise ClientException('no such file: {}'.format(key_file)) try: if filename == '-': json_content = sys.stdin.read() else: with open(filename) as fd: json_content = fd.read() except IOError, e: raise CliException(str(e)) try: txn_content = json2dict(json_content) except ValueError, e: raise CliException("Decoding JSON: {}".format(str(e))) try: txnfamily = importlib.import_module(family_name) except ImportError: raise CliException( "transaction family not found: {}".format(family_name)) fake_journal = FakeJournal() txnfamily.register_transaction_types(fake_journal) client = SawtoothClient(base_url=url, keyfile=key_file, store_name=fake_journal.store_class.__name__)
def verify_signup_info(cls, signup_info, originator_public_key, validator_network_basename, most_recent_wait_certificate_id): # Verify the attestation verification report signature attestation_verification_report = \ signup_info.proof_data.get('attestation_verification_report') if attestation_verification_report is None: raise \ SignupInfoError( 'Attestation verification report is missing from proof ' 'data') if not pybitcointools.ecdsa_verify( dict2json(attestation_verification_report), signup_info.proof_data.get('signature'), cls._report_public_key): raise \ SignupInfoError( 'Attestation verification report signature is invalid') # Verify the presence of the anti-Sybil ID anti_sybil_id = attestation_verification_report.get('anti_sybil_id') if anti_sybil_id is None: raise \ SignupInfoError( 'Attestation verification report does not contain an ' 'anti-Sybil ID') # Verify that the report data field in the report contains the SHA256 # digest of the originator's public key SHA 256 digest and the PoET # public key. attestation_evidence_payload = \ attestation_verification_report.get( 'attestation_evidence_payload') if attestation_evidence_payload is None: raise \ SignupInfoError( 'Attestation verification report does not contain ' 'attestation evidence payload') enclave_quote = attestation_evidence_payload.get('enclave_quote') if enclave_quote is None: raise \ SignupInfoError( 'Attestation evidence payload does not contain an ' 'enclave quote') report = json2dict(pybitcointools.base64.b64decode(enclave_quote)) report_data = report.get('report_data') if report_data is None: raise \ SignupInfoError('Enclave quote does not contain report data') target_report_data = { 'originator_public_key_hash': pybitcointools.sha256( pybitcointools.encode_pubkey( originator_public_key, 'hex')), 'poet_public_key': signup_info.poet_public_key } target_report_data_digest = \ pybitcointools.sha256(dict2json(target_report_data)) if report_data != target_report_data_digest: raise SignupInfoError('Enclave quote report data is invalid') # Verify that the validator base name in the enclave quote report # matches the provided validator network basename validator_net_basename = report.get('validator_network_basename') if validator_net_basename is None: raise \ SignupInfoError( 'Enclave quote report does not have a validator network ' 'basename') if validator_net_basename != validator_network_basename: raise \ SignupInfoError( 'Enclave quote report validator network basename [{0}] ' 'does not match [{1}]'.format( validator_net_basename, validator_network_basename))
def do_post(self, request): """ Handle two types of HTTP POST requests: - gossip messages. relayed to the gossip network as is - validator command and control (/command) """ # break the path into its component parts components = request.path.split('/') while components and components[0] == '': components.pop(0) prefix = components.pop(0) if components else 'error' if prefix not in self.PostPageMap: prefix = 'default' encoding = request.getHeader('Content-Type') data = request.content.getvalue() # process non-gossip API requests if prefix == 'command': try: if encoding == 'application/json': minfo = json2dict(data) else: return self.error_response(request, http.BAD_REQUEST, 'bad message encoding, {0}', encoding) except: logger.info('exception while decoding http request %s; %s', request.path, traceback.format_exc(20)) return self.error_response( request, http.BAD_REQUEST, 'unable to decode incoming request {0}', data) # process /command try: response = self.PostPageMap[prefix](request, components, minfo) request.responseHeaders.addRawHeader("content-type", encoding) result = dict2json(response) return result except Error as e: return self.error_response( request, int(e.status), 'exception while processing request {0}; {1}', request.path, str(e)) except: logger.info('exception while processing http request %s; %s', request.path, traceback.format_exc(20)) return self.error_response( request, http.BAD_REQUEST, 'error processing http request {0}', request.path) else: try: if encoding == 'application/json': minfo = json2dict(data) elif encoding == 'application/cbor': minfo = cbor2dict(data) else: return self.error_response( request, http.BAD_REQUEST, 'unknown message encoding, {0}', encoding) typename = minfo.get('__TYPE__', '**UNSPECIFIED**') if typename not in self.Ledger.MessageHandlerMap: return self.error_response( request, http.BAD_REQUEST, 'received request for unknown message type, {0}', typename) msg = self.Ledger.MessageHandlerMap[typename][0](minfo) except: logger.info('exception while decoding http request %s; %s', request.path, traceback.format_exc(20)) return self.error_response( request, http.BAD_REQUEST, 'unabled to decode incoming request {0}', data) # determine if the message contains a valid transaction before # we send the message to the network # we need to start with a copy of the message due to cases # where side effects of the validity check may impact objects # related to msg mymsg = copy.deepcopy(msg) if hasattr(mymsg, 'Transaction') and mymsg.Transaction is not None: mytxn = mymsg.Transaction logger.info( 'starting local validation ' 'for txn id: %s type: %s', mytxn.Identifier, mytxn.TransactionTypeName) block_id = self.Ledger.MostRecentCommittedBlockID real_store_map = self.Ledger.GlobalStoreMap.get_block_store( block_id) temp_store_map = \ global_store_manager.BlockStore(real_store_map) if not temp_store_map: logger.info('no store map for block %s', block_id) return self.error_response( request, http.BAD_REQUEST, 'unable to validate enclosed transaction {0}', data) transaction_type = mytxn.TransactionTypeName if transaction_type not in temp_store_map.TransactionStores: logger.info('transaction type %s not in global store map', transaction_type) return self.error_response( request, http.BAD_REQUEST, 'unable to validate enclosed transaction {0}', data) # clone a copy of the ledger's message queue so we can # temporarily play forward all locally submitted yet # uncommitted transactions my_queue = copy.deepcopy(self.Ledger.MessageQueue) # apply any enqueued messages while len(my_queue) > 0: qmsg = my_queue.pop() if qmsg and \ qmsg.MessageType in self.Ledger.MessageHandlerMap: if (hasattr(qmsg, 'Transaction') and qmsg.Transaction is not None): my_store = temp_store_map.get_transaction_store( qmsg.Transaction.TransactionTypeName) if qmsg.Transaction.is_valid(my_store): myqtxn = copy.copy(qmsg.Transaction) myqtxn.apply(my_store) # apply any local pending transactions for txn_id in self.Ledger.PendingTransactions.iterkeys(): pend_txn = self.Ledger.TransactionStore[txn_id] my_store = temp_store_map.get_transaction_store( pend_txn.TransactionTypeName) if pend_txn and pend_txn.is_valid(my_store): my_pend_txn = copy.copy(pend_txn) logger.debug( 'applying pending transaction ' '%s to temp store', txn_id) my_pend_txn.apply(my_store) # determine validity of the POSTed transaction against our # new temporary state my_store = temp_store_map.get_transaction_store( mytxn.TransactionTypeName) try: mytxn.check_valid(my_store) except InvalidTransactionError as e: logger.info( 'submitted transaction fails transaction ' 'family validation check: %s; %s', request.path, mymsg.dump()) return self.error_response( request, http.BAD_REQUEST, "enclosed transaction failed transaction " "family validation check: {}".format(str(e)), data) except: logger.info( 'submitted transaction is ' 'not valid %s; %s; %s', request.path, mymsg.dump(), traceback.format_exc(20)) return self.error_response( request, http.BAD_REQUEST, "enclosed transaction is not valid", data) logger.info('transaction %s is valid', msg.Transaction.Identifier) # and finally execute the associated method # and send back the results try: response = self.PostPageMap[prefix](request, components, msg) request.responseHeaders.addRawHeader("content-type", encoding) if encoding == 'application/json': result = dict2json(response.dump()) else: result = dict2cbor(response.dump()) return result except Error as e: return self.error_response( request, int(e.status), 'exception while processing request {0}; {1}', request.path, str(e)) except: logger.info('exception while processing http request %s; %s', request.path, traceback.format_exc(20)) return self.error_response( request, http.BAD_REQUEST, 'error processing http request {0}', request.path)
key_file = os.path.join(key_dir, key_name + '.wif') if not os.path.exists(key_file): raise ClientException('no such file: {}'.format(key_file)) try: if filename == '-': json_content = sys.stdin.read() else: with open(filename) as fd: json_content = fd.read() except IOError, e: raise CliException(str(e)) try: txn_content = json2dict(json_content) except ValueError, e: raise CliException("Decoding JSON: {}".format(str(e))) try: txnfamily = importlib.import_module(family_name) except ImportError: raise CliException( "transaction family not found: {}".format(family_name)) fake_journal = FakeJournal() txnfamily.register_transaction_types(fake_journal) client = SawtoothClient( base_url=url, keyfile=key_file,
def deserialize(cls, serialized): deserialized = json2dict(serialized) return deserialized
def render_POST(self, request): """ Handle two types of HTTP POST requests: - gossip messages. relayed to the gossip network as is - validator command and control (/command) """ # pylint: disable=invalid-name # break the path into its component parts components = request.path.split('/') while components and components[0] == '': components.pop(0) prefix = components.pop(0) if components else 'error' if prefix not in self.PostPageMap: prefix = 'default' encoding = request.getHeader('Content-Type') data = request.content.getvalue() # process non-gossip API requests if prefix == 'command': try: if encoding == 'application/json': minfo = json2dict(data) else: return self.error_response(request, http.BAD_REQUEST, 'bad message encoding, {0}', encoding) except: logger.info('exception while decoding http request %s; %s', request.path, traceback.format_exc(20)) return self.error_response( request, http.BAD_REQUEST, 'unable to decode incoming request {0}', data) # process /command try: response = self.PostPageMap[prefix](request, components, minfo) request.responseHeaders.addRawHeader("content-type", encoding) result = dict2json(response) return result except Error as e: return self.error_response( request, int(e.status), 'exception while processing request {0}; {1}', request.path, str(e)) except: logger.info('exception while processing http request %s; %s', request.path, traceback.format_exc(20)) return self.error_response(request, http.BAD_REQUEST, 'error processing http request {0}', request.path) else: try: if encoding == 'application/json': minfo = json2dict(data) elif encoding == 'application/cbor': minfo = cbor2dict(data) else: return self.error_response(request, http.BAD_REQUEST, 'unknown message encoding, {0}', encoding) typename = minfo.get('__TYPE__', '**UNSPECIFIED**') if typename not in self.Ledger.MessageHandlerMap: return self.error_response( request, http.BAD_REQUEST, 'received request for unknown message type, {0}', typename) msg = self.Ledger.MessageHandlerMap[typename][0](minfo) except: logger.info('exception while decoding http request %s; %s', request.path, traceback.format_exc(20)) return self.error_response( request, http.BAD_REQUEST, 'unabled to decode incoming request {0}', data) # determine if the message contains a valid transaction before # we send the message to the network # we need to start with a copy of the message due to cases # where side effects of the validity check may impact objects # related to msg mymsg = copy.deepcopy(msg) if hasattr(mymsg, 'Transaction') and mymsg.Transaction is not None: mytxn = mymsg.Transaction logger.info('starting local validation ' 'for txn id: %s type: %s', mytxn.Identifier, mytxn.TransactionTypeName) blockid = self.Ledger.MostRecentCommittedBlockID realstoremap = self.Ledger.GlobalStoreMap.get_block_store( blockid) tempstoremap = global_store_manager.BlockStore(realstoremap) if not tempstoremap: logger.info('no store map for block %s', blockid) return self.error_response( request, http.BAD_REQUEST, 'unable to validate enclosed transaction {0}', data) transtype = mytxn.TransactionTypeName if transtype not in tempstoremap.TransactionStores: logger.info('transaction type %s not in global store map', transtype) return self.error_response( request, http.BAD_REQUEST, 'unable to validate enclosed transaction {0}', data) # clone a copy of the ledger's message queue so we can # temporarily play forward all locally submitted yet # uncommitted transactions myqueue = copy.deepcopy(self.Ledger.MessageQueue) # apply any enqueued messages while len(myqueue) > 0: qmsg = myqueue.pop() if qmsg and \ qmsg.MessageType in self.Ledger.MessageHandlerMap: if (hasattr(qmsg, 'Transaction') and qmsg.Transaction is not None): mystore = tempstoremap.get_transaction_store( qmsg.Transaction.TransactionTypeName) if qmsg.Transaction.is_valid(mystore): myqtxn = copy.copy(qmsg.Transaction) myqtxn.apply(mystore) # apply any local pending transactions for txnid in self.Ledger.PendingTransactions.iterkeys(): pendtxn = self.Ledger.TransactionStore[txnid] mystore = tempstoremap.get_transaction_store( pendtxn.TransactionTypeName) if pendtxn and pendtxn.is_valid(mystore): mypendtxn = copy.copy(pendtxn) logger.debug('applying pending transaction ' '%s to temp store', txnid) mypendtxn.apply(mystore) # determine validity of the POSTed transaction against our # new temporary state mystore = tempstoremap.get_transaction_store( mytxn.TransactionTypeName) try: mytxn.check_valid(mystore) except InvalidTransactionError as e: logger.info('submitted transaction fails transaction ' 'family validation check: %s; %s', request.path, mymsg.dump()) return self.error_response( request, http.BAD_REQUEST, "enclosed transaction failed transaction " "family validation check: {}".format(str(e)), data) except: logger.info('submitted transaction is ' 'not valid %s; %s; %s', request.path, mymsg.dump(), traceback.format_exc(20)) return self.error_response( request, http.BAD_REQUEST, "enclosed transaction is not valid", data) logger.info('transaction %s is valid', msg.Transaction.Identifier) # and finally execute the associated method # and send back the results try: response = self.PostPageMap[prefix](request, components, msg) request.responseHeaders.addRawHeader("content-type", encoding) if encoding == 'application/json': result = dict2json(response.dump()) else: result = dict2cbor(response.dump()) return result except Error as e: return self.error_response( request, int(e.status), 'exception while processing request {0}; {1}', request.path, str(e)) except: logger.info('exception while processing http request %s; %s', request.path, traceback.format_exc(20)) return self.error_response(request, http.BAD_REQUEST, 'error processing http request {0}', request.path)
def render_POST(self, request): """ Handle a POST request on the HTTP interface. All message on the POST interface are gossip messages that should be relayed into the gossip network as is. """ # pylint: disable=invalid-name # break the path into its component parts components = request.path.split('/') while components and components[0] == '': components.pop(0) prefix = components.pop(0) if components else 'error' if prefix not in self.PostPageMap: prefix = 'default' # process the message encoding encoding = request.getHeader('Content-Type') data = request.content.getvalue() try: if encoding == 'application/json': minfo = json2dict(data) elif encoding == 'application/cbor': minfo = cbor2dict(data) else: return self.error_response(request, http.BAD_REQUEST, 'unknown message encoding, {0}', encoding) typename = minfo.get('__TYPE__', '**UNSPECIFIED**') if typename not in self.Ledger.MessageHandlerMap: return self.error_response( request, http.BAD_REQUEST, 'received request for unknown message type, {0}', typename) msg = self.Ledger.MessageHandlerMap[typename][0](minfo) except: logger.info('exception while decoding http request %s; %s', request.path, traceback.format_exc(20)) return self.error_response( request, http.BAD_REQUEST, 'unabled to decode incoming request {0}', data) # and finally execute the associated method and send back the results try: response = self.PostPageMap[prefix](request, components, msg) request.responseHeaders.addRawHeader("content-type", encoding) if encoding == 'application/json': return dict2json(response.dump()) else: return dict2cbor(response.dump()) except Error as e: return self.error_response( request, int(e.status), 'exception while processing request {0}; {1}', request.path, str(e)) except: logger.info('exception while processing http request %s; %s', request.path, traceback.format_exc(20)) return self.error_response(request, http.BAD_REQUEST, 'error processing http request {0}', request.path)
def render_post(self, request, components, msg): """ Forward a signed message through the gossip network. """ encoding = request.getHeader('Content-Type') data = request.content.getvalue() try: if encoding == 'application/json': minfo = json2dict(data) elif encoding == 'application/cbor': minfo = cbor2dict(data) else: raise Error( "", 'unknown message' ' encoding: {0}'.format(encoding)) typename = minfo.get('__TYPE__', '**UNSPECIFIED**') if typename not in self.Ledger.MessageHandlerMap: raise Error( "", 'received request for unknown message' ' type, {0}'.format(typename)) msg = self.Ledger.MessageHandlerMap[typename][0](minfo) except Error as e: LOGGER.info('exception while decoding http request %s; %s', request.path, traceback.format_exc(20)) raise Error(http.BAD_REQUEST, 'unable to decode incoming request: {0}'.format(e)) if self.Validator.Config.get("LocalValidation", True): # determine if the message contains a valid transaction before # we send the message to the network # we need to start with a copy of the message due to cases # where side effects of the validity check may impact objects # related to msg mymsg = copy.deepcopy(msg) if hasattr(mymsg, 'Transaction') and mymsg.Transaction is not None: mytxn = mymsg.Transaction LOGGER.info( 'starting local validation ' 'for txn id: %s type: %s', mytxn.Identifier, mytxn.TransactionTypeName) pending_block_txns = None if self.Ledger.PendingTransactionBlock is not None: pending_block_txns = \ self.Ledger.PendingTransactionBlock.TransactionIDs block_id = self.Ledger.MostRecentCommittedBlockID real_store_map = \ self.Ledger.GlobalStoreMap.get_block_store(block_id) temp_store_map = \ global_store_manager.BlockStore(real_store_map) if not temp_store_map: LOGGER.info('no store map for block %s', block_id) raise Error( http.BAD_REQUEST, 'unable to validate enclosed' ' transaction {0}'.format(data)) pending_txns = copy.copy(self.Ledger.PendingTransactions) pending_txn_ids = [x for x in pending_txns.iterkeys()] # clone a copy of the ledger's message queue so we can # temporarily play forward all locally submitted yet # uncommitted transactions my_queue = copy.deepcopy(self.Ledger.MessageQueue) transaction_type = mytxn.TransactionTypeName if transaction_type not in temp_store_map.TransactionStores: LOGGER.info('transaction type %s not in global store map', transaction_type) raise Error( http.BAD_REQUEST, 'unable to validate enclosed' ' transaction {0}'.format(data)) if pending_block_txns is not None: pending_txn_ids = pending_block_txns + pending_txn_ids # apply any local pending transactions for txn_id in pending_txn_ids: pend_txn = self.Ledger.TransactionStore[txn_id] my_store = temp_store_map.get_transaction_store( pend_txn.TransactionTypeName) if pend_txn and pend_txn.is_valid(my_store): my_pend_txn = copy.copy(pend_txn) my_pend_txn.apply(my_store) # apply any enqueued messages while len(my_queue) > 0: qmsg = my_queue.pop() if qmsg and \ qmsg.MessageType in self.Ledger.MessageHandlerMap: if (hasattr(qmsg, 'Transaction') and qmsg.Transaction is not None): my_store = temp_store_map.get_transaction_store( qmsg.Transaction.TransactionTypeName) if qmsg.Transaction.is_valid(my_store): myqtxn = copy.copy(qmsg.Transaction) myqtxn.apply(my_store) # determine validity of the POSTed transaction against our # new temporary state my_store = temp_store_map.get_transaction_store( mytxn.TransactionTypeName) try: mytxn.check_valid(my_store) except InvalidTransactionError as e: LOGGER.info( 'submitted transaction fails transaction ' 'family validation check: %s; %s', request.path, mymsg.dump()) raise Error( http.BAD_REQUEST, "enclosed transaction failed transaction " "family validation check: {}".format(str(e))) except: LOGGER.info( 'submitted transaction is ' 'not valid %s; %s; %s', request.path, mymsg.dump(), traceback.format_exc(20)) raise Error( http.BAD_REQUEST, "enclosed transaction is not" " valid {}".format(data)) LOGGER.info('transaction %s is valid', msg.Transaction.Identifier) # and finally execute the associated method # and send back the results self.Ledger.handle_message(msg) return msg
def verify_signup_info(cls, signup_info, originator_public_key_hash, most_recent_wait_certificate_id): # Verify the attestation verification report signature proof_data_dict = json2dict(signup_info.proof_data) verification_report = proof_data_dict.get('verification_report') if verification_report is None: raise \ SignupInfoError( 'Verification report is missing from proof data') signature = proof_data_dict.get('signature') if signature is None: raise \ SignupInfoError( 'Signature is missing from proof data') if not signing.verify(verification_report, signature, cls._report_public_key): raise \ SignupInfoError('Verification report signature is invalid') verification_report_dict = json2dict(verification_report) # Verify that the verification report contains a PSE manifest status # and it is OK pse_manifest_status = \ verification_report_dict.get('pseManifestStatus') if pse_manifest_status is None: raise \ SignupInfoError( 'Verification report does not contain a PSE manifest ' 'status') if pse_manifest_status != 'OK': raise \ SignupInfoError( 'PSE manifest status is {} (i.e., not OK)'.format( pse_manifest_status)) # Verify that the verification report contains a PSE manifest hash # and it is the value we expect pse_manifest_hash = \ verification_report_dict.get('pseManifestHash') if pse_manifest_hash is None: raise \ SignupInfoError( 'Verification report does not contain a PSE manifest ' 'hash') expected_pse_manifest_hash = \ base64.b64encode( hashlib.sha256( b'Do you believe in manifest destiny?').hexdigest()) if pse_manifest_hash != expected_pse_manifest_hash: raise \ SignupInfoError( 'PSE manifest hash {0} does not match {1}'.format( pse_manifest_hash, expected_pse_manifest_hash)) # Verify that the verification report contains an enclave quote and # that its status is OK enclave_quote_status = \ verification_report_dict.get('isvEnclaveQuoteStatus') if enclave_quote_status is None: raise \ SignupInfoError( 'Verification report does not contain an enclave quote ' 'status') if enclave_quote_status != 'OK': raise \ SignupInfoError( 'Enclave quote status is {} (i.e., not OK)'.format( enclave_quote_status)) enclave_quote = verification_report_dict.get('isvEnclaveQuoteBody') if enclave_quote is None: raise \ SignupInfoError( 'Verification report does not contain an enclave quote') # Verify that the enclave quote contains a report body with the value # we expect (i.e., SHA256(SHA256(OPK)|PPK) report_data = '{0}{1}'.format(originator_public_key_hash.upper(), signup_info.poet_public_key.upper()) expected_report_body = hashlib.sha256( dict2json(report_data)).hexdigest() enclave_quote_dict = \ json2dict(base64.b64decode(enclave_quote)) report_body = enclave_quote_dict.get('report_body') if report_body is None: raise \ SignupInfoError( 'Enclave quote does not contain a report body') if report_body != expected_report_body: raise \ SignupInfoError( 'Enclave quote report body {0} does not match {1}'.format( report_body, expected_report_body)) # Verify that the wait certificate ID in the verification report # matches the provided wait certificate ID. The wait certificate ID # is stored in the nonce field. nonce = verification_report_dict.get('nonce') if nonce is None: raise \ SignupInfoError( 'Verification report does not have a nonce')
def verify_signup_info(cls, signup_info, originator_public_key_hash, most_recent_wait_certificate_id): # Verify the attestation verification report signature proof_data_dict = json2dict(signup_info.proof_data) verification_report = proof_data_dict.get('verification_report') if verification_report is None: raise ValueError('Verification report is missing from proof data') signature = proof_data_dict.get('signature') if signature is None: raise ValueError('Signature is missing from proof data') if not signing.verify( verification_report, signature, cls._report_public_key): raise ValueError('Verification report signature is invalid') verification_report_dict = json2dict(verification_report) # Verify that the verification report contains a PSE manifest status # and it is OK pse_manifest_status = \ verification_report_dict.get('pseManifestStatus') if pse_manifest_status is None: raise \ ValueError( 'Verification report does not contain a PSE manifest ' 'status') if pse_manifest_status != 'OK': raise \ ValueError( 'PSE manifest status is {} (i.e., not OK)'.format( pse_manifest_status)) # Verify that the verification report contains a PSE manifest hash # and it is the value we expect pse_manifest_hash = \ verification_report_dict.get('pseManifestHash') if pse_manifest_hash is None: raise \ ValueError( 'Verification report does not contain a PSE manifest ' 'hash') expected_pse_manifest_hash = \ base64.b64encode( hashlib.sha256( bytes(b'Do you believe in ' b'manifest destiny?')).hexdigest() .encode()).decode() if pse_manifest_hash != expected_pse_manifest_hash: raise \ ValueError( 'PSE manifest hash {0} does not match {1}'.format( pse_manifest_hash, expected_pse_manifest_hash)) # Verify that the verification report contains an enclave quote and # that its status is OK enclave_quote_status = \ verification_report_dict.get('isvEnclaveQuoteStatus') if enclave_quote_status is None: raise \ ValueError( 'Verification report does not contain an enclave quote ' 'status') if enclave_quote_status != 'OK': raise \ ValueError( 'Enclave quote status is {} (i.e., not OK)'.format( enclave_quote_status)) enclave_quote = verification_report_dict.get('isvEnclaveQuoteBody') if enclave_quote is None: raise \ ValueError( 'Verification report does not contain an enclave quote') # Verify that the enclave quote contains a report body with the value # we expect (i.e., SHA256(SHA256(OPK)|PPK) report_data = '{0}{1}'.format( originator_public_key_hash.upper(), signup_info.poet_public_key.upper() ) expected_report_body = hashlib.sha256( dict2json(report_data).encode()).hexdigest() enclave_quote_dict = \ json2dict(base64.b64decode(enclave_quote).decode()) report_body = enclave_quote_dict.get('report_body') if report_body is None: raise ValueError('Enclave quote does not contain a report body') if report_body != expected_report_body: raise \ ValueError( 'Enclave quote report body {0} does not match {1}'.format( report_body, expected_report_body)) # Verify that the wait certificate ID in the verification report # matches the provided wait certificate ID. The wait certificate ID # is stored in the nonce field. nonce = verification_report_dict.get('nonce') if nonce is None: raise \ ValueError( 'Verification report does not have a nonce')
def postmsg(self, msgtype, info): """ Post a transaction message to the validator, parse the returning CBOR and return the corresponding dictionary. """ data = dict2cbor(info) datalen = len(data) url = urlparse.urljoin(self._base_url, msgtype) LOGGER.debug('post transaction to %s with DATALEN=%d, DATA=<%s>', url, datalen, data) try: request = urllib2.Request(url, data, { 'Content-Type': 'application/cbor', 'Content-Length': datalen }) if self._cookie: request.add_header('cookie', self._cookie) opener = urllib2.build_opener(self._proxy_handler) response = opener.open(request, timeout=10) if not self._cookie: self._cookie = response.headers.get('Set-Cookie') except urllib2.HTTPError as err: content = err.read() if content is not None: headers = err.info() encoding = headers.get('Content-Type') if encoding == 'application/json': value = json2dict(content) elif encoding == 'application/cbor': value = cbor2dict(content) else: LOGGER.warn('operation failed with response: %s', err.code) raise MessageException( 'operation failed with response: {0}'.format(err.code)) LOGGER.warn('operation failed with response: %s %s', err.code, str(value)) if "errorType" in value: if value['errorType'] == "InvalidTransactionError": raise InvalidTransactionError( value['error'] if 'error' in value else value) else: raise MessageException(str(value)) else: raise MessageException( 'operation failed with response: {0}'.format(err.code)) except urllib2.URLError as err: LOGGER.warn('operation failed: %s', err.reason) raise MessageException('operation failed: {0}'.format(err.reason)) except: LOGGER.warn('no response from server') raise MessageException('no response from server') content = response.read() headers = response.info() response.close() encoding = headers.get('Content-Type') if encoding == 'application/json': value = json2dict(content) elif encoding == 'application/cbor': value = cbor2dict(content) else: LOGGER.info('server responds with message %s of type %s', content, encoding) return None LOGGER.debug(pretty_print_dict(value)) return value