def _handle_role_state_set(create_role, state): role_container = role_state_pb2.RoleAttributesContainer() role = role_container.role_attributes.add() role.role_id = create_role.role_id role.name = create_role.name role.metadata = create_role.metadata entries_to_set = [ StateEntry(address=addresser.make_role_attributes_address( create_role.role_id), data=role_container.SerializeToString()) ] pubkeys_by_address = {} for admin in list(create_role.admins): admin_address = addresser.make_role_admins_address( role_id=create_role.role_id, user_id=admin) if admin_address in pubkeys_by_address: pubkeys_by_address[admin_address].append(admin) else: pubkeys_by_address[admin_address] = [admin] for owner in list(create_role.owners): owner_address = addresser.make_role_owners_address( role_id=create_role.role_id, user_id=owner) if owner_address in pubkeys_by_address: pubkeys_by_address[owner_address].append(owner) else: pubkeys_by_address[owner_address] = [owner] state_returns = get_state(state, [ addresser.make_role_admins_address(role_id=create_role.role_id, user_id=a) for a in create_role.admins ] + [ addresser.make_role_owners_address(role_id=create_role.role_id, user_id=o) for o in create_role.owners ]) for addr, pubkeys in pubkeys_by_address.items(): try: state_entry = get_state_entry(state_returns, addr) container = role_state_pb2.RoleRelationshipContainer() container.ParseFromString(state_entry.data) except KeyError: container = role_state_pb2.RoleRelationshipContainer() _add_role_rel_to_container(container, create_role.role_id, pubkeys) entries_to_set.append( StateEntry(address=addr, data=container.SerializeToString())) set_state(state, entries_to_set)
def _store_state_data(addr, new_state, context): LOGGER.debug('Storing Upadated State....\nUPDATED STATE:\n%s', new_state) addresses = context.set_state( [StateEntry(address=addr, data=json.dumps(new_state).encode())]) if len(addresses) < 1: raise InternalError("State Error")
def _set_setting_value(context, key, value): address = _make_settings_key(key) setting = _get_setting_entry(context, address) old_value = None old_entry_index = None for i, entry in enumerate(setting.entries): if key == entry.key: old_value = entry.value old_entry_index = i if old_entry_index is not None: setting.entries[old_entry_index].value = value else: setting.entries.add(key=key, value=value) try: addresses = list( context.set_state([ StateEntry(address=address, data=setting.SerializeToString()) ], timeout=STATE_TIMEOUT_SEC)) except FutureTimeoutError: LOGGER.warning('Timeout occured on context.set_state([%s, <value>])', address) raise InternalError('Unable to set {}'.format(key)) if len(addresses) != 1: LOGGER.warning('Failed to save value on address %s', address) raise InternalError('Unable to save config value {}'.format(key)) if setting != 'sawtooth.settings.vote.proposals': LOGGER.info('Setting setting %s changed from %s to %s', key, old_value, value)
def handle_propose_state_set(state_entries, header, payload, address, proposal_type, state, related_type='user_id'): try: entry = get_state_entry(state_entries, address=address) proposal_container = return_prop_container(entry) except KeyError: proposal_container = proposal_state_pb2.ProposalsContainer() proposal = proposal_container.proposals.add() proposal.proposal_id = payload.proposal_id proposal.object_id = payload.task_id proposal.target_id = getattr(payload, related_type) proposal.proposal_type = proposal_type proposal.status = proposal_state_pb2.Proposal.OPEN proposal.opener = header.signer_pubkey proposal.open_reason = payload.reason proposal.metadata = payload.metadata set_state(state, [ StateEntry(address=address, data=proposal_container.SerializeToString()) ])
def handle_state_set(proposal_state_entries, header, user_proposal, state): proposal_address = addresser.make_proposal_address( user_proposal.user_id, user_proposal.new_manager_id) try: state_entry = get_state_entry(proposal_state_entries, proposal_address) proposal_container = return_prop_container(state_entry) except KeyError: proposal_container = proposal_state_pb2.ProposalsContainer() proposal = proposal_container.proposals.add() proposal.proposal_id = user_proposal.proposal_id proposal.proposal_type = proposal_state_pb2.Proposal.UPDATE_USER_MANAGER proposal.object_id = user_proposal.user_id proposal.target_id = user_proposal.new_manager_id proposal.opener = header.signer_pubkey proposal.status = proposal_state_pb2.Proposal.OPEN proposal.open_reason = user_proposal.reason proposal.metadata = user_proposal.metadata set_state(state, [ StateEntry(address=proposal_address, data=proposal_container.SerializeToString()) ])
def _set_container(state, address, container): addresses = state.set( [StateEntry( address=address, data=container.SerializeToString(), )]) if not addresses: raise InternalError('State error -- failed to set state entries')
def handle_create_task(state_entries, payload, state): try: entry = get_state_entry( state_entries, addresser.make_task_attributes_address(payload.task_id)) container = return_task_container(entry) except KeyError: container = task_state_pb2.TaskAttributesContainer() task = container.task_attributes.add() task.task_id = payload.task_id task.name = payload.name task.metadata = payload.metadata address_values = [] pubkeys_by_address = {} for pubkey in payload.admins: address = addresser.make_task_admins_address( task_id=payload.task_id, user_id=pubkey) if address in pubkeys_by_address: pubkeys_by_address[address].append(pubkey) else: pubkeys_by_address[address] = [pubkey] address_values += _handle_task_rel_container( state_entries=state_entries, create_task=payload, pubkeys_by_address=pubkeys_by_address, state=state) pubkeys_by_address = {} for pubkey in payload.owners: address = addresser.make_task_owners_address( task_id=payload.task_id, user_id=pubkey) if address in pubkeys_by_address: pubkeys_by_address[address].append(pubkey) else: pubkeys_by_address[address] = [pubkey] address_values += _handle_task_rel_container( state_entries=state_entries, create_task=payload, pubkeys_by_address=pubkeys_by_address, state=state) address_values += [StateEntry( address=addresser.make_task_attributes_address(payload.task_id), data=container.SerializeToString())] set_state( state, address_values)
def _set_role(data, context): role = Role() role.ParseFromString(data) if not role.name: raise InvalidTransaction("The name must be set in a role") if not role.policy_name: raise InvalidTransaction("A role must contain a policy name.") # Check that the policy refernced exists policy_address = _get_policy_address(role.policy_name) entries_list = _get_data(policy_address, context) if entries_list == []: raise InvalidTransaction( "Cannot set Role: {}, the Policy: {} is not set.".format( role.name, role.policy_name)) else: policy_list = PolicyList() policy_list.ParseFromString(entries_list[0].data) exist = False for policy in policy_list.policies: if policy.name == role.policy_name: exist = True break if not exist: raise InvalidTransaction( "Cannot set Role {}, the Policy {} is not set.".format( role.name, role.policy_name)) address = _get_role_address(role.name) entries_list = _get_data(address, context) # Store role in a Roleist incase of hash collisions role_list = RoleList() if entries_list != []: role_list.ParseFromString(entries_list[0].data) # sort all roles by using sorted(roles, Role.name) roles = [x for x in role_list.roles if x.name != role.name] roles.append(role) roles = sorted(roles, key=lambda role: role.name) # set RoleList at the address above. addresses = context.set_state([ StateEntry(address=address, data=RoleList(roles=roles).SerializeToString()) ]) if not addresses: LOGGER.warning('Failed to set role %s at %s', role.name, address) raise InternalError('Unable to save role {}'.format(role.name)) context.add_event(event_type="identity_update", attributes=[("updated", role.name)]) LOGGER.debug("Set role: \n%s", role)
def _set_state_data(name, state, state_store): address = make_intkey_address(name) encoded = cbor.dumps(state) addresses = state_store.set([StateEntry(address=address, data=encoded)]) if not addresses: raise InternalError('State error')
def handle_reject_state_set(container, proposal, closer, reason, address, state): proposal.status = proposal_state_pb2.Proposal.REJECTED proposal.closer = closer proposal.close_reason = reason set_state( state, [StateEntry(address=address, data=container.SerializeToString())])
def handle_confirm_add(state_entries, header, confirm, role_rel_address, state, rel_type='user_id'): proposal_address = addresser.make_proposal_address( object_id=confirm.role_id, related_id=getattr(confirm, rel_type)) proposal_entry = get_state_entry(state_entries, proposal_address) proposal_container = return_prop_container(proposal_entry) proposal = get_prop_from_container(proposal_container, proposal_id=confirm.proposal_id) proposal.status = proposal_state_pb2.Proposal.CONFIRMED proposal.closer = header.signer_pubkey proposal.close_reason = confirm.reason address_values = [ StateEntry(address=proposal_address, data=proposal_container.SerializeToString()) ] try: role_rel_entry = get_state_entry(state_entries, role_rel_address) role_rel_container = return_role_rel_container(role_rel_entry) except KeyError: role_rel_container = role_state_pb2.RoleRelationshipContainer() try: role_rel = get_role_rel(role_rel_container, confirm.role_id) except KeyError: role_rel = role_rel_container.relationships.add() role_rel.role_id = confirm.role_id role_rel.identifiers.append(getattr(confirm, rel_type)) address_values.append( StateEntry(address=role_rel_address, data=role_rel_container.SerializeToString())) set_state(state, address_values)
def handle_confirm_state_set(container, proposal, closer, reason, address, user_id, new_manager_id, state): proposal.status = proposal_state_pb2.Proposal.CONFIRMED proposal.closer = closer proposal.close_reason = reason set_state( state, [StateEntry(address=address, data=container.SerializeToString())]) user_address = addresser.make_user_address(user_id) state_entries = get_state(state, [user_address]) state_entry = get_state_entry(state_entries=state_entries, address=user_address) user_container = return_user_container(state_entry) user = get_user_from_container(user_container, user_id) user.manager_id = new_manager_id set_state(state, [ StateEntry(address=user_address, data=user_container.SerializeToString()) ])
def handle_confirm_add(state_entries, header, confirm, task_rel_address, state): proposal_address = addresser.make_proposal_address( object_id=confirm.task_id, related_id=confirm.user_id) proposal_entry = get_state_entry(state_entries, proposal_address) proposal_container = return_prop_container(proposal_entry) proposal = get_prop_from_container(proposal_container, proposal_id=confirm.proposal_id) proposal.status = proposal_state_pb2.Proposal.CONFIRMED proposal.closer = header.signer_pubkey proposal.close_reason = confirm.reason address_values = [ StateEntry(address=proposal_address, data=proposal_container.SerializeToString()) ] try: task_rel_entry = get_state_entry(state_entries, task_rel_address) task_rel_container = return_task_rel_container(task_rel_entry) except KeyError: task_rel_container = task_state_pb2.TaskRelationshipContainer() try: task_rel = get_task_rel_from_container(container=task_rel_container, task_id=confirm.task_id, identifier=confirm.user_id) except KeyError: task_rel = task_rel_container.relationships.add() task_rel.task_id = confirm.task_id task_rel.identifiers.append(confirm.user_id) address_values.append( StateEntry(address=task_rel_address, data=task_rel_container.SerializeToString())) set_state(state, address_values)
def _set(state, items): entries = [] for (addr, container) in items: entries.append( StateEntry(address=addr, data=container.SerializeToString())) result_addresses = state.set(entries) if result_addresses: for (addr, _) in items: if addr not in result_addresses: raise InternalError( "Error setting state, " + "address %s not set.", addr) else: raise InternalError("Error setting state nothing updated?")
def _set_policy(data, context): new_policy = Policy() new_policy.ParseFromString(data) if not new_policy.entries: raise InvalidTransaction("Atleast one entry must be in a policy.") if not new_policy.name: raise InvalidTransaction("The name must be set in a policy.") # check entries in the policy for entry in new_policy.entries: if not entry.key: raise InvalidTransaction("Every policy entry must have a key.") address = _get_policy_address(new_policy.name) entries_list = _get_data(address, context) policy_list = PolicyList() policies = [] if entries_list != []: policy_list.ParseFromString(entries_list[0].data) # sort all roles by using sorted(roles, policy.name) # if a policy with the same name exists, replace that policy policies = [ x for x in policy_list.policies if x.name != new_policy.name ] policies.append(new_policy) policies = sorted(policies, key=lambda role: role.name) else: policies.append(new_policy) address = _get_policy_address(new_policy.name) # Store policy in a PolicyList incase of hash collisions new_policy_list = PolicyList(policies=policies) addresses = context.set_state([ StateEntry(address=address, data=new_policy_list.SerializeToString()) ]) if not addresses: LOGGER.warning('Failed to set policy %s at %s', new_policy.name, address) raise InternalError('Unable to save policy {}'.format(new_policy.name)) context.add_event(event_type="identity_update", attributes=[("updated", new_policy.name)]) LOGGER.debug("Set policy : \n%s", new_policy)
def handle_user_state_set(header, create_user, state, manager_id=None): user_container = user_state_pb2.UserContainer() user = user_state_pb2.User(user_id=create_user.user_id, name=create_user.name, metadata=create_user.metadata) if manager_id: user.manager_id = manager_id user_container.users.extend([user]) set_state(state, [ StateEntry(address=addresser.make_user_address(create_user.user_id), data=user_container.SerializeToString()) ])
def _set_data(state, address, data): try: addresses = list( state.set([StateEntry(address=address, data=data)], timeout=STATE_TIMEOUT_SEC)) except FutureTimeoutError: LOGGER.warning('Timeout occurred on state.set([%s, <value>])', address) raise InternalError( 'Failed to save value on address {}'.format(address)) if len(addresses) != 1: LOGGER.warning('Failed to save value on address %s', address) raise InternalError( 'Failed to save value on address {}'.format(address))
def _store_state_data(context, game_list, namespace_prefix, name, board, state, player1, player2): game_list[name] = board, state, player1, player2 state_data = '|'.join( sorted([ ','.join([name, board, state, player1, player2]) for name, (board, state, player1, player2) in game_list.items() ])).encode() addresses = context.set_state([ StateEntry(address=_make_xo_address(namespace_prefix, name), data=state_data) ]) if len(addresses) < 1: raise InternalError("State Error")
def handle_reject(state_entries, header, reject, state): proposal_address = addresser.make_proposal_address( object_id=reject.task_id, related_id=reject.user_id) proposal_entry = get_state_entry(state_entries, proposal_address) proposal_container = return_prop_container(proposal_entry) proposal = get_prop_from_container(proposal_container, proposal_id=reject.proposal_id) proposal.status = proposal_state_pb2.Proposal.REJECTED proposal.closer = header.signer_pubkey proposal.close_reason = reject.reason address_values = [ StateEntry(address=proposal_address, data=proposal_container.SerializeToString()) ] set_state(state, address_values)
def _handle_task_rel_container(state_entries, create_task, pubkeys_by_address, state): entries_to_set = [] for addr, pubkeys in pubkeys_by_address.items(): try: state_entry = get_state_entry(state_entries, addr) container = task_state_pb2.TaskRelationshipContainer() container.ParseFromString(state_entry.data) except KeyError: container = task_state_pb2.TaskRelationshipContainer() _add_task_rel_to_container(container, create_task.task_id, pubkeys) entries_to_set.append( StateEntry( address=addr, data=container.SerializeToString())) return entries_to_set
def _make_entries(self, protobuf=True): if protobuf: return [Entry(address=a, data=d) for a, d in zip(self.addresses, self.data)] return [StateEntry(address=a, data=d) for a, d in zip(self.addresses, self.data)]
def apply(self, transaction, context): # Unpack payload txn = BlockInfoTxn() txn.ParseFromString(transaction.payload) next_block = txn.block # Validate block info fields if next_block.block_num < 0: raise InvalidTransaction( "Invalid block num '{}'".format(next_block.block_num)) if not (validate_hex(next_block.previous_block_id, 128) or next_block.previous_block_id == "0000000000000000"): raise InvalidTransaction("Invalid previous block id '{}'".format( next_block.previous_block_id)) if not validate_hex(next_block.signer_pubkey, 66): raise InvalidTransaction("Invalid signer pubkey '{}'".format( next_block.signer_pubkey)) if not validate_hex(next_block.header_signature, 128): raise InvalidTransaction("Invalid header signature '{}'".format( next_block.header_signature)) if next_block.timestamp <= 0: raise InvalidTransaction( "Invalid timestamp '{}'".format(next_block.timestamp)) # Get config and previous block (according to the block info in the # transaction) from state entries = context.get_state([CONFIG_ADDRESS]) deletes = [] sets = [] config = BlockInfoConfig() # If there is no config in state, we don't know anything about what's # in state, so we have to treat this as the first entry if not entries: # If sync tolerance or target count were not specified in the txn, # use default values. config.sync_tolerance = \ DEFAULT_SYNC_TOLERANCE if txn.sync_tolerance == 0 \ else txn.sync_tolerance config.target_count = \ DEFAULT_TARGET_COUNT if txn.target_count == 0 \ else txn.target_count config.latest_block = next_block.block_num config.oldest_block = next_block.block_num validate_timestamp(next_block.timestamp, config.sync_tolerance) sets.append((CONFIG_ADDRESS, config.SerializeToString())) sets.append(( create_block_address(next_block.block_num), next_block.SerializeToString())) else: config.ParseFromString(entries[0].data) # If the config was changed in this transaction if txn.sync_tolerance != 0: config.sync_tolerance = txn.sync_tolerance if txn.target_count != 0: config.target_count = txn.target_count if next_block.block_num - 1 != config.latest_block: raise InvalidTransaction( "Block number must be one more than previous block's." " Got {} expected {}".format( next_block.block_num, config.latest_block + 1)) validate_timestamp(next_block.timestamp, config.sync_tolerance) entries = context.get_state( [create_block_address(config.latest_block)]) if not entries: raise InternalError( "Config and state out of sync. Latest block not found in" " state.") prev_block = BlockInfo() prev_block.ParseFromString(entries[0].data) if prev_block.block_num != config.latest_block: raise InternalError( "Block info stored at latest block has incorrect block" " num.") if next_block.previous_block_id != prev_block.header_signature: raise InvalidTransaction( "Previous block id must match header signature of previous" " block. Go {} expected {}".format( next_block.previous_block_id, prev_block.header_signature)) if next_block.timestamp < prev_block.timestamp: raise InvalidTransaction( "Timestamp must be greater than previous block's." " Got {}, expected >{}".format( next_block.timestamp, prev_block.timestamp)) config.latest_block = next_block.block_num while (config.latest_block - config.oldest_block) \ > config.target_count: deletes.append(create_block_address(config.oldest_block)) config.oldest_block = config.oldest_block + 1 sets.append((CONFIG_ADDRESS, config.SerializeToString())) sets.append(( create_block_address(next_block.block_num), next_block.SerializeToString())) # If this is not true, something else has modified global state if deletes: if set(deletes) != set(context.delete(deletes)): raise InternalError( "Blocks should have been in state but weren't: {}".format( deletes)) if sets: addresses = set([k for k, _ in sets]) addresses_set = set(context.set_state([ StateEntry(address=k, data=v) for k, v in sets])) if addresses != addresses_set: raise InternalError("Failed to set addresses.") return None