diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 5397648d106..13ca5e31afa 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2771,37 +2771,7 @@ public BytesMessage getShieldTransactionHash(Transaction transaction) } public TransactionInfoList getTransactionInfoByBlockNum(long blockNum) { - TransactionInfoList.Builder transactionInfoList = TransactionInfoList.newBuilder(); - - try { - TransactionRetCapsule result = dbManager.getTransactionRetStore() - .getTransactionInfoByBlockNum(ByteArray.fromLong(blockNum)); - - if (!Objects.isNull(result) && !Objects.isNull(result.getInstance())) { - result.getInstance().getTransactioninfoList().forEach( - transactionInfo -> transactionInfoList.addTransactionInfo(transactionInfo) - ); - } else { - Block block = chainBaseManager.getBlockByNum(blockNum).getInstance(); - - if (block != null) { - List listTransaction = block.getTransactionsList(); - for (Transaction transaction : listTransaction) { - TransactionInfoCapsule transactionInfoCapsule = dbManager.getTransactionHistoryStore() - .get(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); - - if (transactionInfoCapsule != null) { - transactionInfoList.addTransactionInfo(transactionInfoCapsule.getInstance()); - } - } - } - } - } catch (BadItemException | ItemNotFoundException e) { - logger.warn(e.getMessage()); - } - - return transactionInfoList.build(); + return dbManager.getTransactionInfoByBlockNum(blockNum); } public NodeList listNodes() { diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 17e2687e98b..ef14619bf02 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -163,6 +163,7 @@ import org.tron.core.store.WitnessScheduleStore; import org.tron.core.store.WitnessStore; import org.tron.core.utils.TransactionRegister; +import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Permission; import org.tron.protos.Protocol.Transaction; @@ -2488,6 +2489,40 @@ private boolean isBlockWaitingLock() { return blockWaitLock.get() > NO_BLOCK_WAITING_LOCK; } + public TransactionInfoList getTransactionInfoByBlockNum(long blockNum) { + TransactionInfoList.Builder transactionInfoList = TransactionInfoList.newBuilder(); + + try { + TransactionRetCapsule result = getTransactionRetStore() + .getTransactionInfoByBlockNum(ByteArray.fromLong(blockNum)); + + if (!Objects.isNull(result) && !Objects.isNull(result.getInstance())) { + result.getInstance().getTransactioninfoList().forEach( + transactionInfo -> transactionInfoList.addTransactionInfo(transactionInfo) + ); + } else { + Protocol.Block block = chainBaseManager.getBlockByNum(blockNum).getInstance(); + + if (block != null) { + List listTransaction = block.getTransactionsList(); + for (Transaction transaction : listTransaction) { + TransactionInfoCapsule transactionInfoCapsule = getTransactionHistoryStore() + .get(Sha256Hash.hash(CommonParameter.getInstance() + .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); + + if (transactionInfoCapsule != null) { + transactionInfoList.addTransactionInfo(transactionInfoCapsule.getInstance()); + } + } + } + } + } catch (BadItemException | ItemNotFoundException e) { + logger.warn(e.getMessage()); + } + + return transactionInfoList.build(); + } + public void close() { stopRePushThread(); stopRePushTriggerThread(); diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java b/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java index bf668a3e0b6..28f66de5ac9 100644 --- a/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java @@ -57,10 +57,16 @@ public BlockEvent getBlockEvent(long blockNum) throws Exception { BlockCapsule block = manager.getChainBaseManager().getBlockByNum(blockNum); block.getTransactions().forEach(t -> t.setBlockNum(block.getNum())); long solidNum = manager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); + long headNum = manager.getHeadBlockNum(); + // solve the single SR concurrency problem + if (solidNum >= headNum && headNum > 0) { + solidNum = headNum - 1; + } BlockEvent blockEvent = new BlockEvent(); blockEvent.setBlockId(block.getBlockId()); blockEvent.setParentId(block.getParentBlockId()); blockEvent.setSolidId(manager.getChainBaseManager().getBlockIdByNum(solidNum)); + if (instance.isBlockLogTriggerEnable()) { blockEvent.setBlockLogTriggerCapsule(getBlockLogTrigger(block, solidNum)); } @@ -88,18 +94,13 @@ public BlockEvent getBlockEvent(long blockNum) throws Exception { } public SmartContractTrigger getContractTrigger(BlockCapsule block, long solidNum) { - TransactionRetCapsule result; - try { - result = manager.getChainBaseManager().getTransactionRetStore() - .getTransactionInfoByBlockNum(ByteArray.fromLong(block.getNum())); - } catch (BadItemException e) { - throw new RuntimeException(e); - } + + GrpcAPI.TransactionInfoList list = manager.getTransactionInfoByBlockNum(block.getNum()); SmartContractTrigger contractTrigger = new SmartContractTrigger(); for (int i = 0; i < block.getTransactions().size(); i++) { Protocol.Transaction tx = block.getInstance().getTransactions(i); - Protocol.TransactionInfo txInfo = result.getInstance().getTransactioninfo(i); + Protocol.TransactionInfo txInfo = list.getTransactionInfo(i); List triggers = parseLogs(tx, txInfo); for (ContractTrigger trigger : triggers) { diff --git a/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java b/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java index 8f79ee47a3c..56d365972f6 100644 --- a/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java +++ b/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java @@ -54,7 +54,10 @@ private void syncEvent() { try { long tmp = instance.getStartSyncBlockNum(); long endNum = manager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); - while (tmp <= endNum) { + while (tmp < endNum) { + if (thread.isInterrupted()) { + throw new InterruptedException(); + } if (instance.isUseNativeQueue()) { Thread.sleep(20); } else if (instance.isBusy()) { @@ -67,7 +70,8 @@ private void syncEvent() { tmp++; endNum = manager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); } - initEventService(manager.getChainBaseManager().getBlockIdByNum(endNum)); + long startNum = endNum == 0 ? 0 : endNum - 1; + initEventService(manager.getChainBaseManager().getBlockIdByNum(startNum)); } catch (InterruptedException e1) { logger.warn("History event service interrupted."); Thread.currentThread().interrupt(); diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index d05334c5b94..7b387398cf6 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -33,6 +33,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import org.tron.api.GrpcAPI; import org.tron.common.application.TronApplicationContext; import org.tron.common.crypto.ECKey; import org.tron.common.runtime.RuntimeImpl; @@ -52,7 +53,10 @@ import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.BytesCapsule; import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.capsule.TransactionInfoCapsule; +import org.tron.core.capsule.TransactionRetCapsule; import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.Parameter; @@ -1233,6 +1237,45 @@ public void testExpiration() { } + @Test + public void testGetTransactionInfoByBlockNum() throws Exception { + + Transaction transaction = Protocol.Transaction.newBuilder() + .addSignature(ByteString.copyFrom(new byte[1])).build(); + TransactionCapsule transactionCapsule = new TransactionCapsule(transaction); + + Protocol.BlockHeader.raw raw = Protocol.BlockHeader.raw.newBuilder().setNumber(1000L).build(); + Protocol.BlockHeader header = Protocol.BlockHeader.newBuilder().setRawData(raw).build(); + Block block = Block.newBuilder().setBlockHeader(header).addTransactions(transaction).build(); + + Protocol.TransactionInfo info = Protocol.TransactionInfo.newBuilder() + .setBlockNumber(1000L).build(); + + BlockCapsule blockCapsule = new BlockCapsule(block); + byte[] blockId = new BlockCapsule(block).getBlockId().getBytes(); + dbManager.getBlockIndexStore().put(ByteArray.fromLong(1000L), new BytesCapsule(blockId)); + dbManager.getBlockStore().put(blockId, blockCapsule); + dbManager.getTransactionHistoryStore().put(transactionCapsule.getTransactionId().getBytes(), + new TransactionInfoCapsule(info)); + + GrpcAPI.TransactionInfoList transactionInfoList = dbManager.getTransactionInfoByBlockNum(1000L); + + Assert.assertEquals(1, transactionInfoList.getTransactionInfoCount()); + + Protocol.TransactionRet ret = Protocol.TransactionRet.newBuilder() + .addTransactioninfo(info) + .addTransactioninfo(info).build(); + + TransactionRetCapsule transactionRetCapsule = new TransactionRetCapsule(ret.toByteArray()); + + dbManager.getTransactionRetStore() + .put(ByteArray.fromLong(1000L), transactionRetCapsule); + + transactionInfoList = dbManager.getTransactionInfoByBlockNum(1000L); + + Assert.assertEquals(2, transactionInfoList.getTransactionInfoCount()); + } + @Test public void blockTrigger() { Manager manager = spy(new Manager());