mirror of
https://github.com/Qortal/qortal.git
synced 2025-02-11 17:55:50 +00:00
access to decoded online accounts by block
This commit is contained in:
parent
2392b7b155
commit
d9a7648d36
@ -19,6 +19,8 @@ import org.qortal.crypto.Crypto;
|
||||
import org.qortal.data.account.AccountData;
|
||||
import org.qortal.data.block.BlockData;
|
||||
import org.qortal.data.block.BlockSummaryData;
|
||||
import org.qortal.data.block.DecodedOnlineAccountData;
|
||||
import org.qortal.data.network.OnlineAccountData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.repository.BlockArchiveReader;
|
||||
import org.qortal.repository.DataException;
|
||||
@ -27,6 +29,7 @@ import org.qortal.repository.RepositoryManager;
|
||||
import org.qortal.transform.TransformationException;
|
||||
import org.qortal.transform.block.BlockTransformer;
|
||||
import org.qortal.utils.Base58;
|
||||
import org.qortal.utils.Blocks;
|
||||
import org.qortal.utils.Triple;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -45,6 +48,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Path("/blocks")
|
||||
@Tag(name = "Blocks")
|
||||
@ -889,4 +893,50 @@ public class BlocksResource {
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/onlineaccounts/{height}")
|
||||
@Operation(
|
||||
summary = "Get online accounts for block",
|
||||
description = "Returns the online accounts who submitted signatures for this block",
|
||||
responses = {
|
||||
@ApiResponse(
|
||||
description = "online accounts",
|
||||
content = @Content(
|
||||
array = @ArraySchema(
|
||||
schema = @Schema(
|
||||
implementation = DecodedOnlineAccountData.class
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
@ApiErrors({
|
||||
ApiError.BLOCK_UNKNOWN, ApiError.REPOSITORY_ISSUE
|
||||
})
|
||||
public Set<DecodedOnlineAccountData> getOnlineAccounts(@PathParam("height") int height) {
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
|
||||
// get block from database
|
||||
BlockData blockData = repository.getBlockRepository().fromHeight(height);
|
||||
|
||||
// if block data is not in the database, then try the archive
|
||||
if (blockData == null) {
|
||||
blockData = repository.getBlockArchiveRepository().fromHeight(height);
|
||||
|
||||
// if the block is not in the database or the archive, then the block is unknown
|
||||
if( blockData == null ) {
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.BLOCK_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
Set<DecodedOnlineAccountData> onlineAccounts = Blocks.getDecodedOnlineAccountsForBlock(repository, blockData);
|
||||
|
||||
return onlineAccounts;
|
||||
} catch (DataException e) {
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package org.qortal.data.block;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import java.util.Objects;
|
||||
|
||||
// All properties to be converted to JSON via JAX-RS
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class DecodedOnlineAccountData {
|
||||
|
||||
private long onlineTimestamp;
|
||||
private String minter;
|
||||
private String recipient;
|
||||
private int sharePercent;
|
||||
private boolean minterGroupMember;
|
||||
private String name;
|
||||
private int level;
|
||||
|
||||
public DecodedOnlineAccountData() {
|
||||
}
|
||||
|
||||
public DecodedOnlineAccountData(long onlineTimestamp, String minter, String recipient, int sharePercent, boolean minterGroupMember, String name, int level) {
|
||||
this.onlineTimestamp = onlineTimestamp;
|
||||
this.minter = minter;
|
||||
this.recipient = recipient;
|
||||
this.sharePercent = sharePercent;
|
||||
this.minterGroupMember = minterGroupMember;
|
||||
this.name = name;
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public long getOnlineTimestamp() {
|
||||
return onlineTimestamp;
|
||||
}
|
||||
|
||||
public String getMinter() {
|
||||
return minter;
|
||||
}
|
||||
|
||||
public String getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
public int getSharePercent() {
|
||||
return sharePercent;
|
||||
}
|
||||
|
||||
public boolean isMinterGroupMember() {
|
||||
return minterGroupMember;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
DecodedOnlineAccountData that = (DecodedOnlineAccountData) o;
|
||||
return onlineTimestamp == that.onlineTimestamp && sharePercent == that.sharePercent && minterGroupMember == that.minterGroupMember && level == that.level && Objects.equals(minter, that.minter) && Objects.equals(recipient, that.recipient) && Objects.equals(name, that.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(onlineTimestamp, minter, recipient, sharePercent, minterGroupMember, name, level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DecodedOnlineAccountData{" +
|
||||
"onlineTimestamp=" + onlineTimestamp +
|
||||
", minter='" + minter + '\'' +
|
||||
", recipient='" + recipient + '\'' +
|
||||
", sharePercent=" + sharePercent +
|
||||
", minterGroupMember=" + minterGroupMember +
|
||||
", name='" + name + '\'' +
|
||||
", level=" + level +
|
||||
'}';
|
||||
}
|
||||
}
|
99
src/main/java/org/qortal/utils/Blocks.java
Normal file
99
src/main/java/org/qortal/utils/Blocks.java
Normal file
@ -0,0 +1,99 @@
|
||||
package org.qortal.utils;
|
||||
|
||||
import io.druid.extendedset.intset.ConciseSet;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.account.AddressLevelPairing;
|
||||
import org.qortal.data.account.RewardShareData;
|
||||
import org.qortal.data.block.BlockData;
|
||||
import org.qortal.data.block.DecodedOnlineAccountData;
|
||||
import org.qortal.data.group.GroupMemberData;
|
||||
import org.qortal.data.naming.NameData;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
import org.qortal.transform.block.BlockTransformer;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Class Blocks
|
||||
*
|
||||
* Methods for block related logic.
|
||||
*/
|
||||
public class Blocks {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(Blocks.class);
|
||||
|
||||
/**
|
||||
* Get Decode Online Accounts For Block
|
||||
*
|
||||
* @param repository the data repository
|
||||
* @param blockData the block data
|
||||
*
|
||||
* @return the online accounts set to the block
|
||||
*
|
||||
* @throws DataException
|
||||
*/
|
||||
public static Set<DecodedOnlineAccountData> getDecodedOnlineAccountsForBlock(Repository repository, BlockData blockData) throws DataException {
|
||||
try {
|
||||
// get all online account indices from block
|
||||
ConciseSet onlineAccountIndices = BlockTransformer.decodeOnlineAccounts(blockData.getEncodedOnlineAccounts());
|
||||
|
||||
// get online reward shares from the online accounts on the block
|
||||
List<RewardShareData> onlineRewardShares = repository.getAccountRepository().getRewardSharesByIndexes(onlineAccountIndices.toArray());
|
||||
|
||||
// online timestamp for block
|
||||
long onlineTimestamp = blockData.getOnlineAccountsTimestamp();
|
||||
Set<DecodedOnlineAccountData> onlineAccounts = new HashSet<>();
|
||||
|
||||
// all minting group member addresses
|
||||
List<String> mintingGroupAddresses
|
||||
= repository.getGroupRepository()
|
||||
.getGroupMembers(BlockChain.getInstance().getMintingGroupId()).stream()
|
||||
.map(GroupMemberData::getMember)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// all names, indexed by address
|
||||
Map<String, String> nameByAddress
|
||||
= repository.getNameRepository()
|
||||
.getAllNames().stream()
|
||||
.collect(Collectors.toMap(NameData::getOwner, NameData::getName));
|
||||
|
||||
// all accounts at level 1 or higher, indexed by address
|
||||
Map<String, Integer> levelByAddress
|
||||
= repository.getAccountRepository().getAddressLevelPairings(1).stream()
|
||||
.collect(Collectors.toMap(AddressLevelPairing::getAddress, AddressLevelPairing::getLevel));
|
||||
|
||||
// for each reward share where the minter is online,
|
||||
// construct the data object and add it to the return list
|
||||
for (RewardShareData onlineRewardShare : onlineRewardShares) {
|
||||
String minter = onlineRewardShare.getMinter();
|
||||
DecodedOnlineAccountData onlineAccountData
|
||||
= new DecodedOnlineAccountData(
|
||||
onlineTimestamp,
|
||||
minter,
|
||||
onlineRewardShare.getRecipient(),
|
||||
onlineRewardShare.getSharePercent(),
|
||||
mintingGroupAddresses.contains(minter),
|
||||
nameByAddress.get(minter),
|
||||
levelByAddress.get(minter)
|
||||
);
|
||||
|
||||
onlineAccounts.add(onlineAccountData);
|
||||
}
|
||||
|
||||
return onlineAccounts;
|
||||
} catch (DataException e) {
|
||||
throw e;
|
||||
} catch (Exception e ) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
|
||||
return new HashSet<>(0);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user