From 3ac1ad6c0bf103df1a939845e84743cd1072e243 Mon Sep 17 00:00:00 2001 From: semux Date: Thu, 18 Jul 2019 13:54:58 +0100 Subject: [PATCH] DB: fix the transaction result index issue, close #221 --- .../java/org/semux/api/ApiHandlerImpl.java | 1 + src/main/java/org/semux/core/Block.java | 4 +- .../java/org/semux/core/BlockchainImpl.java | 62 ++++++++++++------- 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/semux/api/ApiHandlerImpl.java b/src/main/java/org/semux/api/ApiHandlerImpl.java index 09d0f6e91..376cea60b 100644 --- a/src/main/java/org/semux/api/ApiHandlerImpl.java +++ b/src/main/java/org/semux/api/ApiHandlerImpl.java @@ -79,6 +79,7 @@ public Response service(HttpMethod method, String path, Map para try { return (Response) route.invoke(params); } catch (Exception e) { + logger.warn("Internal error", e); return Response.status(INTERNAL_SERVER_ERROR).entity(HttpHandler.INTERNAL_SERVER_ERROR_RESPONSE).build(); } } diff --git a/src/main/java/org/semux/core/Block.java b/src/main/java/org/semux/core/Block.java index d867764f9..6dc31c08d 100644 --- a/src/main/java/org/semux/core/Block.java +++ b/src/main/java/org/semux/core/Block.java @@ -438,10 +438,10 @@ public Pair> getEncodedTransactionsAndIndices() { * @return */ public byte[] getEncodedResults() { - return getEncodedResultsAndIndex().getLeft(); + return getEncodedResultsAndIndices().getLeft(); } - public Pair> getEncodedResultsAndIndex() { + public Pair> getEncodedResultsAndIndices() { List indices = new ArrayList<>(); SimpleEncoder enc = new SimpleEncoder(); diff --git a/src/main/java/org/semux/core/BlockchainImpl.java b/src/main/java/org/semux/core/BlockchainImpl.java index 35052fe62..a8301e3b0 100644 --- a/src/main/java/org/semux/core/BlockchainImpl.java +++ b/src/main/java/org/semux/core/BlockchainImpl.java @@ -250,6 +250,34 @@ public boolean hasBlock(long number) { return blockDB.get(Bytes.merge(TYPE_BLOCK_HEADER_BY_NUMBER, Bytes.of(number))) != null; } + private static class TransactionIndex { + long blockNumber; + int transactionOffset; + int resultOffset; + + public TransactionIndex(long blockNumber, int transactionOffset, int resultOffset) { + this.blockNumber = blockNumber; + this.transactionOffset = transactionOffset; + this.resultOffset = resultOffset; + } + + public byte[] toBytes() { + SimpleEncoder enc = new SimpleEncoder(); + enc.writeLong(blockNumber); + enc.writeInt(transactionOffset); + enc.writeInt(resultOffset); + return enc.toBytes(); + } + + public static TransactionIndex fromBytes(byte[] bytes) { + SimpleDecoder dec = new SimpleDecoder(bytes); + long number = dec.readLong(); + int transactionOffset = dec.readInt(); + int resultOffset = dec.readInt(); + return new TransactionIndex(number, transactionOffset, resultOffset); + } + } + @Override public Transaction getTransaction(byte[] hash) { byte[] bytes = indexDB.get(Bytes.merge(TYPE_TRANSACTION_INDEX_BY_HASH, hash)); @@ -259,13 +287,10 @@ public Transaction getTransaction(byte[] hash) { return Transaction.fromBytes(bytes); } - SimpleDecoder dec = new SimpleDecoder(bytes); - long number = dec.readLong(); - int start = dec.readInt(); - dec.readInt(); - - byte[] transactions = blockDB.get(Bytes.merge(TYPE_BLOCK_TRANSACTIONS_BY_NUMBER, Bytes.of(number))); - dec = new SimpleDecoder(transactions, start); + TransactionIndex index = TransactionIndex.fromBytes(bytes); + byte[] transactions = blockDB + .get(Bytes.merge(TYPE_BLOCK_TRANSACTIONS_BY_NUMBER, Bytes.of(index.blockNumber))); + SimpleDecoder dec = new SimpleDecoder(transactions, index.transactionOffset); return Transaction.fromBytes(dec.readBytes()); } @@ -290,16 +315,12 @@ public TransactionResult getTransactionResult(byte[] hash) { if (bytes != null) { // coinbase transaction if (bytes.length > 64) { - return null; // no results for coinbase transaction + return new TransactionResult(); } - SimpleDecoder dec = new SimpleDecoder(bytes); - long number = dec.readLong(); - dec.readInt(); - int start = dec.readInt(); - - byte[] results = blockDB.get(Bytes.merge(TYPE_BLOCK_RESULTS_BY_NUMBER, Bytes.of(number))); - dec = new SimpleDecoder(results, start); + TransactionIndex index = TransactionIndex.fromBytes(bytes); + byte[] results = blockDB.get(Bytes.merge(TYPE_BLOCK_RESULTS_BY_NUMBER, Bytes.of(index.blockNumber))); + SimpleDecoder dec = new SimpleDecoder(results, index.resultOffset); return TransactionResult.fromBytes(dec.readBytes()); } @@ -343,18 +364,15 @@ public synchronized void addBlock(Block block) { // [2] update transaction indices List txs = block.getTransactions(); Pair> transactionIndices = block.getEncodedTransactionsAndIndices(); - Pair> resultIndices = block.getEncodedTransactionsAndIndices(); + Pair> resultIndices = block.getEncodedResultsAndIndices(); Amount reward = Block.getBlockReward(block, config); for (int i = 0; i < txs.size(); i++) { Transaction tx = txs.get(i); - SimpleEncoder enc = new SimpleEncoder(); - enc.writeLong(number); - enc.writeInt(transactionIndices.getRight().get(i)); - enc.writeInt(resultIndices.getRight().get(i)); - - indexDB.put(Bytes.merge(TYPE_TRANSACTION_INDEX_BY_HASH, tx.getHash()), enc.toBytes()); + TransactionIndex index = new TransactionIndex(number, transactionIndices.getRight().get(i), + resultIndices.getRight().get(i)); + indexDB.put(Bytes.merge(TYPE_TRANSACTION_INDEX_BY_HASH, tx.getHash()), index.toBytes()); // [3] update transaction_by_account index addTransactionToAccount(tx, tx.getFrom());