Groups: refactored to use group ID, not group name, plus fixes, etc.

This commit is contained in:
catbref 2019-01-16 15:00:25 +00:00
parent 3b4c12da56
commit bc4de8f063
63 changed files with 1478 additions and 1225 deletions

View File

@ -25,14 +25,30 @@ public class GroupWithMemberInfo {
@XmlElement(name = "admins") @XmlElement(name = "admins")
public List<String> groupAdminAddresses; public List<String> groupAdminAddresses;
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(description = "Member info")
public static class MemberInfo {
public String member;
public long joined;
// For JAX-RS
protected MemberInfo() {
}
public MemberInfo(GroupMemberData groupMemberData) {
this.member = groupMemberData.getMember();
this.joined = groupMemberData.getJoined();
}
}
@XmlElement(name = "members") @XmlElement(name = "members")
public List<GroupMemberData> groupMembers; public List<MemberInfo> groupMembers;
// For JAX-RS // For JAX-RS
protected GroupWithMemberInfo() { protected GroupWithMemberInfo() {
} }
public GroupWithMemberInfo(GroupData groupData, List<String> groupAdminAddresses, List<GroupMemberData> groupMembers, Integer memberCount) { public GroupWithMemberInfo(GroupData groupData, List<String> groupAdminAddresses, List<MemberInfo> groupMembers, Integer memberCount) {
this.groupData = groupData; this.groupData = groupData;
this.groupAdminAddresses = groupAdminAddresses; this.groupAdminAddresses = groupAdminAddresses;
this.groupMembers = groupMembers; this.groupMembers = groupMembers;

View File

@ -26,6 +26,7 @@ import org.qora.api.ApiError;
import org.qora.api.ApiErrors; import org.qora.api.ApiErrors;
import org.qora.api.ApiExceptionFactory; import org.qora.api.ApiExceptionFactory;
import org.qora.api.model.GroupWithMemberInfo; import org.qora.api.model.GroupWithMemberInfo;
import org.qora.api.model.GroupWithMemberInfo.MemberInfo;
import org.qora.crypto.Crypto; import org.qora.crypto.Crypto;
import org.qora.data.group.GroupAdminData; import org.qora.data.group.GroupAdminData;
import org.qora.data.group.GroupBanData; import org.qora.data.group.GroupBanData;
@ -39,7 +40,7 @@ import org.qora.data.transaction.CreateGroupTransactionData;
import org.qora.data.transaction.GroupBanTransactionData; import org.qora.data.transaction.GroupBanTransactionData;
import org.qora.data.transaction.GroupInviteTransactionData; import org.qora.data.transaction.GroupInviteTransactionData;
import org.qora.data.transaction.GroupKickTransactionData; import org.qora.data.transaction.GroupKickTransactionData;
import org.qora.data.transaction.GroupUnbanTransactionData; import org.qora.data.transaction.CancelGroupBanTransactionData;
import org.qora.data.transaction.JoinGroupTransactionData; import org.qora.data.transaction.JoinGroupTransactionData;
import org.qora.data.transaction.LeaveGroupTransactionData; import org.qora.data.transaction.LeaveGroupTransactionData;
import org.qora.data.transaction.RemoveGroupAdminTransactionData; import org.qora.data.transaction.RemoveGroupAdminTransactionData;
@ -56,7 +57,7 @@ import org.qora.transform.transaction.CreateGroupTransactionTransformer;
import org.qora.transform.transaction.GroupBanTransactionTransformer; import org.qora.transform.transaction.GroupBanTransactionTransformer;
import org.qora.transform.transaction.GroupInviteTransactionTransformer; import org.qora.transform.transaction.GroupInviteTransactionTransformer;
import org.qora.transform.transaction.GroupKickTransactionTransformer; import org.qora.transform.transaction.GroupKickTransactionTransformer;
import org.qora.transform.transaction.GroupUnbanTransactionTransformer; import org.qora.transform.transaction.CancelGroupBanTransactionTransformer;
import org.qora.transform.transaction.JoinGroupTransactionTransformer; import org.qora.transform.transaction.JoinGroupTransactionTransformer;
import org.qora.transform.transaction.LeaveGroupTransactionTransformer; import org.qora.transform.transaction.LeaveGroupTransactionTransformer;
import org.qora.transform.transaction.RemoveGroupAdminTransactionTransformer; import org.qora.transform.transaction.RemoveGroupAdminTransactionTransformer;
@ -101,7 +102,7 @@ public class GroupsResource {
} }
@GET @GET
@Path("/address/{address}") @Path("/owner/{address}")
@Operation( @Operation(
summary = "List all groups owned by address", summary = "List all groups owned by address",
responses = { responses = {
@ -115,12 +116,40 @@ public class GroupsResource {
} }
) )
@ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE}) @ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
public List<GroupData> getGroupsByAddress(@PathParam("address") String address) { public List<GroupData> getGroupsByOwner(@PathParam("address") String owner) {
if (!Crypto.isValidAddress(address)) if (!Crypto.isValidAddress(owner))
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
List<GroupData> groups = repository.getGroupRepository().getGroupsByOwner(address); List<GroupData> groups = repository.getGroupRepository().getGroupsByOwner(owner);
return groups;
} catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@GET
@Path("/member/{address}")
@Operation(
summary = "List all groups where address is a member",
responses = {
@ApiResponse(
description = "group info",
content = @Content(
mediaType = MediaType.APPLICATION_JSON,
array = @ArraySchema(schema = @Schema(implementation = GroupData.class))
)
)
}
)
@ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
public List<GroupData> getGroupsWithMember(@PathParam("address") String member) {
if (!Crypto.isValidAddress(member))
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) {
List<GroupData> groups = repository.getGroupRepository().getGroupsWithMember(member);
return groups; return groups;
} catch (DataException e) { } catch (DataException e) {
@ -149,28 +178,28 @@ public class GroupsResource {
if (groupData == null) if (groupData == null)
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.GROUP_UNKNOWN); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.GROUP_UNKNOWN);
List<GroupMemberData> groupMembers = null; List<MemberInfo> members = null;
Integer memberCount = null; Integer memberCount = null;
if (includeMembers) { if (includeMembers) {
groupMembers = repository.getGroupRepository().getGroupMembers(groupData.getGroupName()); List<GroupMemberData> groupMembers = repository.getGroupRepository().getGroupMembers(groupData.getGroupId());
// Strip groupName from member info // Convert to MemberInfo
groupMembers = groupMembers.stream().map(groupMemberData -> new GroupMemberData(null, groupMemberData.getMember(), groupMemberData.getJoined(), null)).collect(Collectors.toList()); members = groupMembers.stream().map(groupMemberData -> new MemberInfo(groupMemberData)).collect(Collectors.toList());
memberCount = groupMembers.size(); memberCount = members.size();
} else { } else {
// Just count members instead // Just count members instead
memberCount = repository.getGroupRepository().countGroupMembers(groupData.getGroupName()); memberCount = repository.getGroupRepository().countGroupMembers(groupData.getGroupId());
} }
// Always include admins // Always include admins
List<GroupAdminData> groupAdmins = repository.getGroupRepository().getGroupAdmins(groupData.getGroupName()); List<GroupAdminData> groupAdmins = repository.getGroupRepository().getGroupAdmins(groupData.getGroupId());
// We only need admin addresses // We only need admin addresses
List<String> groupAdminAddresses = groupAdmins.stream().map(groupAdminData -> groupAdminData.getAdmin()).collect(Collectors.toList()); List<String> adminAddresses = groupAdmins.stream().map(groupAdminData -> groupAdminData.getAdmin()).collect(Collectors.toList());
return new GroupWithMemberInfo(groupData, groupAdminAddresses, groupMembers, memberCount); return new GroupWithMemberInfo(groupData, adminAddresses, members, memberCount);
} catch (DataException e) { } catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
} }
@ -393,21 +422,21 @@ public class GroupsResource {
} }
@POST @POST
@Path("/unban") @Path("/ban/cancel")
@Operation( @Operation(
summary = "Build raw, unsigned, GROUP_UNBAN transaction", summary = "Build raw, unsigned, CANCEL_GROUP_BAN transaction",
requestBody = @RequestBody( requestBody = @RequestBody(
required = true, required = true,
content = @Content( content = @Content(
mediaType = MediaType.APPLICATION_JSON, mediaType = MediaType.APPLICATION_JSON,
schema = @Schema( schema = @Schema(
implementation = GroupUnbanTransactionData.class implementation = CancelGroupBanTransactionData.class
) )
) )
), ),
responses = { responses = {
@ApiResponse( @ApiResponse(
description = "raw, unsigned, GROUP_UNBAN transaction encoded in Base58", description = "raw, unsigned, CANCEL_GROUP_BAN transaction encoded in Base58",
content = @Content( content = @Content(
mediaType = MediaType.TEXT_PLAIN, mediaType = MediaType.TEXT_PLAIN,
schema = @Schema( schema = @Schema(
@ -418,7 +447,7 @@ public class GroupsResource {
} }
) )
@ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE}) @ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
public String groupBan(GroupUnbanTransactionData transactionData) { public String cancelGroupBan(CancelGroupBanTransactionData transactionData) {
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
Transaction transaction = Transaction.fromData(repository, transactionData); Transaction transaction = Transaction.fromData(repository, transactionData);
@ -426,7 +455,7 @@ public class GroupsResource {
if (result != ValidationResult.OK) if (result != ValidationResult.OK)
throw TransactionsResource.createTransactionInvalidException(request, result); throw TransactionsResource.createTransactionInvalidException(request, result);
byte[] bytes = GroupUnbanTransactionTransformer.toBytes(transactionData); byte[] bytes = CancelGroupBanTransactionTransformer.toBytes(transactionData);
return Base58.encode(bytes); return Base58.encode(bytes);
} catch (TransformationException e) { } catch (TransformationException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
@ -651,7 +680,7 @@ public class GroupsResource {
} }
@GET @GET
@Path("/invites/{groupname}") @Path("/invites/{groupid}")
@Operation( @Operation(
summary = "Pending group invites", summary = "Pending group invites",
responses = { responses = {
@ -665,16 +694,16 @@ public class GroupsResource {
} }
) )
@ApiErrors({ApiError.REPOSITORY_ISSUE}) @ApiErrors({ApiError.REPOSITORY_ISSUE})
public List<GroupInviteData> getInvites(@PathParam("groupname") String groupName) { public List<GroupInviteData> getInvites(@PathParam("groupid") int groupId) {
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
return repository.getGroupRepository().getGroupInvites(groupName); return repository.getGroupRepository().getGroupInvites(groupId);
} catch (DataException e) { } catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
} }
} }
@GET @GET
@Path("/joinrequests/{groupname}") @Path("/joinrequests/{groupid}")
@Operation( @Operation(
summary = "Pending group join requests", summary = "Pending group join requests",
responses = { responses = {
@ -688,16 +717,16 @@ public class GroupsResource {
} }
) )
@ApiErrors({ApiError.REPOSITORY_ISSUE}) @ApiErrors({ApiError.REPOSITORY_ISSUE})
public List<GroupJoinRequestData> getJoinRequests(@PathParam("groupname") String groupName) { public List<GroupJoinRequestData> getJoinRequests(@PathParam("groupid") int groupId) {
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
return repository.getGroupRepository().getGroupJoinRequests(groupName); return repository.getGroupRepository().getGroupJoinRequests(groupId);
} catch (DataException e) { } catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
} }
} }
@GET @GET
@Path("/bans/{groupname}") @Path("/bans/{groupid}")
@Operation( @Operation(
summary = "Current group join bans", summary = "Current group join bans",
responses = { responses = {
@ -711,9 +740,9 @@ public class GroupsResource {
} }
) )
@ApiErrors({ApiError.REPOSITORY_ISSUE}) @ApiErrors({ApiError.REPOSITORY_ISSUE})
public List<GroupBanData> getBans(@PathParam("groupname") String groupName) { public List<GroupBanData> getBans(@PathParam("groupid") int groupId) {
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
return repository.getGroupRepository().getGroupBans(groupName); return repository.getGroupRepository().getGroupBans(groupId);
} catch (DataException e) { } catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
} }

View File

@ -9,12 +9,12 @@ import javax.xml.bind.annotation.XmlTransient;
public class GroupAdminData { public class GroupAdminData {
// Properties // Properties
private String groupName; private int groupId;
private String admin; private String admin;
/** Reference to transaction that triggered adminship */ /** Reference to transaction that triggered adminship. Could be JOIN_GROUP, GROUP_INVITE, CREATE_GROUP or others... */
// No need to ever expose this via API // No need to ever expose this via API
@XmlTransient @XmlTransient
private byte[] groupReference; private byte[] reference;
// Constructors // Constructors
@ -22,28 +22,28 @@ public class GroupAdminData {
protected GroupAdminData() { protected GroupAdminData() {
} }
public GroupAdminData(String groupName, String admin, byte[] groupReference) { public GroupAdminData(int groupId, String admin, byte[] reference) {
this.groupName = groupName; this.groupId = groupId;
this.admin = admin; this.admin = admin;
this.groupReference = groupReference; this.reference = reference;
} }
// Getters / setters // Getters / setters
public String getGroupName() { public int getGroupId() {
return this.groupName; return this.groupId;
} }
public String getAdmin() { public String getAdmin() {
return this.admin; return this.admin;
} }
public byte[] getGroupReference() { public byte[] getReference() {
return this.groupReference; return this.reference;
} }
public void setGroupReference(byte[] groupReference) { public void setReference(byte[] reference) {
this.groupReference = groupReference; this.reference = reference;
} }
} }

View File

@ -9,12 +9,13 @@ import javax.xml.bind.annotation.XmlTransient;
public class GroupBanData { public class GroupBanData {
// Properties // Properties
private String groupName; private int groupId;
private String offender; private String offender;
private String admin; private String admin;
private long banned; private long banned;
private String reason; private String reason;
private Long expiry; private Long expiry;
/** Reference to GROUP_BAN transaction, used to rebuild this ban during orphaning. */
// No need to ever expose this via API // No need to ever expose this via API
@XmlTransient @XmlTransient
private byte[] reference; private byte[] reference;
@ -25,8 +26,8 @@ public class GroupBanData {
protected GroupBanData() { protected GroupBanData() {
} }
public GroupBanData(String groupName, String offender, String admin, long banned, String reason, Long expiry, byte[] reference) { public GroupBanData(int groupId, String offender, String admin, long banned, String reason, Long expiry, byte[] reference) {
this.groupName = groupName; this.groupId = groupId;
this.offender = offender; this.offender = offender;
this.admin = admin; this.admin = admin;
this.banned = banned; this.banned = banned;
@ -37,8 +38,8 @@ public class GroupBanData {
// Getters / setters // Getters / setters
public String getGroupName() { public int getGroupId() {
return this.groupName; return this.groupId;
} }
public String getOffender() { public String getOffender() {

View File

@ -9,13 +9,14 @@ import javax.xml.bind.annotation.XmlTransient;
public class GroupData { public class GroupData {
// Properties // Properties
private Integer groupId;
private String owner; private String owner;
private String groupName; private String groupName;
private String description; private String description;
private long created; private long created;
private Long updated; private Long updated;
private boolean isOpen; private boolean isOpen;
/** Reference to transaction that created group */ /** Reference to CREATE_GROUP or UPDATE_GROUP transaction, used to rebuild group during orphaning. */
// No need to ever expose this via API // No need to ever expose this via API
@XmlTransient @XmlTransient
private byte[] reference; private byte[] reference;
@ -26,7 +27,9 @@ public class GroupData {
protected GroupData() { protected GroupData() {
} }
public GroupData(String owner, String name, String description, long created, Long updated, boolean isOpen, byte[] reference) { /** Constructs new GroupData with nullable groupId and nullable updated [timestamp] */
public GroupData(Integer groupId, String owner, String name, String description, long created, Long updated, boolean isOpen, byte[] reference) {
this.groupId = groupId;
this.owner = owner; this.owner = owner;
this.groupName = name; this.groupName = name;
this.description = description; this.description = description;
@ -36,12 +39,21 @@ public class GroupData {
this.reference = reference; this.reference = reference;
} }
/** Constructs new GroupData with unassigned groupId */
public GroupData(String owner, String name, String description, long created, boolean isOpen, byte[] reference) { public GroupData(String owner, String name, String description, long created, boolean isOpen, byte[] reference) {
this(owner, name, description, created, null, isOpen, reference); this(null, owner, name, description, created, null, isOpen, reference);
} }
// Getters / setters // Getters / setters
public Integer getGroupId() {
return this.groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public String getOwner() { public String getOwner() {
return this.owner; return this.owner;
} }

View File

@ -9,10 +9,11 @@ import javax.xml.bind.annotation.XmlTransient;
public class GroupInviteData { public class GroupInviteData {
// Properties // Properties
private String groupName; private int groupId;
private String inviter; private String inviter;
private String invitee; private String invitee;
private Long expiry; private Long expiry;
/** Reference to GROUP_INVITE transaction, used to rebuild this invite during orphaning. */
// No need to ever expose this via API // No need to ever expose this via API
@XmlTransient @XmlTransient
private byte[] reference; private byte[] reference;
@ -23,8 +24,8 @@ public class GroupInviteData {
protected GroupInviteData() { protected GroupInviteData() {
} }
public GroupInviteData(String groupName, String inviter, String invitee, Long expiry, byte[] reference) { public GroupInviteData(int groupId, String inviter, String invitee, Long expiry, byte[] reference) {
this.groupName = groupName; this.groupId = groupId;
this.inviter = inviter; this.inviter = inviter;
this.invitee = invitee; this.invitee = invitee;
this.expiry = expiry; this.expiry = expiry;
@ -33,8 +34,8 @@ public class GroupInviteData {
// Getters / setters // Getters / setters
public String getGroupName() { public int getGroupId() {
return this.groupName; return this.groupId;
} }
public String getInviter() { public String getInviter() {

View File

@ -2,14 +2,19 @@ package org.qora.data.group;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;
// All properties to be converted to JSON via JAX-RS // All properties to be converted to JSON via JAX-RS
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
public class GroupJoinRequestData { public class GroupJoinRequestData {
// Properties // Properties
private String groupName; private int groupId;
private String joiner; private String joiner;
/** Reference to JOIN_GROUP transaction, used to rebuild this join request during orphaning. */
// No need to ever expose this via API
@XmlTransient
private byte[] reference;
// Constructors // Constructors
@ -17,19 +22,28 @@ public class GroupJoinRequestData {
protected GroupJoinRequestData() { protected GroupJoinRequestData() {
} }
public GroupJoinRequestData(String groupName, String joiner) { public GroupJoinRequestData(int groupId, String joiner, byte[] reference) {
this.groupName = groupName; this.groupId = groupId;
this.joiner = joiner; this.joiner = joiner;
this.reference = reference;
} }
// Getters / setters // Getters / setters
public String getGroupName() { public int getGroupId() {
return this.groupName; return this.groupId;
} }
public String getJoiner() { public String getJoiner() {
return this.joiner; return this.joiner;
} }
public byte[] getReference() {
return this.reference;
}
public void setReference(byte[] reference) {
this.reference = reference;
}
} }

View File

@ -9,13 +9,13 @@ import javax.xml.bind.annotation.XmlTransient;
public class GroupMemberData { public class GroupMemberData {
// Properties // Properties
private String groupName; private int groupId;
private String member; private String member;
private long joined; private long joined;
/** Reference to transaction that triggered membership */ /** Reference to transaction that triggered membership. Could be JOIN_GROUP, GROUP_INVITE, CREATE_GROUP or others... */
// No need to ever expose this via API // No need to ever expose this via API
@XmlTransient @XmlTransient
private byte[] groupReference; private byte[] reference;
// Constructors // Constructors
@ -23,17 +23,17 @@ public class GroupMemberData {
protected GroupMemberData() { protected GroupMemberData() {
} }
public GroupMemberData(String groupName, String member, long joined, byte[] groupReference) { public GroupMemberData(int groupId, String member, long joined, byte[] reference) {
this.groupName = groupName; this.groupId = groupId;
this.member = member; this.member = member;
this.joined = joined; this.joined = joined;
this.groupReference = groupReference; this.reference = reference;
} }
// Getters / setters // Getters / setters
public String getGroupName() { public int getGroupId() {
return this.groupName; return this.groupId;
} }
public String getMember() { public String getMember() {
@ -44,12 +44,12 @@ public class GroupMemberData {
return this.joined; return this.joined;
} }
public byte[] getGroupReference() { public byte[] getReference() {
return this.groupReference; return this.reference;
} }
public void setGroupReference(byte[] groupReference) { public void setReference(byte[] reference) {
this.groupReference = groupReference; this.reference = reference;
} }
} }

View File

@ -18,8 +18,8 @@ public class AddGroupAdminTransactionData extends TransactionData {
// Properties // Properties
@Schema(description = "group owner's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP") @Schema(description = "group owner's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
private byte[] ownerPublicKey; private byte[] ownerPublicKey;
@Schema(description = "group name", example = "my-group") @Schema(description = "group ID")
private String groupName; private int groupId;
@Schema(description = "member to promote to admin", example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK") @Schema(description = "member to promote to admin", example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK")
private String member; private String member;
@ -34,26 +34,22 @@ public class AddGroupAdminTransactionData extends TransactionData {
this.creatorPublicKey = this.ownerPublicKey; this.creatorPublicKey = this.ownerPublicKey;
} }
public AddGroupAdminTransactionData(byte[] ownerPublicKey, String groupName, String member, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { public AddGroupAdminTransactionData(byte[] ownerPublicKey, int groupId, String member, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
super(TransactionType.ADD_GROUP_ADMIN, fee, ownerPublicKey, timestamp, reference, signature); super(TransactionType.ADD_GROUP_ADMIN, fee, ownerPublicKey, timestamp, reference, signature);
this.ownerPublicKey = ownerPublicKey; this.ownerPublicKey = ownerPublicKey;
this.groupName = groupName; this.groupId = groupId;
this.member = member; this.member = member;
} }
public AddGroupAdminTransactionData(byte[] ownerPublicKey, String groupName, String member, BigDecimal fee, long timestamp, byte[] reference) {
this(ownerPublicKey, groupName, member, fee, timestamp, reference, null);
}
// Getters / setters // Getters / setters
public byte[] getOwnerPublicKey() { public byte[] getOwnerPublicKey() {
return this.ownerPublicKey; return this.ownerPublicKey;
} }
public String getGroupName() { public int getGroupId() {
return this.groupName; return this.groupId;
} }
public String getMember() { public String getMember() {

View File

@ -0,0 +1,78 @@
package org.qora.data.transaction;
import java.math.BigDecimal;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;
import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
// All properties to be converted to JSON via JAX-RS
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class CancelGroupBanTransactionData extends TransactionData {
// Properties
@Schema(description = "admin's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
private byte[] adminPublicKey;
@Schema(description = "group ID")
private int groupId;
@Schema(description = "member to unban from group", example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK")
private String member;
/** Reference to GROUP_BAN transaction, used to rebuild ban during orphaning. */
// No need to ever expose this via API
@XmlTransient
private byte[] banReference;
// Constructors
// For JAX-RS
protected CancelGroupBanTransactionData() {
super(TransactionType.CANCEL_GROUP_BAN);
}
public void afterUnmarshal(Unmarshaller u, Object parent) {
this.creatorPublicKey = this.adminPublicKey;
}
public CancelGroupBanTransactionData(byte[] adminPublicKey, int groupId, String member, byte[] banReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
super(TransactionType.CANCEL_GROUP_BAN, fee, adminPublicKey, timestamp, reference, signature);
this.adminPublicKey = adminPublicKey;
this.groupId = groupId;
this.member = member;
this.banReference = banReference;
}
/** Constructor typically used after deserialization */
public CancelGroupBanTransactionData(byte[] adminPublicKey, int groupId, String member, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
this(adminPublicKey, groupId, member, null, fee, timestamp, reference, signature);
}
// Getters / setters
public byte[] getAdminPublicKey() {
return this.adminPublicKey;
}
public int getGroupId() {
return this.groupId;
}
public String getMember() {
return this.member;
}
public byte[] getBanReference() {
return this.banReference;
}
public void setBanReference(byte[] banReference) {
this.banReference = banReference;
}
}

View File

@ -19,13 +19,14 @@ public class CancelGroupInviteTransactionData extends TransactionData {
// Properties // Properties
@Schema(description = "admin's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP") @Schema(description = "admin's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
private byte[] adminPublicKey; private byte[] adminPublicKey;
@Schema(description = "group name", example = "my-group") @Schema(description = "group ID")
private String groupName; private int groupId;
@Schema(description = "invitee's address", example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK") @Schema(description = "invitee's address", example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK")
private String invitee; private String invitee;
/** Reference to GROUP_INVITE transaction, used to rebuild invite during orphaning. */
// No need to ever expose this via API // No need to ever expose this via API
@XmlTransient @XmlTransient
private byte[] groupReference; private byte[] inviteReference;
// Constructors // Constructors
@ -38,25 +39,18 @@ public class CancelGroupInviteTransactionData extends TransactionData {
this.creatorPublicKey = this.adminPublicKey; this.creatorPublicKey = this.adminPublicKey;
} }
public CancelGroupInviteTransactionData(byte[] adminPublicKey, String groupName, String invitee, byte[] groupReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { public CancelGroupInviteTransactionData(byte[] adminPublicKey, int groupId, String invitee, byte[] inviteReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
super(TransactionType.CANCEL_GROUP_INVITE, fee, adminPublicKey, timestamp, reference, signature); super(TransactionType.CANCEL_GROUP_INVITE, fee, adminPublicKey, timestamp, reference, signature);
this.adminPublicKey = adminPublicKey; this.adminPublicKey = adminPublicKey;
this.groupName = groupName; this.groupId = groupId;
this.invitee = invitee; this.invitee = invitee;
this.groupReference = groupReference; this.inviteReference = inviteReference;
} }
public CancelGroupInviteTransactionData(byte[] adminPublicKey, String groupName, String invitee, byte[] groupReference, BigDecimal fee, long timestamp, byte[] reference) { /** Constructor typically used after deserialization */
this(adminPublicKey, groupName, invitee, groupReference, fee, timestamp, reference, null); public CancelGroupInviteTransactionData(byte[] adminPublicKey, int groupId, String invitee, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
} this(adminPublicKey, groupId, invitee, null, fee, timestamp, reference, signature);
public CancelGroupInviteTransactionData(byte[] adminPublicKey, String groupName, String invitee, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
this(adminPublicKey, groupName, invitee, null, fee, timestamp, reference, signature);
}
public CancelGroupInviteTransactionData(byte[] adminPublicKey, String groupName, String invitee, BigDecimal fee, long timestamp, byte[] reference) {
this(adminPublicKey, groupName, invitee, null, fee, timestamp, reference, null);
} }
// Getters / setters // Getters / setters
@ -65,20 +59,20 @@ public class CancelGroupInviteTransactionData extends TransactionData {
return this.adminPublicKey; return this.adminPublicKey;
} }
public String getGroupName() { public int getGroupId() {
return this.groupName; return this.groupId;
} }
public String getInvitee() { public String getInvitee() {
return this.invitee; return this.invitee;
} }
public byte[] getGroupReference() { public byte[] getInviteReference() {
return this.groupReference; return this.inviteReference;
} }
public void setGroupReference(byte[] groupReference) { public void setInviteReference(byte[] inviteReference) {
this.groupReference = groupReference; this.inviteReference = inviteReference;
} }
} }

View File

@ -9,19 +9,43 @@ import javax.xml.bind.annotation.XmlElement;
import org.qora.transaction.Transaction.TransactionType; import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.AccessMode;
// All properties to be converted to JSON via JAX-RS // All properties to be converted to JSON via JAX-RS
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class }) @Schema(
allOf = {
TransactionData.class
}
)
public class CreateGroupTransactionData extends TransactionData { public class CreateGroupTransactionData extends TransactionData {
@Schema(description = "group owner's address", example = "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v") // Properties
// groupId can be null but assigned during save() or during load from repository
@Schema(
accessMode = AccessMode.READ_ONLY,
description = "assigned group ID"
)
private Integer groupId = null;
@Schema(
description = "group owner's address",
example = "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v"
)
private String owner; private String owner;
@Schema(description = "group name", example = "miner-group") @Schema(
description = "group name",
example = "miner-group"
)
private String groupName; private String groupName;
@Schema(description = "short description of group", example = "this group is for block miners") @Schema(
description = "short description of group",
example = "this group is for block miners"
)
private String description; private String description;
@Schema(description = "whether anyone can join group (open) or group is invite-only (closed)", example = "true") @Schema(
description = "whether anyone can join group (open) or group is invite-only (closed)",
example = "true"
)
private boolean isOpen; private boolean isOpen;
// Constructors // Constructors
@ -31,8 +55,8 @@ public class CreateGroupTransactionData extends TransactionData {
super(TransactionType.CREATE_GROUP); super(TransactionType.CREATE_GROUP);
} }
public CreateGroupTransactionData(byte[] creatorPublicKey, String owner, String groupName, String description, boolean isOpen, BigDecimal fee, long timestamp, byte[] reference, public CreateGroupTransactionData(byte[] creatorPublicKey, String owner, String groupName, String description, boolean isOpen, Integer groupId,
byte[] signature) { BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
super(TransactionType.CREATE_GROUP, fee, creatorPublicKey, timestamp, reference, signature); super(TransactionType.CREATE_GROUP, fee, creatorPublicKey, timestamp, reference, signature);
this.creatorPublicKey = creatorPublicKey; this.creatorPublicKey = creatorPublicKey;
@ -40,10 +64,7 @@ public class CreateGroupTransactionData extends TransactionData {
this.groupName = groupName; this.groupName = groupName;
this.description = description; this.description = description;
this.isOpen = isOpen; this.isOpen = isOpen;
} this.groupId = groupId;
public CreateGroupTransactionData(byte[] creatorPublicKey, String owner, String groupName, String description, boolean isOpen, BigDecimal fee, long timestamp, byte[] reference) {
this(creatorPublicKey, owner, groupName, description, isOpen, fee, timestamp, reference, null);
} }
// Getters / setters // Getters / setters
@ -64,15 +85,35 @@ public class CreateGroupTransactionData extends TransactionData {
return this.isOpen; return this.isOpen;
} }
public Integer getGroupId() {
return this.groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
// Re-expose creatorPublicKey for this transaction type for JAXB // Re-expose creatorPublicKey for this transaction type for JAXB
@XmlElement(name = "creatorPublicKey") @XmlElement(
@Schema(name = "creatorPublicKey", description = "group creator's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP") name = "creatorPublicKey"
)
@Schema(
name = "creatorPublicKey",
description = "group creator's public key",
example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP"
)
public byte[] getGroupCreatorPublicKey() { public byte[] getGroupCreatorPublicKey() {
return this.creatorPublicKey; return this.creatorPublicKey;
} }
@XmlElement(name = "creatorPublicKey") @XmlElement(
@Schema(name = "creatorPublicKey", description = "group creator's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP") name = "creatorPublicKey"
)
@Schema(
name = "creatorPublicKey",
description = "group creator's public key",
example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP"
)
public void setGroupCreatorPublicKey(byte[] creatorPublicKey) { public void setGroupCreatorPublicKey(byte[] creatorPublicKey) {
this.creatorPublicKey = creatorPublicKey; this.creatorPublicKey = creatorPublicKey;
} }

View File

@ -13,26 +13,48 @@ import io.swagger.v3.oas.annotations.media.Schema;
// All properties to be converted to JSON via JAX-RS // All properties to be converted to JSON via JAX-RS
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class }) @Schema(
allOf = {
TransactionData.class
}
)
public class GroupBanTransactionData extends TransactionData { public class GroupBanTransactionData extends TransactionData {
// Properties // Properties
@Schema(description = "admin's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP") @Schema(
description = "admin's public key",
example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP"
)
private byte[] adminPublicKey; private byte[] adminPublicKey;
@Schema(description = "group name", example = "my-group") @Schema(
private String groupName; description = "group ID"
@Schema(description = "offender to ban from group", example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK") )
private int groupId;
@Schema(
description = "offender to ban from group",
example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK"
)
private String offender; private String offender;
@Schema(description = "reason for ban") @Schema(
description = "reason for ban"
)
private String reason; private String reason;
@Schema(description = "ban lifetime in seconds") @Schema(
description = "ban lifetime in seconds"
)
private int timeToLive; private int timeToLive;
/** Reference to transaction that triggered membership. Could be JOIN_GROUP, GROUP_INVITE or UPDATE_GROUP transaction. */
// No need to ever expose this via API // No need to ever expose this via API
@XmlTransient @XmlTransient
private byte[] memberReference; private byte[] memberReference;
/** Reference to transaction that triggered adminship. */
// No need to ever expose this via API // No need to ever expose this via API
@XmlTransient @XmlTransient
private byte[] adminReference; private byte[] adminReference;
/** Reference to pending join-request or invite transaction that was deleted by this so it (invite/join-request) can be rebuilt during orphaning. */
// No need to ever expose this via API
@XmlTransient
private byte[] joinInviteReference;
// Constructors // Constructors
@ -45,28 +67,24 @@ public class GroupBanTransactionData extends TransactionData {
this.creatorPublicKey = this.adminPublicKey; this.creatorPublicKey = this.adminPublicKey;
} }
public GroupBanTransactionData(byte[] adminPublicKey, String groupName, String member, String reason, int timeToLive, byte[] memberReference, byte[] adminReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { public GroupBanTransactionData(byte[] adminPublicKey, int groupId, String member, String reason, int timeToLive, byte[] memberReference,
byte[] adminReference, byte[] joinInviteReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
super(TransactionType.GROUP_BAN, fee, adminPublicKey, timestamp, reference, signature); super(TransactionType.GROUP_BAN, fee, adminPublicKey, timestamp, reference, signature);
this.adminPublicKey = adminPublicKey; this.adminPublicKey = adminPublicKey;
this.groupName = groupName; this.groupId = groupId;
this.offender = member; this.offender = member;
this.reason = reason; this.reason = reason;
this.timeToLive = timeToLive; this.timeToLive = timeToLive;
this.memberReference = memberReference; this.memberReference = memberReference;
this.adminReference = adminReference; this.adminReference = adminReference;
this.joinInviteReference = joinInviteReference;
} }
public GroupBanTransactionData(byte[] adminPublicKey, String groupName, String offender, String reason, int timeToLive, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { /** Constructor typically used after deserialization */
this(adminPublicKey, groupName, offender, reason, timeToLive, null, null, fee, timestamp, reference, signature); public GroupBanTransactionData(byte[] adminPublicKey, int groupId, String offender, String reason, int timeToLive, BigDecimal fee, long timestamp,
} byte[] reference, byte[] signature) {
this(adminPublicKey, groupId, offender, reason, timeToLive, null, null, null, fee, timestamp, reference, signature);
public GroupBanTransactionData(byte[] adminPublicKey, String groupName, String offender, String reason, int timeToLive, byte[] memberReference, byte[] adminReference, BigDecimal fee, long timestamp, byte[] reference) {
this(adminPublicKey, groupName, offender, reason, timeToLive, memberReference, adminReference, fee, timestamp, reference, null);
}
public GroupBanTransactionData(byte[] adminPublicKey, String groupName, String offender, String reason, int timeToLive, BigDecimal fee, long timestamp, byte[] reference) {
this(adminPublicKey, groupName, offender, reason, timeToLive, null, null, fee, timestamp, reference, null);
} }
// Getters / setters // Getters / setters
@ -75,8 +93,8 @@ public class GroupBanTransactionData extends TransactionData {
return this.adminPublicKey; return this.adminPublicKey;
} }
public String getGroupName() { public int getGroupId() {
return this.groupName; return this.groupId;
} }
public String getOffender() { public String getOffender() {
@ -107,4 +125,12 @@ public class GroupBanTransactionData extends TransactionData {
this.adminReference = adminReference; this.adminReference = adminReference;
} }
public byte[] getJoinInviteReference() {
return this.joinInviteReference;
}
public void setJoinInviteReference(byte[] reference) {
this.joinInviteReference = reference;
}
} }

View File

@ -19,15 +19,16 @@ public class GroupInviteTransactionData extends TransactionData {
// Properties // Properties
@Schema(description = "admin's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP") @Schema(description = "admin's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
private byte[] adminPublicKey; private byte[] adminPublicKey;
@Schema(description = "group name", example = "my-group") @Schema(description = "group ID")
private String groupName; private int groupId;
@Schema(description = "invitee's address", example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK") @Schema(description = "invitee's address", example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK")
private String invitee; private String invitee;
@Schema(description = "invitation lifetime in seconds") @Schema(description = "invitation lifetime in seconds")
private int timeToLive; private int timeToLive;
/** Reference to JOIN_GROUP transaction, used to rebuild this join request during orphaning. */
// No need to ever expose this via API // No need to ever expose this via API
@XmlTransient @XmlTransient
private byte[] groupReference; private byte[] joinReference;
// Constructors // Constructors
@ -40,26 +41,19 @@ public class GroupInviteTransactionData extends TransactionData {
this.creatorPublicKey = this.adminPublicKey; this.creatorPublicKey = this.adminPublicKey;
} }
public GroupInviteTransactionData(byte[] adminPublicKey, String groupName, String invitee, int timeToLive, byte[] groupReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { public GroupInviteTransactionData(byte[] adminPublicKey, int groupId, String invitee, int timeToLive, byte[] joinReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
super(TransactionType.GROUP_INVITE, fee, adminPublicKey, timestamp, reference, signature); super(TransactionType.GROUP_INVITE, fee, adminPublicKey, timestamp, reference, signature);
this.adminPublicKey = adminPublicKey; this.adminPublicKey = adminPublicKey;
this.groupName = groupName; this.groupId = groupId;
this.invitee = invitee; this.invitee = invitee;
this.timeToLive = timeToLive; this.timeToLive = timeToLive;
this.groupReference = groupReference; this.joinReference = joinReference;
} }
public GroupInviteTransactionData(byte[] adminPublicKey, String groupName, String invitee, int timeToLive, byte[] groupReference, BigDecimal fee, long timestamp, byte[] reference) { /** Constructor typically used after deserialization */
this(adminPublicKey, groupName, invitee, timeToLive, groupReference, fee, timestamp, reference, null); public GroupInviteTransactionData(byte[] adminPublicKey, int groupId, String invitee, int timeToLive, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
} this(adminPublicKey, groupId, invitee, timeToLive, null, fee, timestamp, reference, signature);
public GroupInviteTransactionData(byte[] adminPublicKey, String groupName, String invitee, int timeToLive, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
this(adminPublicKey, groupName, invitee, timeToLive, null, fee, timestamp, reference, signature);
}
public GroupInviteTransactionData(byte[] adminPublicKey, String groupName, String invitee, int timeToLive, BigDecimal fee, long timestamp, byte[] reference) {
this(adminPublicKey, groupName, invitee, timeToLive, null, fee, timestamp, reference, null);
} }
// Getters / setters // Getters / setters
@ -68,8 +62,8 @@ public class GroupInviteTransactionData extends TransactionData {
return this.adminPublicKey; return this.adminPublicKey;
} }
public String getGroupName() { public int getGroupId() {
return this.groupName; return this.groupId;
} }
public String getInvitee() { public String getInvitee() {
@ -80,12 +74,12 @@ public class GroupInviteTransactionData extends TransactionData {
return this.timeToLive; return this.timeToLive;
} }
public byte[] getGroupReference() { public byte[] getJoinReference() {
return this.groupReference; return this.joinReference;
} }
public void setGroupReference(byte[] groupReference) { public void setJoinReference(byte[] joinReference) {
this.groupReference = groupReference; this.joinReference = joinReference;
} }
} }

View File

@ -13,24 +13,45 @@ import io.swagger.v3.oas.annotations.media.Schema;
// All properties to be converted to JSON via JAX-RS // All properties to be converted to JSON via JAX-RS
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class }) @Schema(
allOf = {
TransactionData.class
}
)
public class GroupKickTransactionData extends TransactionData { public class GroupKickTransactionData extends TransactionData {
// Properties // Properties
@Schema(description = "admin's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP") @Schema(
description = "admin's public key",
example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP"
)
private byte[] adminPublicKey; private byte[] adminPublicKey;
@Schema(description = "group name", example = "my-group") @Schema(
private String groupName; description = "group name",
@Schema(description = "member to kick from group", example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK") example = "my-group"
)
private int groupId;
@Schema(
description = "member to kick from group",
example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK"
)
private String member; private String member;
@Schema(description = "reason for kick") @Schema(
description = "reason for kick"
)
private String reason; private String reason;
/** Reference to transaction that triggered membership. */
// No need to ever expose this via API // No need to ever expose this via API
@XmlTransient @XmlTransient
private byte[] memberReference; private byte[] memberReference;
/** Reference to transaction that triggered adminship. */
// No need to ever expose this via API // No need to ever expose this via API
@XmlTransient @XmlTransient
private byte[] adminReference; private byte[] adminReference;
/** Reference to JOIN_GROUP transaction, used to rebuild this join request during orphaning. */
// No need to ever expose this via API
@XmlTransient
private byte[] joinReference;
// Constructors // Constructors
@ -43,27 +64,23 @@ public class GroupKickTransactionData extends TransactionData {
this.creatorPublicKey = this.adminPublicKey; this.creatorPublicKey = this.adminPublicKey;
} }
public GroupKickTransactionData(byte[] adminPublicKey, String groupName, String member, String reason, byte[] memberReference, byte[] adminReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { public GroupKickTransactionData(byte[] adminPublicKey, int groupId, String member, String reason, byte[] memberReference, byte[] adminReference,
byte[] joinReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
super(TransactionType.GROUP_KICK, fee, adminPublicKey, timestamp, reference, signature); super(TransactionType.GROUP_KICK, fee, adminPublicKey, timestamp, reference, signature);
this.adminPublicKey = adminPublicKey; this.adminPublicKey = adminPublicKey;
this.groupName = groupName; this.groupId = groupId;
this.member = member; this.member = member;
this.reason = reason; this.reason = reason;
this.memberReference = memberReference; this.memberReference = memberReference;
this.adminReference = adminReference; this.adminReference = adminReference;
this.joinReference = joinReference;
} }
public GroupKickTransactionData(byte[] adminPublicKey, String groupName, String member, String reason, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { /** Constructor typically used after deserialization */
this(adminPublicKey, groupName, member, reason, null, null, fee, timestamp, reference, signature); public GroupKickTransactionData(byte[] adminPublicKey, int groupId, String member, String reason, BigDecimal fee, long timestamp, byte[] reference,
} byte[] signature) {
this(adminPublicKey, groupId, member, reason, null, null, null, fee, timestamp, reference, signature);
public GroupKickTransactionData(byte[] adminPublicKey, String groupName, String member, String reason, byte[] memberReference, byte[] adminReference, BigDecimal fee, long timestamp, byte[] reference) {
this(adminPublicKey, groupName, member, reason, memberReference, adminReference, fee, timestamp, reference, null);
}
public GroupKickTransactionData(byte[] adminPublicKey, String groupName, String member, String reason, BigDecimal fee, long timestamp, byte[] reference) {
this(adminPublicKey, groupName, member, reason, null, null, fee, timestamp, reference, null);
} }
// Getters / setters // Getters / setters
@ -72,8 +89,8 @@ public class GroupKickTransactionData extends TransactionData {
return this.adminPublicKey; return this.adminPublicKey;
} }
public String getGroupName() { public int getGroupId() {
return this.groupName; return this.groupId;
} }
public String getMember() { public String getMember() {
@ -100,4 +117,12 @@ public class GroupKickTransactionData extends TransactionData {
this.adminReference = adminReference; this.adminReference = adminReference;
} }
public byte[] getJoinReference() {
return this.joinReference;
}
public void setJoinReference(byte[] joinReference) {
this.joinReference = joinReference;
}
} }

View File

@ -1,84 +0,0 @@
package org.qora.data.transaction;
import java.math.BigDecimal;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;
import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
// All properties to be converted to JSON via JAX-RS
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class GroupUnbanTransactionData extends TransactionData {
// Properties
@Schema(description = "admin's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
private byte[] adminPublicKey;
@Schema(description = "group name", example = "my-group")
private String groupName;
@Schema(description = "member to unban from group", example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK")
private String member;
// No need to ever expose this via API
@XmlTransient
private byte[] groupReference;
// Constructors
// For JAX-RS
protected GroupUnbanTransactionData() {
super(TransactionType.GROUP_UNBAN);
}
public void afterUnmarshal(Unmarshaller u, Object parent) {
this.creatorPublicKey = this.adminPublicKey;
}
public GroupUnbanTransactionData(byte[] adminPublicKey, String groupName, String member, byte[] groupReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
super(TransactionType.GROUP_UNBAN, fee, adminPublicKey, timestamp, reference, signature);
this.adminPublicKey = adminPublicKey;
this.groupName = groupName;
this.member = member;
this.groupReference = groupReference;
}
public GroupUnbanTransactionData(byte[] adminPublicKey, String groupName, String member, byte[] groupReference, BigDecimal fee, long timestamp, byte[] reference) {
this(adminPublicKey, groupName, member, groupReference, fee, timestamp, reference, null);
}
public GroupUnbanTransactionData(byte[] adminPublicKey, String groupName, String member, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
this(adminPublicKey, groupName, member, null, fee, timestamp, reference, signature);
}
public GroupUnbanTransactionData(byte[] adminPublicKey, String groupName, String member, BigDecimal fee, long timestamp, byte[] reference) {
this(adminPublicKey, groupName, member, null, fee, timestamp, reference, null);
}
// Getters / setters
public byte[] getAdminPublicKey() {
return this.adminPublicKey;
}
public String getGroupName() {
return this.groupName;
}
public String getMember() {
return this.member;
}
public byte[] getGroupReference() {
return this.groupReference;
}
public void setGroupReference(byte[] groupReference) {
this.groupReference = groupReference;
}
}

View File

@ -5,6 +5,7 @@ import java.math.BigDecimal;
import javax.xml.bind.Unmarshaller; import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;
import org.qora.transaction.Transaction.TransactionType; import org.qora.transaction.Transaction.TransactionType;
@ -19,7 +20,11 @@ public class JoinGroupTransactionData extends TransactionData {
@Schema(description = "joiner's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP") @Schema(description = "joiner's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
private byte[] joinerPublicKey; private byte[] joinerPublicKey;
@Schema(description = "which group to join", example = "my-group") @Schema(description = "which group to join", example = "my-group")
private String groupName; private int groupId;
/** Reference to GROUP_INVITE transaction, used to rebuild invite during orphaning. */
// No need to ever expose this via API
@XmlTransient
private byte[] inviteReference;
// Constructors // Constructors
@ -32,15 +37,17 @@ public class JoinGroupTransactionData extends TransactionData {
this.creatorPublicKey = this.joinerPublicKey; this.creatorPublicKey = this.joinerPublicKey;
} }
public JoinGroupTransactionData(byte[] joinerPublicKey, String groupName, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { public JoinGroupTransactionData(byte[] joinerPublicKey, int groupId, byte[] inviteReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
super(TransactionType.JOIN_GROUP, fee, joinerPublicKey, timestamp, reference, signature); super(TransactionType.JOIN_GROUP, fee, joinerPublicKey, timestamp, reference, signature);
this.joinerPublicKey = joinerPublicKey; this.joinerPublicKey = joinerPublicKey;
this.groupName = groupName; this.groupId = groupId;
this.inviteReference = inviteReference;
} }
public JoinGroupTransactionData(byte[] joinerPublicKey, String groupName, BigDecimal fee, long timestamp, byte[] reference) { /** Constructor typically used after deserialization */
this(joinerPublicKey, groupName, fee, timestamp, reference, null); public JoinGroupTransactionData(byte[] joinerPublicKey, int groupId, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
this(joinerPublicKey, groupId, null, fee, timestamp, reference, signature);
} }
// Getters / setters // Getters / setters
@ -49,8 +56,16 @@ public class JoinGroupTransactionData extends TransactionData {
return this.joinerPublicKey; return this.joinerPublicKey;
} }
public String getGroupName() { public int getGroupId() {
return this.groupName; return this.groupId;
}
public byte[] getInviteReference() {
return this.inviteReference;
}
public void setInviteReference(byte[] inviteReference) {
this.inviteReference = inviteReference;
} }
} }

View File

@ -20,10 +20,12 @@ public class LeaveGroupTransactionData extends TransactionData {
@Schema(description = "leaver's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP") @Schema(description = "leaver's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
private byte[] leaverPublicKey; private byte[] leaverPublicKey;
@Schema(description = "which group to leave", example = "my-group") @Schema(description = "which group to leave", example = "my-group")
private String groupName; private int groupId;
/** Reference to transaction that triggered membership. */
// No need to ever expose this via API // No need to ever expose this via API
@XmlTransient @XmlTransient
private byte[] memberReference; private byte[] memberReference;
/** Reference to transaction that triggered adminship. */
// No need to ever expose this via API // No need to ever expose this via API
@XmlTransient @XmlTransient
private byte[] adminReference; private byte[] adminReference;
@ -39,25 +41,18 @@ public class LeaveGroupTransactionData extends TransactionData {
this.creatorPublicKey = this.leaverPublicKey; this.creatorPublicKey = this.leaverPublicKey;
} }
public LeaveGroupTransactionData(byte[] leaverPublicKey, String groupName, byte[] memberReference, byte[] adminReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { public LeaveGroupTransactionData(byte[] leaverPublicKey, int groupId, byte[] memberReference, byte[] adminReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
super(TransactionType.LEAVE_GROUP, fee, leaverPublicKey, timestamp, reference, signature); super(TransactionType.LEAVE_GROUP, fee, leaverPublicKey, timestamp, reference, signature);
this.leaverPublicKey = leaverPublicKey; this.leaverPublicKey = leaverPublicKey;
this.groupName = groupName; this.groupId = groupId;
this.memberReference = memberReference; this.memberReference = memberReference;
this.adminReference = adminReference; this.adminReference = adminReference;
} }
public LeaveGroupTransactionData(byte[] leaverPublicKey, String groupName, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { /** Constructor typically used after deserialization */
this(leaverPublicKey, groupName, null, null, fee, timestamp, reference, signature); public LeaveGroupTransactionData(byte[] leaverPublicKey, int groupId, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
} this(leaverPublicKey, groupId, null, null, fee, timestamp, reference, signature);
public LeaveGroupTransactionData(byte[] leaverPublicKey, String groupName, byte[] memberReference, byte[] adminReference, BigDecimal fee, long timestamp, byte[] reference) {
this(leaverPublicKey, groupName, memberReference, adminReference, fee, timestamp, reference, null);
}
public LeaveGroupTransactionData(byte[] leaverPublicKey, String groupName, BigDecimal fee, long timestamp, byte[] reference) {
this(leaverPublicKey, groupName, null, null, fee, timestamp, reference, null);
} }
// Getters / setters // Getters / setters
@ -66,8 +61,8 @@ public class LeaveGroupTransactionData extends TransactionData {
return this.leaverPublicKey; return this.leaverPublicKey;
} }
public String getGroupName() { public int getGroupId() {
return this.groupName; return this.groupId;
} }
public byte[] getMemberReference() { public byte[] getMemberReference() {

View File

@ -19,14 +19,15 @@ public class RemoveGroupAdminTransactionData extends TransactionData {
// Properties // Properties
@Schema(description = "group owner's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP") @Schema(description = "group owner's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
private byte[] ownerPublicKey; private byte[] ownerPublicKey;
@Schema(description = "group name", example = "my-group") @Schema(description = "group ID")
private String groupName; private int groupId;
@Schema(description = "admin to demote", example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK") @Schema(description = "admin to demote", example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK")
private String admin; private String admin;
/** Reference to transaction that triggered adminship. */
// For internal use when orphaning // For internal use when orphaning
@XmlTransient @XmlTransient
@Schema(hidden = true) @Schema(hidden = true)
private byte[] groupReference; private byte[] adminReference;
// Constructors // Constructors
@ -39,25 +40,18 @@ public class RemoveGroupAdminTransactionData extends TransactionData {
this.creatorPublicKey = this.ownerPublicKey; this.creatorPublicKey = this.ownerPublicKey;
} }
public RemoveGroupAdminTransactionData(byte[] ownerPublicKey, String groupName, String admin, byte[] groupReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { public RemoveGroupAdminTransactionData(byte[] ownerPublicKey, int groupId, String admin, byte[] adminReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
super(TransactionType.REMOVE_GROUP_ADMIN, fee, ownerPublicKey, timestamp, reference, signature); super(TransactionType.REMOVE_GROUP_ADMIN, fee, ownerPublicKey, timestamp, reference, signature);
this.ownerPublicKey = ownerPublicKey; this.ownerPublicKey = ownerPublicKey;
this.groupName = groupName; this.groupId = groupId;
this.admin = admin; this.admin = admin;
this.groupReference = groupReference; this.adminReference = adminReference;
} }
public RemoveGroupAdminTransactionData(byte[] ownerPublicKey, String groupName, String admin, byte[] groupReference, BigDecimal fee, long timestamp, byte[] reference) { /** Constructor typically used after deserialization */
this(ownerPublicKey, groupName, admin, groupReference, fee, timestamp, reference, null); public RemoveGroupAdminTransactionData(byte[] ownerPublicKey, int groupId, String admin, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
} this(ownerPublicKey, groupId, admin, null, fee, timestamp, reference, signature);
public RemoveGroupAdminTransactionData(byte[] ownerPublicKey, String groupName, String admin, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
this(ownerPublicKey, groupName, admin, null, fee, timestamp, reference, signature);
}
public RemoveGroupAdminTransactionData(byte[] ownerPublicKey, String groupName, String admin, BigDecimal fee, long timestamp, byte[] reference) {
this(ownerPublicKey, groupName, admin, null, fee, timestamp, reference, null);
} }
// Getters / setters // Getters / setters
@ -66,20 +60,20 @@ public class RemoveGroupAdminTransactionData extends TransactionData {
return this.ownerPublicKey; return this.ownerPublicKey;
} }
public String getGroupName() { public int getGroupId() {
return this.groupName; return this.groupId;
} }
public String getAdmin() { public String getAdmin() {
return this.admin; return this.admin;
} }
public byte[] getGroupReference() { public byte[] getAdminReference() {
return this.groupReference; return this.adminReference;
} }
public void setGroupReference(byte[] groupReference) { public void setAdminReference(byte[] adminReference) {
this.groupReference = groupReference; this.adminReference = adminReference;
} }
} }

View File

@ -35,7 +35,7 @@ import io.swagger.v3.oas.annotations.media.Schema.AccessMode;
MultiPaymentTransactionData.class, DeployATTransactionData.class, MessageTransactionData.class, ATTransactionData.class, MultiPaymentTransactionData.class, DeployATTransactionData.class, MessageTransactionData.class, ATTransactionData.class,
CreateGroupTransactionData.class, UpdateGroupTransactionData.class, CreateGroupTransactionData.class, UpdateGroupTransactionData.class,
AddGroupAdminTransactionData.class, RemoveGroupAdminTransactionData.class, AddGroupAdminTransactionData.class, RemoveGroupAdminTransactionData.class,
GroupBanTransactionData.class, GroupUnbanTransactionData.class, GroupBanTransactionData.class, CancelGroupBanTransactionData.class,
GroupKickTransactionData.class, GroupInviteTransactionData.class, GroupKickTransactionData.class, GroupInviteTransactionData.class,
JoinGroupTransactionData.class, LeaveGroupTransactionData.class JoinGroupTransactionData.class, LeaveGroupTransactionData.class
}) })

View File

@ -22,11 +22,12 @@ public class UpdateGroupTransactionData extends TransactionData {
@Schema(description = "new owner's address", example = "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v") @Schema(description = "new owner's address", example = "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v")
private String newOwner; private String newOwner;
@Schema(description = "which group to update", example = "my-group") @Schema(description = "which group to update", example = "my-group")
private String groupName; private int groupId;
@Schema(description = "replacement group description", example = "my group for accounts I like") @Schema(description = "replacement group description", example = "my group for accounts I like")
private String newDescription; private String newDescription;
@Schema(description = "new group join policy", example = "true") @Schema(description = "new group join policy", example = "true")
private boolean newIsOpen; private boolean newIsOpen;
/** Reference to CREATE_GROUP or UPDATE_GROUP transaction, used to rebuild group during orphaning. */
// For internal use when orphaning // For internal use when orphaning
@XmlTransient @XmlTransient
@Schema(hidden = true) @Schema(hidden = true)
@ -43,26 +44,22 @@ public class UpdateGroupTransactionData extends TransactionData {
this.creatorPublicKey = this.ownerPublicKey; this.creatorPublicKey = this.ownerPublicKey;
} }
public UpdateGroupTransactionData(byte[] ownerPublicKey, String groupName, String newOwner, String newDescription, boolean newIsOpen, byte[] groupReference, BigDecimal fee, long timestamp, public UpdateGroupTransactionData(byte[] ownerPublicKey, int groupId, String newOwner, String newDescription, boolean newIsOpen, byte[] groupReference, BigDecimal fee, long timestamp,
byte[] reference, byte[] signature) { byte[] reference, byte[] signature) {
super(TransactionType.UPDATE_GROUP, fee, ownerPublicKey, timestamp, reference, signature); super(TransactionType.UPDATE_GROUP, fee, ownerPublicKey, timestamp, reference, signature);
this.ownerPublicKey = ownerPublicKey; this.ownerPublicKey = ownerPublicKey;
this.newOwner = newOwner; this.newOwner = newOwner;
this.groupName = groupName; this.groupId = groupId;
this.newDescription = newDescription; this.newDescription = newDescription;
this.newIsOpen = newIsOpen; this.newIsOpen = newIsOpen;
this.groupReference = groupReference; this.groupReference = groupReference;
} }
public UpdateGroupTransactionData(byte[] ownerPublicKey, String groupName, String newOwner, String newDescription, boolean newIsOpen, BigDecimal fee, long timestamp, byte[] reference, /** Constructor typically used after deserialization */
public UpdateGroupTransactionData(byte[] ownerPublicKey, int groupId, String newOwner, String newDescription, boolean newIsOpen, BigDecimal fee, long timestamp, byte[] reference,
byte[] signature) { byte[] signature) {
this(ownerPublicKey, groupName, newOwner, newDescription, newIsOpen, null, fee, timestamp, reference, signature); this(ownerPublicKey, groupId, newOwner, newDescription, newIsOpen, null, fee, timestamp, reference, signature);
}
public UpdateGroupTransactionData(byte[] ownerPublicKey, String groupName, String newOwner, String newDescription, boolean newIsOpen, byte[] groupReference, BigDecimal fee, long timestamp,
byte[] reference) {
this(ownerPublicKey, groupName, newOwner, newDescription, newIsOpen, groupReference, fee, timestamp, reference, null);
} }
// Getters / setters // Getters / setters
@ -75,8 +72,8 @@ public class UpdateGroupTransactionData extends TransactionData {
return this.newOwner; return this.newOwner;
} }
public String getGroupName() { public int getGroupId() {
return this.groupName; return this.groupId;
} }
public String getNewDescription() { public String getNewDescription() {

View File

@ -1,7 +1,6 @@
package org.qora.group; package org.qora.group;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import org.qora.account.Account; import org.qora.account.Account;
import org.qora.account.PublicKeyAccount; import org.qora.account.PublicKeyAccount;
@ -17,7 +16,7 @@ import org.qora.data.transaction.CreateGroupTransactionData;
import org.qora.data.transaction.GroupBanTransactionData; import org.qora.data.transaction.GroupBanTransactionData;
import org.qora.data.transaction.GroupInviteTransactionData; import org.qora.data.transaction.GroupInviteTransactionData;
import org.qora.data.transaction.GroupKickTransactionData; import org.qora.data.transaction.GroupKickTransactionData;
import org.qora.data.transaction.GroupUnbanTransactionData; import org.qora.data.transaction.CancelGroupBanTransactionData;
import org.qora.data.transaction.JoinGroupTransactionData; import org.qora.data.transaction.JoinGroupTransactionData;
import org.qora.data.transaction.LeaveGroupTransactionData; import org.qora.data.transaction.LeaveGroupTransactionData;
import org.qora.data.transaction.RemoveGroupAdminTransactionData; import org.qora.data.transaction.RemoveGroupAdminTransactionData;
@ -31,13 +30,14 @@ public class Group {
// Properties // Properties
private Repository repository; private Repository repository;
private GroupRepository groupRepository;
private GroupData groupData; private GroupData groupData;
// Useful constants // Useful constants
public static final int MAX_NAME_SIZE = 400; public static final int MAX_NAME_SIZE = 32;
public static final int MAX_DESCRIPTION_SIZE = 4000; public static final int MAX_DESCRIPTION_SIZE = 128;
/** Max size of kick/ban reason */ /** Max size of kick/ban reason */
public static final int MAX_REASON_SIZE = 400; public static final int MAX_REASON_SIZE = 128;
// Constructors // Constructors
@ -49,6 +49,8 @@ public class Group {
*/ */
public Group(Repository repository, CreateGroupTransactionData createGroupTransactionData) { public Group(Repository repository, CreateGroupTransactionData createGroupTransactionData) {
this.repository = repository; this.repository = repository;
this.groupRepository = repository.getGroupRepository();
this.groupData = new GroupData(createGroupTransactionData.getOwner(), createGroupTransactionData.getGroupName(), this.groupData = new GroupData(createGroupTransactionData.getOwner(), createGroupTransactionData.getGroupName(),
createGroupTransactionData.getDescription(), createGroupTransactionData.getTimestamp(), createGroupTransactionData.getIsOpen(), createGroupTransactionData.getDescription(), createGroupTransactionData.getTimestamp(), createGroupTransactionData.getIsOpen(),
createGroupTransactionData.getSignature()); createGroupTransactionData.getSignature());
@ -58,16 +60,151 @@ public class Group {
* Construct Group business object using existing group in repository. * Construct Group business object using existing group in repository.
* *
* @param repository * @param repository
* @param groupName * @param groupId
* @throws DataException * @throws DataException
*/ */
public Group(Repository repository, String groupName) throws DataException { public Group(Repository repository, int groupId) throws DataException {
this.repository = repository; this.repository = repository;
this.groupData = this.repository.getGroupRepository().fromGroupName(groupName); this.groupRepository = repository.getGroupRepository();
this.groupData = this.repository.getGroupRepository().fromGroupId(groupId);
}
// Getters / setters
public GroupData getGroupData() {
return this.groupData;
}
// Shortcuts to aid code clarity
// Membership
private GroupMemberData getMember(String member) throws DataException {
return groupRepository.getMember(this.groupData.getGroupId(), member);
}
private boolean memberExists(String member) throws DataException {
return groupRepository.memberExists(this.groupData.getGroupId(), member);
}
private void addMember(String member, long joined, byte[] reference) throws DataException {
GroupMemberData groupMemberData = new GroupMemberData(this.groupData.getGroupId(), member, joined, reference);
groupRepository.save(groupMemberData);
}
private void addMember(String member, TransactionData transactionData) throws DataException {
this.addMember(member, transactionData.getTimestamp(), transactionData.getSignature());
}
private void rebuildMember(String member, byte[] reference) throws DataException {
TransactionData transactionData = this.repository.getTransactionRepository().fromSignature(reference);
this.addMember(member, transactionData);
}
private void deleteMember(String member) throws DataException {
groupRepository.deleteMember(this.groupData.getGroupId(), member);
}
// Adminship
private GroupAdminData getAdmin(String admin) throws DataException {
return groupRepository.getAdmin(this.groupData.getGroupId(), admin);
}
private boolean adminExists(String admin) throws DataException {
return groupRepository.adminExists(this.groupData.getGroupId(), admin);
}
private void addAdmin(String admin, byte[] reference) throws DataException {
GroupAdminData groupAdminData = new GroupAdminData(this.groupData.getGroupId(), admin, reference);
groupRepository.save(groupAdminData);
}
private void addAdmin(String admin, TransactionData transactionData) throws DataException {
this.addAdmin(admin, transactionData.getSignature());
}
private void rebuildAdmin(String admin, byte[] reference) throws DataException {
TransactionData transactionData = this.repository.getTransactionRepository().fromSignature(reference);
this.addAdmin(admin, transactionData);
}
private void deleteAdmin(String admin) throws DataException {
groupRepository.deleteAdmin(this.groupData.getGroupId(), admin);
}
// Join request
private GroupJoinRequestData getJoinRequest(String joiner) throws DataException {
return groupRepository.getJoinRequest(this.groupData.getGroupId(), joiner);
}
private void addJoinRequest(String joiner, byte[] reference) throws DataException {
GroupJoinRequestData groupJoinRequestData = new GroupJoinRequestData(this.groupData.getGroupId(), joiner, reference);
groupRepository.save(groupJoinRequestData);
}
private void rebuildJoinRequest(String joiner, byte[] reference) throws DataException {
this.addJoinRequest(joiner, reference);
}
private void deleteJoinRequest(String joiner) throws DataException {
groupRepository.deleteJoinRequest(this.groupData.getGroupId(), joiner);
}
// Invites
private GroupInviteData getInvite(String invitee) throws DataException {
return groupRepository.getInvite(this.groupData.getGroupId(), invitee);
}
private void addInvite(GroupInviteTransactionData groupInviteTransactionData) throws DataException {
Account inviter = new PublicKeyAccount(this.repository, groupInviteTransactionData.getAdminPublicKey());
String invitee = groupInviteTransactionData.getInvitee();
Long expiry = null;
int timeToLive = groupInviteTransactionData.getTimeToLive();
if (timeToLive != 0)
expiry = groupInviteTransactionData.getTimestamp() + timeToLive * 1000;
GroupInviteData groupInviteData = new GroupInviteData(this.groupData.getGroupId(), inviter.getAddress(), invitee, expiry,
groupInviteTransactionData.getSignature());
groupRepository.save(groupInviteData);
}
private void rebuildInvite(String invitee, byte[] reference) throws DataException {
TransactionData previousTransactionData = this.repository.getTransactionRepository().fromSignature(reference);
this.addInvite((GroupInviteTransactionData) previousTransactionData);
}
private void deleteInvite(String invitee) throws DataException {
groupRepository.deleteInvite(this.groupData.getGroupId(), invitee);
}
// Bans
private void addBan(GroupBanTransactionData groupBanTransactionData) throws DataException {
String offender = groupBanTransactionData.getOffender();
Account admin = new PublicKeyAccount(this.repository, groupBanTransactionData.getAdminPublicKey());
long banned = groupBanTransactionData.getTimestamp();
String reason = groupBanTransactionData.getReason();
Long expiry = null;
int timeToLive = groupBanTransactionData.getTimeToLive();
if (timeToLive != 0)
expiry = groupBanTransactionData.getTimestamp() + timeToLive * 1000;
// Save reference to this banning transaction so cancel-ban can rebuild ban during orphaning.
byte[] reference = groupBanTransactionData.getSignature();
GroupBanData groupBanData = new GroupBanData(this.groupData.getGroupId(), offender, admin.getAddress(), banned, reason, expiry, reference);
groupRepository.save(groupBanData);
} }
// Processing // Processing
// "un"-methods are the orphaning versions. e.g. "uncreate" undoes "create" processing.
/* /*
* GroupData records can be changed by CREATE_GROUP or UPDATE_GROUP transactions. * GroupData records can be changed by CREATE_GROUP or UPDATE_GROUP transactions.
* *
@ -75,7 +212,8 @@ public class Group {
* in a field called "reference". * in a field called "reference".
* *
* During orphaning, "reference" is used to fetch the previous GroupData-changing transaction * During orphaning, "reference" is used to fetch the previous GroupData-changing transaction
* and that transaction's contents are used to restore the previous GroupData state. * and that transaction's contents are used to restore the previous GroupData state,
* including GroupData's previous "reference" value.
*/ */
// CREATE GROUP // CREATE GROUP
@ -84,19 +222,16 @@ public class Group {
// Note: this.groupData already populated by our constructor above // Note: this.groupData already populated by our constructor above
this.repository.getGroupRepository().save(this.groupData); this.repository.getGroupRepository().save(this.groupData);
// Add owner as admin
GroupAdminData groupAdminData = new GroupAdminData(this.groupData.getGroupName(), this.groupData.getOwner(), createGroupTransactionData.getSignature());
this.repository.getGroupRepository().save(groupAdminData);
// Add owner as member // Add owner as member
GroupMemberData groupMemberData = new GroupMemberData(this.groupData.getGroupName(), this.groupData.getOwner(), this.groupData.getCreated(), this.addMember(this.groupData.getOwner(), createGroupTransactionData);
createGroupTransactionData.getSignature());
this.repository.getGroupRepository().save(groupMemberData); // Add owner as admin
this.addAdmin(this.groupData.getOwner(), createGroupTransactionData);
} }
public void uncreate() throws DataException { public void uncreate() throws DataException {
// Repository takes care of cleaning up ancilliary data! // Repository takes care of cleaning up ancilliary data!
this.repository.getGroupRepository().delete(this.groupData.getGroupName()); this.repository.getGroupRepository().delete(this.groupData.getGroupId());
} }
// UPDATE GROUP // UPDATE GROUP
@ -108,9 +243,6 @@ public class Group {
*/ */
public void updateGroup(UpdateGroupTransactionData updateGroupTransactionData) throws DataException { public void updateGroup(UpdateGroupTransactionData updateGroupTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = updateGroupTransactionData.getGroupName();
// Save GroupData's reference in our transaction data // Save GroupData's reference in our transaction data
updateGroupTransactionData.setGroupReference(this.groupData.getReference()); updateGroupTransactionData.setGroupReference(this.groupData.getReference());
@ -129,25 +261,17 @@ public class Group {
String newOwner = updateGroupTransactionData.getNewOwner(); String newOwner = updateGroupTransactionData.getNewOwner();
// New owner should be a member if not already // New owner should be a member if not already
if (!groupRepository.memberExists(groupName, newOwner)) { if (!this.memberExists(newOwner))
GroupMemberData groupMemberData = new GroupMemberData(groupName, newOwner, updateGroupTransactionData.getTimestamp(), this.addMember(newOwner, updateGroupTransactionData);
updateGroupTransactionData.getSignature());
groupRepository.save(groupMemberData);
}
// New owner should be an admin if not already // New owner should be an admin if not already
if (!groupRepository.adminExists(groupName, newOwner)) { if (!this.adminExists(newOwner))
GroupAdminData groupAdminData = new GroupAdminData(groupName, newOwner, updateGroupTransactionData.getSignature()); this.addAdmin(newOwner, updateGroupTransactionData);
groupRepository.save(groupAdminData);
}
// Previous owner retained as admin and member // Previous owner retained as admin and member
} }
public void unupdateGroup(UpdateGroupTransactionData updateGroupTransactionData) throws DataException { public void unupdateGroup(UpdateGroupTransactionData updateGroupTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = updateGroupTransactionData.getGroupName();
// Previous group reference is taken from this transaction's cached copy // Previous group reference is taken from this transaction's cached copy
this.groupData.setReference(updateGroupTransactionData.getGroupReference()); this.groupData.setReference(updateGroupTransactionData.getGroupReference());
@ -159,21 +283,23 @@ public class Group {
// If ownership changed we need to do more work. Note groupData's owner is reverted at this point. // If ownership changed we need to do more work. Note groupData's owner is reverted at this point.
String newOwner = updateGroupTransactionData.getNewOwner(); String newOwner = updateGroupTransactionData.getNewOwner();
if (!this.groupData.getOwner().equals(newOwner)) { if (!this.groupData.getOwner().equals(newOwner)) {
// If this update caused [what was] new owner to become admin, then revoke that now. // If this update caused [what was] new owner to become admin, then revoke that now.
// (It's possible they were an admin prior to being given ownership so we need to retain that). // (It's possible they were an admin prior to being given ownership so we need to retain that).
GroupAdminData groupAdminData = groupRepository.getAdmin(groupName, newOwner); GroupAdminData groupAdminData = this.getAdmin(newOwner);
if (Arrays.equals(groupAdminData.getGroupReference(), updateGroupTransactionData.getSignature())) if (Arrays.equals(groupAdminData.getReference(), updateGroupTransactionData.getSignature()))
groupRepository.deleteAdmin(groupName, newOwner); this.deleteAdmin(newOwner);
// If this update caused [what was] new owner to become member, then revoke that now. // If this update caused [what was] new owner to become member, then revoke that now.
// (It's possible they were a member prior to being given ownership so we need to retain that). // (It's possible they were a member prior to being given ownership so we need to retain that).
GroupMemberData groupMemberData = groupRepository.getMember(groupName, newOwner); GroupMemberData groupMemberData = this.getMember(newOwner);
if (Arrays.equals(groupMemberData.getGroupReference(), updateGroupTransactionData.getSignature())) if (Arrays.equals(groupMemberData.getReference(), updateGroupTransactionData.getSignature()))
groupRepository.deleteMember(groupName, newOwner); this.deleteMember(newOwner);
} }
} }
/** Reverts groupData using previous values stored in referenced transaction. */
private void revertGroupUpdate() throws DataException { private void revertGroupUpdate() throws DataException {
TransactionData previousTransactionData = this.repository.getTransactionRepository().fromSignature(this.groupData.getReference()); TransactionData previousTransactionData = this.repository.getTransactionRepository().fromSignature(this.groupData.getReference());
if (previousTransactionData == null) if (previousTransactionData == null)
@ -204,47 +330,46 @@ public class Group {
} }
public void promoteToAdmin(AddGroupAdminTransactionData addGroupAdminTransactionData) throws DataException { public void promoteToAdmin(AddGroupAdminTransactionData addGroupAdminTransactionData) throws DataException {
GroupAdminData groupAdminData = new GroupAdminData(addGroupAdminTransactionData.getGroupName(), addGroupAdminTransactionData.getMember(), this.addAdmin(addGroupAdminTransactionData.getMember(), addGroupAdminTransactionData.getSignature());
addGroupAdminTransactionData.getSignature());
this.repository.getGroupRepository().save(groupAdminData);
} }
public void unpromoteToAdmin(AddGroupAdminTransactionData addGroupAdminTransactionData) throws DataException { public void unpromoteToAdmin(AddGroupAdminTransactionData addGroupAdminTransactionData) throws DataException {
this.repository.getGroupRepository().deleteAdmin(addGroupAdminTransactionData.getGroupName(), addGroupAdminTransactionData.getMember()); this.deleteAdmin(addGroupAdminTransactionData.getMember());
} }
public void demoteFromAdmin(RemoveGroupAdminTransactionData removeGroupAdminTransactionData) throws DataException { public void demoteFromAdmin(RemoveGroupAdminTransactionData removeGroupAdminTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = removeGroupAdminTransactionData.getGroupName();
String admin = removeGroupAdminTransactionData.getAdmin(); String admin = removeGroupAdminTransactionData.getAdmin();
// Save admin's promotion transaction reference for orphaning purposes // Save reference to the transaction that caused adminship so we can revert if orphaning.
GroupAdminData groupAdminData = groupRepository.getAdmin(groupName, admin); GroupAdminData groupAdminData = this.getAdmin(admin);
removeGroupAdminTransactionData.setGroupReference(groupAdminData.getGroupReference()); // Reference now part of this transaction but actually saved into repository by caller.
removeGroupAdminTransactionData.setAdminReference(groupAdminData.getReference());
// Demote // Demote
groupRepository.deleteAdmin(groupName, admin); this.deleteAdmin(admin);
} }
public void undemoteFromAdmin(RemoveGroupAdminTransactionData removeGroupAdminTransactionData) throws DataException { public void undemoteFromAdmin(RemoveGroupAdminTransactionData removeGroupAdminTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = removeGroupAdminTransactionData.getGroupName();
String admin = removeGroupAdminTransactionData.getAdmin(); String admin = removeGroupAdminTransactionData.getAdmin();
// Rebuild admin entry using stored promotion transaction reference // Rebuild admin entry using stored reference to transaction that causes adminship
GroupAdminData groupAdminData = new GroupAdminData(groupName, admin, removeGroupAdminTransactionData.getGroupReference()); this.rebuildAdmin(admin, removeGroupAdminTransactionData.getAdminReference());
groupRepository.save(groupAdminData);
// Clean cached reference in this transaction
removeGroupAdminTransactionData.setAdminReference(null);
} }
public void kick(GroupKickTransactionData groupKickTransactionData) throws DataException { public void kick(GroupKickTransactionData groupKickTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = groupKickTransactionData.getGroupName();
String member = groupKickTransactionData.getMember(); String member = groupKickTransactionData.getMember();
// If pending join request then this is a essentially a deny response so delete join request and exit // If there is a pending join request then this is a essentially a deny response so delete join request and exit
if (groupRepository.joinRequestExists(groupName, member)) { GroupJoinRequestData groupJoinRequestData = this.getJoinRequest(member);
if (groupJoinRequestData != null) {
// Save reference to the transaction that created join request so we can rebuild join request during orphaning.
groupKickTransactionData.setJoinReference(groupJoinRequestData.getReference());
// Delete join request // Delete join request
groupRepository.deleteJoinRequest(groupName, member); this.deleteJoinRequest(member);
// Make sure kick transaction's member/admin-references are null to indicate that there // Make sure kick transaction's member/admin-references are null to indicate that there
// was no existing member but actually only a join request. This should prevent orphaning code // was no existing member but actually only a join request. This should prevent orphaning code
@ -253,271 +378,298 @@ public class Group {
groupKickTransactionData.setAdminReference(null); groupKickTransactionData.setAdminReference(null);
return; return;
} else {
// Clear any cached join reference
groupKickTransactionData.setJoinReference(null);
} }
// Store membership and (optionally) adminship transactions for orphaning purposes GroupAdminData groupAdminData = this.getAdmin(member);
GroupAdminData groupAdminData = groupRepository.getAdmin(groupName, member);
if (groupAdminData != null) { if (groupAdminData != null) {
groupKickTransactionData.setAdminReference(groupAdminData.getGroupReference()); // Save reference to the transaction that caused adminship so we can rebuild adminship during orphaning.
groupKickTransactionData.setAdminReference(groupAdminData.getReference());
groupRepository.deleteAdmin(groupName, member); // Kicked, so no longer an admin
this.deleteAdmin(member);
} else { } else {
// Not an admin // Not an admin so no reference
groupKickTransactionData.setAdminReference(null); groupKickTransactionData.setAdminReference(null);
} }
GroupMemberData groupMemberData = groupRepository.getMember(groupName, member); GroupMemberData groupMemberData = this.getMember(member);
groupKickTransactionData.setMemberReference(groupMemberData.getGroupReference()); // Save reference to the transaction that caused membership so we can rebuild membership during orphaning.
groupKickTransactionData.setMemberReference(groupMemberData.getReference());
groupRepository.deleteMember(groupName, member); // Kicked, so no longer a member
this.deleteMember(member);
} }
public void unkick(GroupKickTransactionData groupKickTransactionData) throws DataException { public void unkick(GroupKickTransactionData groupKickTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = groupKickTransactionData.getGroupName();
String member = groupKickTransactionData.getMember(); String member = groupKickTransactionData.getMember();
// If there's no member-reference then there wasn't an actual member, only a join request // If there's no cached reference to the transaction that caused membership then the kick was only a deny response to a join-request.
if (groupKickTransactionData.getMemberReference() == null) { byte[] joinReference = groupKickTransactionData.getJoinReference();
if (joinReference != null) {
// Rebuild join-request // Rebuild join-request
GroupJoinRequestData groupJoinRequestData = new GroupJoinRequestData(groupName, member); this.rebuildJoinRequest(member, joinReference);
groupRepository.save(groupJoinRequestData);
return; return;
} }
// Rebuild member entry using stored transaction reference // Rebuild member entry using stored transaction reference
TransactionData membershipTransactionData = this.repository.getTransactionRepository().fromSignature(groupKickTransactionData.getMemberReference()); this.rebuildMember(member, groupKickTransactionData.getMemberReference());
GroupMemberData groupMemberData = new GroupMemberData(groupName, member, membershipTransactionData.getTimestamp(),
membershipTransactionData.getSignature());
groupRepository.save(groupMemberData);
if (groupKickTransactionData.getAdminReference() != null) { if (groupKickTransactionData.getAdminReference() != null)
// Rebuild admin entry using stored transaction reference // Rebuild admin entry using stored transaction reference
GroupAdminData groupAdminData = new GroupAdminData(groupName, member, groupKickTransactionData.getAdminReference()); this.rebuildAdmin(member, groupKickTransactionData.getAdminReference());
groupRepository.save(groupAdminData);
} // Clean cached references to transactions used to rebuild member/admin info
groupKickTransactionData.setMemberReference(null);
groupKickTransactionData.setAdminReference(null);
} }
public void ban(GroupBanTransactionData groupBanTransactionData) throws DataException { public void ban(GroupBanTransactionData groupBanTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = groupBanTransactionData.getGroupName();
String offender = groupBanTransactionData.getOffender(); String offender = groupBanTransactionData.getOffender();
// Kick if member // Kick if member
if (groupRepository.memberExists(groupName, offender)) { if (this.memberExists(offender)) {
// Store membership and (optionally) adminship transactions for orphaning purposes GroupAdminData groupAdminData = this.getAdmin(offender);
GroupAdminData groupAdminData = groupRepository.getAdmin(groupName, offender);
if (groupAdminData != null) { if (groupAdminData != null) {
groupBanTransactionData.setAdminReference(groupAdminData.getGroupReference()); // Save reference to the transaction that caused adminship so we can revert if orphaning.
groupBanTransactionData.setAdminReference(groupAdminData.getReference());
groupRepository.deleteAdmin(groupName, offender); // Kicked, so no longer an admin
this.deleteAdmin(offender);
} else { } else {
// Not an admin // Not an admin so no reference
groupBanTransactionData.setAdminReference(null); groupBanTransactionData.setAdminReference(null);
} }
GroupMemberData groupMemberData = groupRepository.getMember(groupName, offender); GroupMemberData groupMemberData = this.getMember(offender);
groupBanTransactionData.setMemberReference(groupMemberData.getGroupReference()); // Save reference to the transaction that caused membership so we can revert if orphaning.
groupBanTransactionData.setMemberReference(groupMemberData.getReference());
groupRepository.deleteMember(groupName, offender); // Kicked, so no longer a member
this.deleteMember(offender);
} else { } else {
groupBanTransactionData.setMemberReference(null); // If there is a pending join request then this is a essentially a deny response so delete join request
GroupJoinRequestData groupJoinRequestData = this.getJoinRequest(offender);
if (groupJoinRequestData != null) {
// Save reference to join request so we can rebuild join request if orphaning,
// and differentiate between needing to rebuild join request and rebuild invite.
groupBanTransactionData.setJoinInviteReference(groupJoinRequestData.getReference());
// XXX maybe set join-request reference here? // Delete join request
// XXX what about invites? this.deleteJoinRequest(offender);
}
// XXX Delete pending join request // Make sure kick transaction's member/admin-references are null to indicate that there
// XXX Delete pending invites // was no existing member but actually only a join request. This should prevent orphaning code
// from trying to incorrectly recreate a member/admin.
groupBanTransactionData.setMemberReference(null);
groupBanTransactionData.setAdminReference(null);
} else {
// No join request, but there could be a pending invite
GroupInviteData groupInviteData = this.getInvite(offender);
if (groupInviteData != null) {
// Save reference to invite so we can rebuild invite if orphaning,
// and differentiate between needing to rebuild join request and rebuild invite.
groupBanTransactionData.setJoinInviteReference(groupInviteData.getReference());
// Ban // Delete invite
Account admin = new PublicKeyAccount(this.repository, groupBanTransactionData.getAdminPublicKey()); this.deleteInvite(offender);
long banned = groupBanTransactionData.getTimestamp();
String reason = groupBanTransactionData.getReason();
Long expiry = null; // Make sure kick transaction's member/admin-references are null to indicate that there
int timeToLive = groupBanTransactionData.getTimeToLive(); // was no existing member but actually only a join request. This should prevent orphaning code
if (timeToLive != 0) // from trying to incorrectly recreate a member/admin.
expiry = groupBanTransactionData.getTimestamp() + timeToLive * 1000; groupBanTransactionData.setMemberReference(null);
groupBanTransactionData.setAdminReference(null);
// Save reference to banning transaction for orphaning purposes }
byte[] reference = groupBanTransactionData.getSignature();
GroupBanData groupBanData = new GroupBanData(groupName, offender, admin.getAddress(), banned, reason, expiry, reference);
groupRepository.save(groupBanData);
}
public void unban(GroupBanTransactionData groupBanTransactionData) throws DataException {
// Orphaning version of "ban" - not actual "unban"
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = groupBanTransactionData.getGroupName();
String offender = groupBanTransactionData.getOffender();
// If was kicked as part of ban then reinstate
if (groupBanTransactionData.getMemberReference() != null) {
// Rebuild member entry using stored transaction reference
TransactionData membershipTransactionData = this.repository.getTransactionRepository().fromSignature(groupBanTransactionData.getMemberReference());
GroupMemberData groupMemberData = new GroupMemberData(groupName, offender, membershipTransactionData.getTimestamp(),
membershipTransactionData.getSignature());
groupRepository.save(groupMemberData);
if (groupBanTransactionData.getAdminReference() != null) {
// Rebuild admin entry using stored transaction reference
GroupAdminData groupAdminData = new GroupAdminData(groupName, offender, groupBanTransactionData.getAdminReference());
groupRepository.save(groupAdminData);
} }
} }
// XXX Reinstate pending join request // Create ban
// XXX Reinstate pending invites this.addBan(groupBanTransactionData);
// Delete ban
groupRepository.deleteBan(groupName, offender);
} }
public void cancelBan(GroupUnbanTransactionData groupUnbanTransactionData) throws DataException { public void unban(GroupBanTransactionData groupBanTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository(); // Orphaning version of "ban" - not "cancel-ban"!
String groupName = groupUnbanTransactionData.getGroupName(); String offender = groupBanTransactionData.getOffender();
// Delete ban
groupRepository.deleteBan(this.groupData.getGroupId(), offender);
// If member was kicked as part of ban then reinstate
if (groupBanTransactionData.getMemberReference() != null) {
this.rebuildMember(offender, groupBanTransactionData.getMemberReference());
if (groupBanTransactionData.getAdminReference() != null)
// Rebuild admin entry using stored transaction reference
this.rebuildAdmin(offender, groupBanTransactionData.getAdminReference());
} else {
// Do we need to reinstate pending invite or join-request?
byte[] groupReference = groupBanTransactionData.getJoinInviteReference();
if (groupReference != null) {
TransactionData transactionData = this.repository.getTransactionRepository().fromSignature(groupReference);
switch (transactionData.getType()) {
case GROUP_INVITE:
// Reinstate invite
this.rebuildInvite(offender, groupReference);
break;
case JOIN_GROUP:
// Rebuild join-request
this.rebuildJoinRequest(offender, groupReference);
break;
default:
throw new IllegalStateException("Unable to revert group transaction due to unsupported referenced transaction");
}
}
}
}
public void cancelBan(CancelGroupBanTransactionData groupUnbanTransactionData) throws DataException {
String member = groupUnbanTransactionData.getMember(); String member = groupUnbanTransactionData.getMember();
GroupBanData groupBanData = groupRepository.getBan(groupName, member); GroupBanData groupBanData = groupRepository.getBan(this.groupData.getGroupId(), member);
// Save reference to banning transaction for orphaning purposes // Save reference to banning transaction for orphaning purposes
groupUnbanTransactionData.setGroupReference(groupBanData.getReference()); groupUnbanTransactionData.setBanReference(groupBanData.getReference());
// Delete ban // Delete ban
groupRepository.deleteBan(groupName, member); groupRepository.deleteBan(this.groupData.getGroupId(), member);
} }
public void uncancelBan(GroupUnbanTransactionData groupUnbanTransactionData) throws DataException { public void uncancelBan(CancelGroupBanTransactionData groupUnbanTransactionData) throws DataException {
// Reinstate ban // Reinstate ban using cached reference to banning transaction, stored in our transaction
TransactionData transactionData = this.repository.getTransactionRepository().fromSignature(groupUnbanTransactionData.getGroupReference()); TransactionData transactionData = this.repository.getTransactionRepository().fromSignature(groupUnbanTransactionData.getBanReference());
ban((GroupBanTransactionData) transactionData); this.addBan((GroupBanTransactionData) transactionData);
groupUnbanTransactionData.setGroupReference(null); // Clear cached reference to banning transaction
groupUnbanTransactionData.setBanReference(null);
} }
public void invite(GroupInviteTransactionData groupInviteTransactionData) throws DataException { public void invite(GroupInviteTransactionData groupInviteTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository(); String invitee = groupInviteTransactionData.getInvitee();
String groupName = groupInviteTransactionData.getGroupName();
Account inviter = new PublicKeyAccount(this.repository, groupInviteTransactionData.getAdminPublicKey());
// If there is a pending "join request" then add new group member // If there is a pending "join request" then add new group member
if (groupRepository.joinRequestExists(groupName, groupInviteTransactionData.getInvitee())) { GroupJoinRequestData groupJoinRequestData = this.getJoinRequest(invitee);
GroupMemberData groupMemberData = new GroupMemberData(groupName, groupInviteTransactionData.getInvitee(), groupInviteTransactionData.getTimestamp(), if (groupJoinRequestData != null) {
groupInviteTransactionData.getSignature()); this.addMember(invitee, groupInviteTransactionData);
groupRepository.save(groupMemberData);
// Save reference to transaction that created join request so we can rebuild join request during orphaning.
groupInviteTransactionData.setJoinReference(groupJoinRequestData.getReference());
// Delete join request // Delete join request
groupRepository.deleteJoinRequest(groupName, groupInviteTransactionData.getInvitee()); this.deleteJoinRequest(invitee);
return; return;
} }
Long expiry = null; this.addInvite(groupInviteTransactionData);
int timeToLive = groupInviteTransactionData.getTimeToLive();
if (timeToLive != 0)
expiry = groupInviteTransactionData.getTimestamp() + timeToLive * 1000;
GroupInviteData groupInviteData = new GroupInviteData(groupName, inviter.getAddress(), groupInviteTransactionData.getInvitee(), expiry,
groupInviteTransactionData.getSignature());
groupRepository.save(groupInviteData);
} }
public void uninvite(GroupInviteTransactionData groupInviteTransactionData) throws DataException { public void uninvite(GroupInviteTransactionData groupInviteTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = groupInviteTransactionData.getGroupName();
Account inviter = new PublicKeyAccount(this.repository, groupInviteTransactionData.getAdminPublicKey());
String invitee = groupInviteTransactionData.getInvitee(); String invitee = groupInviteTransactionData.getInvitee();
// Put back any "join request" // If member exists then they were added when invite matched join request
if (groupRepository.memberExists(groupName, invitee)) { if (this.memberExists(invitee)) {
GroupJoinRequestData groupJoinRequestData = new GroupJoinRequestData(groupName, invitee); // Rebuild join request using cached reference to transaction that created join request.
groupRepository.save(groupJoinRequestData); this.rebuildJoinRequest(invitee, groupInviteTransactionData.getJoinReference());
// Delete member // Delete member
groupRepository.deleteMember(groupName, invitee); this.deleteMember(invitee);
// Clear cached reference
groupInviteTransactionData.setJoinReference(null);
} }
// Delete invite // Delete invite
groupRepository.deleteInvite(groupName, inviter.getAddress(), invitee); this.deleteInvite(invitee);
} }
public void cancelInvite(CancelGroupInviteTransactionData cancelGroupInviteTransactionData) throws DataException { public void cancelInvite(CancelGroupInviteTransactionData cancelGroupInviteTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = cancelGroupInviteTransactionData.getGroupName();
Account inviter = new PublicKeyAccount(this.repository, cancelGroupInviteTransactionData.getAdminPublicKey());
String invitee = cancelGroupInviteTransactionData.getInvitee(); String invitee = cancelGroupInviteTransactionData.getInvitee();
// Save invite's transaction signature for orphaning purposes // Save reference to invite transaction so invite can be rebuilt during orphaning.
GroupInviteData groupInviteData = groupRepository.getInvite(groupName, inviter.getAddress(), invitee); GroupInviteData groupInviteData = this.getInvite(invitee);
cancelGroupInviteTransactionData.setGroupReference(groupInviteData.getReference()); cancelGroupInviteTransactionData.setInviteReference(groupInviteData.getReference());
// Delete invite // Delete invite
groupRepository.deleteInvite(groupName, inviter.getAddress(), invitee); this.deleteInvite(invitee);
} }
public void uncancelInvite(CancelGroupInviteTransactionData cancelGroupInviteTransactionData) throws DataException { public void uncancelInvite(CancelGroupInviteTransactionData cancelGroupInviteTransactionData) throws DataException {
// Reinstate invite // Reinstate invite
TransactionData transactionData = this.repository.getTransactionRepository().fromSignature(cancelGroupInviteTransactionData.getGroupReference()); TransactionData transactionData = this.repository.getTransactionRepository().fromSignature(cancelGroupInviteTransactionData.getInviteReference());
invite((GroupInviteTransactionData) transactionData); this.addInvite((GroupInviteTransactionData) transactionData);
cancelGroupInviteTransactionData.setGroupReference(null); // Clear cached reference to invite transaction
cancelGroupInviteTransactionData.setInviteReference(null);
} }
public void join(JoinGroupTransactionData joinGroupTransactionData) throws DataException { public void join(JoinGroupTransactionData joinGroupTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = joinGroupTransactionData.getGroupName();
Account joiner = new PublicKeyAccount(this.repository, joinGroupTransactionData.getJoinerPublicKey()); Account joiner = new PublicKeyAccount(this.repository, joinGroupTransactionData.getJoinerPublicKey());
// Set invite transactions' group-reference to this transaction's signature so the invites can be put back if we orphan this join // Any pending invite?
// Delete any pending invites GroupInviteData groupInviteData = this.getInvite(joiner.getAddress());
List<GroupInviteData> invites = groupRepository.getInvitesByInvitee(groupName, joiner.getAddress());
for (GroupInviteData invite : invites) {
TransactionData transactionData = this.repository.getTransactionRepository().fromSignature(invite.getReference());
((GroupInviteTransactionData) transactionData).setGroupReference(joinGroupTransactionData.getSignature());
groupRepository.deleteInvite(groupName, invite.getInviter(), joiner.getAddress()); // If there is no invites and this group is "closed" (i.e. invite-only) then
}
// If there were no invites and this group is "closed" (i.e. invite-only) then
// this is now a pending "join request" // this is now a pending "join request"
if (invites.isEmpty() && !groupData.getIsOpen()) { if (groupInviteData == null && !groupData.getIsOpen()) {
GroupJoinRequestData groupJoinRequestData = new GroupJoinRequestData(groupName, joiner.getAddress()); // Save join request
groupRepository.save(groupJoinRequestData); this.addJoinRequest(joiner.getAddress(), joinGroupTransactionData.getSignature());
// Clear any reference to invite transaction to prevent invite rebuild during orphaning.
joinGroupTransactionData.setInviteReference(null);
return; return;
} }
// Actually add new member to group // Any invite?
GroupMemberData groupMemberData = new GroupMemberData(groupName, joiner.getAddress(), joinGroupTransactionData.getTimestamp(), if (groupInviteData != null) {
joinGroupTransactionData.getSignature()); // Save reference to invite transaction so invite can be rebuilt during orphaning.
groupRepository.save(groupMemberData); joinGroupTransactionData.setInviteReference(groupInviteData.getReference());
// Delete invite
this.deleteInvite(joiner.getAddress());
} else {
// Clear any reference to invite transaction to prevent invite rebuild during orphaning.
joinGroupTransactionData.setInviteReference(null);
}
// Actually add new member to group
this.addMember(joiner.getAddress(), joinGroupTransactionData);
} }
public void unjoin(JoinGroupTransactionData joinGroupTransactionData) throws DataException { public void unjoin(JoinGroupTransactionData joinGroupTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = joinGroupTransactionData.getGroupName();
Account joiner = new PublicKeyAccount(this.repository, joinGroupTransactionData.getJoinerPublicKey()); Account joiner = new PublicKeyAccount(this.repository, joinGroupTransactionData.getJoinerPublicKey());
groupRepository.deleteMember(groupName, joiner.getAddress()); byte[] inviteReference = joinGroupTransactionData.getInviteReference();
// Put back any pending invites // Was this a join-request only?
List<GroupInviteTransactionData> inviteTransactions = this.repository.getTransactionRepository() if (inviteReference == null && !groupData.getIsOpen()) {
.getInvitesWithGroupReference(joinGroupTransactionData.getSignature()); // Delete join request
for (GroupInviteTransactionData inviteTransaction : inviteTransactions) { this.deleteJoinRequest(joiner.getAddress());
this.invite(inviteTransaction);
// Remove group-reference return;
inviteTransaction.setGroupReference(null);
this.repository.getTransactionRepository().save(inviteTransaction);
} }
// Any invite to rebuild?
if (inviteReference != null) {
// Rebuild invite using cache reference to invite transaction
TransactionData transactionData = this.repository.getTransactionRepository().fromSignature(inviteReference);
this.addInvite((GroupInviteTransactionData) transactionData);
// Clear cached reference to invite transaction
joinGroupTransactionData.setInviteReference(null);
}
// Delete member
this.deleteMember(joiner.getAddress());
} }
public void leave(LeaveGroupTransactionData leaveGroupTransactionData) throws DataException { public void leave(LeaveGroupTransactionData leaveGroupTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = leaveGroupTransactionData.getGroupName();
Account leaver = new PublicKeyAccount(this.repository, leaveGroupTransactionData.getLeaverPublicKey()); Account leaver = new PublicKeyAccount(this.repository, leaveGroupTransactionData.getLeaverPublicKey());
// Potentially record reference to transaction that restores previous admin state. // Potentially record reference to transaction that restores previous admin state.
@ -526,41 +678,35 @@ public class Group {
// Owners are also admins, so skip if owner // Owners are also admins, so skip if owner
if (!leaver.getAddress().equals(this.groupData.getOwner())) { if (!leaver.getAddress().equals(this.groupData.getOwner())) {
// Fetch admin data for leaver // Fetch admin data for leaver
GroupAdminData groupAdminData = groupRepository.getAdmin(groupName, leaver.getAddress()); GroupAdminData groupAdminData = this.getAdmin(leaver.getAddress());
if (groupAdminData != null) { if (groupAdminData != null) {
// Leaver is admin - use promotion transaction reference as restore-state reference // Save reference to transaction that caused adminship in our transaction so we can rebuild adminship during orphaning.
leaveGroupTransactionData.setAdminReference(groupAdminData.getGroupReference()); leaveGroupTransactionData.setAdminReference(groupAdminData.getReference());
// Remove as admin // Remove as admin
groupRepository.deleteAdmin(groupName, leaver.getAddress()); this.deleteAdmin(leaver.getAddress());
} }
} }
// Save membership transaction reference // Save reference to transaction that caused membership in our transaction so we can rebuild membership during orphaning.
GroupMemberData groupMemberData = groupRepository.getMember(groupName, leaver.getAddress()); GroupMemberData groupMemberData = this.getMember(leaver.getAddress());
leaveGroupTransactionData.setMemberReference(groupMemberData.getGroupReference()); leaveGroupTransactionData.setMemberReference(groupMemberData.getReference());
// Remove as member // Remove as member
groupRepository.deleteMember(leaveGroupTransactionData.getGroupName(), leaver.getAddress()); this.deleteMember(leaver.getAddress());
} }
public void unleave(LeaveGroupTransactionData leaveGroupTransactionData) throws DataException { public void unleave(LeaveGroupTransactionData leaveGroupTransactionData) throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = leaveGroupTransactionData.getGroupName();
Account leaver = new PublicKeyAccount(this.repository, leaveGroupTransactionData.getLeaverPublicKey()); Account leaver = new PublicKeyAccount(this.repository, leaveGroupTransactionData.getLeaverPublicKey());
// Rejoin as member // Restore membership using cached reference to transaction that caused membership
TransactionData membershipTransactionData = this.repository.getTransactionRepository().fromSignature(leaveGroupTransactionData.getMemberReference()); this.rebuildMember(leaver.getAddress(), leaveGroupTransactionData.getMemberReference());
groupRepository
.save(new GroupMemberData(groupName, leaver.getAddress(), membershipTransactionData.getTimestamp(), membershipTransactionData.getSignature()));
// Put back any admin state based on referenced group-related transaction
byte[] adminTransactionSignature = leaveGroupTransactionData.getAdminReference(); byte[] adminTransactionSignature = leaveGroupTransactionData.getAdminReference();
if (adminTransactionSignature != null) { if (adminTransactionSignature != null)
GroupAdminData groupAdminData = new GroupAdminData(leaveGroupTransactionData.getGroupName(), leaver.getAddress(), adminTransactionSignature); // Restore adminship using cached reference to transaction that caused adminship
groupRepository.save(groupAdminData); this.rebuildAdmin(leaver.getAddress(), adminTransactionSignature);
}
} }
} }

View File

@ -13,81 +13,89 @@ public interface GroupRepository {
// Groups // Groups
public GroupData fromGroupId(int groupId) throws DataException;
public GroupData fromGroupName(String groupName) throws DataException; public GroupData fromGroupName(String groupName) throws DataException;
public boolean groupExists(int groupId) throws DataException;
public boolean groupExists(String groupName) throws DataException; public boolean groupExists(String groupName) throws DataException;
public List<GroupData> getAllGroups() throws DataException; public List<GroupData> getAllGroups() throws DataException;
public List<GroupData> getGroupsByOwner(String address) throws DataException; public List<GroupData> getGroupsByOwner(String address) throws DataException;
public List<GroupData> getGroupsWithMember(String member) throws DataException;
public void save(GroupData groupData) throws DataException; public void save(GroupData groupData) throws DataException;
public void delete(int groupId) throws DataException;
public void delete(String groupName) throws DataException; public void delete(String groupName) throws DataException;
// Group Admins // Group Admins
public GroupAdminData getAdmin(String groupName, String address) throws DataException; public GroupAdminData getAdmin(int groupId, String address) throws DataException;
public boolean adminExists(String groupName, String address) throws DataException; public boolean adminExists(int groupId, String address) throws DataException;
public List<GroupAdminData> getGroupAdmins(String groupName) throws DataException; public List<GroupAdminData> getGroupAdmins(int groupId) throws DataException;
public void save(GroupAdminData groupAdminData) throws DataException; public void save(GroupAdminData groupAdminData) throws DataException;
public void deleteAdmin(String groupName, String address) throws DataException; public void deleteAdmin(int groupId, String address) throws DataException;
// Group Members // Group Members
public GroupMemberData getMember(String groupName, String address) throws DataException; public GroupMemberData getMember(int groupId, String address) throws DataException;
public boolean memberExists(String groupName, String address) throws DataException; public boolean memberExists(int groupId, String address) throws DataException;
public List<GroupMemberData> getGroupMembers(String groupName) throws DataException; public List<GroupMemberData> getGroupMembers(int groupId) throws DataException;
/** Returns number of group members, or null if group doesn't exist */ /** Returns number of group members, or null if group doesn't exist */
public Integer countGroupMembers(String groupName) throws DataException; public Integer countGroupMembers(int groupId) throws DataException;
public void save(GroupMemberData groupMemberData) throws DataException; public void save(GroupMemberData groupMemberData) throws DataException;
public void deleteMember(String groupName, String address) throws DataException; public void deleteMember(int groupId, String address) throws DataException;
// Group Invites // Group Invites
public GroupInviteData getInvite(String groupName, String inviter, String invitee) throws DataException; public GroupInviteData getInvite(int groupId, String invitee) throws DataException;
public boolean inviteExists(String groupName, String invitee) throws DataException; public boolean inviteExists(int groupId, String invitee) throws DataException;
public boolean inviteExists(String groupName, String inviter, String invitee) throws DataException; public List<GroupInviteData> getGroupInvites(int groupId) throws DataException;
public List<GroupInviteData> getGroupInvites(String groupName) throws DataException; public List<GroupInviteData> getInvitesByInvitee(String invitee) throws DataException;
public List<GroupInviteData> getInvitesByInvitee(String groupName, String invitee) throws DataException;
public void save(GroupInviteData groupInviteData) throws DataException; public void save(GroupInviteData groupInviteData) throws DataException;
public void deleteInvite(String groupName, String inviter, String invitee) throws DataException; public void deleteInvite(int groupId, String invitee) throws DataException;
// Group Join Requests // Group Join Requests
public boolean joinRequestExists(String groupName, String joiner) throws DataException; public GroupJoinRequestData getJoinRequest(Integer groupId, String joiner) throws DataException;
public List<GroupJoinRequestData> getGroupJoinRequests(String groupName) throws DataException; public boolean joinRequestExists(int groupId, String joiner) throws DataException;
public List<GroupJoinRequestData> getGroupJoinRequests(int groupId) throws DataException;
public void save(GroupJoinRequestData groupJoinRequestData) throws DataException; public void save(GroupJoinRequestData groupJoinRequestData) throws DataException;
public void deleteJoinRequest(String groupName, String joiner) throws DataException; public void deleteJoinRequest(int groupId, String joiner) throws DataException;
// Group Bans // Group Bans
public GroupBanData getBan(String groupName, String member) throws DataException; public GroupBanData getBan(int groupId, String member) throws DataException;
public boolean banExists(String groupName, String offender) throws DataException; public boolean banExists(int groupId, String offender) throws DataException;
public List<GroupBanData> getGroupBans(String groupName) throws DataException; public List<GroupBanData> getGroupBans(int groupId) throws DataException;
public void save(GroupBanData groupBanData) throws DataException; public void save(GroupBanData groupBanData) throws DataException;
public void deleteBan(String groupName, String offender) throws DataException; public void deleteBan(int groupId, String offender) throws DataException;
} }

View File

@ -2,7 +2,6 @@ package org.qora.repository;
import java.util.List; import java.util.List;
import org.qora.data.transaction.GroupInviteTransactionData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.transaction.Transaction.TransactionType; import org.qora.transaction.Transaction.TransactionType;
@ -53,8 +52,4 @@ public interface TransactionRepository {
public void delete(TransactionData transactionData) throws DataException; public void delete(TransactionData transactionData) throws DataException;
/** Returns transaction data for group invite transactions that have groupReference that matches passed value.
* @throws DataException */
public List<GroupInviteTransactionData> getInvitesWithGroupReference(byte[] groupReference) throws DataException;
} }

View File

@ -91,22 +91,27 @@ public class HSQLDBDatabaseUpdates {
stmt.execute("CREATE TYPE QoraPublicKey AS VARBINARY(32)"); stmt.execute("CREATE TYPE QoraPublicKey AS VARBINARY(32)");
stmt.execute("CREATE TYPE QoraAmount AS DECIMAL(27, 8)"); stmt.execute("CREATE TYPE QoraAmount AS DECIMAL(27, 8)");
stmt.execute("CREATE TYPE GenericDescription AS VARCHAR(4000)"); stmt.execute("CREATE TYPE GenericDescription AS VARCHAR(4000)");
stmt.execute("CREATE TYPE RegisteredName AS VARCHAR(400) COLLATE SQL_TEXT_NO_PAD"); stmt.execute("CREATE TYPE RegisteredName AS VARCHAR(128) COLLATE SQL_TEXT_NO_PAD");
stmt.execute("CREATE TYPE NameData AS VARCHAR(4000)"); stmt.execute("CREATE TYPE NameData AS VARCHAR(4000)");
stmt.execute("CREATE TYPE PollName AS VARCHAR(400) COLLATE SQL_TEXT_NO_PAD"); stmt.execute("CREATE TYPE MessageData AS VARBINARY(4000)");
stmt.execute("CREATE TYPE PollOption AS VARCHAR(400) COLLATE SQL_TEXT_UCC_NO_PAD"); stmt.execute("CREATE TYPE PollName AS VARCHAR(128) COLLATE SQL_TEXT_NO_PAD");
stmt.execute("CREATE TYPE PollOption AS VARCHAR(80) COLLATE SQL_TEXT_UCC_NO_PAD");
stmt.execute("CREATE TYPE PollOptionIndex AS INTEGER"); stmt.execute("CREATE TYPE PollOptionIndex AS INTEGER");
stmt.execute("CREATE TYPE DataHash AS VARBINARY(32)"); stmt.execute("CREATE TYPE DataHash AS VARBINARY(32)");
stmt.execute("CREATE TYPE AssetID AS BIGINT"); stmt.execute("CREATE TYPE AssetID AS BIGINT");
stmt.execute("CREATE TYPE AssetName AS VARCHAR(400) COLLATE SQL_TEXT_NO_PAD"); stmt.execute("CREATE TYPE AssetName AS VARCHAR(34) COLLATE SQL_TEXT_NO_PAD");
stmt.execute("CREATE TYPE AssetOrderID AS VARBINARY(64)"); stmt.execute("CREATE TYPE AssetOrderID AS VARBINARY(64)");
stmt.execute("CREATE TYPE ATName AS VARCHAR(200) COLLATE SQL_TEXT_UCC_NO_PAD"); stmt.execute("CREATE TYPE ATName AS VARCHAR(32) COLLATE SQL_TEXT_UCC_NO_PAD");
stmt.execute("CREATE TYPE ATType AS VARCHAR(200) COLLATE SQL_TEXT_UCC_NO_PAD"); stmt.execute("CREATE TYPE ATType AS VARCHAR(32) COLLATE SQL_TEXT_UCC_NO_PAD");
stmt.execute("CREATE TYPE ATTags AS VARCHAR(32) COLLATE SQL_TEXT_UCC_NO_PAD");
stmt.execute("CREATE TYPE ATCode AS BLOB(64K)"); // 16bit * 1 stmt.execute("CREATE TYPE ATCode AS BLOB(64K)"); // 16bit * 1
stmt.execute("CREATE TYPE ATState AS BLOB(1M)"); // 16bit * 8 + 16bit * 4 + 16bit * 4 stmt.execute("CREATE TYPE ATState AS BLOB(1M)"); // 16bit * 8 + 16bit * 4 + 16bit * 4
stmt.execute("CREATE TYPE ATCreationBytes AS BLOB(576K)"); // 16bit * 1 + 16bit * 8
stmt.execute("CREATE TYPE ATStateHash as VARBINARY(32)"); stmt.execute("CREATE TYPE ATStateHash as VARBINARY(32)");
stmt.execute("CREATE TYPE ATMessage AS VARBINARY(256)"); stmt.execute("CREATE TYPE ATMessage AS VARBINARY(256)");
stmt.execute("CREATE TYPE GroupID AS INTEGER");
stmt.execute("CREATE TYPE GroupName AS VARCHAR(400) COLLATE SQL_TEXT_UCC_NO_PAD"); stmt.execute("CREATE TYPE GroupName AS VARCHAR(400) COLLATE SQL_TEXT_UCC_NO_PAD");
stmt.execute("CREATE TYPE GroupReason AS VARCHAR(128) COLLATE SQL_TEXT_UCC_NO_PAD");
break; break;
case 1: case 1:
@ -283,8 +288,8 @@ public class HSQLDBDatabaseUpdates {
case 19: case 19:
// Deploy CIYAM AT Transactions // Deploy CIYAM AT Transactions
stmt.execute("CREATE TABLE DeployATTransactions (signature Signature, creator QoraPublicKey NOT NULL, AT_name ATName NOT NULL, " stmt.execute("CREATE TABLE DeployATTransactions (signature Signature, creator QoraPublicKey NOT NULL, AT_name ATName NOT NULL, "
+ "description VARCHAR(2000) NOT NULL, AT_type ATType NOT NULL, AT_tags VARCHAR(200) NOT NULL, " + "description GenericDescription NOT NULL, AT_type ATType NOT NULL, AT_tags ATTags NOT NULL, "
+ "creation_bytes VARBINARY(100000) NOT NULL, amount QoraAmount NOT NULL, asset_id AssetID NOT NULL, AT_address QoraAddress, " + "creation_bytes ATCreationBytes NOT NULL, amount QoraAmount NOT NULL, asset_id AssetID NOT NULL, AT_address QoraAddress, "
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); + "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
// For looking up the Deploy AT Transaction based on deployed AT address // For looking up the Deploy AT Transaction based on deployed AT address
stmt.execute("CREATE INDEX DeployATAddressIndex on DeployATTransactions (AT_address)"); stmt.execute("CREATE INDEX DeployATAddressIndex on DeployATTransactions (AT_address)");
@ -294,7 +299,7 @@ public class HSQLDBDatabaseUpdates {
// Message Transactions // Message Transactions
stmt.execute( stmt.execute(
"CREATE TABLE MessageTransactions (signature Signature, version TINYINT NOT NULL, sender QoraPublicKey NOT NULL, recipient QoraAddress NOT NULL, " "CREATE TABLE MessageTransactions (signature Signature, version TINYINT NOT NULL, sender QoraPublicKey NOT NULL, recipient QoraAddress NOT NULL, "
+ "is_text BOOLEAN NOT NULL, is_encrypted BOOLEAN NOT NULL, amount QoraAmount NOT NULL, asset_id AssetID NOT NULL, data VARBINARY(4000) NOT NULL, " + "is_text BOOLEAN NOT NULL, is_encrypted BOOLEAN NOT NULL, amount QoraAmount NOT NULL, asset_id AssetID NOT NULL, data MessageData NOT NULL, "
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); + "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
break; break;
@ -303,7 +308,7 @@ public class HSQLDBDatabaseUpdates {
stmt.execute("CREATE TABLE Assets (asset_id AssetID, owner QoraAddress NOT NULL, " stmt.execute("CREATE TABLE Assets (asset_id AssetID, owner QoraAddress NOT NULL, "
+ "asset_name AssetName NOT NULL, description GenericDescription NOT NULL, " + "asset_name AssetName NOT NULL, description GenericDescription NOT NULL, "
+ "quantity BIGINT NOT NULL, is_divisible BOOLEAN NOT NULL, reference Signature NOT NULL, PRIMARY KEY (asset_id))"); + "quantity BIGINT NOT NULL, is_divisible BOOLEAN NOT NULL, reference Signature NOT NULL, PRIMARY KEY (asset_id))");
// We need a corresponding trigger to make sure new asset_id values are assigned sequentially // We need a corresponding trigger to make sure new asset_id values are assigned sequentially start from 0
stmt.execute( stmt.execute(
"CREATE TRIGGER Asset_ID_Trigger BEFORE INSERT ON Assets REFERENCING NEW ROW AS new_row FOR EACH ROW WHEN (new_row.asset_id IS NULL) " "CREATE TRIGGER Asset_ID_Trigger BEFORE INSERT ON Assets REFERENCING NEW ROW AS new_row FOR EACH ROW WHEN (new_row.asset_id IS NULL) "
+ "SET new_row.asset_id = (SELECT IFNULL(MAX(asset_id) + 1, 0) FROM Assets)"); + "SET new_row.asset_id = (SELECT IFNULL(MAX(asset_id) + 1, 0) FROM Assets)");
@ -359,10 +364,9 @@ public class HSQLDBDatabaseUpdates {
case 26: case 26:
// Registered Names // Registered Names
stmt.execute( stmt.execute("CREATE TABLE Names (name RegisteredName, data NameData NOT NULL, owner QoraAddress NOT NULL, "
"CREATE TABLE Names (name RegisteredName, data VARCHAR(4000) NOT NULL, owner QoraAddress NOT NULL, " + "registered TIMESTAMP WITH TIME ZONE NOT NULL, updated TIMESTAMP WITH TIME ZONE, reference Signature, is_for_sale BOOLEAN NOT NULL, sale_price QoraAmount, "
+ "registered TIMESTAMP WITH TIME ZONE NOT NULL, updated TIMESTAMP WITH TIME ZONE, reference Signature, is_for_sale BOOLEAN NOT NULL, sale_price QoraAmount, " + "PRIMARY KEY (name))");
+ "PRIMARY KEY (name))");
break; break;
case 27: case 27:
@ -394,90 +398,106 @@ public class HSQLDBDatabaseUpdates {
case 28: case 28:
// Account groups // Account groups
stmt.execute("CREATE TABLE AccountGroups (group_name GroupName, owner QoraAddress NOT NULL, description GenericDescription NOT NULL, " stmt.execute(
+ "created TIMESTAMP WITH TIME ZONE NOT NULL, updated TIMESTAMP WITH TIME ZONE, is_open BOOLEAN NOT NULL, " "CREATE TABLE Groups (group_id GroupID, owner QoraAddress NOT NULL, group_name GroupName, description GenericDescription NOT NULL, "
+ "reference Signature, PRIMARY KEY (group_name))"); + "created TIMESTAMP WITH TIME ZONE NOT NULL, updated TIMESTAMP WITH TIME ZONE, is_open BOOLEAN NOT NULL, "
+ "reference Signature, PRIMARY KEY (group_id))");
// We need a corresponding trigger to make sure new group_id values are assigned sequentially starting from 1
stmt.execute(
"CREATE TRIGGER Group_ID_Trigger BEFORE INSERT ON Groups REFERENCING NEW ROW AS new_row FOR EACH ROW WHEN (new_row.group_id IS NULL) "
+ "SET new_row.group_id = (SELECT IFNULL(MAX(group_id) + 1, 1) FROM Groups)");
// For when a user wants to lookup an group by name
stmt.execute("CREATE INDEX GroupNameIndex on Groups (group_name)");
// For finding groups by owner // For finding groups by owner
stmt.execute("CREATE INDEX AccountGroupOwnerIndex ON AccountGroups (owner)"); stmt.execute("CREATE INDEX GroupOwnerIndex ON Groups (owner)");
// Admins // Admins
stmt.execute("CREATE TABLE AccountGroupAdmins (group_name GroupName, admin QoraAddress, group_reference Signature NOT NULL, PRIMARY KEY (group_name, admin))"); stmt.execute("CREATE TABLE GroupAdmins (group_id GroupID, admin QoraAddress, reference Signature NOT NULL, "
+ "PRIMARY KEY (group_id, admin), FOREIGN KEY (group_id) REFERENCES Groups (group_id) ON DELETE CASCADE)");
// For finding groups that address administrates // For finding groups that address administrates
stmt.execute("CREATE INDEX AccountGroupAdminIndex ON AccountGroupAdmins (admin)"); stmt.execute("CREATE INDEX GroupAdminIndex ON GroupAdmins (admin)");
// Members // Members
stmt.execute("CREATE TABLE AccountGroupMembers (group_name GroupName, address QoraAddress, joined TIMESTAMP WITH TIME ZONE NOT NULL, group_reference Signature NOT NULL, " stmt.execute(
+ "PRIMARY KEY (group_name, address))"); "CREATE TABLE GroupMembers (group_id GroupID, address QoraAddress, joined TIMESTAMP WITH TIME ZONE NOT NULL, reference Signature NOT NULL, "
+ "PRIMARY KEY (group_id, address), FOREIGN KEY (group_id) REFERENCES Groups (group_id) ON DELETE CASCADE)");
// For finding groups that address is member // For finding groups that address is member
stmt.execute("CREATE INDEX AccountGroupMemberIndex ON AccountGroupMembers (address)"); stmt.execute("CREATE INDEX GroupMemberIndex ON GroupMembers (address)");
// Invites // Invites
// PRIMARY KEY (invitee + group + inviter) because most queries will be "what have I been invited to?" from UI stmt.execute("CREATE TABLE GroupInvites (group_id GroupID, inviter QoraAddress, invitee QoraAddress, "
stmt.execute("CREATE TABLE AccountGroupInvites (group_name GroupName, inviter QoraAddress, invitee QoraAddress, " + "expiry TIMESTAMP WITH TIME ZONE NOT NULL, reference Signature, "
+ "expiry TIMESTAMP WITH TIME ZONE NOT NULL, reference Signature, PRIMARY KEY (invitee, group_name, inviter))"); + "PRIMARY KEY (group_id, invitee), FOREIGN KEY (group_id) REFERENCES Groups (group_id) ON DELETE CASCADE)");
// For finding invites sent by inviter // For finding invites sent by inviter
stmt.execute("CREATE INDEX AccountGroupSentInviteIndex ON AccountGroupInvites (inviter)"); stmt.execute("CREATE INDEX GroupInviteInviterIndex ON GroupInvites (inviter)");
// For finding invites by group // For finding invites by group
stmt.execute("CREATE INDEX AccountGroupInviteIndex ON AccountGroupInvites (group_name)"); stmt.execute("CREATE INDEX GroupInviteInviteeIndex ON GroupInvites (invitee)");
// For expiry maintenance // For expiry maintenance
stmt.execute("CREATE INDEX AccountGroupInviteExpiryIndex ON AccountGroupInvites (expiry)"); stmt.execute("CREATE INDEX GroupInviteExpiryIndex ON GroupInvites (expiry)");
// Pending "join requests" // Pending "join requests"
stmt.execute("CREATE TABLE AccountGroupJoinRequests (group_name GroupName, joiner QoraAddress, " stmt.execute(
+ "PRIMARY KEY (group_name, joiner))"); "CREATE TABLE GroupJoinRequests (group_id GroupID, joiner QoraAddress, reference Signature NOT NULL, PRIMARY KEY (group_id, joiner))");
// Bans // Bans
// NULL expiry means does not expire! // NULL expiry means does not expire!
stmt.execute("CREATE TABLE AccountGroupBans (group_name GroupName, offender QoraAddress, admin QoraAddress NOT NULL, banned TIMESTAMP WITH TIME ZONE NOT NULL, " stmt.execute(
+ "reason GenericDescription NOT NULL, expiry TIMESTAMP WITH TIME ZONE, reference Signature NOT NULL, " "CREATE TABLE GroupBans (group_id GroupID, offender QoraAddress, admin QoraAddress NOT NULL, banned TIMESTAMP WITH TIME ZONE NOT NULL, "
+ "PRIMARY KEY (group_name, offender))"); + "reason GenericDescription NOT NULL, expiry TIMESTAMP WITH TIME ZONE, reference Signature NOT NULL, "
+ "PRIMARY KEY (group_id, offender), FOREIGN KEY (group_id) REFERENCES Groups (group_id) ON DELETE CASCADE)");
// For expiry maintenance // For expiry maintenance
stmt.execute("CREATE INDEX AccountGroupBanExpiryIndex ON AccountGroupBans (expiry)"); stmt.execute("CREATE INDEX GroupBanExpiryIndex ON GroupBans (expiry)");
break; break;
case 29: case 29:
// Account group transactions // Account group transactions
stmt.execute("CREATE TABLE CreateGroupTransactions (signature Signature, creator QoraPublicKey NOT NULL, group_name GroupName NOT NULL, " stmt.execute("CREATE TABLE CreateGroupTransactions (signature Signature, creator QoraPublicKey NOT NULL, group_name GroupName NOT NULL, "
+ "owner QoraAddress NOT NULL, description GenericDescription NOT NULL, is_open BOOLEAN NOT NULL, " + "owner QoraAddress NOT NULL, description GenericDescription NOT NULL, is_open BOOLEAN NOT NULL, group_id GroupID, "
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); + "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
stmt.execute("CREATE TABLE UpdateGroupTransactions (signature Signature, owner QoraPublicKey NOT NULL, group_name GroupName NOT NULL, " stmt.execute("CREATE TABLE UpdateGroupTransactions (signature Signature, owner QoraPublicKey NOT NULL, group_id GroupID NOT NULL, "
+ "new_owner QoraAddress NOT NULL, new_description GenericDescription NOT NULL, new_is_open BOOLEAN NOT NULL, group_reference Signature, " + "new_owner QoraAddress NOT NULL, new_description GenericDescription NOT NULL, new_is_open BOOLEAN NOT NULL, group_reference Signature, "
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); + "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
// Account group add/remove admin transactions // Account group add/remove admin transactions
stmt.execute("CREATE TABLE AddGroupAdminTransactions (signature Signature, owner QoraPublicKey NOT NULL, group_name GroupName NOT NULL, address QoraAddress NOT NULL, " stmt.execute(
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); "CREATE TABLE AddGroupAdminTransactions (signature Signature, owner QoraPublicKey NOT NULL, group_id GroupID NOT NULL, address QoraAddress NOT NULL, "
stmt.execute("CREATE TABLE RemoveGroupAdminTransactions (signature Signature, owner QoraPublicKey NOT NULL, group_name GroupName NOT NULL, admin QoraAddress NOT NULL, " + "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
+ "group_reference Signature, PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); stmt.execute(
"CREATE TABLE RemoveGroupAdminTransactions (signature Signature, owner QoraPublicKey NOT NULL, group_id GroupID NOT NULL, admin QoraAddress NOT NULL, "
+ "admin_reference Signature, PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
// Account group join/leave transactions // Account group join/leave transactions
stmt.execute("CREATE TABLE JoinGroupTransactions (signature Signature, joiner QoraPublicKey NOT NULL, group_name GroupName NOT NULL, " stmt.execute("CREATE TABLE JoinGroupTransactions (signature Signature, joiner QoraPublicKey NOT NULL, group_id GroupID NOT NULL, "
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); + "invite_reference Signature, PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
stmt.execute("CREATE TABLE LeaveGroupTransactions (signature Signature, leaver QoraPublicKey NOT NULL, group_name GroupName NOT NULL, " stmt.execute("CREATE TABLE LeaveGroupTransactions (signature Signature, leaver QoraPublicKey NOT NULL, group_id GroupID NOT NULL, "
+ "member_reference Signature, admin_reference Signature, " + "member_reference Signature, admin_reference Signature, "
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); + "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
// Account group kick transaction // Account group kick transaction
stmt.execute("CREATE TABLE GroupKickTransactions (signature Signature, admin QoraPublicKey NOT NULL, group_name GroupName NOT NULL, address QoraAddress NOT NULL, " stmt.execute(
+ "reason VARCHAR(400), member_reference Signature, admin_reference Signature, " "CREATE TABLE GroupKickTransactions (signature Signature, admin QoraPublicKey NOT NULL, group_id GroupID NOT NULL, address QoraAddress NOT NULL, "
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); + "reason GroupReason, member_reference Signature, admin_reference Signature, join_reference Signature, "
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
// Account group invite/cancel-invite transactions // Account group invite/cancel-invite transactions
stmt.execute("CREATE TABLE GroupInviteTransactions (signature Signature, admin QoraPublicKey NOT NULL, group_name GroupName NOT NULL, invitee QoraAddress NOT NULL, " stmt.execute(
+ "time_to_live INTEGER NOT NULL, group_reference Signature, " "CREATE TABLE GroupInviteTransactions (signature Signature, admin QoraPublicKey NOT NULL, group_id GroupID NOT NULL, invitee QoraAddress NOT NULL, "
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); + "time_to_live INTEGER NOT NULL, join_reference Signature, "
// For finding invite transactions during orphaning + "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
stmt.execute("CREATE INDEX GroupInviteTransactionReferenceIndex ON GroupInviteTransactions (group_reference)");
// Cancel group invite // Cancel group invite
stmt.execute("CREATE TABLE CancelGroupInviteTransactions (signature Signature, admin QoraPublicKey NOT NULL, group_name GroupName NOT NULL, invitee QoraAddress NOT NULL, " stmt.execute(
+ "group_reference Signature, PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); "CREATE TABLE CancelGroupInviteTransactions (signature Signature, admin QoraPublicKey NOT NULL, group_id GroupID NOT NULL, invitee QoraAddress NOT NULL, "
+ "invite_reference Signature, PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
// Account ban/unban transactions // Account ban/cancel-ban transactions
stmt.execute("CREATE TABLE GroupBanTransactions (signature Signature, admin QoraPublicKey NOT NULL, group_name GroupName NOT NULL, address QoraAddress NOT NULL, " stmt.execute(
+ "reason VARCHAR(400), time_to_live INTEGER NOT NULL, member_reference Signature, admin_reference Signature, " "CREATE TABLE GroupBanTransactions (signature Signature, admin QoraPublicKey NOT NULL, group_id GroupID NOT NULL, address QoraAddress NOT NULL, "
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); + "reason GroupReason, time_to_live INTEGER NOT NULL, "
stmt.execute("CREATE TABLE GroupUnbanTransactions (signature Signature, admin QoraPublicKey NOT NULL, group_name GroupName NOT NULL, address QoraAddress NOT NULL, " + "member_reference Signature, admin_reference Signature, join_invite_reference Signature, "
+ "group_reference Signature, PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); + "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
stmt.execute(
"CREATE TABLE CancelGroupBanTransactions (signature Signature, admin QoraPublicKey NOT NULL, group_id GroupID NOT NULL, address QoraAddress NOT NULL, "
+ "ban_reference Signature, PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
break; break;
default: default:

View File

@ -27,33 +27,68 @@ public class HSQLDBGroupRepository implements GroupRepository {
// Groups // Groups
@Override @Override
public GroupData fromGroupName(String groupName) throws DataException { public GroupData fromGroupId(int groupId) throws DataException {
try (ResultSet resultSet = this.repository try (ResultSet resultSet = this.repository
.checkedExecute("SELECT owner, description, created, updated, reference, is_open FROM AccountGroups WHERE group_name = ?", groupName)) { .checkedExecute("SELECT group_name, owner, description, created, updated, reference, is_open FROM Groups WHERE group_id = ?", groupId)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
String owner = resultSet.getString(1); String groupName = resultSet.getString(1);
String description = resultSet.getString(2); String owner = resultSet.getString(2);
long created = resultSet.getTimestamp(3, Calendar.getInstance(HSQLDBRepository.UTC)).getTime(); String description = resultSet.getString(3);
long created = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
// Special handling for possibly-NULL "updated" column // Special handling for possibly-NULL "updated" column
Timestamp updatedTimestamp = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC)); Timestamp updatedTimestamp = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC));
Long updated = resultSet.wasNull() ? null : updatedTimestamp.getTime(); Long updated = resultSet.wasNull() ? null : updatedTimestamp.getTime();
byte[] reference = resultSet.getBytes(5); byte[] reference = resultSet.getBytes(6);
boolean isOpen = resultSet.getBoolean(6); boolean isOpen = resultSet.getBoolean(7);
return new GroupData(owner, groupName, description, created, updated, isOpen, reference); return new GroupData(groupId, owner, groupName, description, created, updated, isOpen, reference);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch group info from repository", e); throw new DataException("Unable to fetch group info from repository", e);
} }
} }
@Override
public GroupData fromGroupName(String groupName) throws DataException {
try (ResultSet resultSet = this.repository
.checkedExecute("SELECT group_id, owner, description, created, updated, reference, is_open FROM Groups WHERE group_name = ?", groupName)) {
if (resultSet == null)
return null;
int groupId = resultSet.getInt(1);
String owner = resultSet.getString(2);
String description = resultSet.getString(3);
long created = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
// Special handling for possibly-NULL "updated" column
Timestamp updatedTimestamp = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC));
Long updated = resultSet.wasNull() ? null : updatedTimestamp.getTime();
byte[] reference = resultSet.getBytes(6);
boolean isOpen = resultSet.getBoolean(7);
return new GroupData(groupId, owner, groupName, description, created, updated, isOpen, reference);
} catch (SQLException e) {
throw new DataException("Unable to fetch group info from repository", e);
}
}
@Override
public boolean groupExists(int groupId) throws DataException {
try {
return this.repository.exists("Groups", "group_id = ?", groupId);
} catch (SQLException e) {
throw new DataException("Unable to check for group in repository", e);
}
}
@Override @Override
public boolean groupExists(String groupName) throws DataException { public boolean groupExists(String groupName) throws DataException {
try { try {
return this.repository.exists("AccountGroups", "group_name = ?", groupName); return this.repository.exists("Groups", "group_name = ?", groupName);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to check for group in repository", e); throw new DataException("Unable to check for group in repository", e);
} }
@ -64,24 +99,25 @@ public class HSQLDBGroupRepository implements GroupRepository {
List<GroupData> groups = new ArrayList<>(); List<GroupData> groups = new ArrayList<>();
try (ResultSet resultSet = this.repository try (ResultSet resultSet = this.repository
.checkedExecute("SELECT group_name, description, owner, created, updated, reference, is_open FROM AccountGroups")) { .checkedExecute("SELECT group_id, owner, group_name, description, created, updated, reference, is_open FROM Groups")) {
if (resultSet == null) if (resultSet == null)
return groups; return groups;
do { do {
String groupName = resultSet.getString(1); int groupId = resultSet.getInt(1);
String description = resultSet.getString(2); String owner = resultSet.getString(2);
String owner = resultSet.getString(3); String groupName = resultSet.getString(3);
long created = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC)).getTime(); String description = resultSet.getString(4);
long created = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
// Special handling for possibly-NULL "updated" column // Special handling for possibly-NULL "updated" column
Timestamp updatedTimestamp = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC)); Timestamp updatedTimestamp = resultSet.getTimestamp(6, Calendar.getInstance(HSQLDBRepository.UTC));
Long updated = resultSet.wasNull() ? null : updatedTimestamp.getTime(); Long updated = resultSet.wasNull() ? null : updatedTimestamp.getTime();
byte[] reference = resultSet.getBytes(6); byte[] reference = resultSet.getBytes(7);
boolean isOpen = resultSet.getBoolean(7); boolean isOpen = resultSet.getBoolean(8);
groups.add(new GroupData(owner, groupName, description, created, updated, isOpen, reference)); groups.add(new GroupData(groupId, owner, groupName, description, created, updated, isOpen, reference));
} while (resultSet.next()); } while (resultSet.next());
return groups; return groups;
@ -95,23 +131,57 @@ public class HSQLDBGroupRepository implements GroupRepository {
List<GroupData> groups = new ArrayList<>(); List<GroupData> groups = new ArrayList<>();
try (ResultSet resultSet = this.repository try (ResultSet resultSet = this.repository
.checkedExecute("SELECT group_name, description, created, updated, reference, is_open FROM AccountGroups WHERE owner = ?", owner)) { .checkedExecute("SELECT group_id, group_name, description, created, updated, reference, is_open FROM Groups WHERE owner = ?", owner)) {
if (resultSet == null) if (resultSet == null)
return groups; return groups;
do { do {
String groupName = resultSet.getString(1); int groupId = resultSet.getInt(1);
String description = resultSet.getString(2); String groupName = resultSet.getString(2);
long created = resultSet.getTimestamp(3, Calendar.getInstance(HSQLDBRepository.UTC)).getTime(); String description = resultSet.getString(3);
long created = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
// Special handling for possibly-NULL "updated" column // Special handling for possibly-NULL "updated" column
Timestamp updatedTimestamp = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC)); Timestamp updatedTimestamp = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC));
Long updated = updatedTimestamp == null ? null : updatedTimestamp.getTime(); Long updated = updatedTimestamp == null ? null : updatedTimestamp.getTime();
byte[] reference = resultSet.getBytes(5); byte[] reference = resultSet.getBytes(6);
boolean isOpen = resultSet.getBoolean(6); boolean isOpen = resultSet.getBoolean(7);
groups.add(new GroupData(owner, groupName, description, created, updated, isOpen, reference)); groups.add(new GroupData(groupId, owner, groupName, description, created, updated, isOpen, reference));
} while (resultSet.next());
return groups;
} catch (SQLException e) {
throw new DataException("Unable to fetch account's groups from repository", e);
}
}
@Override
public List<GroupData> getGroupsWithMember(String member) throws DataException {
List<GroupData> groups = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(
"SELECT group_id, owner, group_name, description, created, updated, reference, is_open FROM Groups JOIN GroupMembers USING (group_id) WHERE address = ?",
member)) {
if (resultSet == null)
return groups;
do {
int groupId = resultSet.getInt(1);
String owner = resultSet.getString(2);
String groupName = resultSet.getString(3);
String description = resultSet.getString(4);
long created = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
// Special handling for possibly-NULL "updated" column
Timestamp updatedTimestamp = resultSet.getTimestamp(6, Calendar.getInstance(HSQLDBRepository.UTC));
Long updated = updatedTimestamp == null ? null : updatedTimestamp.getTime();
byte[] reference = resultSet.getBytes(7);
boolean isOpen = resultSet.getBoolean(8);
groups.add(new GroupData(groupId, owner, groupName, description, created, updated, isOpen, reference));
} while (resultSet.next()); } while (resultSet.next());
return groups; return groups;
@ -122,36 +192,48 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override @Override
public void save(GroupData groupData) throws DataException { public void save(GroupData groupData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("AccountGroups"); HSQLDBSaver saveHelper = new HSQLDBSaver("Groups");
// Special handling for "updated" timestamp // Special handling for "updated" timestamp
Long updated = groupData.getUpdated(); Long updated = groupData.getUpdated();
Timestamp updatedTimestamp = updated == null ? null : new Timestamp(updated); Timestamp updatedTimestamp = updated == null ? null : new Timestamp(updated);
saveHelper.bind("owner", groupData.getOwner()).bind("group_name", groupData.getGroupName()).bind("description", groupData.getDescription()) saveHelper.bind("group_id", groupData.getGroupId()).bind("owner", groupData.getOwner()).bind("group_name", groupData.getGroupName())
.bind("created", new Timestamp(groupData.getCreated())).bind("updated", updatedTimestamp).bind("reference", groupData.getReference()) .bind("description", groupData.getDescription()).bind("created", new Timestamp(groupData.getCreated())).bind("updated", updatedTimestamp)
.bind("is_open", groupData.getIsOpen()); .bind("reference", groupData.getReference()).bind("is_open", groupData.getIsOpen());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);
if (groupData.getGroupId() == null) {
// Fetch new groupId
try (ResultSet resultSet = this.repository.checkedExecute("SELECT group_id FROM Groups WHERE reference = ?", groupData.getReference())) {
if (resultSet == null)
throw new DataException("Unable to fetch new group ID from repository");
groupData.setGroupId(resultSet.getInt(1));
}
}
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to save group info into repository", e); throw new DataException("Unable to save group info into repository", e);
} }
} }
@Override
public void delete(int groupId) throws DataException {
try {
// Remove group
this.repository.delete("Groups", "group_id = ?", groupId);
} catch (SQLException e) {
throw new DataException("Unable to delete group info from repository", e);
}
}
@Override @Override
public void delete(String groupName) throws DataException { public void delete(String groupName) throws DataException {
try { try {
// Remove invites
this.repository.delete("AccountGroupInvites", "group_name = ?", groupName);
// Remove bans
this.repository.delete("AccountGroupBans", "group_name = ?", groupName);
// Remove members
this.repository.delete("AccountGroupMembers", "group_name = ?", groupName);
// Remove admins
this.repository.delete("AccountGroupAdmins", "group_name = ?", groupName);
// Remove group // Remove group
this.repository.delete("AccountGroups", "group_name = ?", groupName); this.repository.delete("Groups", "group_name = ?", groupName);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to delete group info from repository", e); throw new DataException("Unable to delete group info from repository", e);
} }
@ -160,42 +242,42 @@ public class HSQLDBGroupRepository implements GroupRepository {
// Group Admins // Group Admins
@Override @Override
public GroupAdminData getAdmin(String groupName, String address) throws DataException { public GroupAdminData getAdmin(int groupId, String address) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT admin, group_reference FROM AccountGroupAdmins WHERE group_name = ?", groupName)) { try (ResultSet resultSet = this.repository.checkedExecute("SELECT admin, reference FROM GroupAdmins WHERE group_id = ?", groupId)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
String admin = resultSet.getString(1); String admin = resultSet.getString(1);
byte[] groupReference = resultSet.getBytes(2); byte[] reference = resultSet.getBytes(2);
return new GroupAdminData(groupName, admin, groupReference); return new GroupAdminData(groupId, admin, reference);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch group admin from repository", e); throw new DataException("Unable to fetch group admin from repository", e);
} }
} }
@Override @Override
public boolean adminExists(String groupName, String address) throws DataException { public boolean adminExists(int groupId, String address) throws DataException {
try { try {
return this.repository.exists("AccountGroupAdmins", "group_name = ? AND admin = ?", groupName, address); return this.repository.exists("GroupAdmins", "group_id = ? AND admin = ?", groupId, address);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to check for group admin in repository", e); throw new DataException("Unable to check for group admin in repository", e);
} }
} }
@Override @Override
public List<GroupAdminData> getGroupAdmins(String groupName) throws DataException { public List<GroupAdminData> getGroupAdmins(int groupId) throws DataException {
List<GroupAdminData> admins = new ArrayList<>(); List<GroupAdminData> admins = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute("SELECT admin, group_reference FROM AccountGroupAdmins WHERE group_name = ?", groupName)) { try (ResultSet resultSet = this.repository.checkedExecute("SELECT admin, reference FROM GroupAdmins WHERE group_id = ?", groupId)) {
if (resultSet == null) if (resultSet == null)
return admins; return admins;
do { do {
String admin = resultSet.getString(1); String admin = resultSet.getString(1);
byte[] groupReference = resultSet.getBytes(2); byte[] reference = resultSet.getBytes(2);
admins.add(new GroupAdminData(groupName, admin, groupReference)); admins.add(new GroupAdminData(groupId, admin, reference));
} while (resultSet.next()); } while (resultSet.next());
return admins; return admins;
@ -206,10 +288,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override @Override
public void save(GroupAdminData groupAdminData) throws DataException { public void save(GroupAdminData groupAdminData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("AccountGroupAdmins"); HSQLDBSaver saveHelper = new HSQLDBSaver("GroupAdmins");
saveHelper.bind("group_name", groupAdminData.getGroupName()).bind("admin", groupAdminData.getAdmin()).bind("group_reference", saveHelper.bind("group_id", groupAdminData.getGroupId()).bind("admin", groupAdminData.getAdmin()).bind("reference", groupAdminData.getReference());
groupAdminData.getGroupReference());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);
@ -219,9 +300,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
} }
@Override @Override
public void deleteAdmin(String groupName, String address) throws DataException { public void deleteAdmin(int groupId, String address) throws DataException {
try { try {
this.repository.delete("AccountGroupAdmins", "group_name = ? AND admin = ?", groupName, address); this.repository.delete("GroupAdmins", "group_id = ? AND admin = ?", groupId, address);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to delete group admin info from repository", e); throw new DataException("Unable to delete group admin info from repository", e);
} }
@ -230,46 +311,44 @@ public class HSQLDBGroupRepository implements GroupRepository {
// Group Members // Group Members
@Override @Override
public GroupMemberData getMember(String groupName, String address) throws DataException { public GroupMemberData getMember(int groupId, String address) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT address, joined, group_reference FROM AccountGroupMembers WHERE group_name = ?", try (ResultSet resultSet = this.repository.checkedExecute("SELECT address, joined, reference FROM GroupMembers WHERE group_id = ?", groupId)) {
groupName)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
String member = resultSet.getString(1); String member = resultSet.getString(1);
long joined = resultSet.getTimestamp(2, Calendar.getInstance(HSQLDBRepository.UTC)).getTime(); long joined = resultSet.getTimestamp(2, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
byte[] groupReference = resultSet.getBytes(3); byte[] reference = resultSet.getBytes(3);
return new GroupMemberData(groupName, member, joined, groupReference); return new GroupMemberData(groupId, member, joined, reference);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch group members from repository", e); throw new DataException("Unable to fetch group members from repository", e);
} }
} }
@Override @Override
public boolean memberExists(String groupName, String address) throws DataException { public boolean memberExists(int groupId, String address) throws DataException {
try { try {
return this.repository.exists("AccountGroupMembers", "group_name = ? AND address = ?", groupName, address); return this.repository.exists("GroupMembers", "group_id = ? AND address = ?", groupId, address);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to check for group member in repository", e); throw new DataException("Unable to check for group member in repository", e);
} }
} }
@Override @Override
public List<GroupMemberData> getGroupMembers(String groupName) throws DataException { public List<GroupMemberData> getGroupMembers(int groupId) throws DataException {
List<GroupMemberData> members = new ArrayList<>(); List<GroupMemberData> members = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute("SELECT address, joined, group_reference FROM AccountGroupMembers WHERE group_name = ?", try (ResultSet resultSet = this.repository.checkedExecute("SELECT address, joined, reference FROM GroupMembers WHERE group_id = ?", groupId)) {
groupName)) {
if (resultSet == null) if (resultSet == null)
return members; return members;
do { do {
String member = resultSet.getString(1); String member = resultSet.getString(1);
long joined = resultSet.getTimestamp(2, Calendar.getInstance(HSQLDBRepository.UTC)).getTime(); long joined = resultSet.getTimestamp(2, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
byte[] groupReference = resultSet.getBytes(3); byte[] reference = resultSet.getBytes(3);
members.add(new GroupMemberData(groupName, member, joined, groupReference)); members.add(new GroupMemberData(groupId, member, joined, reference));
} while (resultSet.next()); } while (resultSet.next());
return members; return members;
@ -279,9 +358,10 @@ public class HSQLDBGroupRepository implements GroupRepository {
} }
@Override @Override
public Integer countGroupMembers(String groupName) throws DataException { public Integer countGroupMembers(int groupId) throws DataException {
try (ResultSet resultSet = this.repository // "GROUP BY" clause required to avoid error "expression not in aggregate or GROUP BY columns: PUBLIC.GROUPS.GROUP_ID"
.checkedExecute("SELECT group_name, COUNT(*) FROM AccountGroupMembers WHERE group_name = ? GROUP BY group_name", groupName)) { try (ResultSet resultSet = this.repository.checkedExecute("SELECT group_id, COUNT(*) FROM GroupMembers WHERE group_id = ? GROUP BY group_id",
groupId)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
@ -293,10 +373,10 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override @Override
public void save(GroupMemberData groupMemberData) throws DataException { public void save(GroupMemberData groupMemberData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("AccountGroupMembers"); HSQLDBSaver saveHelper = new HSQLDBSaver("GroupMembers");
saveHelper.bind("group_name", groupMemberData.getGroupName()).bind("address", groupMemberData.getMember()) saveHelper.bind("group_id", groupMemberData.getGroupId()).bind("address", groupMemberData.getMember())
.bind("joined", new Timestamp(groupMemberData.getJoined())).bind("group_reference", groupMemberData.getGroupReference()); .bind("joined", new Timestamp(groupMemberData.getJoined())).bind("reference", groupMemberData.getReference());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);
@ -306,9 +386,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
} }
@Override @Override
public void deleteMember(String groupName, String address) throws DataException { public void deleteMember(int groupId, String address) throws DataException {
try { try {
this.repository.delete("AccountGroupMembers", "group_name = ? AND address = ?", groupName, address); this.repository.delete("GroupMembers", "group_id = ? AND address = ?", groupId, address);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to delete group member info from repository", e); throw new DataException("Unable to delete group member info from repository", e);
} }
@ -317,46 +397,38 @@ public class HSQLDBGroupRepository implements GroupRepository {
// Group Invites // Group Invites
@Override @Override
public GroupInviteData getInvite(String groupName, String inviter, String invitee) throws DataException { public GroupInviteData getInvite(int groupId, String invitee) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT expiry, reference FROM AccountGroupInvites WHERE group_name = ?", groupName)) { try (ResultSet resultSet = this.repository.checkedExecute("SELECT inviter, expiry, reference FROM GroupInvites WHERE group_id = ? AND invitee = ?",
groupId, invitee)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
Timestamp expiryTimestamp = resultSet.getTimestamp(1, Calendar.getInstance(HSQLDBRepository.UTC)); String inviter = resultSet.getString(1);
Timestamp expiryTimestamp = resultSet.getTimestamp(2, Calendar.getInstance(HSQLDBRepository.UTC));
Long expiry = expiryTimestamp == null ? null : expiryTimestamp.getTime(); Long expiry = expiryTimestamp == null ? null : expiryTimestamp.getTime();
byte[] reference = resultSet.getBytes(2); byte[] reference = resultSet.getBytes(3);
return new GroupInviteData(groupName, inviter, invitee, expiry, reference); return new GroupInviteData(groupId, inviter, invitee, expiry, reference);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch group invite from repository", e); throw new DataException("Unable to fetch group invite from repository", e);
} }
} }
@Override @Override
public boolean inviteExists(String groupName, String invitee) throws DataException { public boolean inviteExists(int groupId, String invitee) throws DataException {
try { try {
return this.repository.exists("AccountGroupInvites", "group_name = ? AND invitee = ?", groupName, invitee); return this.repository.exists("GroupInvites", "group_id = ? AND invitee = ?", groupId, invitee);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to check for group invite in repository", e); throw new DataException("Unable to check for group invite in repository", e);
} }
} }
@Override @Override
public boolean inviteExists(String groupName, String inviter, String invitee) throws DataException { public List<GroupInviteData> getGroupInvites(int groupId) throws DataException {
try {
return this.repository.exists("AccountGroupInvites", "group_name = ? AND inviter = ? AND invitee = ?", groupName, inviter, invitee);
} catch (SQLException e) {
throw new DataException("Unable to check for group invite in repository", e);
}
}
@Override
public List<GroupInviteData> getGroupInvites(String groupName) throws DataException {
List<GroupInviteData> invites = new ArrayList<>(); List<GroupInviteData> invites = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute("SELECT inviter, invitee, expiry, reference FROM AccountGroupInvites WHERE group_name = ?", try (ResultSet resultSet = this.repository.checkedExecute("SELECT inviter, invitee, expiry, reference FROM GroupInvites WHERE group_id = ?", groupId)) {
groupName)) {
if (resultSet == null) if (resultSet == null)
return invites; return invites;
@ -369,7 +441,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
byte[] reference = resultSet.getBytes(4); byte[] reference = resultSet.getBytes(4);
invites.add(new GroupInviteData(groupName, inviter, invitee, expiry, reference)); invites.add(new GroupInviteData(groupId, inviter, invitee, expiry, reference));
} while (resultSet.next()); } while (resultSet.next());
return invites; return invites;
@ -379,23 +451,23 @@ public class HSQLDBGroupRepository implements GroupRepository {
} }
@Override @Override
public List<GroupInviteData> getInvitesByInvitee(String groupName, String invitee) throws DataException { public List<GroupInviteData> getInvitesByInvitee(String invitee) throws DataException {
List<GroupInviteData> invites = new ArrayList<>(); List<GroupInviteData> invites = new ArrayList<>();
try (ResultSet resultSet = this.repository try (ResultSet resultSet = this.repository.checkedExecute("SELECT group_id, inviter, expiry, reference FROM GroupInvites WHERE invitee = ?", invitee)) {
.checkedExecute("SELECT inviter, expiry, reference FROM AccountGroupInvites WHERE group_name = ? AND invitee = ?", groupName, invitee)) {
if (resultSet == null) if (resultSet == null)
return invites; return invites;
do { do {
String inviter = resultSet.getString(1); int groupId = resultSet.getInt(1);
String inviter = resultSet.getString(2);
Timestamp expiryTimestamp = resultSet.getTimestamp(2, Calendar.getInstance(HSQLDBRepository.UTC)); Timestamp expiryTimestamp = resultSet.getTimestamp(3, Calendar.getInstance(HSQLDBRepository.UTC));
Long expiry = expiryTimestamp == null ? null : expiryTimestamp.getTime(); Long expiry = expiryTimestamp == null ? null : expiryTimestamp.getTime();
byte[] reference = resultSet.getBytes(3); byte[] reference = resultSet.getBytes(4);
invites.add(new GroupInviteData(groupName, inviter, invitee, expiry, reference)); invites.add(new GroupInviteData(groupId, inviter, invitee, expiry, reference));
} while (resultSet.next()); } while (resultSet.next());
return invites; return invites;
@ -406,14 +478,14 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override @Override
public void save(GroupInviteData groupInviteData) throws DataException { public void save(GroupInviteData groupInviteData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("AccountGroupInvites"); HSQLDBSaver saveHelper = new HSQLDBSaver("GroupInvites");
Timestamp expiryTimestamp = null; Timestamp expiryTimestamp = null;
if (groupInviteData.getExpiry() != null) if (groupInviteData.getExpiry() != null)
expiryTimestamp = new Timestamp(groupInviteData.getExpiry()); expiryTimestamp = new Timestamp(groupInviteData.getExpiry());
saveHelper.bind("group_name", groupInviteData.getGroupName()).bind("inviter", groupInviteData.getInviter()) saveHelper.bind("group_id", groupInviteData.getGroupId()).bind("inviter", groupInviteData.getInviter()).bind("invitee", groupInviteData.getInvitee())
.bind("invitee", groupInviteData.getInvitee()).bind("expiry", expiryTimestamp).bind("reference", groupInviteData.getReference()); .bind("expiry", expiryTimestamp).bind("reference", groupInviteData.getReference());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);
@ -423,9 +495,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
} }
@Override @Override
public void deleteInvite(String groupName, String inviter, String invitee) throws DataException { public void deleteInvite(int groupId, String invitee) throws DataException {
try { try {
this.repository.delete("AccountGroupInvites", "group_name = ? AND inviter = ? AND invitee = ?", groupName, inviter, invitee); this.repository.delete("GroupInvites", "group_id = ? AND invitee = ?", groupId, invitee);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to delete group invite from repository", e); throw new DataException("Unable to delete group invite from repository", e);
} }
@ -434,26 +506,42 @@ public class HSQLDBGroupRepository implements GroupRepository {
// Group Join Requests // Group Join Requests
@Override @Override
public boolean joinRequestExists(String groupName, String joiner) throws DataException { public GroupJoinRequestData getJoinRequest(Integer groupId, String joiner) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT reference FROM GroupJoinRequests WHERE group_id = ? AND joiner = ?", groupId,
joiner)) {
if (resultSet == null)
return null;
byte[] reference = resultSet.getBytes(1);
return new GroupJoinRequestData(groupId, joiner, reference);
} catch (SQLException e) {
throw new DataException("Unable to fetch group join requests from repository", e);
}
}
@Override
public boolean joinRequestExists(int groupId, String joiner) throws DataException {
try { try {
return this.repository.exists("AccountGroupJoinRequests", "group_name = ? AND joiner = ?", groupName, joiner); return this.repository.exists("GroupJoinRequests", "group_id = ? AND joiner = ?", groupId, joiner);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to check for group join request in repository", e); throw new DataException("Unable to check for group join request in repository", e);
} }
} }
@Override @Override
public List<GroupJoinRequestData> getGroupJoinRequests(String groupName) throws DataException { public List<GroupJoinRequestData> getGroupJoinRequests(int groupId) throws DataException {
List<GroupJoinRequestData> joinRequests = new ArrayList<>(); List<GroupJoinRequestData> joinRequests = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute("SELECT joiner FROM AccountGroupJoinRequests WHERE group_name = ?", groupName)) { try (ResultSet resultSet = this.repository.checkedExecute("SELECT joiner, reference FROM GroupJoinRequests WHERE group_id = ?", groupId)) {
if (resultSet == null) if (resultSet == null)
return joinRequests; return joinRequests;
do { do {
String joiner = resultSet.getString(1); String joiner = resultSet.getString(1);
byte[] reference = resultSet.getBytes(2);
joinRequests.add(new GroupJoinRequestData(groupName, joiner)); joinRequests.add(new GroupJoinRequestData(groupId, joiner, reference));
} while (resultSet.next()); } while (resultSet.next());
return joinRequests; return joinRequests;
@ -464,9 +552,10 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override @Override
public void save(GroupJoinRequestData groupJoinRequestData) throws DataException { public void save(GroupJoinRequestData groupJoinRequestData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("AccountGroupJoinRequests"); HSQLDBSaver saveHelper = new HSQLDBSaver("GroupJoinRequests");
saveHelper.bind("group_name", groupJoinRequestData.getGroupName()).bind("joiner", groupJoinRequestData.getJoiner()); saveHelper.bind("group_id", groupJoinRequestData.getGroupId()).bind("joiner", groupJoinRequestData.getJoiner()).bind("reference",
groupJoinRequestData.getReference());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);
@ -476,9 +565,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
} }
@Override @Override
public void deleteJoinRequest(String groupName, String joiner) throws DataException { public void deleteJoinRequest(int groupId, String joiner) throws DataException {
try { try {
this.repository.delete("AccountGroupJoinRequests", "group_name = ? AND joiner = ?", groupName, joiner); this.repository.delete("GroupJoinRequests", "group_id = ? AND joiner = ?", groupId, joiner);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to delete group join request from repository", e); throw new DataException("Unable to delete group join request from repository", e);
} }
@ -487,40 +576,39 @@ public class HSQLDBGroupRepository implements GroupRepository {
// Group Bans // Group Bans
@Override @Override
public GroupBanData getBan(String groupName, String member) throws DataException { public GroupBanData getBan(int groupId, String offender) throws DataException {
try (ResultSet resultSet = this.repository try (ResultSet resultSet = this.repository
.checkedExecute("SELECT offender, admin, banned, reason, expiry, reference FROM AccountGroupBans WHERE group_name = ?", groupName)) { .checkedExecute("SELECT admin, banned, reason, expiry, reference FROM GroupBans WHERE group_id = ? AND offender = ?", groupId, offender)) {
String offender = resultSet.getString(1); String admin = resultSet.getString(1);
String admin = resultSet.getString(2); long banned = resultSet.getTimestamp(2, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
long banned = resultSet.getTimestamp(3, Calendar.getInstance(HSQLDBRepository.UTC)).getTime(); String reason = resultSet.getString(3);
String reason = resultSet.getString(4);
Timestamp expiryTimestamp = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC)); Timestamp expiryTimestamp = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC));
Long expiry = expiryTimestamp == null ? null : expiryTimestamp.getTime(); Long expiry = expiryTimestamp == null ? null : expiryTimestamp.getTime();
byte[] reference = resultSet.getBytes(6); byte[] reference = resultSet.getBytes(5);
return new GroupBanData(groupName, offender, admin, banned, reason, expiry, reference); return new GroupBanData(groupId, offender, admin, banned, reason, expiry, reference);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch group bans from repository", e); throw new DataException("Unable to fetch group bans from repository", e);
} }
} }
@Override @Override
public boolean banExists(String groupName, String offender) throws DataException { public boolean banExists(int groupId, String offender) throws DataException {
try { try {
return this.repository.exists("AccountGroupBans", "group_name = ? AND offender = ?", groupName, offender); return this.repository.exists("GroupBans", "group_id = ? AND offender = ?", groupId, offender);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to check for group ban in repository", e); throw new DataException("Unable to check for group ban in repository", e);
} }
} }
@Override @Override
public List<GroupBanData> getGroupBans(String groupName) throws DataException { public List<GroupBanData> getGroupBans(int groupId) throws DataException {
List<GroupBanData> bans = new ArrayList<>(); List<GroupBanData> bans = new ArrayList<>();
try (ResultSet resultSet = this.repository try (ResultSet resultSet = this.repository.checkedExecute("SELECT offender, admin, banned, reason, expiry, reference FROM GroupBans WHERE group_id = ?",
.checkedExecute("SELECT offender, admin, banned, reason, expiry, reference FROM AccountGroupBans WHERE group_name = ?", groupName)) { groupId)) {
if (resultSet == null) if (resultSet == null)
return bans; return bans;
@ -535,7 +623,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
byte[] reference = resultSet.getBytes(6); byte[] reference = resultSet.getBytes(6);
bans.add(new GroupBanData(groupName, offender, admin, banned, reason, expiry, reference)); bans.add(new GroupBanData(groupId, offender, admin, banned, reason, expiry, reference));
} while (resultSet.next()); } while (resultSet.next());
return bans; return bans;
@ -546,13 +634,13 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override @Override
public void save(GroupBanData groupBanData) throws DataException { public void save(GroupBanData groupBanData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("AccountGroupBans"); HSQLDBSaver saveHelper = new HSQLDBSaver("GroupBans");
Timestamp expiryTimestamp = null; Timestamp expiryTimestamp = null;
if (groupBanData.getExpiry() != null) if (groupBanData.getExpiry() != null)
expiryTimestamp = new Timestamp(groupBanData.getExpiry()); expiryTimestamp = new Timestamp(groupBanData.getExpiry());
saveHelper.bind("group_name", groupBanData.getGroupName()).bind("offender", groupBanData.getOffender()).bind("admin", groupBanData.getAdmin()) saveHelper.bind("group_id", groupBanData.getGroupId()).bind("offender", groupBanData.getOffender()).bind("admin", groupBanData.getAdmin())
.bind("banned", new Timestamp(groupBanData.getBanned())).bind("reason", groupBanData.getReason()).bind("expiry", expiryTimestamp) .bind("banned", new Timestamp(groupBanData.getBanned())).bind("reason", groupBanData.getReason()).bind("expiry", expiryTimestamp)
.bind("reference", groupBanData.getReference()); .bind("reference", groupBanData.getReference());
@ -564,9 +652,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
} }
@Override @Override
public void deleteBan(String groupName, String offender) throws DataException { public void deleteBan(int groupId, String offender) throws DataException {
try { try {
this.repository.delete("AccountGroupBans", "group_name = ? AND offender = ?", groupName, offender); this.repository.delete("GroupBans", "group_id = ? AND offender = ?", groupId, offender);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to delete group ban from repository", e); throw new DataException("Unable to delete group ban from repository", e);
} }

View File

@ -17,14 +17,14 @@ public class HSQLDBAddGroupAdminTransactionRepository extends HSQLDBTransactionR
} }
TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT group_name, address FROM AddGroupAdminTransactions WHERE signature = ?", signature)) { try (ResultSet resultSet = this.repository.checkedExecute("SELECT group_id, address FROM AddGroupAdminTransactions WHERE signature = ?", signature)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
String groupName = resultSet.getString(1); int groupId = resultSet.getInt(1);
String member = resultSet.getString(2); String member = resultSet.getString(2);
return new AddGroupAdminTransactionData(creatorPublicKey, groupName, member, fee, timestamp, reference, signature); return new AddGroupAdminTransactionData(creatorPublicKey, groupId, member, fee, timestamp, reference, signature);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch add group admin transaction from repository", e); throw new DataException("Unable to fetch add group admin transaction from repository", e);
} }
@ -37,7 +37,7 @@ public class HSQLDBAddGroupAdminTransactionRepository extends HSQLDBTransactionR
HSQLDBSaver saveHelper = new HSQLDBSaver("AddGroupAdminTransactions"); HSQLDBSaver saveHelper = new HSQLDBSaver("AddGroupAdminTransactions");
saveHelper.bind("signature", addGroupAdminTransactionData.getSignature()).bind("owner", addGroupAdminTransactionData.getOwnerPublicKey()) saveHelper.bind("signature", addGroupAdminTransactionData.getSignature()).bind("owner", addGroupAdminTransactionData.getOwnerPublicKey())
.bind("group_name", addGroupAdminTransactionData.getGroupName()).bind("address", addGroupAdminTransactionData.getMember()); .bind("group_id", addGroupAdminTransactionData.getGroupId()).bind("address", addGroupAdminTransactionData.getMember());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);

View File

@ -4,29 +4,29 @@ import java.math.BigDecimal;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import org.qora.data.transaction.GroupUnbanTransactionData; import org.qora.data.transaction.CancelGroupBanTransactionData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.repository.DataException; import org.qora.repository.DataException;
import org.qora.repository.hsqldb.HSQLDBRepository; import org.qora.repository.hsqldb.HSQLDBRepository;
import org.qora.repository.hsqldb.HSQLDBSaver; import org.qora.repository.hsqldb.HSQLDBSaver;
public class HSQLDBGroupUnbanTransactionRepository extends HSQLDBTransactionRepository { public class HSQLDBCancelGroupBanTransactionRepository extends HSQLDBTransactionRepository {
public HSQLDBGroupUnbanTransactionRepository(HSQLDBRepository repository) { public HSQLDBCancelGroupBanTransactionRepository(HSQLDBRepository repository) {
this.repository = repository; this.repository = repository;
} }
TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT group_name, address, group_reference FROM GroupUnbanTransactions WHERE signature = ?", try (ResultSet resultSet = this.repository.checkedExecute("SELECT group_id, address, ban_reference FROM CancelGroupBanTransactions WHERE signature = ?",
signature)) { signature)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
String groupName = resultSet.getString(1); int groupId = resultSet.getInt(1);
String member = resultSet.getString(2); String member = resultSet.getString(2);
byte[] groupReference = resultSet.getBytes(3); byte[] banReference = resultSet.getBytes(3);
return new GroupUnbanTransactionData(creatorPublicKey, groupName, member, groupReference, fee, timestamp, reference, signature); return new CancelGroupBanTransactionData(creatorPublicKey, groupId, member, banReference, fee, timestamp, reference, signature);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch group unban transaction from repository", e); throw new DataException("Unable to fetch group unban transaction from repository", e);
} }
@ -34,13 +34,13 @@ public class HSQLDBGroupUnbanTransactionRepository extends HSQLDBTransactionRepo
@Override @Override
public void save(TransactionData transactionData) throws DataException { public void save(TransactionData transactionData) throws DataException {
GroupUnbanTransactionData groupUnbanTransactionData = (GroupUnbanTransactionData) transactionData; CancelGroupBanTransactionData groupUnbanTransactionData = (CancelGroupBanTransactionData) transactionData;
HSQLDBSaver saveHelper = new HSQLDBSaver("GroupUnbanTransactions"); HSQLDBSaver saveHelper = new HSQLDBSaver("CancelGroupBanTransactions");
saveHelper.bind("signature", groupUnbanTransactionData.getSignature()).bind("admin", groupUnbanTransactionData.getAdminPublicKey()) saveHelper.bind("signature", groupUnbanTransactionData.getSignature()).bind("admin", groupUnbanTransactionData.getAdminPublicKey())
.bind("group_name", groupUnbanTransactionData.getGroupName()).bind("address", groupUnbanTransactionData.getMember()) .bind("group_id", groupUnbanTransactionData.getGroupId()).bind("address", groupUnbanTransactionData.getMember())
.bind("group_reference", groupUnbanTransactionData.getGroupReference()); .bind("ban_reference", groupUnbanTransactionData.getBanReference());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);

View File

@ -18,14 +18,15 @@ public class HSQLDBCancelGroupInviteTransactionRepository extends HSQLDBTransact
TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
try (ResultSet resultSet = this.repository try (ResultSet resultSet = this.repository
.checkedExecute("SELECT group_name, invitee FROM CancelGroupInviteTransactions WHERE signature = ?", signature)) { .checkedExecute("SELECT group_id, invitee, invite_reference FROM CancelGroupInviteTransactions WHERE signature = ?", signature)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
String groupName = resultSet.getString(1); int groupId = resultSet.getInt(1);
String invitee = resultSet.getString(2); String invitee = resultSet.getString(2);
byte[] inviteReference = resultSet.getBytes(3);
return new CancelGroupInviteTransactionData(creatorPublicKey, groupName, invitee, fee, timestamp, reference, signature); return new CancelGroupInviteTransactionData(creatorPublicKey, groupId, invitee, inviteReference, fee, timestamp, reference, signature);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch cancel group invite transaction from repository", e); throw new DataException("Unable to fetch cancel group invite transaction from repository", e);
} }
@ -38,7 +39,8 @@ public class HSQLDBCancelGroupInviteTransactionRepository extends HSQLDBTransact
HSQLDBSaver saveHelper = new HSQLDBSaver("CancelGroupInviteTransactions"); HSQLDBSaver saveHelper = new HSQLDBSaver("CancelGroupInviteTransactions");
saveHelper.bind("signature", cancelGroupInviteTransactionData.getSignature()).bind("admin", cancelGroupInviteTransactionData.getAdminPublicKey()) saveHelper.bind("signature", cancelGroupInviteTransactionData.getSignature()).bind("admin", cancelGroupInviteTransactionData.getAdminPublicKey())
.bind("group_name", cancelGroupInviteTransactionData.getGroupName()).bind("invitee", cancelGroupInviteTransactionData.getInvitee()); .bind("group_id", cancelGroupInviteTransactionData.getGroupId()).bind("invitee", cancelGroupInviteTransactionData.getInvitee())
.bind("invite_reference", cancelGroupInviteTransactionData.getInviteReference());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);

View File

@ -17,8 +17,8 @@ public class HSQLDBCreateGroupTransactionRepository extends HSQLDBTransactionRep
} }
TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT owner, group_name, description, is_open FROM CreateGroupTransactions WHERE signature = ?", try (ResultSet resultSet = this.repository
signature)) { .checkedExecute("SELECT owner, group_name, description, is_open, group_id FROM CreateGroupTransactions WHERE signature = ?", signature)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
@ -27,7 +27,11 @@ public class HSQLDBCreateGroupTransactionRepository extends HSQLDBTransactionRep
String description = resultSet.getString(3); String description = resultSet.getString(3);
boolean isOpen = resultSet.getBoolean(4); boolean isOpen = resultSet.getBoolean(4);
return new CreateGroupTransactionData(creatorPublicKey, owner, groupName, description, isOpen, fee, timestamp, reference, signature); Integer groupId = resultSet.getInt(5);
if (resultSet.wasNull())
groupId = null;
return new CreateGroupTransactionData(creatorPublicKey, owner, groupName, description, isOpen, groupId, fee, timestamp, reference, signature);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch create group transaction from repository", e); throw new DataException("Unable to fetch create group transaction from repository", e);
} }
@ -41,7 +45,8 @@ public class HSQLDBCreateGroupTransactionRepository extends HSQLDBTransactionRep
saveHelper.bind("signature", createGroupTransactionData.getSignature()).bind("creator", createGroupTransactionData.getCreatorPublicKey()) saveHelper.bind("signature", createGroupTransactionData.getSignature()).bind("creator", createGroupTransactionData.getCreatorPublicKey())
.bind("owner", createGroupTransactionData.getOwner()).bind("group_name", createGroupTransactionData.getGroupName()) .bind("owner", createGroupTransactionData.getOwner()).bind("group_name", createGroupTransactionData.getGroupName())
.bind("description", createGroupTransactionData.getDescription()).bind("is_open", createGroupTransactionData.getIsOpen()); .bind("description", createGroupTransactionData.getDescription()).bind("is_open", createGroupTransactionData.getIsOpen())
.bind("group_id", createGroupTransactionData.getGroupId());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);

View File

@ -18,20 +18,21 @@ public class HSQLDBGroupBanTransactionRepository extends HSQLDBTransactionReposi
TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute( try (ResultSet resultSet = this.repository.checkedExecute(
"SELECT group_name, address, reason, time_to_live, member_reference, admin_reference FROM GroupBanTransactions WHERE signature = ?", "SELECT group_id, address, reason, time_to_live, member_reference, admin_reference, join_invite_reference FROM GroupBanTransactions WHERE signature = ?",
signature)) { signature)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
String groupName = resultSet.getString(1); int groupId = resultSet.getInt(1);
String offender = resultSet.getString(2); String offender = resultSet.getString(2);
String reason = resultSet.getString(3); String reason = resultSet.getString(3);
int timeToLive = resultSet.getInt(4); int timeToLive = resultSet.getInt(4);
byte[] memberReference = resultSet.getBytes(5); byte[] memberReference = resultSet.getBytes(5);
byte[] adminReference = resultSet.getBytes(6); byte[] adminReference = resultSet.getBytes(6);
byte[] joinInviteReference = resultSet.getBytes(7);
return new GroupBanTransactionData(creatorPublicKey, groupName, offender, reason, timeToLive, memberReference, adminReference, fee, timestamp, return new GroupBanTransactionData(creatorPublicKey, groupId, offender, reason, timeToLive, memberReference, adminReference, joinInviteReference,
reference, signature); fee, timestamp, reference, signature);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch group ban transaction from repository", e); throw new DataException("Unable to fetch group ban transaction from repository", e);
} }
@ -44,9 +45,10 @@ public class HSQLDBGroupBanTransactionRepository extends HSQLDBTransactionReposi
HSQLDBSaver saveHelper = new HSQLDBSaver("GroupBanTransactions"); HSQLDBSaver saveHelper = new HSQLDBSaver("GroupBanTransactions");
saveHelper.bind("signature", groupBanTransactionData.getSignature()).bind("admin", groupBanTransactionData.getAdminPublicKey()) saveHelper.bind("signature", groupBanTransactionData.getSignature()).bind("admin", groupBanTransactionData.getAdminPublicKey())
.bind("group_name", groupBanTransactionData.getGroupName()).bind("address", groupBanTransactionData.getOffender()) .bind("group_id", groupBanTransactionData.getGroupId()).bind("address", groupBanTransactionData.getOffender())
.bind("reason", groupBanTransactionData.getReason()).bind("time_to_live", groupBanTransactionData.getTimeToLive()) .bind("reason", groupBanTransactionData.getReason()).bind("time_to_live", groupBanTransactionData.getTimeToLive())
.bind("member_reference", groupBanTransactionData.getMemberReference()).bind("admin_reference", groupBanTransactionData.getAdminReference()); .bind("member_reference", groupBanTransactionData.getMemberReference()).bind("admin_reference", groupBanTransactionData.getAdminReference())
.bind("join_invite_reference", groupBanTransactionData.getJoinInviteReference());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);

View File

@ -3,8 +3,6 @@ package org.qora.repository.hsqldb.transaction;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.qora.data.transaction.GroupInviteTransactionData; import org.qora.data.transaction.GroupInviteTransactionData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
@ -20,16 +18,16 @@ public class HSQLDBGroupInviteTransactionRepository extends HSQLDBTransactionRep
TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
try (ResultSet resultSet = this.repository try (ResultSet resultSet = this.repository
.checkedExecute("SELECT group_name, invitee, time_to_live, group_reference FROM GroupInviteTransactions WHERE signature = ?", signature)) { .checkedExecute("SELECT group_id, invitee, time_to_live, join_reference FROM GroupInviteTransactions WHERE signature = ?", signature)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
String groupName = resultSet.getString(1); int groupId = resultSet.getInt(1);
String invitee = resultSet.getString(2); String invitee = resultSet.getString(2);
int timeToLive = resultSet.getInt(3); int timeToLive = resultSet.getInt(3);
byte[] groupReference = resultSet.getBytes(4); byte[] joinReference = resultSet.getBytes(4);
return new GroupInviteTransactionData(creatorPublicKey, groupName, invitee, timeToLive, groupReference, fee, timestamp, reference, signature); return new GroupInviteTransactionData(creatorPublicKey, groupId, invitee, timeToLive, joinReference, fee, timestamp, reference, signature);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch group invite transaction from repository", e); throw new DataException("Unable to fetch group invite transaction from repository", e);
} }
@ -42,8 +40,8 @@ public class HSQLDBGroupInviteTransactionRepository extends HSQLDBTransactionRep
HSQLDBSaver saveHelper = new HSQLDBSaver("GroupInviteTransactions"); HSQLDBSaver saveHelper = new HSQLDBSaver("GroupInviteTransactions");
saveHelper.bind("signature", groupInviteTransactionData.getSignature()).bind("admin", groupInviteTransactionData.getAdminPublicKey()) saveHelper.bind("signature", groupInviteTransactionData.getSignature()).bind("admin", groupInviteTransactionData.getAdminPublicKey())
.bind("group_name", groupInviteTransactionData.getGroupName()).bind("invitee", groupInviteTransactionData.getInvitee()) .bind("group_id", groupInviteTransactionData.getGroupId()).bind("invitee", groupInviteTransactionData.getInvitee())
.bind("time_to_live", groupInviteTransactionData.getTimeToLive()).bind("group_reference", groupInviteTransactionData.getGroupReference()); .bind("time_to_live", groupInviteTransactionData.getTimeToLive()).bind("join_reference", groupInviteTransactionData.getJoinReference());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);
@ -52,25 +50,4 @@ public class HSQLDBGroupInviteTransactionRepository extends HSQLDBTransactionRep
} }
} }
@Override
public List<GroupInviteTransactionData> getInvitesWithGroupReference(byte[] groupReference) throws DataException {
List<GroupInviteTransactionData> invites = new ArrayList<>();
try (ResultSet resultSet = this.repository
.checkedExecute("SELECT signature FROM GroupInviteTransactions WHERE group_reference = ?", groupReference)) {
if (resultSet == null)
return invites;
do {
byte[] signature = resultSet.getBytes(1);
invites.add((GroupInviteTransactionData) this.repository.getTransactionRepository().fromSignature(signature));
} while (resultSet.next());
return invites;
} catch (SQLException e) {
throw new DataException("Unable to fetch group invite transaction from repository", e);
}
}
} }

View File

@ -18,18 +18,20 @@ public class HSQLDBGroupKickTransactionRepository extends HSQLDBTransactionRepos
TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute( try (ResultSet resultSet = this.repository.checkedExecute(
"SELECT group_name, address, reason, member_reference, admin_reference FROM GroupKickTransactions WHERE signature = ?", signature)) { "SELECT group_id, address, reason, member_reference, admin_reference, join_reference FROM GroupKickTransactions WHERE signature = ?",
signature)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
String groupName = resultSet.getString(1); int groupId = resultSet.getInt(1);
String member = resultSet.getString(2); String member = resultSet.getString(2);
String reason = resultSet.getString(3); String reason = resultSet.getString(3);
byte[] memberReference = resultSet.getBytes(4); byte[] memberReference = resultSet.getBytes(4);
byte[] adminReference = resultSet.getBytes(5); byte[] adminReference = resultSet.getBytes(5);
byte[] joinReference = resultSet.getBytes(6);
return new GroupKickTransactionData(creatorPublicKey, groupName, member, reason, memberReference, adminReference, fee, timestamp, reference, return new GroupKickTransactionData(creatorPublicKey, groupId, member, reason, memberReference, adminReference, joinReference, fee, timestamp,
signature); reference, signature);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch group kick transaction from repository", e); throw new DataException("Unable to fetch group kick transaction from repository", e);
} }
@ -42,9 +44,9 @@ public class HSQLDBGroupKickTransactionRepository extends HSQLDBTransactionRepos
HSQLDBSaver saveHelper = new HSQLDBSaver("GroupKickTransactions"); HSQLDBSaver saveHelper = new HSQLDBSaver("GroupKickTransactions");
saveHelper.bind("signature", groupKickTransactionData.getSignature()).bind("admin", groupKickTransactionData.getAdminPublicKey()) saveHelper.bind("signature", groupKickTransactionData.getSignature()).bind("admin", groupKickTransactionData.getAdminPublicKey())
.bind("group_name", groupKickTransactionData.getGroupName()).bind("address", groupKickTransactionData.getMember()) .bind("group_id", groupKickTransactionData.getGroupId()).bind("address", groupKickTransactionData.getMember())
.bind("reason", groupKickTransactionData.getReason()).bind("member_reference", groupKickTransactionData.getMemberReference()) .bind("reason", groupKickTransactionData.getReason()).bind("member_reference", groupKickTransactionData.getMemberReference())
.bind("admin_reference", groupKickTransactionData.getAdminReference()); .bind("admin_reference", groupKickTransactionData.getAdminReference()).bind("join_reference", groupKickTransactionData.getJoinReference());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);

View File

@ -17,13 +17,15 @@ public class HSQLDBJoinGroupTransactionRepository extends HSQLDBTransactionRepos
} }
TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT group_name FROM JoinGroupTransactions WHERE signature = ?", signature)) { try (ResultSet resultSet = this.repository.checkedExecute("SELECT group_id, invite_reference FROM JoinGroupTransactions WHERE signature = ?",
signature)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
String groupName = resultSet.getString(1); int groupId = resultSet.getInt(1);
byte[] inviteReference = resultSet.getBytes(2);
return new JoinGroupTransactionData(creatorPublicKey, groupName, fee, timestamp, reference, signature); return new JoinGroupTransactionData(creatorPublicKey, groupId, inviteReference, fee, timestamp, reference, signature);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch join group transaction from repository", e); throw new DataException("Unable to fetch join group transaction from repository", e);
} }
@ -36,7 +38,7 @@ public class HSQLDBJoinGroupTransactionRepository extends HSQLDBTransactionRepos
HSQLDBSaver saveHelper = new HSQLDBSaver("JoinGroupTransactions"); HSQLDBSaver saveHelper = new HSQLDBSaver("JoinGroupTransactions");
saveHelper.bind("signature", joinGroupTransactionData.getSignature()).bind("joiner", joinGroupTransactionData.getJoinerPublicKey()) saveHelper.bind("signature", joinGroupTransactionData.getSignature()).bind("joiner", joinGroupTransactionData.getJoinerPublicKey())
.bind("group_name", joinGroupTransactionData.getGroupName()); .bind("group_id", joinGroupTransactionData.getGroupId()).bind("invite_reference", joinGroupTransactionData.getInviteReference());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);

View File

@ -18,15 +18,15 @@ public class HSQLDBLeaveGroupTransactionRepository extends HSQLDBTransactionRepo
TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
try (ResultSet resultSet = this.repository try (ResultSet resultSet = this.repository
.checkedExecute("SELECT group_name, member_reference, admin_reference FROM LeaveGroupTransactions WHERE signature = ?", signature)) { .checkedExecute("SELECT group_id, member_reference, admin_reference FROM LeaveGroupTransactions WHERE signature = ?", signature)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
String groupName = resultSet.getString(1); int groupId = resultSet.getInt(1);
byte[] memberReference = resultSet.getBytes(2); byte[] memberReference = resultSet.getBytes(2);
byte[] adminReference = resultSet.getBytes(3); byte[] adminReference = resultSet.getBytes(3);
return new LeaveGroupTransactionData(creatorPublicKey, groupName, memberReference, adminReference, fee, timestamp, reference, signature); return new LeaveGroupTransactionData(creatorPublicKey, groupId, memberReference, adminReference, fee, timestamp, reference, signature);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch leave group transaction from repository", e); throw new DataException("Unable to fetch leave group transaction from repository", e);
} }
@ -39,7 +39,7 @@ public class HSQLDBLeaveGroupTransactionRepository extends HSQLDBTransactionRepo
HSQLDBSaver saveHelper = new HSQLDBSaver("LeaveGroupTransactions"); HSQLDBSaver saveHelper = new HSQLDBSaver("LeaveGroupTransactions");
saveHelper.bind("signature", leaveGroupTransactionData.getSignature()).bind("leaver", leaveGroupTransactionData.getLeaverPublicKey()) saveHelper.bind("signature", leaveGroupTransactionData.getSignature()).bind("leaver", leaveGroupTransactionData.getLeaverPublicKey())
.bind("group_name", leaveGroupTransactionData.getGroupName()).bind("member_reference", leaveGroupTransactionData.getMemberReference()) .bind("group_id", leaveGroupTransactionData.getGroupId()).bind("member_reference", leaveGroupTransactionData.getMemberReference())
.bind("admin_reference", leaveGroupTransactionData.getAdminReference()); .bind("admin_reference", leaveGroupTransactionData.getAdminReference());
try { try {

View File

@ -18,15 +18,15 @@ public class HSQLDBRemoveGroupAdminTransactionRepository extends HSQLDBTransacti
TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
try (ResultSet resultSet = this.repository try (ResultSet resultSet = this.repository
.checkedExecute("SELECT group_name, admin, group_reference FROM RemoveGroupAdminTransactions WHERE signature = ?", signature)) { .checkedExecute("SELECT group_id, admin, admin_reference FROM RemoveGroupAdminTransactions WHERE signature = ?", signature)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
String groupName = resultSet.getString(1); int groupId = resultSet.getInt(1);
String admin = resultSet.getString(2); String admin = resultSet.getString(2);
byte[] groupReference = resultSet.getBytes(3); byte[] adminReference = resultSet.getBytes(3);
return new RemoveGroupAdminTransactionData(creatorPublicKey, groupName, admin, groupReference, fee, timestamp, reference, signature); return new RemoveGroupAdminTransactionData(creatorPublicKey, groupId, admin, adminReference, fee, timestamp, reference, signature);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch remove group admin transaction from repository", e); throw new DataException("Unable to fetch remove group admin transaction from repository", e);
} }
@ -39,8 +39,8 @@ public class HSQLDBRemoveGroupAdminTransactionRepository extends HSQLDBTransacti
HSQLDBSaver saveHelper = new HSQLDBSaver("RemoveGroupAdminTransactions"); HSQLDBSaver saveHelper = new HSQLDBSaver("RemoveGroupAdminTransactions");
saveHelper.bind("signature", removeGroupAdminTransactionData.getSignature()).bind("owner", removeGroupAdminTransactionData.getOwnerPublicKey()) saveHelper.bind("signature", removeGroupAdminTransactionData.getSignature()).bind("owner", removeGroupAdminTransactionData.getOwnerPublicKey())
.bind("group_name", removeGroupAdminTransactionData.getGroupName()).bind("admin", removeGroupAdminTransactionData.getAdmin()) .bind("group_id", removeGroupAdminTransactionData.getGroupId()).bind("admin", removeGroupAdminTransactionData.getAdmin())
.bind("group_reference", removeGroupAdminTransactionData.getGroupReference()); .bind("admin_reference", removeGroupAdminTransactionData.getAdminReference());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);

View File

@ -11,7 +11,6 @@ import java.util.List;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.qora.data.PaymentData; import org.qora.data.PaymentData;
import org.qora.data.transaction.GroupInviteTransactionData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.repository.DataException; import org.qora.repository.DataException;
import org.qora.repository.TransactionRepository; import org.qora.repository.TransactionRepository;
@ -47,7 +46,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
private HSQLDBAddGroupAdminTransactionRepository addGroupAdminTransactionRepository; private HSQLDBAddGroupAdminTransactionRepository addGroupAdminTransactionRepository;
private HSQLDBRemoveGroupAdminTransactionRepository removeGroupAdminTransactionRepository; private HSQLDBRemoveGroupAdminTransactionRepository removeGroupAdminTransactionRepository;
private HSQLDBGroupBanTransactionRepository groupBanTransactionRepository; private HSQLDBGroupBanTransactionRepository groupBanTransactionRepository;
private HSQLDBGroupUnbanTransactionRepository groupUnbanTransactionRepository; private HSQLDBCancelGroupBanTransactionRepository groupUnbanTransactionRepository;
private HSQLDBGroupKickTransactionRepository groupKickTransactionRepository; private HSQLDBGroupKickTransactionRepository groupKickTransactionRepository;
private HSQLDBGroupInviteTransactionRepository groupInviteTransactionRepository; private HSQLDBGroupInviteTransactionRepository groupInviteTransactionRepository;
private HSQLDBCancelGroupInviteTransactionRepository cancelGroupInviteTransactionRepository; private HSQLDBCancelGroupInviteTransactionRepository cancelGroupInviteTransactionRepository;
@ -79,7 +78,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
this.addGroupAdminTransactionRepository = new HSQLDBAddGroupAdminTransactionRepository(repository); this.addGroupAdminTransactionRepository = new HSQLDBAddGroupAdminTransactionRepository(repository);
this.removeGroupAdminTransactionRepository = new HSQLDBRemoveGroupAdminTransactionRepository(repository); this.removeGroupAdminTransactionRepository = new HSQLDBRemoveGroupAdminTransactionRepository(repository);
this.groupBanTransactionRepository = new HSQLDBGroupBanTransactionRepository(repository); this.groupBanTransactionRepository = new HSQLDBGroupBanTransactionRepository(repository);
this.groupUnbanTransactionRepository = new HSQLDBGroupUnbanTransactionRepository(repository); this.groupUnbanTransactionRepository = new HSQLDBCancelGroupBanTransactionRepository(repository);
this.groupKickTransactionRepository = new HSQLDBGroupKickTransactionRepository(repository); this.groupKickTransactionRepository = new HSQLDBGroupKickTransactionRepository(repository);
this.groupInviteTransactionRepository = new HSQLDBGroupInviteTransactionRepository(repository); this.groupInviteTransactionRepository = new HSQLDBGroupInviteTransactionRepository(repository);
this.cancelGroupInviteTransactionRepository = new HSQLDBCancelGroupInviteTransactionRepository(repository); this.cancelGroupInviteTransactionRepository = new HSQLDBCancelGroupInviteTransactionRepository(repository);
@ -226,7 +225,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
case GROUP_BAN: case GROUP_BAN:
return this.groupBanTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); return this.groupBanTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
case GROUP_UNBAN: case CANCEL_GROUP_BAN:
return this.groupUnbanTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); return this.groupUnbanTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
case GROUP_KICK: case GROUP_KICK:
@ -584,7 +583,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
this.groupBanTransactionRepository.save(transactionData); this.groupBanTransactionRepository.save(transactionData);
break; break;
case GROUP_UNBAN: case CANCEL_GROUP_BAN:
this.groupUnbanTransactionRepository.save(transactionData); this.groupUnbanTransactionRepository.save(transactionData);
break; break;
@ -629,10 +628,4 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
} }
} }
@Override
public List<GroupInviteTransactionData> getInvitesWithGroupReference(byte[] groupReference) throws DataException {
// Let specialized subclass handle this
return this.groupInviteTransactionRepository.getInvitesWithGroupReference(groupReference);
}
} }

View File

@ -17,18 +17,19 @@ public class HSQLDBUpdateGroupTransactionRepository extends HSQLDBTransactionRep
} }
TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT group_name, new_owner, new_description, new_is_open, group_reference FROM UpdateGroupTransactions WHERE signature = ?", try (ResultSet resultSet = this.repository.checkedExecute(
signature)) { "SELECT group_id, new_owner, new_description, new_is_open, group_reference FROM UpdateGroupTransactions WHERE signature = ?", signature)) {
if (resultSet == null) if (resultSet == null)
return null; return null;
String groupName = resultSet.getString(1); int groupId = resultSet.getInt(1);
String newOwner = resultSet.getString(2); String newOwner = resultSet.getString(2);
String newDescription = resultSet.getString(3); String newDescription = resultSet.getString(3);
boolean newIsOpen = resultSet.getBoolean(4); boolean newIsOpen = resultSet.getBoolean(4);
byte[] groupReference = resultSet.getBytes(5); byte[] groupReference = resultSet.getBytes(5);
return new UpdateGroupTransactionData(creatorPublicKey, groupName, newOwner, newDescription, newIsOpen, groupReference, fee, timestamp, reference, signature); return new UpdateGroupTransactionData(creatorPublicKey, groupId, newOwner, newDescription, newIsOpen, groupReference, fee, timestamp, reference,
signature);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch update group transaction from repository", e); throw new DataException("Unable to fetch update group transaction from repository", e);
} }
@ -41,7 +42,7 @@ public class HSQLDBUpdateGroupTransactionRepository extends HSQLDBTransactionRep
HSQLDBSaver saveHelper = new HSQLDBSaver("UpdateGroupTransactions"); HSQLDBSaver saveHelper = new HSQLDBSaver("UpdateGroupTransactions");
saveHelper.bind("signature", updateGroupTransactionData.getSignature()).bind("owner", updateGroupTransactionData.getOwnerPublicKey()) saveHelper.bind("signature", updateGroupTransactionData.getSignature()).bind("owner", updateGroupTransactionData.getOwnerPublicKey())
.bind("group_name", updateGroupTransactionData.getGroupName()).bind("new_owner", updateGroupTransactionData.getNewOwner()) .bind("group_id", updateGroupTransactionData.getGroupId()).bind("new_owner", updateGroupTransactionData.getNewOwner())
.bind("new_description", updateGroupTransactionData.getNewDescription()).bind("new_is_open", updateGroupTransactionData.getNewIsOpen()) .bind("new_description", updateGroupTransactionData.getNewDescription()).bind("new_is_open", updateGroupTransactionData.getNewIsOpen())
.bind("group_reference", updateGroupTransactionData.getGroupReference()); .bind("group_reference", updateGroupTransactionData.getGroupReference());

View File

@ -16,8 +16,6 @@ import org.qora.group.Group;
import org.qora.repository.DataException; import org.qora.repository.DataException;
import org.qora.repository.Repository; import org.qora.repository.Repository;
import com.google.common.base.Utf8;
public class AddGroupAdminTransaction extends Transaction { public class AddGroupAdminTransaction extends Transaction {
// Properties // Properties
@ -76,16 +74,11 @@ public class AddGroupAdminTransaction extends Transaction {
@Override @Override
public ValidationResult isValid() throws DataException { public ValidationResult isValid() throws DataException {
// Check group name size bounds // Check member address is valid
int groupNameLength = Utf8.encodedLength(addGroupAdminTransactionData.getGroupName()); if (!Crypto.isValidAddress(addGroupAdminTransactionData.getMember()))
if (groupNameLength < 1 || groupNameLength > Group.MAX_NAME_SIZE) return ValidationResult.INVALID_ADDRESS;
return ValidationResult.INVALID_NAME_LENGTH;
// Check group name is lowercase GroupData groupData = this.repository.getGroupRepository().fromGroupId(addGroupAdminTransactionData.getGroupId());
if (!addGroupAdminTransactionData.getGroupName().equals(addGroupAdminTransactionData.getGroupName().toLowerCase()))
return ValidationResult.NAME_NOT_LOWER_CASE;
GroupData groupData = this.repository.getGroupRepository().fromGroupName(addGroupAdminTransactionData.getGroupName());
// Check group exists // Check group exists
if (groupData == null) if (groupData == null)
@ -97,24 +90,21 @@ public class AddGroupAdminTransaction extends Transaction {
if (!owner.getAddress().equals(groupData.getOwner())) if (!owner.getAddress().equals(groupData.getOwner()))
return ValidationResult.INVALID_GROUP_OWNER; return ValidationResult.INVALID_GROUP_OWNER;
// Check member address is valid
if (!Crypto.isValidAddress(addGroupAdminTransactionData.getMember()))
return ValidationResult.INVALID_ADDRESS;
Account member = getMember(); Account member = getMember();
// Check address is a member // Check address is a member
if (!this.repository.getGroupRepository().memberExists(addGroupAdminTransactionData.getGroupName(), member.getAddress())) if (!this.repository.getGroupRepository().memberExists(addGroupAdminTransactionData.getGroupId(), member.getAddress()))
return ValidationResult.NOT_GROUP_MEMBER; return ValidationResult.NOT_GROUP_MEMBER;
// Check member is not already an admin // Check member is not already an admin
if (this.repository.getGroupRepository().adminExists(addGroupAdminTransactionData.getGroupName(), member.getAddress())) if (this.repository.getGroupRepository().adminExists(addGroupAdminTransactionData.getGroupId(), member.getAddress()))
return ValidationResult.ALREADY_GROUP_ADMIN; return ValidationResult.ALREADY_GROUP_ADMIN;
// Check fee is positive // Check fee is positive
if (addGroupAdminTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0) if (addGroupAdminTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
return ValidationResult.NEGATIVE_FEE; return ValidationResult.NEGATIVE_FEE;
// Check reference
if (!Arrays.equals(owner.getLastReference(), addGroupAdminTransactionData.getReference())) if (!Arrays.equals(owner.getLastReference(), addGroupAdminTransactionData.getReference()))
return ValidationResult.INVALID_REFERENCE; return ValidationResult.INVALID_REFERENCE;
@ -128,7 +118,7 @@ public class AddGroupAdminTransaction extends Transaction {
@Override @Override
public void process() throws DataException { public void process() throws DataException {
// Update Group adminship // Update Group adminship
Group group = new Group(this.repository, addGroupAdminTransactionData.getGroupName()); Group group = new Group(this.repository, addGroupAdminTransactionData.getGroupId());
group.promoteToAdmin(addGroupAdminTransactionData); group.promoteToAdmin(addGroupAdminTransactionData);
// Save this transaction // Save this transaction
@ -145,7 +135,7 @@ public class AddGroupAdminTransaction extends Transaction {
@Override @Override
public void orphan() throws DataException { public void orphan() throws DataException {
// Revert group adminship // Revert group adminship
Group group = new Group(this.repository, addGroupAdminTransactionData.getGroupName()); Group group = new Group(this.repository, addGroupAdminTransactionData.getGroupId());
group.unpromoteToAdmin(addGroupAdminTransactionData); group.unpromoteToAdmin(addGroupAdminTransactionData);
// Delete this transaction itself // Delete this transaction itself

View File

@ -9,27 +9,24 @@ import org.qora.account.Account;
import org.qora.account.PublicKeyAccount; import org.qora.account.PublicKeyAccount;
import org.qora.asset.Asset; import org.qora.asset.Asset;
import org.qora.crypto.Crypto; import org.qora.crypto.Crypto;
import org.qora.data.transaction.GroupUnbanTransactionData; import org.qora.data.transaction.CancelGroupBanTransactionData;
import org.qora.data.group.GroupData; import org.qora.data.group.GroupData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.group.Group; import org.qora.group.Group;
import org.qora.repository.DataException; import org.qora.repository.DataException;
import org.qora.repository.GroupRepository;
import org.qora.repository.Repository; import org.qora.repository.Repository;
import com.google.common.base.Utf8; public class CancelGroupBanTransaction extends Transaction {
public class GroupUnbanTransaction extends Transaction {
// Properties // Properties
private GroupUnbanTransactionData groupUnbanTransactionData; private CancelGroupBanTransactionData groupUnbanTransactionData;
// Constructors // Constructors
public GroupUnbanTransaction(Repository repository, TransactionData transactionData) { public CancelGroupBanTransaction(Repository repository, TransactionData transactionData) {
super(repository, transactionData); super(repository, transactionData);
this.groupUnbanTransactionData = (GroupUnbanTransactionData) this.transactionData; this.groupUnbanTransactionData = (CancelGroupBanTransactionData) this.transactionData;
} }
// More information // More information
@ -77,43 +74,33 @@ public class GroupUnbanTransaction extends Transaction {
@Override @Override
public ValidationResult isValid() throws DataException { public ValidationResult isValid() throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = groupUnbanTransactionData.getGroupName();
// Check member address is valid // Check member address is valid
if (!Crypto.isValidAddress(groupUnbanTransactionData.getMember())) if (!Crypto.isValidAddress(groupUnbanTransactionData.getMember()))
return ValidationResult.INVALID_ADDRESS; return ValidationResult.INVALID_ADDRESS;
// Check group name size bounds GroupData groupData = this.repository.getGroupRepository().fromGroupId(groupUnbanTransactionData.getGroupId());
int groupNameLength = Utf8.encodedLength(groupName);
if (groupNameLength < 1 || groupNameLength > Group.MAX_NAME_SIZE)
return ValidationResult.INVALID_NAME_LENGTH;
// Check group name is lowercase
if (!groupName.equals(groupName.toLowerCase()))
return ValidationResult.NAME_NOT_LOWER_CASE;
GroupData groupData = groupRepository.fromGroupName(groupName);
// Check group exists // Check group exists
if (groupData == null) if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST; return ValidationResult.GROUP_DOES_NOT_EXIST;
Account admin = getAdmin(); Account admin = getAdmin();
Account member = getMember();
// Can't unban if not an admin // Can't unban if not an admin
if (!groupRepository.adminExists(groupName, admin.getAddress())) if (!this.repository.getGroupRepository().adminExists(groupUnbanTransactionData.getGroupId(), admin.getAddress()))
return ValidationResult.NOT_GROUP_ADMIN; return ValidationResult.NOT_GROUP_ADMIN;
Account member = getMember();
// Check ban actually exists // Check ban actually exists
if (!groupRepository.banExists(groupName, member.getAddress())) if (!this.repository.getGroupRepository().banExists(groupUnbanTransactionData.getGroupId(), member.getAddress()))
return ValidationResult.BAN_UNKNOWN; return ValidationResult.BAN_UNKNOWN;
// Check fee is positive // Check fee is positive
if (groupUnbanTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0) if (groupUnbanTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
return ValidationResult.NEGATIVE_FEE; return ValidationResult.NEGATIVE_FEE;
// Check reference
if (!Arrays.equals(admin.getLastReference(), groupUnbanTransactionData.getReference())) if (!Arrays.equals(admin.getLastReference(), groupUnbanTransactionData.getReference()))
return ValidationResult.INVALID_REFERENCE; return ValidationResult.INVALID_REFERENCE;
@ -127,7 +114,7 @@ public class GroupUnbanTransaction extends Transaction {
@Override @Override
public void process() throws DataException { public void process() throws DataException {
// Update Group Membership // Update Group Membership
Group group = new Group(this.repository, groupUnbanTransactionData.getGroupName()); Group group = new Group(this.repository, groupUnbanTransactionData.getGroupId());
group.cancelBan(groupUnbanTransactionData); group.cancelBan(groupUnbanTransactionData);
// Save this transaction with updated member/admin references to transactions that can help restore state // Save this transaction with updated member/admin references to transactions that can help restore state
@ -144,7 +131,7 @@ public class GroupUnbanTransaction extends Transaction {
@Override @Override
public void orphan() throws DataException { public void orphan() throws DataException {
// Revert group membership // Revert group membership
Group group = new Group(this.repository, groupUnbanTransactionData.getGroupName()); Group group = new Group(this.repository, groupUnbanTransactionData.getGroupId());
group.uncancelBan(groupUnbanTransactionData); group.uncancelBan(groupUnbanTransactionData);
// Delete this transaction itself // Delete this transaction itself

View File

@ -14,22 +14,19 @@ import org.qora.data.group.GroupData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.group.Group; import org.qora.group.Group;
import org.qora.repository.DataException; import org.qora.repository.DataException;
import org.qora.repository.GroupRepository;
import org.qora.repository.Repository; import org.qora.repository.Repository;
import com.google.common.base.Utf8;
public class CancelGroupInviteTransaction extends Transaction { public class CancelGroupInviteTransaction extends Transaction {
// Properties // Properties
private CancelGroupInviteTransactionData cancelCancelGroupInviteTransactionData; private CancelGroupInviteTransactionData cancelGroupInviteTransactionData;
// Constructors // Constructors
public CancelGroupInviteTransaction(Repository repository, TransactionData transactionData) { public CancelGroupInviteTransaction(Repository repository, TransactionData transactionData) {
super(repository, transactionData); super(repository, transactionData);
this.cancelCancelGroupInviteTransactionData = (CancelGroupInviteTransactionData) this.transactionData; this.cancelGroupInviteTransactionData = (CancelGroupInviteTransactionData) this.transactionData;
} }
// More information // More information
@ -66,55 +63,49 @@ public class CancelGroupInviteTransaction extends Transaction {
// Navigation // Navigation
public Account getAdmin() throws DataException { public Account getAdmin() throws DataException {
return new PublicKeyAccount(this.repository, this.cancelCancelGroupInviteTransactionData.getAdminPublicKey()); return new PublicKeyAccount(this.repository, this.cancelGroupInviteTransactionData.getAdminPublicKey());
} }
public Account getInvitee() throws DataException { public Account getInvitee() throws DataException {
return new Account(this.repository, this.cancelCancelGroupInviteTransactionData.getInvitee()); return new Account(this.repository, this.cancelGroupInviteTransactionData.getInvitee());
} }
// Processing // Processing
@Override @Override
public ValidationResult isValid() throws DataException { public ValidationResult isValid() throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository(); // Check invitee address is valid
String groupName = cancelCancelGroupInviteTransactionData.getGroupName(); if (!Crypto.isValidAddress(cancelGroupInviteTransactionData.getInvitee()))
// Check member address is valid
if (!Crypto.isValidAddress(cancelCancelGroupInviteTransactionData.getInvitee()))
return ValidationResult.INVALID_ADDRESS; return ValidationResult.INVALID_ADDRESS;
// Check group name size bounds GroupData groupData = this.repository.getGroupRepository().fromGroupId(cancelGroupInviteTransactionData.getGroupId());
int groupNameLength = Utf8.encodedLength(groupName);
if (groupNameLength < 1 || groupNameLength > Group.MAX_NAME_SIZE)
return ValidationResult.INVALID_NAME_LENGTH;
// Check group name is lowercase
if (!groupName.equals(groupName.toLowerCase()))
return ValidationResult.NAME_NOT_LOWER_CASE;
GroupData groupData = groupRepository.fromGroupName(groupName);
// Check group exists // Check group exists
if (groupData == null) if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST; return ValidationResult.GROUP_DOES_NOT_EXIST;
Account admin = getAdmin(); Account admin = getAdmin();
// Check admin is actually an admin
if (!this.repository.getGroupRepository().adminExists(cancelGroupInviteTransactionData.getGroupId(), admin.getAddress()))
return ValidationResult.NOT_GROUP_ADMIN;
Account invitee = getInvitee(); Account invitee = getInvitee();
// Check invite exists // Check invite exists
if (!groupRepository.inviteExists(groupName, admin.getAddress(), invitee.getAddress())) if (!this.repository.getGroupRepository().inviteExists(cancelGroupInviteTransactionData.getGroupId(), invitee.getAddress()))
return ValidationResult.INVITE_UNKNOWN; return ValidationResult.INVITE_UNKNOWN;
// Check fee is positive // Check fee is positive
if (cancelCancelGroupInviteTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0) if (cancelGroupInviteTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
return ValidationResult.NEGATIVE_FEE; return ValidationResult.NEGATIVE_FEE;
if (!Arrays.equals(admin.getLastReference(), cancelCancelGroupInviteTransactionData.getReference())) // Check reference
if (!Arrays.equals(admin.getLastReference(), cancelGroupInviteTransactionData.getReference()))
return ValidationResult.INVALID_REFERENCE; return ValidationResult.INVALID_REFERENCE;
// Check creator has enough funds // Check creator has enough funds
if (admin.getConfirmedBalance(Asset.QORA).compareTo(cancelCancelGroupInviteTransactionData.getFee()) < 0) if (admin.getConfirmedBalance(Asset.QORA).compareTo(cancelGroupInviteTransactionData.getFee()) < 0)
return ValidationResult.NO_BALANCE; return ValidationResult.NO_BALANCE;
return ValidationResult.OK; return ValidationResult.OK;
@ -123,35 +114,35 @@ public class CancelGroupInviteTransaction extends Transaction {
@Override @Override
public void process() throws DataException { public void process() throws DataException {
// Update Group Membership // Update Group Membership
Group group = new Group(this.repository, cancelCancelGroupInviteTransactionData.getGroupName()); Group group = new Group(this.repository, cancelGroupInviteTransactionData.getGroupId());
group.cancelInvite(cancelCancelGroupInviteTransactionData); group.cancelInvite(cancelGroupInviteTransactionData);
// Save this transaction with updated member/admin references to transactions that can help restore state // Save this transaction with updated member/admin references to transactions that can help restore state
this.repository.getTransactionRepository().save(cancelCancelGroupInviteTransactionData); this.repository.getTransactionRepository().save(cancelGroupInviteTransactionData);
// Update admin's balance // Update admin's balance
Account admin = getAdmin(); Account admin = getAdmin();
admin.setConfirmedBalance(Asset.QORA, admin.getConfirmedBalance(Asset.QORA).subtract(cancelCancelGroupInviteTransactionData.getFee())); admin.setConfirmedBalance(Asset.QORA, admin.getConfirmedBalance(Asset.QORA).subtract(cancelGroupInviteTransactionData.getFee()));
// Update admin's reference // Update admin's reference
admin.setLastReference(cancelCancelGroupInviteTransactionData.getSignature()); admin.setLastReference(cancelGroupInviteTransactionData.getSignature());
} }
@Override @Override
public void orphan() throws DataException { public void orphan() throws DataException {
// Revert group membership // Revert group membership
Group group = new Group(this.repository, cancelCancelGroupInviteTransactionData.getGroupName()); Group group = new Group(this.repository, cancelGroupInviteTransactionData.getGroupId());
group.uncancelInvite(cancelCancelGroupInviteTransactionData); group.uncancelInvite(cancelGroupInviteTransactionData);
// Delete this transaction itself // Delete this transaction itself
this.repository.getTransactionRepository().delete(cancelCancelGroupInviteTransactionData); this.repository.getTransactionRepository().delete(cancelGroupInviteTransactionData);
// Update admin's balance // Update admin's balance
Account admin = getAdmin(); Account admin = getAdmin();
admin.setConfirmedBalance(Asset.QORA, admin.getConfirmedBalance(Asset.QORA).add(cancelCancelGroupInviteTransactionData.getFee())); admin.setConfirmedBalance(Asset.QORA, admin.getConfirmedBalance(Asset.QORA).add(cancelGroupInviteTransactionData.getFee()));
// Update admin's reference // Update admin's reference
admin.setLastReference(cancelCancelGroupInviteTransactionData.getReference()); admin.setLastReference(cancelGroupInviteTransactionData.getReference());
} }
} }

View File

@ -96,9 +96,9 @@ public class CreateGroupTransaction extends Transaction {
if (createGroupTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0) if (createGroupTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
return ValidationResult.NEGATIVE_FEE; return ValidationResult.NEGATIVE_FEE;
// Check reference is correct
Account creator = getCreator(); Account creator = getCreator();
// Check reference is correct
if (!Arrays.equals(creator.getLastReference(), createGroupTransactionData.getReference())) if (!Arrays.equals(creator.getLastReference(), createGroupTransactionData.getReference()))
return ValidationResult.INVALID_REFERENCE; return ValidationResult.INVALID_REFERENCE;
@ -115,6 +115,9 @@ public class CreateGroupTransaction extends Transaction {
Group group = new Group(this.repository, createGroupTransactionData); Group group = new Group(this.repository, createGroupTransactionData);
group.create(createGroupTransactionData); group.create(createGroupTransactionData);
// Note newly assigned group ID in our transaction record
createGroupTransactionData.setGroupId(group.getGroupData().getGroupId());
// Save this transaction // Save this transaction
this.repository.getTransactionRepository().save(createGroupTransactionData); this.repository.getTransactionRepository().save(createGroupTransactionData);
@ -129,7 +132,7 @@ public class CreateGroupTransaction extends Transaction {
@Override @Override
public void orphan() throws DataException { public void orphan() throws DataException {
// Uncreate group // Uncreate group
Group group = new Group(this.repository, createGroupTransactionData.getGroupName()); Group group = new Group(this.repository, createGroupTransactionData.getGroupId());
group.uncreate(); group.uncreate();
// Delete this transaction itself // Delete this transaction itself

View File

@ -14,11 +14,8 @@ import org.qora.data.group.GroupData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.group.Group; import org.qora.group.Group;
import org.qora.repository.DataException; import org.qora.repository.DataException;
import org.qora.repository.GroupRepository;
import org.qora.repository.Repository; import org.qora.repository.Repository;
import com.google.common.base.Utf8;
public class GroupBanTransaction extends Transaction { public class GroupBanTransaction extends Transaction {
// Properties // Properties
@ -77,47 +74,38 @@ public class GroupBanTransaction extends Transaction {
@Override @Override
public ValidationResult isValid() throws DataException { public ValidationResult isValid() throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository(); // Check offender address is valid
String groupName = groupBanTransactionData.getGroupName();
// Check member address is valid
if (!Crypto.isValidAddress(groupBanTransactionData.getOffender())) if (!Crypto.isValidAddress(groupBanTransactionData.getOffender()))
return ValidationResult.INVALID_ADDRESS; return ValidationResult.INVALID_ADDRESS;
// Check group name size bounds GroupData groupData = this.repository.getGroupRepository().fromGroupId(groupBanTransactionData.getGroupId());
int groupNameLength = Utf8.encodedLength(groupName);
if (groupNameLength < 1 || groupNameLength > Group.MAX_NAME_SIZE)
return ValidationResult.INVALID_NAME_LENGTH;
// Check group name is lowercase
if (!groupName.equals(groupName.toLowerCase()))
return ValidationResult.NAME_NOT_LOWER_CASE;
GroupData groupData = groupRepository.fromGroupName(groupName);
// Check group exists // Check group exists
if (groupData == null) if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST; return ValidationResult.GROUP_DOES_NOT_EXIST;
Account admin = getAdmin(); Account admin = getAdmin();
Account member = getOffender();
// Can't ban if not an admin // Can't ban if not an admin
if (!groupRepository.adminExists(groupName, admin.getAddress())) if (!this.repository.getGroupRepository().adminExists(groupBanTransactionData.getGroupId(), admin.getAddress()))
return ValidationResult.NOT_GROUP_ADMIN; return ValidationResult.NOT_GROUP_ADMIN;
Account offender = getOffender();
// Can't ban another admin unless the group owner // Can't ban another admin unless the group owner
if (!admin.getAddress().equals(groupData.getOwner()) && groupRepository.adminExists(groupName, member.getAddress())) if (!admin.getAddress().equals(groupData.getOwner())
&& this.repository.getGroupRepository().adminExists(groupBanTransactionData.getGroupId(), offender.getAddress()))
return ValidationResult.INVALID_GROUP_OWNER; return ValidationResult.INVALID_GROUP_OWNER;
// Check fee is positive // Check fee is positive
if (groupBanTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0) if (groupBanTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
return ValidationResult.NEGATIVE_FEE; return ValidationResult.NEGATIVE_FEE;
// Check reference
if (!Arrays.equals(admin.getLastReference(), groupBanTransactionData.getReference())) if (!Arrays.equals(admin.getLastReference(), groupBanTransactionData.getReference()))
return ValidationResult.INVALID_REFERENCE; return ValidationResult.INVALID_REFERENCE;
// Check creator has enough funds // Check admin has enough funds
if (admin.getConfirmedBalance(Asset.QORA).compareTo(groupBanTransactionData.getFee()) < 0) if (admin.getConfirmedBalance(Asset.QORA).compareTo(groupBanTransactionData.getFee()) < 0)
return ValidationResult.NO_BALANCE; return ValidationResult.NO_BALANCE;
@ -127,7 +115,7 @@ public class GroupBanTransaction extends Transaction {
@Override @Override
public void process() throws DataException { public void process() throws DataException {
// Update Group Membership // Update Group Membership
Group group = new Group(this.repository, groupBanTransactionData.getGroupName()); Group group = new Group(this.repository, groupBanTransactionData.getGroupId());
group.ban(groupBanTransactionData); group.ban(groupBanTransactionData);
// Save this transaction with updated member/admin references to transactions that can help restore state // Save this transaction with updated member/admin references to transactions that can help restore state
@ -144,7 +132,7 @@ public class GroupBanTransaction extends Transaction {
@Override @Override
public void orphan() throws DataException { public void orphan() throws DataException {
// Revert group membership // Revert group membership
Group group = new Group(this.repository, groupBanTransactionData.getGroupName()); Group group = new Group(this.repository, groupBanTransactionData.getGroupId());
group.unban(groupBanTransactionData); group.unban(groupBanTransactionData);
// Delete this transaction itself // Delete this transaction itself

View File

@ -14,11 +14,8 @@ import org.qora.data.group.GroupData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.group.Group; import org.qora.group.Group;
import org.qora.repository.DataException; import org.qora.repository.DataException;
import org.qora.repository.GroupRepository;
import org.qora.repository.Repository; import org.qora.repository.Repository;
import com.google.common.base.Utf8;
public class GroupInviteTransaction extends Transaction { public class GroupInviteTransaction extends Transaction {
// Properties // Properties
@ -77,9 +74,6 @@ public class GroupInviteTransaction extends Transaction {
@Override @Override
public ValidationResult isValid() throws DataException { public ValidationResult isValid() throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = groupInviteTransactionData.getGroupName();
// Check time to live zero (infinite) or positive // Check time to live zero (infinite) or positive
if (groupInviteTransactionData.getTimeToLive() < 0) if (groupInviteTransactionData.getTimeToLive() < 0)
return ValidationResult.INVALID_LIFETIME; return ValidationResult.INVALID_LIFETIME;
@ -88,36 +82,33 @@ public class GroupInviteTransaction extends Transaction {
if (!Crypto.isValidAddress(groupInviteTransactionData.getInvitee())) if (!Crypto.isValidAddress(groupInviteTransactionData.getInvitee()))
return ValidationResult.INVALID_ADDRESS; return ValidationResult.INVALID_ADDRESS;
// Check group name size bounds GroupData groupData = this.repository.getGroupRepository().fromGroupId(groupInviteTransactionData.getGroupId());
int groupNameLength = Utf8.encodedLength(groupName);
if (groupNameLength < 1 || groupNameLength > Group.MAX_NAME_SIZE)
return ValidationResult.INVALID_NAME_LENGTH;
// Check group name is lowercase
if (!groupName.equals(groupName.toLowerCase()))
return ValidationResult.NAME_NOT_LOWER_CASE;
GroupData groupData = groupRepository.fromGroupName(groupName);
// Check group exists // Check group exists
if (groupData == null) if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST; return ValidationResult.GROUP_DOES_NOT_EXIST;
Account admin = getAdmin(); Account admin = getAdmin();
Account invitee = getInvitee();
// Can't invite if not an admin // Can't invite if not an admin
if (!groupRepository.adminExists(groupName, admin.getAddress())) if (!this.repository.getGroupRepository().adminExists(groupInviteTransactionData.getGroupId(), admin.getAddress()))
return ValidationResult.NOT_GROUP_ADMIN; return ValidationResult.NOT_GROUP_ADMIN;
Account invitee = getInvitee();
// Check invitee not already in group // Check invitee not already in group
if (groupRepository.memberExists(groupName, invitee.getAddress())) if (this.repository.getGroupRepository().memberExists(groupInviteTransactionData.getGroupId(), invitee.getAddress()))
return ValidationResult.ALREADY_GROUP_MEMBER; return ValidationResult.ALREADY_GROUP_MEMBER;
// Check invitee is not banned
if (this.repository.getGroupRepository().banExists(groupInviteTransactionData.getGroupId(), invitee.getAddress()))
return ValidationResult.BANNED_FROM_GROUP;
// Check fee is positive // Check fee is positive
if (groupInviteTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0) if (groupInviteTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
return ValidationResult.NEGATIVE_FEE; return ValidationResult.NEGATIVE_FEE;
// Check reference
if (!Arrays.equals(admin.getLastReference(), groupInviteTransactionData.getReference())) if (!Arrays.equals(admin.getLastReference(), groupInviteTransactionData.getReference()))
return ValidationResult.INVALID_REFERENCE; return ValidationResult.INVALID_REFERENCE;
@ -131,7 +122,7 @@ public class GroupInviteTransaction extends Transaction {
@Override @Override
public void process() throws DataException { public void process() throws DataException {
// Update Group Membership // Update Group Membership
Group group = new Group(this.repository, groupInviteTransactionData.getGroupName()); Group group = new Group(this.repository, groupInviteTransactionData.getGroupId());
group.invite(groupInviteTransactionData); group.invite(groupInviteTransactionData);
// Save this transaction with updated member/admin references to transactions that can help restore state // Save this transaction with updated member/admin references to transactions that can help restore state
@ -148,7 +139,7 @@ public class GroupInviteTransaction extends Transaction {
@Override @Override
public void orphan() throws DataException { public void orphan() throws DataException {
// Revert group membership // Revert group membership
Group group = new Group(this.repository, groupInviteTransactionData.getGroupName()); Group group = new Group(this.repository, groupInviteTransactionData.getGroupId());
group.uninvite(groupInviteTransactionData); group.uninvite(groupInviteTransactionData);
// Delete this transaction itself // Delete this transaction itself

View File

@ -17,8 +17,6 @@ import org.qora.repository.DataException;
import org.qora.repository.GroupRepository; import org.qora.repository.GroupRepository;
import org.qora.repository.Repository; import org.qora.repository.Repository;
import com.google.common.base.Utf8;
public class GroupKickTransaction extends Transaction { public class GroupKickTransaction extends Transaction {
// Properties // Properties
@ -77,47 +75,39 @@ public class GroupKickTransaction extends Transaction {
@Override @Override
public ValidationResult isValid() throws DataException { public ValidationResult isValid() throws DataException {
GroupRepository groupRepository = this.repository.getGroupRepository();
String groupName = groupKickTransactionData.getGroupName();
// Check member address is valid // Check member address is valid
if (!Crypto.isValidAddress(groupKickTransactionData.getMember())) if (!Crypto.isValidAddress(groupKickTransactionData.getMember()))
return ValidationResult.INVALID_ADDRESS; return ValidationResult.INVALID_ADDRESS;
// Check group name size bounds GroupRepository groupRepository = this.repository.getGroupRepository();
int groupNameLength = Utf8.encodedLength(groupName); int groupId = groupKickTransactionData.getGroupId();
if (groupNameLength < 1 || groupNameLength > Group.MAX_NAME_SIZE) GroupData groupData = groupRepository.fromGroupId(groupId);
return ValidationResult.INVALID_NAME_LENGTH;
// Check group name is lowercase
if (!groupName.equals(groupName.toLowerCase()))
return ValidationResult.NAME_NOT_LOWER_CASE;
GroupData groupData = groupRepository.fromGroupName(groupName);
// Check group exists // Check group exists
if (groupData == null) if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST; return ValidationResult.GROUP_DOES_NOT_EXIST;
Account admin = getAdmin(); Account admin = getAdmin();
Account member = getMember();
// Can't kick if not an admin // Can't kick if not an admin
if (!groupRepository.adminExists(groupName, admin.getAddress())) if (!groupRepository.adminExists(groupId, admin.getAddress()))
return ValidationResult.NOT_GROUP_ADMIN; return ValidationResult.NOT_GROUP_ADMIN;
Account member = getMember();
// Check member actually in group UNLESS there's a pending join request // Check member actually in group UNLESS there's a pending join request
if (!groupRepository.joinRequestExists(groupName, member.getAddress()) && !groupRepository.memberExists(groupName, member.getAddress())) if (!groupRepository.joinRequestExists(groupId, member.getAddress()) && !groupRepository.memberExists(groupId, member.getAddress()))
return ValidationResult.NOT_GROUP_MEMBER; return ValidationResult.NOT_GROUP_MEMBER;
// Can't kick another admin unless the group owner // Can't kick another admin unless the group owner
if (!admin.getAddress().equals(groupData.getOwner()) && groupRepository.adminExists(groupName, member.getAddress())) if (!admin.getAddress().equals(groupData.getOwner()) && groupRepository.adminExists(groupId, member.getAddress()))
return ValidationResult.INVALID_GROUP_OWNER; return ValidationResult.INVALID_GROUP_OWNER;
// Check fee is positive // Check fee is positive
if (groupKickTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0) if (groupKickTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
return ValidationResult.NEGATIVE_FEE; return ValidationResult.NEGATIVE_FEE;
// Check reference
if (!Arrays.equals(admin.getLastReference(), groupKickTransactionData.getReference())) if (!Arrays.equals(admin.getLastReference(), groupKickTransactionData.getReference()))
return ValidationResult.INVALID_REFERENCE; return ValidationResult.INVALID_REFERENCE;
@ -131,7 +121,7 @@ public class GroupKickTransaction extends Transaction {
@Override @Override
public void process() throws DataException { public void process() throws DataException {
// Update Group Membership // Update Group Membership
Group group = new Group(this.repository, groupKickTransactionData.getGroupName()); Group group = new Group(this.repository, groupKickTransactionData.getGroupId());
group.kick(groupKickTransactionData); group.kick(groupKickTransactionData);
// Save this transaction with updated member/admin references to transactions that can help restore state // Save this transaction with updated member/admin references to transactions that can help restore state
@ -148,7 +138,7 @@ public class GroupKickTransaction extends Transaction {
@Override @Override
public void orphan() throws DataException { public void orphan() throws DataException {
// Revert group membership // Revert group membership
Group group = new Group(this.repository, groupKickTransactionData.getGroupName()); Group group = new Group(this.repository, groupKickTransactionData.getGroupId());
group.unkick(groupKickTransactionData); group.unkick(groupKickTransactionData);
// Delete this transaction itself // Delete this transaction itself

View File

@ -161,7 +161,7 @@ public class IssueAssetTransaction extends Transaction {
Account owner = getOwner(); Account owner = getOwner();
owner.deleteBalance(issueAssetTransactionData.getAssetId()); owner.deleteBalance(issueAssetTransactionData.getAssetId());
// Issue asset // Deissue asset
Asset asset = new Asset(this.repository, issueAssetTransactionData.getAssetId()); Asset asset = new Asset(this.repository, issueAssetTransactionData.getAssetId());
asset.deissue(); asset.deissue();

View File

@ -15,8 +15,6 @@ import org.qora.group.Group;
import org.qora.repository.DataException; import org.qora.repository.DataException;
import org.qora.repository.Repository; import org.qora.repository.Repository;
import com.google.common.base.Utf8;
public class JoinGroupTransaction extends Transaction { public class JoinGroupTransaction extends Transaction {
// Properties // Properties
@ -68,16 +66,7 @@ public class JoinGroupTransaction extends Transaction {
@Override @Override
public ValidationResult isValid() throws DataException { public ValidationResult isValid() throws DataException {
// Check group name size bounds GroupData groupData = this.repository.getGroupRepository().fromGroupId(joinGroupTransactionData.getGroupId());
int groupNameLength = Utf8.encodedLength(joinGroupTransactionData.getGroupName());
if (groupNameLength < 1 || groupNameLength > Group.MAX_NAME_SIZE)
return ValidationResult.INVALID_NAME_LENGTH;
// Check group name is lowercase
if (!joinGroupTransactionData.getGroupName().equals(joinGroupTransactionData.getGroupName().toLowerCase()))
return ValidationResult.NAME_NOT_LOWER_CASE;
GroupData groupData = this.repository.getGroupRepository().fromGroupName(joinGroupTransactionData.getGroupName());
// Check group exists // Check group exists
if (groupData == null) if (groupData == null)
@ -85,13 +74,17 @@ public class JoinGroupTransaction extends Transaction {
Account joiner = getJoiner(); Account joiner = getJoiner();
if (this.repository.getGroupRepository().memberExists(joinGroupTransactionData.getGroupName(), joiner.getAddress())) if (this.repository.getGroupRepository().memberExists(joinGroupTransactionData.getGroupId(), joiner.getAddress()))
return ValidationResult.ALREADY_GROUP_MEMBER; return ValidationResult.ALREADY_GROUP_MEMBER;
// Check member is not banned // Check member is not banned
if (this.repository.getGroupRepository().banExists(joinGroupTransactionData.getGroupName(), joiner.getAddress())) if (this.repository.getGroupRepository().banExists(joinGroupTransactionData.getGroupId(), joiner.getAddress()))
return ValidationResult.BANNED_FROM_GROUP; return ValidationResult.BANNED_FROM_GROUP;
// Check join request doesn't already exist
if (this.repository.getGroupRepository().joinRequestExists(joinGroupTransactionData.getGroupId(), joiner.getAddress()))
return ValidationResult.JOIN_REQUEST_EXISTS;
// Check fee is positive // Check fee is positive
if (joinGroupTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0) if (joinGroupTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
return ValidationResult.NEGATIVE_FEE; return ValidationResult.NEGATIVE_FEE;
@ -109,7 +102,7 @@ public class JoinGroupTransaction extends Transaction {
@Override @Override
public void process() throws DataException { public void process() throws DataException {
// Update Group Membership // Update Group Membership
Group group = new Group(this.repository, joinGroupTransactionData.getGroupName()); Group group = new Group(this.repository, joinGroupTransactionData.getGroupId());
group.join(joinGroupTransactionData); group.join(joinGroupTransactionData);
// Save this transaction // Save this transaction
@ -126,7 +119,7 @@ public class JoinGroupTransaction extends Transaction {
@Override @Override
public void orphan() throws DataException { public void orphan() throws DataException {
// Revert group membership // Revert group membership
Group group = new Group(this.repository, joinGroupTransactionData.getGroupName()); Group group = new Group(this.repository, joinGroupTransactionData.getGroupId());
group.unjoin(joinGroupTransactionData); group.unjoin(joinGroupTransactionData);
// Delete this transaction itself // Delete this transaction itself

View File

@ -15,8 +15,6 @@ import org.qora.group.Group;
import org.qora.repository.DataException; import org.qora.repository.DataException;
import org.qora.repository.Repository; import org.qora.repository.Repository;
import com.google.common.base.Utf8;
public class LeaveGroupTransaction extends Transaction { public class LeaveGroupTransaction extends Transaction {
// Properties // Properties
@ -68,16 +66,7 @@ public class LeaveGroupTransaction extends Transaction {
@Override @Override
public ValidationResult isValid() throws DataException { public ValidationResult isValid() throws DataException {
// Check group name size bounds GroupData groupData = this.repository.getGroupRepository().fromGroupId(leaveGroupTransactionData.getGroupId());
int groupNameLength = Utf8.encodedLength(leaveGroupTransactionData.getGroupName());
if (groupNameLength < 1 || groupNameLength > Group.MAX_NAME_SIZE)
return ValidationResult.INVALID_NAME_LENGTH;
// Check group name is lowercase
if (!leaveGroupTransactionData.getGroupName().equals(leaveGroupTransactionData.getGroupName().toLowerCase()))
return ValidationResult.NAME_NOT_LOWER_CASE;
GroupData groupData = this.repository.getGroupRepository().fromGroupName(leaveGroupTransactionData.getGroupName());
// Check group exists // Check group exists
if (groupData == null) if (groupData == null)
@ -89,13 +78,15 @@ public class LeaveGroupTransaction extends Transaction {
if (leaver.getAddress().equals(groupData.getOwner())) if (leaver.getAddress().equals(groupData.getOwner()))
return ValidationResult.GROUP_OWNER_CANNOT_LEAVE; return ValidationResult.GROUP_OWNER_CANNOT_LEAVE;
if (!this.repository.getGroupRepository().memberExists(leaveGroupTransactionData.getGroupName(), leaver.getAddress())) // Check leaver is actually a member of group
if (!this.repository.getGroupRepository().memberExists(leaveGroupTransactionData.getGroupId(), leaver.getAddress()))
return ValidationResult.NOT_GROUP_MEMBER; return ValidationResult.NOT_GROUP_MEMBER;
// Check fee is positive // Check fee is positive
if (leaveGroupTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0) if (leaveGroupTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
return ValidationResult.NEGATIVE_FEE; return ValidationResult.NEGATIVE_FEE;
// Check reference
if (!Arrays.equals(leaver.getLastReference(), leaveGroupTransactionData.getReference())) if (!Arrays.equals(leaver.getLastReference(), leaveGroupTransactionData.getReference()))
return ValidationResult.INVALID_REFERENCE; return ValidationResult.INVALID_REFERENCE;
@ -109,7 +100,7 @@ public class LeaveGroupTransaction extends Transaction {
@Override @Override
public void process() throws DataException { public void process() throws DataException {
// Update Group Membership // Update Group Membership
Group group = new Group(this.repository, leaveGroupTransactionData.getGroupName()); Group group = new Group(this.repository, leaveGroupTransactionData.getGroupId());
group.leave(leaveGroupTransactionData); group.leave(leaveGroupTransactionData);
// Save this transaction with updated member/admin references to transactions that can help restore state // Save this transaction with updated member/admin references to transactions that can help restore state
@ -126,7 +117,7 @@ public class LeaveGroupTransaction extends Transaction {
@Override @Override
public void orphan() throws DataException { public void orphan() throws DataException {
// Revert group membership // Revert group membership
Group group = new Group(this.repository, leaveGroupTransactionData.getGroupName()); Group group = new Group(this.repository, leaveGroupTransactionData.getGroupId());
group.unleave(leaveGroupTransactionData); group.unleave(leaveGroupTransactionData);
// Delete this transaction itself // Delete this transaction itself

View File

@ -16,8 +16,6 @@ import org.qora.group.Group;
import org.qora.repository.DataException; import org.qora.repository.DataException;
import org.qora.repository.Repository; import org.qora.repository.Repository;
import com.google.common.base.Utf8;
public class RemoveGroupAdminTransaction extends Transaction { public class RemoveGroupAdminTransaction extends Transaction {
// Properties // Properties
@ -80,16 +78,7 @@ public class RemoveGroupAdminTransaction extends Transaction {
if (!Crypto.isValidAddress(removeGroupAdminTransactionData.getAdmin())) if (!Crypto.isValidAddress(removeGroupAdminTransactionData.getAdmin()))
return ValidationResult.INVALID_ADDRESS; return ValidationResult.INVALID_ADDRESS;
// Check group name size bounds GroupData groupData = this.repository.getGroupRepository().fromGroupId(removeGroupAdminTransactionData.getGroupId());
int groupNameLength = Utf8.encodedLength(removeGroupAdminTransactionData.getGroupName());
if (groupNameLength < 1 || groupNameLength > Group.MAX_NAME_SIZE)
return ValidationResult.INVALID_NAME_LENGTH;
// Check group name is lowercase
if (!removeGroupAdminTransactionData.getGroupName().equals(removeGroupAdminTransactionData.getGroupName().toLowerCase()))
return ValidationResult.NAME_NOT_LOWER_CASE;
GroupData groupData = this.repository.getGroupRepository().fromGroupName(removeGroupAdminTransactionData.getGroupName());
// Check group exists // Check group exists
if (groupData == null) if (groupData == null)
@ -104,13 +93,14 @@ public class RemoveGroupAdminTransaction extends Transaction {
Account admin = getAdmin(); Account admin = getAdmin();
// Check member is an admin // Check member is an admin
if (!this.repository.getGroupRepository().adminExists(removeGroupAdminTransactionData.getGroupName(), admin.getAddress())) if (!this.repository.getGroupRepository().adminExists(removeGroupAdminTransactionData.getGroupId(), admin.getAddress()))
return ValidationResult.NOT_GROUP_ADMIN; return ValidationResult.NOT_GROUP_ADMIN;
// Check fee is positive // Check fee is positive
if (removeGroupAdminTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0) if (removeGroupAdminTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
return ValidationResult.NEGATIVE_FEE; return ValidationResult.NEGATIVE_FEE;
// Check reference
if (!Arrays.equals(owner.getLastReference(), removeGroupAdminTransactionData.getReference())) if (!Arrays.equals(owner.getLastReference(), removeGroupAdminTransactionData.getReference()))
return ValidationResult.INVALID_REFERENCE; return ValidationResult.INVALID_REFERENCE;
@ -124,7 +114,7 @@ public class RemoveGroupAdminTransaction extends Transaction {
@Override @Override
public void process() throws DataException { public void process() throws DataException {
// Update Group adminship // Update Group adminship
Group group = new Group(this.repository, removeGroupAdminTransactionData.getGroupName()); Group group = new Group(this.repository, removeGroupAdminTransactionData.getGroupId());
group.demoteFromAdmin(removeGroupAdminTransactionData); group.demoteFromAdmin(removeGroupAdminTransactionData);
// Save this transaction // Save this transaction
@ -141,7 +131,7 @@ public class RemoveGroupAdminTransaction extends Transaction {
@Override @Override
public void orphan() throws DataException { public void orphan() throws DataException {
// Revert group adminship // Revert group adminship
Group group = new Group(this.repository, removeGroupAdminTransactionData.getGroupName()); Group group = new Group(this.repository, removeGroupAdminTransactionData.getGroupId());
group.undemoteFromAdmin(removeGroupAdminTransactionData); group.undemoteFromAdmin(removeGroupAdminTransactionData);
// Delete this transaction itself // Delete this transaction itself

View File

@ -58,7 +58,7 @@ public abstract class Transaction {
ADD_GROUP_ADMIN(24), ADD_GROUP_ADMIN(24),
REMOVE_GROUP_ADMIN(25), REMOVE_GROUP_ADMIN(25),
GROUP_BAN(26), GROUP_BAN(26),
GROUP_UNBAN(27), CANCEL_GROUP_BAN(27),
GROUP_KICK(28), GROUP_KICK(28),
GROUP_INVITE(29), GROUP_INVITE(29),
CANCEL_GROUP_INVITE(30), CANCEL_GROUP_INVITE(30),
@ -138,6 +138,7 @@ public abstract class Transaction {
BAN_EXISTS(58), BAN_EXISTS(58),
BAN_UNKNOWN(59), BAN_UNKNOWN(59),
BANNED_FROM_GROUP(60), BANNED_FROM_GROUP(60),
JOIN_REQUEST_EXISTS(61),
NOT_YET_RELEASED(1000); NOT_YET_RELEASED(1000);
public final int value; public final int value;
@ -252,8 +253,8 @@ public abstract class Transaction {
case GROUP_BAN: case GROUP_BAN:
return new GroupBanTransaction(repository, transactionData); return new GroupBanTransaction(repository, transactionData);
case GROUP_UNBAN: case CANCEL_GROUP_BAN:
return new GroupUnbanTransaction(repository, transactionData); return new CancelGroupBanTransaction(repository, transactionData);
case GROUP_KICK: case GROUP_KICK:
return new GroupKickTransaction(repository, transactionData); return new GroupKickTransaction(repository, transactionData);

View File

@ -80,43 +80,39 @@ public class UpdateGroupTransaction extends Transaction {
if (!Crypto.isValidAddress(updateGroupTransactionData.getNewOwner())) if (!Crypto.isValidAddress(updateGroupTransactionData.getNewOwner()))
return ValidationResult.INVALID_ADDRESS; return ValidationResult.INVALID_ADDRESS;
// Check group name size bounds
int groupNameLength = Utf8.encodedLength(updateGroupTransactionData.getGroupName());
if (groupNameLength < 1 || groupNameLength > Group.MAX_NAME_SIZE)
return ValidationResult.INVALID_NAME_LENGTH;
// Check new description size bounds // Check new description size bounds
int newDescriptionLength = Utf8.encodedLength(updateGroupTransactionData.getNewDescription()); int newDescriptionLength = Utf8.encodedLength(updateGroupTransactionData.getNewDescription());
if (newDescriptionLength < 1 || newDescriptionLength > Group.MAX_DESCRIPTION_SIZE) if (newDescriptionLength < 1 || newDescriptionLength > Group.MAX_DESCRIPTION_SIZE)
return ValidationResult.INVALID_DESCRIPTION_LENGTH; return ValidationResult.INVALID_DESCRIPTION_LENGTH;
// Check group name is lowercase GroupData groupData = this.repository.getGroupRepository().fromGroupId(updateGroupTransactionData.getGroupId());
if (!updateGroupTransactionData.getGroupName().equals(updateGroupTransactionData.getGroupName().toLowerCase()))
return ValidationResult.NAME_NOT_LOWER_CASE;
GroupData groupData = this.repository.getGroupRepository().fromGroupName(updateGroupTransactionData.getGroupName());
// Check group exists // Check group exists
if (groupData == null) if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST; return ValidationResult.GROUP_DOES_NOT_EXIST;
// Check transaction's public key matches group's current owner
Account owner = getOwner(); Account owner = getOwner();
// Check transaction's public key matches group's current owner
if (!owner.getAddress().equals(groupData.getOwner())) if (!owner.getAddress().equals(groupData.getOwner()))
return ValidationResult.INVALID_GROUP_OWNER; return ValidationResult.INVALID_GROUP_OWNER;
Account newOwner = getNewOwner();
// Check new owner is not banned
if (this.repository.getGroupRepository().banExists(updateGroupTransactionData.getGroupId(), newOwner.getAddress()))
return ValidationResult.BANNED_FROM_GROUP;
// Check fee is positive // Check fee is positive
if (updateGroupTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0) if (updateGroupTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
return ValidationResult.NEGATIVE_FEE; return ValidationResult.NEGATIVE_FEE;
// Check reference is correct // Check reference is correct
Account creator = getCreator(); if (!Arrays.equals(owner.getLastReference(), updateGroupTransactionData.getReference()))
if (!Arrays.equals(creator.getLastReference(), updateGroupTransactionData.getReference()))
return ValidationResult.INVALID_REFERENCE; return ValidationResult.INVALID_REFERENCE;
// Check creator has enough funds // Check creator has enough funds
if (creator.getConfirmedBalance(Asset.QORA).compareTo(updateGroupTransactionData.getFee()) < 0) if (owner.getConfirmedBalance(Asset.QORA).compareTo(updateGroupTransactionData.getFee()) < 0)
return ValidationResult.NO_BALANCE; return ValidationResult.NO_BALANCE;
return ValidationResult.OK; return ValidationResult.OK;
@ -125,7 +121,7 @@ public class UpdateGroupTransaction extends Transaction {
@Override @Override
public void process() throws DataException { public void process() throws DataException {
// Update Group // Update Group
Group group = new Group(this.repository, updateGroupTransactionData.getGroupName()); Group group = new Group(this.repository, updateGroupTransactionData.getGroupId());
group.updateGroup(updateGroupTransactionData); group.updateGroup(updateGroupTransactionData);
// Save this transaction, now with updated "group reference" to previous transaction that updated group // Save this transaction, now with updated "group reference" to previous transaction that updated group
@ -142,7 +138,7 @@ public class UpdateGroupTransaction extends Transaction {
@Override @Override
public void orphan() throws DataException { public void orphan() throws DataException {
// Revert Group update // Revert Group update
Group group = new Group(this.repository, updateGroupTransactionData.getGroupName()); Group group = new Group(this.repository, updateGroupTransactionData.getGroupId());
group.unupdateGroup(updateGroupTransactionData); group.unupdateGroup(updateGroupTransactionData);
// Delete this transaction itself // Delete this transaction itself

View File

@ -9,11 +9,9 @@ import org.json.simple.JSONObject;
import org.qora.account.PublicKeyAccount; import org.qora.account.PublicKeyAccount;
import org.qora.data.transaction.AddGroupAdminTransactionData; import org.qora.data.transaction.AddGroupAdminTransactionData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.group.Group;
import org.qora.transform.TransformationException; import org.qora.transform.TransformationException;
import org.qora.utils.Serialization; import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
import com.google.common.hash.HashCode; import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs; import com.google.common.primitives.Longs;
@ -22,10 +20,10 @@ public class AddGroupAdminTransactionTransformer extends TransactionTransformer
// Property lengths // Property lengths
private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH; private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH; private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int MEMBER_LENGTH = ADDRESS_LENGTH; private static final int MEMBER_LENGTH = ADDRESS_LENGTH;
private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + MEMBER_LENGTH; private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH;
static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong(); long timestamp = byteBuffer.getLong();
@ -35,7 +33,7 @@ public class AddGroupAdminTransactionTransformer extends TransactionTransformer
byte[] ownerPublicKey = Serialization.deserializePublicKey(byteBuffer); byte[] ownerPublicKey = Serialization.deserializePublicKey(byteBuffer);
String groupName = Serialization.deserializeSizedString(byteBuffer, Group.MAX_NAME_SIZE); int groupId = byteBuffer.getInt();
String member = Serialization.deserializeAddress(byteBuffer); String member = Serialization.deserializeAddress(byteBuffer);
@ -44,15 +42,11 @@ public class AddGroupAdminTransactionTransformer extends TransactionTransformer
byte[] signature = new byte[SIGNATURE_LENGTH]; byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature); byteBuffer.get(signature);
return new AddGroupAdminTransactionData(ownerPublicKey, groupName, member, fee, timestamp, reference, signature); return new AddGroupAdminTransactionData(ownerPublicKey, groupId, member, fee, timestamp, reference, signature);
} }
public static int getDataLength(TransactionData transactionData) throws TransformationException { public static int getDataLength(TransactionData transactionData) throws TransformationException {
AddGroupAdminTransactionData addGroupAdminTransactionData = (AddGroupAdminTransactionData) transactionData; return TYPE_LENGTH + TYPELESS_LENGTH;
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(addGroupAdminTransactionData.getGroupName());
return dataLength;
} }
public static byte[] toBytes(TransactionData transactionData) throws TransformationException { public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@ -66,7 +60,7 @@ public class AddGroupAdminTransactionTransformer extends TransactionTransformer
bytes.write(addGroupAdminTransactionData.getReference()); bytes.write(addGroupAdminTransactionData.getReference());
bytes.write(addGroupAdminTransactionData.getCreatorPublicKey()); bytes.write(addGroupAdminTransactionData.getCreatorPublicKey());
Serialization.serializeSizedString(bytes, addGroupAdminTransactionData.getGroupName()); bytes.write(Ints.toByteArray(addGroupAdminTransactionData.getGroupId()));
Serialization.serializeAddress(bytes, addGroupAdminTransactionData.getMember()); Serialization.serializeAddress(bytes, addGroupAdminTransactionData.getMember());
Serialization.serializeBigDecimal(bytes, addGroupAdminTransactionData.getFee()); Serialization.serializeBigDecimal(bytes, addGroupAdminTransactionData.getFee());
@ -92,7 +86,7 @@ public class AddGroupAdminTransactionTransformer extends TransactionTransformer
json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey)); json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey));
json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString()); json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString());
json.put("groupName", addGroupAdminTransactionData.getGroupName()); json.put("groupId", addGroupAdminTransactionData.getGroupId());
json.put("member", addGroupAdminTransactionData.getMember()); json.put("member", addGroupAdminTransactionData.getMember());
} catch (ClassCastException e) { } catch (ClassCastException e) {
throw new TransformationException(e); throw new TransformationException(e);

View File

@ -7,25 +7,23 @@ import java.nio.ByteBuffer;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import org.qora.account.PublicKeyAccount; import org.qora.account.PublicKeyAccount;
import org.qora.data.transaction.GroupUnbanTransactionData; import org.qora.data.transaction.CancelGroupBanTransactionData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.group.Group;
import org.qora.transform.TransformationException; import org.qora.transform.TransformationException;
import org.qora.utils.Serialization; import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
import com.google.common.hash.HashCode; import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs; import com.google.common.primitives.Longs;
public class GroupUnbanTransactionTransformer extends TransactionTransformer { public class CancelGroupBanTransactionTransformer extends TransactionTransformer {
// Property lengths // Property lengths
private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH; private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH; private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int MEMBER_LENGTH = ADDRESS_LENGTH; private static final int MEMBER_LENGTH = ADDRESS_LENGTH;
private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + NAME_SIZE_LENGTH + MEMBER_LENGTH; private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH;
static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong(); long timestamp = byteBuffer.getLong();
@ -35,7 +33,7 @@ public class GroupUnbanTransactionTransformer extends TransactionTransformer {
byte[] adminPublicKey = Serialization.deserializePublicKey(byteBuffer); byte[] adminPublicKey = Serialization.deserializePublicKey(byteBuffer);
String groupName = Serialization.deserializeSizedString(byteBuffer, Group.MAX_NAME_SIZE); int groupId = byteBuffer.getInt();
String member = Serialization.deserializeAddress(byteBuffer); String member = Serialization.deserializeAddress(byteBuffer);
@ -44,20 +42,16 @@ public class GroupUnbanTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH]; byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature); byteBuffer.get(signature);
return new GroupUnbanTransactionData(adminPublicKey, groupName, member, fee, timestamp, reference, signature); return new CancelGroupBanTransactionData(adminPublicKey, groupId, member, fee, timestamp, reference, signature);
} }
public static int getDataLength(TransactionData transactionData) throws TransformationException { public static int getDataLength(TransactionData transactionData) throws TransformationException {
GroupUnbanTransactionData groupUnbanTransactionData = (GroupUnbanTransactionData) transactionData; return TYPE_LENGTH + TYPELESS_LENGTH;
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(groupUnbanTransactionData.getGroupName());
return dataLength;
} }
public static byte[] toBytes(TransactionData transactionData) throws TransformationException { public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
try { try {
GroupUnbanTransactionData groupUnbanTransactionData = (GroupUnbanTransactionData) transactionData; CancelGroupBanTransactionData groupUnbanTransactionData = (CancelGroupBanTransactionData) transactionData;
ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ByteArrayOutputStream bytes = new ByteArrayOutputStream();
@ -66,7 +60,7 @@ public class GroupUnbanTransactionTransformer extends TransactionTransformer {
bytes.write(groupUnbanTransactionData.getReference()); bytes.write(groupUnbanTransactionData.getReference());
bytes.write(groupUnbanTransactionData.getCreatorPublicKey()); bytes.write(groupUnbanTransactionData.getCreatorPublicKey());
Serialization.serializeSizedString(bytes, groupUnbanTransactionData.getGroupName()); bytes.write(Ints.toByteArray(groupUnbanTransactionData.getGroupId()));
Serialization.serializeAddress(bytes, groupUnbanTransactionData.getMember()); Serialization.serializeAddress(bytes, groupUnbanTransactionData.getMember());
Serialization.serializeBigDecimal(bytes, groupUnbanTransactionData.getFee()); Serialization.serializeBigDecimal(bytes, groupUnbanTransactionData.getFee());
@ -85,14 +79,14 @@ public class GroupUnbanTransactionTransformer extends TransactionTransformer {
JSONObject json = TransactionTransformer.getBaseJSON(transactionData); JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
try { try {
GroupUnbanTransactionData groupUnbanTransactionData = (GroupUnbanTransactionData) transactionData; CancelGroupBanTransactionData groupUnbanTransactionData = (CancelGroupBanTransactionData) transactionData;
byte[] adminPublicKey = groupUnbanTransactionData.getAdminPublicKey(); byte[] adminPublicKey = groupUnbanTransactionData.getAdminPublicKey();
json.put("admin", PublicKeyAccount.getAddress(adminPublicKey)); json.put("admin", PublicKeyAccount.getAddress(adminPublicKey));
json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString()); json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString());
json.put("groupName", groupUnbanTransactionData.getGroupName()); json.put("groupId", groupUnbanTransactionData.getGroupId());
json.put("member", groupUnbanTransactionData.getMember()); json.put("member", groupUnbanTransactionData.getMember());
} catch (ClassCastException e) { } catch (ClassCastException e) {
throw new TransformationException(e); throw new TransformationException(e);

View File

@ -9,11 +9,9 @@ import org.json.simple.JSONObject;
import org.qora.account.PublicKeyAccount; import org.qora.account.PublicKeyAccount;
import org.qora.data.transaction.CancelGroupInviteTransactionData; import org.qora.data.transaction.CancelGroupInviteTransactionData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.group.Group;
import org.qora.transform.TransformationException; import org.qora.transform.TransformationException;
import org.qora.utils.Serialization; import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
import com.google.common.hash.HashCode; import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs; import com.google.common.primitives.Longs;
@ -22,10 +20,10 @@ public class CancelGroupInviteTransactionTransformer extends TransactionTransfor
// Property lengths // Property lengths
private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH; private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH; private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int INVITEE_LENGTH = ADDRESS_LENGTH; private static final int INVITEE_LENGTH = ADDRESS_LENGTH;
private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + NAME_SIZE_LENGTH + INVITEE_LENGTH; private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + INVITEE_LENGTH;
static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong(); long timestamp = byteBuffer.getLong();
@ -35,7 +33,7 @@ public class CancelGroupInviteTransactionTransformer extends TransactionTransfor
byte[] adminPublicKey = Serialization.deserializePublicKey(byteBuffer); byte[] adminPublicKey = Serialization.deserializePublicKey(byteBuffer);
String groupName = Serialization.deserializeSizedString(byteBuffer, Group.MAX_NAME_SIZE); int groupId = byteBuffer.getInt();
String invitee = Serialization.deserializeAddress(byteBuffer); String invitee = Serialization.deserializeAddress(byteBuffer);
@ -44,15 +42,11 @@ public class CancelGroupInviteTransactionTransformer extends TransactionTransfor
byte[] signature = new byte[SIGNATURE_LENGTH]; byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature); byteBuffer.get(signature);
return new CancelGroupInviteTransactionData(adminPublicKey, groupName, invitee, fee, timestamp, reference, signature); return new CancelGroupInviteTransactionData(adminPublicKey, groupId, invitee, fee, timestamp, reference, signature);
} }
public static int getDataLength(TransactionData transactionData) throws TransformationException { public static int getDataLength(TransactionData transactionData) throws TransformationException {
CancelGroupInviteTransactionData cancelGroupInviteTransactionData = (CancelGroupInviteTransactionData) transactionData; return TYPE_LENGTH + TYPELESS_LENGTH;
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(cancelGroupInviteTransactionData.getGroupName());
return dataLength;
} }
public static byte[] toBytes(TransactionData transactionData) throws TransformationException { public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@ -66,7 +60,7 @@ public class CancelGroupInviteTransactionTransformer extends TransactionTransfor
bytes.write(cancelGroupInviteTransactionData.getReference()); bytes.write(cancelGroupInviteTransactionData.getReference());
bytes.write(cancelGroupInviteTransactionData.getCreatorPublicKey()); bytes.write(cancelGroupInviteTransactionData.getCreatorPublicKey());
Serialization.serializeSizedString(bytes, cancelGroupInviteTransactionData.getGroupName()); bytes.write(Ints.toByteArray(cancelGroupInviteTransactionData.getGroupId()));
Serialization.serializeAddress(bytes, cancelGroupInviteTransactionData.getInvitee()); Serialization.serializeAddress(bytes, cancelGroupInviteTransactionData.getInvitee());
Serialization.serializeBigDecimal(bytes, cancelGroupInviteTransactionData.getFee()); Serialization.serializeBigDecimal(bytes, cancelGroupInviteTransactionData.getFee());
@ -92,7 +86,7 @@ public class CancelGroupInviteTransactionTransformer extends TransactionTransfor
json.put("admin", PublicKeyAccount.getAddress(adminPublicKey)); json.put("admin", PublicKeyAccount.getAddress(adminPublicKey));
json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString()); json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString());
json.put("groupName", cancelGroupInviteTransactionData.getGroupName()); json.put("groupId", cancelGroupInviteTransactionData.getGroupId());
json.put("invitee", cancelGroupInviteTransactionData.getInvitee()); json.put("invitee", cancelGroupInviteTransactionData.getInvitee());
} catch (ClassCastException e) { } catch (ClassCastException e) {
throw new TransformationException(e); throw new TransformationException(e);

View File

@ -27,7 +27,8 @@ public class CreateGroupTransactionTransformer extends TransactionTransformer {
private static final int DESCRIPTION_SIZE_LENGTH = INT_LENGTH; private static final int DESCRIPTION_SIZE_LENGTH = INT_LENGTH;
private static final int IS_OPEN_LENGTH = BOOLEAN_LENGTH; private static final int IS_OPEN_LENGTH = BOOLEAN_LENGTH;
private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + CREATOR_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + IS_OPEN_LENGTH; private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + CREATOR_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH
+ IS_OPEN_LENGTH;
static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong(); long timestamp = byteBuffer.getLong();
@ -50,7 +51,7 @@ public class CreateGroupTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH]; byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature); byteBuffer.get(signature);
return new CreateGroupTransactionData(creatorPublicKey, owner, groupName, description, isOpen, fee, timestamp, reference, signature); return new CreateGroupTransactionData(creatorPublicKey, owner, groupName, description, isOpen, null, fee, timestamp, reference, signature);
} }
public static int getDataLength(TransactionData transactionData) throws TransformationException { public static int getDataLength(TransactionData transactionData) throws TransformationException {

View File

@ -22,12 +22,12 @@ public class GroupBanTransactionTransformer extends TransactionTransformer {
// Property lengths // Property lengths
private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH; private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH; private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int MEMBER_LENGTH = ADDRESS_LENGTH; private static final int MEMBER_LENGTH = ADDRESS_LENGTH;
private static final int REASON_SIZE_LENGTH = INT_LENGTH; private static final int REASON_SIZE_LENGTH = INT_LENGTH;
private static final int TTL_LENGTH = INT_LENGTH; private static final int TTL_LENGTH = INT_LENGTH;
private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + NAME_SIZE_LENGTH + MEMBER_LENGTH + REASON_SIZE_LENGTH + TTL_LENGTH; private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH + REASON_SIZE_LENGTH + TTL_LENGTH;
static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong(); long timestamp = byteBuffer.getLong();
@ -37,7 +37,7 @@ public class GroupBanTransactionTransformer extends TransactionTransformer {
byte[] adminPublicKey = Serialization.deserializePublicKey(byteBuffer); byte[] adminPublicKey = Serialization.deserializePublicKey(byteBuffer);
String groupName = Serialization.deserializeSizedString(byteBuffer, Group.MAX_NAME_SIZE); int groupId = byteBuffer.getInt();
String offender = Serialization.deserializeAddress(byteBuffer); String offender = Serialization.deserializeAddress(byteBuffer);
@ -50,14 +50,13 @@ public class GroupBanTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH]; byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature); byteBuffer.get(signature);
return new GroupBanTransactionData(adminPublicKey, groupName, offender, reason, timeToLive, fee, timestamp, reference, signature); return new GroupBanTransactionData(adminPublicKey, groupId, offender, reason, timeToLive, fee, timestamp, reference, signature);
} }
public static int getDataLength(TransactionData transactionData) throws TransformationException { public static int getDataLength(TransactionData transactionData) throws TransformationException {
GroupBanTransactionData groupBanTransactionData = (GroupBanTransactionData) transactionData; GroupBanTransactionData groupBanTransactionData = (GroupBanTransactionData) transactionData;
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(groupBanTransactionData.getGroupName()) int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(groupBanTransactionData.getReason());
+ Utf8.encodedLength(groupBanTransactionData.getReason());
return dataLength; return dataLength;
} }
@ -73,7 +72,7 @@ public class GroupBanTransactionTransformer extends TransactionTransformer {
bytes.write(groupBanTransactionData.getReference()); bytes.write(groupBanTransactionData.getReference());
bytes.write(groupBanTransactionData.getCreatorPublicKey()); bytes.write(groupBanTransactionData.getCreatorPublicKey());
Serialization.serializeSizedString(bytes, groupBanTransactionData.getGroupName()); bytes.write(Ints.toByteArray(groupBanTransactionData.getGroupId()));
Serialization.serializeAddress(bytes, groupBanTransactionData.getOffender()); Serialization.serializeAddress(bytes, groupBanTransactionData.getOffender());
Serialization.serializeSizedString(bytes, groupBanTransactionData.getReason()); Serialization.serializeSizedString(bytes, groupBanTransactionData.getReason());
bytes.write(Ints.toByteArray(groupBanTransactionData.getTimeToLive())); bytes.write(Ints.toByteArray(groupBanTransactionData.getTimeToLive()));
@ -101,7 +100,7 @@ public class GroupBanTransactionTransformer extends TransactionTransformer {
json.put("admin", PublicKeyAccount.getAddress(adminPublicKey)); json.put("admin", PublicKeyAccount.getAddress(adminPublicKey));
json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString()); json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString());
json.put("groupName", groupBanTransactionData.getGroupName()); json.put("groupId", groupBanTransactionData.getGroupId());
json.put("offender", groupBanTransactionData.getOffender()); json.put("offender", groupBanTransactionData.getOffender());
json.put("reason", groupBanTransactionData.getReason()); json.put("reason", groupBanTransactionData.getReason());
json.put("timeToLive", groupBanTransactionData.getTimeToLive()); json.put("timeToLive", groupBanTransactionData.getTimeToLive());

View File

@ -9,11 +9,9 @@ import org.json.simple.JSONObject;
import org.qora.account.PublicKeyAccount; import org.qora.account.PublicKeyAccount;
import org.qora.data.transaction.GroupInviteTransactionData; import org.qora.data.transaction.GroupInviteTransactionData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.group.Group;
import org.qora.transform.TransformationException; import org.qora.transform.TransformationException;
import org.qora.utils.Serialization; import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
import com.google.common.hash.HashCode; import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs; import com.google.common.primitives.Longs;
@ -22,11 +20,11 @@ public class GroupInviteTransactionTransformer extends TransactionTransformer {
// Property lengths // Property lengths
private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH; private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH; private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int INVITEE_LENGTH = ADDRESS_LENGTH; private static final int INVITEE_LENGTH = ADDRESS_LENGTH;
private static final int TTL_LENGTH = INT_LENGTH; private static final int TTL_LENGTH = INT_LENGTH;
private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + NAME_SIZE_LENGTH + INVITEE_LENGTH + TTL_LENGTH; private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + INVITEE_LENGTH + TTL_LENGTH;
static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong(); long timestamp = byteBuffer.getLong();
@ -36,7 +34,7 @@ public class GroupInviteTransactionTransformer extends TransactionTransformer {
byte[] adminPublicKey = Serialization.deserializePublicKey(byteBuffer); byte[] adminPublicKey = Serialization.deserializePublicKey(byteBuffer);
String groupName = Serialization.deserializeSizedString(byteBuffer, Group.MAX_NAME_SIZE); int groupId = byteBuffer.getInt();
String invitee = Serialization.deserializeAddress(byteBuffer); String invitee = Serialization.deserializeAddress(byteBuffer);
@ -47,15 +45,11 @@ public class GroupInviteTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH]; byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature); byteBuffer.get(signature);
return new GroupInviteTransactionData(adminPublicKey, groupName, invitee, timeToLive, fee, timestamp, reference, signature); return new GroupInviteTransactionData(adminPublicKey, groupId, invitee, timeToLive, fee, timestamp, reference, signature);
} }
public static int getDataLength(TransactionData transactionData) throws TransformationException { public static int getDataLength(TransactionData transactionData) throws TransformationException {
GroupInviteTransactionData groupInviteTransactionData = (GroupInviteTransactionData) transactionData; return TYPE_LENGTH + TYPELESS_LENGTH;
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(groupInviteTransactionData.getGroupName());
return dataLength;
} }
public static byte[] toBytes(TransactionData transactionData) throws TransformationException { public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@ -69,7 +63,7 @@ public class GroupInviteTransactionTransformer extends TransactionTransformer {
bytes.write(groupInviteTransactionData.getReference()); bytes.write(groupInviteTransactionData.getReference());
bytes.write(groupInviteTransactionData.getCreatorPublicKey()); bytes.write(groupInviteTransactionData.getCreatorPublicKey());
Serialization.serializeSizedString(bytes, groupInviteTransactionData.getGroupName()); bytes.write(Ints.toByteArray(groupInviteTransactionData.getGroupId()));
Serialization.serializeAddress(bytes, groupInviteTransactionData.getInvitee()); Serialization.serializeAddress(bytes, groupInviteTransactionData.getInvitee());
bytes.write(Ints.toByteArray(groupInviteTransactionData.getTimeToLive())); bytes.write(Ints.toByteArray(groupInviteTransactionData.getTimeToLive()));
@ -96,7 +90,7 @@ public class GroupInviteTransactionTransformer extends TransactionTransformer {
json.put("admin", PublicKeyAccount.getAddress(adminPublicKey)); json.put("admin", PublicKeyAccount.getAddress(adminPublicKey));
json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString()); json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString());
json.put("groupName", groupInviteTransactionData.getGroupName()); json.put("groupId", groupInviteTransactionData.getGroupId());
json.put("invitee", groupInviteTransactionData.getInvitee()); json.put("invitee", groupInviteTransactionData.getInvitee());
json.put("timeToLive", groupInviteTransactionData.getTimeToLive()); json.put("timeToLive", groupInviteTransactionData.getTimeToLive());
} catch (ClassCastException e) { } catch (ClassCastException e) {

View File

@ -22,11 +22,11 @@ public class GroupKickTransactionTransformer extends TransactionTransformer {
// Property lengths // Property lengths
private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH; private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH; private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int MEMBER_LENGTH = ADDRESS_LENGTH; private static final int MEMBER_LENGTH = ADDRESS_LENGTH;
private static final int REASON_SIZE_LENGTH = INT_LENGTH; private static final int REASON_SIZE_LENGTH = INT_LENGTH;
private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + NAME_SIZE_LENGTH + MEMBER_LENGTH + REASON_SIZE_LENGTH; private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH + REASON_SIZE_LENGTH;
static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong(); long timestamp = byteBuffer.getLong();
@ -36,7 +36,7 @@ public class GroupKickTransactionTransformer extends TransactionTransformer {
byte[] adminPublicKey = Serialization.deserializePublicKey(byteBuffer); byte[] adminPublicKey = Serialization.deserializePublicKey(byteBuffer);
String groupName = Serialization.deserializeSizedString(byteBuffer, Group.MAX_NAME_SIZE); int groupId = byteBuffer.getInt();
String member = Serialization.deserializeAddress(byteBuffer); String member = Serialization.deserializeAddress(byteBuffer);
@ -47,14 +47,13 @@ public class GroupKickTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH]; byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature); byteBuffer.get(signature);
return new GroupKickTransactionData(adminPublicKey, groupName, member, reason, fee, timestamp, reference, signature); return new GroupKickTransactionData(adminPublicKey, groupId, member, reason, fee, timestamp, reference, signature);
} }
public static int getDataLength(TransactionData transactionData) throws TransformationException { public static int getDataLength(TransactionData transactionData) throws TransformationException {
GroupKickTransactionData groupKickTransactionData = (GroupKickTransactionData) transactionData; GroupKickTransactionData groupKickTransactionData = (GroupKickTransactionData) transactionData;
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(groupKickTransactionData.getGroupName()) int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(groupKickTransactionData.getReason());
+ Utf8.encodedLength(groupKickTransactionData.getReason());
return dataLength; return dataLength;
} }
@ -70,7 +69,7 @@ public class GroupKickTransactionTransformer extends TransactionTransformer {
bytes.write(groupKickTransactionData.getReference()); bytes.write(groupKickTransactionData.getReference());
bytes.write(groupKickTransactionData.getCreatorPublicKey()); bytes.write(groupKickTransactionData.getCreatorPublicKey());
Serialization.serializeSizedString(bytes, groupKickTransactionData.getGroupName()); bytes.write(Ints.toByteArray(groupKickTransactionData.getGroupId()));
Serialization.serializeAddress(bytes, groupKickTransactionData.getMember()); Serialization.serializeAddress(bytes, groupKickTransactionData.getMember());
Serialization.serializeSizedString(bytes, groupKickTransactionData.getReason()); Serialization.serializeSizedString(bytes, groupKickTransactionData.getReason());
@ -97,7 +96,7 @@ public class GroupKickTransactionTransformer extends TransactionTransformer {
json.put("admin", PublicKeyAccount.getAddress(adminPublicKey)); json.put("admin", PublicKeyAccount.getAddress(adminPublicKey));
json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString()); json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString());
json.put("groupName", groupKickTransactionData.getGroupName()); json.put("groupId", groupKickTransactionData.getGroupId());
json.put("member", groupKickTransactionData.getMember()); json.put("member", groupKickTransactionData.getMember());
json.put("reason", groupKickTransactionData.getReason()); json.put("reason", groupKickTransactionData.getReason());
} catch (ClassCastException e) { } catch (ClassCastException e) {

View File

@ -9,11 +9,9 @@ import org.json.simple.JSONObject;
import org.qora.account.PublicKeyAccount; import org.qora.account.PublicKeyAccount;
import org.qora.data.transaction.JoinGroupTransactionData; import org.qora.data.transaction.JoinGroupTransactionData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.group.Group;
import org.qora.transform.TransformationException; import org.qora.transform.TransformationException;
import org.qora.utils.Serialization; import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
import com.google.common.hash.HashCode; import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs; import com.google.common.primitives.Longs;
@ -22,9 +20,9 @@ public class JoinGroupTransactionTransformer extends TransactionTransformer {
// Property lengths // Property lengths
private static final int JOINER_LENGTH = PUBLIC_KEY_LENGTH; private static final int JOINER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH; private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + JOINER_LENGTH + NAME_SIZE_LENGTH; private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + JOINER_LENGTH + GROUPID_LENGTH;
static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong(); long timestamp = byteBuffer.getLong();
@ -34,22 +32,18 @@ public class JoinGroupTransactionTransformer extends TransactionTransformer {
byte[] joinerPublicKey = Serialization.deserializePublicKey(byteBuffer); byte[] joinerPublicKey = Serialization.deserializePublicKey(byteBuffer);
String groupName = Serialization.deserializeSizedString(byteBuffer, Group.MAX_NAME_SIZE); int groupId = byteBuffer.getInt();
BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer); BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer);
byte[] signature = new byte[SIGNATURE_LENGTH]; byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature); byteBuffer.get(signature);
return new JoinGroupTransactionData(joinerPublicKey, groupName, fee, timestamp, reference, signature); return new JoinGroupTransactionData(joinerPublicKey, groupId, fee, timestamp, reference, signature);
} }
public static int getDataLength(TransactionData transactionData) throws TransformationException { public static int getDataLength(TransactionData transactionData) throws TransformationException {
JoinGroupTransactionData joinGroupTransactionData = (JoinGroupTransactionData) transactionData; return TYPE_LENGTH + TYPELESS_LENGTH;
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(joinGroupTransactionData.getGroupName());
return dataLength;
} }
public static byte[] toBytes(TransactionData transactionData) throws TransformationException { public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@ -63,7 +57,7 @@ public class JoinGroupTransactionTransformer extends TransactionTransformer {
bytes.write(joinGroupTransactionData.getReference()); bytes.write(joinGroupTransactionData.getReference());
bytes.write(joinGroupTransactionData.getCreatorPublicKey()); bytes.write(joinGroupTransactionData.getCreatorPublicKey());
Serialization.serializeSizedString(bytes, joinGroupTransactionData.getGroupName()); bytes.write(Ints.toByteArray(joinGroupTransactionData.getGroupId()));
Serialization.serializeBigDecimal(bytes, joinGroupTransactionData.getFee()); Serialization.serializeBigDecimal(bytes, joinGroupTransactionData.getFee());
@ -88,7 +82,7 @@ public class JoinGroupTransactionTransformer extends TransactionTransformer {
json.put("joiner", PublicKeyAccount.getAddress(joinerPublicKey)); json.put("joiner", PublicKeyAccount.getAddress(joinerPublicKey));
json.put("joinerPublicKey", HashCode.fromBytes(joinerPublicKey).toString()); json.put("joinerPublicKey", HashCode.fromBytes(joinerPublicKey).toString());
json.put("groupName", joinGroupTransactionData.getGroupName()); json.put("groupId", joinGroupTransactionData.getGroupId());
} catch (ClassCastException e) { } catch (ClassCastException e) {
throw new TransformationException(e); throw new TransformationException(e);
} }

View File

@ -9,11 +9,9 @@ import org.json.simple.JSONObject;
import org.qora.account.PublicKeyAccount; import org.qora.account.PublicKeyAccount;
import org.qora.data.transaction.LeaveGroupTransactionData; import org.qora.data.transaction.LeaveGroupTransactionData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.group.Group;
import org.qora.transform.TransformationException; import org.qora.transform.TransformationException;
import org.qora.utils.Serialization; import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
import com.google.common.hash.HashCode; import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs; import com.google.common.primitives.Longs;
@ -22,9 +20,9 @@ public class LeaveGroupTransactionTransformer extends TransactionTransformer {
// Property lengths // Property lengths
private static final int JOINER_LENGTH = PUBLIC_KEY_LENGTH; private static final int JOINER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH; private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + JOINER_LENGTH + NAME_SIZE_LENGTH; private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + JOINER_LENGTH + GROUPID_LENGTH;
static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong(); long timestamp = byteBuffer.getLong();
@ -34,22 +32,18 @@ public class LeaveGroupTransactionTransformer extends TransactionTransformer {
byte[] leaverPublicKey = Serialization.deserializePublicKey(byteBuffer); byte[] leaverPublicKey = Serialization.deserializePublicKey(byteBuffer);
String groupName = Serialization.deserializeSizedString(byteBuffer, Group.MAX_NAME_SIZE); int groupId = byteBuffer.getInt();
BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer); BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer);
byte[] signature = new byte[SIGNATURE_LENGTH]; byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature); byteBuffer.get(signature);
return new LeaveGroupTransactionData(leaverPublicKey, groupName, fee, timestamp, reference, signature); return new LeaveGroupTransactionData(leaverPublicKey, groupId, fee, timestamp, reference, signature);
} }
public static int getDataLength(TransactionData transactionData) throws TransformationException { public static int getDataLength(TransactionData transactionData) throws TransformationException {
LeaveGroupTransactionData leaveGroupTransactionData = (LeaveGroupTransactionData) transactionData; return TYPE_LENGTH + TYPELESS_LENGTH;
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(leaveGroupTransactionData.getGroupName());
return dataLength;
} }
public static byte[] toBytes(TransactionData transactionData) throws TransformationException { public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@ -63,7 +57,7 @@ public class LeaveGroupTransactionTransformer extends TransactionTransformer {
bytes.write(leaveGroupTransactionData.getReference()); bytes.write(leaveGroupTransactionData.getReference());
bytes.write(leaveGroupTransactionData.getCreatorPublicKey()); bytes.write(leaveGroupTransactionData.getCreatorPublicKey());
Serialization.serializeSizedString(bytes, leaveGroupTransactionData.getGroupName()); bytes.write(Ints.toByteArray(leaveGroupTransactionData.getGroupId()));
Serialization.serializeBigDecimal(bytes, leaveGroupTransactionData.getFee()); Serialization.serializeBigDecimal(bytes, leaveGroupTransactionData.getFee());
@ -88,7 +82,7 @@ public class LeaveGroupTransactionTransformer extends TransactionTransformer {
json.put("leaver", PublicKeyAccount.getAddress(leaverPublicKey)); json.put("leaver", PublicKeyAccount.getAddress(leaverPublicKey));
json.put("leaverPublicKey", HashCode.fromBytes(leaverPublicKey).toString()); json.put("leaverPublicKey", HashCode.fromBytes(leaverPublicKey).toString());
json.put("groupName", leaveGroupTransactionData.getGroupName()); json.put("groupId", leaveGroupTransactionData.getGroupId());
} catch (ClassCastException e) { } catch (ClassCastException e) {
throw new TransformationException(e); throw new TransformationException(e);
} }

View File

@ -9,11 +9,9 @@ import org.json.simple.JSONObject;
import org.qora.account.PublicKeyAccount; import org.qora.account.PublicKeyAccount;
import org.qora.data.transaction.RemoveGroupAdminTransactionData; import org.qora.data.transaction.RemoveGroupAdminTransactionData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.group.Group;
import org.qora.transform.TransformationException; import org.qora.transform.TransformationException;
import org.qora.utils.Serialization; import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
import com.google.common.hash.HashCode; import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs; import com.google.common.primitives.Longs;
@ -22,10 +20,10 @@ public class RemoveGroupAdminTransactionTransformer extends TransactionTransform
// Property lengths // Property lengths
private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH; private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH; private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int MEMBER_LENGTH = ADDRESS_LENGTH; private static final int MEMBER_LENGTH = ADDRESS_LENGTH;
private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + MEMBER_LENGTH; private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH;
static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong(); long timestamp = byteBuffer.getLong();
@ -35,7 +33,7 @@ public class RemoveGroupAdminTransactionTransformer extends TransactionTransform
byte[] ownerPublicKey = Serialization.deserializePublicKey(byteBuffer); byte[] ownerPublicKey = Serialization.deserializePublicKey(byteBuffer);
String groupName = Serialization.deserializeSizedString(byteBuffer, Group.MAX_NAME_SIZE); int groupId = byteBuffer.getInt();
String admin = Serialization.deserializeAddress(byteBuffer); String admin = Serialization.deserializeAddress(byteBuffer);
@ -44,15 +42,11 @@ public class RemoveGroupAdminTransactionTransformer extends TransactionTransform
byte[] signature = new byte[SIGNATURE_LENGTH]; byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature); byteBuffer.get(signature);
return new RemoveGroupAdminTransactionData(ownerPublicKey, groupName, admin, fee, timestamp, reference, signature); return new RemoveGroupAdminTransactionData(ownerPublicKey, groupId, admin, fee, timestamp, reference, signature);
} }
public static int getDataLength(TransactionData transactionData) throws TransformationException { public static int getDataLength(TransactionData transactionData) throws TransformationException {
RemoveGroupAdminTransactionData removeGroupAdminTransactionData = (RemoveGroupAdminTransactionData) transactionData; return TYPE_LENGTH + TYPELESS_LENGTH;
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(removeGroupAdminTransactionData.getGroupName());
return dataLength;
} }
public static byte[] toBytes(TransactionData transactionData) throws TransformationException { public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@ -66,7 +60,7 @@ public class RemoveGroupAdminTransactionTransformer extends TransactionTransform
bytes.write(removeGroupAdminTransactionData.getReference()); bytes.write(removeGroupAdminTransactionData.getReference());
bytes.write(removeGroupAdminTransactionData.getCreatorPublicKey()); bytes.write(removeGroupAdminTransactionData.getCreatorPublicKey());
Serialization.serializeSizedString(bytes, removeGroupAdminTransactionData.getGroupName()); bytes.write(Ints.toByteArray(removeGroupAdminTransactionData.getGroupId()));
Serialization.serializeAddress(bytes, removeGroupAdminTransactionData.getAdmin()); Serialization.serializeAddress(bytes, removeGroupAdminTransactionData.getAdmin());
Serialization.serializeBigDecimal(bytes, removeGroupAdminTransactionData.getFee()); Serialization.serializeBigDecimal(bytes, removeGroupAdminTransactionData.getFee());
@ -92,7 +86,7 @@ public class RemoveGroupAdminTransactionTransformer extends TransactionTransform
json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey)); json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey));
json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString()); json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString());
json.put("groupName", removeGroupAdminTransactionData.getGroupName()); json.put("groupId", removeGroupAdminTransactionData.getGroupId());
json.put("admin", removeGroupAdminTransactionData.getAdmin()); json.put("admin", removeGroupAdminTransactionData.getAdmin());
} catch (ClassCastException e) { } catch (ClassCastException e) {
throw new TransformationException(e); throw new TransformationException(e);

View File

@ -109,8 +109,8 @@ public class TransactionTransformer extends Transformer {
case GROUP_BAN: case GROUP_BAN:
return GroupBanTransactionTransformer.fromByteBuffer(byteBuffer); return GroupBanTransactionTransformer.fromByteBuffer(byteBuffer);
case GROUP_UNBAN: case CANCEL_GROUP_BAN:
return GroupUnbanTransactionTransformer.fromByteBuffer(byteBuffer); return CancelGroupBanTransactionTransformer.fromByteBuffer(byteBuffer);
case GROUP_KICK: case GROUP_KICK:
return GroupKickTransactionTransformer.fromByteBuffer(byteBuffer); return GroupKickTransactionTransformer.fromByteBuffer(byteBuffer);
@ -203,8 +203,8 @@ public class TransactionTransformer extends Transformer {
case GROUP_BAN: case GROUP_BAN:
return GroupBanTransactionTransformer.getDataLength(transactionData); return GroupBanTransactionTransformer.getDataLength(transactionData);
case GROUP_UNBAN: case CANCEL_GROUP_BAN:
return GroupUnbanTransactionTransformer.getDataLength(transactionData); return CancelGroupBanTransactionTransformer.getDataLength(transactionData);
case GROUP_KICK: case GROUP_KICK:
return GroupKickTransactionTransformer.getDataLength(transactionData); return GroupKickTransactionTransformer.getDataLength(transactionData);
@ -294,8 +294,8 @@ public class TransactionTransformer extends Transformer {
case GROUP_BAN: case GROUP_BAN:
return GroupBanTransactionTransformer.toBytes(transactionData); return GroupBanTransactionTransformer.toBytes(transactionData);
case GROUP_UNBAN: case CANCEL_GROUP_BAN:
return GroupUnbanTransactionTransformer.toBytes(transactionData); return CancelGroupBanTransactionTransformer.toBytes(transactionData);
case GROUP_KICK: case GROUP_KICK:
return GroupKickTransactionTransformer.toBytes(transactionData); return GroupKickTransactionTransformer.toBytes(transactionData);
@ -394,8 +394,8 @@ public class TransactionTransformer extends Transformer {
case GROUP_BAN: case GROUP_BAN:
return GroupBanTransactionTransformer.toBytesForSigningImpl(transactionData); return GroupBanTransactionTransformer.toBytesForSigningImpl(transactionData);
case GROUP_UNBAN: case CANCEL_GROUP_BAN:
return GroupUnbanTransactionTransformer.toBytesForSigningImpl(transactionData); return CancelGroupBanTransactionTransformer.toBytesForSigningImpl(transactionData);
case GROUP_KICK: case GROUP_KICK:
return GroupKickTransactionTransformer.toBytesForSigningImpl(transactionData); return GroupKickTransactionTransformer.toBytesForSigningImpl(transactionData);
@ -506,8 +506,8 @@ public class TransactionTransformer extends Transformer {
case GROUP_BAN: case GROUP_BAN:
return GroupBanTransactionTransformer.toJSON(transactionData); return GroupBanTransactionTransformer.toJSON(transactionData);
case GROUP_UNBAN: case CANCEL_GROUP_BAN:
return GroupUnbanTransactionTransformer.toJSON(transactionData); return CancelGroupBanTransactionTransformer.toJSON(transactionData);
case GROUP_KICK: case GROUP_KICK:
return GroupKickTransactionTransformer.toJSON(transactionData); return GroupKickTransactionTransformer.toJSON(transactionData);

View File

@ -22,12 +22,13 @@ public class UpdateGroupTransactionTransformer extends TransactionTransformer {
// Property lengths // Property lengths
private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH; private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int NEW_OWNER_LENGTH = ADDRESS_LENGTH; private static final int NEW_OWNER_LENGTH = ADDRESS_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
private static final int NEW_DESCRIPTION_SIZE_LENGTH = INT_LENGTH; private static final int NEW_DESCRIPTION_SIZE_LENGTH = INT_LENGTH;
private static final int NEW_IS_OPEN_LENGTH = BOOLEAN_LENGTH; private static final int NEW_IS_OPEN_LENGTH = BOOLEAN_LENGTH;
private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + NEW_OWNER_LENGTH + NAME_SIZE_LENGTH + NEW_DESCRIPTION_SIZE_LENGTH + NEW_IS_OPEN_LENGTH; private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + GROUPID_LENGTH + NEW_OWNER_LENGTH + NEW_DESCRIPTION_SIZE_LENGTH
+ NEW_IS_OPEN_LENGTH;
static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong(); long timestamp = byteBuffer.getLong();
@ -37,7 +38,7 @@ public class UpdateGroupTransactionTransformer extends TransactionTransformer {
byte[] ownerPublicKey = Serialization.deserializePublicKey(byteBuffer); byte[] ownerPublicKey = Serialization.deserializePublicKey(byteBuffer);
String groupName = Serialization.deserializeSizedString(byteBuffer, Group.MAX_NAME_SIZE); int groupId = byteBuffer.getInt();
String newOwner = Serialization.deserializeAddress(byteBuffer); String newOwner = Serialization.deserializeAddress(byteBuffer);
@ -50,14 +51,13 @@ public class UpdateGroupTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH]; byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature); byteBuffer.get(signature);
return new UpdateGroupTransactionData(ownerPublicKey, groupName, newOwner, newDescription, newIsOpen, fee, timestamp, reference, signature); return new UpdateGroupTransactionData(ownerPublicKey, groupId, newOwner, newDescription, newIsOpen, fee, timestamp, reference, signature);
} }
public static int getDataLength(TransactionData transactionData) throws TransformationException { public static int getDataLength(TransactionData transactionData) throws TransformationException {
UpdateGroupTransactionData updateGroupTransactionData = (UpdateGroupTransactionData) transactionData; UpdateGroupTransactionData updateGroupTransactionData = (UpdateGroupTransactionData) transactionData;
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(updateGroupTransactionData.getGroupName()) int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(updateGroupTransactionData.getNewDescription());
+ Utf8.encodedLength(updateGroupTransactionData.getNewDescription());
return dataLength; return dataLength;
} }
@ -73,7 +73,7 @@ public class UpdateGroupTransactionTransformer extends TransactionTransformer {
bytes.write(updateGroupTransactionData.getReference()); bytes.write(updateGroupTransactionData.getReference());
bytes.write(updateGroupTransactionData.getCreatorPublicKey()); bytes.write(updateGroupTransactionData.getCreatorPublicKey());
Serialization.serializeSizedString(bytes, updateGroupTransactionData.getGroupName()); bytes.write(Ints.toByteArray(updateGroupTransactionData.getGroupId()));
Serialization.serializeAddress(bytes, updateGroupTransactionData.getNewOwner()); Serialization.serializeAddress(bytes, updateGroupTransactionData.getNewOwner());
Serialization.serializeSizedString(bytes, updateGroupTransactionData.getNewDescription()); Serialization.serializeSizedString(bytes, updateGroupTransactionData.getNewDescription());
@ -103,7 +103,7 @@ public class UpdateGroupTransactionTransformer extends TransactionTransformer {
json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey)); json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey));
json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString()); json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString());
json.put("groupName", updateGroupTransactionData.getGroupName()); json.put("groupId", updateGroupTransactionData.getGroupId());
json.put("newOwner", updateGroupTransactionData.getNewOwner()); json.put("newOwner", updateGroupTransactionData.getNewOwner());
json.put("newDescription", updateGroupTransactionData.getNewDescription()); json.put("newDescription", updateGroupTransactionData.getNewDescription());
json.put("newIsOpen", updateGroupTransactionData.getNewIsOpen()); json.put("newIsOpen", updateGroupTransactionData.getNewIsOpen());