From bf8f0f22354b845fe16b49e3e65e8212156070ea Mon Sep 17 00:00:00 2001 From: Cameron Voell <1103838+cameronvoell@users.noreply.github.com> Date: Tue, 30 Jul 2024 08:23:43 -0700 Subject: [PATCH 01/11] Adds functions for creating a DM group (#901) * update bindings cargo locks * Added dm group functionality * dm members can update all metadata * fix tests * fix indentation * fix test imports * gen protos back to main --------- Co-authored-by: cameronvoell --- xmtp_mls/src/client.rs | 17 + xmtp_mls/src/groups/group_metadata.rs | 80 +- xmtp_mls/src/groups/group_mutable_metadata.rs | 29 + xmtp_mls/src/groups/group_permissions.rs | 289 +++- xmtp_mls/src/groups/mod.rs | 155 +- xmtp_mls/src/groups/validated_commit.rs | 4 +- xmtp_proto/src/gen/xmtp.message_contents.rs | 28 +- .../src/gen/xmtp.message_contents.serde.rs | 14 +- .../src/gen/xmtp.mls.message_contents.rs | 1522 +++++++++-------- .../gen/xmtp.mls.message_contents.serde.rs | 220 +++ 10 files changed, 1544 insertions(+), 814 deletions(-) diff --git a/xmtp_mls/src/client.rs b/xmtp_mls/src/client.rs index fc9270c29..aabf75f79 100644 --- a/xmtp_mls/src/client.rs +++ b/xmtp_mls/src/client.rs @@ -350,6 +350,23 @@ where Ok(group) } + /// Create a new Direct Message with the default settings + pub fn create_dm(&self, dm_target_inbox_id: InboxId) -> Result { + log::info!("creating dm with {}", dm_target_inbox_id); + + let group = MlsGroup::create_dm_and_insert( + self.context.clone(), + GroupMembershipState::Allowed, + dm_target_inbox_id, + ) + .map_err(Box::new)?; + + // notify any streams of the new group + let _ = self.local_events.send(LocalEvents::NewGroup(group.clone())); + + Ok(group) + } + pub(crate) fn create_sync_group(&self) -> Result { log::info!("creating sync group"); let sync_group = diff --git a/xmtp_mls/src/groups/group_metadata.rs b/xmtp_mls/src/groups/group_metadata.rs index e8db126a5..781ab0f49 100644 --- a/xmtp_mls/src/groups/group_metadata.rs +++ b/xmtp_mls/src/groups/group_metadata.rs @@ -3,7 +3,8 @@ use prost::Message; use thiserror::Error; use xmtp_proto::xmtp::mls::message_contents::{ - ConversationType as ConversationTypeProto, GroupMetadataV1 as GroupMetadataProto, + ConversationType as ConversationTypeProto, DmMembers as DmMembersProto, + GroupMetadataV1 as GroupMetadataProto, Inbox as InboxProto, }; #[derive(Debug, Error)] @@ -23,39 +24,35 @@ pub struct GroupMetadata { pub conversation_type: ConversationType, // TODO: Remove this once transition is completed pub creator_inbox_id: String, + pub dm_members: Option, } impl GroupMetadata { - pub fn new(conversation_type: ConversationType, creator_inbox_id: String) -> Self { + pub fn new( + conversation_type: ConversationType, + creator_inbox_id: String, + dm_members: Option, + ) -> Self { Self { conversation_type, creator_inbox_id, + dm_members, } } - - pub(crate) fn from_proto(proto: GroupMetadataProto) -> Result { - Ok(Self::new( - proto.conversation_type.try_into()?, - proto.creator_inbox_id.clone(), - )) - } - - pub(crate) fn to_proto(&self) -> Result { - let conversation_type: ConversationTypeProto = self.conversation_type.clone().into(); - Ok(GroupMetadataProto { - conversation_type: conversation_type as i32, - creator_inbox_id: self.creator_inbox_id.clone(), - creator_account_address: "".to_string(), // TODO: remove from proto - }) - } } impl TryFrom for Vec { type Error = GroupMetadataError; fn try_from(value: GroupMetadata) -> Result { - let mut buf = Vec::new(); - let proto_val = value.to_proto()?; + let conversation_type: ConversationTypeProto = value.conversation_type.clone().into(); + let proto_val = GroupMetadataProto { + conversation_type: conversation_type as i32, + creator_inbox_id: value.creator_inbox_id.clone(), + creator_account_address: "".to_string(), // TODO: remove from proto + dm_members: value.dm_members.clone().map(|dm| dm.into()), + }; + let mut buf: Vec = Vec::new(); proto_val.encode(&mut buf)?; Ok(buf) @@ -67,7 +64,7 @@ impl TryFrom<&Vec> for GroupMetadata { fn try_from(value: &Vec) -> Result { let proto_val = GroupMetadataProto::decode(value.as_slice())?; - Self::from_proto(proto_val) + proto_val.try_into() } } @@ -75,7 +72,16 @@ impl TryFrom for GroupMetadata { type Error = GroupMetadataError; fn try_from(value: GroupMetadataProto) -> Result { - Self::from_proto(value) + let dm_members = if value.dm_members.is_some() { + Some(DmMembers::try_from(value.dm_members.unwrap())?) + } else { + None + }; + Ok(Self::new( + value.conversation_type.try_into()?, + value.creator_inbox_id.clone(), + dm_members, + )) } } @@ -120,6 +126,36 @@ impl TryFrom for ConversationType { } } +#[derive(Debug, Clone, PartialEq)] +pub struct DmMembers { + pub member_one_inbox_id: String, + pub member_two_inbox_id: String, +} + +impl From for DmMembersProto { + fn from(value: DmMembers) -> Self { + DmMembersProto { + dm_member_one: Some(InboxProto { + inbox_id: value.member_one_inbox_id.clone(), + }), + dm_member_two: Some(InboxProto { + inbox_id: value.member_two_inbox_id.clone(), + }), + } + } +} + +impl TryFrom for DmMembers { + type Error = GroupMetadataError; + + fn try_from(value: DmMembersProto) -> Result { + Ok(Self { + member_one_inbox_id: value.dm_member_one.unwrap().inbox_id.clone(), + member_two_inbox_id: value.dm_member_two.unwrap().inbox_id.clone(), + }) + } +} + pub fn extract_group_metadata(group: &OpenMlsGroup) -> Result { let extension = group .export_group_context() diff --git a/xmtp_mls/src/groups/group_mutable_metadata.rs b/xmtp_mls/src/groups/group_mutable_metadata.rs index 6b1eaf2fe..b97c14c0e 100644 --- a/xmtp_mls/src/groups/group_mutable_metadata.rs +++ b/xmtp_mls/src/groups/group_mutable_metadata.rs @@ -113,6 +113,35 @@ impl GroupMutableMetadata { } } + // Admin / super admin is not needed for a DM + pub fn new_dm_default(_creator_inbox_id: String, _dm_target_inbox_id: String) -> Self { + let mut attributes = HashMap::new(); + // TODO: would it be helpful to incorporate the dm inbox ids in the name or description? + attributes.insert( + MetadataField::GroupName.to_string(), + DEFAULT_GROUP_NAME.to_string(), + ); + attributes.insert( + MetadataField::Description.to_string(), + DEFAULT_GROUP_DESCRIPTION.to_string(), + ); + attributes.insert( + MetadataField::GroupImageUrlSquare.to_string(), + DEFAULT_GROUP_IMAGE_URL_SQUARE.to_string(), + ); + attributes.insert( + MetadataField::GroupPinnedFrameUrl.to_string(), + DEFAULT_GROUP_PINNED_FRAME_URL.to_string(), + ); + let admin_list = vec![]; + let super_admin_list = vec![]; + Self { + attributes, + admin_list, + super_admin_list, + } + } + // These fields will receive default permission policies for new groups pub fn supported_fields() -> Vec { vec![ diff --git a/xmtp_mls/src/groups/group_permissions.rs b/xmtp_mls/src/groups/group_permissions.rs index 443ef9bc2..883a3ba2a 100644 --- a/xmtp_mls/src/groups/group_permissions.rs +++ b/xmtp_mls/src/groups/group_permissions.rs @@ -209,6 +209,15 @@ impl MetadataPolicies { map } + // by default members of DM groups can update all metadata + pub fn dm_map() -> HashMap { + let mut map: HashMap = HashMap::new(); + for field in GroupMutableMetadata::supported_fields() { + map.insert(field.to_string(), MetadataPolicies::allow()); + } + map + } + pub fn allow() -> Self { MetadataPolicies::Standard(MetadataBasePolicies::Allow) } @@ -832,14 +841,37 @@ impl PolicySet { } } + pub fn new_dm() -> Self { + Self { + add_member_policy: MembershipPolicies::deny(), + remove_member_policy: MembershipPolicies::deny(), + update_metadata_policy: MetadataPolicies::dm_map(), + add_admin_policy: PermissionsPolicies::deny(), + remove_admin_policy: PermissionsPolicies::deny(), + update_permissions_policy: PermissionsPolicies::deny(), + } + } + pub fn evaluate_commit(&self, commit: &ValidatedCommit) -> bool { // Verify add member policy was not violated - let added_inboxes_valid = self.evaluate_policy( + let mut added_inboxes_valid = self.evaluate_policy( commit.added_inboxes.iter(), &self.add_member_policy, &commit.actor, ); + // We can always add DM member's inboxId to a DM + if commit.dm_members.is_some() + && commit.added_inboxes.len() == 1 + && (commit.added_inboxes[0].inbox_id + == commit.dm_members.as_ref().unwrap().member_one_inbox_id + || commit.added_inboxes[0].inbox_id + == commit.dm_members.as_ref().unwrap().member_two_inbox_id) + && commit.added_inboxes[0].inbox_id != commit.actor_inbox_id() + { + added_inboxes_valid = true; + } + // Verify remove member policy was not violated // Super admin can not be removed from a group let removed_inboxes_valid = self.evaluate_policy( @@ -1141,7 +1173,10 @@ impl std::fmt::Display for PreconfiguredPolicies { #[cfg(test)] mod tests { use crate::{ - groups::{group_mutable_metadata::MetadataField, validated_commit::MutableMetadataChanges}, + groups::{ + group_metadata::DmMembers, group_mutable_metadata::MetadataField, + validated_commit::MutableMetadataChanges, + }, utils::test::{rand_string, rand_vec}, }; @@ -1171,26 +1206,34 @@ mod tests { } } + enum MemberType { + SameAsActor, + DmTarget, + Random, + } + fn build_validated_commit( // Add a member with the same account address as the actor if true, random account address if false - member_added: Option, - member_removed: Option, + member_added: Option, + member_removed: Option, metadata_fields_changed: Option>, permissions_changed: bool, actor_is_admin: bool, actor_is_super_admin: bool, + dm_target_inbox_id: Option, ) -> ValidatedCommit { let actor = build_actor(None, None, actor_is_admin, actor_is_super_admin); - let build_membership_change = |same_address_as_actor| { - if same_address_as_actor { - vec![build_change( - Some(actor.inbox_id.clone()), - actor_is_admin, - actor_is_super_admin, - )] - } else { - vec![build_change(None, false, false)] + let dm_target_inbox_id_clone = dm_target_inbox_id.clone(); + let build_membership_change = |member_type: MemberType| match member_type { + MemberType::SameAsActor => vec![build_change( + Some(actor.inbox_id.clone()), + actor_is_admin, + actor_is_super_admin, + )], + MemberType::DmTarget => { + vec![build_change(dm_target_inbox_id_clone.clone(), false, false)] } + MemberType::Random => vec![build_change(None, false, false)], }; let field_changes = metadata_fields_changed @@ -1199,6 +1242,15 @@ mod tests { .map(|field| MetadataFieldChange::new(field, Some(rand_string()), Some(rand_string()))) .collect(); + let dm_members = if let Some(dm_target_inbox_id) = dm_target_inbox_id { + Some(DmMembers { + member_one_inbox_id: actor.inbox_id.clone(), + member_two_inbox_id: dm_target_inbox_id, + }) + } else { + None + }; + ValidatedCommit { actor: actor.clone(), added_inboxes: member_added @@ -1212,6 +1264,7 @@ mod tests { ..Default::default() }, permissions_changed, + dm_members, } } @@ -1226,7 +1279,15 @@ mod tests { PermissionsPolicies::allow_if_actor_super_admin(), ); - let commit = build_validated_commit(Some(true), Some(true), None, false, false, false); + let commit = build_validated_commit( + Some(MemberType::SameAsActor), + Some(MemberType::SameAsActor), + None, + false, + false, + false, + None, + ); assert!(permissions.evaluate_commit(&commit)); } @@ -1241,12 +1302,26 @@ mod tests { PermissionsPolicies::allow_if_actor_super_admin(), ); - let member_added_commit = - build_validated_commit(Some(false), None, None, false, false, false); + let member_added_commit = build_validated_commit( + Some(MemberType::Random), + None, + None, + false, + false, + false, + None, + ); assert!(!permissions.evaluate_commit(&member_added_commit)); - let member_removed_commit = - build_validated_commit(None, Some(false), None, false, false, false); + let member_removed_commit = build_validated_commit( + None, + Some(MemberType::Random), + None, + false, + false, + false, + None, + ); assert!(!permissions.evaluate_commit(&member_removed_commit)); } @@ -1262,16 +1337,37 @@ mod tests { ); // Can not remove the creator if they are the only super admin - let commit_with_creator = - build_validated_commit(Some(true), Some(true), None, false, false, true); + let commit_with_creator = build_validated_commit( + Some(MemberType::SameAsActor), + Some(MemberType::SameAsActor), + None, + false, + false, + true, + None, + ); assert!(!permissions.evaluate_commit(&commit_with_creator)); - let commit_with_creator = - build_validated_commit(Some(true), Some(false), None, false, false, true); + let commit_with_creator = build_validated_commit( + Some(MemberType::SameAsActor), + Some(MemberType::Random), + None, + false, + false, + true, + None, + ); assert!(permissions.evaluate_commit(&commit_with_creator)); - let commit_without_creator = - build_validated_commit(Some(true), Some(true), None, false, false, false); + let commit_without_creator = build_validated_commit( + Some(MemberType::SameAsActor), + Some(MemberType::SameAsActor), + None, + false, + false, + false, + None, + ); assert!(!permissions.evaluate_commit(&commit_without_creator)); } @@ -1286,12 +1382,26 @@ mod tests { PermissionsPolicies::allow_if_actor_super_admin(), ); - let commit_with_same_member = - build_validated_commit(Some(true), None, None, false, false, false); + let commit_with_same_member = build_validated_commit( + Some(MemberType::SameAsActor), + None, + None, + false, + false, + false, + None, + ); assert!(permissions.evaluate_commit(&commit_with_same_member)); - let commit_with_different_member = - build_validated_commit(Some(false), None, None, false, false, false); + let commit_with_different_member = build_validated_commit( + Some(MemberType::Random), + None, + None, + false, + false, + false, + None, + ); assert!(!permissions.evaluate_commit(&commit_with_different_member)); } @@ -1309,8 +1419,15 @@ mod tests { PermissionsPolicies::allow_if_actor_super_admin(), ); - let member_added_commit = - build_validated_commit(Some(true), None, None, false, false, false); + let member_added_commit = build_validated_commit( + Some(MemberType::SameAsActor), + None, + None, + false, + false, + false, + None, + ); assert!(!permissions.evaluate_commit(&member_added_commit)); } @@ -1328,8 +1445,15 @@ mod tests { PermissionsPolicies::allow_if_actor_super_admin(), ); - let member_added_commit = - build_validated_commit(Some(true), None, None, false, false, false); + let member_added_commit = build_validated_commit( + Some(MemberType::SameAsActor), + None, + None, + false, + false, + false, + None, + ); assert!(permissions.evaluate_commit(&member_added_commit)); } @@ -1372,12 +1496,13 @@ mod tests { ); let member_added_commit = build_validated_commit( - Some(true), + Some(MemberType::SameAsActor), None, Some(vec![MetadataField::GroupName.to_string()]), false, false, false, + None, ); assert!(allow_permissions.evaluate_commit(&member_added_commit)); @@ -1474,11 +1599,11 @@ mod tests { ); // Commit should fail because actor is not superadmin - let commit = build_validated_commit(None, None, None, true, false, false); + let commit = build_validated_commit(None, None, None, true, false, false, None); assert!(!permissions.evaluate_commit(&commit)); // Commit should pass because actor is superadmin - let commit = build_validated_commit(None, None, None, true, false, true); + let commit = build_validated_commit(None, None, None, true, false, true, None); assert!(permissions.evaluate_commit(&commit)); } @@ -1502,6 +1627,7 @@ mod tests { false, false, false, + None, ); assert!(permissions.evaluate_commit(&name_updated_commit)); @@ -1513,6 +1639,7 @@ mod tests { false, false, false, + None, ); assert!(!permissions.evaluate_commit(&non_existing_field_updated_commit)); @@ -1524,6 +1651,7 @@ mod tests { false, true, false, + None, ); assert!(permissions.evaluate_commit(&non_existing_field_updated_commit)); @@ -1537,6 +1665,7 @@ mod tests { false, true, false, + None, ); assert!(!permissions.evaluate_commit(&non_existing_field_updated_commit)); @@ -1550,7 +1679,97 @@ mod tests { false, false, true, + None, ); assert!(permissions.evaluate_commit(&non_existing_field_updated_commit)); } + + #[test] + fn test_dm_group_permissions() { + // Simulate a group with DM Permissions + let permissions = PolicySet::new_dm(); + + // String below represents the inbox id of the DM target + const TARGET_INBOX_ID: &str = "example_target_dm_id"; + + // DM group can not add a random inbox + let commit = build_validated_commit( + Some(MemberType::Random), + None, + None, + false, + false, + false, + Some(TARGET_INBOX_ID.to_string()), + ); + assert!(!permissions.evaluate_commit(&commit)); + + // DM group can not add themselves + let commit = build_validated_commit( + Some(MemberType::SameAsActor), + None, + None, + false, + false, + false, + Some(TARGET_INBOX_ID.to_string()), + ); + assert!(!permissions.evaluate_commit(&commit)); + + // DM group can add the target inbox + let commit = build_validated_commit( + Some(MemberType::DmTarget), + None, + None, + false, + false, + false, + Some(TARGET_INBOX_ID.to_string()), + ); + assert!(permissions.evaluate_commit(&commit)); + + // DM group can not remove + let commit = build_validated_commit( + None, + Some(MemberType::Random), + None, + false, + false, + false, + Some(TARGET_INBOX_ID.to_string()), + ); + assert!(!permissions.evaluate_commit(&commit)); + let commit = build_validated_commit( + None, + Some(MemberType::DmTarget), + None, + false, + false, + false, + Some(TARGET_INBOX_ID.to_string()), + ); + assert!(!permissions.evaluate_commit(&commit)); + let commit = build_validated_commit( + None, + Some(MemberType::SameAsActor), + None, + false, + false, + false, + Some(TARGET_INBOX_ID.to_string()), + ); + assert!(!permissions.evaluate_commit(&commit)); + + // DM group can update metadata + let commit = build_validated_commit( + None, + None, + Some(vec![MetadataField::GroupName.to_string()]), + false, + false, + false, + Some(TARGET_INBOX_ID.to_string()), + ); + assert!(permissions.evaluate_commit(&commit)); + } } diff --git a/xmtp_mls/src/groups/mod.rs b/xmtp_mls/src/groups/mod.rs index 2ce711899..79ad6a378 100644 --- a/xmtp_mls/src/groups/mod.rs +++ b/xmtp_mls/src/groups/mod.rs @@ -36,7 +36,7 @@ pub use self::group_permissions::PreconfiguredPolicies; pub use self::intents::{AddressesOrInstallationIds, IntentError}; use self::{ group_membership::GroupMembership, - group_metadata::extract_group_metadata, + group_metadata::{extract_group_metadata, DmMembers}, group_mutable_metadata::{GroupMutableMetadata, GroupMutableMetadataError, MetadataField}, group_permissions::{ extract_group_permissions, GroupMutablePermissions, GroupMutablePermissionsError, @@ -178,6 +178,8 @@ pub enum GroupError { PublishCancelled, #[error("the publish failed to complete due to panic")] PublishPanicked, + #[error("dm requires target inbox_id")] + InvalidDmMissingInboxId, } impl RetryableError for GroupError { @@ -302,6 +304,55 @@ impl MlsGroup { )) } + // Create a new DM and save it to the DB + pub fn create_dm_and_insert( + context: Arc, + membership_state: GroupMembershipState, + dm_target_inbox_id: InboxId, + ) -> Result { + let conn = context.store.conn()?; + let provider = XmtpOpenMlsProvider::new(conn); + let protected_metadata = + build_dm_protected_metadata_extension(&context.identity, dm_target_inbox_id.clone())?; + let mutable_metadata = + build_dm_mutable_metadata_extension_default(context.inbox_id(), dm_target_inbox_id)?; + let group_membership = build_starting_group_membership_extension(context.inbox_id(), 0); + let mutable_permissions = PolicySet::new_dm(); + let mutable_permission_extension = + build_mutable_permissions_extension(mutable_permissions)?; + let group_config = build_group_config( + protected_metadata, + mutable_metadata, + group_membership, + mutable_permission_extension, + )?; + + let mls_group = OpenMlsGroup::new( + &provider, + &context.identity.installation_keys, + &group_config, + CredentialWithKey { + credential: context.identity.credential(), + signature_key: context.identity.installation_keys.to_public_vec().into(), + }, + )?; + + let group_id = mls_group.group_id().to_vec(); + let stored_group = StoredGroup::new( + group_id.clone(), + now_ns(), + membership_state, + context.inbox_id(), + ); + + stored_group.store(provider.conn_ref())?; + Ok(Self::new( + context.clone(), + group_id, + stored_group.created_at_ns, + )) + } + // Create a group from a decrypted and decoded welcome message // If the group already exists in the store, overwrite the MLS state and do not update the group entry async fn create_from_welcome( @@ -936,7 +987,27 @@ fn build_protected_metadata_extension( Purpose::Conversation => ConversationType::Group, Purpose::Sync => ConversationType::Sync, }; - let metadata = GroupMetadata::new(group_type, identity.inbox_id().clone()); + + let metadata = GroupMetadata::new(group_type, identity.inbox_id().clone(), None); + let protected_metadata = Metadata::new(metadata.try_into()?); + + Ok(Extension::ImmutableMetadata(protected_metadata)) +} + +fn build_dm_protected_metadata_extension( + identity: &Identity, + dm_inbox_id: InboxId, +) -> Result { + let dm_members = Some(DmMembers { + member_one_inbox_id: identity.inbox_id().clone(), + member_two_inbox_id: dm_inbox_id, + }); + + let metadata = GroupMetadata::new( + ConversationType::Dm, + identity.inbox_id().clone(), + dm_members, + ); let protected_metadata = Metadata::new(metadata.try_into()?); Ok(Extension::ImmutableMetadata(protected_metadata)) @@ -966,6 +1037,20 @@ pub fn build_mutable_metadata_extension_default( )) } +pub fn build_dm_mutable_metadata_extension_default( + creator_inbox_id: String, + dm_target_inbox_id: String, +) -> Result { + let mutable_metadata: Vec = + GroupMutableMetadata::new_dm_default(creator_inbox_id, dm_target_inbox_id).try_into()?; + let unknown_gc_extension = UnknownExtension(mutable_metadata); + + Ok(Extension::Unknown( + MUTABLE_METADATA_EXTENSION_ID, + unknown_gc_extension, + )) +} + #[tracing::instrument(level = "trace", skip_all)] pub fn build_extensions_for_metadata_update( group: &OpenMlsGroup, @@ -2692,4 +2777,70 @@ mod tests { ] ); } + + #[tokio::test(flavor = "multi_thread")] + async fn test_dm_creation() { + let amal = ClientBuilder::new_test_client(&generate_local_wallet()).await; + let bola = ClientBuilder::new_test_client(&generate_local_wallet()).await; + let caro = ClientBuilder::new_test_client(&generate_local_wallet()).await; + + // Amal creates a dm group targetting bola + let amal_dm: MlsGroup = amal.create_dm(bola.inbox_id()).unwrap(); + + // Amal can not add caro to the dm group + let result = amal_dm + .add_members_by_inbox_id(&amal, vec![bola.inbox_id(), caro.inbox_id()]) + .await; + assert!(result.is_err()); + let result = amal_dm + .add_members_by_inbox_id(&amal, vec![caro.inbox_id()]) + .await; + assert!(result.is_err()); + amal_dm.sync(&amal).await.unwrap(); + let members = amal_dm.members().unwrap(); + assert_eq!(members.len(), 1); + + // Amal can add bola + amal_dm + .add_members_by_inbox_id(&amal, vec![bola.inbox_id()]) + .await + .unwrap(); + amal_dm.sync(&amal).await.unwrap(); + let members = amal_dm.members().unwrap(); + assert_eq!(members.len(), 2); + + // Bola can message amal + let _ = bola.sync_welcomes().await; + let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_dm: &MlsGroup = bola_groups.first().unwrap(); + bola_dm.send_message(b"test one", &bola).await.unwrap(); + + // Amal sync and reads message + amal_dm.sync(&amal).await.unwrap(); + let messages = amal_dm.find_messages(None, None, None, None, None).unwrap(); + assert_eq!(messages.len(), 2); + let message = messages.last().unwrap(); + assert_eq!(message.decrypted_message_bytes, b"test one"); + + // Amal can not remove bola + let result = amal_dm + .remove_members_by_inbox_id(&amal, vec![bola.inbox_id()]) + .await; + assert!(result.is_err()); + amal_dm.sync(&amal).await.unwrap(); + let members = amal_dm.members().unwrap(); + assert_eq!(members.len(), 2); + + // Neither Amal nor Bola is an admin or super admin + amal_dm.sync(&amal).await.unwrap(); + bola_dm.sync(&bola).await.unwrap(); + let is_amal_admin = amal_dm.is_admin(amal.inbox_id()).unwrap(); + let is_bola_admin = amal_dm.is_admin(bola.inbox_id()).unwrap(); + let is_amal_super_admin = amal_dm.is_super_admin(amal.inbox_id()).unwrap(); + let is_bola_super_admin = amal_dm.is_super_admin(bola.inbox_id()).unwrap(); + assert!(!is_amal_admin); + assert!(!is_bola_admin); + assert!(!is_amal_super_admin); + assert!(!is_bola_super_admin); + } } diff --git a/xmtp_mls/src/groups/validated_commit.rs b/xmtp_mls/src/groups/validated_commit.rs index 6c4f8271a..562f23589 100644 --- a/xmtp_mls/src/groups/validated_commit.rs +++ b/xmtp_mls/src/groups/validated_commit.rs @@ -32,7 +32,7 @@ use crate::{ use super::{ group_membership::{GroupMembership, MembershipDiff}, - group_metadata::{GroupMetadata, GroupMetadataError}, + group_metadata::{DmMembers, GroupMetadata, GroupMetadataError}, group_mutable_metadata::{ find_mutable_metadata_extension, GroupMutableMetadata, GroupMutableMetadataError, }, @@ -210,6 +210,7 @@ pub struct ValidatedCommit { pub removed_inboxes: Vec, pub metadata_changes: MutableMetadataChanges, pub permissions_changed: bool, + pub dm_members: Option, } impl ValidatedCommit { @@ -326,6 +327,7 @@ impl ValidatedCommit { removed_inboxes, metadata_changes, permissions_changed, + dm_members: immutable_metadata.dm_members, }; let policy_set = extract_group_permissions(openmls_group)?; diff --git a/xmtp_proto/src/gen/xmtp.message_contents.rs b/xmtp_proto/src/gen/xmtp.message_contents.rs index 46078b71c..1d3966343 100644 --- a/xmtp_proto/src/gen/xmtp.message_contents.rs +++ b/xmtp_proto/src/gen/xmtp.message_contents.rs @@ -859,16 +859,16 @@ pub mod private_preferences_action { #[derive(Clone, PartialEq, ::prost::Message)] pub struct AllowGroup { /// Add the given group_ids to the allow list - #[prost(bytes="vec", repeated, tag="1")] - pub group_ids: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, + #[prost(string, repeated, tag="1")] + pub group_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, } /// Deny (deny) Group access #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct DenyGroup { /// Add the given group_ids to the deny list - #[prost(bytes="vec", repeated, tag="1")] - pub group_ids: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, + #[prost(string, repeated, tag="1")] + pub group_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Oneof)] @@ -2892,10 +2892,10 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x1a, 0x29, 0x0a, 0x0a, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x67, 0x72, 0x6f, 0x75, + 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x73, 0x1a, 0x28, 0x0a, 0x09, 0x44, 0x65, 0x6e, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x73, 0x42, 0x0e, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x5b, 0x0a, 0x19, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x33, 0x0a, 0x02, 0x76, @@ -2990,25 +2990,25 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x20, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x04, 0x01, 0x12, 0x03, 0x2a, 0x0a, 0x14, 0x0a, 0x3a, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x04, 0x02, 0x00, 0x12, 0x03, 0x2c, 0x04, - 0x21, 0x1a, 0x2b, 0x20, 0x41, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, + 0x22, 0x1a, 0x2b, 0x20, 0x41, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, 0x02, 0x00, 0x04, 0x12, 0x03, 0x2c, 0x04, 0x0c, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, 0x02, 0x00, 0x05, 0x12, 0x03, 0x2c, 0x0d, 0x12, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2c, 0x13, 0x1c, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2c, 0x1f, 0x20, 0x0a, 0x28, + 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, 0x02, 0x00, 0x05, 0x12, 0x03, 0x2c, 0x0d, 0x13, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2c, 0x14, 0x1d, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2c, 0x20, 0x21, 0x0a, 0x28, 0x0a, 0x04, 0x04, 0x00, 0x03, 0x05, 0x12, 0x04, 0x30, 0x02, 0x33, 0x03, 0x1a, 0x1a, 0x20, 0x44, 0x65, 0x6e, 0x79, 0x20, 0x28, 0x64, 0x65, 0x6e, 0x79, 0x29, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x05, 0x01, 0x12, 0x03, 0x30, 0x0a, 0x13, 0x0a, 0x39, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x05, 0x02, 0x00, - 0x12, 0x03, 0x32, 0x04, 0x21, 0x1a, 0x2a, 0x20, 0x41, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x12, 0x03, 0x32, 0x04, 0x22, 0x1a, 0x2a, 0x20, 0x41, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x6e, 0x79, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x05, 0x02, 0x00, 0x04, 0x12, 0x03, 0x32, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x05, 0x02, 0x00, 0x05, 0x12, 0x03, 0x32, 0x0d, - 0x12, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x05, 0x02, 0x00, 0x01, 0x12, 0x03, 0x32, 0x13, - 0x1c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x05, 0x02, 0x00, 0x03, 0x12, 0x03, 0x32, 0x1f, - 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x00, 0x08, 0x00, 0x12, 0x04, 0x35, 0x02, 0x3c, 0x03, 0x0a, + 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x05, 0x02, 0x00, 0x01, 0x12, 0x03, 0x32, 0x14, + 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x05, 0x02, 0x00, 0x03, 0x12, 0x03, 0x32, 0x20, + 0x21, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x00, 0x08, 0x00, 0x12, 0x04, 0x35, 0x02, 0x3c, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x08, 0x00, 0x01, 0x12, 0x03, 0x35, 0x08, 0x14, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x36, 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x36, 0x04, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, diff --git a/xmtp_proto/src/gen/xmtp.message_contents.serde.rs b/xmtp_proto/src/gen/xmtp.message_contents.serde.rs index a28bf3ea2..8df3e631b 100644 --- a/xmtp_proto/src/gen/xmtp.message_contents.serde.rs +++ b/xmtp_proto/src/gen/xmtp.message_contents.serde.rs @@ -4171,7 +4171,7 @@ impl serde::Serialize for private_preferences_action::AllowGroup { } let mut struct_ser = serializer.serialize_struct("xmtp.message_contents.PrivatePreferencesAction.AllowGroup", len)?; if !self.group_ids.is_empty() { - struct_ser.serialize_field("groupIds", &self.group_ids.iter().map(pbjson::private::base64::encode).collect::>())?; + struct_ser.serialize_field("groupIds", &self.group_ids)?; } struct_ser.end() } @@ -4238,10 +4238,7 @@ impl<'de> serde::Deserialize<'de> for private_preferences_action::AllowGroup { if group_ids__.is_some() { return Err(serde::de::Error::duplicate_field("groupIds")); } - group_ids__ = - Some(map_.next_value::>>()? - .into_iter().map(|x| x.0).collect()) - ; + group_ids__ = Some(map_.next_value()?); } } } @@ -4450,7 +4447,7 @@ impl serde::Serialize for private_preferences_action::DenyGroup { } let mut struct_ser = serializer.serialize_struct("xmtp.message_contents.PrivatePreferencesAction.DenyGroup", len)?; if !self.group_ids.is_empty() { - struct_ser.serialize_field("groupIds", &self.group_ids.iter().map(pbjson::private::base64::encode).collect::>())?; + struct_ser.serialize_field("groupIds", &self.group_ids)?; } struct_ser.end() } @@ -4517,10 +4514,7 @@ impl<'de> serde::Deserialize<'de> for private_preferences_action::DenyGroup { if group_ids__.is_some() { return Err(serde::de::Error::duplicate_field("groupIds")); } - group_ids__ = - Some(map_.next_value::>>()? - .into_iter().map(|x| x.0).collect()) - ; + group_ids__ = Some(map_.next_value()?); } } } diff --git a/xmtp_proto/src/gen/xmtp.mls.message_contents.rs b/xmtp_proto/src/gen/xmtp.mls.message_contents.rs index a54015412..5b70dda68 100644 --- a/xmtp_proto/src/gen/xmtp.mls.message_contents.rs +++ b/xmtp_proto/src/gen/xmtp.mls.message_contents.rs @@ -328,6 +328,25 @@ pub struct GroupMetadataV1 { pub creator_account_address: ::prost::alloc::string::String, #[prost(string, tag="3")] pub creator_inbox_id: ::prost::alloc::string::String, + /// Should only be present for CONVERSATION_TYPE_DM + #[prost(message, optional, tag="4")] + pub dm_members: ::core::option::Option, +} +/// Wrapper around an Inbox Id +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Inbox { + #[prost(string, tag="1")] + pub inbox_id: ::prost::alloc::string::String, +} +/// Ordering does not matter here +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DmMembers { + #[prost(message, optional, tag="1")] + pub dm_member_one: ::core::option::Option, + #[prost(message, optional, tag="2")] + pub dm_member_two: ::core::option::Option, } /// Defines the type of conversation #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] @@ -1408,12 +1427,12 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0b, 0x02, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x0b, 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0b, 0x16, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, - 0x12, 0x03, 0x0b, 0x20, 0x21, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xc2, 0x09, + 0x12, 0x03, 0x0b, 0x20, 0x21, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xe5, 0x0e, 0x0a, 0x29, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xcd, 0x01, 0x0a, 0x0f, 0x47, 0x72, 0x6f, 0x75, 0x70, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xa6, 0x02, 0x0a, 0x0f, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x56, 0x31, 0x12, 0x58, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, @@ -1426,758 +1445,801 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x49, - 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x2a, 0x88, 0x01, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x1d, 0x43, - 0x4f, 0x4e, 0x56, 0x45, 0x52, 0x53, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, - 0x0a, 0x17, 0x43, 0x4f, 0x4e, 0x56, 0x45, 0x52, 0x53, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x43, - 0x4f, 0x4e, 0x56, 0x45, 0x52, 0x53, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x44, 0x4d, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x4f, 0x4e, 0x56, 0x45, 0x52, 0x53, - 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x10, - 0x03, 0x42, 0xe7, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, - 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0x42, 0x12, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, - 0x4d, 0xaa, 0x02, 0x18, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x6c, 0x73, 0x2e, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, 0x18, 0x58, - 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xe2, 0x02, 0x24, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, - 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x1a, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x6c, 0x73, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xac, 0x04, 0x0a, 0x06, - 0x12, 0x04, 0x01, 0x00, 0x16, 0x01, 0x0a, 0x24, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, - 0x1a, 0x1a, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x69, 0x6d, 0x6d, 0x75, 0x74, 0x61, 0x62, + 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, 0x48, 0x0a, 0x0a, 0x64, 0x6d, 0x5f, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x44, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, + 0x48, 0x00, 0x52, 0x09, 0x64, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x88, 0x01, 0x01, + 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x64, 0x6d, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, + 0x22, 0x0a, 0x05, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x62, 0x6f, + 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x6e, 0x62, 0x6f, + 0x78, 0x49, 0x64, 0x22, 0x97, 0x01, 0x0a, 0x09, 0x44, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x12, 0x44, 0x0a, 0x0d, 0x64, 0x6d, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6f, + 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, + 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x52, 0x0b, 0x64, 0x6d, 0x4d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x6e, 0x65, 0x12, 0x44, 0x0a, 0x0d, 0x64, 0x6d, 0x5f, 0x6d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x74, 0x77, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x78, + 0x52, 0x0b, 0x64, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x54, 0x77, 0x6f, 0x2a, 0x88, 0x01, + 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x21, 0x0a, 0x1d, 0x43, 0x4f, 0x4e, 0x56, 0x45, 0x52, 0x53, 0x41, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4f, 0x4e, 0x56, 0x45, 0x52, 0x53, + 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, + 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4f, 0x4e, 0x56, 0x45, 0x52, 0x53, 0x41, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4d, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, + 0x43, 0x4f, 0x4e, 0x56, 0x45, 0x52, 0x53, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x10, 0x03, 0x42, 0xe7, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x12, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, + 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x6c, + 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x4d, 0xaa, 0x02, 0x18, 0x58, 0x6d, 0x74, 0x70, 0x2e, + 0x4d, 0x6c, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x73, 0xca, 0x02, 0x18, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xe2, 0x02, + 0x24, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1a, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x6c, + 0x73, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0x4a, 0xb8, 0x07, 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x23, 0x01, 0x0a, 0x24, 0x0a, + 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x1a, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, + 0x69, 0x6d, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x22, 0x0a, 0x08, 0x0a, + 0x01, 0x08, 0x12, 0x03, 0x05, 0x00, 0x47, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x05, + 0x00, 0x47, 0x0a, 0x2f, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x09, 0x00, 0x10, 0x01, 0x1a, 0x23, + 0x20, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x09, 0x08, 0x17, 0x0a, + 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0a, 0x02, 0x29, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x0a, 0x02, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x0a, 0x13, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, + 0x03, 0x12, 0x03, 0x0a, 0x27, 0x28, 0x0a, 0x28, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, + 0x0c, 0x02, 0x25, 0x1a, 0x1b, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, + 0x62, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x73, 0x6f, 0x6f, 0x6e, 0x0a, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x0c, 0x02, 0x08, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x0c, 0x09, 0x20, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x0c, 0x23, 0x24, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, + 0x02, 0x02, 0x12, 0x03, 0x0d, 0x02, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x05, + 0x12, 0x03, 0x0d, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, + 0x0d, 0x09, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x0d, 0x1c, + 0x1d, 0x0a, 0x3e, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x03, 0x12, 0x03, 0x0f, 0x02, 0x24, 0x1a, 0x31, + 0x20, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x65, 0x20, + 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x43, 0x4f, 0x4e, 0x56, + 0x45, 0x52, 0x53, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4d, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x04, 0x12, 0x03, 0x0f, 0x02, 0x0a, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x06, 0x12, 0x03, 0x0f, 0x0b, 0x14, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x0f, 0x15, 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x00, 0x02, 0x03, 0x03, 0x12, 0x03, 0x0f, 0x22, 0x23, 0x0a, 0x2e, 0x0a, 0x02, 0x05, 0x00, 0x12, + 0x04, 0x13, 0x00, 0x18, 0x01, 0x1a, 0x22, 0x20, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x05, 0x00, 0x01, + 0x12, 0x03, 0x13, 0x05, 0x15, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x00, 0x12, 0x03, 0x14, + 0x02, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x14, 0x02, 0x1f, + 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x14, 0x22, 0x23, 0x0a, 0x0b, + 0x0a, 0x04, 0x05, 0x00, 0x02, 0x01, 0x12, 0x03, 0x15, 0x02, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x05, + 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x15, 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, + 0x01, 0x02, 0x12, 0x03, 0x15, 0x1c, 0x1d, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x02, 0x12, + 0x03, 0x16, 0x02, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x16, + 0x02, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x02, 0x12, 0x03, 0x16, 0x19, 0x1a, + 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x03, 0x12, 0x03, 0x17, 0x02, 0x1d, 0x0a, 0x0c, 0x0a, + 0x05, 0x05, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x17, 0x02, 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x05, + 0x00, 0x02, 0x03, 0x02, 0x12, 0x03, 0x17, 0x1b, 0x1c, 0x0a, 0x28, 0x0a, 0x02, 0x04, 0x01, 0x12, + 0x04, 0x1b, 0x00, 0x1d, 0x01, 0x1a, 0x1c, 0x20, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, + 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x20, + 0x49, 0x64, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x1b, 0x08, 0x0d, 0x0a, + 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x1c, 0x02, 0x16, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x01, 0x02, 0x00, 0x05, 0x12, 0x03, 0x1c, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x1c, 0x09, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, + 0x03, 0x12, 0x03, 0x1c, 0x14, 0x15, 0x0a, 0x2b, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x20, 0x00, + 0x23, 0x01, 0x1a, 0x1f, 0x20, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x6f, + 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, + 0x72, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, 0x20, 0x08, 0x11, 0x0a, + 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, 0x21, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x02, 0x02, 0x00, 0x06, 0x12, 0x03, 0x21, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x21, 0x08, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, + 0x03, 0x12, 0x03, 0x21, 0x18, 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, + 0x22, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x06, 0x12, 0x03, 0x22, 0x02, + 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x01, 0x12, 0x03, 0x22, 0x08, 0x15, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, 0x12, 0x03, 0x22, 0x18, 0x19, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0x92, 0x0a, 0x0a, 0x31, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xcb, 0x02, 0x0a, 0x16, 0x47, 0x72, 0x6f, 0x75, 0x70, + 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x56, + 0x31, 0x12, 0x61, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, + 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x56, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x12, 0x41, 0x0a, 0x0a, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x69, + 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, + 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x52, 0x09, 0x61, 0x64, + 0x6d, 0x69, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x4c, 0x0a, 0x10, 0x73, 0x75, 0x70, 0x65, 0x72, + 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x49, 0x6e, + 0x62, 0x6f, 0x78, 0x65, 0x73, 0x52, 0x0e, 0x73, 0x75, 0x70, 0x65, 0x72, 0x41, 0x64, 0x6d, 0x69, + 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0x26, 0x0a, 0x07, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x12, + 0x1b, 0x0a, 0x09, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x42, 0xee, 0x01, 0x0a, + 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x19, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, + 0x58, 0x4d, 0x4d, 0xaa, 0x02, 0x18, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x6c, 0x73, 0x2e, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, + 0x18, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xe2, 0x02, 0x24, 0x58, 0x6d, 0x74, 0x70, + 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0xea, 0x02, 0x1a, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x6c, 0x73, 0x3a, 0x3a, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xd2, 0x04, + 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x16, 0x01, 0x0a, 0x22, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, + 0x00, 0x12, 0x1a, 0x18, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x22, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x05, 0x00, 0x47, - 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x05, 0x00, 0x47, 0x0a, 0x2f, 0x0a, 0x02, 0x04, - 0x00, 0x12, 0x04, 0x09, 0x00, 0x0e, 0x01, 0x1a, 0x23, 0x20, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, - 0x04, 0x00, 0x01, 0x12, 0x03, 0x09, 0x08, 0x17, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, - 0x12, 0x03, 0x0a, 0x02, 0x29, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, - 0x0a, 0x02, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0a, 0x13, - 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x0a, 0x27, 0x28, 0x0a, - 0x28, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x0c, 0x02, 0x25, 0x1a, 0x1b, 0x20, 0x54, - 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x64, 0x20, 0x73, 0x6f, 0x6f, 0x6e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x01, 0x05, 0x12, 0x03, 0x0c, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, - 0x12, 0x03, 0x0c, 0x09, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, - 0x0c, 0x23, 0x24, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x0d, 0x02, 0x1e, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x0d, 0x02, 0x08, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x0d, 0x09, 0x19, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x0d, 0x1c, 0x1d, 0x0a, 0x2e, 0x0a, 0x02, 0x05, 0x00, - 0x12, 0x04, 0x11, 0x00, 0x16, 0x01, 0x1a, 0x22, 0x20, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6e, - 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x05, 0x00, - 0x01, 0x12, 0x03, 0x11, 0x05, 0x15, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x00, 0x12, 0x03, - 0x12, 0x02, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x12, 0x02, - 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x12, 0x22, 0x23, 0x0a, - 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x01, 0x12, 0x03, 0x13, 0x02, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, - 0x05, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x13, 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, - 0x02, 0x01, 0x02, 0x12, 0x03, 0x13, 0x1c, 0x1d, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x02, - 0x12, 0x03, 0x14, 0x02, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, - 0x14, 0x02, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x02, 0x12, 0x03, 0x14, 0x19, - 0x1a, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x03, 0x12, 0x03, 0x15, 0x02, 0x1d, 0x0a, 0x0c, - 0x0a, 0x05, 0x05, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x15, 0x02, 0x18, 0x0a, 0x0c, 0x0a, 0x05, - 0x05, 0x00, 0x02, 0x03, 0x02, 0x12, 0x03, 0x15, 0x1b, 0x1c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, 0x0a, 0x92, 0x0a, 0x0a, 0x31, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, - 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0xcb, 0x02, 0x0a, 0x16, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x75, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x56, 0x31, 0x12, 0x61, - 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x56, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x12, 0x41, 0x0a, 0x0a, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, + 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x05, 0x00, 0x47, 0x0a, 0x30, 0x0a, 0x02, 0x04, + 0x00, 0x12, 0x04, 0x0a, 0x00, 0x11, 0x01, 0x1a, 0x24, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6d, 0x75, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x0a, 0x0a, 0x0a, + 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x0a, 0x08, 0x1e, 0x0a, 0x4a, 0x0a, 0x04, 0x04, 0x00, 0x02, + 0x00, 0x12, 0x03, 0x0c, 0x02, 0x25, 0x1a, 0x3d, 0x20, 0x4d, 0x61, 0x70, 0x20, 0x74, 0x6f, 0x20, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x76, 0x61, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x20, 0x28, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x65, + 0x74, 0x63, 0x2e, 0x29, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, + 0x0c, 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0c, 0x16, + 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x0c, 0x23, 0x24, 0x0a, + 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x0d, 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, 0x0d, 0x02, 0x09, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x01, 0x01, 0x12, 0x03, 0x0d, 0x0a, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, + 0x03, 0x12, 0x03, 0x0d, 0x17, 0x18, 0x0a, 0x64, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, + 0x10, 0x02, 0x1f, 0x1a, 0x57, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x73, 0x20, 0x61, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x73, 0x75, 0x70, + 0x65, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0a, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x73, + 0x75, 0x70, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x61, + 0x64, 0x64, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, + 0x73, 0x75, 0x70, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x02, 0x06, 0x12, 0x03, 0x10, 0x02, 0x09, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x02, 0x01, 0x12, 0x03, 0x10, 0x0a, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, + 0x03, 0x12, 0x03, 0x10, 0x1d, 0x1e, 0x0a, 0x39, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x14, 0x00, + 0x16, 0x01, 0x1a, 0x2d, 0x20, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x61, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, + 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x20, 0x49, 0x64, 0x73, + 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x14, 0x08, 0x0f, 0x0a, 0x0b, 0x0a, + 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x15, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, + 0x02, 0x00, 0x04, 0x12, 0x03, 0x15, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, + 0x05, 0x12, 0x03, 0x15, 0x0b, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, + 0x03, 0x15, 0x12, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x15, + 0x1e, 0x1f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xfb, 0x31, 0x0a, 0x2c, 0x6d, + 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x73, 0x2f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x5d, 0x0a, 0x19, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, + 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x56, 0x31, 0x12, 0x40, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x4c, 0x69, 0x73, 0x74, 0x12, 0x4c, 0x0a, 0x10, 0x73, 0x75, 0x70, 0x65, 0x72, 0x5f, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x73, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x65, 0x74, 0x52, 0x08, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0xdf, 0x05, 0x0a, 0x09, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x53, 0x65, 0x74, 0x12, 0x57, 0x0a, 0x11, 0x61, 0x64, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x78, - 0x65, 0x73, 0x52, 0x0e, 0x73, 0x75, 0x70, 0x65, 0x72, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4c, 0x69, - 0x73, 0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x22, 0x26, 0x0a, 0x07, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, - 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x42, 0xee, 0x01, 0x0a, 0x1d, 0x63, 0x6f, - 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x19, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x4d, - 0xaa, 0x02, 0x18, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x6c, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, 0x18, 0x58, 0x6d, - 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xe2, 0x02, 0x24, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, - 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1a, - 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x6c, 0x73, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xd2, 0x04, 0x0a, 0x06, 0x12, - 0x04, 0x01, 0x00, 0x16, 0x01, 0x0a, 0x22, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, - 0x18, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, - 0x03, 0x00, 0x22, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x05, 0x00, 0x47, 0x0a, 0x09, 0x0a, - 0x02, 0x08, 0x0b, 0x12, 0x03, 0x05, 0x00, 0x47, 0x0a, 0x30, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, - 0x0a, 0x00, 0x11, 0x01, 0x1a, 0x24, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x66, - 0x6f, 0x72, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, - 0x01, 0x12, 0x03, 0x0a, 0x08, 0x1e, 0x0a, 0x4a, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, - 0x0c, 0x02, 0x25, 0x1a, 0x3d, 0x20, 0x4d, 0x61, 0x70, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x20, 0x76, 0x61, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x20, 0x28, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x2e, - 0x29, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x0c, 0x02, 0x15, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0c, 0x16, 0x20, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x0c, 0x23, 0x24, 0x0a, 0x0b, 0x0a, 0x04, - 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x0d, 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x01, 0x06, 0x12, 0x03, 0x0d, 0x02, 0x09, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, - 0x12, 0x03, 0x0d, 0x0a, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, - 0x0d, 0x17, 0x18, 0x0a, 0x64, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x10, 0x02, 0x1f, - 0x1a, 0x57, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x73, 0x20, 0x61, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x73, 0x75, 0x70, 0x65, 0x72, 0x5f, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0a, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x73, 0x75, 0x70, 0x65, - 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x2f, - 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x75, 0x70, - 0x65, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x02, 0x06, 0x12, 0x03, 0x10, 0x02, 0x09, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, - 0x12, 0x03, 0x10, 0x0a, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, - 0x10, 0x1d, 0x1e, 0x0a, 0x39, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x14, 0x00, 0x16, 0x01, 0x1a, - 0x2d, 0x20, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, - 0x20, 0x61, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x70, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x20, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x20, 0x49, 0x64, 0x73, 0x0a, 0x0a, 0x0a, - 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x14, 0x08, 0x0f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, - 0x02, 0x00, 0x12, 0x03, 0x15, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x04, - 0x12, 0x03, 0x15, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x05, 0x12, 0x03, - 0x15, 0x0b, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x15, 0x12, - 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x15, 0x1e, 0x1f, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xfb, 0x31, 0x0a, 0x2c, 0x6d, 0x6c, 0x73, 0x2f, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x2f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, - 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0x5d, 0x0a, 0x19, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x75, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x56, 0x31, - 0x12, 0x40, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x65, 0x74, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, - 0x65, 0x73, 0x22, 0xdf, 0x05, 0x0a, 0x09, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x65, 0x74, - 0x12, 0x57, 0x0a, 0x11, 0x61, 0x64, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x6d, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0f, 0x61, 0x64, 0x64, + 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x5d, 0x0a, 0x14, + 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, + 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x12, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x74, 0x0a, 0x16, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, - 0x69, 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0f, 0x61, 0x64, 0x64, 0x4d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x5d, 0x0a, 0x14, 0x72, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, - 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x52, 0x12, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x74, 0x0a, 0x16, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x65, 0x74, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x5c, - 0x0a, 0x10, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0e, 0x61, 0x64, - 0x64, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x62, 0x0a, 0x13, - 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x11, 0x72, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x12, 0x6e, 0x0a, 0x19, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, - 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x17, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x1a, 0x72, 0x0a, 0x19, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x65, + 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x12, 0x5c, 0x0a, 0x10, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, + 0x0e, 0x61, 0x64, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, + 0x62, 0x0a, 0x13, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x78, + 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x52, 0x11, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x12, 0x6e, 0x0a, 0x19, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, + 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, + 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x17, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x1a, 0x72, 0x0a, 0x19, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x29, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8a, 0x05, 0x0a, 0x10, 0x4d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x4c, 0x0a, 0x04, + 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, + 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x48, 0x00, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0d, 0x61, 0x6e, + 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x38, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, + 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0c, 0x61, + 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5f, 0x0a, 0x0d, 0x61, + 0x6e, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x41, 0x6e, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0c, + 0x61, 0x6e, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x57, 0x0a, 0x0c, + 0x41, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x08, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8a, 0x05, 0x0a, 0x10, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, - 0x68, 0x69, 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x4c, 0x0a, 0x04, 0x62, 0x61, 0x73, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x69, 0x65, 0x73, 0x1a, 0x57, 0x0a, 0x0c, 0x41, 0x6e, 0x79, 0x43, 0x6f, 0x6e, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x48, - 0x00, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0d, 0x61, 0x6e, 0x64, 0x5f, 0x63, - 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, - 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x6e, 0x64, 0x43, - 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0c, 0x61, 0x6e, 0x64, 0x43, - 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5f, 0x0a, 0x0d, 0x61, 0x6e, 0x79, 0x5f, - 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x38, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x6e, 0x79, + 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0xab, + 0x01, 0x0a, 0x0a, 0x42, 0x61, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1b, 0x0a, + 0x17, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x42, 0x41, + 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x10, + 0x01, 0x12, 0x14, 0x0a, 0x10, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, + 0x5f, 0x44, 0x45, 0x4e, 0x59, 0x10, 0x02, 0x12, 0x2d, 0x0a, 0x29, 0x42, 0x41, 0x53, 0x45, 0x5f, + 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x46, 0x5f, + 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x53, 0x55, 0x50, 0x45, 0x52, 0x5f, 0x41, + 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x03, 0x12, 0x24, 0x0a, 0x20, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, + 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x46, 0x5f, 0x53, + 0x55, 0x50, 0x45, 0x52, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x04, 0x42, 0x06, 0x0a, 0x04, + 0x6b, 0x69, 0x6e, 0x64, 0x22, 0xac, 0x05, 0x0a, 0x0e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x52, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, + 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x61, 0x73, 0x65, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x48, 0x00, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0d, 0x61, + 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x6e, + 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0c, 0x61, 0x6e, + 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5d, 0x0a, 0x0d, 0x61, 0x6e, + 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x36, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x6e, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0c, 0x61, 0x6e, 0x79, - 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x57, 0x0a, 0x0c, 0x41, 0x6e, 0x64, - 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x08, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x6d, + 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x55, 0x0a, 0x0c, 0x41, 0x6e, 0x64, + 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x08, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, - 0x69, 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, - 0x65, 0x73, 0x1a, 0x57, 0x0a, 0x0c, 0x41, 0x6e, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0xab, 0x01, 0x0a, 0x0a, - 0x42, 0x61, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1b, 0x0a, 0x17, 0x42, 0x41, - 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x42, 0x41, 0x53, 0x45, 0x5f, - 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x10, 0x01, 0x12, 0x14, - 0x0a, 0x10, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x44, 0x45, - 0x4e, 0x59, 0x10, 0x02, 0x12, 0x2d, 0x0a, 0x29, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, - 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x46, 0x5f, 0x41, 0x44, 0x4d, - 0x49, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x53, 0x55, 0x50, 0x45, 0x52, 0x5f, 0x41, 0x44, 0x4d, 0x49, - 0x4e, 0x10, 0x03, 0x12, 0x24, 0x0a, 0x20, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, - 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x46, 0x5f, 0x53, 0x55, 0x50, 0x45, - 0x52, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x04, 0x42, 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, - 0x64, 0x22, 0xac, 0x05, 0x0a, 0x0e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x12, 0x52, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x3c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, + 0x1a, 0x55, 0x0a, 0x0c, 0x41, 0x6e, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x45, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x61, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x48, 0x00, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0d, 0x61, 0x6e, 0x64, 0x5f, - 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x36, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x6e, 0x64, 0x43, 0x6f, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0xd1, 0x01, 0x0a, 0x12, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x42, 0x61, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x24, + 0x0a, 0x20, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x42, 0x41, 0x53, 0x45, 0x5f, + 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, + 0x5f, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, + 0x4f, 0x57, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, + 0x5f, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x44, 0x45, 0x4e, + 0x59, 0x10, 0x02, 0x12, 0x27, 0x0a, 0x23, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, + 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, + 0x57, 0x5f, 0x49, 0x46, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x03, 0x12, 0x2d, 0x0a, 0x29, + 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, + 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x46, 0x5f, 0x53, 0x55, + 0x50, 0x45, 0x52, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x04, 0x42, 0x06, 0x0a, 0x04, 0x6b, + 0x69, 0x6e, 0x64, 0x22, 0xd4, 0x05, 0x0a, 0x17, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, + 0x5e, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x48, 0x2e, + 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x61, 0x73, + 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x48, 0x00, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, + 0x66, 0x0a, 0x0d, 0x61, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, + 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0c, 0x61, 0x6e, 0x64, 0x43, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5d, 0x0a, 0x0d, 0x61, 0x6e, 0x79, 0x5f, 0x63, - 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, - 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x6e, 0x79, 0x43, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0c, 0x61, 0x6e, 0x79, 0x43, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x55, 0x0a, 0x0c, 0x41, 0x6e, 0x64, 0x43, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x1a, 0x55, 0x0a, - 0x0c, 0x41, 0x6e, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, - 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x29, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x69, 0x65, 0x73, 0x22, 0xd1, 0x01, 0x0a, 0x12, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x42, 0x61, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x24, 0x0a, 0x20, 0x4d, - 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, - 0x49, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x42, 0x41, - 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x10, - 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x42, 0x41, - 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x44, 0x45, 0x4e, 0x59, 0x10, 0x02, - 0x12, 0x27, 0x0a, 0x23, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x42, 0x41, 0x53, - 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x49, - 0x46, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x03, 0x12, 0x2d, 0x0a, 0x29, 0x4d, 0x45, 0x54, - 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, - 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x46, 0x5f, 0x53, 0x55, 0x50, 0x45, 0x52, - 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x04, 0x42, 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, - 0x22, 0xd4, 0x05, 0x0a, 0x17, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x5e, 0x0a, 0x04, - 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x48, 0x2e, 0x78, 0x6d, 0x74, - 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x61, 0x73, 0x65, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x48, 0x00, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x0d, - 0x61, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, - 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0c, 0x61, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x66, 0x0a, 0x0d, 0x61, 0x6e, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x78, 0x6d, - 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x41, 0x6e, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0c, - 0x61, 0x6e, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x5e, 0x0a, 0x0c, - 0x41, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x08, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, - 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x1a, 0x5e, 0x0a, 0x0c, - 0x41, 0x6e, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x08, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, + 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x66, 0x0a, 0x0d, 0x61, 0x6e, 0x79, 0x5f, 0x63, + 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0xc0, 0x01, 0x0a, - 0x15, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x61, 0x73, 0x65, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x27, 0x0a, 0x23, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, - 0x53, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, - 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x20, 0x0a, 0x1c, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x42, - 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x44, 0x45, 0x4e, 0x59, 0x10, - 0x01, 0x12, 0x2a, 0x0a, 0x26, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x53, - 0x5f, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, - 0x4f, 0x57, 0x5f, 0x49, 0x46, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x30, 0x0a, - 0x2c, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x42, 0x41, 0x53, - 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x49, - 0x46, 0x5f, 0x53, 0x55, 0x50, 0x45, 0x52, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x03, 0x42, - 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x42, 0xea, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x15, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, - 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, - 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x4d, 0xaa, 0x02, 0x18, 0x58, 0x6d, 0x74, - 0x70, 0x2e, 0x4d, 0x6c, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, 0x18, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, - 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0xe2, 0x02, 0x24, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1a, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, - 0x4d, 0x6c, 0x73, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xe6, 0x18, 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x68, 0x01, 0x0a, - 0x2e, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x24, 0x20, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x20, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x0a, - 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x22, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, - 0x05, 0x00, 0x47, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x05, 0x00, 0x47, 0x0a, 0x30, - 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x09, 0x00, 0x0b, 0x01, 0x1a, 0x24, 0x20, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6d, - 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x0a, - 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x09, 0x08, 0x21, 0x0a, 0x0b, 0x0a, 0x04, - 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0a, 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x00, 0x06, 0x12, 0x03, 0x0a, 0x02, 0x0b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, - 0x12, 0x03, 0x0a, 0x0c, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, - 0x0a, 0x17, 0x18, 0x0a, 0x37, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x0e, 0x00, 0x15, 0x01, 0x1a, - 0x2b, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, 0x6f, 0x76, 0x65, 0x72, - 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, - 0x04, 0x01, 0x01, 0x12, 0x03, 0x0e, 0x08, 0x11, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, - 0x12, 0x03, 0x0f, 0x02, 0x29, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, - 0x0f, 0x02, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0f, 0x13, - 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x0f, 0x27, 0x28, 0x0a, - 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, 0x03, 0x10, 0x02, 0x2c, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x01, 0x02, 0x01, 0x06, 0x12, 0x03, 0x10, 0x02, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, - 0x02, 0x01, 0x01, 0x12, 0x03, 0x10, 0x13, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, - 0x03, 0x12, 0x03, 0x10, 0x2a, 0x2b, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x02, 0x12, 0x03, - 0x11, 0x02, 0x39, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x06, 0x12, 0x03, 0x11, 0x02, - 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x01, 0x12, 0x03, 0x11, 0x1e, 0x34, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x03, 0x12, 0x03, 0x11, 0x37, 0x38, 0x0a, 0x0b, 0x0a, - 0x04, 0x04, 0x01, 0x02, 0x03, 0x12, 0x03, 0x12, 0x02, 0x2f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, - 0x02, 0x03, 0x06, 0x12, 0x03, 0x12, 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, - 0x01, 0x12, 0x03, 0x12, 0x1a, 0x2a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x03, 0x12, - 0x03, 0x12, 0x2d, 0x2e, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x04, 0x12, 0x03, 0x13, 0x02, - 0x32, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, 0x06, 0x12, 0x03, 0x13, 0x02, 0x19, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, 0x01, 0x12, 0x03, 0x13, 0x1a, 0x2d, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x01, 0x02, 0x04, 0x03, 0x12, 0x03, 0x13, 0x30, 0x31, 0x0a, 0x0b, 0x0a, 0x04, 0x04, - 0x01, 0x02, 0x05, 0x12, 0x03, 0x14, 0x02, 0x38, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x05, - 0x06, 0x12, 0x03, 0x14, 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x05, 0x01, 0x12, - 0x03, 0x14, 0x1a, 0x33, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x05, 0x03, 0x12, 0x03, 0x14, - 0x36, 0x37, 0x0a, 0x4c, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x18, 0x00, 0x31, 0x01, 0x1a, 0x40, - 0x20, 0x41, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, - 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2f, 0x72, 0x65, - 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x20, 0x6f, - 0x72, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, - 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, 0x18, 0x08, 0x18, 0x0a, 0x1b, 0x0a, 0x04, - 0x04, 0x02, 0x04, 0x00, 0x12, 0x04, 0x1a, 0x02, 0x20, 0x03, 0x1a, 0x0d, 0x20, 0x42, 0x61, 0x73, - 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x04, - 0x00, 0x01, 0x12, 0x03, 0x1a, 0x07, 0x11, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x04, 0x00, 0x02, - 0x00, 0x12, 0x03, 0x1b, 0x04, 0x20, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, 0x00, - 0x01, 0x12, 0x03, 0x1b, 0x04, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, 0x00, - 0x02, 0x12, 0x03, 0x1b, 0x1e, 0x1f, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x04, 0x00, 0x02, 0x01, - 0x12, 0x03, 0x1c, 0x04, 0x1a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, 0x01, 0x01, - 0x12, 0x03, 0x1c, 0x04, 0x15, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, 0x01, 0x02, - 0x12, 0x03, 0x1c, 0x18, 0x19, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x04, 0x00, 0x02, 0x02, 0x12, - 0x03, 0x1d, 0x04, 0x19, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, - 0x03, 0x1d, 0x04, 0x14, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, 0x02, 0x02, 0x12, - 0x03, 0x1d, 0x17, 0x18, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x04, 0x00, 0x02, 0x03, 0x12, 0x03, - 0x1e, 0x04, 0x32, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, - 0x1e, 0x04, 0x2d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, 0x03, 0x02, 0x12, 0x03, - 0x1e, 0x30, 0x31, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x04, 0x00, 0x02, 0x04, 0x12, 0x03, 0x1f, - 0x04, 0x29, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, 0x04, 0x01, 0x12, 0x03, 0x1f, - 0x04, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, 0x04, 0x02, 0x12, 0x03, 0x1f, - 0x27, 0x28, 0x0a, 0x44, 0x0a, 0x04, 0x04, 0x02, 0x03, 0x00, 0x12, 0x04, 0x23, 0x02, 0x25, 0x03, - 0x1a, 0x36, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, - 0x70, 0x6c, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x20, 0x41, 0x6c, - 0x6c, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x20, - 0x74, 0x6f, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x03, 0x00, - 0x01, 0x12, 0x03, 0x23, 0x0a, 0x16, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, - 0x12, 0x03, 0x24, 0x04, 0x2b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x04, - 0x12, 0x03, 0x24, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x06, - 0x12, 0x03, 0x24, 0x0d, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x01, - 0x12, 0x03, 0x24, 0x1e, 0x26, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x03, - 0x12, 0x03, 0x24, 0x29, 0x2a, 0x0a, 0x44, 0x0a, 0x04, 0x04, 0x02, 0x03, 0x01, 0x12, 0x04, 0x28, - 0x02, 0x2a, 0x03, 0x1a, 0x36, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x20, 0x6d, 0x75, + 0x63, 0x79, 0x2e, 0x41, 0x6e, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, + 0x00, 0x52, 0x0c, 0x61, 0x6e, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, + 0x5e, 0x0a, 0x0c, 0x41, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x4e, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x32, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x65, + 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x1a, + 0x5e, 0x0a, 0x0c, 0x41, 0x6e, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x4e, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x32, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x65, + 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, + 0xc0, 0x01, 0x0a, 0x15, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x42, + 0x61, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x27, 0x0a, 0x23, 0x50, 0x45, 0x52, + 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, + 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x20, 0x0a, 0x1c, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, + 0x53, 0x5f, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x44, 0x45, + 0x4e, 0x59, 0x10, 0x01, 0x12, 0x2a, 0x0a, 0x26, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, + 0x4f, 0x4e, 0x53, 0x5f, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, + 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x46, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x02, + 0x12, 0x30, 0x0a, 0x2c, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x53, 0x5f, + 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, + 0x57, 0x5f, 0x49, 0x46, 0x5f, 0x53, 0x55, 0x50, 0x45, 0x52, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, + 0x10, 0x03, 0x42, 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x42, 0xea, 0x01, 0x0a, 0x1d, 0x63, + 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x15, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, + 0x67, 0x6f, 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x4d, 0xaa, 0x02, 0x18, + 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x6c, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, 0x18, 0x58, 0x6d, 0x74, 0x70, 0x5c, + 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x73, 0xe2, 0x02, 0x24, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, + 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1a, 0x58, 0x6d, 0x74, + 0x70, 0x3a, 0x3a, 0x4d, 0x6c, 0x73, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xe6, 0x18, 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, + 0x68, 0x01, 0x0a, 0x2e, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x24, 0x20, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x70, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x22, 0x0a, 0x08, 0x0a, 0x01, + 0x08, 0x12, 0x03, 0x05, 0x00, 0x47, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x05, 0x00, + 0x47, 0x0a, 0x30, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x09, 0x00, 0x0b, 0x01, 0x1a, 0x24, 0x20, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x20, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x09, 0x08, 0x21, 0x0a, + 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0a, 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x0a, 0x02, 0x0b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x0a, 0x0c, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, + 0x03, 0x12, 0x03, 0x0a, 0x17, 0x18, 0x0a, 0x37, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x0e, 0x00, + 0x15, 0x01, 0x1a, 0x2b, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, 0x6f, + 0x76, 0x65, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x0a, 0x0a, + 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x0e, 0x08, 0x11, 0x0a, 0x0b, 0x0a, 0x04, 0x04, + 0x01, 0x02, 0x00, 0x12, 0x03, 0x0f, 0x02, 0x29, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, + 0x06, 0x12, 0x03, 0x0f, 0x02, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, + 0x03, 0x0f, 0x13, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x0f, + 0x27, 0x28, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, 0x03, 0x10, 0x02, 0x2c, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x06, 0x12, 0x03, 0x10, 0x02, 0x12, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, 0x10, 0x13, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x10, 0x2a, 0x2b, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, + 0x02, 0x12, 0x03, 0x11, 0x02, 0x39, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x06, 0x12, + 0x03, 0x11, 0x02, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x01, 0x12, 0x03, 0x11, + 0x1e, 0x34, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x03, 0x12, 0x03, 0x11, 0x37, 0x38, + 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x03, 0x12, 0x03, 0x12, 0x02, 0x2f, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x01, 0x02, 0x03, 0x06, 0x12, 0x03, 0x12, 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x01, 0x02, 0x03, 0x01, 0x12, 0x03, 0x12, 0x1a, 0x2a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, + 0x03, 0x03, 0x12, 0x03, 0x12, 0x2d, 0x2e, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x04, 0x12, + 0x03, 0x13, 0x02, 0x32, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, 0x06, 0x12, 0x03, 0x13, + 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, 0x01, 0x12, 0x03, 0x13, 0x1a, 0x2d, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, 0x03, 0x12, 0x03, 0x13, 0x30, 0x31, 0x0a, 0x0b, + 0x0a, 0x04, 0x04, 0x01, 0x02, 0x05, 0x12, 0x03, 0x14, 0x02, 0x38, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x01, 0x02, 0x05, 0x06, 0x12, 0x03, 0x14, 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, + 0x05, 0x01, 0x12, 0x03, 0x14, 0x1a, 0x33, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x05, 0x03, + 0x12, 0x03, 0x14, 0x36, 0x37, 0x0a, 0x4c, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x18, 0x00, 0x31, + 0x01, 0x1a, 0x40, 0x20, 0x41, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x20, 0x74, 0x68, 0x61, + 0x74, 0x20, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, + 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x20, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, 0x18, 0x08, 0x18, 0x0a, + 0x1b, 0x0a, 0x04, 0x04, 0x02, 0x04, 0x00, 0x12, 0x04, 0x1a, 0x02, 0x20, 0x03, 0x1a, 0x0d, 0x20, + 0x42, 0x61, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x02, 0x04, 0x00, 0x01, 0x12, 0x03, 0x1a, 0x07, 0x11, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, + 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x1b, 0x04, 0x20, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, + 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x1b, 0x04, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, + 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x1b, 0x1e, 0x1f, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x04, + 0x00, 0x02, 0x01, 0x12, 0x03, 0x1c, 0x04, 0x1a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, + 0x02, 0x01, 0x01, 0x12, 0x03, 0x1c, 0x04, 0x15, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, + 0x02, 0x01, 0x02, 0x12, 0x03, 0x1c, 0x18, 0x19, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x04, 0x00, + 0x02, 0x02, 0x12, 0x03, 0x1d, 0x04, 0x19, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, + 0x02, 0x01, 0x12, 0x03, 0x1d, 0x04, 0x14, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, + 0x02, 0x02, 0x12, 0x03, 0x1d, 0x17, 0x18, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x04, 0x00, 0x02, + 0x03, 0x12, 0x03, 0x1e, 0x04, 0x32, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, 0x03, + 0x01, 0x12, 0x03, 0x1e, 0x04, 0x2d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, 0x03, + 0x02, 0x12, 0x03, 0x1e, 0x30, 0x31, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x04, 0x00, 0x02, 0x04, + 0x12, 0x03, 0x1f, 0x04, 0x29, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, 0x04, 0x01, + 0x12, 0x03, 0x1f, 0x04, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x04, 0x00, 0x02, 0x04, 0x02, + 0x12, 0x03, 0x1f, 0x27, 0x28, 0x0a, 0x44, 0x0a, 0x04, 0x04, 0x02, 0x03, 0x00, 0x12, 0x04, 0x23, + 0x02, 0x25, 0x03, 0x1a, 0x36, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, - 0x20, 0x41, 0x6e, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, + 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x02, 0x03, 0x01, 0x01, 0x12, 0x03, 0x28, 0x0a, 0x16, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, - 0x01, 0x02, 0x00, 0x12, 0x03, 0x29, 0x04, 0x2b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, - 0x02, 0x00, 0x04, 0x12, 0x03, 0x29, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, - 0x02, 0x00, 0x06, 0x12, 0x03, 0x29, 0x0d, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, - 0x02, 0x00, 0x01, 0x12, 0x03, 0x29, 0x1e, 0x26, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, - 0x02, 0x00, 0x03, 0x12, 0x03, 0x29, 0x29, 0x2a, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x02, 0x08, 0x00, - 0x12, 0x04, 0x2c, 0x02, 0x30, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x08, 0x00, 0x01, 0x12, - 0x03, 0x2c, 0x08, 0x0c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, 0x2d, 0x04, - 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x06, 0x12, 0x03, 0x2d, 0x04, 0x0e, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2d, 0x0f, 0x13, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2d, 0x16, 0x17, 0x0a, 0x0b, 0x0a, 0x04, 0x04, - 0x02, 0x02, 0x01, 0x12, 0x03, 0x2e, 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, - 0x06, 0x12, 0x03, 0x2e, 0x04, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x01, 0x12, - 0x03, 0x2e, 0x11, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, 0x12, 0x03, 0x2e, - 0x21, 0x22, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x02, 0x12, 0x03, 0x2f, 0x04, 0x23, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x06, 0x12, 0x03, 0x2f, 0x04, 0x10, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x02, 0x02, 0x02, 0x01, 0x12, 0x03, 0x2f, 0x11, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x02, 0x02, 0x02, 0x03, 0x12, 0x03, 0x2f, 0x21, 0x22, 0x0a, 0x35, 0x0a, 0x02, 0x04, 0x03, 0x12, - 0x04, 0x34, 0x00, 0x4d, 0x01, 0x1a, 0x29, 0x20, 0x41, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x73, 0x20, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x0a, - 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x34, 0x08, 0x16, 0x0a, 0x1b, 0x0a, 0x04, - 0x04, 0x03, 0x04, 0x00, 0x12, 0x04, 0x36, 0x02, 0x3c, 0x03, 0x1a, 0x0d, 0x20, 0x42, 0x61, 0x73, - 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x04, - 0x00, 0x01, 0x12, 0x03, 0x36, 0x07, 0x19, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x04, 0x00, 0x02, - 0x00, 0x12, 0x03, 0x37, 0x04, 0x29, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, 0x00, - 0x01, 0x12, 0x03, 0x37, 0x04, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, 0x00, - 0x02, 0x12, 0x03, 0x37, 0x27, 0x28, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x04, 0x00, 0x02, 0x01, - 0x12, 0x03, 0x38, 0x04, 0x23, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, 0x01, 0x01, - 0x12, 0x03, 0x38, 0x04, 0x1e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, 0x01, 0x02, - 0x12, 0x03, 0x38, 0x21, 0x22, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x04, 0x00, 0x02, 0x02, 0x12, - 0x03, 0x39, 0x04, 0x22, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, - 0x03, 0x39, 0x04, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, 0x02, 0x02, 0x12, - 0x03, 0x39, 0x20, 0x21, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x04, 0x00, 0x02, 0x03, 0x12, 0x03, - 0x3a, 0x04, 0x2c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, - 0x3a, 0x04, 0x27, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, 0x03, 0x02, 0x12, 0x03, - 0x3a, 0x2a, 0x2b, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x04, 0x00, 0x02, 0x04, 0x12, 0x03, 0x3b, - 0x04, 0x32, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, 0x04, 0x01, 0x12, 0x03, 0x3b, - 0x04, 0x2d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, 0x04, 0x02, 0x12, 0x03, 0x3b, - 0x30, 0x31, 0x0a, 0x44, 0x0a, 0x04, 0x04, 0x03, 0x03, 0x00, 0x12, 0x04, 0x3f, 0x02, 0x41, 0x03, - 0x1a, 0x36, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, - 0x70, 0x6c, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x20, 0x41, 0x6c, - 0x6c, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x20, - 0x74, 0x6f, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x03, 0x00, - 0x01, 0x12, 0x03, 0x3f, 0x0a, 0x16, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, - 0x12, 0x03, 0x40, 0x04, 0x29, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x04, - 0x12, 0x03, 0x40, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x06, - 0x12, 0x03, 0x40, 0x0d, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x01, - 0x12, 0x03, 0x40, 0x1c, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x03, - 0x12, 0x03, 0x40, 0x27, 0x28, 0x0a, 0x44, 0x0a, 0x04, 0x04, 0x03, 0x03, 0x01, 0x12, 0x04, 0x44, - 0x02, 0x46, 0x03, 0x1a, 0x36, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x20, 0x6d, 0x75, + 0x02, 0x03, 0x00, 0x01, 0x12, 0x03, 0x23, 0x0a, 0x16, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, + 0x00, 0x02, 0x00, 0x12, 0x03, 0x24, 0x04, 0x2b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, + 0x02, 0x00, 0x04, 0x12, 0x03, 0x24, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, + 0x02, 0x00, 0x06, 0x12, 0x03, 0x24, 0x0d, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x24, 0x1e, 0x26, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, + 0x02, 0x00, 0x03, 0x12, 0x03, 0x24, 0x29, 0x2a, 0x0a, 0x44, 0x0a, 0x04, 0x04, 0x02, 0x03, 0x01, + 0x12, 0x04, 0x28, 0x02, 0x2a, 0x03, 0x1a, 0x36, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, + 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, + 0x65, 0x73, 0x2e, 0x20, 0x41, 0x6e, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x65, 0x76, 0x61, + 0x6c, 0x75, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x02, 0x03, 0x01, 0x01, 0x12, 0x03, 0x28, 0x0a, 0x16, 0x0a, 0x0d, 0x0a, 0x06, + 0x04, 0x02, 0x03, 0x01, 0x02, 0x00, 0x12, 0x03, 0x29, 0x04, 0x2b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x02, 0x03, 0x01, 0x02, 0x00, 0x04, 0x12, 0x03, 0x29, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x02, 0x03, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, 0x29, 0x0d, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x02, 0x03, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x29, 0x1e, 0x26, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x02, 0x03, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x29, 0x29, 0x2a, 0x0a, 0x0c, 0x0a, 0x04, 0x04, + 0x02, 0x08, 0x00, 0x12, 0x04, 0x2c, 0x02, 0x30, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x08, + 0x00, 0x01, 0x12, 0x03, 0x2c, 0x08, 0x0c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, + 0x03, 0x2d, 0x04, 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x06, 0x12, 0x03, 0x2d, + 0x04, 0x0e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2d, 0x0f, 0x13, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2d, 0x16, 0x17, 0x0a, 0x0b, + 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, 0x2e, 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x02, 0x02, 0x01, 0x06, 0x12, 0x03, 0x2e, 0x04, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, + 0x01, 0x01, 0x12, 0x03, 0x2e, 0x11, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, + 0x12, 0x03, 0x2e, 0x21, 0x22, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x02, 0x12, 0x03, 0x2f, + 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x06, 0x12, 0x03, 0x2f, 0x04, 0x10, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x01, 0x12, 0x03, 0x2f, 0x11, 0x1e, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x03, 0x12, 0x03, 0x2f, 0x21, 0x22, 0x0a, 0x35, 0x0a, 0x02, + 0x04, 0x03, 0x12, 0x04, 0x34, 0x00, 0x4d, 0x01, 0x1a, 0x29, 0x20, 0x41, 0x20, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x73, + 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x34, 0x08, 0x16, 0x0a, + 0x1b, 0x0a, 0x04, 0x04, 0x03, 0x04, 0x00, 0x12, 0x04, 0x36, 0x02, 0x3c, 0x03, 0x1a, 0x0d, 0x20, + 0x42, 0x61, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x36, 0x07, 0x19, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, + 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x37, 0x04, 0x29, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, + 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x37, 0x04, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, + 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x37, 0x27, 0x28, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x04, + 0x00, 0x02, 0x01, 0x12, 0x03, 0x38, 0x04, 0x23, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, + 0x02, 0x01, 0x01, 0x12, 0x03, 0x38, 0x04, 0x1e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, + 0x02, 0x01, 0x02, 0x12, 0x03, 0x38, 0x21, 0x22, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x04, 0x00, + 0x02, 0x02, 0x12, 0x03, 0x39, 0x04, 0x22, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, + 0x02, 0x01, 0x12, 0x03, 0x39, 0x04, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, + 0x02, 0x02, 0x12, 0x03, 0x39, 0x20, 0x21, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x04, 0x00, 0x02, + 0x03, 0x12, 0x03, 0x3a, 0x04, 0x2c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, 0x03, + 0x01, 0x12, 0x03, 0x3a, 0x04, 0x27, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, 0x03, + 0x02, 0x12, 0x03, 0x3a, 0x2a, 0x2b, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x04, 0x00, 0x02, 0x04, + 0x12, 0x03, 0x3b, 0x04, 0x32, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, 0x04, 0x01, + 0x12, 0x03, 0x3b, 0x04, 0x2d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x04, 0x00, 0x02, 0x04, 0x02, + 0x12, 0x03, 0x3b, 0x30, 0x31, 0x0a, 0x44, 0x0a, 0x04, 0x04, 0x03, 0x03, 0x00, 0x12, 0x04, 0x3f, + 0x02, 0x41, 0x03, 0x1a, 0x36, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, - 0x20, 0x41, 0x6e, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, + 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x03, 0x03, 0x01, 0x01, 0x12, 0x03, 0x44, 0x0a, 0x16, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, - 0x01, 0x02, 0x00, 0x12, 0x03, 0x45, 0x04, 0x29, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x01, - 0x02, 0x00, 0x04, 0x12, 0x03, 0x45, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x01, - 0x02, 0x00, 0x06, 0x12, 0x03, 0x45, 0x0d, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x01, - 0x02, 0x00, 0x01, 0x12, 0x03, 0x45, 0x1c, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x01, - 0x02, 0x00, 0x03, 0x12, 0x03, 0x45, 0x27, 0x28, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x03, 0x08, 0x00, - 0x12, 0x04, 0x48, 0x02, 0x4c, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x08, 0x00, 0x01, 0x12, - 0x03, 0x48, 0x08, 0x0c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x00, 0x12, 0x03, 0x49, 0x04, - 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x06, 0x12, 0x03, 0x49, 0x04, 0x16, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, 0x49, 0x17, 0x1b, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x49, 0x1e, 0x1f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, - 0x03, 0x02, 0x01, 0x12, 0x03, 0x4a, 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, - 0x06, 0x12, 0x03, 0x4a, 0x04, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x12, - 0x03, 0x4a, 0x11, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x03, 0x12, 0x03, 0x4a, - 0x21, 0x22, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x02, 0x12, 0x03, 0x4b, 0x04, 0x23, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x06, 0x12, 0x03, 0x4b, 0x04, 0x10, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x03, 0x02, 0x02, 0x01, 0x12, 0x03, 0x4b, 0x11, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x03, 0x02, 0x02, 0x03, 0x12, 0x03, 0x4b, 0x21, 0x22, 0x0a, 0x38, 0x0a, 0x02, 0x04, 0x04, 0x12, - 0x04, 0x50, 0x00, 0x68, 0x01, 0x1a, 0x2c, 0x20, 0x41, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x73, 0x20, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, 0x12, 0x03, 0x50, 0x08, 0x1f, 0x0a, - 0x1b, 0x0a, 0x04, 0x04, 0x04, 0x04, 0x00, 0x12, 0x04, 0x52, 0x02, 0x57, 0x03, 0x1a, 0x0d, 0x20, - 0x42, 0x61, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x04, 0x04, 0x00, 0x01, 0x12, 0x03, 0x52, 0x07, 0x1c, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, - 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x53, 0x04, 0x2c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x04, - 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x53, 0x04, 0x27, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x04, - 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x53, 0x2a, 0x2b, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, 0x04, - 0x00, 0x02, 0x01, 0x12, 0x03, 0x54, 0x04, 0x25, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x04, 0x00, - 0x02, 0x01, 0x01, 0x12, 0x03, 0x54, 0x04, 0x20, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x04, 0x00, - 0x02, 0x01, 0x02, 0x12, 0x03, 0x54, 0x23, 0x24, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, 0x04, 0x00, - 0x02, 0x02, 0x12, 0x03, 0x55, 0x04, 0x2f, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x04, 0x00, 0x02, - 0x02, 0x01, 0x12, 0x03, 0x55, 0x04, 0x2a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x04, 0x00, 0x02, - 0x02, 0x02, 0x12, 0x03, 0x55, 0x2d, 0x2e, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, 0x04, 0x00, 0x02, - 0x03, 0x12, 0x03, 0x56, 0x04, 0x35, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x04, 0x00, 0x02, 0x03, - 0x01, 0x12, 0x03, 0x56, 0x04, 0x30, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x04, 0x00, 0x02, 0x03, - 0x02, 0x12, 0x03, 0x56, 0x33, 0x34, 0x0a, 0x44, 0x0a, 0x04, 0x04, 0x04, 0x03, 0x00, 0x12, 0x04, - 0x5a, 0x02, 0x5c, 0x03, 0x1a, 0x36, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x20, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, - 0x2e, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, - 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x04, 0x03, 0x00, 0x01, 0x12, 0x03, 0x5a, 0x0a, 0x16, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, - 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x5b, 0x04, 0x32, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, - 0x00, 0x02, 0x00, 0x04, 0x12, 0x03, 0x5b, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, - 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x5b, 0x0d, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, - 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x5b, 0x25, 0x2d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, - 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x5b, 0x30, 0x31, 0x0a, 0x44, 0x0a, 0x04, 0x04, 0x04, 0x03, - 0x01, 0x12, 0x04, 0x5f, 0x02, 0x61, 0x03, 0x1a, 0x36, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, + 0x03, 0x03, 0x00, 0x01, 0x12, 0x03, 0x3f, 0x0a, 0x16, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, + 0x00, 0x02, 0x00, 0x12, 0x03, 0x40, 0x04, 0x29, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, + 0x02, 0x00, 0x04, 0x12, 0x03, 0x40, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, + 0x02, 0x00, 0x06, 0x12, 0x03, 0x40, 0x0d, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x40, 0x1c, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, + 0x02, 0x00, 0x03, 0x12, 0x03, 0x40, 0x27, 0x28, 0x0a, 0x44, 0x0a, 0x04, 0x04, 0x03, 0x03, 0x01, + 0x12, 0x04, 0x44, 0x02, 0x46, 0x03, 0x1a, 0x36, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, + 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, + 0x65, 0x73, 0x2e, 0x20, 0x41, 0x6e, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x65, 0x76, 0x61, + 0x6c, 0x75, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x03, 0x03, 0x01, 0x01, 0x12, 0x03, 0x44, 0x0a, 0x16, 0x0a, 0x0d, 0x0a, 0x06, + 0x04, 0x03, 0x03, 0x01, 0x02, 0x00, 0x12, 0x03, 0x45, 0x04, 0x29, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x03, 0x03, 0x01, 0x02, 0x00, 0x04, 0x12, 0x03, 0x45, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x03, 0x03, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, 0x45, 0x0d, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x03, 0x03, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x45, 0x1c, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x03, 0x03, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x45, 0x27, 0x28, 0x0a, 0x0c, 0x0a, 0x04, 0x04, + 0x03, 0x08, 0x00, 0x12, 0x04, 0x48, 0x02, 0x4c, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x08, + 0x00, 0x01, 0x12, 0x03, 0x48, 0x08, 0x0c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x00, 0x12, + 0x03, 0x49, 0x04, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x06, 0x12, 0x03, 0x49, + 0x04, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, 0x49, 0x17, 0x1b, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x49, 0x1e, 0x1f, 0x0a, 0x0b, + 0x0a, 0x04, 0x04, 0x03, 0x02, 0x01, 0x12, 0x03, 0x4a, 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x06, 0x12, 0x03, 0x4a, 0x04, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, + 0x01, 0x01, 0x12, 0x03, 0x4a, 0x11, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x03, + 0x12, 0x03, 0x4a, 0x21, 0x22, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x02, 0x12, 0x03, 0x4b, + 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x06, 0x12, 0x03, 0x4b, 0x04, 0x10, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x01, 0x12, 0x03, 0x4b, 0x11, 0x1e, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x03, 0x12, 0x03, 0x4b, 0x21, 0x22, 0x0a, 0x38, 0x0a, 0x02, + 0x04, 0x04, 0x12, 0x04, 0x50, 0x00, 0x68, 0x01, 0x1a, 0x2c, 0x20, 0x41, 0x20, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x73, + 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, 0x12, 0x03, 0x50, + 0x08, 0x1f, 0x0a, 0x1b, 0x0a, 0x04, 0x04, 0x04, 0x04, 0x00, 0x12, 0x04, 0x52, 0x02, 0x57, 0x03, + 0x1a, 0x0d, 0x20, 0x42, 0x61, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x0a, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x04, 0x00, 0x01, 0x12, 0x03, 0x52, 0x07, 0x1c, 0x0a, 0x0d, 0x0a, + 0x06, 0x04, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x53, 0x04, 0x2c, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x04, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x53, 0x04, 0x27, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x04, 0x04, 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x53, 0x2a, 0x2b, 0x0a, 0x0d, 0x0a, 0x06, + 0x04, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x54, 0x04, 0x25, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x04, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x54, 0x04, 0x20, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x04, 0x04, 0x00, 0x02, 0x01, 0x02, 0x12, 0x03, 0x54, 0x23, 0x24, 0x0a, 0x0d, 0x0a, 0x06, 0x04, + 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x55, 0x04, 0x2f, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, + 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x55, 0x04, 0x2a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, + 0x04, 0x00, 0x02, 0x02, 0x02, 0x12, 0x03, 0x55, 0x2d, 0x2e, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, + 0x04, 0x00, 0x02, 0x03, 0x12, 0x03, 0x56, 0x04, 0x35, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x04, + 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x56, 0x04, 0x30, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x04, + 0x00, 0x02, 0x03, 0x02, 0x12, 0x03, 0x56, 0x33, 0x34, 0x0a, 0x44, 0x0a, 0x04, 0x04, 0x04, 0x03, + 0x00, 0x12, 0x04, 0x5a, 0x02, 0x5c, 0x03, 0x1a, 0x36, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x69, 0x65, 0x73, 0x2e, 0x20, 0x41, 0x6e, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x65, 0x76, + 0x69, 0x65, 0x73, 0x2e, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x03, 0x01, 0x01, 0x12, 0x03, 0x5f, 0x0a, 0x16, 0x0a, 0x0d, 0x0a, - 0x06, 0x04, 0x04, 0x03, 0x01, 0x02, 0x00, 0x12, 0x03, 0x60, 0x04, 0x32, 0x0a, 0x0e, 0x0a, 0x07, - 0x04, 0x04, 0x03, 0x01, 0x02, 0x00, 0x04, 0x12, 0x03, 0x60, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, - 0x04, 0x04, 0x03, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, 0x60, 0x0d, 0x24, 0x0a, 0x0e, 0x0a, 0x07, - 0x04, 0x04, 0x03, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x60, 0x25, 0x2d, 0x0a, 0x0e, 0x0a, 0x07, - 0x04, 0x04, 0x03, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x60, 0x30, 0x31, 0x0a, 0x0c, 0x0a, 0x04, - 0x04, 0x04, 0x08, 0x00, 0x12, 0x04, 0x63, 0x02, 0x67, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, - 0x08, 0x00, 0x01, 0x12, 0x03, 0x63, 0x08, 0x0c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, - 0x12, 0x03, 0x64, 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x06, 0x12, 0x03, - 0x64, 0x04, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x01, 0x12, 0x03, 0x64, 0x1a, - 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, 0x64, 0x21, 0x22, 0x0a, - 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x01, 0x12, 0x03, 0x65, 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x04, 0x02, 0x01, 0x06, 0x12, 0x03, 0x65, 0x04, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, - 0x02, 0x01, 0x01, 0x12, 0x03, 0x65, 0x11, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, - 0x03, 0x12, 0x03, 0x65, 0x21, 0x22, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x02, 0x12, 0x03, - 0x66, 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x02, 0x06, 0x12, 0x03, 0x66, 0x04, - 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, 0x66, 0x11, 0x1e, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x02, 0x03, 0x12, 0x03, 0x66, 0x21, 0x22, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xb8, 0x1a, 0x0a, 0x2e, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x74, - 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, - 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x10, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, - 0x69, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0c, 0x52, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x49, 0x64, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3f, 0x0a, 0x1c, - 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x19, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x41, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x80, 0x03, - 0x0a, 0x16, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, - 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x0d, 0x6d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0c, 0x6d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x65, 0x64, 0x12, 0x54, 0x0a, 0x0f, 0x6d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, + 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x03, 0x00, 0x01, 0x12, 0x03, 0x5a, 0x0a, 0x16, 0x0a, 0x0d, 0x0a, + 0x06, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x5b, 0x04, 0x32, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x04, 0x12, 0x03, 0x5b, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x5b, 0x0d, 0x24, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x5b, 0x25, 0x2d, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x5b, 0x30, 0x31, 0x0a, 0x44, 0x0a, 0x04, + 0x04, 0x04, 0x03, 0x01, 0x12, 0x04, 0x5f, 0x02, 0x61, 0x03, 0x1a, 0x36, 0x20, 0x43, 0x6f, 0x6d, + 0x62, 0x69, 0x6e, 0x65, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x20, 0x41, 0x6e, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x74, + 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x75, + 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x03, 0x01, 0x01, 0x12, 0x03, 0x5f, 0x0a, 0x16, + 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, 0x03, 0x01, 0x02, 0x00, 0x12, 0x03, 0x60, 0x04, 0x32, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x01, 0x02, 0x00, 0x04, 0x12, 0x03, 0x60, 0x04, 0x0c, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, 0x60, 0x0d, 0x24, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x60, 0x25, 0x2d, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x60, 0x30, 0x31, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x04, 0x08, 0x00, 0x12, 0x04, 0x63, 0x02, 0x67, 0x03, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x04, 0x08, 0x00, 0x01, 0x12, 0x03, 0x63, 0x08, 0x0c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, + 0x04, 0x02, 0x00, 0x12, 0x03, 0x64, 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, + 0x06, 0x12, 0x03, 0x64, 0x04, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x01, 0x12, + 0x03, 0x64, 0x1a, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, 0x64, + 0x21, 0x22, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x01, 0x12, 0x03, 0x65, 0x04, 0x23, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x06, 0x12, 0x03, 0x65, 0x04, 0x10, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x04, 0x02, 0x01, 0x01, 0x12, 0x03, 0x65, 0x11, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x04, 0x02, 0x01, 0x03, 0x12, 0x03, 0x65, 0x21, 0x22, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, + 0x02, 0x12, 0x03, 0x66, 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x02, 0x06, 0x12, + 0x03, 0x66, 0x04, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, 0x66, + 0x11, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x02, 0x03, 0x12, 0x03, 0x66, 0x21, 0x22, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xb8, 0x1a, 0x0a, 0x2e, 0x6d, 0x6c, 0x73, + 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x10, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x73, 0x68, 0x69, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x3f, 0x0a, 0x1c, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, + 0x42, 0x79, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x22, 0x80, 0x03, 0x0a, 0x16, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x68, 0x69, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x0d, 0x6d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, + 0x0c, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x65, 0x64, 0x12, 0x54, 0x0a, + 0x0f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, + 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x52, 0x0e, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x64, 0x12, 0x5c, 0x0a, 0x13, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x12, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x41, 0x64, 0x64, 0x65, + 0x64, 0x12, 0x60, 0x0a, 0x15, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x14, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x64, 0x22, 0x9b, 0x04, 0x0a, 0x0c, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x64, 0x12, 0x31, 0x0a, 0x15, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x12, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, + 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, 0x52, 0x0a, 0x0d, 0x61, 0x64, 0x64, 0x65, 0x64, + 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x52, 0x0c, 0x61, + 0x64, 0x64, 0x65, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x12, 0x56, 0x0a, 0x0f, 0x72, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, + 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x49, 0x6e, + 0x62, 0x6f, 0x78, 0x52, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x49, 0x6e, 0x62, 0x6f, + 0x78, 0x65, 0x73, 0x12, 0x71, 0x0a, 0x16, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, - 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x52, 0x0e, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, - 0x12, 0x5c, 0x0a, 0x13, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x73, 0x68, 0x69, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x12, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x41, 0x64, 0x64, 0x65, 0x64, 0x12, 0x60, - 0x0a, 0x15, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, - 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x73, 0x68, 0x69, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x14, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, - 0x22, 0x9b, 0x04, 0x0a, 0x0c, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x64, 0x12, 0x31, 0x0a, 0x15, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, - 0x79, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x12, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x49, 0x6e, 0x62, - 0x6f, 0x78, 0x49, 0x64, 0x12, 0x52, 0x0a, 0x0d, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x69, 0x6e, - 0x62, 0x6f, 0x78, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x78, 0x6d, - 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x64, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x52, 0x0c, 0x61, 0x64, 0x64, 0x65, - 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x12, 0x56, 0x0a, 0x0f, 0x72, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x78, - 0x52, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, - 0x12, 0x71, 0x0a, 0x16, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x3b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x14, 0x6d, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x52, 0x14, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x1a, 0x22, 0x0a, 0x05, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x12, + 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x1a, 0x94, 0x01, 0x0a, 0x13, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x73, 0x1a, 0x22, 0x0a, 0x05, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x12, 0x19, 0x0a, 0x08, - 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x1a, 0x94, 0x01, 0x0a, 0x13, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, - 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, - 0x0a, 0x09, 0x6f, 0x6c, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x08, 0x6f, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x88, 0x01, 0x01, - 0x12, 0x20, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x88, - 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6f, 0x6c, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0xec, - 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, + 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x20, 0x0a, 0x09, 0x6f, 0x6c, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x6f, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6f, 0x6c, 0x64, 0x5f, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x42, 0xec, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, + 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x73, 0x42, 0x17, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x42, 0x17, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, - 0x58, 0x4d, 0x4d, 0xaa, 0x02, 0x18, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x6c, 0x73, 0x2e, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, - 0x18, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xe2, 0x02, 0x24, 0x58, 0x6d, 0x74, 0x70, - 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x1a, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x6c, 0x73, 0x3a, 0x3a, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xa8, 0x0f, - 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x38, 0x01, 0x0a, 0x2f, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, - 0x00, 0x12, 0x1a, 0x25, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, - 0x03, 0x00, 0x22, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x05, 0x00, 0x47, 0x0a, 0x09, 0x0a, - 0x02, 0x08, 0x0b, 0x12, 0x03, 0x05, 0x00, 0x47, 0x0a, 0x3a, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, - 0x09, 0x00, 0x0d, 0x01, 0x1a, 0x2e, 0x20, 0x41, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x49, 0x44, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x09, 0x08, 0x18, - 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0a, 0x02, 0x26, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x00, 0x02, 0x00, 0x04, 0x12, 0x03, 0x0a, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x0a, 0x0b, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x00, 0x01, 0x12, 0x03, 0x0a, 0x11, 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, - 0x12, 0x03, 0x0a, 0x24, 0x25, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x0b, - 0x02, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x0b, 0x02, 0x08, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x0b, 0x09, 0x18, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x0b, 0x1b, 0x1c, 0x0a, 0x0b, 0x0a, 0x04, - 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x0c, 0x02, 0x2a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x02, 0x05, 0x12, 0x03, 0x0c, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, - 0x12, 0x03, 0x0c, 0x09, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, - 0x0c, 0x28, 0x29, 0x0a, 0x64, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x10, 0x00, 0x1d, 0x01, 0x1a, - 0x23, 0x20, 0x54, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x0a, 0x22, 0x33, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6c, 0x69, 0x6e, 0x74, - 0x3a, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0x45, - 0x44, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x4e, 0x41, 0x4d, 0x45, 0x53, 0x5f, 0x50, 0x4c, - 0x55, 0x52, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, - 0x12, 0x03, 0x10, 0x08, 0x1e, 0x0a, 0x39, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x14, - 0x02, 0x2e, 0x1a, 0x2c, 0x20, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x20, 0x74, 0x68, 0x61, - 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x65, - 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x0a, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x04, 0x12, 0x03, 0x14, 0x02, 0x0a, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, 0x14, 0x0b, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x14, 0x1c, 0x29, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, - 0x02, 0x00, 0x03, 0x12, 0x03, 0x14, 0x2c, 0x2d, 0x0a, 0x3b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, - 0x12, 0x03, 0x16, 0x02, 0x30, 0x1a, 0x2e, 0x20, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x20, - 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x72, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x04, 0x12, 0x03, - 0x16, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x06, 0x12, 0x03, 0x16, 0x0b, - 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, 0x16, 0x1c, 0x2b, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x16, 0x2e, 0x2f, 0x0a, 0x52, 0x0a, - 0x04, 0x04, 0x01, 0x02, 0x02, 0x12, 0x03, 0x18, 0x02, 0x34, 0x1a, 0x45, 0x20, 0x49, 0x6e, 0x73, - 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, - 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, - 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2c, 0x20, 0x67, - 0x72, 0x6f, 0x75, 0x70, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x04, 0x12, 0x03, 0x18, 0x02, 0x0a, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x06, 0x12, 0x03, 0x18, 0x0b, 0x1b, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x01, 0x02, 0x02, 0x01, 0x12, 0x03, 0x18, 0x1c, 0x2f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x01, 0x02, 0x02, 0x03, 0x12, 0x03, 0x18, 0x32, 0x33, 0x0a, 0x45, 0x0a, 0x04, 0x04, 0x01, 0x02, - 0x03, 0x12, 0x03, 0x1a, 0x02, 0x36, 0x1a, 0x38, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x69, - 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2c, 0x20, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x0a, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x04, 0x12, 0x03, 0x1a, 0x02, 0x0a, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x06, 0x12, 0x03, 0x1a, 0x0b, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x01, 0x02, 0x03, 0x01, 0x12, 0x03, 0x1a, 0x1c, 0x31, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, - 0x02, 0x03, 0x03, 0x12, 0x03, 0x1a, 0x34, 0x35, 0x0a, 0x6b, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, - 0x21, 0x00, 0x38, 0x01, 0x1a, 0x5f, 0x20, 0x41, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, - 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, - 0x69, 0x6e, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2e, 0x0a, 0x20, 0x49, 0x6e, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x2f, 0x72, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, 0x21, 0x08, - 0x14, 0x0a, 0x41, 0x0a, 0x04, 0x04, 0x02, 0x03, 0x00, 0x12, 0x04, 0x23, 0x02, 0x25, 0x03, 0x1a, - 0x33, 0x20, 0x41, 0x6e, 0x20, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, - 0x77, 0x61, 0x73, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x03, 0x00, 0x01, 0x12, 0x03, 0x23, - 0x0a, 0x0f, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x24, 0x04, - 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x24, 0x04, - 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x24, 0x0b, - 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x24, 0x16, - 0x17, 0x0a, 0x3d, 0x0a, 0x04, 0x04, 0x02, 0x03, 0x01, 0x12, 0x04, 0x28, 0x02, 0x2f, 0x03, 0x1a, - 0x2f, 0x20, 0x41, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x61, - 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, - 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x0a, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x03, 0x01, 0x01, 0x12, 0x03, 0x28, 0x0a, 0x1d, 0x0a, 0x2b, - 0x0a, 0x06, 0x04, 0x02, 0x03, 0x01, 0x02, 0x00, 0x12, 0x03, 0x2a, 0x04, 0x1a, 0x1a, 0x1c, 0x20, - 0x54, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, - 0x61, 0x73, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, - 0x02, 0x03, 0x01, 0x02, 0x00, 0x05, 0x12, 0x03, 0x2a, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, - 0x02, 0x03, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2a, 0x0b, 0x15, 0x0a, 0x0e, 0x0a, 0x07, 0x04, - 0x02, 0x03, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2a, 0x18, 0x19, 0x0a, 0x23, 0x0a, 0x06, 0x04, - 0x02, 0x03, 0x01, 0x02, 0x01, 0x12, 0x03, 0x2c, 0x04, 0x22, 0x1a, 0x14, 0x20, 0x54, 0x68, 0x65, - 0x20, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x0a, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x04, 0x12, 0x03, 0x2c, 0x04, 0x0c, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x05, 0x12, 0x03, 0x2c, 0x0d, 0x13, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, 0x2c, 0x14, 0x1d, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x2c, 0x20, 0x21, - 0x0a, 0x22, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x01, 0x02, 0x02, 0x12, 0x03, 0x2e, 0x04, 0x22, 0x1a, - 0x13, 0x20, 0x54, 0x68, 0x65, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x20, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x02, 0x04, 0x12, - 0x03, 0x2e, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x02, 0x05, 0x12, - 0x03, 0x2e, 0x0d, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x02, 0x01, 0x12, - 0x03, 0x2e, 0x14, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x12, - 0x03, 0x2e, 0x20, 0x21, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, 0x31, 0x02, - 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x05, 0x12, 0x03, 0x31, 0x02, 0x08, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x31, 0x09, 0x1e, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x31, 0x21, 0x22, 0x0a, 0x2e, 0x0a, 0x04, 0x04, - 0x02, 0x02, 0x01, 0x12, 0x03, 0x33, 0x02, 0x23, 0x1a, 0x21, 0x20, 0x54, 0x68, 0x65, 0x20, 0x69, - 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x02, 0x02, 0x01, 0x04, 0x12, 0x03, 0x33, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, - 0x01, 0x06, 0x12, 0x03, 0x33, 0x0b, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x01, - 0x12, 0x03, 0x33, 0x11, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, 0x12, 0x03, - 0x33, 0x21, 0x22, 0x0a, 0x30, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x02, 0x12, 0x03, 0x35, 0x02, 0x25, - 0x1a, 0x23, 0x20, 0x54, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x20, 0x72, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x04, 0x12, 0x03, - 0x35, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x06, 0x12, 0x03, 0x35, 0x0b, - 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x01, 0x12, 0x03, 0x35, 0x11, 0x20, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x03, 0x12, 0x03, 0x35, 0x23, 0x24, 0x0a, 0x31, 0x0a, - 0x04, 0x04, 0x02, 0x02, 0x03, 0x12, 0x03, 0x37, 0x02, 0x3a, 0x1a, 0x24, 0x20, 0x54, 0x68, 0x65, - 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x0a, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x03, 0x04, 0x12, 0x03, 0x37, 0x02, 0x0a, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x02, 0x02, 0x03, 0x06, 0x12, 0x03, 0x37, 0x0b, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x02, 0x02, 0x03, 0x01, 0x12, 0x03, 0x37, 0x1f, 0x35, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, - 0x02, 0x03, 0x03, 0x12, 0x03, 0x37, 0x38, 0x39, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x4d, 0xaa, 0x02, 0x18, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x6c, + 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0xca, 0x02, 0x18, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xe2, 0x02, 0x24, 0x58, + 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x1a, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x6c, 0x73, 0x3a, + 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, + 0x4a, 0xa8, 0x0f, 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x38, 0x01, 0x0a, 0x2f, 0x0a, 0x01, 0x0c, + 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x25, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, + 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x0a, 0x0a, 0x08, 0x0a, 0x01, + 0x02, 0x12, 0x03, 0x03, 0x00, 0x22, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x05, 0x00, 0x47, + 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x05, 0x00, 0x47, 0x0a, 0x3a, 0x0a, 0x02, 0x04, + 0x00, 0x12, 0x04, 0x09, 0x00, 0x0d, 0x01, 0x1a, 0x2e, 0x20, 0x41, 0x20, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x66, 0x66, + 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x49, 0x44, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, + 0x09, 0x08, 0x18, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0a, 0x02, 0x26, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x04, 0x12, 0x03, 0x0a, 0x02, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x0a, 0x0b, 0x10, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0a, 0x11, 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x00, 0x03, 0x12, 0x03, 0x0a, 0x24, 0x25, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, + 0x12, 0x03, 0x0b, 0x02, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, + 0x0b, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x0b, 0x09, + 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x0b, 0x1b, 0x1c, 0x0a, + 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x0c, 0x02, 0x2a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x0c, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x02, 0x01, 0x12, 0x03, 0x0c, 0x09, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, + 0x03, 0x12, 0x03, 0x0c, 0x28, 0x29, 0x0a, 0x64, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x10, 0x00, + 0x1d, 0x01, 0x1a, 0x23, 0x20, 0x54, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x0a, 0x22, 0x33, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6c, + 0x69, 0x6e, 0x74, 0x3a, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x52, 0x45, 0x50, 0x45, + 0x41, 0x54, 0x45, 0x44, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x4e, 0x41, 0x4d, 0x45, 0x53, + 0x5f, 0x50, 0x4c, 0x55, 0x52, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, + 0x04, 0x01, 0x01, 0x12, 0x03, 0x10, 0x08, 0x1e, 0x0a, 0x39, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, + 0x12, 0x03, 0x14, 0x02, 0x2e, 0x1a, 0x2c, 0x20, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x20, + 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x61, + 0x64, 0x64, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x04, 0x12, 0x03, 0x14, 0x02, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, 0x14, 0x0b, 0x1b, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x14, 0x1c, 0x29, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x14, 0x2c, 0x2d, 0x0a, 0x3b, 0x0a, 0x04, 0x04, + 0x01, 0x02, 0x01, 0x12, 0x03, 0x16, 0x02, 0x30, 0x1a, 0x2e, 0x20, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, + 0x6e, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, + 0x04, 0x12, 0x03, 0x16, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x06, 0x12, + 0x03, 0x16, 0x0b, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, 0x16, + 0x1c, 0x2b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x16, 0x2e, 0x2f, + 0x0a, 0x52, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x02, 0x12, 0x03, 0x18, 0x02, 0x34, 0x1a, 0x45, 0x20, + 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x68, + 0x61, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x64, 0x64, + 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x2c, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x04, 0x12, 0x03, 0x18, + 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x06, 0x12, 0x03, 0x18, 0x0b, 0x1b, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x01, 0x12, 0x03, 0x18, 0x1c, 0x2f, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x03, 0x12, 0x03, 0x18, 0x32, 0x33, 0x0a, 0x45, 0x0a, 0x04, + 0x04, 0x01, 0x02, 0x03, 0x12, 0x03, 0x1a, 0x02, 0x36, 0x1a, 0x38, 0x20, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2c, + 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x6d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x04, 0x12, 0x03, 0x1a, 0x02, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x06, 0x12, 0x03, 0x1a, 0x0b, 0x1b, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x01, 0x12, 0x03, 0x1a, 0x1c, 0x31, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x01, 0x02, 0x03, 0x03, 0x12, 0x03, 0x1a, 0x34, 0x35, 0x0a, 0x6b, 0x0a, 0x02, 0x04, + 0x02, 0x12, 0x04, 0x21, 0x00, 0x38, 0x01, 0x1a, 0x5f, 0x20, 0x41, 0x20, 0x73, 0x75, 0x6d, 0x6d, + 0x61, 0x72, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2e, 0x0a, + 0x20, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x2f, + 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, + 0x03, 0x21, 0x08, 0x14, 0x0a, 0x41, 0x0a, 0x04, 0x04, 0x02, 0x03, 0x00, 0x12, 0x04, 0x23, 0x02, + 0x25, 0x03, 0x1a, 0x33, 0x20, 0x41, 0x6e, 0x20, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x20, 0x74, 0x68, + 0x61, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x6f, 0x72, 0x20, + 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x03, 0x00, 0x01, + 0x12, 0x03, 0x23, 0x0a, 0x0f, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x12, + 0x03, 0x24, 0x04, 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, + 0x03, 0x24, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, + 0x03, 0x24, 0x0b, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, + 0x03, 0x24, 0x16, 0x17, 0x0a, 0x3d, 0x0a, 0x04, 0x04, 0x02, 0x03, 0x01, 0x12, 0x04, 0x28, 0x02, + 0x2f, 0x03, 0x1a, 0x2f, 0x20, 0x41, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x6f, + 0x66, 0x20, 0x61, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x03, 0x01, 0x01, 0x12, 0x03, 0x28, 0x0a, + 0x1d, 0x0a, 0x2b, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x01, 0x02, 0x00, 0x12, 0x03, 0x2a, 0x04, 0x1a, + 0x1a, 0x1c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x61, + 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x00, 0x05, 0x12, 0x03, 0x2a, 0x04, 0x0a, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2a, 0x0b, 0x15, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2a, 0x18, 0x19, 0x0a, 0x23, + 0x0a, 0x06, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x12, 0x03, 0x2c, 0x04, 0x22, 0x1a, 0x14, 0x20, + 0x54, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x04, 0x12, 0x03, + 0x2c, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x05, 0x12, 0x03, + 0x2c, 0x0d, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, + 0x2c, 0x14, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, + 0x2c, 0x20, 0x21, 0x0a, 0x22, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x01, 0x02, 0x02, 0x12, 0x03, 0x2e, + 0x04, 0x22, 0x1a, 0x13, 0x20, 0x54, 0x68, 0x65, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, + 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, + 0x02, 0x04, 0x12, 0x03, 0x2e, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, + 0x02, 0x05, 0x12, 0x03, 0x2e, 0x0d, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, + 0x02, 0x01, 0x12, 0x03, 0x2e, 0x14, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, + 0x02, 0x03, 0x12, 0x03, 0x2e, 0x20, 0x21, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, + 0x03, 0x31, 0x02, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x05, 0x12, 0x03, 0x31, + 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x31, 0x09, 0x1e, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x31, 0x21, 0x22, 0x0a, 0x2e, + 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, 0x33, 0x02, 0x23, 0x1a, 0x21, 0x20, 0x54, 0x68, + 0x65, 0x20, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x04, 0x12, 0x03, 0x33, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x02, 0x02, 0x01, 0x06, 0x12, 0x03, 0x33, 0x0b, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, + 0x02, 0x01, 0x01, 0x12, 0x03, 0x33, 0x11, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, + 0x03, 0x12, 0x03, 0x33, 0x21, 0x22, 0x0a, 0x30, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x02, 0x12, 0x03, + 0x35, 0x02, 0x25, 0x1a, 0x23, 0x20, 0x54, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x65, + 0x73, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, + 0x04, 0x12, 0x03, 0x35, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x06, 0x12, + 0x03, 0x35, 0x0b, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x01, 0x12, 0x03, 0x35, + 0x11, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x03, 0x12, 0x03, 0x35, 0x23, 0x24, + 0x0a, 0x31, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x03, 0x12, 0x03, 0x37, 0x02, 0x3a, 0x1a, 0x24, 0x20, + 0x54, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x03, 0x04, 0x12, 0x03, 0x37, 0x02, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x03, 0x06, 0x12, 0x03, 0x37, 0x0b, 0x1e, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x03, 0x01, 0x12, 0x03, 0x37, 0x1f, 0x35, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x02, 0x02, 0x03, 0x03, 0x12, 0x03, 0x37, 0x38, 0x39, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, ]; include!("xmtp.mls.message_contents.serde.rs"); // @@protoc_insertion_point(module) \ No newline at end of file diff --git a/xmtp_proto/src/gen/xmtp.mls.message_contents.serde.rs b/xmtp_proto/src/gen/xmtp.mls.message_contents.serde.rs index 5b3ec2bfa..d8b12dd1f 100644 --- a/xmtp_proto/src/gen/xmtp.mls.message_contents.serde.rs +++ b/xmtp_proto/src/gen/xmtp.mls.message_contents.serde.rs @@ -502,6 +502,116 @@ impl<'de> serde::Deserialize<'de> for CredentialRevocation { deserializer.deserialize_struct("xmtp.mls.message_contents.CredentialRevocation", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for DmMembers { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.dm_member_one.is_some() { + len += 1; + } + if self.dm_member_two.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.message_contents.DmMembers", len)?; + if let Some(v) = self.dm_member_one.as_ref() { + struct_ser.serialize_field("dmMemberOne", v)?; + } + if let Some(v) = self.dm_member_two.as_ref() { + struct_ser.serialize_field("dmMemberTwo", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for DmMembers { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "dm_member_one", + "dmMemberOne", + "dm_member_two", + "dmMemberTwo", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + DmMemberOne, + DmMemberTwo, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "dmMemberOne" | "dm_member_one" => Ok(GeneratedField::DmMemberOne), + "dmMemberTwo" | "dm_member_two" => Ok(GeneratedField::DmMemberTwo), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = DmMembers; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.message_contents.DmMembers") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut dm_member_one__ = None; + let mut dm_member_two__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::DmMemberOne => { + if dm_member_one__.is_some() { + return Err(serde::de::Error::duplicate_field("dmMemberOne")); + } + dm_member_one__ = map_.next_value()?; + } + GeneratedField::DmMemberTwo => { + if dm_member_two__.is_some() { + return Err(serde::de::Error::duplicate_field("dmMemberTwo")); + } + dm_member_two__ = map_.next_value()?; + } + } + } + Ok(DmMembers { + dm_member_one: dm_member_one__, + dm_member_two: dm_member_two__, + }) + } + } + deserializer.deserialize_struct("xmtp.mls.message_contents.DmMembers", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for EdDsaSignature { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -1171,6 +1281,9 @@ impl serde::Serialize for GroupMetadataV1 { if !self.creator_inbox_id.is_empty() { len += 1; } + if self.dm_members.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("xmtp.mls.message_contents.GroupMetadataV1", len)?; if self.conversation_type != 0 { let v = ConversationType::try_from(self.conversation_type) @@ -1183,6 +1296,9 @@ impl serde::Serialize for GroupMetadataV1 { if !self.creator_inbox_id.is_empty() { struct_ser.serialize_field("creatorInboxId", &self.creator_inbox_id)?; } + if let Some(v) = self.dm_members.as_ref() { + struct_ser.serialize_field("dmMembers", v)?; + } struct_ser.end() } } @@ -1199,6 +1315,8 @@ impl<'de> serde::Deserialize<'de> for GroupMetadataV1 { "creatorAccountAddress", "creator_inbox_id", "creatorInboxId", + "dm_members", + "dmMembers", ]; #[allow(clippy::enum_variant_names)] @@ -1206,6 +1324,7 @@ impl<'de> serde::Deserialize<'de> for GroupMetadataV1 { ConversationType, CreatorAccountAddress, CreatorInboxId, + DmMembers, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -1230,6 +1349,7 @@ impl<'de> serde::Deserialize<'de> for GroupMetadataV1 { "conversationType" | "conversation_type" => Ok(GeneratedField::ConversationType), "creatorAccountAddress" | "creator_account_address" => Ok(GeneratedField::CreatorAccountAddress), "creatorInboxId" | "creator_inbox_id" => Ok(GeneratedField::CreatorInboxId), + "dmMembers" | "dm_members" => Ok(GeneratedField::DmMembers), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -1252,6 +1372,7 @@ impl<'de> serde::Deserialize<'de> for GroupMetadataV1 { let mut conversation_type__ = None; let mut creator_account_address__ = None; let mut creator_inbox_id__ = None; + let mut dm_members__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::ConversationType => { @@ -1272,12 +1393,19 @@ impl<'de> serde::Deserialize<'de> for GroupMetadataV1 { } creator_inbox_id__ = Some(map_.next_value()?); } + GeneratedField::DmMembers => { + if dm_members__.is_some() { + return Err(serde::de::Error::duplicate_field("dmMembers")); + } + dm_members__ = map_.next_value()?; + } } } Ok(GroupMetadataV1 { conversation_type: conversation_type__.unwrap_or_default(), creator_account_address: creator_account_address__.unwrap_or_default(), creator_inbox_id: creator_inbox_id__.unwrap_or_default(), + dm_members: dm_members__, }) } } @@ -1870,6 +1998,98 @@ impl<'de> serde::Deserialize<'de> for group_updated::MetadataFieldChange { deserializer.deserialize_struct("xmtp.mls.message_contents.GroupUpdated.MetadataFieldChange", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for Inbox { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.inbox_id.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.message_contents.Inbox", len)?; + if !self.inbox_id.is_empty() { + struct_ser.serialize_field("inboxId", &self.inbox_id)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for Inbox { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "inbox_id", + "inboxId", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + InboxId, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "inboxId" | "inbox_id" => Ok(GeneratedField::InboxId), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = Inbox; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.message_contents.Inbox") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut inbox_id__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::InboxId => { + if inbox_id__.is_some() { + return Err(serde::de::Error::duplicate_field("inboxId")); + } + inbox_id__ = Some(map_.next_value()?); + } + } + } + Ok(Inbox { + inbox_id: inbox_id__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.message_contents.Inbox", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for Inboxes { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result From 7f3f0cf56d8eeb3d5cf1c7b23a19d6bc24215f7e Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Tue, 10 Sep 2024 07:52:50 -0600 Subject: [PATCH 02/11] Private Preferences DB (#946) * create the database migration for the private preference work * update the table to be focused on consent * first pass at database storage structure * update the get method for consent records * fix up the set method * add a test * fix up the test * fix up the clippy error with consent record * fix up the clippy error with consent record * fix up all clippy issues * cargo fmt --- Cargo.lock | 13 +- .../down.sql | 2 + .../up.sql | 9 + xmtp_mls/src/groups/group_metadata.rs | 20 +- xmtp_mls/src/groups/group_permissions.rs | 19 +- xmtp_mls/src/groups/mod.rs | 8 +- .../storage/encrypted_store/consent_record.rs | 189 ++++++++++++++++++ xmtp_mls/src/storage/encrypted_store/mod.rs | 1 + .../src/storage/encrypted_store/schema.rs | 9 + 9 files changed, 238 insertions(+), 32 deletions(-) create mode 100644 xmtp_mls/migrations/2024-08-07-213816_create-private-preference-store/down.sql create mode 100644 xmtp_mls/migrations/2024-08-07-213816_create-private-preference-store/up.sql create mode 100644 xmtp_mls/src/storage/encrypted_store/consent_record.rs diff --git a/Cargo.lock b/Cargo.lock index dcfbe4341..59a3775b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2646,15 +2646,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -3902,7 +3893,7 @@ checksum = "5bb182580f71dd070f88d01ce3de9f4da5021db7115d2e1c3605a754153b77c1" dependencies = [ "bytes", "heck", - "itertools 0.12.1", + "itertools 0.13.0", "log", "multimap", "once_cell", @@ -3922,7 +3913,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.13.0", "proc-macro2", "quote", "syn 2.0.72", diff --git a/xmtp_mls/migrations/2024-08-07-213816_create-private-preference-store/down.sql b/xmtp_mls/migrations/2024-08-07-213816_create-private-preference-store/down.sql new file mode 100644 index 000000000..dd3043403 --- /dev/null +++ b/xmtp_mls/migrations/2024-08-07-213816_create-private-preference-store/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +DROP TABLE IF EXISTS "consent_records"; diff --git a/xmtp_mls/migrations/2024-08-07-213816_create-private-preference-store/up.sql b/xmtp_mls/migrations/2024-08-07-213816_create-private-preference-store/up.sql new file mode 100644 index 000000000..76e7f7f27 --- /dev/null +++ b/xmtp_mls/migrations/2024-08-07-213816_create-private-preference-store/up.sql @@ -0,0 +1,9 @@ +CREATE TABLE "consent_records"( + -- Enum of the CONSENT_TYPE (GROUP_ID, INBOX_ID, etc..) + "entity_type" int NOT NULL, + -- Enum of CONSENT_STATE (ALLOWED, DENIED, etc..) + "state" int NOT NULL, + -- The entity of what has consent (0x00 etc..) + "entity" text NOT NULL, + PRIMARY KEY (entity_type, entity) +); \ No newline at end of file diff --git a/xmtp_mls/src/groups/group_metadata.rs b/xmtp_mls/src/groups/group_metadata.rs index 781ab0f49..b274df3f1 100644 --- a/xmtp_mls/src/groups/group_metadata.rs +++ b/xmtp_mls/src/groups/group_metadata.rs @@ -17,6 +17,8 @@ pub enum GroupMetadataError { InvalidConversationType, #[error("missing extension")] MissingExtension, + #[error("missing a dm member")] + MissingDmMember, } #[derive(Debug, Clone, PartialEq)] @@ -72,14 +74,10 @@ impl TryFrom for GroupMetadata { type Error = GroupMetadataError; fn try_from(value: GroupMetadataProto) -> Result { - let dm_members = if value.dm_members.is_some() { - Some(DmMembers::try_from(value.dm_members.unwrap())?) - } else { - None - }; + let dm_members = value.dm_members.map(DmMembers::try_from).transpose()?; Ok(Self::new( value.conversation_type.try_into()?, - value.creator_inbox_id.clone(), + value.creator_inbox_id, dm_members, )) } @@ -150,8 +148,14 @@ impl TryFrom for DmMembers { fn try_from(value: DmMembersProto) -> Result { Ok(Self { - member_one_inbox_id: value.dm_member_one.unwrap().inbox_id.clone(), - member_two_inbox_id: value.dm_member_two.unwrap().inbox_id.clone(), + member_one_inbox_id: value + .dm_member_one + .ok_or(GroupMetadataError::MissingDmMember)? + .inbox_id, + member_two_inbox_id: value + .dm_member_two + .ok_or(GroupMetadataError::MissingDmMember)? + .inbox_id, }) } } diff --git a/xmtp_mls/src/groups/group_permissions.rs b/xmtp_mls/src/groups/group_permissions.rs index 43c331ba4..870f6b588 100644 --- a/xmtp_mls/src/groups/group_permissions.rs +++ b/xmtp_mls/src/groups/group_permissions.rs @@ -863,15 +863,16 @@ impl PolicySet { ); // We can always add DM member's inboxId to a DM - if commit.dm_members.is_some() - && commit.added_inboxes.len() == 1 - && (commit.added_inboxes[0].inbox_id - == commit.dm_members.as_ref().unwrap().member_one_inbox_id - || commit.added_inboxes[0].inbox_id - == commit.dm_members.as_ref().unwrap().member_two_inbox_id) - && commit.added_inboxes[0].inbox_id != commit.actor_inbox_id() - { - added_inboxes_valid = true; + if let Some(dm_members) = &commit.dm_members { + if commit.added_inboxes.len() == 1 { + let added_inbox_id = &commit.added_inboxes[0].inbox_id; + if (added_inbox_id == &dm_members.member_one_inbox_id + || added_inbox_id == &dm_members.member_two_inbox_id) + && added_inbox_id != &commit.actor_inbox_id() + { + added_inboxes_valid = true; + } + } } // Verify remove member policy was not violated diff --git a/xmtp_mls/src/groups/mod.rs b/xmtp_mls/src/groups/mod.rs index f7727a49c..957b597d3 100644 --- a/xmtp_mls/src/groups/mod.rs +++ b/xmtp_mls/src/groups/mod.rs @@ -3068,16 +3068,16 @@ mod tests { amal_dm.sync(&amal).await.unwrap(); bola_dm.sync(&bola).await.unwrap(); let is_amal_admin = amal_dm - .is_admin(amal.inbox_id(), &amal.mls_provider().unwrap()) + .is_admin(amal.inbox_id(), amal.mls_provider().unwrap()) .unwrap(); let is_bola_admin = amal_dm - .is_admin(bola.inbox_id(), &bola.mls_provider().unwrap()) + .is_admin(bola.inbox_id(), bola.mls_provider().unwrap()) .unwrap(); let is_amal_super_admin = amal_dm - .is_super_admin(amal.inbox_id(), &amal.mls_provider().unwrap()) + .is_super_admin(amal.inbox_id(), amal.mls_provider().unwrap()) .unwrap(); let is_bola_super_admin = amal_dm - .is_super_admin(bola.inbox_id(), &bola.mls_provider().unwrap()) + .is_super_admin(bola.inbox_id(), bola.mls_provider().unwrap()) .unwrap(); assert!(!is_amal_admin); assert!(!is_bola_admin); diff --git a/xmtp_mls/src/storage/encrypted_store/consent_record.rs b/xmtp_mls/src/storage/encrypted_store/consent_record.rs new file mode 100644 index 000000000..d124c3490 --- /dev/null +++ b/xmtp_mls/src/storage/encrypted_store/consent_record.rs @@ -0,0 +1,189 @@ +use crate::{impl_store, storage::StorageError}; + +use super::{ + db_connection::DbConnection, + schema::consent_records::{self, dsl}, +}; +use diesel::{ + backend::Backend, + deserialize::{self, FromSql, FromSqlRow}, + expression::AsExpression, + prelude::*, + serialize::{self, IsNull, Output, ToSql}, + sql_types::Integer, + sqlite::Sqlite, + upsert::excluded, +}; +use serde::{Deserialize, Serialize}; + +/// StoredConsentRecord holds a serialized ConsentRecord +#[derive(Insertable, Queryable, Debug, Clone, PartialEq, Eq)] +#[diesel(table_name = consent_records)] +#[diesel(primary_key(entity_type, entity))] +pub struct StoredConsentRecord { + /// Enum, [`ConsentType`] representing the type of consent (group_id inbox_id, etc..) + pub entity_type: ConsentType, + /// Enum, [`ConsentState`] representing the state of consent (allowed, denied, etc..) + pub state: ConsentState, + /// The entity of what was consented (0x00 etc..) + pub entity: String, +} + +impl StoredConsentRecord { + pub fn new(entity_type: ConsentType, state: ConsentState, entity: String) -> Self { + Self { + entity_type, + state, + entity, + } + } +} + +impl_store!(StoredConsentRecord, consent_records); + +impl DbConnection { + /// Returns the consent_records for the given entity up + pub fn get_consent_record( + &self, + entity: String, + entity_type: ConsentType, + ) -> Result, StorageError> { + Ok(self.raw_query(|conn| { + dsl::consent_records + .filter(dsl::entity.eq(entity)) + .filter(dsl::entity_type.eq(entity_type)) + .first(conn) + .optional() + })?) + } + + /// Insert consent_record, and replace existing entries + pub fn insert_or_replace_consent_record( + &self, + record: StoredConsentRecord, + ) -> Result<(), StorageError> { + self.raw_query(|conn| { + diesel::insert_into(dsl::consent_records) + .values(&record) + .on_conflict((dsl::entity_type, dsl::entity)) + .do_update() + .set(dsl::state.eq(excluded(dsl::state))) + .execute(conn)?; + Ok(()) + })?; + + Ok(()) + } +} + +#[repr(i32)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize, Eq, PartialEq, AsExpression, FromSqlRow)] +#[diesel(sql_type = Integer)] +/// Type of consent record stored +pub enum ConsentType { + /// Consent is for a group + GroupId = 1, + /// Consent is for an inbox + InboxId = 2, + /// Consent is for an address + Address = 3, +} + +impl ToSql for ConsentType +where + i32: ToSql, +{ + fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result { + out.set_value(*self as i32); + Ok(IsNull::No) + } +} + +impl FromSql for ConsentType +where + i32: FromSql, +{ + fn from_sql(bytes: ::RawValue<'_>) -> deserialize::Result { + match i32::from_sql(bytes)? { + 1 => Ok(ConsentType::GroupId), + 2 => Ok(ConsentType::InboxId), + 3 => Ok(ConsentType::Address), + x => Err(format!("Unrecognized variant {}", x).into()), + } + } +} + +#[repr(i32)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize, Eq, PartialEq, AsExpression, FromSqlRow)] +#[diesel(sql_type = Integer)] +/// The state of the consent +pub enum ConsentState { + /// Consent is allowed + Allowed = 1, + /// Consent is denied + Denied = 2, +} + +impl ToSql for ConsentState +where + i32: ToSql, +{ + fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result { + out.set_value(*self as i32); + Ok(IsNull::No) + } +} + +impl FromSql for ConsentState +where + i32: FromSql, +{ + fn from_sql(bytes: ::RawValue<'_>) -> deserialize::Result { + match i32::from_sql(bytes)? { + 1 => Ok(ConsentState::Allowed), + 2 => Ok(ConsentState::Denied), + x => Err(format!("Unrecognized variant {}", x).into()), + } + } +} + +#[cfg(test)] +mod tests { + use crate::storage::encrypted_store::tests::with_connection; + + use super::*; + + fn generate_consent_record( + entity_type: ConsentType, + state: ConsentState, + entity: String, + ) -> StoredConsentRecord { + StoredConsentRecord { + entity_type, + state, + entity, + } + } + + #[test] + fn insert_and_read() { + with_connection(|conn| { + let inbox_id = "inbox_1"; + let consent_record = generate_consent_record( + ConsentType::InboxId, + ConsentState::Denied, + inbox_id.to_string(), + ); + let consent_record_entity = consent_record.entity.clone(); + + conn.insert_or_replace_consent_record(consent_record) + .expect("should store without error"); + + let consent_record = conn + .get_consent_record(inbox_id.to_owned(), ConsentType::InboxId) + .expect("query should work"); + + assert_eq!(consent_record.unwrap().entity, consent_record_entity); + }); + } +} diff --git a/xmtp_mls/src/storage/encrypted_store/mod.rs b/xmtp_mls/src/storage/encrypted_store/mod.rs index f5d2f843d..371f060c6 100644 --- a/xmtp_mls/src/storage/encrypted_store/mod.rs +++ b/xmtp_mls/src/storage/encrypted_store/mod.rs @@ -11,6 +11,7 @@ //! `diesel print-schema` or use `cargo run update-schema` which will update the files for you. pub mod association_state; +pub mod consent_record; pub mod db_connection; pub mod group; pub mod group_intent; diff --git a/xmtp_mls/src/storage/encrypted_store/schema.rs b/xmtp_mls/src/storage/encrypted_store/schema.rs index 84d3c69ec..026969582 100644 --- a/xmtp_mls/src/storage/encrypted_store/schema.rs +++ b/xmtp_mls/src/storage/encrypted_store/schema.rs @@ -8,6 +8,14 @@ diesel::table! { } } +diesel::table! { + consent_records (entity_type, entity) { + entity_type -> Integer, + state -> Integer, + entity -> Text, + } +} + diesel::table! { group_intents (id) { id -> Integer, @@ -94,6 +102,7 @@ diesel::joinable!(group_messages -> groups (group_id)); diesel::allow_tables_to_appear_in_same_query!( association_state, + consent_records, group_intents, group_messages, groups, From 7432cee2a5d5d3bf91e24b05c4fa074471eac8ea Mon Sep 17 00:00:00 2001 From: Cameron Voell <1103838+cameronvoell@users.noreply.github.com> Date: Thu, 19 Sep 2024 11:08:05 -0700 Subject: [PATCH 03/11] Validate dm group metadata + permissions from welcome (#1075) * validate dm group before creating from welcome * lint fix * lint fix --------- Co-authored-by: cameronvoell --- xmtp_mls/src/groups/mod.rs | 281 ++++++++++++++++++++++++++++++++++--- 1 file changed, 261 insertions(+), 20 deletions(-) diff --git a/xmtp_mls/src/groups/mod.rs b/xmtp_mls/src/groups/mod.rs index f3b006082..931b64b1f 100644 --- a/xmtp_mls/src/groups/mod.rs +++ b/xmtp_mls/src/groups/mod.rs @@ -79,7 +79,7 @@ use crate::{ SEND_MESSAGE_UPDATE_INSTALLATIONS_INTERVAL_NS, }, hpke::{decrypt_welcome, HpkeError}, - identity::{parse_credential, Identity, IdentityError}, + identity::{parse_credential, IdentityError}, identity_updates::{load_identity_updates, InstallationDiffError}, retry::RetryableError, storage::{ @@ -295,9 +295,10 @@ impl MlsGroup { ) -> Result { let conn = context.store.conn()?; let provider = XmtpOpenMlsProvider::new(conn); + let creator_inbox_id = context.inbox_id(); let protected_metadata = - build_protected_metadata_extension(&context.identity, Purpose::Conversation)?; - let mutable_metadata = build_mutable_metadata_extension_default(&context.identity, opts)?; + build_protected_metadata_extension(creator_inbox_id.clone(), Purpose::Conversation)?; + let mutable_metadata = build_mutable_metadata_extension_default(creator_inbox_id, opts)?; let group_membership = build_starting_group_membership_extension(context.inbox_id(), 0); let mutable_permissions = build_mutable_permissions_extension(permissions_policy_set)?; let group_config = build_group_config( @@ -342,7 +343,7 @@ impl MlsGroup { let conn = context.store.conn()?; let provider = XmtpOpenMlsProvider::new(conn); let protected_metadata = - build_dm_protected_metadata_extension(&context.identity, dm_target_inbox_id.clone())?; + build_dm_protected_metadata_extension(context.inbox_id(), dm_target_inbox_id.clone())?; let mutable_metadata = build_dm_mutable_metadata_extension_default(context.inbox_id(), dm_target_inbox_id)?; let group_membership = build_starting_group_membership_extension(context.inbox_id(), 0); @@ -400,7 +401,7 @@ impl MlsGroup { let group_type = metadata.conversation_type; let to_store = match group_type { - ConversationType::Group | ConversationType::Dm => StoredGroup::new_from_welcome( + ConversationType::Group => StoredGroup::new_from_welcome( group_id.clone(), now_ns(), GroupMembershipState::Pending, @@ -408,6 +409,17 @@ impl MlsGroup { welcome_id, Purpose::Conversation, ), + ConversationType::Dm => { + validate_dm_group(client, &mls_group, &added_by_inbox)?; + StoredGroup::new_from_welcome( + group_id.clone(), + now_ns(), + GroupMembershipState::Pending, + added_by_inbox, + welcome_id, + Purpose::Conversation, + ) + } ConversationType::Sync => StoredGroup::new_from_welcome( group_id.clone(), now_ns(), @@ -465,11 +477,12 @@ impl MlsGroup { ) -> Result { let conn = context.store.conn()?; // let my_sequence_id = context.inbox_sequence_id(&conn)?; + let creator_inbox_id = context.inbox_id().to_string(); let provider = XmtpOpenMlsProvider::new(conn); let protected_metadata = - build_protected_metadata_extension(&context.identity, Purpose::Sync)?; + build_protected_metadata_extension(creator_inbox_id.clone(), Purpose::Sync)?; let mutable_metadata = build_mutable_metadata_extension_default( - &context.identity, + creator_inbox_id, GroupMetadataOptions::default(), )?; let group_membership = build_starting_group_membership_extension(context.inbox_id(), 0); @@ -1063,6 +1076,70 @@ impl MlsGroup { Ok(extract_group_permissions(&mls_group)?) } + /// Used for testing that dm group validation works as expected. + /// + /// See the `test_validate_dm_group` test function for more details. + #[cfg(test)] + pub fn create_test_dm_group( + context: Arc, + dm_target_inbox_id: InboxId, + custom_protected_metadata: Option, + custom_mutable_metadata: Option, + custom_group_membership: Option, + custom_mutable_permissions: Option, + ) -> Result { + let conn = context.store.conn()?; + let provider = XmtpOpenMlsProvider::new(conn); + + let protected_metadata = custom_protected_metadata.unwrap_or_else(|| { + build_dm_protected_metadata_extension(context.inbox_id(), dm_target_inbox_id.clone()) + .unwrap() + }); + let mutable_metadata = custom_mutable_metadata.unwrap_or_else(|| { + build_dm_mutable_metadata_extension_default( + context.inbox_id(), + dm_target_inbox_id.clone(), + ) + .unwrap() + }); + let group_membership = custom_group_membership + .unwrap_or_else(|| build_starting_group_membership_extension(context.inbox_id(), 0)); + let mutable_permissions = custom_mutable_permissions.unwrap_or_else(PolicySet::new_dm); + let mutable_permission_extension = + build_mutable_permissions_extension(mutable_permissions)?; + + let group_config = build_group_config( + protected_metadata, + mutable_metadata, + group_membership, + mutable_permission_extension, + )?; + + let mls_group = OpenMlsGroup::new( + &provider, + &context.identity.installation_keys, + &group_config, + CredentialWithKey { + credential: context.identity.credential(), + signature_key: context.identity.installation_keys.to_public_vec().into(), + }, + )?; + + let group_id = mls_group.group_id().to_vec(); + let stored_group = StoredGroup::new( + group_id.clone(), + now_ns(), + GroupMembershipState::Allowed, // Use Allowed as default for tests + context.inbox_id(), + ); + + stored_group.store(provider.conn_ref())?; + Ok(Self::new( + context.clone(), + group_id, + stored_group.created_at_ns, + )) + } } fn extract_message_v1(message: GroupMessage) -> Result { @@ -1080,7 +1157,7 @@ pub fn extract_group_id(message: &GroupMessage) -> Result, MessageProces } fn build_protected_metadata_extension( - identity: &Identity, + creator_inbox_id: String, group_purpose: Purpose, ) -> Result { let group_type = match group_purpose { @@ -1088,26 +1165,22 @@ fn build_protected_metadata_extension( Purpose::Sync => ConversationType::Sync, }; - let metadata = GroupMetadata::new(group_type, identity.inbox_id().clone(), None); + let metadata = GroupMetadata::new(group_type, creator_inbox_id, None); let protected_metadata = Metadata::new(metadata.try_into()?); Ok(Extension::ImmutableMetadata(protected_metadata)) } fn build_dm_protected_metadata_extension( - identity: &Identity, + creator_inbox_id: String, dm_inbox_id: InboxId, ) -> Result { let dm_members = Some(DmMembers { - member_one_inbox_id: identity.inbox_id().clone(), + member_one_inbox_id: creator_inbox_id.clone(), member_two_inbox_id: dm_inbox_id, }); - let metadata = GroupMetadata::new( - ConversationType::Dm, - identity.inbox_id().clone(), - dm_members, - ); + let metadata = GroupMetadata::new(ConversationType::Dm, creator_inbox_id, dm_members); let protected_metadata = Metadata::new(metadata.try_into()?); Ok(Extension::ImmutableMetadata(protected_metadata)) @@ -1124,11 +1197,11 @@ fn build_mutable_permissions_extension(policies: PolicySet) -> Result Result { let mutable_metadata: Vec = - GroupMutableMetadata::new_default(identity.inbox_id.clone(), opts).try_into()?; + GroupMutableMetadata::new_default(creator_inbox_id, opts).try_into()?; let unknown_gc_extension = UnknownExtension(mutable_metadata); Ok(Extension::Unknown( @@ -1377,6 +1450,59 @@ async fn validate_initial_group_membership( Ok(()) } +fn validate_dm_group( + client: &Client, + mls_group: &OpenMlsGroup, + added_by_inbox: &str, +) -> Result<(), GroupError> { + let metadata = extract_group_metadata(mls_group)?; + + // Check if the conversation type is DM + if metadata.conversation_type != ConversationType::Dm { + return Err(GroupError::Generic( + "Invalid conversation type for DM group".to_string(), + )); + } + + // Check if DmMembers are set and validate their contents + if let Some(dm_members) = metadata.dm_members { + let our_inbox_id = client.context.identity.inbox_id().clone(); + if !((dm_members.member_one_inbox_id == added_by_inbox + && dm_members.member_two_inbox_id == our_inbox_id) + || (dm_members.member_one_inbox_id == our_inbox_id + && dm_members.member_two_inbox_id == added_by_inbox)) + { + return Err(GroupError::Generic( + "DM members do not match expected inboxes".to_string(), + )); + } + } else { + return Err(GroupError::Generic( + "DM group must have DmMembers set".to_string(), + )); + } + + // Validate mutable metadata + let mutable_metadata: GroupMutableMetadata = mls_group.try_into()?; + + // Check if the admin list and super admin list are empty + if !mutable_metadata.admin_list.is_empty() || !mutable_metadata.super_admin_list.is_empty() { + return Err(GroupError::Generic( + "DM group must have empty admin and super admin lists".to_string(), + )); + } + + // Validate permissions + let permissions = extract_group_permissions(mls_group)?; + if permissions != GroupMutablePermissions::new(PolicySet::new_dm()) { + return Err(GroupError::Generic( + "Invalid permissions for DM group".to_string(), + )); + } + + Ok(()) +} + fn build_group_join_config() -> MlsGroupJoinConfig { MlsGroupJoinConfig::builder() .wire_format_policy(WireFormatPolicy::default()) @@ -1402,16 +1528,19 @@ mod tests { client::MessageProcessingError, codecs::{group_updated::GroupUpdatedCodec, ContentCodec}, groups::{ - build_group_membership_extension, + build_dm_protected_metadata_extension, build_group_membership_extension, + build_mutable_metadata_extension_default, build_protected_metadata_extension, group_membership::GroupMembership, group_metadata::{ConversationType, GroupMetadata}, group_mutable_metadata::MetadataField, intents::{PermissionPolicyOption, PermissionUpdateType}, members::{GroupMember, PermissionLevel}, - DeliveryStatus, GroupMetadataOptions, PreconfiguredPolicies, UpdateAdminListType, + validate_dm_group, DeliveryStatus, GroupMetadataOptions, PreconfiguredPolicies, + UpdateAdminListType, }, storage::{ consent_record::ConsentState, + group::Purpose, group_intent::{IntentKind, IntentState, NewGroupIntent}, group_message::{GroupMessageKind, StoredGroupMessage}, }, @@ -1420,6 +1549,7 @@ mod tests { }; use super::{ + group_permissions::PolicySet, intents::{Installation, SendWelcomesAction}, GroupError, MlsGroup, }; @@ -3419,4 +3549,115 @@ mod tests { assert_eq!(consent, ConsentState::Denied); } + + #[tokio::test] + async fn test_validate_dm_group() { + let client = ClientBuilder::new_test_client(&generate_local_wallet()).await; + let added_by_inbox = "added_by_inbox_id"; + let creator_inbox_id = client.context.identity.inbox_id().clone(); + let dm_target_inbox_id = added_by_inbox.to_string(); + + // Test case 1: Valid DM group + let valid_dm_group = MlsGroup::create_test_dm_group( + client.context.clone(), + dm_target_inbox_id.clone(), + None, + None, + None, + None, + ) + .unwrap(); + assert!(validate_dm_group( + &client, + &valid_dm_group + .load_mls_group(client.mls_provider().unwrap()) + .unwrap(), + added_by_inbox + ) + .is_ok()); + + // Test case 2: Invalid conversation type + let invalid_protected_metadata = + build_protected_metadata_extension(creator_inbox_id.clone(), Purpose::Conversation) + .unwrap(); + let invalid_type_group = MlsGroup::create_test_dm_group( + client.context.clone(), + dm_target_inbox_id.clone(), + Some(invalid_protected_metadata), + None, + None, + None, + ) + .unwrap(); + assert!(matches!( + validate_dm_group(&client, &invalid_type_group.load_mls_group(client.mls_provider().unwrap()).unwrap(), added_by_inbox), + Err(GroupError::Generic(msg)) if msg.contains("Invalid conversation type") + )); + + // Test case 3: Missing DmMembers + // This case is not easily testable with the current structure, as DmMembers are set in the protected metadata + + // Test case 4: Mismatched DM members + let mismatched_dm_members = build_dm_protected_metadata_extension( + creator_inbox_id.clone(), + "wrong_inbox_id".to_string(), + ) + .unwrap(); + let mismatched_dm_members_group = MlsGroup::create_test_dm_group( + client.context.clone(), + dm_target_inbox_id.clone(), + Some(mismatched_dm_members), + None, + None, + None, + ) + .unwrap(); + assert!(matches!( + validate_dm_group(&client, &mismatched_dm_members_group.load_mls_group(client.mls_provider().unwrap()).unwrap(), added_by_inbox), + Err(GroupError::Generic(msg)) if msg.contains("DM members do not match expected inboxes") + )); + + // Test case 5: Non-empty admin list + let non_empty_admin_list = build_mutable_metadata_extension_default( + creator_inbox_id.clone(), + GroupMetadataOptions::default(), + ) + .unwrap(); + let non_empty_admin_list_group = MlsGroup::create_test_dm_group( + client.context.clone(), + dm_target_inbox_id.clone(), + None, + Some(non_empty_admin_list), + None, + None, + ) + .unwrap(); + assert!(matches!( + validate_dm_group(&client, &non_empty_admin_list_group.load_mls_group(client.mls_provider().unwrap()).unwrap(), added_by_inbox), + Err(GroupError::Generic(msg)) if msg.contains("DM group must have empty admin and super admin lists") + )); + + // Test case 6: Non-empty super admin list + // Similar to test case 5, but with super_admin_list + + // Test case 7: Invalid permissions + let invalid_permissions = PolicySet::default(); + let invalid_permissions_group = MlsGroup::create_test_dm_group( + client.context.clone(), + dm_target_inbox_id.clone(), + None, + None, + None, + Some(invalid_permissions), + ) + .unwrap(); + assert!(matches!( + validate_dm_group( + &client, + &invalid_permissions_group.load_mls_group(client.mls_provider().unwrap()).unwrap(), + added_by_inbox + ), + Err(GroupError::Generic(msg)) if msg.contains("Invalid permissions for DM group") + )); + } } From 0d29fb006249218e5690b7463f19a2f8abcfd039 Mon Sep 17 00:00:00 2001 From: cameronvoell Date: Fri, 20 Sep 2024 22:21:22 -0700 Subject: [PATCH 04/11] fixes after merge --- xmtp_mls/src/groups/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xmtp_mls/src/groups/mod.rs b/xmtp_mls/src/groups/mod.rs index 0624a52d6..f60f37a8d 100644 --- a/xmtp_mls/src/groups/mod.rs +++ b/xmtp_mls/src/groups/mod.rs @@ -3191,7 +3191,7 @@ mod tests { .await; assert!(result.is_err()); amal_dm.sync(&amal).await.unwrap(); - let members = amal_dm.members().unwrap(); + let members = amal_dm.members(&amal).await.unwrap(); assert_eq!(members.len(), 1); // Amal can add bola @@ -3200,7 +3200,7 @@ mod tests { .await .unwrap(); amal_dm.sync(&amal).await.unwrap(); - let members = amal_dm.members().unwrap(); + let members = amal_dm.members(&amal).await.unwrap(); assert_eq!(members.len(), 2); // Bola can message amal @@ -3222,7 +3222,7 @@ mod tests { .await; assert!(result.is_err()); amal_dm.sync(&amal).await.unwrap(); - let members = amal_dm.members().unwrap(); + let members = amal_dm.members(&amal).await.unwrap(); assert_eq!(members.len(), 2); // Neither Amal nor Bola is an admin or super admin From 76a8d46f513b088169a8670a4357b210ea5f1492 Mon Sep 17 00:00:00 2001 From: Cameron Voell <1103838+cameronvoell@users.noreply.github.com> Date: Fri, 20 Sep 2024 23:39:53 -0700 Subject: [PATCH 05/11] DM updates - default to not displaying dm groups (#1046) * bindings create_dm function * find groups by default does not include dm groups * fmt fix * dont execute callbacks when dm group welcomes are streamed * Update bindings_ffi/src/mls.rs Co-authored-by: Andrew Plaza * fixed bad merge * filter dms in stream_conversations * surface include_dm_groups in bindings list function more clearly --------- Co-authored-by: cameronvoell Co-authored-by: Andrew Plaza --- bindings_ffi/src/mls.rs | 79 ++++++++-- bindings_node/src/conversations.rs | 22 +-- examples/cli/cli-client.rs | 3 +- .../down.sql | 3 + .../up.sql | 3 + xmtp_mls/src/client.rs | 65 +++++++-- xmtp_mls/src/groups/group_metadata.rs | 2 + xmtp_mls/src/groups/group_mutable_metadata.rs | 2 +- xmtp_mls/src/groups/message_history.rs | 8 +- xmtp_mls/src/groups/mod.rs | 77 +++++----- xmtp_mls/src/storage/encrypted_store/group.rs | 49 ++++++- .../storage/encrypted_store/group_intent.rs | 1 + xmtp_mls/src/storage/encrypted_store/mod.rs | 2 + .../src/storage/encrypted_store/schema.rs | 1 + xmtp_mls/src/subscriptions.rs | 137 +++++++++++++++--- 15 files changed, 358 insertions(+), 96 deletions(-) create mode 100644 xmtp_mls/migrations/2024-09-09-231735_create_dm_inbox_id/down.sql create mode 100644 xmtp_mls/migrations/2024-09-09-231735_create_dm_inbox_id/up.sql diff --git a/bindings_ffi/src/mls.rs b/bindings_ffi/src/mls.rs index 5deb0291f..53c8e1297 100644 --- a/bindings_ffi/src/mls.rs +++ b/bindings_ffi/src/mls.rs @@ -16,6 +16,7 @@ use xmtp_id::{ associations::{builder::SignatureRequest, generate_inbox_id as xmtp_id_generate_inbox_id}, InboxId, }; +use xmtp_mls::client::FindGroupParams; use xmtp_mls::groups::group_mutable_metadata::MetadataField; use xmtp_mls::groups::group_permissions::BasePolicies; use xmtp_mls::groups::group_permissions::GroupMutablePermissionsError; @@ -763,6 +764,20 @@ impl FfiConversations { Ok(out) } + pub async fn create_dm(&self, account_address: String) -> Result, GenericError> { + log::info!("creating dm with target address: {}", account_address); + + let convo = self.inner_client.create_dm(account_address).await?; + + let out = Arc::new(FfiGroup { + inner_client: self.inner_client.clone(), + group_id: convo.group_id, + created_at_ns: convo.created_at_ns, + }); + + Ok(out) + } + pub async fn process_streamed_welcome_message( &self, envelope_bytes: Vec, @@ -787,7 +802,16 @@ impl FfiConversations { pub async fn sync_all_groups(&self) -> Result { let inner = self.inner_client.as_ref(); - let groups = inner.find_groups(None, None, None, None)?; + let groups = inner.find_groups(FindGroupParams { + include_dm_groups: true, + ..FindGroupParams::default() + })?; + + log::info!( + "groups for client inbox id {:?}: {:?}", + self.inner_client.inbox_id(), + groups.len() + ); let num_groups_synced: usize = inner.sync_all_groups(groups).await?; // Uniffi does not work with usize, so we need to convert to u32 @@ -807,12 +831,13 @@ impl FfiConversations { ) -> Result>, GenericError> { let inner = self.inner_client.as_ref(); let convo_list: Vec> = inner - .find_groups( - None, - opts.created_after_ns, - opts.created_before_ns, - opts.limit, - )? + .find_groups(FindGroupParams { + allowed_states: None, + created_after_ns: opts.created_after_ns, + created_before_ns: opts.created_before_ns, + limit: opts.limit, + include_dm_groups: false, + })? .into_iter() .map(|group| { Arc::new(FfiGroup { @@ -828,14 +853,17 @@ impl FfiConversations { pub async fn stream(&self, callback: Box) -> FfiStreamCloser { let client = self.inner_client.clone(); - let handle = - RustXmtpClient::stream_conversations_with_callback(client.clone(), move |convo| { + let handle = RustXmtpClient::stream_conversations_with_callback( + client.clone(), + move |convo| { callback.on_conversation(Arc::new(FfiGroup { inner_client: client.clone(), group_id: convo.group_id, created_at_ns: convo.created_at_ns, })) - }); + }, + false, + ); FfiStreamCloser::new(handle) } @@ -3683,6 +3711,37 @@ mod tests { ); } + #[tokio::test(flavor = "multi_thread", worker_threads = 5)] + async fn test_dms_sync_but_do_not_list() { + let alix = new_test_client().await; + let bola = new_test_client().await; + + let alix_conversations = alix.conversations(); + let bola_conversations = bola.conversations(); + + let _alix_group = alix_conversations + .create_dm(bola.account_address.clone()) + .await + .unwrap(); + let alix_num_sync = alix_conversations.sync_all_groups().await.unwrap(); + bola_conversations.sync().await.unwrap(); + let bola_num_sync = bola_conversations.sync_all_groups().await.unwrap(); + assert_eq!(alix_num_sync, 1); + assert_eq!(bola_num_sync, 1); + + let alix_groups = alix_conversations + .list(FfiListConversationsOptions::default()) + .await + .unwrap(); + assert_eq!(alix_groups.len(), 0); + + let bola_groups = bola_conversations + .list(FfiListConversationsOptions::default()) + .await + .unwrap(); + assert_eq!(bola_groups.len(), 0); + } + #[tokio::test(flavor = "multi_thread", worker_threads = 5)] async fn test_set_and_get_group_consent() { let alix = new_test_client().await; diff --git a/bindings_node/src/conversations.rs b/bindings_node/src/conversations.rs index 3928c36f0..ed39f37fa 100644 --- a/bindings_node/src/conversations.rs +++ b/bindings_node/src/conversations.rs @@ -6,6 +6,7 @@ use napi::bindgen_prelude::{Error, Result, Uint8Array}; use napi::threadsafe_function::{ErrorStrategy, ThreadsafeFunction, ThreadsafeFunctionCallMode}; use napi::JsFunction; use napi_derive::napi; +use xmtp_mls::client::FindGroupParams; use xmtp_mls::groups::{GroupMetadataOptions, PreconfiguredPolicies}; use crate::messages::NapiMessage; @@ -171,12 +172,12 @@ impl NapiConversations { }; let convo_list: Vec = self .inner_client - .find_groups( - None, - opts.created_after_ns, - opts.created_before_ns, - opts.limit, - ) + .find_groups(FindGroupParams { + created_after_ns: opts.created_after_ns, + created_before_ns: opts.created_before_ns, + limit: opts.limit, + ..FindGroupParams::default() + }) .map_err(|e| Error::from_reason(format!("{}", e)))? .into_iter() .map(|group| { @@ -196,8 +197,9 @@ impl NapiConversations { let tsfn: ThreadsafeFunction = callback.create_threadsafe_function(0, |ctx| Ok(vec![ctx.value]))?; let client = self.inner_client.clone(); - let stream_closer = - RustXmtpClient::stream_conversations_with_callback(client.clone(), move |convo| { + let stream_closer = RustXmtpClient::stream_conversations_with_callback( + client.clone(), + move |convo| { tsfn.call( Ok(NapiGroup::new( client.clone(), @@ -206,7 +208,9 @@ impl NapiConversations { )), ThreadsafeFunctionCallMode::Blocking, ); - }); + }, + false, + ); Ok(NapiStreamCloser::new(stream_closer)) } diff --git a/examples/cli/cli-client.rs b/examples/cli/cli-client.rs index 6ede48fa3..9125e2ff6 100755 --- a/examples/cli/cli-client.rs +++ b/examples/cli/cli-client.rs @@ -19,6 +19,7 @@ use futures::future::join_all; use kv_log_macro::{error, info}; use prost::Message; use xmtp_id::associations::unverified::{UnverifiedRecoverableEcdsaSignature, UnverifiedSignature}; +use xmtp_mls::client::FindGroupParams; use xmtp_mls::groups::message_history::MessageHistoryContent; use xmtp_mls::storage::group_message::GroupMessageKind; @@ -209,7 +210,7 @@ async fn main() { // recv(&client).await.unwrap(); let group_list = client - .find_groups(None, None, None, None) + .find_groups(FindGroupParams::default()) .expect("failed to list groups"); for group in group_list.iter() { group.sync(&client).await.expect("error syncing group"); diff --git a/xmtp_mls/migrations/2024-09-09-231735_create_dm_inbox_id/down.sql b/xmtp_mls/migrations/2024-09-09-231735_create_dm_inbox_id/down.sql new file mode 100644 index 000000000..2dbbf5787 --- /dev/null +++ b/xmtp_mls/migrations/2024-09-09-231735_create_dm_inbox_id/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE groups DROP COLUMN dm_inbox_id; +DROP INDEX idx_dm_target; diff --git a/xmtp_mls/migrations/2024-09-09-231735_create_dm_inbox_id/up.sql b/xmtp_mls/migrations/2024-09-09-231735_create_dm_inbox_id/up.sql new file mode 100644 index 000000000..6614f371a --- /dev/null +++ b/xmtp_mls/migrations/2024-09-09-231735_create_dm_inbox_id/up.sql @@ -0,0 +1,3 @@ +-- Your SQL goes here +ALTER TABLE groups ADD COLUMN dm_inbox_id text; +CREATE INDEX idx_dm_target ON groups(dm_inbox_id); diff --git a/xmtp_mls/src/client.rs b/xmtp_mls/src/client.rs index 47d742584..a5982cb26 100644 --- a/xmtp_mls/src/client.rs +++ b/xmtp_mls/src/client.rs @@ -218,6 +218,15 @@ impl From<&str> for ClientError { } } +#[derive(Debug, Default)] +pub struct FindGroupParams { + pub allowed_states: Option>, + pub created_after_ns: Option, + pub created_before_ns: Option, + pub limit: Option, + pub include_dm_groups: bool, +} + /// Clients manage access to the network, identity, and data store #[derive(Debug)] pub struct Client { @@ -496,15 +505,42 @@ where } /// Create a new Direct Message with the default settings - pub fn create_dm(&self, dm_target_inbox_id: InboxId) -> Result { + pub async fn create_dm(&self, account_address: String) -> Result { + log::info!("creating dm with address: {}", account_address); + + let inbox_id = match self + .find_inbox_id_from_address(account_address.clone()) + .await? + { + Some(id) => id, + None => { + return Err(ClientError::Storage(StorageError::NotFound(format!( + "inbox id for address {} not found", + account_address + )))) + } + }; + + self.create_dm_by_inbox_id(inbox_id).await + } + + /// Create a new Direct Message with the default settings + pub async fn create_dm_by_inbox_id( + &self, + dm_target_inbox_id: InboxId, + ) -> Result { log::info!("creating dm with {}", dm_target_inbox_id); let group = MlsGroup::create_dm_and_insert( self.context.clone(), GroupMembershipState::Allowed, - dm_target_inbox_id, + dm_target_inbox_id.clone(), )?; + group + .add_members_by_inbox_id(self, vec![dm_target_inbox_id]) + .await?; + // notify any streams of the new group let _ = self.local_events.send(LocalEvents::NewGroup(group.clone())); @@ -558,17 +594,17 @@ where /// - created_after_ns: only return groups created after the given timestamp (in nanoseconds) /// - created_before_ns: only return groups created before the given timestamp (in nanoseconds) /// - limit: only return the first `limit` groups - pub fn find_groups( - &self, - allowed_states: Option>, - created_after_ns: Option, - created_before_ns: Option, - limit: Option, - ) -> Result, ClientError> { + pub fn find_groups(&self, params: FindGroupParams) -> Result, ClientError> { Ok(self .store() .conn()? - .find_groups(allowed_states, created_after_ns, created_before_ns, limit)? + .find_groups( + params.allowed_states, + params.created_after_ns, + params.created_before_ns, + params.limit, + params.include_dm_groups, + )? .into_iter() .map(|stored_group| { MlsGroup::new( @@ -870,6 +906,7 @@ mod tests { use crate::{ builder::ClientBuilder, + client::FindGroupParams, groups::GroupMetadataOptions, hpke::{decrypt_welcome, encrypt_welcome}, identity::serialize_key_package_hash_ref, @@ -971,7 +1008,7 @@ mod tests { .create_group(None, GroupMetadataOptions::default()) .unwrap(); - let groups = client.find_groups(None, None, None, None).unwrap(); + let groups = client.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(groups.len(), 2); assert_eq!(groups[0].group_id, group_1.group_id); assert_eq!(groups[1].group_id, group_2.group_id); @@ -1037,7 +1074,7 @@ mod tests { let bob_received_groups = bo.sync_welcomes().await.unwrap(); assert_eq!(bob_received_groups.len(), 2); - let bo_groups = bo.find_groups(None, None, None, None).unwrap(); + let bo_groups = bo.find_groups(FindGroupParams::default()).unwrap(); let bo_group1 = bo.group(alix_bo_group1.clone().group_id).unwrap(); let bo_messages1 = bo_group1 .find_messages(None, None, None, None, None) @@ -1142,7 +1179,7 @@ mod tests { log::info!("Syncing bolas welcomes"); // See if Bola can see that they were added to the group bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group = bola_groups.first().unwrap(); log::info!("Syncing bolas messages"); @@ -1275,7 +1312,7 @@ mod tests { bo.sync_welcomes().await.unwrap(); // Bo should have two groups now - let bo_groups = bo.find_groups(None, None, None, None).unwrap(); + let bo_groups = bo.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bo_groups.len(), 2); // Bo's original key should be deleted diff --git a/xmtp_mls/src/groups/group_metadata.rs b/xmtp_mls/src/groups/group_metadata.rs index b274df3f1..d80ea93ec 100644 --- a/xmtp_mls/src/groups/group_metadata.rs +++ b/xmtp_mls/src/groups/group_metadata.rs @@ -17,6 +17,8 @@ pub enum GroupMetadataError { InvalidConversationType, #[error("missing extension")] MissingExtension, + #[error("invalid dm members")] + InvalidDmMembers, #[error("missing a dm member")] MissingDmMember, } diff --git a/xmtp_mls/src/groups/group_mutable_metadata.rs b/xmtp_mls/src/groups/group_mutable_metadata.rs index b97c14c0e..13a91aa42 100644 --- a/xmtp_mls/src/groups/group_mutable_metadata.rs +++ b/xmtp_mls/src/groups/group_mutable_metadata.rs @@ -114,7 +114,7 @@ impl GroupMutableMetadata { } // Admin / super admin is not needed for a DM - pub fn new_dm_default(_creator_inbox_id: String, _dm_target_inbox_id: String) -> Self { + pub fn new_dm_default(_creator_inbox_id: String, _dm_target_inbox_id: &str) -> Self { let mut attributes = HashMap::new(); // TODO: would it be helpful to incorporate the dm inbox ids in the name or description? attributes.insert( diff --git a/xmtp_mls/src/groups/message_history.rs b/xmtp_mls/src/groups/message_history.rs index 0f0768397..86aaca7ba 100644 --- a/xmtp_mls/src/groups/message_history.rs +++ b/xmtp_mls/src/groups/message_history.rs @@ -135,7 +135,7 @@ where pub async fn ensure_member_of_all_groups(&self, inbox_id: String) -> Result<(), GroupError> { let conn = self.store().conn()?; - let groups = conn.find_groups(None, None, None, None)?; + let groups = conn.find_groups(None, None, None, None, false)?; for group in groups { let group = self.group(group.id)?; Box::pin(group.add_members_by_inbox_id(self, vec![inbox_id.clone()])).await?; @@ -384,7 +384,7 @@ where self.sync_welcomes().await?; let conn = self.store().conn()?; - let groups = conn.find_groups(None, None, None, None)?; + let groups = conn.find_groups(None, None, None, None, false)?; for crate::storage::group::StoredGroup { id, .. } in groups.into_iter() { let group = self.group(id)?; Box::pin(group.sync(self)).await?; @@ -502,14 +502,14 @@ where async fn prepare_groups_to_sync(&self) -> Result, MessageHistoryError> { let conn = self.store().conn()?; - Ok(conn.find_groups(None, None, None, None)?) + Ok(conn.find_groups(None, None, None, None, false)?) } async fn prepare_messages_to_sync( &self, ) -> Result, MessageHistoryError> { let conn = self.store().conn()?; - let groups = conn.find_groups(None, None, None, None)?; + let groups = conn.find_groups(None, None, None, None, false)?; let mut all_messages: Vec = vec![]; for StoredGroup { id, .. } in groups.into_iter() { diff --git a/xmtp_mls/src/groups/mod.rs b/xmtp_mls/src/groups/mod.rs index f60f37a8d..61cea7a98 100644 --- a/xmtp_mls/src/groups/mod.rs +++ b/xmtp_mls/src/groups/mod.rs @@ -324,6 +324,7 @@ impl MlsGroup { now_ns(), membership_state, context.inbox_id(), + None, ); stored_group.store(provider.conn_ref())?; @@ -345,7 +346,7 @@ impl MlsGroup { let protected_metadata = build_dm_protected_metadata_extension(context.inbox_id(), dm_target_inbox_id.clone())?; let mutable_metadata = - build_dm_mutable_metadata_extension_default(context.inbox_id(), dm_target_inbox_id)?; + build_dm_mutable_metadata_extension_default(context.inbox_id(), &dm_target_inbox_id)?; let group_membership = build_starting_group_membership_extension(context.inbox_id(), 0); let mutable_permissions = PolicySet::new_dm(); let mutable_permission_extension = @@ -373,6 +374,7 @@ impl MlsGroup { now_ns(), membership_state, context.inbox_id(), + Some(dm_target_inbox_id), ); stored_group.store(provider.conn_ref())?; @@ -398,6 +400,16 @@ impl MlsGroup { let mls_group = mls_welcome.into_group(provider)?; let group_id = mls_group.group_id().to_vec(); let metadata = extract_group_metadata(&mls_group)?; + let dm_members = metadata.dm_members; + let dm_inbox_id = if let Some(dm_members) = &dm_members { + if dm_members.member_one_inbox_id == client.inbox_id() { + Some(dm_members.member_two_inbox_id.clone()) + } else { + Some(dm_members.member_one_inbox_id.clone()) + } + } else { + None + }; let group_type = metadata.conversation_type; let to_store = match group_type { @@ -408,6 +420,7 @@ impl MlsGroup { added_by_inbox, welcome_id, Purpose::Conversation, + dm_inbox_id, ), ConversationType::Dm => { validate_dm_group(client, &mls_group, &added_by_inbox)?; @@ -418,6 +431,7 @@ impl MlsGroup { added_by_inbox, welcome_id, Purpose::Conversation, + dm_inbox_id, ) } ConversationType::Sync => StoredGroup::new_from_welcome( @@ -427,6 +441,7 @@ impl MlsGroup { added_by_inbox, welcome_id, Purpose::Sync, + dm_inbox_id, ), }; @@ -1096,11 +1111,8 @@ impl MlsGroup { .unwrap() }); let mutable_metadata = custom_mutable_metadata.unwrap_or_else(|| { - build_dm_mutable_metadata_extension_default( - context.inbox_id(), - dm_target_inbox_id.clone(), - ) - .unwrap() + build_dm_mutable_metadata_extension_default(context.inbox_id(), &dm_target_inbox_id) + .unwrap() }); let group_membership = custom_group_membership .unwrap_or_else(|| build_starting_group_membership_extension(context.inbox_id(), 0)); @@ -1131,6 +1143,7 @@ impl MlsGroup { now_ns(), GroupMembershipState::Allowed, // Use Allowed as default for tests context.inbox_id(), + Some(dm_target_inbox_id), ); stored_group.store(provider.conn_ref())?; @@ -1212,7 +1225,7 @@ pub fn build_mutable_metadata_extension_default( pub fn build_dm_mutable_metadata_extension_default( creator_inbox_id: String, - dm_target_inbox_id: String, + dm_target_inbox_id: &str, ) -> Result { let mutable_metadata: Vec = GroupMutableMetadata::new_dm_default(creator_inbox_id, dm_target_inbox_id).try_into()?; @@ -1525,7 +1538,7 @@ mod tests { use crate::{ assert_err, assert_logged, builder::ClientBuilder, - client::MessageProcessingError, + client::{FindGroupParams, MessageProcessingError}, codecs::{group_updated::GroupUpdatedCodec, ContentCodec}, groups::{ build_dm_protected_metadata_extension, build_group_membership_extension, @@ -1559,7 +1572,7 @@ mod tests { ApiClient: XmtpApi, { client.sync_welcomes().await.unwrap(); - let mut groups = client.find_groups(None, None, None, None).unwrap(); + let mut groups = client.find_groups(FindGroupParams::default()).unwrap(); groups.remove(0) } @@ -1871,7 +1884,7 @@ mod tests { // Bo should not be able to actually read this group bo.sync_welcomes().await.unwrap(); - let groups = bo.find_groups(None, None, None, None).unwrap(); + let groups = bo.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(groups.len(), 0); assert_logged!("failed to create group from welcome", 1); } @@ -1999,7 +2012,7 @@ mod tests { .expect("send message"); bola_client.sync_welcomes().await.unwrap(); - let bola_groups = bola_client.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola_client.find_groups(FindGroupParams::default()).unwrap(); let bola_group = bola_groups.first().unwrap(); bola_group.sync(&bola_client).await.unwrap(); let bola_messages = bola_group @@ -2352,7 +2365,7 @@ mod tests { .await .unwrap(); bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); @@ -2520,7 +2533,7 @@ mod tests { .await .unwrap(); bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); @@ -2599,7 +2612,7 @@ mod tests { .await .unwrap(); bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); @@ -2615,7 +2628,7 @@ mod tests { // Verify that bola can not add caro because they are not an admin bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group: &MlsGroup = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); @@ -2679,7 +2692,7 @@ mod tests { // Verify that bola can not add charlie because they are not an admin bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group: &MlsGroup = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); @@ -2707,7 +2720,7 @@ mod tests { .await .unwrap(); bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); @@ -2723,7 +2736,7 @@ mod tests { // Verify that bola can not add caro as an admin because they are not a super admin bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group: &MlsGroup = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); @@ -2970,7 +2983,7 @@ mod tests { // Step 3: Verify that Bola can update the group name, and amal sees the update bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); let bola_group: &MlsGroup = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); bola_group @@ -3035,7 +3048,7 @@ mod tests { // Step 3: Bola attemps to add Caro, but fails because group is admin only let caro = ClientBuilder::new_test_client(&generate_local_wallet()).await; bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); let bola_group: &MlsGroup = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); let result = bola_group @@ -3179,33 +3192,31 @@ mod tests { let caro = ClientBuilder::new_test_client(&generate_local_wallet()).await; // Amal creates a dm group targetting bola - let amal_dm: MlsGroup = amal.create_dm(bola.inbox_id()).unwrap(); + let amal_dm: MlsGroup = amal.create_dm_by_inbox_id(bola.inbox_id()).await.unwrap(); // Amal can not add caro to the dm group let result = amal_dm - .add_members_by_inbox_id(&amal, vec![bola.inbox_id(), caro.inbox_id()]) + .add_members_by_inbox_id(&amal, vec![caro.inbox_id()]) .await; assert!(result.is_err()); + + // Bola is already a member let result = amal_dm - .add_members_by_inbox_id(&amal, vec![caro.inbox_id()]) + .add_members_by_inbox_id(&amal, vec![bola.inbox_id(), caro.inbox_id()]) .await; assert!(result.is_err()); amal_dm.sync(&amal).await.unwrap(); let members = amal_dm.members(&amal).await.unwrap(); - assert_eq!(members.len(), 1); - - // Amal can add bola - amal_dm - .add_members_by_inbox_id(&amal, vec![bola.inbox_id()]) - .await - .unwrap(); - amal_dm.sync(&amal).await.unwrap(); - let members = amal_dm.members(&amal).await.unwrap(); assert_eq!(members.len(), 2); // Bola can message amal let _ = bola.sync_welcomes().await; - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola + .find_groups(FindGroupParams { + include_dm_groups: true, + ..FindGroupParams::default() + }) + .unwrap(); let bola_dm: &MlsGroup = bola_groups.first().unwrap(); bola_dm.send_message(b"test one", &bola).await.unwrap(); diff --git a/xmtp_mls/src/storage/encrypted_store/group.rs b/xmtp_mls/src/storage/encrypted_store/group.rs index d5516e7ec..b68e61e11 100644 --- a/xmtp_mls/src/storage/encrypted_store/group.rs +++ b/xmtp_mls/src/storage/encrypted_store/group.rs @@ -39,6 +39,8 @@ pub struct StoredGroup { pub added_by_inbox_id: String, /// The sequence id of the welcome message pub welcome_id: Option, + /// The inbox_id of the DM target + pub dm_inbox_id: Option, } impl_fetch!(StoredGroup, groups, Vec); @@ -53,6 +55,7 @@ impl StoredGroup { added_by_inbox_id: String, welcome_id: i64, purpose: Purpose, + dm_inbox_id: Option, ) -> Self { Self { id, @@ -62,6 +65,7 @@ impl StoredGroup { purpose, added_by_inbox_id, welcome_id: Some(welcome_id), + dm_inbox_id, } } @@ -71,6 +75,7 @@ impl StoredGroup { created_at_ns: i64, membership_state: GroupMembershipState, added_by_inbox_id: String, + dm_inbox_id: Option, ) -> Self { Self { id, @@ -80,6 +85,7 @@ impl StoredGroup { purpose: Purpose::Conversation, added_by_inbox_id, welcome_id: None, + dm_inbox_id, } } @@ -98,6 +104,7 @@ impl StoredGroup { purpose: Purpose::Sync, added_by_inbox_id: "".into(), welcome_id: None, + dm_inbox_id: None, } } } @@ -110,6 +117,7 @@ impl DbConnection { created_after_ns: Option, created_before_ns: Option, limit: Option, + include_dm_groups: bool, ) -> Result, StorageError> { let mut query = dsl::groups.order(dsl::created_at_ns.asc()).into_boxed(); @@ -129,6 +137,10 @@ impl DbConnection { query = query.limit(limit); } + if !include_dm_groups { + query = query.filter(dsl::dm_inbox_id.is_null()); + } + query = query.filter(dsl::purpose.eq(Purpose::Conversation)); Ok(self.raw_query(|conn| query.load(conn))?) @@ -331,6 +343,22 @@ pub(crate) mod tests { created_at_ns, membership_state, "placeholder_address".to_string(), + None, + ) + } + + /// Generate a test dm group + pub fn generate_dm(state: Option) -> StoredGroup { + let id = rand_vec(); + let created_at_ns = now_ns(); + let membership_state = state.unwrap_or(GroupMembershipState::Allowed); + let dm_inbox_id = Some("placeholder_inbox_id".to_string()); + StoredGroup::new( + id, + created_at_ns, + membership_state, + "placeholder_address".to_string(), + dm_inbox_id, ) } @@ -392,23 +420,31 @@ pub(crate) mod tests { test_group_1.store(conn).unwrap(); let test_group_2 = generate_group(Some(GroupMembershipState::Allowed)); test_group_2.store(conn).unwrap(); + let test_group_3 = generate_dm(Some(GroupMembershipState::Allowed)); + test_group_3.store(conn).unwrap(); - let all_results = conn.find_groups(None, None, None, None).unwrap(); + let all_results = conn.find_groups(None, None, None, None, false).unwrap(); assert_eq!(all_results.len(), 2); let pending_results = conn - .find_groups(Some(vec![GroupMembershipState::Pending]), None, None, None) + .find_groups( + Some(vec![GroupMembershipState::Pending]), + None, + None, + None, + false, + ) .unwrap(); assert_eq!(pending_results[0].id, test_group_1.id); assert_eq!(pending_results.len(), 1); // Offset and limit - let results_with_limit = conn.find_groups(None, None, None, Some(1)).unwrap(); + let results_with_limit = conn.find_groups(None, None, None, Some(1), false).unwrap(); assert_eq!(results_with_limit.len(), 1); assert_eq!(results_with_limit[0].id, test_group_1.id); let results_with_created_at_ns_after = conn - .find_groups(None, Some(test_group_1.created_at_ns), None, Some(1)) + .find_groups(None, Some(test_group_1.created_at_ns), None, Some(1), false) .unwrap(); assert_eq!(results_with_created_at_ns_after.len(), 1); assert_eq!(results_with_created_at_ns_after[0].id, test_group_2.id); @@ -417,7 +453,10 @@ pub(crate) mod tests { let synced_groups = conn.find_sync_groups().unwrap(); assert_eq!(synced_groups.len(), 0); - // test that ONLY normal groups show up. + // test that dm groups are included + let dm_results = conn.find_groups(None, None, None, None, true).unwrap(); + assert_eq!(dm_results.len(), 3); + assert_eq!(dm_results[2].id, test_group_3.id); }) } diff --git a/xmtp_mls/src/storage/encrypted_store/group_intent.rs b/xmtp_mls/src/storage/encrypted_store/group_intent.rs index 4ff7615e7..b5104f9ac 100644 --- a/xmtp_mls/src/storage/encrypted_store/group_intent.rs +++ b/xmtp_mls/src/storage/encrypted_store/group_intent.rs @@ -404,6 +404,7 @@ mod tests { 100, GroupMembershipState::Allowed, "placeholder_address".to_string(), + None, ); group.store(conn).unwrap(); } diff --git a/xmtp_mls/src/storage/encrypted_store/mod.rs b/xmtp_mls/src/storage/encrypted_store/mod.rs index 687ba7631..6b1ab0731 100644 --- a/xmtp_mls/src/storage/encrypted_store/mod.rs +++ b/xmtp_mls/src/storage/encrypted_store/mod.rs @@ -679,6 +679,7 @@ mod tests { 0, GroupMembershipState::Allowed, "goodbye".to_string(), + None, ); group.store(connection)?; Ok(()) @@ -730,6 +731,7 @@ mod tests { 0, GroupMembershipState::Allowed, "goodbye".to_string(), + None, ); group.store(conn1).unwrap(); diff --git a/xmtp_mls/src/storage/encrypted_store/schema.rs b/xmtp_mls/src/storage/encrypted_store/schema.rs index 7d835a5b9..7266406cd 100644 --- a/xmtp_mls/src/storage/encrypted_store/schema.rs +++ b/xmtp_mls/src/storage/encrypted_store/schema.rs @@ -53,6 +53,7 @@ diesel::table! { purpose -> Integer, added_by_inbox_id -> Text, welcome_id -> Nullable, + dm_inbox_id -> Nullable, } } diff --git a/xmtp_mls/src/subscriptions.rs b/xmtp_mls/src/subscriptions.rs index 2bb6f8cc4..c69bfdaac 100644 --- a/xmtp_mls/src/subscriptions.rs +++ b/xmtp_mls/src/subscriptions.rs @@ -1,5 +1,6 @@ use std::{collections::HashMap, sync::Arc}; +use crate::xmtp_openmls_provider::XmtpOpenMlsProvider; use futures::{FutureExt, Stream, StreamExt}; use prost::Message; use tokio::{sync::oneshot, task::JoinHandle}; @@ -9,7 +10,7 @@ use xmtp_proto::xmtp::mls::api::v1::WelcomeMessage; use crate::{ api::GroupFilter, client::{extract_welcome_message, ClientError}, - groups::{extract_group_id, GroupError, MlsGroup}, + groups::{extract_group_id, group_metadata::ConversationType, GroupError, MlsGroup}, retry::Retry, retry_async, storage::{group::StoredGroup, group_message::StoredGroupMessage}, @@ -130,18 +131,42 @@ where pub async fn stream_conversations( &self, + include_dm: bool, ) -> Result + '_, ClientError> { + let provider = Arc::new(self.context.mls_provider()?); + let event_queue = tokio_stream::wrappers::BroadcastStream::new(self.local_events.subscribe()); - let event_queue = event_queue.filter_map(|event| async move { - match event { - Ok(LocalEvents::NewGroup(g)) => Some(g), - Err(BroadcastStreamRecvError::Lagged(missed)) => { - log::warn!("Missed {missed} messages due to local event queue lagging"); + // Helper function for filtering Dm groups + let filter_group = move |group: MlsGroup, provider: Arc| async move { + match group.metadata(provider.as_ref()) { + Ok(metadata) => { + if include_dm || metadata.conversation_type != ConversationType::Dm { + Some(group) + } else { + None + } + } + Err(err) => { + log::error!("Error processing group metadata: {:?}", err); None } } + }; + + let event_provider = Arc::clone(&provider); + let event_queue = event_queue.filter_map(move |event| { + let provider = Arc::clone(&event_provider); + async move { + match event { + Ok(LocalEvents::NewGroup(group)) => filter_group(group, provider).await, + Err(BroadcastStreamRecvError::Lagged(missed)) => { + log::warn!("Missed {missed} messages due to local event queue lagging"); + None + } + } + } }); let installation_key = self.installation_public_key(); @@ -152,17 +177,24 @@ where .subscribe_welcome_messages(installation_key, Some(id_cursor)) .await?; + let stream_provider = Arc::clone(&provider); let stream = subscription .map(|welcome| async { log::info!("Received conversation streaming payload"); self.process_streamed_welcome(welcome?).await }) - .filter_map(|res| async { - match res.await { - Ok(group) => Some(group), - Err(err) => { - log::error!("Error processing stream entry for conversation: {:?}", err); - None + .filter_map(move |res| { + let provider = Arc::clone(&stream_provider); + async move { + match res.await { + Ok(group) => filter_group(group, provider).await, + Err(err) => { + log::error!( + "Error processing stream entry for conversation: {:?}", + err + ); + None + } } } }); @@ -234,11 +266,12 @@ where pub fn stream_conversations_with_callback( client: Arc>, mut convo_callback: impl FnMut(MlsGroup) + Send + 'static, + include_dm: bool, ) -> StreamHandle> { let (tx, rx) = oneshot::channel(); let handle = tokio::spawn(async move { - let stream = client.stream_conversations().await?; + let stream = client.stream_conversations(include_dm).await?; futures::pin_mut!(stream); let _ = tx.send(()); while let Some(convo) = stream.next().await { @@ -287,7 +320,7 @@ where let mut group_id_to_info = self .store() .conn()? - .find_groups(None, None, None, None)? + .find_groups(None, None, None, None, false)? .into_iter() .map(Into::into) .collect::, MessagesStreamInfo>>(); @@ -298,7 +331,7 @@ where .await?; futures::pin_mut!(messages_stream); - let convo_stream = self.stream_conversations().await?; + let convo_stream = self.stream_conversations(true).await?; futures::pin_mut!(convo_stream); let mut extra_messages = Vec::new(); @@ -416,7 +449,7 @@ mod tests { let mut stream = tokio_stream::wrappers::UnboundedReceiverStream::new(rx); let bob_ptr = bob.clone(); tokio::spawn(async move { - let bob_stream = bob_ptr.stream_conversations().await.unwrap(); + let bob_stream = bob_ptr.stream_conversations(true).await.unwrap(); futures::pin_mut!(bob_stream); while let Some(item) = bob_stream.next().await { let _ = tx.send(item); @@ -726,12 +759,15 @@ mod tests { let notify = Delivery::new(None); let (notify_pointer, groups_pointer) = (notify.clone(), groups.clone()); - let closer = - Client::::stream_conversations_with_callback(alix.clone(), move |g| { + let closer = Client::::stream_conversations_with_callback( + alix.clone(), + move |g| { let mut groups = groups_pointer.lock(); groups.push(g); notify_pointer.notify_one(); - }); + }, + false, + ); alix.create_group(None, GroupMetadataOptions::default()) .unwrap(); @@ -763,4 +799,67 @@ mod tests { closer.handle.abort(); } + + #[tokio::test(flavor = "multi_thread")] + async fn test_dm_streaming() { + let alix = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); + let bo = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); + + let groups = Arc::new(Mutex::new(Vec::new())); + // Wait for 2 seconds for the group creation to be streamed + let notify = Delivery::new(Some(std::time::Duration::from_secs(1))); + let (notify_pointer, groups_pointer) = (notify.clone(), groups.clone()); + + // Start a stream with enableDm set to false + let closer = Client::::stream_conversations_with_callback( + alix.clone(), + move |g| { + let mut groups = groups_pointer.lock(); + groups.push(g); + notify_pointer.notify_one(); + }, + false, + ); + + alix.create_dm_by_inbox_id(bo.inbox_id()).await.unwrap(); + + let result = notify.wait_for_delivery().await; + assert!(result.is_err(), "Stream unexpectedly received a DM group"); + + closer.handle.abort(); + + // Start a stream with enableDm set to true + let groups = Arc::new(Mutex::new(Vec::new())); + // Wait for 2 seconds for the group creation to be streamed + let notify = Delivery::new(Some(std::time::Duration::from_secs(1))); + let (notify_pointer, groups_pointer) = (notify.clone(), groups.clone()); + let closer = Client::::stream_conversations_with_callback( + alix.clone(), + move |g| { + let mut groups = groups_pointer.lock(); + groups.push(g); + notify_pointer.notify_one(); + }, + true, + ); + + alix.create_dm_by_inbox_id(bo.inbox_id()).await.unwrap(); + notify.wait_for_delivery().await.unwrap(); + { + let grps = groups.lock(); + assert_eq!(grps.len(), 1); + } + + let dm = bo.create_dm_by_inbox_id(alix.inbox_id()).await.unwrap(); + dm.add_members_by_inbox_id(&bo, vec![alix.inbox_id()]) + .await + .unwrap(); + notify.wait_for_delivery().await.unwrap(); + { + let grps = groups.lock(); + assert_eq!(grps.len(), 2); + } + + closer.handle.abort(); + } } From 86551ea1dc09b1f26cbb02cd389ffa2daf0df0bb Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Mon, 30 Sep 2024 17:15:31 -0600 Subject: [PATCH 06/11] fix merge conflicts --- xmtp_mls/src/client.rs | 4 ++-- xmtp_mls/src/subscriptions.rs | 16 +++------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/xmtp_mls/src/client.rs b/xmtp_mls/src/client.rs index 049a795f8..9e2e5e369 100644 --- a/xmtp_mls/src/client.rs +++ b/xmtp_mls/src/client.rs @@ -506,7 +506,7 @@ where /// Create a new Direct Message with the default settings pub async fn create_dm(&self, account_address: String) -> Result { - log::info!("creating dm with address: {}", account_address); + tracing::info!("creating dm with address: {}", account_address); let inbox_id = match self .find_inbox_id_from_address(account_address.clone()) @@ -529,7 +529,7 @@ where &self, dm_target_inbox_id: InboxId, ) -> Result { - log::info!("creating dm with {}", dm_target_inbox_id); + tracing::info!("creating dm with {}", dm_target_inbox_id); let group = MlsGroup::create_dm_and_insert( self.context.clone(), diff --git a/xmtp_mls/src/subscriptions.rs b/xmtp_mls/src/subscriptions.rs index 61c9da37c..18e384ffd 100644 --- a/xmtp_mls/src/subscriptions.rs +++ b/xmtp_mls/src/subscriptions.rs @@ -150,17 +150,7 @@ where } } Err(err) => { - log::error!("Error processing group metadata: {:?}", err); - None - } - } - }; - - let event_queue = event_queue.filter_map(|event| async move { - match event { - Ok(LocalEvents::NewGroup(g)) => Some(g), - Err(BroadcastStreamRecvError::Lagged(missed)) => { - tracing::warn!("Missed {missed} messages due to local event queue lagging"); + tracing::error!("Error processing group metadata: {:?}", err); None } } @@ -173,7 +163,7 @@ where match event { Ok(LocalEvents::NewGroup(group)) => filter_group(group, provider).await, Err(BroadcastStreamRecvError::Lagged(missed)) => { - log::warn!("Missed {missed} messages due to local event queue lagging"); + tracing::warn!("Missed {missed} messages due to local event queue lagging"); None } } @@ -201,7 +191,7 @@ where match res.await { Ok(group) => filter_group(group, provider).await, Err(err) => { - log::error!( + tracing::error!( "Error processing stream entry for conversation: {:?}", err ); From e8235701316d1e382391ee905c05a8b3d7064968 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Mon, 30 Sep 2024 17:26:05 -0600 Subject: [PATCH 07/11] cargo clippy --- xmtp_mls/src/groups/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/xmtp_mls/src/groups/mod.rs b/xmtp_mls/src/groups/mod.rs index 291b6899e..9b423e5b7 100644 --- a/xmtp_mls/src/groups/mod.rs +++ b/xmtp_mls/src/groups/mod.rs @@ -1866,7 +1866,6 @@ mod tests { } #[tokio::test(flavor = "multi_thread", worker_threads = 1)] - #[traced_test] async fn test_create_from_welcome_validation() { crate::traced_test(|| async { let alix = ClientBuilder::new_test_client(&generate_local_wallet()).await; @@ -1896,7 +1895,7 @@ mod tests { // Bo should not be able to actually read this group bo.sync_welcomes().await.unwrap(); - let groups = bo.find_groups(None, None, None, None).unwrap(); + let groups = bo.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(groups.len(), 0); assert_logged!("failed to create group from welcome", 1); }); @@ -3586,7 +3585,7 @@ mod tests { .unwrap(); bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); let bola_group = bola_groups.first().unwrap(); // group consent state should default to unknown for users who did not create the group assert_eq!(bola_group.consent_state().unwrap(), ConsentState::Unknown); @@ -3605,7 +3604,7 @@ mod tests { .unwrap(); caro.sync_welcomes().await.unwrap(); - let caro_groups = caro.find_groups(None, None, None, None).unwrap(); + let caro_groups = caro.find_groups(FindGroupParams::default()).unwrap(); let caro_group = caro_groups.first().unwrap(); caro_group From afbdab50d71531919a8434b85b0c23093f68e947 Mon Sep 17 00:00:00 2001 From: Ry Racherbaumer Date: Mon, 30 Sep 2024 16:33:27 -0700 Subject: [PATCH 08/11] Remove tracing from test --- xmtp_mls/src/groups/mod.rs | 56 ++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/xmtp_mls/src/groups/mod.rs b/xmtp_mls/src/groups/mod.rs index 9b423e5b7..f3581ce75 100644 --- a/xmtp_mls/src/groups/mod.rs +++ b/xmtp_mls/src/groups/mod.rs @@ -1867,38 +1867,36 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn test_create_from_welcome_validation() { - crate::traced_test(|| async { - let alix = ClientBuilder::new_test_client(&generate_local_wallet()).await; - let bo = ClientBuilder::new_test_client(&generate_local_wallet()).await; + let alix = ClientBuilder::new_test_client(&generate_local_wallet()).await; + let bo = ClientBuilder::new_test_client(&generate_local_wallet()).await; - let alix_group: MlsGroup = alix - .create_group(None, GroupMetadataOptions::default()) - .unwrap(); - let provider = alix.mls_provider().unwrap(); - // Doctor the group membership - let mut mls_group = alix_group.load_mls_group(&provider).unwrap(); - let mut existing_extensions = mls_group.extensions().clone(); - let mut group_membership = GroupMembership::new(); - group_membership.add("foo".to_string(), 1); - existing_extensions.add_or_replace(build_group_membership_extension(&group_membership)); - mls_group - .update_group_context_extensions( - &provider, - existing_extensions.clone(), - &alix.identity().installation_keys, - ) - .unwrap(); - mls_group.merge_pending_commit(&provider).unwrap(); + let alix_group: MlsGroup = alix + .create_group(None, GroupMetadataOptions::default()) + .unwrap(); + let provider = alix.mls_provider().unwrap(); + // Doctor the group membership + let mut mls_group = alix_group.load_mls_group(&provider).unwrap(); + let mut existing_extensions = mls_group.extensions().clone(); + let mut group_membership = GroupMembership::new(); + group_membership.add("foo".to_string(), 1); + existing_extensions.add_or_replace(build_group_membership_extension(&group_membership)); + mls_group + .update_group_context_extensions( + &provider, + existing_extensions.clone(), + &alix.identity().installation_keys, + ) + .unwrap(); + mls_group.merge_pending_commit(&provider).unwrap(); - // Now add bo to the group - force_add_member(&alix, &bo, &alix_group, &mut mls_group, &provider).await; + // Now add bo to the group + force_add_member(&alix, &bo, &alix_group, &mut mls_group, &provider).await; - // Bo should not be able to actually read this group - bo.sync_welcomes().await.unwrap(); - let groups = bo.find_groups(FindGroupParams::default()).unwrap(); - assert_eq!(groups.len(), 0); - assert_logged!("failed to create group from welcome", 1); - }); + // Bo should not be able to actually read this group + bo.sync_welcomes().await.unwrap(); + let groups = bo.find_groups(FindGroupParams::default()).unwrap(); + assert_eq!(groups.len(), 0); + assert_logged!("failed to create group from welcome", 1); } #[tokio::test(flavor = "multi_thread", worker_threads = 1)] From 32014b94c7fcee10e874dad391b9570b3fa1ba92 Mon Sep 17 00:00:00 2001 From: Ry Racherbaumer Date: Mon, 30 Sep 2024 16:58:01 -0700 Subject: [PATCH 09/11] Fix test --- xmtp_mls/src/groups/mod.rs | 62 ++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/xmtp_mls/src/groups/mod.rs b/xmtp_mls/src/groups/mod.rs index f3581ce75..bf6357cfb 100644 --- a/xmtp_mls/src/groups/mod.rs +++ b/xmtp_mls/src/groups/mod.rs @@ -1865,38 +1865,40 @@ mod tests { assert!(matching_message.is_some()); } - #[tokio::test(flavor = "multi_thread", worker_threads = 1)] - async fn test_create_from_welcome_validation() { - let alix = ClientBuilder::new_test_client(&generate_local_wallet()).await; - let bo = ClientBuilder::new_test_client(&generate_local_wallet()).await; - - let alix_group: MlsGroup = alix - .create_group(None, GroupMetadataOptions::default()) - .unwrap(); - let provider = alix.mls_provider().unwrap(); - // Doctor the group membership - let mut mls_group = alix_group.load_mls_group(&provider).unwrap(); - let mut existing_extensions = mls_group.extensions().clone(); - let mut group_membership = GroupMembership::new(); - group_membership.add("foo".to_string(), 1); - existing_extensions.add_or_replace(build_group_membership_extension(&group_membership)); - mls_group - .update_group_context_extensions( - &provider, - existing_extensions.clone(), - &alix.identity().installation_keys, - ) - .unwrap(); - mls_group.merge_pending_commit(&provider).unwrap(); + #[test] + fn test_create_from_welcome_validation() { + crate::traced_test(|| async { + let alix = ClientBuilder::new_test_client(&generate_local_wallet()).await; + let bo = ClientBuilder::new_test_client(&generate_local_wallet()).await; + + let alix_group: MlsGroup = alix + .create_group(None, GroupMetadataOptions::default()) + .unwrap(); + let provider = alix.mls_provider().unwrap(); + // Doctor the group membership + let mut mls_group = alix_group.load_mls_group(&provider).unwrap(); + let mut existing_extensions = mls_group.extensions().clone(); + let mut group_membership = GroupMembership::new(); + group_membership.add("foo".to_string(), 1); + existing_extensions.add_or_replace(build_group_membership_extension(&group_membership)); + mls_group + .update_group_context_extensions( + &provider, + existing_extensions.clone(), + &alix.identity().installation_keys, + ) + .unwrap(); + mls_group.merge_pending_commit(&provider).unwrap(); - // Now add bo to the group - force_add_member(&alix, &bo, &alix_group, &mut mls_group, &provider).await; + // Now add bo to the group + force_add_member(&alix, &bo, &alix_group, &mut mls_group, &provider).await; - // Bo should not be able to actually read this group - bo.sync_welcomes().await.unwrap(); - let groups = bo.find_groups(FindGroupParams::default()).unwrap(); - assert_eq!(groups.len(), 0); - assert_logged!("failed to create group from welcome", 1); + // Bo should not be able to actually read this group + bo.sync_welcomes().await.unwrap(); + let groups = bo.find_groups(FindGroupParams::default()).unwrap(); + assert_eq!(groups.len(), 0); + assert_logged!("failed to create group from welcome", 1); + }); } #[tokio::test(flavor = "multi_thread", worker_threads = 1)] From b96026e016d95950718f8769af095cadd71598b3 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Tue, 1 Oct 2024 11:26:12 -0600 Subject: [PATCH 10/11] try and fix the tests --- xmtp_mls/src/subscriptions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmtp_mls/src/subscriptions.rs b/xmtp_mls/src/subscriptions.rs index 18e384ffd..85449af0c 100644 --- a/xmtp_mls/src/subscriptions.rs +++ b/xmtp_mls/src/subscriptions.rs @@ -837,7 +837,7 @@ mod tests { // Start a stream with enableDm set to true let groups = Arc::new(Mutex::new(Vec::new())); // Wait for 2 seconds for the group creation to be streamed - let notify = Delivery::new(Some(std::time::Duration::from_secs(1))); + let notify = Delivery::new(Some(std::time::Duration::from_secs(60))); let (notify_pointer, groups_pointer) = (notify.clone(), groups.clone()); let closer = Client::::stream_conversations_with_callback( alix.clone(), From b067ae2ac2dee95f83e65a920cd31af7c47982be Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Tue, 1 Oct 2024 11:58:51 -0600 Subject: [PATCH 11/11] fix up the test --- xmtp_mls/src/groups/group_permissions.rs | 34 ------------------------ 1 file changed, 34 deletions(-) diff --git a/xmtp_mls/src/groups/group_permissions.rs b/xmtp_mls/src/groups/group_permissions.rs index 1c188ba5d..cff50081d 100644 --- a/xmtp_mls/src/groups/group_permissions.rs +++ b/xmtp_mls/src/groups/group_permissions.rs @@ -1477,40 +1477,6 @@ mod tests { assert!(!permissions.evaluate_commit(&commit_without_creator)); } - #[test] - fn test_allow_same_member() { - let permissions = PolicySet::new( - MembershipPolicies::allow_same_member(), - MembershipPolicies::deny(), - MetadataPolicies::default_map(MetadataPolicies::deny()), - PermissionsPolicies::allow_if_actor_super_admin(), - PermissionsPolicies::allow_if_actor_super_admin(), - PermissionsPolicies::allow_if_actor_super_admin(), - ); - - let commit_with_same_member = build_validated_commit( - Some(MemberType::SameAsActor), - None, - None, - false, - false, - false, - None, - ); - assert!(permissions.evaluate_commit(&commit_with_same_member)); - - let commit_with_different_member = build_validated_commit( - Some(MemberType::Random), - None, - None, - false, - false, - false, - None, - ); - assert!(!permissions.evaluate_commit(&commit_with_different_member)); - } - /// Tests that and conditions are enforced as expected. #[test] fn test_and_condition() {