diff --git a/src/main/java/org/qortal/api/model/BlockInfo.java b/src/main/java/org/qortal/api/model/BlockInfo.java deleted file mode 100644 index 5d288e7f..00000000 --- a/src/main/java/org/qortal/api/model/BlockInfo.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.qortal.api.model; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; - -import org.qortal.data.account.RewardShareData; -import org.qortal.data.block.BlockData; -import org.qortal.repository.DataException; -import org.qortal.repository.Repository; -import org.qortal.repository.RepositoryManager; - -@XmlAccessorType(XmlAccessType.FIELD) -public class BlockInfo { - - private byte[] signature; - private int height; - private long timestamp; - private int transactionCount; - private String minterAddress; - - protected BlockInfo() { - /* For JAXB */ - } - - public BlockInfo(byte[] signature, int height, long timestamp, int transactionCount, String minterAddress) { - this.signature = signature; - this.height = height; - this.timestamp = timestamp; - this.transactionCount = transactionCount; - this.minterAddress = minterAddress; - } - - public BlockInfo(BlockData blockData) { - // Convert BlockData to BlockInfo, using additional data - this.minterAddress = "unknown?"; - - try (final Repository repository = RepositoryManager.getRepository()) { - RewardShareData rewardShareData = repository.getAccountRepository().getRewardShare(blockData.getMinterPublicKey()); - if (rewardShareData != null) - this.minterAddress = rewardShareData.getMintingAccount(); - } catch (DataException e) { - // We'll carry on with placeholder minterAddress then... - } - - this.signature = blockData.getSignature(); - this.height = blockData.getHeight(); - this.timestamp = blockData.getTimestamp(); - this.transactionCount = blockData.getTransactionCount(); - } - - public byte[] getSignature() { - return this.signature; - } - - public int getHeight() { - return this.height; - } - - public long getTimestamp() { - return this.timestamp; - } - - public int getTransactionCount() { - return this.transactionCount; - } - - public String getMinterAddress() { - return this.minterAddress; - } - -} diff --git a/src/main/java/org/qortal/api/resource/BlocksResource.java b/src/main/java/org/qortal/api/resource/BlocksResource.java index 3e1e2cfa..30cc477e 100644 --- a/src/main/java/org/qortal/api/resource/BlocksResource.java +++ b/src/main/java/org/qortal/api/resource/BlocksResource.java @@ -23,7 +23,6 @@ import javax.ws.rs.core.MediaType; import org.qortal.api.ApiError; import org.qortal.api.ApiErrors; import org.qortal.api.ApiExceptionFactory; -import org.qortal.api.model.BlockInfo; import org.qortal.api.model.BlockSignerSummary; import org.qortal.crypto.Crypto; import org.qortal.data.account.AccountData; @@ -492,7 +491,7 @@ public class BlocksResource { content = @Content( array = @ArraySchema( schema = @Schema( - implementation = BlockInfo.class + implementation = BlockSummaryData.class ) ) ) @@ -502,7 +501,7 @@ public class BlocksResource { @ApiErrors({ ApiError.REPOSITORY_ISSUE }) - public List getBlockRange( + public List getBlockSummaries( @QueryParam("start") Integer startHeight, @QueryParam("end") Integer endHeight, @Parameter(ref = "count") @QueryParam("count") Integer count) { @@ -515,7 +514,7 @@ public class BlocksResource { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); try (final Repository repository = RepositoryManager.getRepository()) { - return repository.getBlockRepository().getBlockInfos(startHeight, endHeight, count); + return repository.getBlockRepository().getBlockSummaries(startHeight, endHeight, count); } catch (DataException e) { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); } diff --git a/src/main/java/org/qortal/api/websocket/BlocksWebSocket.java b/src/main/java/org/qortal/api/websocket/BlocksWebSocket.java index 6698dd8b..20847b7b 100644 --- a/src/main/java/org/qortal/api/websocket/BlocksWebSocket.java +++ b/src/main/java/org/qortal/api/websocket/BlocksWebSocket.java @@ -13,9 +13,9 @@ import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; import org.qortal.api.ApiError; -import org.qortal.api.model.BlockInfo; import org.qortal.controller.Controller; import org.qortal.data.block.BlockData; +import org.qortal.data.block.BlockSummaryData; import org.qortal.event.Event; import org.qortal.event.EventBus; import org.qortal.event.Listener; @@ -41,10 +41,10 @@ public class BlocksWebSocket extends ApiWebSocket implements Listener { return; BlockData blockData = ((Controller.NewBlockEvent) event).getBlockData(); - BlockInfo blockInfo = new BlockInfo(blockData); + BlockSummaryData blockSummary = new BlockSummaryData(blockData); for (Session session : getSessions()) - sendBlockInfo(session, blockInfo); + sendBlockSummary(session, blockSummary); } @OnWebSocketConnect @@ -85,13 +85,13 @@ public class BlocksWebSocket extends ApiWebSocket implements Listener { return; } - List blockInfos = repository.getBlockRepository().getBlockInfos(height, null, 1); - if (blockInfos == null || blockInfos.isEmpty()) { + List blockSummaries = repository.getBlockRepository().getBlockSummaries(height, height); + if (blockSummaries == null || blockSummaries.isEmpty()) { sendError(session, ApiError.BLOCK_UNKNOWN); return; } - sendBlockInfo(session, blockInfos.get(0)); + sendBlockSummary(session, blockSummaries.get(0)); } catch (DataException e) { sendError(session, ApiError.REPOSITORY_ISSUE); } @@ -114,23 +114,23 @@ public class BlocksWebSocket extends ApiWebSocket implements Listener { } try (final Repository repository = RepositoryManager.getRepository()) { - List blockInfos = repository.getBlockRepository().getBlockInfos(height, null, 1); - if (blockInfos == null || blockInfos.isEmpty()) { + List blockSummaries = repository.getBlockRepository().getBlockSummaries(height, height); + if (blockSummaries == null || blockSummaries.isEmpty()) { sendError(session, ApiError.BLOCK_UNKNOWN); return; } - sendBlockInfo(session, blockInfos.get(0)); + sendBlockSummary(session, blockSummaries.get(0)); } catch (DataException e) { sendError(session, ApiError.REPOSITORY_ISSUE); } } - private void sendBlockInfo(Session session, BlockInfo blockInfo) { + private void sendBlockSummary(Session session, BlockSummaryData blockSummary) { StringWriter stringWriter = new StringWriter(); try { - marshall(stringWriter, blockInfo); + marshall(stringWriter, blockSummary); session.getRemote().sendStringByFuture(stringWriter.toString()); } catch (IOException | WebSocketException e) { diff --git a/src/main/java/org/qortal/data/block/BlockSummaryData.java b/src/main/java/org/qortal/data/block/BlockSummaryData.java index 3d789dd6..a0c39f75 100644 --- a/src/main/java/org/qortal/data/block/BlockSummaryData.java +++ b/src/main/java/org/qortal/data/block/BlockSummaryData.java @@ -3,8 +3,6 @@ package org.qortal.data.block; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; -import org.qortal.transform.block.BlockTransformer; - @XmlAccessorType(XmlAccessType.FIELD) public class BlockSummaryData { @@ -14,6 +12,10 @@ public class BlockSummaryData { private byte[] minterPublicKey; private int onlineAccountsCount; + // Optional, set during construction + private Long timestamp; + private Integer transactionCount; + // Optional, set after construction private Integer minterLevel; @@ -29,17 +31,23 @@ public class BlockSummaryData { this.onlineAccountsCount = onlineAccountsCount; } + public BlockSummaryData(int height, byte[] signature, byte[] minterPublicKey, int onlineAccountsCount, long timestamp, int transactionCount) { + this.height = height; + this.signature = signature; + this.minterPublicKey = minterPublicKey; + this.onlineAccountsCount = onlineAccountsCount; + this.timestamp = timestamp; + this.transactionCount = transactionCount; + } + public BlockSummaryData(BlockData blockData) { this.height = blockData.getHeight(); this.signature = blockData.getSignature(); this.minterPublicKey = blockData.getMinterPublicKey(); + this.onlineAccountsCount = blockData.getOnlineAccountsCount(); - byte[] encodedOnlineAccounts = blockData.getEncodedOnlineAccounts(); - if (encodedOnlineAccounts != null) { - this.onlineAccountsCount = BlockTransformer.decodeOnlineAccounts(encodedOnlineAccounts).size(); - } else { - this.onlineAccountsCount = 0; - } + this.timestamp = blockData.getTimestamp(); + this.transactionCount = blockData.getTransactionCount(); } // Getters / setters @@ -60,6 +68,14 @@ public class BlockSummaryData { return this.onlineAccountsCount; } + public Long getTimestamp() { + return this.timestamp; + } + + public Integer getTransactionCount() { + return this.transactionCount; + } + public Integer getMinterLevel() { return this.minterLevel; } diff --git a/src/main/java/org/qortal/repository/BlockRepository.java b/src/main/java/org/qortal/repository/BlockRepository.java index 937607cf..78eba399 100644 --- a/src/main/java/org/qortal/repository/BlockRepository.java +++ b/src/main/java/org/qortal/repository/BlockRepository.java @@ -2,7 +2,6 @@ package org.qortal.repository; import java.util.List; -import org.qortal.api.model.BlockInfo; import org.qortal.api.model.BlockSignerSummary; import org.qortal.data.block.BlockData; import org.qortal.data.block.BlockSummaryData; @@ -139,9 +138,9 @@ public interface BlockRepository { public List getBlockSummaries(int firstBlockHeight, int lastBlockHeight) throws DataException; /** - * Returns block infos for the passed height range, for API use. + * Returns block summaries for the passed height range, for API use. */ - public List getBlockInfos(Integer startHeight, Integer endHeight, Integer count) throws DataException; + public List getBlockSummaries(Integer startHeight, Integer endHeight, Integer count) throws DataException; /** Returns height of first trimmable online accounts signatures. */ public int getOnlineAccountsSignaturesTrimHeight() throws DataException; diff --git a/src/main/java/org/qortal/repository/hsqldb/HSQLDBBlockRepository.java b/src/main/java/org/qortal/repository/hsqldb/HSQLDBBlockRepository.java index d9d6ed51..b486e6a0 100644 --- a/src/main/java/org/qortal/repository/hsqldb/HSQLDBBlockRepository.java +++ b/src/main/java/org/qortal/repository/hsqldb/HSQLDBBlockRepository.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.qortal.api.model.BlockInfo; import org.qortal.api.model.BlockSignerSummary; import org.qortal.data.block.BlockData; import org.qortal.data.block.BlockSummaryData; @@ -355,7 +354,8 @@ public class HSQLDBBlockRepository implements BlockRepository { @Override public List getBlockSummaries(int firstBlockHeight, int lastBlockHeight) throws DataException { - String sql = "SELECT signature, height, minter, online_accounts_count FROM Blocks WHERE height BETWEEN ? AND ?"; + String sql = "SELECT signature, height, minter, online_accounts_count, minted_when, transaction_count " + + "FROM Blocks WHERE height BETWEEN ? AND ?"; List blockSummaries = new ArrayList<>(); @@ -368,8 +368,11 @@ public class HSQLDBBlockRepository implements BlockRepository { int height = resultSet.getInt(2); byte[] minterPublicKey = resultSet.getBytes(3); int onlineAccountsCount = resultSet.getInt(4); + long timestamp = resultSet.getLong(5); + int transactionCount = resultSet.getInt(6); - BlockSummaryData blockSummary = new BlockSummaryData(height, signature, minterPublicKey, onlineAccountsCount); + BlockSummaryData blockSummary = new BlockSummaryData(height, signature, minterPublicKey, onlineAccountsCount, + timestamp, transactionCount); blockSummaries.add(blockSummary); } while (resultSet.next()); @@ -380,11 +383,11 @@ public class HSQLDBBlockRepository implements BlockRepository { } @Override - public List getBlockInfos(Integer startHeight, Integer endHeight, Integer count) throws DataException { + public List getBlockSummaries(Integer startHeight, Integer endHeight, Integer count) throws DataException { StringBuilder sql = new StringBuilder(512); List bindParams = new ArrayList<>(); - sql.append("SELECT signature, height, minted_when, transaction_count, RewardShares.minter "); + sql.append("SELECT signature, height, minter, online_accounts_count, minted_when, transaction_count "); /* * start end count result @@ -401,7 +404,6 @@ public class HSQLDBBlockRepository implements BlockRepository { if (startHeight != null && endHeight != null) { sql.append("FROM Blocks "); - sql.append("JOIN RewardShares ON RewardShares.reward_share_public_key = Blocks.minter "); sql.append("WHERE height BETWEEN ? AND ?"); bindParams.add(startHeight); bindParams.add(Integer.valueOf(endHeight - 1)); @@ -413,11 +415,9 @@ public class HSQLDBBlockRepository implements BlockRepository { if (endHeight == null) { sql.append("FROM (SELECT height FROM Blocks ORDER BY height DESC LIMIT 1) AS MaxHeights (max_height) "); sql.append("JOIN Blocks ON height BETWEEN (max_height - ? + 1) AND max_height "); - sql.append("JOIN RewardShares ON RewardShares.reward_share_public_key = Blocks.minter"); bindParams.add(count); } else { sql.append("FROM Blocks "); - sql.append("JOIN RewardShares ON RewardShares.reward_share_public_key = Blocks.minter "); sql.append("WHERE height BETWEEN ? AND ?"); bindParams.add(Integer.valueOf(endHeight - count)); bindParams.add(Integer.valueOf(endHeight - 1)); @@ -432,32 +432,33 @@ public class HSQLDBBlockRepository implements BlockRepository { count = 50; sql.append("FROM Blocks "); - sql.append("JOIN RewardShares ON RewardShares.reward_share_public_key = Blocks.minter "); sql.append("WHERE height BETWEEN ? AND ?"); bindParams.add(startHeight); bindParams.add(Integer.valueOf(startHeight + count - 1)); } - List blockInfos = new ArrayList<>(); + List blockSummaries = new ArrayList<>(); try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), bindParams.toArray())) { if (resultSet == null) - return blockInfos; + return blockSummaries; do { byte[] signature = resultSet.getBytes(1); int height = resultSet.getInt(2); - long timestamp = resultSet.getLong(3); - int transactionCount = resultSet.getInt(4); - String minterAddress = resultSet.getString(5); + byte[] minterPublicKey = resultSet.getBytes(3); + int onlineAccountsCount = resultSet.getInt(4); + long timestamp = resultSet.getLong(5); + int transactionCount = resultSet.getInt(6); - BlockInfo blockInfo = new BlockInfo(signature, height, timestamp, transactionCount, minterAddress); - blockInfos.add(blockInfo); + BlockSummaryData blockSummary = new BlockSummaryData(height, signature, minterPublicKey, onlineAccountsCount, + timestamp, transactionCount); + blockSummaries.add(blockSummary); } while (resultSet.next()); - return blockInfos; + return blockSummaries; } catch (SQLException e) { - throw new DataException("Unable to fetch height-ranged block infos from repository", e); + throw new DataException("Unable to fetch height-ranged block summaries from repository", e); } } diff --git a/src/test/java/org/qortal/test/api/BlockApiTests.java b/src/test/java/org/qortal/test/api/BlockApiTests.java index a664fa8b..5b8721af 100644 --- a/src/test/java/org/qortal/test/api/BlockApiTests.java +++ b/src/test/java/org/qortal/test/api/BlockApiTests.java @@ -90,11 +90,11 @@ public class BlockApiTests extends ApiCommon { for (Integer endHeight : testValues) for (Integer count : testValues) { if (startHeight != null && endHeight != null && count != null) { - assertApiError(ApiError.INVALID_CRITERIA, () -> this.blocksResource.getBlockRange(startHeight, endHeight, count)); + assertApiError(ApiError.INVALID_CRITERIA, () -> this.blocksResource.getBlockSummaries(startHeight, endHeight, count)); continue; } - assertNotNull(this.blocksResource.getBlockRange(startHeight, endHeight, count)); + assertNotNull(this.blocksResource.getBlockSummaries(startHeight, endHeight, count)); } }