Creator automatically joins the group after creating it

This commit is contained in:
Torsten Grote
2016-10-20 12:45:56 -02:00
parent e06726b2f9
commit 4f4f1956eb
7 changed files with 178 additions and 51 deletions

View File

@@ -34,6 +34,8 @@ import org.briarproject.api.messaging.MessagingManager;
import org.briarproject.api.messaging.PrivateMessageFactory; import org.briarproject.api.messaging.PrivateMessageFactory;
import org.briarproject.api.plugins.ConnectionRegistry; import org.briarproject.api.plugins.ConnectionRegistry;
import org.briarproject.api.plugins.PluginManager; import org.briarproject.api.plugins.PluginManager;
import org.briarproject.api.privategroup.GroupMessageFactory;
import org.briarproject.api.privategroup.PrivateGroupFactory;
import org.briarproject.api.privategroup.PrivateGroupManager; import org.briarproject.api.privategroup.PrivateGroupManager;
import org.briarproject.api.privategroup.invitation.GroupInvitationManager; import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
import org.briarproject.api.settings.SettingsManager; import org.briarproject.api.settings.SettingsManager;
@@ -99,6 +101,10 @@ public interface AndroidComponent extends CoreEagerSingletons {
GroupInvitationManager groupInvitationManager(); GroupInvitationManager groupInvitationManager();
PrivateGroupFactory privateGroupFactory();
GroupMessageFactory groupMessageFactory();
ForumManager forumManager(); ForumManager forumManager();
ForumSharingManager forumSharingManager(); ForumSharingManager forumSharingManager();

View File

@@ -15,6 +15,7 @@ import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.privategroup.GroupMessage; import org.briarproject.api.privategroup.GroupMessage;
import org.briarproject.api.privategroup.GroupMessageFactory;
import org.briarproject.api.privategroup.GroupMessageHeader; import org.briarproject.api.privategroup.GroupMessageHeader;
import org.briarproject.api.privategroup.PrivateGroup; import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.privategroup.PrivateGroupManager; import org.briarproject.api.privategroup.PrivateGroupManager;
@@ -35,16 +36,19 @@ public class GroupControllerImpl extends
Logger.getLogger(GroupControllerImpl.class.getName()); Logger.getLogger(GroupControllerImpl.class.getName());
private final PrivateGroupManager privateGroupManager; private final PrivateGroupManager privateGroupManager;
private final GroupMessageFactory groupMessageFactory;
@Inject @Inject
GroupControllerImpl(@DatabaseExecutor Executor dbExecutor, GroupControllerImpl(@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager, IdentityManager identityManager, LifecycleManager lifecycleManager, IdentityManager identityManager,
@CryptoExecutor Executor cryptoExecutor, @CryptoExecutor Executor cryptoExecutor,
PrivateGroupManager privateGroupManager, EventBus eventBus, PrivateGroupManager privateGroupManager,
GroupMessageFactory groupMessageFactory, EventBus eventBus,
AndroidNotificationManager notificationManager, Clock clock) { AndroidNotificationManager notificationManager, Clock clock) {
super(dbExecutor, lifecycleManager, identityManager, cryptoExecutor, super(dbExecutor, lifecycleManager, identityManager, cryptoExecutor,
eventBus, notificationManager, clock); eventBus, notificationManager, clock);
this.privateGroupManager = privateGroupManager; this.privateGroupManager = privateGroupManager;
this.groupMessageFactory = groupMessageFactory;
} }
@Override @Override
@@ -101,8 +105,10 @@ public class GroupControllerImpl extends
@Override @Override
protected GroupMessage createLocalMessage(String body, long timestamp, protected GroupMessage createLocalMessage(String body, long timestamp,
@Nullable MessageId parentId, LocalAuthor author) { @Nullable MessageId parentId, LocalAuthor author) {
return privateGroupManager.createLocalMessage(getGroupId(), body, MessageId previousMsgId = null; // TODO
timestamp, parentId, author); return groupMessageFactory
.createGroupMessage(getGroupId(), timestamp, parentId,
author, body, previousMsgId);
} }
@Override @Override

View File

@@ -3,11 +3,19 @@ package org.briarproject.android.privategroup.creation;
import org.briarproject.android.controller.DbControllerImpl; import org.briarproject.android.controller.DbControllerImpl;
import org.briarproject.android.controller.handler.ResultExceptionHandler; import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
import org.briarproject.api.crypto.CryptoExecutor;
import org.briarproject.api.db.DatabaseExecutor; import org.briarproject.api.db.DatabaseExecutor;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.privategroup.GroupMessage;
import org.briarproject.api.privategroup.GroupMessageFactory;
import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.privategroup.PrivateGroupFactory;
import org.briarproject.api.privategroup.PrivateGroupManager; import org.briarproject.api.privategroup.PrivateGroupManager;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.system.Clock;
import java.util.Collection; import java.util.Collection;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -23,25 +31,81 @@ public class CreateGroupControllerImpl extends DbControllerImpl
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(CreateGroupControllerImpl.class.getName()); Logger.getLogger(CreateGroupControllerImpl.class.getName());
private final IdentityManager identityManager;
private final PrivateGroupFactory groupFactory;
private final GroupMessageFactory groupMessageFactory;
private final PrivateGroupManager groupManager; private final PrivateGroupManager groupManager;
private final Clock clock;
@CryptoExecutor
private final Executor cryptoExecutor;
@Inject @Inject
CreateGroupControllerImpl(@DatabaseExecutor Executor dbExecutor, CreateGroupControllerImpl(@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager, @CryptoExecutor Executor cryptoExecutor,
PrivateGroupManager groupManager) { LifecycleManager lifecycleManager, IdentityManager identityManager,
PrivateGroupFactory groupFactory,
GroupMessageFactory groupMessageFactory,
PrivateGroupManager groupManager, Clock clock) {
super(dbExecutor, lifecycleManager); super(dbExecutor, lifecycleManager);
this.identityManager = identityManager;
this.groupFactory = groupFactory;
this.groupMessageFactory = groupMessageFactory;
this.groupManager = groupManager; this.groupManager = groupManager;
this.clock = clock;
this.cryptoExecutor = cryptoExecutor;
} }
@Override @Override
public void createGroup(final String name, public void createGroup(final String name,
final ResultExceptionHandler<GroupId, DbException> handler) { final ResultExceptionHandler<GroupId, DbException> handler) {
runOnDbThread(new Runnable() {
@Override
public void run() {
try {
LocalAuthor author = identityManager.getLocalAuthor();
createGroupAndMessages(author, name, handler);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
handler.onException(e);
}
}
});
}
private void createGroupAndMessages(final LocalAuthor author,
final String name,
final ResultExceptionHandler<GroupId, DbException> handler) {
cryptoExecutor.execute(new Runnable() {
@Override
public void run() {
LOG.info("Creating group...");
PrivateGroup group =
groupFactory.createPrivateGroup(name, author);
LOG.info("Creating new member announcement...");
GroupMessage newMemberMsg = groupMessageFactory
.createNewMemberMessage(group.getId(),
clock.currentTimeMillis(), author, author);
LOG.info("Creating new join announcement...");
GroupMessage joinMsg = groupMessageFactory
.createJoinMessage(group.getId(),
newMemberMsg.getMessage().getTimestamp(),
author, newMemberMsg.getMessage().getId());
storeGroup(group, newMemberMsg, joinMsg, handler);
}
});
}
private void storeGroup(final PrivateGroup group,
final GroupMessage newMemberMsg, final GroupMessage joinMsg,
final ResultExceptionHandler<GroupId, DbException> handler) {
runOnDbThread(new Runnable() { runOnDbThread(new Runnable() {
@Override @Override
public void run() { public void run() {
LOG.info("Adding group to database..."); LOG.info("Adding group to database...");
try { try {
handler.onResult(groupManager.addPrivateGroup(name)); groupManager.addPrivateGroup(group, newMemberMsg, joinMsg);
handler.onResult(group.getId());
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);

View File

@@ -44,6 +44,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
Logger.getLogger(ThreadListControllerImpl.class.getName()); Logger.getLogger(ThreadListControllerImpl.class.getName());
private final IdentityManager identityManager; private final IdentityManager identityManager;
@CryptoExecutor
private final Executor cryptoExecutor; private final Executor cryptoExecutor;
protected final AndroidNotificationManager notificationManager; protected final AndroidNotificationManager notificationManager;
private final EventBus eventBus; private final EventBus eventBus;

View File

@@ -3,57 +3,57 @@ package org.briarproject.api.privategroup;
import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction; import org.briarproject.api.db.Transaction;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection; import java.util.Collection;
public interface PrivateGroupManager extends MessageTracker { public interface PrivateGroupManager extends MessageTracker {
/** Returns the unique ID of the private group client. */ /** Returns the unique ID of the private group client. */
@NotNull
ClientId getClientId(); ClientId getClientId();
/** Adds a new private group. */ /**
GroupId addPrivateGroup(String name) throws DbException; * Adds a new private group and joins it.
*
* @param group The private group to add
* @param newMemberMsg The creator's message announcing the first new member
* @param joinMsg The first new member's join message
*/
void addPrivateGroup(PrivateGroup group, GroupMessage newMemberMsg,
GroupMessage joinMsg) throws DbException;
/** Removes a dissolved private group. */ /** Removes a dissolved private group. */
void removePrivateGroup(GroupId g) throws DbException; void removePrivateGroup(GroupId g) throws DbException;
/** Creates a local group message. */ /** Gets the MessageId of the */
GroupMessage createLocalMessage(GroupId groupId, String body, MessageId getPreviousMsgId(GroupId g) throws DbException;
long timestamp, @Nullable MessageId parentId, LocalAuthor author);
/** Returns the timestamp of the message with the given ID */
long getMessageTimestamp(MessageId id) throws DbException;
/** Stores (and sends) a local group message. */ /** Stores (and sends) a local group message. */
GroupMessageHeader addLocalMessage(GroupMessage p) throws DbException; GroupMessageHeader addLocalMessage(GroupMessage p) throws DbException;
/** Returns the private group with the given ID. */ /** Returns the private group with the given ID. */
@NotNull
PrivateGroup getPrivateGroup(GroupId g) throws DbException; PrivateGroup getPrivateGroup(GroupId g) throws DbException;
/** /**
* Returns the private group with the given ID within the given transaction. * Returns the private group with the given ID within the given transaction.
*/ */
@NotNull
PrivateGroup getPrivateGroup(Transaction txn, GroupId g) throws DbException; PrivateGroup getPrivateGroup(Transaction txn, GroupId g) throws DbException;
/** Returns all private groups the user is a member of. */ /** Returns all private groups the user is a member of. */
@NotNull
Collection<PrivateGroup> getPrivateGroups() throws DbException; Collection<PrivateGroup> getPrivateGroups() throws DbException;
/** Returns true if the private group has been dissolved. */ /** Returns true if the private group has been dissolved. */
boolean isDissolved(GroupId g) throws DbException; boolean isDissolved(GroupId g) throws DbException;
/** Returns the body of the group message with the given ID. */ /** Returns the body of the group message with the given ID. */
@NotNull
String getMessageBody(MessageId m) throws DbException; String getMessageBody(MessageId m) throws DbException;
/** Returns the headers of all group messages in the given group. */ /** Returns the headers of all group messages in the given group. */
@NotNull
Collection<GroupMessageHeader> getHeaders(GroupId g) throws DbException; Collection<GroupMessageHeader> getHeaders(GroupId g) throws DbException;
} }

View File

@@ -11,4 +11,6 @@ interface Constants {
String KEY_AUTHOR_NAME = "authorName"; String KEY_AUTHOR_NAME = "authorName";
String KEY_AUTHOR_PUBLIC_KEY = "authorPublicKey"; String KEY_AUTHOR_PUBLIC_KEY = "authorPublicKey";
// Messaging Group Metadata
String KEY_PREVIOUS_MSG_ID = "previousMsgId";
} }

View File

@@ -3,16 +3,15 @@ package org.briarproject.privategroup;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfEntry;
import org.briarproject.api.data.BdfList; import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataParser; import org.briarproject.api.data.MetadataParser;
import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction; import org.briarproject.api.db.Transaction;
import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.privategroup.GroupMessage; import org.briarproject.api.privategroup.GroupMessage;
import org.briarproject.api.privategroup.GroupMessageFactory;
import org.briarproject.api.privategroup.GroupMessageHeader; import org.briarproject.api.privategroup.GroupMessageHeader;
import org.briarproject.api.privategroup.MessageType;
import org.briarproject.api.privategroup.PrivateGroup; import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.privategroup.PrivateGroupFactory; import org.briarproject.api.privategroup.PrivateGroupFactory;
import org.briarproject.api.privategroup.PrivateGroupManager; import org.briarproject.api.privategroup.PrivateGroupManager;
@@ -21,13 +20,10 @@ import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
import org.briarproject.api.system.Clock;
import org.briarproject.clients.BdfIncomingMessageHook; import org.briarproject.clients.BdfIncomingMessageHook;
import org.briarproject.util.StringUtils; import org.briarproject.util.StringUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.security.GeneralSecurityException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@@ -36,6 +32,12 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.api.identity.Author.Status.OURSELVES; import static org.briarproject.api.identity.Author.Status.OURSELVES;
import static org.briarproject.privategroup.Constants.KEY_AUTHOR_NAME;
import static org.briarproject.privategroup.Constants.KEY_AUTHOR_PUBLIC_KEY;
import static org.briarproject.privategroup.Constants.KEY_PREVIOUS_MSG_ID;
import static org.briarproject.privategroup.Constants.KEY_READ;
import static org.briarproject.privategroup.Constants.KEY_TIMESTAMP;
import static org.briarproject.privategroup.Constants.KEY_TYPE;
public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
PrivateGroupManager { PrivateGroupManager {
@@ -46,23 +48,15 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
StringUtils.fromHexString("5072697661746547726f75704d616e61" StringUtils.fromHexString("5072697661746547726f75704d616e61"
+ "67657220627920546f727374656e2047")); + "67657220627920546f727374656e2047"));
private final IdentityManager identityManager;
private final PrivateGroupFactory privateGroupFactory; private final PrivateGroupFactory privateGroupFactory;
private final GroupMessageFactory groupMessageFactory;
private final Clock clock;
@Inject @Inject
PrivateGroupManagerImpl(ClientHelper clientHelper, PrivateGroupManagerImpl(ClientHelper clientHelper,
MetadataParser metadataParser, DatabaseComponent db, MetadataParser metadataParser, DatabaseComponent db,
IdentityManager identityManager, PrivateGroupFactory privateGroupFactory) {
PrivateGroupFactory privateGroupFactory,
GroupMessageFactory groupMessageFactory, Clock clock) {
super(db, clientHelper, metadataParser); super(db, clientHelper, metadataParser);
this.identityManager = identityManager;
this.privateGroupFactory = privateGroupFactory; this.privateGroupFactory = privateGroupFactory;
this.groupMessageFactory = groupMessageFactory;
this.clock = clock;
} }
@NotNull @NotNull
@@ -72,36 +66,81 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
} }
@Override @Override
public GroupId addPrivateGroup(String name) throws DbException { public void addPrivateGroup(PrivateGroup group,
PrivateGroup group; GroupMessage newMemberMsg, GroupMessage joinMsg)
throws DbException {
Transaction txn = db.startTransaction(false); Transaction txn = db.startTransaction(false);
try { try {
LocalAuthor a = identityManager.getLocalAuthor(txn);
group = privateGroupFactory.createPrivateGroup(name, a);
db.addGroup(txn, group.getGroup()); db.addGroup(txn, group.getGroup());
announceNewMember(txn, newMemberMsg);
joinPrivateGroup(txn, joinMsg);
txn.setComplete(); txn.setComplete();
} catch (FormatException e) {
throw new DbException(e);
} finally { } finally {
db.endTransaction(txn); db.endTransaction(txn);
} }
return group.getId(); }
private void announceNewMember(Transaction txn, GroupMessage m)
throws DbException, FormatException {
BdfDictionary meta = new BdfDictionary();
meta.put(KEY_TYPE, MessageType.NEW_MEMBER.getInt());
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
}
private void joinPrivateGroup(Transaction txn, GroupMessage m)
throws DbException, FormatException {
BdfDictionary meta = new BdfDictionary();
meta.put(KEY_TYPE, MessageType.JOIN.getInt());
addMessageMetadata(meta, m, true);
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
trackOutgoingMessage(txn, m.getMessage());
setPreviousMsgId(txn, m.getMessage().getGroupId(),
m.getMessage().getId());
} }
@Override @Override
public void removePrivateGroup(GroupId g) throws DbException { public void removePrivateGroup(GroupId g) throws DbException {
// TODO
} }
@Override @Override
public GroupMessage createLocalMessage(GroupId groupId, String body, public MessageId getPreviousMsgId(GroupId g) throws DbException {
long timestamp, @Nullable MessageId parentId, LocalAuthor author) { MessageId previousMsgId;
Transaction txn = db.startTransaction(true);
try { try {
return groupMessageFactory previousMsgId = getPreviousMsgId(txn, g);
.createGroupMessage(groupId, timestamp, parentId, author, txn.setComplete();
body);
} catch (FormatException e) { } catch (FormatException e) {
throw new RuntimeException(e); throw new DbException(e);
} catch (GeneralSecurityException e) { } finally {
throw new RuntimeException(e); db.endTransaction(txn);
}
return previousMsgId;
}
private MessageId getPreviousMsgId(Transaction txn, GroupId g)
throws DbException, FormatException {
BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(txn, g);
byte[] previousMsgIdBytes = d.getOptionalRaw(KEY_PREVIOUS_MSG_ID);
if (previousMsgIdBytes == null) throw new DbException();
return new MessageId(previousMsgIdBytes);
}
private void setPreviousMsgId(Transaction txn, GroupId g,
MessageId previousMsgId) throws DbException, FormatException {
BdfDictionary d = BdfDictionary
.of(new BdfEntry(KEY_PREVIOUS_MSG_ID, previousMsgId));
clientHelper.mergeGroupMetadata(txn, g, d);
}
public long getMessageTimestamp(MessageId id) throws DbException {
try {
BdfDictionary d = clientHelper.getMessageMetadataAsDictionary(id);
return d.getLong(KEY_TIMESTAMP);
} catch (FormatException e) {
throw new DbException(e);
} }
} }
@@ -111,6 +150,8 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
Transaction txn = db.startTransaction(false); Transaction txn = db.startTransaction(false);
try { try {
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put(KEY_TYPE, MessageType.POST.getInt());
addMessageMetadata(meta, m, true);
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true); clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
trackOutgoingMessage(txn, m.getMessage()); trackOutgoingMessage(txn, m.getMessage());
txn.setComplete(); txn.setComplete();
@@ -121,7 +162,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
} }
return new GroupMessageHeader(m.getMessage().getGroupId(), return new GroupMessageHeader(m.getMessage().getGroupId(),
m.getMessage().getId(), m.getParent(), m.getMessage().getId(), m.getParent(),
m.getMessage().getTimestamp(), m.getAuthor(), OURSELVES, true); m.getMessage().getTimestamp(), m.getMember(), OURSELVES, true);
} }
@NotNull @NotNull
@@ -198,7 +239,6 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
trackIncomingMessage(txn, m); trackIncomingMessage(txn, m);
// TODO POST timestamp must be greater than the timestamps of the parent post, if any, and the member's previous message // TODO POST timestamp must be greater than the timestamps of the parent post, if any, and the member's previous message
// TODO JOIN timestamp must be equal to the timestamp of the new member message. // TODO JOIN timestamp must be equal to the timestamp of the new member message.
@@ -207,4 +247,12 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
return true; return true;
} }
private void addMessageMetadata(BdfDictionary meta, GroupMessage m,
boolean read) {
meta.put(KEY_TIMESTAMP, m.getMessage().getTimestamp());
meta.put(KEY_READ, read);
meta.put(KEY_AUTHOR_NAME, m.getMember().getName());
meta.put(KEY_AUTHOR_PUBLIC_KEY, m.getMember().getPublicKey());
}
} }