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.account.AccountData;
|
||||||
import org.qortal.data.block.BlockData;
|
import org.qortal.data.block.BlockData;
|
||||||
import org.qortal.data.block.BlockSummaryData;
|
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.data.transaction.TransactionData;
|
||||||
import org.qortal.repository.BlockArchiveReader;
|
import org.qortal.repository.BlockArchiveReader;
|
||||||
import org.qortal.repository.DataException;
|
import org.qortal.repository.DataException;
|
||||||
@ -27,6 +29,7 @@ import org.qortal.repository.RepositoryManager;
|
|||||||
import org.qortal.transform.TransformationException;
|
import org.qortal.transform.TransformationException;
|
||||||
import org.qortal.transform.block.BlockTransformer;
|
import org.qortal.transform.block.BlockTransformer;
|
||||||
import org.qortal.utils.Base58;
|
import org.qortal.utils.Base58;
|
||||||
|
import org.qortal.utils.Blocks;
|
||||||
import org.qortal.utils.Triple;
|
import org.qortal.utils.Triple;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
@ -45,6 +48,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@Path("/blocks")
|
@Path("/blocks")
|
||||||
@Tag(name = "Blocks")
|
@Tag(name = "Blocks")
|
||||||
@ -889,4 +893,50 @@ public class BlocksResource {
|
|||||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
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