def __init__(self, state_view): """Initialize a PbftSettingsView object. Args: state_view (StateView): The current state view. Returns: None """ self._settings_view = SettingsView(state_view) self._max_log_size = None self._enclave_module_name = None self._signup_commit_maximum_delay = 2 self._key_block_claim_limit = 2 self._block_claim_delay = 2
def __init__(self, state_view): """Initialize a PbftSettingsView object. Args: state_view (StateView): The current state view. Returns: None """ self._settings_view = SettingsView(state_view) self._node = None self._nodes = None self._max_log_size = None self._block_duration = None self._checkpoint_period = None self._view_change_timeout = None self._signup_commit_maximum_delay = 2 self._key_block_claim_limit = 2 self._block_claim_delay = 2
class PbftSettingsView: """A class to wrap the retrieval of PBFT configuration settings from the configuration view. For values that are not in the current state view or that are invalid, default values are returned. """ _MAX_LOG_SIZE_ = 1000 _ENCLAVE_MODULE_NAME_ = 'bgx_pbft.enclave.pbft_enclave' def __init__(self, state_view): """Initialize a PbftSettingsView object. Args: state_view (StateView): The current state view. Returns: None """ self._settings_view = SettingsView(state_view) self._max_log_size = None self._enclave_module_name = None self._signup_commit_maximum_delay = 2 self._key_block_claim_limit = 2 self._block_claim_delay = 2 def _get_config_setting(self, name, value_type, default_value, validate_function=None): """Retrieves a value from the config view, returning the default value if does not exist in the current state view or if the value is invalid. Args: name (str): The config setting to return. value_type (type): The value type, for example, int, float, etc., of config value. default_value (object): The default value to be used if no value found or if value in config is invalid, for example, a non-integer value for an int config setting. validate_function (function): An optional function that can be applied to the setting to determine validity. The function should return True if setting is valid, False otherwise. Returns: The value for the config setting. """ try: value = \ self._settings_view.get_setting( key=name, default_value=default_value, value_type=value_type) if validate_function is not None: if not validate_function(value): raise \ ValueError( 'Value ({}) for {} is not valid'.format( value, name)) except ValueError: value = default_value return value @property def pbft_max_log_size(self): """Return the max log size if config setting exists and is valid, otherwise return the default. """ if self._max_log_size is None: self._max_log_size = self._get_config_setting( name='sawtooth.consensus.pbft.max_log_size', value_type=int, default_value=PbftSettingsView._MAX_LOG_SIZE_, validate_function=lambda value: value >= 0) return self._max_log_size @property def enclave_module_name(self): """Return the enclave module name if config setting exists and is valid, otherwise return the default. The enclave module name is the name of the Python module containing the implementation of the underlying PBFT enclave. """ if self._enclave_module_name is None: self._enclave_module_name = \ self._get_config_setting( name='sawtooth.consensus.pbft.enclave_module_name', value_type=str, default_value=PbftSettingsView._ENCLAVE_MODULE_NAME_, # function should return true if value is nonempty validate_function=lambda value: value) return self._enclave_module_name @property def signup_commit_maximum_delay(self): return self._signup_commit_maximum_delay @property def key_block_claim_limit(self): return self._key_block_claim_limit @property def block_claim_delay(self): return self._block_claim_delay
class PbftSettingsView: """A class to wrap the retrieval of PBFT configuration settings from the configuration view. For values that are not in the current state view or that are invalid, default values are returned. """ _NODE_ = 'plink' _NODES_ = "{\"0281e398fc978e8d36d6b2244c71e140f3ee464cb4c0371a193bb0a5c6574810ba\": \"leader\",\"028c7e06db3af50a9958390e3e29f166b1cf6198586acf37cde46c8ea54e4a79ef\": \"plink\"}" _MAX_LOG_SIZE_ = 1000 _BLOCK_DURATION_ = 200 _CHECKPOINT_PERIOD_ = 100 _VIEW_CHANGE_TIMEOUT_ = 4000 _DAG_STEP_ = 3 _IS_PBFT_FULL_ = False _IS_LEADER_SHIFT_ = False _BLOCK_TIMEOUT_ = 0.5 _MAX_BRANCH_ = 6 _MAX_FEDER_PEER_ = 6 BLOCK_TIMEOUT = 'bgx.consensus.block_timeout' LEADER_SHIFT = 'bgx.fbft.leader_shift' MAX_FEDER_PEER = 'bgx.fbft.max_feder_peer' PBFT_FULL = 'bgx.consensus.pbft.full' MAX_BRANCH = 'bgx.dag.max_branch' DAG_STEP = 'bgx.dag.step' def __init__(self, state_view): """Initialize a PbftSettingsView object. Args: state_view (StateView): The current state view. Returns: None """ self._settings_view = SettingsView(state_view) self._node = None self._nodes = None self._max_log_size = None self._block_duration = None self._checkpoint_period = None self._view_change_timeout = None self._signup_commit_maximum_delay = 2 self._key_block_claim_limit = 2 self._block_claim_delay = 2 self._params = {} self._max_branch = None self._send_batches = None def _get_config_setting(self, name, value_type, default_value, validate_function=None): """Retrieves a value from the config view, returning the default value if does not exist in the current state view or if the value is invalid. Args: name (str): The config setting to return. value_type (type): The value type, for example, int, float, etc., of config value. default_value (object): The default value to be used if no value found or if value in config is invalid, for example, a non-integer value for an int config setting. validate_function (function): An optional function that can be applied to the setting to determine validity. The function should return True if setting is valid, False otherwise. Returns: The value for the config setting. """ try: value = \ self._settings_view.get_setting( key=name, default_value=default_value, value_type=value_type) if validate_function is not None: if not validate_function(value): raise ValueError('Value ({}) for {} is not valid'.format(value,name)) except ValueError: value = default_value LOGGER.debug('use default for %s=%s',name,value) return value def update_param(self,pname): if pname in self._params: del self._params[pname] LOGGER.debug('CLEAR PARAM %s',pname) return True return False @property def pbft_max_log_size(self): """Return the max log size if config setting exists and is valid, otherwise return the default. """ if self._max_log_size is None: self._max_log_size = self._get_config_setting( name='bgx.consensus.pbft.max_log_size', value_type=int, default_value=PbftSettingsView._MAX_LOG_SIZE_, validate_function=lambda value: value >= 0) return self._max_log_size @property def pbft_block_duration(self): """Return the block_duration if config setting exists and is valid, otherwise return the default. """ if self._block_duration is None: self._block_duration = self._get_config_setting( name='bgx.consensus.pbft.block_duration', value_type=int, default_value=PbftSettingsView._BLOCK_DURATION_, validate_function=lambda value: value >= 0) return self._block_duration @property def pbft_checkpoint_period(self): """Return the checkpoint_period if config setting exists and is valid, otherwise return the default. """ if self._checkpoint_period is None: self._block_duration = self._get_config_setting( name='bgx.consensus.pbft.checkpoint_period', value_type=int, default_value=PbftSettingsView._CHECKPOINT_PERIOD_, validate_function=lambda value: value >= 0) return self._checkpoint_period @property def pbft_view_change_timeout(self): """Return the view_change_timeout if config setting exists and is valid, otherwise return the default. """ if self._view_change_timeout is None: self._view_change_timeout = self._get_config_setting( name='bgx.consensus.pbft.view_change_timeout', value_type=int, default_value=PbftSettingsView._VIEW_CHANGE_TIMEOUT_, validate_function=lambda value: value >= 0) return self._view_change_timeout @property def authorized_keys(self): """Return node type. """ if self._node is None: self._node = self._get_config_setting( name='sawtooth.settings.vote.authorized_keys', value_type=str, default_value=None, validate_function=lambda value: value) return self._node @property def pbft_node(self): """Return node type. """ if self._node is None: self._node = self._get_config_setting( name='bgx.consensus.pbft.node', value_type=str, default_value=PbftSettingsView._NODE_, validate_function=lambda value: value) return self._node @property def pbft_nodes(self): """Return nodes list. """ if TOPOLOGY_SET_NM not in self._params: #self._settings_view.get_setting.cache_clear() #self._settings_view.get_setting.cache_info() self._params[TOPOLOGY_SET_NM] = self._get_config_setting( name=TOPOLOGY_SET_NM, value_type=str, default_value=PbftSettingsView._NODES_, validate_function=lambda value: value) return self._params[TOPOLOGY_SET_NM] @property def dag_step(self): if PbftSettingsView.DAG_STEP not in self._params : self._params[PbftSettingsView.DAG_STEP] = self._get_config_setting( name='bgx.dag.step', value_type=int, default_value=PbftSettingsView._DAG_STEP_, validate_function=lambda value: value) return self._params[PbftSettingsView.DAG_STEP] @property def max_branch(self): if PbftSettingsView.MAX_BRANCH not in self._params: self._params[PbftSettingsView.MAX_BRANCH] = self._get_config_setting( name=PbftSettingsView.MAX_BRANCH, value_type=int, default_value=PbftSettingsView._MAX_BRANCH_, validate_function=lambda value: value) return self._params[PbftSettingsView.MAX_BRANCH] @property def is_pbft_full(self): if PbftSettingsView.PBFT_FULL not in self._params : val = self._get_config_setting( name=PbftSettingsView.PBFT_FULL, value_type=int, default_value=PbftSettingsView._IS_PBFT_FULL_, validate_function=lambda value: value==0 or value==1) self._params[PbftSettingsView.PBFT_FULL] = bool(val) return self._params[PbftSettingsView.PBFT_FULL] @property def is_leader_shift(self): if PbftSettingsView.LEADER_SHIFT not in self._params: val = self._get_config_setting( name=PbftSettingsView.LEADER_SHIFT, value_type=int, default_value=PbftSettingsView._IS_LEADER_SHIFT_, validate_function=lambda value: value==0 or value==1) self._params[PbftSettingsView.LEADER_SHIFT] = bool(val) return self._params[PbftSettingsView.LEADER_SHIFT] @property def max_feder_peer(self): if PbftSettingsView.MAX_FEDER_PEER not in self._params: self._params[PbftSettingsView.MAX_FEDER_PEER] = self._get_config_setting( name=PbftSettingsView.MAX_FEDER_PEER, value_type=int, default_value=PbftSettingsView._MAX_FEDER_PEER_, validate_function=lambda value: value==0 or value==1) return self._params[PbftSettingsView.MAX_FEDER_PEER] @property def send_batches(self): if self._send_batches is None: val = self._get_config_setting( name='bgx.publisher.send_batches', value_type=int, default_value=1, validate_function=lambda value: value==0 or value==1) self._send_batches = bool(val) return self._send_batches # bgx.consensus.block_timeout @property def block_timeout(self): if PbftSettingsView.BLOCK_TIMEOUT not in self._params : val = self._get_config_setting( name=PbftSettingsView.BLOCK_TIMEOUT, value_type=float, default_value=PbftSettingsView._BLOCK_TIMEOUT_, validate_function=lambda value: value) self._params[PbftSettingsView.BLOCK_TIMEOUT] = val LOGGER.debug('block_timeout new=%s',val) return self._params[PbftSettingsView.BLOCK_TIMEOUT] @property def signup_commit_maximum_delay(self): return self._signup_commit_maximum_delay @property def key_block_claim_limit(self): return self._key_block_claim_limit @property def block_claim_delay(self): return self._block_claim_delay
class PbftSettingsView: """A class to wrap the retrieval of PBFT configuration settings from the configuration view. For values that are not in the current state view or that are invalid, default values are returned. """ _NODE_ = 'plink' _NODES_ = "{\"0281e398fc978e8d36d6b2244c71e140f3ee464cb4c0371a193bb0a5c6574810ba\": \"leader\",\"028c7e06db3af50a9958390e3e29f166b1cf6198586acf37cde46c8ea54e4a79ef\": \"plink\"}" _MAX_LOG_SIZE_ = 1000 _BLOCK_DURATION_ = 200 _CHECKPOINT_PERIOD_ = 100 _VIEW_CHANGE_TIMEOUT_ = 4000 def __init__(self, state_view): """Initialize a PbftSettingsView object. Args: state_view (StateView): The current state view. Returns: None """ self._settings_view = SettingsView(state_view) self._node = None self._nodes = None self._max_log_size = None self._block_duration = None self._checkpoint_period = None self._view_change_timeout = None self._signup_commit_maximum_delay = 2 self._key_block_claim_limit = 2 self._block_claim_delay = 2 def _get_config_setting(self, name, value_type, default_value, validate_function=None): """Retrieves a value from the config view, returning the default value if does not exist in the current state view or if the value is invalid. Args: name (str): The config setting to return. value_type (type): The value type, for example, int, float, etc., of config value. default_value (object): The default value to be used if no value found or if value in config is invalid, for example, a non-integer value for an int config setting. validate_function (function): An optional function that can be applied to the setting to determine validity. The function should return True if setting is valid, False otherwise. Returns: The value for the config setting. """ try: value = \ self._settings_view.get_setting( key=name, default_value=default_value, value_type=value_type) if validate_function is not None: if not validate_function(value): raise \ ValueError( 'Value ({}) for {} is not valid'.format( value, name)) except ValueError: value = default_value return value @property def pbft_max_log_size(self): """Return the max log size if config setting exists and is valid, otherwise return the default. """ if self._max_log_size is None: self._max_log_size = self._get_config_setting( name='sawtooth.consensus.pbft.max_log_size', value_type=int, default_value=PbftSettingsView._MAX_LOG_SIZE_, validate_function=lambda value: value >= 0) return self._max_log_size @property def pbft_block_duration(self): """Return the block_duration if config setting exists and is valid, otherwise return the default. """ if self._block_duration is None: self._block_duration = self._get_config_setting( name='sawtooth.consensus.pbft.block_duration', value_type=int, default_value=PbftSettingsView._BLOCK_DURATION_, validate_function=lambda value: value >= 0) return self._block_duration @property def pbft_checkpoint_period(self): """Return the checkpoint_period if config setting exists and is valid, otherwise return the default. """ if self._checkpoint_period is None: self._block_duration = self._get_config_setting( name='sawtooth.consensus.pbft.checkpoint_period', value_type=int, default_value=PbftSettingsView._CHECKPOINT_PERIOD_, validate_function=lambda value: value >= 0) return self._checkpoint_period @property def pbft_view_change_timeout(self): """Return the view_change_timeout if config setting exists and is valid, otherwise return the default. """ if self._view_change_timeout is None: self._view_change_timeout = self._get_config_setting( name='sawtooth.consensus.pbft.view_change_timeout', value_type=int, default_value=PbftSettingsView._VIEW_CHANGE_TIMEOUT_, validate_function=lambda value: value >= 0) return self._view_change_timeout @property def pbft_node(self): """Return node type. """ if self._node is None: self._node = self._get_config_setting( name='sawtooth.consensus.pbft.node', value_type=str, default_value=PbftSettingsView._NODE_, validate_function=lambda value: value) return self._node @property def pbft_nodes(self): """Return nodes list. """ if self._nodes is None: self._nodes = self._get_config_setting( name='sawtooth.consensus.pbft.nodes', value_type=str, default_value=PbftSettingsView._NODES_, validate_function=lambda value: value) return self._nodes @property def signup_commit_maximum_delay(self): return self._signup_commit_maximum_delay @property def key_block_claim_limit(self): return self._key_block_claim_limit @property def block_claim_delay(self): return self._block_claim_delay
def _register_signup_information(self, block_header, pbft_enclave_module=None): # Create signup information for this validator, putting the block ID # of the block previous to the block referenced by block_header in the # nonce. Block ID is better than wait certificate ID for testing # freshness as we need to account for non-BGT blocks. LOGGER.debug('_register_signup_information: TRY to REGISTER') public_key_hash = hashlib.sha256( block_header.signer_public_key.encode()).hexdigest() nonce = SignupInfo.block_id_to_nonce(block_header.previous_block_id) pbft_public_key = self._validator_id anti_sybil_id = hashlib.sha256(pbft_public_key.encode()).hexdigest() signup_data = { 'pbft_public_key': pbft_public_key, } sealed_signup_data = base64.b64encode( dict2json(signup_data).encode()).decode('utf-8') """ signup_info = SignupInfo.create_signup_info( pbft_enclave_module=pbft_enclave_module, originator_public_key_hash=public_key_hash, nonce=nonce) """ # Create the validator registry payload payload = vr_pb.BgxValidatorRegistryPayload( verb='register', name='validator-{}'.format(block_header.signer_public_key[:8]), id=block_header.signer_public_key, node=self._node, signup_info=vr_pb.BgxSignUpInfo( pbft_public_key=pbft_public_key, # signup_info.pbft_public_key, anti_sybil_id=anti_sybil_id, # signup_info.anti_sybil_id, nonce=nonce), ) serialized = payload.SerializeToString() # Create the address that will be used to look up this validator # registry transaction. Seems like a potential for refactoring.. validator_entry_address = PbftBlockPublisher._validator_registry_namespace + hashlib.sha256( block_header.signer_public_key.encode()).hexdigest() # Create a transaction header and transaction for the validator # registry update amd then hand it off to the batch publisher to # send out. output_addresses = [ validator_entry_address, PbftBlockPublisher._validator_map_address ] input_addresses = output_addresses + \ [SettingsView.setting_address('sawtooth.bgt.report_public_key_pem'), SettingsView.setting_address('sawtooth.bgt.valid_enclave_measurements'), SettingsView.setting_address('sawtooth.bgt.valid_enclave_basenames') ] header = txn_pb.TransactionHeader( signer_public_key=block_header.signer_public_key, family_name='bgx_validator_registry', family_version='1.0', inputs=input_addresses, outputs=output_addresses, dependencies=[], payload_sha512=hashlib.sha512(serialized).hexdigest(), batcher_public_key=block_header.signer_public_key, nonce=hex(random.randint(0, 2**64))).SerializeToString() signature = self._batch_publisher.identity_signer.sign(header) transaction = txn_pb.Transaction(header=header, payload=serialized, header_signature=signature) LOGGER.info('Register Validator Name=%s, ID=%s...%s,Nonce=%s', payload.name, payload.id[:8], payload.id[-8:], nonce) self._batch_publisher.send([transaction]) # Store the key state so that we can look it up later if need be and # set the new key as our active key self._pbft_key_state_store[pbft_public_key] = PbftKeyState( sealed_signup_data=sealed_signup_data, has_been_refreshed=False, signup_nonce=nonce) self._pbft_key_state_store.active_key = pbft_public_key LOGGER.debug('_register_signup_information: REGISTER DONE')