diff --git a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java
index 162ff130..ba330e04 100644
--- a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java
+++ b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java
@@ -243,6 +243,7 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer
messageHandle.commitBatch(realmName, batchId);
} catch (Exception e) {
// todo 需要处理应答码 404
+ LOGGER.error("Error occurred while processing ordered messages! --" + e.getMessage(), e);
messageHandle.rollbackBatch(realmName, batchId, TransactionState.CONSENSUS_ERROR.CODE);
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java
index a28a5fb5..bb57cd3c 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java
@@ -333,9 +333,9 @@ public class AccountSet implements Transactional, MerkleProvable {
if (!updated) {
return;
}
- String[] addresses = new String[latestAccountsCache.size()];
+ Bytes[] addresses = new Bytes[latestAccountsCache.size()];
latestAccountsCache.keySet().toArray(addresses);
- for (String address : addresses) {
+ for (Bytes address : addresses) {
VersioningAccount acc = latestAccountsCache.remove(address);
// cancel;
if (acc.isUpdated()) {
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java
index ced98b45..46c21655 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java
@@ -50,9 +50,11 @@ public interface LedgerEditor {
* 每一次事务性的账本写入操作在提交后,都会记录该事务相关的系统全局快照,以交易对象 {@link LedgerTransaction} 进行保存;
*
*
- * 注:方法不解析、不执行交易中的操作;
*
- * @param txRequest
+ *
+ * 注:方法不解析、不执行交易中的操作;
+ *
+ * @param txRequest 交易请求;
* @return
*/
LedgerTransactionContext newTransaction(TransactionRequest txRequest);
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java
index 33f589c5..a4feb79e 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java
@@ -24,7 +24,7 @@ public interface LedgerTransactionContext {
*
* @return
*/
- TransactionRequest getRequestTX();
+ TransactionRequest getTransactionRequest();
/**
* 提交对账本数据的修改,以指定的交易状态提交交易;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SettingContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SettingContext.java
new file mode 100644
index 00000000..516b2acf
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SettingContext.java
@@ -0,0 +1,51 @@
+package com.jd.blockchain.ledger.core;
+
+public class SettingContext {
+
+ private static final TxSettingContext txSettings = new TxSettingContext();
+
+ private static final QueryingSettingContext queryingSettings = new QueryingSettingContext();
+
+ public static TxSettingContext txSettings() {
+ return txSettings;
+ }
+
+ public static QueryingSettingContext queryingSettings() {
+ return queryingSettings;
+ }
+
+ /**
+ * 与交易处理相关的设置;
+ * @author huanghaiquan
+ *
+ */
+ public static class TxSettingContext {
+
+ public boolean verifyLedger() {
+ return true;
+ }
+
+ public boolean verifySignature() {
+ return true;
+ }
+
+ }
+
+ /**
+ * 与账本查询相关的设置;
+ * @author huanghaiquan
+ *
+ */
+ public static class QueryingSettingContext {
+
+ /**
+ * 查询区块等具有 hash 标识符的对象时是否重新校验哈希;
+ * @return
+ */
+ public boolean verifyHash() {
+ return false;
+ }
+
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerBlockData.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerBlockData.java
index 24b20401..1e8865b7 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerBlockData.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerBlockData.java
@@ -33,7 +33,9 @@ public class LedgerBlockData implements LedgerBlock {
// private HashDigest contractPrivilegeHash;
private HashDigest transactionSetHash;
-
+
+ private long timestamp;
+
public LedgerBlockData() {
}
@@ -155,4 +157,14 @@ public class LedgerBlockData implements LedgerBlock {
this.ledgerHash = ledgerHash;
}
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+
+
}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java
index 7b9b4a9a..1fe559b7 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java
@@ -15,6 +15,7 @@ import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.ledger.core.LedgerTransactionContext;
+import com.jd.blockchain.ledger.core.SettingContext;
import com.jd.blockchain.ledger.core.TransactionSet;
import com.jd.blockchain.ledger.core.UserAccountSet;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
@@ -77,7 +78,7 @@ public class LedgerRepositoryImpl implements LedgerRepository {
this.ledgerIndexKey = encodeLedgerIndexKey(ledgerHash);
if (getLatestBlockHeight() < 0) {
- throw new LedgerException("Ledger doesn't exist!");
+ throw new RuntimeException("Ledger doesn't exist!");
}
}
@@ -205,15 +206,14 @@ public class LedgerRepositoryImpl implements LedgerRepository {
LedgerBlockData block = new LedgerBlockData(deserialize(blockBytes));
if (!blockHash.equals(block.getHash())) {
- throw new LedgerException("Block hash not equals to it's storage key!");
+ throw new RuntimeException("Block hash not equals to it's storage key!");
}
// verify hash;
// boolean requiredVerifyHash =
// adminAccount.getMetadata().getSetting().getCryptoSetting().getAutoVerifyHash();
// TODO: 未实现从配置中加载是否校验 Hash 的设置;
- boolean requiredVerifyHash = false;
- if (requiredVerifyHash) {
+ if (SettingContext.queryingSettings().verifyHash()) {
byte[] blockBodyBytes = null;
if (block.getHeight() == 0) {
// 计算创世区块的 hash 时,不包括 ledgerHash 字段;
@@ -227,14 +227,14 @@ public class LedgerRepositoryImpl implements LedgerRepository {
HashFunction hashFunc = Crypto.getHashFunction(blockHash.getAlgorithm());
boolean pass = hashFunc.verify(blockHash, blockBodyBytes);
if (!pass) {
- throw new LedgerException("Block hash verification fail!");
+ throw new RuntimeException("Block hash verification fail!");
}
}
// verify height;
HashDigest indexedHash = getBlockHash(block.getHeight());
if (indexedHash == null || !indexedHash.equals(blockHash)) {
- throw new LedgerException(
+ throw new RuntimeException(
"Illegal ledger state in storage that ledger height index doesn't match it's block data in height["
+ block.getHeight() + "] and block hash[" + Base58Utils.encode(blockHash.toBytes())
+ "] !");
@@ -394,15 +394,15 @@ public class LedgerRepositoryImpl implements LedgerRepository {
@Override
public synchronized LedgerEditor createNextBlock() {
if (closed) {
- throw new LedgerException("Ledger repository has been closed!");
+ throw new RuntimeException("Ledger repository has been closed!");
}
if (this.nextBlockEditor != null) {
- throw new LedgerException(
+ throw new RuntimeException(
"A new block is in process, cann't create another one until it finish by committing or canceling.");
}
LedgerBlock previousBlock = getLatestBlock();
- LedgerTransactionalEditor editor = LedgerTransactionalEditor.createEditor(ledgerHash,
- getAdminInfo().getMetadata().getSetting(), previousBlock, keyPrefix, exPolicyStorage,
+ LedgerTransactionalEditor editor = LedgerTransactionalEditor.createEditor(previousBlock,
+ getAdminInfo().getMetadata().getSetting(), keyPrefix, exPolicyStorage,
versioningStorage);
NewBlockCommittingMonitor committingMonitor = new NewBlockCommittingMonitor(editor, this);
this.nextBlockEditor = committingMonitor;
@@ -420,7 +420,7 @@ public class LedgerRepositoryImpl implements LedgerRepository {
return;
}
if (this.nextBlockEditor != null) {
- throw new LedgerException("A new block is in process, cann't close the ledger repository!");
+ throw new RuntimeException("A new block is in process, cann't close the ledger repository!");
}
closed = true;
}
@@ -600,7 +600,7 @@ public class LedgerRepositoryImpl implements LedgerRepository {
public void commit() {
try {
editor.commit();
- LedgerBlock latestBlock = editor.getNewlyBlock();
+ LedgerBlock latestBlock = editor.getCurrentBlock();
ledgerRepo.latestState = new LedgerState(latestBlock);
} finally {
ledgerRepo.nextBlockEditor = null;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionData.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionData.java
index 6e231b44..432c24e1 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionData.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionData.java
@@ -1,8 +1,5 @@
package com.jd.blockchain.ledger.core.impl;
-import java.util.Arrays;
-import java.util.Comparator;
-
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.LedgerTransaction;
@@ -29,48 +26,27 @@ public class LedgerTransactionData implements LedgerTransaction {
private OperationResult[] operationResults;
- // private HashDigest adminAccountHash;
- //
- // private HashDigest userAccountSetHash;
- //
- // private HashDigest dataAccountSetHash;
- //
- // private HashDigest contractAccountSetHash;
-
/**
* Declare a private no-arguments constructor for deserializing purpose;
*/
+ @SuppressWarnings("unused")
private LedgerTransactionData() {
-// this.txSnapshot = new TransactionStagedSnapshot();
}
/**
- * @param blockHeight
- * 区块链高度;
- * @param txReq
- * 交易请求;
- * @param execState
- * 执行状态;
- * @param txSnapshot
- * 交易级的系统快照;
+ * @param blockHeight 区块链高度;
+ * @param txReq 交易请求;
+ * @param execState 执行状态;
+ * @param txSnapshot 交易级的系统快照;
*/
public LedgerTransactionData(long blockHeight, TransactionRequest txReq, TransactionState execState,
TransactionStagedSnapshot txSnapshot, OperationResult... opResults) {
this.blockHeight = blockHeight;
-// this.txSnapshot = txSnapshot == null ? new TransactionStagedSnapshot() : txSnapshot;
this.txSnapshot = txSnapshot;
this.transactionContent = txReq.getTransactionContent();
this.endpointSignatures = txReq.getEndpointSignatures();
this.nodeSignatures = txReq.getNodeSignatures();
this.executionState = execState;
- if (opResults != null) {
- Arrays.sort(opResults, new Comparator() {
- @Override
- public int compare(OperationResult o1, OperationResult o2) {
- return o1.getIndex() - o2.getIndex();
- }
- });
- }
this.operationResults = opResults;
}
@@ -116,17 +92,17 @@ public class LedgerTransactionData implements LedgerTransaction {
@Override
public HashDigest getUserAccountSetHash() {
- return txSnapshot == null ? null :txSnapshot.getUserAccountSetHash();
+ return txSnapshot == null ? null : txSnapshot.getUserAccountSetHash();
}
@Override
public HashDigest getDataAccountSetHash() {
- return txSnapshot == null ? null :txSnapshot.getDataAccountSetHash();
+ return txSnapshot == null ? null : txSnapshot.getDataAccountSetHash();
}
@Override
public HashDigest getContractAccountSetHash() {
- return txSnapshot == null ? null :txSnapshot.getContractAccountSetHash();
+ return txSnapshot == null ? null : txSnapshot.getContractAccountSetHash();
}
public void setTxSnapshot(TransactionStagedSnapshot txSnapshot) {
@@ -140,20 +116,22 @@ public class LedgerTransactionData implements LedgerTransaction {
this.transactionContent = content;
}
- public void setEndpointSignatures(Object[] participantSignatures) {
- int length = participantSignatures.length;
- this.endpointSignatures = new DigitalSignature[length];
- for (int i = 0; i < length; i++) {
- this.endpointSignatures[i] = (DigitalSignature) participantSignatures[i];
- }
+ public void setEndpointSignatures(DigitalSignature[] participantSignatures) {
+ this.endpointSignatures = participantSignatures;
+// int length = participantSignatures.length;
+// this.endpointSignatures = new DigitalSignature[length];
+// for (int i = 0; i < length; i++) {
+// this.endpointSignatures[i] = (DigitalSignature) participantSignatures[i];
+// }
}
- public void setNodeSignatures(Object[] nodeSignatures) {
- int length = nodeSignatures.length;
- this.nodeSignatures = new DigitalSignature[length];
- for (int i = 0; i < length; i++) {
- this.nodeSignatures[i] = (DigitalSignature) nodeSignatures[i];
- }
+ public void setNodeSignatures(DigitalSignature[] nodeSignatures) {
+ this.nodeSignatures = nodeSignatures;
+// int length = nodeSignatures.length;
+// this.nodeSignatures = new DigitalSignature[length];
+// for (int i = 0; i < length; i++) {
+// this.nodeSignatures[i] = (DigitalSignature) nodeSignatures[i];
+// }
}
public void setExecutionState(TransactionState executionState) {
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java
index 5113dde4..235d08b8 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java
@@ -1,19 +1,35 @@
package com.jd.blockchain.ledger.core.impl;
import java.util.List;
-import java.util.Stack;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.ledger.*;
+import com.jd.blockchain.ledger.BlockBody;
+import com.jd.blockchain.ledger.BlockRollbackException;
+import com.jd.blockchain.ledger.CryptoSetting;
+import com.jd.blockchain.ledger.DigitalSignature;
+import com.jd.blockchain.ledger.IllegalTransactionException;
+import com.jd.blockchain.ledger.LedgerBlock;
+import com.jd.blockchain.ledger.LedgerDataSnapshot;
+import com.jd.blockchain.ledger.LedgerInitSetting;
+import com.jd.blockchain.ledger.LedgerSetting;
+import com.jd.blockchain.ledger.LedgerTransaction;
+import com.jd.blockchain.ledger.OperationResult;
+import com.jd.blockchain.ledger.TransactionContent;
+import com.jd.blockchain.ledger.TransactionRequest;
+import com.jd.blockchain.ledger.TransactionRollbackException;
+import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerTransactionContext;
+import com.jd.blockchain.ledger.core.SettingContext;
import com.jd.blockchain.ledger.core.TransactionSet;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.storage.service.utils.BufferedKVStorage;
+import com.jd.blockchain.transaction.TxBuilder;
+import com.jd.blockchain.transaction.TxRequestBuilder;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.codec.Base58Utils;
@@ -35,9 +51,9 @@ public class LedgerTransactionalEditor implements LedgerEditor {
private CryptoSetting cryptoSetting;
- private LedgerBlockData newlyBlock;
+ private LedgerBlockData currentBlock;
- private Stack stagedSnapshots = new Stack<>();
+// private Stack stagedSnapshots = new Stack<>();
private boolean prepared = false;
@@ -45,43 +61,70 @@ public class LedgerTransactionalEditor implements LedgerEditor {
private boolean committed = false;
-// private BufferedKVStorage baseStorage;
- private BufferedKVStorage bufferedStorage;
+ private StagedSnapshot startingPoint;
/**
- * 最近一个交易上下文;
+ * 当前区块的存储;
*/
- private LedgerDataContext lastTxCtx;
+ private BufferedKVStorage baseStorage;
- private LedgerDataContext newTxCtx;
+ /**
+ * 上一个交易的上下文;
+ */
+// private LedgerTransactionContextImpl previousTxCtx;
+
+ private TxSnapshot previousTxSnapshot;
+
+ /**
+ * 当前交易的上下文;
+ */
+ private volatile LedgerTransactionContextImpl currentTxCtx;
- private LedgerTransactionalEditor(HashDigest ledgerHash, CryptoSetting cryptoSetting, LedgerBlockData newlyBlock,
+ /**
+ * @param ledgerHash
+ * @param cryptoSetting
+ * @param currentBlock
+ * @param startingPoint
+ * @param ledgerKeyPrefix
+ * @param bufferedStorage
+ * @param verifyTx 是否校验交易请求;当外部调用者在调用前已经实施了验证时,将次参数设置为 false 能够提升性能;
+ */
+ private LedgerTransactionalEditor(HashDigest ledgerHash, CryptoSetting cryptoSetting, LedgerBlockData currentBlock,
StagedSnapshot startingPoint, String ledgerKeyPrefix, BufferedKVStorage bufferedStorage) {
this.ledgerHash = ledgerHash;
this.ledgerKeyPrefix = ledgerKeyPrefix;
this.cryptoSetting = cryptoSetting;
- this.newlyBlock = newlyBlock;
- this.bufferedStorage = bufferedStorage;
+ this.currentBlock = currentBlock;
+ this.baseStorage = bufferedStorage;
+
+ this.startingPoint = startingPoint;
- this.stagedSnapshots.push(startingPoint);
+// this.stagedSnapshots.push(startingPoint);
}
/**
* 创建账本新区块的编辑器;
*
- * @param ledgerHash
- * @param ledgerSetting
- * @param previousBlock
- * @param ledgerKeyPrefix
- * @param ledgerExStorage
- * @param ledgerVerStorage
+ * @param ledgerHash 账本哈希;
+ * @param ledgerSetting 账本设置;
+ * @param previousBlock 前置区块;
+ * @param ledgerKeyPrefix 账本数据前缀;
+ * @param ledgerExStorage 账本数据存储;
+ * @param ledgerVerStorage 账本数据版本化存储;
+ * @param verifyTx 是否校验交易请求;当外部调用者在调用前已经实施了验证时,将次参数设置为 false 能够提升性能;
* @return
*/
- public static LedgerTransactionalEditor createEditor(HashDigest ledgerHash, LedgerSetting ledgerSetting,
- LedgerBlock previousBlock, String ledgerKeyPrefix, ExPolicyKVStorage ledgerExStorage,
- VersioningKVStorage ledgerVerStorage) {
+ public static LedgerTransactionalEditor createEditor(LedgerBlock previousBlock, LedgerSetting ledgerSetting,
+ String ledgerKeyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
// new block;
- LedgerBlockData currBlock = new LedgerBlockData(previousBlock.getHeight() + 1, previousBlock.getLedgerHash(),
+ HashDigest ledgerHash = previousBlock.getLedgerHash();
+ if (ledgerHash == null) {
+ ledgerHash = previousBlock.getHash();
+ }
+ if (ledgerHash == null) {
+ throw new IllegalArgumentException("Illegal previous block was specified!");
+ }
+ LedgerBlockData currBlock = new LedgerBlockData(previousBlock.getHeight() + 1, ledgerHash,
previousBlock.getHash());
// init storage;
@@ -101,6 +144,7 @@ public class LedgerTransactionalEditor implements LedgerEditor {
* @param ledgerKeyPrefix
* @param ledgerExStorage
* @param ledgerVerStorage
+ * @param verifyTx 是否校验交易请求;当外部调用者在调用前已经实施了验证时,将次参数设置为 false 能够提升性能;
* @return
*/
public static LedgerTransactionalEditor createEditor(LedgerInitSetting initSetting, String ledgerKeyPrefix,
@@ -114,29 +158,21 @@ public class LedgerTransactionalEditor implements LedgerEditor {
}
private void commitTxSnapshot(TxSnapshot snapshot) {
- lastTxCtx = newTxCtx;
- newTxCtx = null;
- stagedSnapshots.push(snapshot);
+ previousTxSnapshot = snapshot;
+ currentTxCtx = null;
}
- private void rollbackNewTx() {
- newTxCtx = null;
+ private void rollbackCurrentTx() {
+ currentTxCtx = null;
}
- // public LedgerDataSet getLatestDataSet() {
- // if (lastTxCtx == null) {
- // return null;
- // }
- // return lastTxCtx.getDataSet();
- // }
-
- LedgerBlock getNewlyBlock() {
- return newlyBlock;
+ LedgerBlock getCurrentBlock() {
+ return currentBlock;
}
@Override
public long getBlockHeight() {
- return newlyBlock.getHeight();
+ return currentBlock.getHeight();
}
@Override
@@ -161,134 +197,182 @@ public class LedgerTransactionalEditor implements LedgerEditor {
return ledgerHash.equals(reqLedgerHash);
}
+ private boolean verifyTxContent(TransactionRequest request) {
+ TransactionContent txContent = request.getTransactionContent();
+ if (!TxBuilder.verifyTxContentHash(txContent, txContent.getHash())) {
+ return false;
+ }
+ DigitalSignature[] endpointSignatures = request.getEndpointSignatures();
+ if (endpointSignatures != null) {
+ for (DigitalSignature signature : endpointSignatures) {
+ if (!TxRequestBuilder.verifyHashSignature(txContent.getHash(), signature.getDigest(),
+ signature.getPubKey())) {
+ return false;
+ }
+ }
+ }
+ DigitalSignature[] nodeSignatures = request.getNodeSignatures();
+ if (nodeSignatures != null) {
+ for (DigitalSignature signature : nodeSignatures) {
+ if (!TxRequestBuilder.verifyHashSignature(txContent.getHash(), signature.getDigest(),
+ signature.getPubKey())) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
@Override
- public LedgerTransactionContext newTransaction(TransactionRequest txRequest) {
- // 验证账本是否;
- if (!isRequestedLedger(txRequest)) {
- throw new LedgerException("This ledger is not the target ledger of transaction request["
- + txRequest.getTransactionContent().getHash() + "]!");
+ public synchronized LedgerTransactionContext newTransaction(TransactionRequest txRequest) {
+ if (SettingContext.txSettings().verifyLedger() && !isRequestedLedger(txRequest)) {
+ throw new IllegalTransactionException(
+ "Transaction request is dispatched to a wrong ledger! --[TxHash="
+ + txRequest.getTransactionContent().getHash() + "]!",
+ TransactionState.IGNORED_BY_WRONG_LEDGER);
+ }
+
+ // TODO: 把验签和创建交易并行化;
+ if (SettingContext.txSettings().verifySignature() && !verifyTxContent(txRequest)) {
+ // 抛弃哈希和签名校验失败的交易请求;
+ throw new IllegalTransactionException(
+ "Wrong transaction signature! --[TxHash=" + txRequest.getTransactionContent().getHash() + "]!",
+ TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE);
+ }
+
+ if (currentTxCtx != null) {
+ throw new IllegalStateException(
+ "Unable to open another new transaction before the current transaction is completed! --[TxHash="
+ + txRequest.getTransactionContent().getHash() + "]!");
}
// 检查状态是否允许创建新的交易请求;;
checkState();
- BufferedKVStorage txBuffStorage = null;
+ // init storage of new transaction;
+ BufferedKVStorage txBufferedStorage = new BufferedKVStorage(baseStorage, baseStorage, false);
+
LedgerDataSetImpl txDataset = null;
TransactionSet txset = null;
- if (lastTxCtx == null) {
- // init storage of new transaction;
- // txBuffStorage = new BufferedKVStorage(bufferedStorage, bufferedStorage,
- // false);
- txBuffStorage = bufferedStorage;
-
+ if (previousTxSnapshot == null) {
// load the starting point of the new transaction;
- StagedSnapshot previousSnapshot = stagedSnapshots.peek();
- if (previousSnapshot instanceof GenesisSnapshot) {
+ if (startingPoint instanceof GenesisSnapshot) {
// 准备生成创世区块;
- GenesisSnapshot snpht = (GenesisSnapshot) previousSnapshot;
- txDataset = LedgerRepositoryImpl.newDataSet(snpht.initSetting, ledgerKeyPrefix, txBuffStorage,
- txBuffStorage);
+ GenesisSnapshot snpht = (GenesisSnapshot) startingPoint;
+ txDataset = LedgerRepositoryImpl.newDataSet(snpht.initSetting, ledgerKeyPrefix, txBufferedStorage,
+ txBufferedStorage);
txset = LedgerRepositoryImpl.newTransactionSet(txDataset.getAdminAccount().getSetting(),
- ledgerKeyPrefix, txBuffStorage, txBuffStorage);
- } else {
+ ledgerKeyPrefix, txBufferedStorage, txBufferedStorage);
+ } else if (startingPoint instanceof TxSnapshot) {
// 新的区块;
// TxSnapshot; reload dataset and txset;
- TxSnapshot snpht = (TxSnapshot) previousSnapshot;
+ TxSnapshot snpht = (TxSnapshot) startingPoint;
// load dataset;
- txDataset = LedgerRepositoryImpl.loadDataSet(snpht.dataSnapshot, ledgerKeyPrefix, txBuffStorage,
- txBuffStorage, false);
+ txDataset = LedgerRepositoryImpl.loadDataSet(snpht.dataSnapshot, ledgerKeyPrefix, txBufferedStorage,
+ txBufferedStorage, false);
- // load tx set;
- txset = LedgerRepositoryImpl.loadTransactionSet(snpht.transactionSetHash, this.cryptoSetting,
- ledgerKeyPrefix, txBuffStorage, txBuffStorage, false);
+ // load txset;
+ txset = LedgerRepositoryImpl.loadTransactionSet(snpht.txsetHash, this.cryptoSetting, ledgerKeyPrefix,
+ txBufferedStorage, txBufferedStorage, false);
+ } else {
+ // Unreachable;
+ throw new IllegalStateException("Unreachable code was accidentally executed!");
}
- lastTxCtx = new LedgerDataContext(txDataset, txset, txBuffStorage);
} else {
// Reuse previous object to optimize performance;
- txBuffStorage = lastTxCtx.storage;
- txDataset = lastTxCtx.dataset;
- txset = lastTxCtx.txset;
+ // load dataset;
+ txDataset = LedgerRepositoryImpl.loadDataSet(previousTxSnapshot.dataSnapshot, ledgerKeyPrefix,
+ txBufferedStorage, txBufferedStorage, false);
+
+ // load txset;
+ txset = LedgerRepositoryImpl.loadTransactionSet(previousTxSnapshot.txsetHash, this.cryptoSetting,
+ ledgerKeyPrefix, txBufferedStorage, txBufferedStorage, false);
}
- // newTxCtx = new LedgerTransactionContextImpl(newlyBlock.getHeight(),
- // txRequest, txDataset, txset, txBuffStorage,
- // this);
- // return newTxCtx;
+ currentTxCtx = new LedgerTransactionContextImpl(txRequest, txDataset, txset, txBufferedStorage, this);
- return new LedgerTransactionContextImpl(newlyBlock.getHeight(), txRequest, txDataset, txset, txBuffStorage,
- this);
+ return currentTxCtx;
}
@Override
public LedgerBlock prepare() {
checkState();
- if (newTxCtx != null) {
- throw new IllegalStateException("There is a opening transaction which isn't committed or rollbacked!");
+ if (currentTxCtx != null) {
+ // 有进行中的交易尚未提交或回滚;
+ throw new IllegalStateException(
+ "There is an ongoing transaction that has been not committed or rolled back!");
}
- if (lastTxCtx == null) {
- // Genesis;
- throw new IllegalStateException("No transaction to prepare!");
+ if (previousTxSnapshot == null) {
+ // 当前区块没有加入过交易,不允许产生空区块;
+ throw new IllegalStateException(
+ "There is no transaction in the current block, and no empty blocks is allowed!");
}
// do commit when transaction isolation level is BLOCK;
- lastTxCtx.dataset.commit();
- lastTxCtx.txset.commit();
+ currentBlock.setAdminAccountHash(previousTxSnapshot.getAdminAccountHash());
+ currentBlock.setUserAccountSetHash(previousTxSnapshot.getUserAccountSetHash());
+ currentBlock.setDataAccountSetHash(previousTxSnapshot.getDataAccountSetHash());
+ currentBlock.setContractAccountSetHash(previousTxSnapshot.getContractAccountSetHash());
+ currentBlock.setTransactionSetHash(previousTxSnapshot.getTransactionSetHash());
- newlyBlock.setAdminAccountHash(lastTxCtx.dataset.getAdminAccount().getHash());
- newlyBlock.setContractAccountSetHash(lastTxCtx.dataset.getContractAccountSet().getRootHash());
- newlyBlock.setDataAccountSetHash(lastTxCtx.dataset.getDataAccountSet().getRootHash());
- newlyBlock.setUserAccountSetHash(lastTxCtx.dataset.getUserAccountSet().getRootHash());
- newlyBlock.setTransactionSetHash(lastTxCtx.txset.getRootHash());
+ // TODO: 根据所有交易的时间戳的平均值来生成区块的时间戳;
+// long timestamp =
+// currentBlock.setTimestamp(timestamp);
// compute block hash;
- byte[] blockBodyBytes = BinaryProtocol.encode(newlyBlock, BlockBody.class);
+ byte[] blockBodyBytes = BinaryProtocol.encode(currentBlock, BlockBody.class);
HashDigest blockHash = Crypto.getHashFunction(cryptoSetting.getHashAlgorithm()).hash(blockBodyBytes);
- newlyBlock.setHash(blockHash);
- if (newlyBlock.getLedgerHash() == null) {
- // init GenesisBlock's ledger hash;
- newlyBlock.setLedgerHash(blockHash);
- }
+ currentBlock.setHash(blockHash);
+
+// if (currentBlock.getLedgerHash() == null) {
+// // init GenesisBlock's ledger hash;
+// currentBlock.setLedgerHash(blockHash);
+// }
// persist block bytes;
// only one version per block;
- byte[] blockBytes = BinaryProtocol.encode(newlyBlock, LedgerBlock.class);
- Bytes blockStorageKey = LedgerRepositoryImpl.encodeBlockStorageKey(newlyBlock.getHash());
- long v = bufferedStorage.set(blockStorageKey, blockBytes, -1);
+ byte[] blockBytes = BinaryProtocol.encode(currentBlock, LedgerBlock.class);
+ Bytes blockStorageKey = LedgerRepositoryImpl.encodeBlockStorageKey(currentBlock.getHash());
+ long v = baseStorage.set(blockStorageKey, blockBytes, -1);
if (v < 0) {
throw new IllegalStateException(
- "Block already exist! --[BlockHash=" + Base58Utils.encode(newlyBlock.getHash().toBytes()) + "]");
+ "Block already exist! --[BlockHash=" + Base58Utils.encode(currentBlock.getHash().toBytes()) + "]");
}
// persist block hash to ledger index;
- HashDigest ledgerHash = newlyBlock.getLedgerHash();
+ HashDigest ledgerHash = currentBlock.getLedgerHash();
+ if (ledgerHash == null) {
+ ledgerHash = blockHash;
+ }
Bytes ledgerIndexKey = LedgerRepositoryImpl.encodeLedgerIndexKey(ledgerHash);
- long expectedVersion = newlyBlock.getHeight() - 1;
- v = bufferedStorage.set(ledgerIndexKey, newlyBlock.getHash().toBytes(), expectedVersion);
+ long expectedVersion = currentBlock.getHeight() - 1;
+ v = baseStorage.set(ledgerIndexKey, currentBlock.getHash().toBytes(), expectedVersion);
if (v < 0) {
- throw new IllegalStateException("Index of BlockHash already exist! --[BlockHash="
- + Base58Utils.encode(newlyBlock.getHash().toBytes()) + "]");
+ throw new IllegalStateException(
+ String.format("Index of BlockHash already exist! --[BlockHeight=%s][BlockHash=%s]",
+ currentBlock.getHeight(), currentBlock.getHash()));
}
prepared = true;
- return newlyBlock;
+ return currentBlock;
}
@Override
public void commit() {
if (committed) {
- throw new IllegalStateException("LedgerEditor had been committed!");
+ throw new IllegalStateException("The current block has been committed!");
}
if (canceled) {
- throw new IllegalStateException("LedgerEditor had been canceled!");
+ throw new IllegalStateException("The current block has been canceled!");
}
if (!prepared) {
// 未就绪;
- throw new IllegalStateException("LedgerEditor has not prepared!");
+ throw new IllegalStateException("The current block is not ready yet!");
}
- bufferedStorage.flush();
+ baseStorage.flush();
committed = true;
}
@@ -296,38 +380,47 @@ public class LedgerTransactionalEditor implements LedgerEditor {
@Override
public void cancel() {
if (committed) {
- throw new IllegalStateException("LedgerEditor had been committed!");
+ throw new IllegalStateException("The current block has been committed!");
}
if (canceled) {
return;
}
canceled = true;
- // if (newTxCtx != null) {
- // newTxCtx.rollback();
- // newTxCtx = null;
- // }
- bufferedStorage.cancel();
+
+ baseStorage.cancel();
}
private void checkState() {
if (prepared) {
- throw new IllegalStateException("LedgerEditor has been prepared!");
+ throw new IllegalStateException("The current block is ready!");
}
if (committed) {
- throw new IllegalStateException("LedgerEditor has been committed!");
+ throw new IllegalStateException("The current block has been committed!");
}
if (canceled) {
- throw new IllegalStateException("LedgerEditor has been canceled!");
+ throw new IllegalStateException("The current block has been canceled!");
}
}
// --------------------------- inner type --------------------------
+ /**
+ * 用于暂存交易上下文数据的快照对象;
+ *
+ * @author huanghaiquan
+ *
+ */
private static interface StagedSnapshot {
}
+ /**
+ * 创世区块的快照对象;
+ *
+ * @author huanghaiquan
+ *
+ */
private static class GenesisSnapshot implements StagedSnapshot {
private LedgerInitSetting initSetting;
@@ -337,6 +430,12 @@ public class LedgerTransactionalEditor implements LedgerEditor {
}
}
+ /**
+ * 交易执行完毕后的快照对象;
+ *
+ * @author huanghaiquan
+ *
+ */
private static class TxSnapshot implements StagedSnapshot {
/**
@@ -347,58 +446,90 @@ public class LedgerTransactionalEditor implements LedgerEditor {
/**
* 交易集合的快照(根哈希);
*/
- private HashDigest transactionSetHash;
+ private HashDigest txsetHash;
- public TxSnapshot(LedgerDataSnapshot dataSnapshot, HashDigest txSetHash) {
- this.dataSnapshot = dataSnapshot;
- this.transactionSetHash = txSetHash;
+ public HashDigest getAdminAccountHash() {
+ return dataSnapshot.getAdminAccountHash();
}
- }
-
- private static class LedgerDataContext {
+ public HashDigest getUserAccountSetHash() {
+ return dataSnapshot.getUserAccountSetHash();
+ }
- protected LedgerDataSetImpl dataset;
+ public HashDigest getDataAccountSetHash() {
+ return dataSnapshot.getDataAccountSetHash();
+ }
- protected TransactionSet txset;
+ public HashDigest getContractAccountSetHash() {
+ return dataSnapshot.getContractAccountSetHash();
+ }
- protected BufferedKVStorage storage;
+ public HashDigest getTransactionSetHash() {
+ return txsetHash;
+ }
- public LedgerDataContext(LedgerDataSetImpl dataset, TransactionSet txset, BufferedKVStorage storage) {
- this.dataset = dataset;
- this.txset = txset;
- this.storage = storage;
+ public TxSnapshot(LedgerDataSnapshot dataSnapshot, HashDigest txsetHash) {
+ this.dataSnapshot = dataSnapshot;
+ this.txsetHash = txsetHash;
}
}
- private static class LedgerTransactionContextImpl extends LedgerDataContext implements LedgerTransactionContext {
+// /**
+// * 账本的数据上下文;
+// *
+// * @author huanghaiquan
+// *
+// */
+// private static class LedgerDataContext {
+//
+// protected LedgerDataSetImpl dataset;
+//
+// protected TransactionSet txset;
+//
+// protected BufferedKVStorage storage;
+//
+// public LedgerDataContext(LedgerDataSetImpl dataset, TransactionSet txset, BufferedKVStorage storage) {
+// this.dataset = dataset;
+// this.txset = txset;
+// this.storage = storage;
+// }
+//
+// }
- private long blockHeight;
+ /**
+ * 交易的上下文;
+ *
+ * @author huanghaiquan
+ *
+ */
+ private static class LedgerTransactionContextImpl implements LedgerTransactionContext {
- private LedgerTransactionalEditor editor;
+ private LedgerTransactionalEditor blockEditor;
private TransactionRequest txRequest;
- // private LedgerDataSetImpl dataset;
- //
- // private TransactionSet txset;
- //
- // private BufferedKVStorage storage;
+ private LedgerDataSetImpl dataset;
+
+ private TransactionSet txset;
+
+ private BufferedKVStorage storage;
private boolean committed = false;
private boolean rollbacked = false;
- private LedgerTransactionContextImpl(long blockHeight, TransactionRequest txRequest, LedgerDataSetImpl dataset,
+ private LedgerTransaction transaction;
+
+ private HashDigest txRootHash;
+
+ private LedgerTransactionContextImpl(TransactionRequest txRequest, LedgerDataSetImpl dataset,
TransactionSet txset, BufferedKVStorage storage, LedgerTransactionalEditor editor) {
- super(dataset, txset, storage);
this.txRequest = txRequest;
- // this.dataset = dataset;
- // this.txset = txset;
- // this.storage = storage;
- this.editor = editor;
- this.blockHeight = blockHeight;
+ this.dataset = dataset;
+ this.txset = txset;
+ this.storage = storage;
+ this.blockEditor = editor;
}
@Override
@@ -407,7 +538,7 @@ public class LedgerTransactionalEditor implements LedgerEditor {
}
@Override
- public TransactionRequest getRequestTX() {
+ public TransactionRequest getTransactionRequest() {
return txRequest;
}
@@ -421,24 +552,28 @@ public class LedgerTransactionalEditor implements LedgerEditor {
checkTxState();
// capture snapshot
- // this.dataset.commit();
- // TransactionStagedSnapshot txDataSnapshot = takeSnapshot();
-
- // LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest,
- // txResult, txDataSnapshot);
-
- LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest, txResult, null,
- operationResultArray(operationResults));
- this.txset.add(tx);
- // this.txset.commit();
-
- // this.storage.flush();
+ this.dataset.commit();
+ TransactionStagedSnapshot txDataSnapshot = takeDataSnapshot();
+
+ LedgerTransactionData tx;
+ try {
+ tx = new LedgerTransactionData(blockEditor.getBlockHeight(), txRequest, txResult, txDataSnapshot,
+ operationResultArray(operationResults));
+ this.txset.add(tx);
+ this.txset.commit();
+ } catch (Exception e) {
+ throw new TransactionRollbackException(e.getMessage(), e);
+ }
- // TODO: 未处理出错时 dataset 和 txset 的内部状态恢复,有可能出现不一致的情况;
+ try {
+ this.storage.flush();
+ } catch (Exception e) {
+ throw new BlockRollbackException(e.getMessage(), e);
+ }
// put snapshot into stack;
- // TxSnapshot snapshot = new TxSnapshot(txDataSnapshot, txset.getRootHash());
- // editor.commitTxSnapshot(snapshot);
+ TxSnapshot snapshot = new TxSnapshot(txDataSnapshot, txset.getRootHash());
+ blockEditor.commitTxSnapshot(snapshot);
committed = true;
return tx;
@@ -454,29 +589,35 @@ public class LedgerTransactionalEditor implements LedgerEditor {
checkTxState();
// 未处理
- // dataset.cancel();
-
- // TransactionStagedSnapshot txDataSnapshot = takeSnapshot();
- // LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest,
- // txResult, txDataSnapshot);
- LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest, txResult, null,
- operationResultArray(operationResults));
- this.txset.add(tx);
- // this.txset.commit();
-
- // this.storage.flush();
+ dataset.cancel();
+
+ TransactionStagedSnapshot txDataSnapshot = takeDataSnapshot();
+
+ LedgerTransactionData tx;
+ try {
+ tx = new LedgerTransactionData(blockEditor.getBlockHeight(), txRequest, txResult, txDataSnapshot,
+ operationResultArray(operationResults));
+ this.txset.add(tx);
+ this.txset.commit();
+ } catch (Exception e) {
+ throw new TransactionRollbackException(e.getMessage(), e);
+ }
- // TODO: 未处理出错时 dataset 和 txset 的内部状态恢复,有可能出现不一致的情况;
+ try {
+ this.storage.flush();
+ } catch (Exception e) {
+ throw new BlockRollbackException(e.getMessage(), e);
+ }
// put snapshot into stack;
- // TxSnapshot snapshot = new TxSnapshot(txDataSnapshot, txset.getRootHash());
- // editor.commitTxSnapshot(snapshot);
+ TxSnapshot snapshot = new TxSnapshot(txDataSnapshot, txset.getRootHash());
+ blockEditor.commitTxSnapshot(snapshot);
committed = true;
return tx;
}
- private TransactionStagedSnapshot takeSnapshot() {
+ private TransactionStagedSnapshot takeDataSnapshot() {
TransactionStagedSnapshot txDataSnapshot = new TransactionStagedSnapshot();
txDataSnapshot.setAdminAccountHash(dataset.getAdminAccount().getHash());
txDataSnapshot.setContractAccountSetHash(dataset.getContractAccountSet().getRootHash());
@@ -500,22 +641,22 @@ public class LedgerTransactionalEditor implements LedgerEditor {
return;
}
if (this.committed) {
- throw new IllegalStateException("Transaction had been committed!");
+ throw new IllegalStateException("This transaction had been committed!");
}
- // dataset.cancel();
- // storage.cancel();
+ dataset.cancel();
+ storage.cancel();
- // editor.rollbackNewTx();
+ blockEditor.rollbackCurrentTx();
rollbacked = true;
}
private void checkTxState() {
if (this.committed) {
- throw new IllegalStateException("Transaction had been committed!");
+ throw new IllegalStateException("This transaction had been committed!");
}
if (this.rollbacked) {
- throw new IllegalStateException("Transaction had been rollbacked!");
+ throw new IllegalStateException("This transaction had been rollbacked!");
}
}
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java
index 78b099ae..aa8fcf93 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java
@@ -8,18 +8,19 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.BlockRollbackException;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.ContractDoesNotExistException;
import com.jd.blockchain.ledger.DataAccountDoesNotExistException;
-import com.jd.blockchain.ledger.DigitalSignature;
+import com.jd.blockchain.ledger.IllegalTransactionException;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.OperationResult;
import com.jd.blockchain.ledger.OperationResultData;
-import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionResponse;
+import com.jd.blockchain.ledger.TransactionRollbackException;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.UserDoesNotExistException;
import com.jd.blockchain.ledger.core.LedgerDataSet;
@@ -31,8 +32,6 @@ import com.jd.blockchain.ledger.core.TransactionRequestContext;
import com.jd.blockchain.service.TransactionBatchProcess;
import com.jd.blockchain.service.TransactionBatchResult;
import com.jd.blockchain.service.TransactionBatchResultHandle;
-import com.jd.blockchain.transaction.TxBuilder;
-import com.jd.blockchain.transaction.TxRequestBuilder;
import com.jd.blockchain.transaction.TxResponseMessage;
import com.jd.blockchain.utils.Bytes;
@@ -70,18 +69,6 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
this.ledgerService = ledgerService;
}
- private boolean isRequestedLedger(TransactionRequest txRequest) {
- HashDigest currLedgerHash = newBlockEditor.getLedgerHash();
- HashDigest reqLedgerHash = txRequest.getTransactionContent().getLedgerHash();
- if (currLedgerHash == reqLedgerHash) {
- return true;
- }
- if (currLedgerHash == null || reqLedgerHash == null) {
- return false;
- }
- return currLedgerHash.equals(reqLedgerHash);
- }
-
/*
* (non-Javadoc)
*
@@ -93,19 +80,6 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
public TransactionResponse schedule(TransactionRequest request) {
TransactionResponse resp;
try {
- if (!isRequestedLedger(request)) {
- // 抛弃不属于当前账本的交易请求;
- resp = discard(request, TransactionState.DISCARD_BY_WRONG_LEDGER);
- responseList.add(resp);
- return resp;
- }
- if (!verifyTxContent(request)) {
- // 抛弃哈希和签名校验失败的交易请求;
- resp = discard(request, TransactionState.DISCARD_BY_WRONG_CONTENT_SIGNATURE);
- responseList.add(resp);
- return resp;
- }
-
LOGGER.debug("Start handling transaction... --[BlockHeight={}][RequestHash={}][TxHash={}]",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash());
// 创建交易上下文;
@@ -118,19 +92,34 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
LOGGER.debug("Complete handling transaction. --[BlockHeight={}][RequestHash={}][TxHash={}]",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash());
- responseList.add(resp);
- return resp;
+ } catch (IllegalTransactionException e) {
+ // 抛弃发生处理异常的交易请求;
+ resp = discard(request, e.getTxState());
+ LOGGER.error(String.format(
+ "Ignore transaction caused by IllegalTransactionException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
+ e.getMessage()), e);
+
+ } catch (BlockRollbackException e) {
+ // 抛弃发生处理异常的交易请求;
+// resp = discard(request, TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK);
+ LOGGER.error(String.format(
+ "Ignore transaction caused by BlockRollbackException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
+ e.getMessage()), e);
+ throw e;
} catch (Exception e) {
// 抛弃发生处理异常的交易请求;
resp = discard(request, TransactionState.SYSTEM_ERROR);
LOGGER.error(String.format(
- "Discard transaction rollback caused by the system exception! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ "Ignore transaction caused by the system exception! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);
- responseList.add(resp);
- return resp;
}
+
+ responseList.add(resp);
+ return resp;
}
/**
@@ -186,6 +175,23 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
// 提交交易(事务);
result = TransactionState.SUCCESS;
txCtx.commit(result, operationResults);
+ } catch (TransactionRollbackException e) {
+ result = TransactionState.IGNORED_BY_TX_FULL_ROLLBACK;
+ txCtx.rollback();
+ LOGGER.error(String.format(
+ "Transaction was full rolled back! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
+ e.getMessage()), e);
+ } catch (BlockRollbackException e) {
+ result = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK;
+ txCtx.rollback();
+ LOGGER.error(
+ String.format("Transaction was rolled back! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ newBlockEditor.getBlockHeight(), request.getHash(),
+ request.getTransactionContent().getHash(), e.getMessage()),
+ e);
+ // 重新抛出由上层错误处理;
+ throw e;
} catch (LedgerException e) {
// TODO: 识别更详细的异常类型以及执行对应的处理;
result = TransactionState.LEDGER_ERROR;
@@ -198,14 +204,14 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
}
txCtx.discardAndCommit(result, operationResults);
LOGGER.error(String.format(
- "Transaction rollback caused by the ledger exception! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ "Due to ledger exception, the data changes resulting from the transaction will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);
} catch (Exception e) {
result = TransactionState.SYSTEM_ERROR;
txCtx.discardAndCommit(TransactionState.SYSTEM_ERROR, operationResults);
LOGGER.error(String.format(
- "Transaction rollback caused by the system exception! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ "Due to system exception, the data changes resulting from the transaction will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);
}
@@ -218,32 +224,6 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
return resp;
}
- private boolean verifyTxContent(TransactionRequest request) {
- TransactionContent txContent = request.getTransactionContent();
- if (!TxBuilder.verifyTxContentHash(txContent, txContent.getHash())) {
- return false;
- }
- DigitalSignature[] endpointSignatures = request.getEndpointSignatures();
- if (endpointSignatures != null) {
- for (DigitalSignature signature : endpointSignatures) {
- if (!TxRequestBuilder.verifyHashSignature(txContent.getHash(), signature.getDigest(),
- signature.getPubKey())) {
- return false;
- }
- }
- }
- DigitalSignature[] nodeSignatures = request.getNodeSignatures();
- if (nodeSignatures != null) {
- for (DigitalSignature signature : nodeSignatures) {
- if (!TxRequestBuilder.verifyHashSignature(txContent.getHash(), signature.getDigest(),
- signature.getPubKey())) {
- return false;
- }
- }
- }
- return true;
- }
-
/**
* 直接丢弃交易;
*
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditorTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditorTest.java
index 7ce6908b..c75b624a 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditorTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditorTest.java
@@ -138,7 +138,7 @@ public class LedgerEditorTest {
LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS);
- TransactionRequest genesisTxReq = genisisTxCtx.getRequestTX();
+ TransactionRequest genesisTxReq = genisisTxCtx.getTransactionRequest();
assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash());
assertEquals(0, tx.getBlockHeight());
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java
index 73e4a8c1..dfc17f24 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java
@@ -116,7 +116,8 @@ public class LedgerManagerTest {
assertEquals(0, genesisBlock.getHeight());
assertNotNull(genesisBlock.getHash());
assertNull(genesisBlock.getPreviousHash());
- assertEquals(ledgerHash, genesisBlock.getLedgerHash());
+ // 创世区块的账本hash 为null;创世区块本身的哈希就代表了账本的哈希;
+ assertNull(genesisBlock.getLedgerHash());
// 提交数据,写入存储;
ldgEdt.commit();
@@ -131,7 +132,8 @@ public class LedgerManagerTest {
LedgerBlock latestBlock = reloadLedgerRepo.getLatestBlock();
assertEquals(0, latestBlock.getHeight());
assertEquals(ledgerHash, latestBlock.getHash());
- assertEquals(ledgerHash, latestBlock.getLedgerHash());
+ // 创世区块的账本hash 为null;创世区块本身的哈希就代表了账本的哈希;
+ assertNull(latestBlock.getLedgerHash());
LedgerEditor editor1 = reloadLedgerRepo.createNextBlock();
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java
index 9fae875a..6101cdba 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java
@@ -24,6 +24,7 @@ import com.jd.blockchain.transaction.ConsensusParticipantData;
import com.jd.blockchain.transaction.LedgerInitSettingData;
import com.jd.blockchain.transaction.TransactionService;
import com.jd.blockchain.transaction.TxBuilder;
+import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.net.NetworkAddress;
@@ -124,6 +125,44 @@ public class LedgerTestUtils {
return txReqBuilder.buildRequest();
}
+
+ public static TransactionRequest createTxRequest_DataAccountReg(BlockchainKeypair dataAccountID, HashDigest ledgerHash,
+ BlockchainKeypair nodeKeypair, BlockchainKeypair... signers) {
+ TxBuilder txBuilder = new TxBuilder(ledgerHash);
+
+ txBuilder.dataAccounts().register(dataAccountID.getIdentity());
+
+ TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
+ if (signers != null) {
+ for (BlockchainKeypair signer : signers) {
+ txReqBuilder.signAsEndpoint(signer);
+ }
+ }
+ if (nodeKeypair != null) {
+ txReqBuilder.signAsNode(nodeKeypair);
+ }
+
+ return txReqBuilder.buildRequest();
+ }
+
+ public static TransactionRequest createTxRequest_DataAccountWrite(Bytes dataAccountAddress, String key, String value, long version, HashDigest ledgerHash,
+ BlockchainKeypair nodeKeypair, BlockchainKeypair... signers) {
+ TxBuilder txBuilder = new TxBuilder(ledgerHash);
+
+ txBuilder.dataAccount(dataAccountAddress).setText(key, value, version);
+
+ TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
+ if (signers != null) {
+ for (BlockchainKeypair signer : signers) {
+ txReqBuilder.signAsEndpoint(signer);
+ }
+ }
+ if (nodeKeypair != null) {
+ txReqBuilder.signAsNode(nodeKeypair);
+ }
+
+ return txReqBuilder.buildRequest();
+ }
/**
* @param userKeypair 要注册的用户key;
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleDataSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleDataSetTest.java
index fbb5eb09..ce571d71 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleDataSetTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleDataSetTest.java
@@ -58,6 +58,7 @@ public class MerkleDataSetTest {
mds.setValue("C", "C".getBytes(), -1);
mds.commit();
+ HashDigest root1 = mds.getRootHash();
// 1个KV项的存储KEY的数量= 1 + 1(保存SN) + Merkle节点数量;
// 所以:3 项;
@@ -68,6 +69,8 @@ public class MerkleDataSetTest {
mds.setValue("B", "B".getBytes(), 0);
mds.setValue("C", "C".getBytes(), 0);
mds.commit();
+ HashDigest root2 = mds.getRootHash();
+ assertNotEquals(root1, root2);
// Version changed only;仅仅增加 merkle 节点,此时 Merkle 树只有 1 层路径节点,因此只更新2个数据节点和 1
// 个路径节点;(注:版本值是在同一个 key 下按序列保存的);
@@ -76,6 +79,9 @@ public class MerkleDataSetTest {
mds.setValue("D", "DValue".getBytes(), -1);
mds.commit();
+ HashDigest root3 = mds.getRootHash();
+ assertNotEquals(root2, root3);
+ assertNotEquals(root1, root3);
// New key added, include 1 versioning kv, 1 sn key, 2 merkle nodes;
// String[] keys = StringUtils.toStringArray(storage.keySet());
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionBatchProcessorTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionBatchProcessorTest.java
index ea20f8b1..f857a6ad 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionBatchProcessorTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionBatchProcessorTest.java
@@ -12,6 +12,8 @@ import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
+import com.jd.blockchain.ledger.BytesValue;
+import com.jd.blockchain.ledger.DataAccountRegisterOperation;
import com.jd.blockchain.ledger.EndpointRequest;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInitSetting;
@@ -23,6 +25,7 @@ import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionResponse;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.UserRegisterOperation;
+import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerRepository;
@@ -44,6 +47,7 @@ public class TransactionBatchProcessorTest {
DataContractRegistry.register(EndpointRequest.class);
DataContractRegistry.register(TransactionResponse.class);
DataContractRegistry.register(UserRegisterOperation.class);
+ DataContractRegistry.register(DataAccountRegisterOperation.class);
}
private static final String LEDGER_KEY_PREFIX = "LDG://";
@@ -223,7 +227,7 @@ public class TransactionBatchProcessorTest {
.get(transactionRequest2.getTransactionContent().getHash());
LedgerTransaction tx3 = ledgerRepo.getTransactionSet()
.get(transactionRequest3.getTransactionContent().getHash());
-
+
assertNotNull(tx1);
assertEquals(TransactionState.SUCCESS, tx1.getExecutionState());
assertNotNull(tx2);
@@ -240,6 +244,131 @@ public class TransactionBatchProcessorTest {
assertTrue(existUser3);
}
+ @Test
+ public void testTxRollbackByVersionsConfliction() {
+ final MemoryKVStorage STORAGE = new MemoryKVStorage();
+
+ // 初始化账本到指定的存储库;
+ ledgerHash = initLedger(STORAGE, parti0, parti1, parti2, parti3);
+
+ // 加载账本;
+ LedgerManager ledgerManager = new LedgerManager();
+ LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, STORAGE);
+
+ // 验证参与方账户的存在;
+ LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock());
+ UserAccount user0 = previousBlockDataset.getUserAccountSet().getUser(parti0.getAddress());
+ assertNotNull(user0);
+ boolean partiRegistered = previousBlockDataset.getUserAccountSet().contains(parti0.getAddress());
+ assertTrue(partiRegistered);
+
+ // 注册数据账户;
+ // 生成新区块;
+ LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+
+ OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
+ TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset,
+ opReg, ledgerManager);
+
+ BlockchainKeypair dataAccountKeypair = BlockchainKeyGenerator.getInstance().generate();
+ TransactionRequest transactionRequest1 = LedgerTestUtils.createTxRequest_DataAccountReg(dataAccountKeypair,
+ ledgerHash, parti0, parti0);
+ TransactionResponse txResp1 = txbatchProcessor.schedule(transactionRequest1);
+ LedgerBlock newBlock = newBlockEditor.prepare();
+ newBlockEditor.commit();
+
+ assertEquals(TransactionState.SUCCESS, txResp1.getExecutionState());
+ DataAccount dataAccount = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress());
+ assertNotNull(dataAccount);
+
+ // 正确写入 KV 数据;
+ TransactionRequest txreq1 = LedgerTestUtils.createTxRequest_DataAccountWrite(dataAccountKeypair.getAddress(),
+ "K1", "V-1-1", -1, ledgerHash, parti0, parti0);
+ TransactionRequest txreq2 = LedgerTestUtils.createTxRequest_DataAccountWrite(dataAccountKeypair.getAddress(),
+ "K2", "V-2-1", -1, ledgerHash, parti0, parti0);
+ TransactionRequest txreq3 = LedgerTestUtils.createTxRequest_DataAccountWrite(dataAccountKeypair.getAddress(),
+ "K3", "V-3-1", -1, ledgerHash, parti0, parti0);
+ TransactionRequest txreq4 = LedgerTestUtils.createTxRequest_DataAccountWrite(dataAccountKeypair.getAddress(),
+ "K1", "V-1-2", 0, ledgerHash, parti0, parti0);
+
+ newBlockEditor = ledgerRepo.createNextBlock();
+ previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock());
+ txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset, opReg, ledgerManager);
+
+ txbatchProcessor.schedule(txreq1);
+ txbatchProcessor.schedule(txreq2);
+ txbatchProcessor.schedule(txreq3);
+ txbatchProcessor.schedule(txreq4);
+
+ newBlock = newBlockEditor.prepare();
+ newBlockEditor.commit();
+
+ BytesValue v1_0 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K1",
+ 0);
+ BytesValue v1_1 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K1",
+ 1);
+ BytesValue v2 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K2",
+ 0);
+ BytesValue v3 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K3",
+ 0);
+
+ assertNotNull(v1_0);
+ assertNotNull(v1_1);
+ assertNotNull(v2);
+ assertNotNull(v3);
+
+ assertEquals("V-1-1", v1_0.getValue().toUTF8String());
+ assertEquals("V-1-2", v1_1.getValue().toUTF8String());
+ assertEquals("V-2-1", v2.getValue().toUTF8String());
+ assertEquals("V-3-1", v3.getValue().toUTF8String());
+
+ // 提交多笔数据写入的交易,包含存在数据版本冲突的交易,验证交易是否正确回滚;
+
+ TransactionRequest txreq5 = LedgerTestUtils.createTxRequest_DataAccountWrite(dataAccountKeypair.getAddress(),
+ "K3", "V-3-2", 0, ledgerHash, parti0, parti0);
+ // 指定冲突的版本号,正确的应该是版本1;
+ TransactionRequest txreq6 = LedgerTestUtils.createTxRequest_DataAccountWrite(dataAccountKeypair.getAddress(),
+ "K1", "V-1-3", 0, ledgerHash, parti0, parti0);
+
+ newBlockEditor = ledgerRepo.createNextBlock();
+ previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock());
+ txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset, opReg, ledgerManager);
+
+ txbatchProcessor.schedule(txreq5);
+ txbatchProcessor.schedule(txreq6);
+
+ newBlock = newBlockEditor.prepare();
+ newBlockEditor.commit();
+
+ BytesValue v1 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K1");
+ v3 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K3");
+
+ long k1_version = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getDataVersion("K1");
+ assertEquals(1, k1_version);
+ long k3_version = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getDataVersion("K3");
+ assertEquals(1, k3_version);
+
+ assertNotNull(v1);
+ assertNotNull(v3);
+ assertEquals("V-1-2", v1.getValue().toUTF8String());
+ assertEquals("V-3-2", v3.getValue().toUTF8String());
+
+// // 验证正确性;
+// ledgerManager = new LedgerManager();
+// ledgerRepo = ledgerManager.register(ledgerHash, STORAGE);
+//
+// LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
+// assertEquals(newBlock.getHash(), latestBlock.getHash());
+// assertEquals(1, newBlock.getHeight());
+//
+// LedgerTransaction tx1 = ledgerRepo.getTransactionSet()
+// .get(transactionRequest1.getTransactionContent().getHash());
+//
+// assertNotNull(tx1);
+// assertEquals(TransactionState.SUCCESS, tx1.getExecutionState());
+
+ }
+
private HashDigest initLedger(MemoryKVStorage storage, BlockchainKeypair... partiKeys) {
// 创建初始化配置;
LedgerInitSetting initSetting = LedgerTestUtils.createLedgerInitSetting(partiKeys);
@@ -269,7 +398,9 @@ public class TransactionBatchProcessorTest {
assertNotNull(block.getHash());
assertNull(block.getPreviousHash());
- assertEquals(block.getHash(), block.getLedgerHash());
+ // 创世区块的账本哈希为 null;
+ assertNull(block.getLedgerHash());
+ assertNotNull(block.getHash());
// 提交数据,写入存储;
ldgEdt.commit();
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockBody.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockBody.java
index ff8f3705..7c82b214 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockBody.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockBody.java
@@ -20,4 +20,7 @@ public interface BlockBody extends LedgerDataSnapshot{
@DataField(order=5, primitiveType = PrimitiveType.BYTES)
HashDigest getTransactionSetHash();
+
+ @DataField(order=6, primitiveType = PrimitiveType.INT64)
+ long getTimestamp();
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockRollbackException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockRollbackException.java
new file mode 100644
index 00000000..c64f9e42
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockRollbackException.java
@@ -0,0 +1,33 @@
+package com.jd.blockchain.ledger;
+
+public class BlockRollbackException extends LedgerException {
+
+ private static final long serialVersionUID = 3583192000738807503L;
+
+ private TransactionState state;
+
+ public BlockRollbackException(String message) {
+ this(TransactionState.SYSTEM_ERROR, message);
+ }
+
+ public BlockRollbackException(TransactionState state, String message) {
+ super(message);
+ assert TransactionState.SUCCESS != state;
+ this.state = state;
+ }
+
+ public BlockRollbackException(String message, Throwable cause) {
+ this(TransactionState.SYSTEM_ERROR, message, cause);
+ }
+
+ public BlockRollbackException(TransactionState state, String message, Throwable cause) {
+ super(message, cause);
+ assert TransactionState.SUCCESS != state;
+ this.state = state;
+ }
+
+ public TransactionState getState() {
+ return state;
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/IllegalTransactionException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/IllegalTransactionException.java
new file mode 100644
index 00000000..5a2bb5a1
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/IllegalTransactionException.java
@@ -0,0 +1,35 @@
+package com.jd.blockchain.ledger;
+
+public class IllegalTransactionException extends RuntimeException {
+
+ private static final long serialVersionUID = 6348921847690512944L;
+
+ private TransactionState txState;
+
+ public IllegalTransactionException(String message) {
+ super(message);
+ this.txState = TransactionState.SYSTEM_ERROR;
+ }
+
+ public IllegalTransactionException(String message, TransactionState txState) {
+ super(message);
+ assert TransactionState.SUCCESS != txState;
+ this.txState = txState;
+ }
+
+ public IllegalTransactionException(String message, Throwable cause) {
+ super(message, cause);
+ this.txState = TransactionState.SYSTEM_ERROR;
+ }
+
+ public IllegalTransactionException(String message, Throwable cause, TransactionState txState) {
+ super(message, cause);
+ assert TransactionState.SUCCESS != txState;
+ this.txState = txState;
+ }
+
+ public TransactionState getTxState() {
+ return txState;
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java
index 5ffa8739..0c227ab5 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java
@@ -40,6 +40,6 @@ public interface TransactionContentBody {
* @return
*/
@DataField(order = 3, primitiveType = PrimitiveType.INT64)
- long getTime();
+ long getTimestamp();
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionException.java
deleted file mode 100644
index c88f0792..00000000
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionException.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.jd.blockchain.ledger;
-
-public class TransactionException extends Exception {
-
- private static final long serialVersionUID = 3583192000738807503L;
-
- private TransactionState state;
-
- public TransactionException(TransactionState state) {
- this.state = state;
- }
-
- public TransactionException(TransactionState state, String message) {
- super(message);
- this.state = state;
- }
-
- public TransactionState getState() {
- return state;
- }
-
-}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRollbackException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRollbackException.java
new file mode 100644
index 00000000..7694d898
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRollbackException.java
@@ -0,0 +1,16 @@
+package com.jd.blockchain.ledger;
+
+public class TransactionRollbackException extends RuntimeException {
+
+
+ private static final long serialVersionUID = -1223140447229570029L;
+
+ public TransactionRollbackException(String message) {
+ super(message);
+ }
+
+ public TransactionRollbackException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java
index 8483f84d..6955eb94 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java
@@ -20,39 +20,58 @@ public enum TransactionState {
SUCCESS((byte) 0),
/**
- * 共识错误;
+ * 账本错误;
*/
- CONSENSUS_ERROR((byte) 1),
+ LEDGER_ERROR((byte) 0x01),
/**
- * 账本错误;
+ * 数据账户不存在;
+ */
+ DATA_ACCOUNT_DOES_NOT_EXIST((byte) 0x02),
+
+ /**
+ * 用户不存在;
+ */
+ USER_DOES_NOT_EXIST((byte) 0x03),
+
+ /**
+ * 合约不存在;
*/
- LEDGER_ERROR((byte) 2),
+ CONTRACT_DOES_NOT_EXIST((byte) 0x04),
/**
* 由于在错误的账本上执行交易而被丢弃;
*/
- DISCARD_BY_WRONG_LEDGER((byte) 3),
+ IGNORED_BY_WRONG_LEDGER((byte) 0x40),
/**
* 由于交易内容的验签失败而丢弃;
*/
- DISCARD_BY_WRONG_CONTENT_SIGNATURE((byte) 4),
+ IGNORED_BY_WRONG_CONTENT_SIGNATURE((byte) 0x41),
/**
- * 数据账户不存在;
+ * 由于交易内容的验签失败而丢弃;
*/
- DATA_ACCOUNT_DOES_NOT_EXIST((byte) 5),
-
+ IGNORED_BY_CONFLICTING_STATE((byte) 0x42),
+
/**
- * 用户不存在;
+ * 由于交易的整体回滚而丢弃;
+ *
+ *
+ * 注: “整体回滚”是指把交易引入的数据更改以及交易记录本身全部都回滚;
+ * “部分回滚”是指把交易引入的数据更改回滚了,但是交易记录本身以及相应的“交易结果({@link TransactionState})”都会提交;
*/
- USER_DOES_NOT_EXIST((byte) 6),
-
+ IGNORED_BY_TX_FULL_ROLLBACK((byte) 0x43),
+
/**
- * 合约不存在;
+ * 由于区块的整体回滚而丢弃;
+ *
+ *
+ * 注: “整体回滚”是指把交易引入的数据更改以及交易记录本身全部都回滚;
+ *
+ * “部分回滚”是指把交易引入的数据更改回滚了,但是交易记录本身以及相应的“交易结果({@link TransactionState})”都会提交;
*/
- CONTRACT_DOES_NOT_EXIST((byte) 6),
+ IGNORED_BY_BLOCK_FULL_ROLLBACK((byte) 0x44),
/**
* 系统错误;
@@ -62,7 +81,12 @@ public enum TransactionState {
/**
* 超时;
*/
- TIMEOUT((byte) 0x81);
+ TIMEOUT((byte) 0x81),
+
+ /**
+ * 共识错误;
+ */
+ CONSENSUS_ERROR((byte) 0x82);
@EnumField(type = PrimitiveType.INT8)
public final byte CODE;
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxContentBlob.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxContentBlob.java
index c03f1cc7..7413a5ff 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxContentBlob.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxContentBlob.java
@@ -84,7 +84,7 @@ public class TxContentBlob implements TransactionContent {
}
@Override
- public long getTime() {
+ public long getTimestamp() {
return time;
}
diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVStorage.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVStorage.java
index f9d859ff..711606d3 100644
--- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVStorage.java
+++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVStorage.java
@@ -59,8 +59,8 @@ public interface VersioningKVStorage extends BatchStorageService {
/**
* Update the value of the key;
*
- * If key exist, and the specified version equals to latest , then the value is
- * updated and version is increased by 1;
+ * If key exist, and the specified version equals to it's latest version, then the value will be
+ * updated and version will be increased by 1;
* If key not exist, and the specified version is -1, then the value will be
* created and initialized it's version by 0;
*