getHeaders();
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
index 69dfac2c..19c76463 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
@@ -1,81 +1,72 @@
package com.jd.blockchain.ledger.core;
-import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
-import com.jd.blockchain.ledger.BytesData;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.ContractInfo;
-import com.jd.blockchain.ledger.MerkleProof;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.utils.Bytes;
-public class ContractAccount implements ContractInfo {
+public class ContractAccount extends AccountDecorator implements ContractInfo {
- private static final Bytes CONTRACT_INFO_PREFIX = Bytes.fromString("INFO" + LedgerConsts.KEY_SEPERATOR);
+ private static final String CONTRACT_INFO_PREFIX = "INFO" + LedgerConsts.KEY_SEPERATOR;
- private static final Bytes CHAIN_CODE_KEY = Bytes.fromString("CHAIN-CODE");
+ private static final String CHAIN_CODE_KEY = "CHAIN-CODE";
- private MerkleAccount accBase;
-
- public ContractAccount(MerkleAccount accBase) {
- this.accBase = accBase;
+ public ContractAccount(CompositeAccount mklAccount) {
+ super(mklAccount);
}
@Override
public Bytes getAddress() {
- return accBase.getAddress();
+ return getID().getAddress();
}
@Override
public PubKey getPubKey() {
- return accBase.getPubKey();
- }
-
- @Override
- public HashDigest getRootHash() {
- return accBase.getRootHash();
+ return getID().getPubKey();
}
- public MerkleProof getChaincodeProof() {
- return accBase.getProof(CHAIN_CODE_KEY);
- }
-
- public MerkleProof getPropertyProof(Bytes key) {
- return accBase.getProof(encodePropertyKey(key));
- }
+// public MerkleProof getChaincodeProof() {
+// return getHeaders().getProof(CHAIN_CODE_KEY);
+// }
+//
+// public MerkleProof getPropertyProof(Bytes key) {
+// return getHeaders().getProof(encodePropertyKey(key));
+// }
public long setChaincode(byte[] chaincode, long version) {
- BytesValue bytesValue = BytesData.fromBytes(chaincode);
- return accBase.setBytes(CHAIN_CODE_KEY, bytesValue, version);
+ TypedValue bytesValue = TypedValue.fromBytes(chaincode);
+ return getHeaders().setValue(CHAIN_CODE_KEY, bytesValue, version);
}
public byte[] getChainCode() {
- return accBase.getBytes(CHAIN_CODE_KEY).getValue().toBytes();
+ return getHeaders().getValue(CHAIN_CODE_KEY).getBytes().toBytes();
}
public byte[] getChainCode(long version) {
- return accBase.getBytes(CHAIN_CODE_KEY, version).getValue().toBytes();
+ return getHeaders().getValue(CHAIN_CODE_KEY, version).getBytes().toBytes();
}
public long getChaincodeVersion() {
- return accBase.getVersion(CHAIN_CODE_KEY);
+ return getHeaders().getVersion(CHAIN_CODE_KEY);
}
- public long setProperty(Bytes key, String value, long version) {
- BytesValue bytesValue = BytesData.fromText(value);
- return accBase.setBytes(encodePropertyKey(key), bytesValue, version);
+ public long setProperty(String key, String value, long version) {
+ TypedValue bytesValue = TypedValue.fromText(value);
+ return getHeaders().setValue(encodePropertyKey(key), bytesValue, version);
}
- public String getProperty(Bytes key) {
- BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key));
- return BytesData.toText(bytesValue);
+ public String getProperty(String key) {
+ BytesValue bytesValue = getHeaders().getValue(encodePropertyKey(key));
+ return TypedValue.wrap(bytesValue).stringValue();
}
- public String getProperty(Bytes key, long version) {
- BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key), version);
- return BytesData.toText(bytesValue);
+ public String getProperty(String key, long version) {
+ BytesValue bytesValue = getHeaders().getValue(encodePropertyKey(key), version);
+ return TypedValue.wrap(bytesValue).stringValue();
}
- private Bytes encodePropertyKey(Bytes key) {
+ private String encodePropertyKey(String key) {
return CONTRACT_INFO_PREFIX.concat(key);
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java
index 5f4c7855..c4ee0408 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java
@@ -2,7 +2,7 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
-import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.MerkleProof;
@@ -17,17 +17,18 @@ public class ContractAccountSet implements Transactional, ContractAccountQuery {
public ContractAccountSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage,
VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) {
- accountSet = new MerkleAccountSet(cryptoSetting, prefix, exStorage, verStorage, accessPolicy);
+ accountSet = new MerkleAccountSet(cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage, accessPolicy);
}
public ContractAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String prefix,
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly,
AccountAccessPolicy accessPolicy) {
- accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy);
+ accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage,
+ readonly, accessPolicy);
}
@Override
- public AccountHeader[] getHeaders(int fromIndex, int count) {
+ public BlockchainIdentity[] getHeaders(int fromIndex, int count) {
return accountSet.getHeaders(fromIndex, count);
}
@@ -66,7 +67,7 @@ public class ContractAccountSet implements Transactional, ContractAccountQuery {
@Override
public ContractAccount getAccount(Bytes address) {
- MerkleAccount accBase = accountSet.getAccount(address);
+ CompositeAccount accBase = accountSet.getAccount(address);
return new ContractAccount(accBase);
}
@@ -77,7 +78,7 @@ public class ContractAccountSet implements Transactional, ContractAccountQuery {
@Override
public ContractAccount getAccount(Bytes address, long version) {
- MerkleAccount accBase = accountSet.getAccount(address, version);
+ CompositeAccount accBase = accountSet.getAccount(address, version);
return new ContractAccount(accBase);
}
@@ -92,7 +93,7 @@ public class ContractAccountSet implements Transactional, ContractAccountQuery {
*/
public ContractAccount deploy(Bytes address, PubKey pubKey, DigitalSignature addressSignature, byte[] chaincode) {
// TODO: 校验和记录合约地址签名;
- MerkleAccount accBase = accountSet.register(address, pubKey);
+ CompositeAccount accBase = accountSet.register(address, pubKey);
ContractAccount contractAcc = new ContractAccount(accBase);
contractAcc.setChaincode(chaincode, -1);
return contractAcc;
@@ -107,7 +108,7 @@ public class ContractAccountSet implements Transactional, ContractAccountQuery {
* @return 返回链码的新版本号;
*/
public long update(Bytes address, byte[] chaincode, long version) {
- MerkleAccount accBase = accountSet.getAccount(address);
+ CompositeAccount accBase = accountSet.getAccount(address);
ContractAccount contractAcc = new ContractAccount(accBase);
return contractAcc.setChaincode(chaincode, version);
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java
index afaab416..4814cdf6 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java
@@ -1,268 +1,234 @@
package com.jd.blockchain.ledger.core;
-import com.jd.blockchain.binaryproto.BinaryProtocol;
-import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.crypto.PubKey;
-import com.jd.blockchain.ledger.AccountHeader;
-import com.jd.blockchain.ledger.BytesData;
-import com.jd.blockchain.ledger.BytesValue;
-import com.jd.blockchain.ledger.KVDataEntry;
-import com.jd.blockchain.ledger.KVDataObject;
-import com.jd.blockchain.ledger.MerkleProof;
-import com.jd.blockchain.utils.Bytes;
-
-public class DataAccount implements AccountHeader, MerkleProvable {
-
- private MerkleAccount baseAccount;
-
- public DataAccount(MerkleAccount accBase) {
- this.baseAccount = accBase;
- }
-
- @Override
- public Bytes getAddress() {
- return baseAccount.getAddress();
- }
-
- @Override
- public PubKey getPubKey() {
- return baseAccount.getPubKey();
- }
-
- @Override
- public HashDigest getRootHash() {
- return baseAccount.getRootHash();
- }
-
- /**
- * 返回指定数据的存在性证明;
- */
- @Override
- public MerkleProof getProof(Bytes key) {
- return baseAccount.getProof(key);
- }
+public class DataAccount extends AccountDecorator {
+
+ public DataAccount(CompositeAccount mklAccount) {
+ super(mklAccount);
+ }
+
+// /**
+// * Create or update the value associated the specified key if the version
+// * checking is passed.
+// *
+// * The value of the key will be updated only if it's latest version equals the
+// * specified version argument.
+// * If the key doesn't exist, the version checking will be ignored, and key will
+// * be created with a new sequence number as id.
+// * It also could specify the version argument to -1 to ignore the version
+// * checking.
+// *
+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// *
+// * @param key The key of data;
+// * @param value The value of data;
+// * @param version The expected version of the key.
+// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then
+// * return -1;
+// */
+// public long setBytes(Bytes key, BytesValue value, long version) {
+// return super.getDataset().setValue(key, value, version);
+// }
+
+//
+// /**
+// * Create or update the value associated the specified key if the version
+// * checking is passed.
+// *
+// * The value of the key will be updated only if it's latest version equals the
+// * specified version argument.
+// * If the key doesn't exist, the version checking will be ignored, and key will
+// * be created with a new sequence number as id.
+// * It also could specify the version argument to -1 to ignore the version
+// * checking.
+// *
+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// *
+// * @param key The key of data;
+// * @param value The value of data;
+// * @param version The expected version of the key.
+// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then
+// * return -1;
+// */
+// public long setBytes(Bytes key, String value, long version) {
+// BytesValue bytesValue = TypedValue.fromText(value);
+// return baseAccount.setValue(key, bytesValue, version);
+// }
+//
+// /**
+// * Create or update the value associated the specified key if the version
+// * checking is passed.
+// *
+// * The value of the key will be updated only if it's latest version equals the
+// * specified version argument.
+// * If the key doesn't exist, the version checking will be ignored, and key will
+// * be created with a new sequence number as id.
+// * It also could specify the version argument to -1 to ignore the version
+// * checking.
+// *
+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// *
+// * @param key The key of data;
+// * @param value The value of data;
+// * @param version The expected version of the key.
+// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then
+// * return -1;
+// */
+// public long setBytes(Bytes key, byte[] value, long version) {
+// BytesValue bytesValue = TypedValue.fromBytes(value);
+// return baseAccount.setValue(key, bytesValue, version);
+// }
+//
+// /**
+// * Return the latest version entry associated the specified key; If the key
+// * doesn't exist, then return -1;
+// *
+// * @param key
+// * @return
+// */
+// public long getDataVersion(String key) {
+// return baseAccount.getVersion(Bytes.fromString(key));
+// }
+//
+// /**
+// * Return the latest version entry associated the specified key; If the key
+// * doesn't exist, then return -1;
+// *
+// * @param key
+// * @return
+// */
+// public long getDataVersion(Bytes key) {
+// return baseAccount.getVersion(key);
+// }
+//
+// /**
+// * return the latest version's value;
+// *
+// * @param key
+// * @return return null if not exist;
+// */
+// public BytesValue getBytes(String key) {
+// return baseAccount.getValue(Bytes.fromString(key));
+// }
+//
+// /**
+// * return the latest version's value;
+// *
+// * @param key
+// * @return return null if not exist;
+// */
+// public BytesValue getBytes(Bytes key) {
+// return baseAccount.getValue(key);
+// }
+//
+// /**
+// * return the specified version's value;
+// *
+// * @param key
+// * @param version
+// * @return return null if not exist;
+// */
+// public BytesValue getBytes(String key, long version) {
+// return baseAccount.getValue(Bytes.fromString(key), version);
+// }
+//
+// /**
+// * return the specified version's value;
+// *
+// * @param key
+// * @param version
+// * @return return null if not exist;
+// */
+// public BytesValue getBytes(Bytes key, long version) {
+// return baseAccount.getValue(key, version);
+// }
-
- /**
- * Create or update the value associated the specified key if the version
- * checking is passed.
- *
- * The value of the key will be updated only if it's latest version equals the
- * specified version argument.
- * If the key doesn't exist, the version checking will be ignored, and key will
- * be created with a new sequence number as id.
- * It also could specify the version argument to -1 to ignore the version
- * checking.
- *
- * If updating is performed, the version of the key increase by 1.
- * If creating is performed, the version of the key initialize by 0.
- *
- * @param key The key of data;
- * @param value The value of data;
- * @param version The expected version of the key.
- * @return The new version of the key.
- * If the key is new created success, then return 0;
- * If the key is updated success, then return the new version;
- * If this operation fail by version checking or other reason, then
- * return -1;
- */
- public long setBytes(Bytes key, BytesValue value, long version) {
- return baseAccount.setBytes(key, value, version);
- }
-
- /**
- * Create or update the value associated the specified key if the version
- * checking is passed.
- *
- * The value of the key will be updated only if it's latest version equals the
- * specified version argument.
- * If the key doesn't exist, the version checking will be ignored, and key will
- * be created with a new sequence number as id.
- * It also could specify the version argument to -1 to ignore the version
- * checking.
- *
- * If updating is performed, the version of the key increase by 1.
- * If creating is performed, the version of the key initialize by 0.
- *
- * @param key The key of data;
- * @param value The value of data;
- * @param version The expected version of the key.
- * @return The new version of the key.
- * If the key is new created success, then return 0;
- * If the key is updated success, then return the new version;
- * If this operation fail by version checking or other reason, then
- * return -1;
- */
- public long setBytes(Bytes key, String value, long version) {
- BytesValue bytesValue = BytesData.fromText(value);
- return baseAccount.setBytes(key, bytesValue, version);
- }
-
- /**
- * Create or update the value associated the specified key if the version
- * checking is passed.
- *
- * The value of the key will be updated only if it's latest version equals the
- * specified version argument.
- * If the key doesn't exist, the version checking will be ignored, and key will
- * be created with a new sequence number as id.
- * It also could specify the version argument to -1 to ignore the version
- * checking.
- *
- * If updating is performed, the version of the key increase by 1.
- * If creating is performed, the version of the key initialize by 0.
- *
- * @param key The key of data;
- * @param value The value of data;
- * @param version The expected version of the key.
- * @return The new version of the key.
- * If the key is new created success, then return 0;
- * If the key is updated success, then return the new version;
- * If this operation fail by version checking or other reason, then
- * return -1;
- */
- public long setBytes(Bytes key, byte[] value, long version) {
- BytesValue bytesValue = BytesData.fromBytes(value);
- return baseAccount.setBytes(key, bytesValue, version);
- }
-
- /**
- * Return the latest version entry associated the specified key; If the key
- * doesn't exist, then return -1;
- *
- * @param key
- * @return
- */
- public long getDataVersion(String key) {
- return baseAccount.getVersion(Bytes.fromString(key));
- }
-
- /**
- * Return the latest version entry associated the specified key; If the key
- * doesn't exist, then return -1;
- *
- * @param key
- * @return
- */
- public long getDataVersion(Bytes key) {
- return baseAccount.getVersion(key);
- }
-
- /**
- * return the latest version's value;
- *
- * @param key
- * @return return null if not exist;
- */
- public BytesValue getBytes(String key) {
- return baseAccount.getBytes(Bytes.fromString(key));
- }
-
- /**
- * return the latest version's value;
- *
- * @param key
- * @return return null if not exist;
- */
- public BytesValue getBytes(Bytes key) {
- return baseAccount.getBytes(key);
- }
-
- /**
- * return the specified version's value;
- *
- * @param key
- * @param version
- * @return return null if not exist;
- */
- public BytesValue getBytes(String key, long version) {
- return baseAccount.getBytes(Bytes.fromString(key), version);
- }
-
- /**
- * return the specified version's value;
- *
- * @param key
- * @param version
- * @return return null if not exist;
- */
- public BytesValue getBytes(Bytes key, long version) {
- return baseAccount.getBytes(key, version);
- }
- /**
- * @param key
- * @param version
- * @return
- */
- public KVDataEntry getDataEntry(String key, long version) {
- return getDataEntry(Bytes.fromString(key), version);
- }
- /**
- * @param key
- * @param version
- * @return
- */
- public KVDataEntry getDataEntry(Bytes key, long version) {
- BytesValue value = baseAccount.getBytes(key, version);
- if (value == null) {
- return new KVDataObject(key.toUTF8String(), -1, null);
- }else {
- return new KVDataObject(key.toUTF8String(), version, value);
- }
- }
-
- /**
- * return the specified index's KVDataEntry;
- *
- * @param fromIndex
- * @param count
- * @return return null if not exist;
- */
-
- public KVDataEntry[] getDataEntries(int fromIndex, int count) {
- if (count == 0 || getDataEntriesTotalCount() == 0) {
- return null;
- }
-
- if (count == -1 || count > getDataEntriesTotalCount()) {
- fromIndex = 0;
- count = (int)getDataEntriesTotalCount();
- }
-
- if (fromIndex < 0 || fromIndex > getDataEntriesTotalCount() - 1) {
- fromIndex = 0;
- }
-
- KVDataEntry[] kvDataEntries = new KVDataEntry[count];
- byte[] value;
- String key;
- long ver;
- for (int i = 0; i < count; i++) {
- value = baseAccount.dataset.getValuesAtIndex(fromIndex);
- key = baseAccount.dataset.getKeyAtIndex(fromIndex);
- ver = baseAccount.dataset.getVersion(key);
- BytesValue decodeData = BinaryProtocol.decode(value);
- kvDataEntries[i] = new KVDataObject(key, ver, decodeData);
- fromIndex++;
- }
-
- return kvDataEntries;
- }
-
- /**
- * return the dataAccount's kv total count;
- *
- * @param
- * @param
- * @return return total count;
- */
- public long getDataEntriesTotalCount() {
- if(baseAccount == null){
- return 0;
- }
- return baseAccount.dataset.getDataCount();
- }
+// /**
+// * @param key
+// * @param version
+// * @return
+// */
+// public KVDataEntry getDataEntry(String key, long version) {
+// return getDataEntry(Bytes.fromString(key), version);
+// }
+//
+// /**
+// * @param key
+// * @param version
+// * @return
+// */
+// public KVDataEntry getDataEntry(Bytes key, long version) {
+// BytesValue value = baseAccount.getValue(key, version);
+// if (value == null) {
+// return new KVDataObject(key.toUTF8String(), -1, null);
+// }else {
+// return new KVDataObject(key.toUTF8String(), version, value);
+// }
+// }
+//
+// /**
+// * return the specified index's KVDataEntry;
+// *
+// * @param fromIndex
+// * @param count
+// * @return return null if not exist;
+// */
+//
+// public KVDataEntry[] getDataEntries(int fromIndex, int count) {
+// if (count == 0 || getDataEntriesTotalCount() == 0) {
+// return null;
+// }
+//
+// if (count == -1 || count > getDataEntriesTotalCount()) {
+// fromIndex = 0;
+// count = (int)getDataEntriesTotalCount();
+// }
+//
+// if (fromIndex < 0 || fromIndex > getDataEntriesTotalCount() - 1) {
+// fromIndex = 0;
+// }
+//
+// KVDataEntry[] kvDataEntries = new KVDataEntry[count];
+// byte[] value;
+// String key;
+// long ver;
+// for (int i = 0; i < count; i++) {
+// value = baseAccount.dataset.getValuesAtIndex(fromIndex);
+// key = baseAccount.dataset.getKeyAtIndex(fromIndex);
+// ver = baseAccount.dataset.getVersion(key);
+// BytesValue decodeData = BinaryProtocol.decode(value);
+// kvDataEntries[i] = new KVDataObject(key, ver, decodeData);
+// fromIndex++;
+// }
+//
+// return kvDataEntries;
+// }
+//
+// /**
+// * return the dataAccount's kv total count;
+// *
+// * @param
+// * @param
+// * @return return total count;
+// */
+// public long getDataEntriesTotalCount() {
+// if(baseAccount == null){
+// return 0;
+// }
+// return baseAccount.dataset.getDataCount();
+// }
}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java
index f693211b..0f849c1d 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java
@@ -2,7 +2,7 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
-import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.MerkleProof;
@@ -17,17 +17,18 @@ public class DataAccountSet implements Transactional, DataAccountQuery {
public DataAccountSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage,
VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) {
- accountSet = new MerkleAccountSet(cryptoSetting, prefix, exStorage, verStorage, accessPolicy);
+ accountSet = new MerkleAccountSet(cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage, accessPolicy);
}
public DataAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String prefix,
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly,
AccountAccessPolicy accessPolicy) {
- accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy);
+ accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage,
+ readonly, accessPolicy);
}
@Override
- public AccountHeader[] getHeaders(int fromIndex, int count) {
+ public BlockchainIdentity[] getHeaders(int fromIndex, int count) {
return accountSet.getHeaders(fromIndex, count);
}
@@ -64,7 +65,7 @@ public class DataAccountSet implements Transactional, DataAccountQuery {
public DataAccount register(Bytes address, PubKey pubKey, DigitalSignature addressSignature) {
// TODO: 未实现对地址签名的校验和记录;
- MerkleAccount accBase = accountSet.register(address, pubKey);
+ CompositeAccount accBase = accountSet.register(address, pubKey);
return new DataAccount(accBase);
}
@@ -82,7 +83,7 @@ public class DataAccountSet implements Transactional, DataAccountQuery {
*/
@Override
public DataAccount getAccount(Bytes address) {
- MerkleAccount accBase = accountSet.getAccount(address);
+ CompositeAccount accBase = accountSet.getAccount(address);
if (accBase == null) {
return null;
}
@@ -91,7 +92,7 @@ public class DataAccountSet implements Transactional, DataAccountQuery {
@Override
public DataAccount getAccount(Bytes address, long version) {
- MerkleAccount accBase = accountSet.getAccount(address, version);
+ CompositeAccount accBase = accountSet.getAccount(address, version);
return new DataAccount(accBase);
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyAccountSet.java
index 879bf702..8cfdd7fc 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyAccountSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyAccountSet.java
@@ -1,13 +1,13 @@
package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.utils.Bytes;
public class EmptyAccountSet implements AccountQuery {
- private static final AccountHeader[] EMPTY = {};
+ private static final BlockchainIdentity[] EMPTY = {};
@Override
public HashDigest getRootHash() {
@@ -20,7 +20,7 @@ public class EmptyAccountSet implements AccountQuery {
}
@Override
- public AccountHeader[] getHeaders(int fromIndex, int count) {
+ public BlockchainIdentity[] getHeaders(int fromIndex, int count) {
return EMPTY;
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenericAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenericAccountSet.java
new file mode 100644
index 00000000..372163e1
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenericAccountSet.java
@@ -0,0 +1,92 @@
+//package com.jd.blockchain.ledger.core;
+//
+//import com.jd.blockchain.crypto.HashDigest;
+//import com.jd.blockchain.ledger.AccountHeader;
+//import com.jd.blockchain.ledger.CryptoSetting;
+//import com.jd.blockchain.ledger.MerkleProof;
+//import com.jd.blockchain.storage.service.ExPolicyKVStorage;
+//import com.jd.blockchain.storage.service.VersioningKVStorage;
+//import com.jd.blockchain.utils.Bytes;
+//import com.jd.blockchain.utils.Transactional;
+//
+//public class GenericAccountSet> implements AccountQuery, Transactional {
+//
+// private Class headerType;
+//
+// private MerkleAccountSet merkleAccountSet;
+//
+// public GenericAccountSet(Class headerType, CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage,
+// VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) {
+// this(headerType, null, cryptoSetting, keyPrefix, exStorage, verStorage, false, accessPolicy);
+// }
+//
+// public GenericAccountSet(Class headerType, HashDigest rootHash, CryptoSetting cryptoSetting, String keyPrefix,
+// ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly,
+// AccountAccessPolicy accessPolicy) {
+// this.headerType = headerType;
+// this.merkleAccountSet = new MerkleAccountSet(rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly, accessPolicy);
+// }
+//
+// @Override
+// public MerkleProof getProof(Bytes address) {
+// return merkleAccountSet.getProof(address);
+// }
+//
+// @Override
+// public HashDigest getRootHash() {
+// return merkleAccountSet.getRootHash();
+// }
+//
+// @Override
+// public boolean isUpdated() {
+// return merkleAccountSet.isUpdated();
+// }
+//
+// @Override
+// public void commit() {
+// merkleAccountSet.commit();
+// }
+//
+// @Override
+// public void cancel() {
+// merkleAccountSet.cancel();
+// }
+//
+// @Override
+// public H[] getHeaders(int fromIndex, int count) {
+// merkleAccountSet.getHeaders(fromIndex, count)
+// return null;
+// }
+//
+// @Override
+// public long getTotal() {
+// // TODO Auto-generated method stub
+// return 0;
+// }
+//
+// @Override
+// public boolean contains(Bytes address) {
+// // TODO Auto-generated method stub
+// return false;
+// }
+//
+// @Override
+// public T getAccount(String address) {
+// // TODO Auto-generated method stub
+// return null;
+// }
+//
+// @Override
+// public T getAccount(Bytes address) {
+// // TODO Auto-generated method stub
+// return null;
+// }
+//
+// @Override
+// public T getAccount(Bytes address, long version) {
+// // TODO Auto-generated method stub
+// return null;
+// }
+//
+//
+//}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/HashDigestList.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/HashDigestList.java
new file mode 100644
index 00000000..e2a74de7
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/HashDigestList.java
@@ -0,0 +1,42 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.HashProof;
+
+/**
+ *
+ * @author huanghaiquan
+ *
+ */
+public class HashDigestList implements HashProof {
+
+ private List proofs = new ArrayList();
+
+ public HashDigestList() {
+ }
+
+ public HashDigestList(HashProof proof) {
+ concat(proof);
+ }
+
+ public void concat(HashProof proof) {
+ int levels = proof.getLevels();
+ for (int i = levels; i > -1; i--) {
+ proofs.add(proof.getHash(i));
+ }
+ }
+
+ @Override
+ public int getLevels() {
+ return proofs.size();
+ }
+
+ @Override
+ public HashDigest getHash(int level) {
+ return proofs.get(level);
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/HashProvable.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/HashProvable.java
new file mode 100644
index 00000000..88da19ae
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/HashProvable.java
@@ -0,0 +1,10 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.ledger.HashProof;
+import com.jd.blockchain.utils.Bytes;
+
+public interface HashProvable {
+
+ HashProof getProof(Bytes key);
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java
index 41e70138..c377a56a 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java
@@ -5,11 +5,12 @@ import java.util.List;
import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.ContractInfo;
-import com.jd.blockchain.ledger.KVDataEntry;
-import com.jd.blockchain.ledger.KVDataObject;
+import com.jd.blockchain.ledger.TypedKVEntry;
+import com.jd.blockchain.ledger.TypedValue;
+import com.jd.blockchain.ledger.TypedKVData;
import com.jd.blockchain.ledger.KVDataVO;
import com.jd.blockchain.ledger.KVInfoVO;
import com.jd.blockchain.ledger.LedgerAdminInfo;
@@ -22,22 +23,25 @@ import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.UserInfo;
import com.jd.blockchain.transaction.BlockchainQueryService;
+import com.jd.blockchain.utils.ArrayUtils;
import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.DataEntry;
+import com.jd.blockchain.utils.DataIterator;
import com.jd.blockchain.utils.QueryUtil;
public class LedgerQueryService implements BlockchainQueryService {
- private static final KVDataEntry[] EMPTY_ENTRIES = new KVDataEntry[0];
-
+ private static final TypedKVEntry[] EMPTY_ENTRIES = new TypedKVEntry[0];
+
private HashDigest[] ledgerHashs;
private LedgerQuery ledger;
public LedgerQueryService(LedgerQuery ledger) {
this.ledger = ledger;
- this.ledgerHashs = new HashDigest[] {ledger.getHash()};
+ this.ledgerHashs = new HashDigest[] { ledger.getHash() };
}
-
+
private void checkLedgerHash(HashDigest ledgerHash) {
if (!ledgerHashs[0].equals(ledgerHash)) {
throw new LedgerException("Unsupport cross chain query!");
@@ -58,7 +62,7 @@ public class LedgerQueryService implements BlockchainQueryService {
ledgerInfo.setLatestBlockHeight(ledger.getLatestBlockHeight());
return ledgerInfo;
}
-
+
@Override
public LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash) {
checkLedgerHash(ledgerHash);
@@ -270,15 +274,15 @@ public class LedgerQueryService implements BlockchainQueryService {
}
@Override
- public AccountHeader getDataAccount(HashDigest ledgerHash, String address) {
+ public BlockchainIdentity getDataAccount(HashDigest ledgerHash, String address) {
checkLedgerHash(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
- return dataAccountSet.getAccount(Bytes.fromBase58(address));
+ return dataAccountSet.getAccount(Bytes.fromBase58(address)).getID();
}
@Override
- public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) {
+ public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) {
if (keys == null || keys.length == 0) {
return EMPTY_ENTRIES;
}
@@ -287,25 +291,26 @@ public class LedgerQueryService implements BlockchainQueryService {
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address));
- KVDataEntry[] entries = new KVDataEntry[keys.length];
+
+ TypedKVEntry[] entries = new TypedKVEntry[keys.length];
long ver;
for (int i = 0; i < entries.length; i++) {
final String currKey = keys[i];
- ver = dataAccount == null ? -1 : dataAccount.getDataVersion(Bytes.fromString(currKey));
+ ver = dataAccount == null ? -1 : dataAccount.getDataset().getVersion(currKey);
if (ver < 0) {
- entries[i] = new KVDataObject(currKey, -1, null);
+ entries[i] = new TypedKVData(currKey, -1, null);
} else {
- BytesValue value = dataAccount.getBytes(Bytes.fromString(currKey), ver);
- entries[i] = new KVDataObject(currKey, ver, value);
+ BytesValue value = dataAccount.getDataset().getValue(currKey, ver);
+ entries[i] = new TypedKVData(currKey, ver, value);
}
}
return entries;
}
- public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
+ public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
// parse kvInfoVO;
List keyList = new ArrayList<>();
List versionList = new ArrayList<>();
@@ -335,22 +340,22 @@ public class LedgerQueryService implements BlockchainQueryService {
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address));
- KVDataEntry[] entries = new KVDataEntry[keys.length];
+ TypedKVEntry[] entries = new TypedKVEntry[keys.length];
long ver = -1;
for (int i = 0; i < entries.length; i++) {
// ver = dataAccount.getDataVersion(Bytes.fromString(keys[i]));
// dataAccount.getBytes(Bytes.fromString(keys[i]),1);
ver = versions[i];
if (ver < 0) {
- entries[i] = new KVDataObject(keys[i], -1, null);
+ entries[i] = new TypedKVData(keys[i], -1, null);
} else {
- if (dataAccount.getDataEntriesTotalCount() == 0
- || dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null) {
+ if (dataAccount.getDataset().getDataCount() == 0
+ || dataAccount.getDataset().getValue(keys[i], ver) == null) {
// is the address is not exist; the result is null;
- entries[i] = new KVDataObject(keys[i], -1, null);
+ entries[i] = new TypedKVData(keys[i], -1, null);
} else {
- BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver);
- entries[i] = new KVDataObject(keys[i], ver, value);
+ BytesValue value = dataAccount.getDataset().getValue(keys[i], ver);
+ entries[i] = new TypedKVData(keys[i], ver, value);
}
}
}
@@ -359,14 +364,22 @@ public class LedgerQueryService implements BlockchainQueryService {
}
@Override
- public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {
+ public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {
checkLedgerHash(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address));
- int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataEntriesTotalCount());
- return dataAccount.getDataEntries(pages[0], pages[1]);
+// int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataset().getDataCount());
+// return dataAccount.getDataset().getDataEntry(key, version).getDataEntries(pages[0], pages[1]);
+
+ DataIterator iterator = dataAccount.getDataset().iterator();
+ iterator.skip(fromIndex);
+ DataEntry[] dataEntries = iterator.next(count);
+
+ TypedKVEntry[] typedKVEntries = ArrayUtils.castTo(dataEntries, TypedKVEntry.class,
+ e -> e == null ? null : new TypedKVData(e.getKey(), e.getVersion(), e.getValue()));
+ return typedKVEntries;
}
@Override
@@ -376,7 +389,7 @@ public class LedgerQueryService implements BlockchainQueryService {
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address));
- return dataAccount.getDataEntriesTotalCount();
+ return dataAccount.getDataset().getDataCount();
}
@Override
@@ -388,7 +401,7 @@ public class LedgerQueryService implements BlockchainQueryService {
}
@Override
- public AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count) {
+ public BlockchainIdentity[] getUsers(HashDigest ledgerHash, int fromIndex, int count) {
checkLedgerHash(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
UserAccountQuery userAccountSet = ledger.getUserAccountSet(block);
@@ -397,7 +410,7 @@ public class LedgerQueryService implements BlockchainQueryService {
}
@Override
- public AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) {
+ public BlockchainIdentity[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) {
checkLedgerHash(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
@@ -406,7 +419,7 @@ public class LedgerQueryService implements BlockchainQueryService {
}
@Override
- public AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) {
+ public BlockchainIdentity[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) {
checkLedgerHash(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block);
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccount.java
index 49ef5753..38a65e31 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccount.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccount.java
@@ -3,15 +3,21 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
-import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BlockchainIdentity;
-import com.jd.blockchain.ledger.BlockchainIdentityData;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.CryptoSetting;
+import com.jd.blockchain.ledger.HashProof;
+import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.MerkleProof;
+import com.jd.blockchain.ledger.MerkleSnapshot;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.Dataset;
+import com.jd.blockchain.utils.DatasetHelper;
+import com.jd.blockchain.utils.DatasetHelper.DataChangedListener;
+import com.jd.blockchain.utils.DatasetHelper.TypeMapper;
import com.jd.blockchain.utils.Transactional;
/**
@@ -20,94 +26,166 @@ import com.jd.blockchain.utils.Transactional;
* @author huanghaiquan
*
*/
-public class MerkleAccount implements AccountHeader, MerkleProvable, Transactional {
+public class MerkleAccount implements CompositeAccount, HashProvable, MerkleSnapshot, Transactional {
- private BlockchainIdentity bcid;
+ private static final Bytes HEADER_PREFIX = Bytes.fromString("HD/");
+ private static final Bytes DATA_PREFIX = Bytes.fromString("DT/");
- protected MerkleDataSet dataset;
+ private static final Bytes KEY_HEADER_ROOT = Bytes.fromString("HEADER");
+
+ private static final Bytes KEY_DATA_ROOT = Bytes.fromString("DATA");
+
+ private static final String KEY_PUBKEY = "PUBKEY";
+
+ private BlockchainIdentity accountID;
+
+ private MerkleDataSet rootDataset;
+
+ private MerkleDataSet headerDataset;
+
+ private MerkleDataSet dataDataset;
+
+ private Dataset typedHeader;
+
+ private Dataset typedData;
+
+// private long version;
/**
- * Create a new Account with the specified address and pubkey;
+ * Create a new Account with the specified identity(address and pubkey);
*
* At the same time, a empty merkle dataset is also created for this account,
* which is used for storing data of this account.
- *
- * Note that, the blockchain identity of the account is not stored in the
- * account's merkle dataset, but is stored by the outer invoker;
*
- * @param address
- * @param pubKey
+ * This new account will be writable.
+ *
+ * @param accountID Identity of this new account;
+ * @param cryptoSetting Settings about crypto operations;
+ * @param keyPrefix Prefix of all keys in this account's dataset;
+ * @param exStorage The base storage for existance operation;
+ * @param verStorage The base storage for versioning operation;
*/
- public MerkleAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix,
+ public MerkleAccount(BlockchainIdentity accountID, CryptoSetting cryptoSetting, Bytes keyPrefix,
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) {
- this(address, pubKey, null, cryptoSetting, keyPrefix, exStorage, verStorage, false);
+ // 初始化数据集;
+ initializeDatasets(null, cryptoSetting, keyPrefix, exStorage, verStorage, false);
+
+ initPubKey(accountID.getPubKey());
+ this.accountID = accountID;
}
/**
- * Create a new Account with the specified address and pubkey;
+ * Create a account instance with the specified address and root hash; load it's
+ * merkle dataset from the specified root hash. This merkle dateset is used for
+ * storing data of this account.
*
- * At the same time, a empty merkle dataset is also created for this account,
- * which is used for storing data of this account.
- *
- * Note that, the blockchain identity of the account is not stored in the
- * account's merkle dataset, but is stored by the outer invoker;
- *
- * @param bcid
- * @param cryptoSetting
- * @param exStorage
- * @param verStorage
- * @param accessPolicy
+ * @param address Address of this account;
+ * @param rootHash Merkle root hash of this account; It can not be null;
+ * @param cryptoSetting Settings about crypto operations;
+ * @param keyPrefix Prefix of all keys in this account's dataset;
+ * @param exStorage The base storage for existance operation;
+ * @param verStorage The base storage for versioning operation;
+ * @param readonly Readonly about this account's dataset;
*/
- public MerkleAccount(BlockchainIdentity bcid, CryptoSetting cryptoSetting, String keyPrefix,
- ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) {
- this(bcid, null, cryptoSetting, keyPrefix, exStorage, verStorage, false);
+ public MerkleAccount(Bytes address, HashDigest rootHash, CryptoSetting cryptoSetting, Bytes keyPrefix,
+ ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) {
+ if (rootHash == null) {
+ throw new IllegalArgumentException("Specified a null root hash for account[" + address.toBase58() + "]!");
+ }
+
+ // 初始化数据集;
+ initializeDatasets(rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly);
+
+ // 初始化账户的身份;
+ PubKey pubKey = loadPubKey();
+ this.accountID = new AccountID(address, pubKey);
}
- /**
- * Create a account instance with the specified address and pubkey and load it's
- * merkle dataset from the specified root hash. This merkle dateset is used for storing data
- * of this account.
- *
- * @param address
- * @param pubKey
- * @param dataRootHash merkle root hash of account's data; if set to a null value,
- * an empty merkle dataset is created;
- * @param cryptoSetting
- * @param exStorage
- * @param verStorage
- * @param readonly
- * @param accessPolicy
- */
- public MerkleAccount(Bytes address, PubKey pubKey, HashDigest dataRootHash, CryptoSetting cryptoSetting,
- String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) {
- this(new BlockchainIdentityData(address, pubKey), dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage,
+ private void initializeDatasets(HashDigest rootHash, CryptoSetting cryptoSetting, Bytes keyPrefix,
+ ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) {
+ // 加载“根数据集”
+ this.rootDataset = new MerkleDataSet(rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly);
+
+ // 初始化数据修改监听器;
+ DataChangedListener dataChangedListener = new DataChangedListener() {
+ @Override
+ public void onChanged(String key, TypedValue value, long expectedVersion, long newVersion) {
+ onUpdated(key, value, expectedVersion, newVersion);
+ }
+ };
+
+ TypeMapper valueMapper = new TypeMapper() {
+
+ @Override
+ public byte[] encode(TypedValue t2) {
+ return BinaryProtocol.encode(t2, BytesValue.class);
+ }
+
+ @Override
+ public TypedValue decode(byte[] t1) {
+ BytesValue v = BinaryProtocol.decodeAs(t1, BytesValue.class);
+ return TypedValue.wrap(v);
+ }
+ };
+
+ // 加载“头数据集”;
+ HashDigest headerRoot = loadHeaderRoot();
+ Bytes headerPrefix = keyPrefix.concat(HEADER_PREFIX);
+ this.headerDataset = new MerkleDataSet(headerRoot, cryptoSetting, headerPrefix, exStorage, verStorage,
readonly);
+ this.typedHeader = DatasetHelper.listen(DatasetHelper.map(headerDataset, valueMapper), dataChangedListener);
+
+ // 加载“主数据集”
+ HashDigest dataRoot = loadDataRoot();
+ Bytes dataPrefix = keyPrefix.concat(DATA_PREFIX);
+ this.dataDataset = new MerkleDataSet(dataRoot, cryptoSetting, dataPrefix, exStorage, verStorage, readonly);
+ this.typedData = DatasetHelper.listen(DatasetHelper.map(dataDataset, valueMapper), dataChangedListener);
}
- public MerkleAccount(BlockchainIdentity bcid, HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix,
- ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) {
- this.bcid = bcid;
- this.dataset = new MerkleDataSet(dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly);
+ private HashDigest loadHeaderRoot() {
+ byte[] hashBytes = rootDataset.getValue(KEY_HEADER_ROOT);
+ if (hashBytes == null) {
+ return null;
+ }
+ return new HashDigest(hashBytes);
+ }
+
+ private HashDigest loadDataRoot() {
+ byte[] hashBytes = rootDataset.getValue(KEY_DATA_ROOT);
+ if (hashBytes == null) {
+ return null;
+ }
+ return new HashDigest(hashBytes);
+ }
+
+ private long getHeaderRootVersion() {
+ return rootDataset.getVersion(KEY_HEADER_ROOT);
+ }
+
+ private long getDataRootVersion() {
+ return rootDataset.getVersion(KEY_DATA_ROOT);
}
- /*
- * (non-Javadoc)
- *
- * @see com.jd.blockchain.ledger.core.AccountDataSet#getAddress()
- */
- @Override
public Bytes getAddress() {
- return bcid.getAddress();
+ return accountID.getAddress();
}
- /*
- * (non-Javadoc)
- *
- * @see com.jd.blockchain.ledger.core.AccountDataSet#getPubKey()
- */
- @Override
public PubKey getPubKey() {
- return bcid.getPubKey();
+ return accountID.getPubKey();
+ }
+
+ @Override
+ public BlockchainIdentity getID() {
+ return accountID;
+ }
+
+ public Dataset getHeaders() {
+ return typedHeader;
+ }
+
+ @Override
+ public Dataset getDataset() {
+ return typedData;
}
/*
@@ -117,12 +195,22 @@ public class MerkleAccount implements AccountHeader, MerkleProvable, Transaction
*/
@Override
public HashDigest getRootHash() {
- return dataset.getRootHash();
+ return rootDataset.getRootHash();
}
@Override
- public MerkleProof getProof(Bytes key) {
- return dataset.getProof(key);
+ public HashProof getProof(Bytes key) {
+ MerkleProof dataProof = dataDataset.getProof(key);
+ if (dataProof == null) {
+ return null;
+ }
+ MerkleProof rootProof = rootDataset.getProof(KEY_DATA_ROOT);
+ if (rootProof == null) {
+ return null;
+ }
+ HashDigestList proof = new HashDigestList(rootProof);
+ proof.concat(dataProof);
+ return proof;
}
/**
@@ -131,90 +219,298 @@ public class MerkleAccount implements AccountHeader, MerkleProvable, Transaction
* @return
*/
public boolean isReadonly() {
- return dataset.isReadonly();
+ return dataDataset.isReadonly() || headerDataset.isReadonly();
}
/**
- * Create or update the value associated the specified key if the version
- * checking is passed.
- *
- * The value of the key will be updated only if it's latest version equals the
- * specified version argument.
- * If the key doesn't exist, the version checking will be ignored, and key will
- * be created with a new sequence number as id.
- * It also could specify the version argument to -1 to ignore the version
- * checking.
- *
- * If updating is performed, the version of the key increase by 1.
- * If creating is performed, the version of the key initialize by 0.
+ * 初始化账户的公钥;
*
- * @param key The key of data;
- * @param value The value of data;
- * @param version The expected version of the key.
- * @return The new version of the key.
- * If the key is new created success, then return 0;
- * If the key is updated success, then return the new version;
- * If this operation fail by version checking or other reason, then
- * return -1;
+ * @param pubKey
*/
- public long setBytes(Bytes key, BytesValue value, long version) {
- byte[] bytesValue = BinaryProtocol.encode(value, BytesValue.class);
- return dataset.setValue(key, bytesValue, version);
+ private void initPubKey(PubKey pubKey) {
+ long v = typedHeader.setValue(KEY_PUBKEY, TypedValue.fromPubKey(pubKey), -1);
+ if (v < 0) {
+ throw new LedgerException("PubKey storage conflict!");
+ }
}
/**
- * Return the latest version entry associated the specified key; If the key
- * doesn't exist, then return -1;
+ * 加载公钥;
*
- * @param key
* @return
*/
- public long getVersion(Bytes key) {
- return dataset.getVersion(key);
+ private PubKey loadPubKey() {
+ TypedValue value = typedHeader.getValue(KEY_PUBKEY);
+ if (value == null) {
+ return null;
+ }
+ return value.pubKeyValue();
}
/**
- * return the latest version's value;
+ * 当写入新值时触发此方法;
*
* @param key
- * @return return null if not exist;
+ * @param value
+ * @param newVersion
*/
- public BytesValue getBytes(Bytes key) {
- byte[] bytesValue = dataset.getValue(key);
- if (bytesValue == null) {
- return null;
- }
- return BinaryProtocol.decodeAs(bytesValue, BytesValue.class);
+ protected void onUpdated(String key, TypedValue value, long expectedVersion, long newVersion) {
}
/**
- * Return the specified version's value;
+ * 当账户数据提交后触发此方法;
*
- * @param key
- * @param version
- * @return return null if not exist;
+ * 此方法默认会返回新的账户版本号,等于当前版本号加 1 ;
+ *
+ * @param previousRootHash 提交前的根哈希;如果是新账户的首次提交,则为 null;
+ * @param newRootHash 新的根哈希;
*/
- public BytesValue getBytes(Bytes key, long version) {
- byte[] bytesValue = dataset.getValue(key, version);
- if (bytesValue == null) {
- return null;
- }
- return BinaryProtocol.decodeAs(bytesValue, BytesValue.class);
+ protected void onCommited(HashDigest previousRootHash, HashDigest newRootHash) {
}
@Override
public boolean isUpdated() {
- return dataset.isUpdated();
+ return headerDataset.isUpdated() || dataDataset.isUpdated() || rootDataset.isUpdated();
}
@Override
public void commit() {
- dataset.commit();
+ if (headerDataset.isUpdated()) {
+ headerDataset.commit();
+ long version = getHeaderRootVersion();
+ rootDataset.setValue(KEY_HEADER_ROOT, headerDataset.getRootHash().toBytes(), version);
+ }
+ if (dataDataset.isUpdated()) {
+ long version = getDataRootVersion();
+ dataDataset.commit();
+ rootDataset.setValue(KEY_DATA_ROOT, dataDataset.getRootHash().toBytes(), version);
+ }
+
+ if (rootDataset.isUpdated()) {
+ HashDigest previousRootHash = rootDataset.getRootHash();
+ rootDataset.commit();
+ onCommited(previousRootHash, rootDataset.getRootHash());
+ }
}
@Override
public void cancel() {
- dataset.cancel();
+ headerDataset.cancel();
+ dataDataset.cancel();
+ rootDataset.cancel();
+ }
+
+ // ----------------------
+
+ private class AccountID implements BlockchainIdentity {
+
+ private Bytes address;
+
+ private PubKey pubKey;
+
+ public AccountID(Bytes address, PubKey pubKey) {
+ this.address = address;
+ this.pubKey = pubKey;
+ }
+
+ @Override
+ public Bytes getAddress() {
+ return address;
+ }
+
+ @Override
+ public PubKey getPubKey() {
+ return pubKey;
+ }
+
}
+// private static class MerkleDatasetAdapter implements Dataset {
+//
+// private static DataChangedListener NULL_LISTENER = new DataChangedListener() {
+// @Override
+// public void onChanged(Bytes key, BytesValue value, long newVersion) {
+// }
+// };
+//
+// private DataChangedListener changedListener;
+//
+// private MerkleDataSet dataset;
+//
+// public MerkleDataSet getDataset() {
+// return dataset;
+// }
+//
+// @SuppressWarnings("unused")
+// public MerkleDatasetAdapter(MerkleDataSet dataset) {
+// this(dataset, NULL_LISTENER);
+// }
+//
+// public MerkleDatasetAdapter(MerkleDataSet dataset, DataChangedListener listener) {
+// this.dataset = dataset;
+// this.changedListener = listener == null ? NULL_LISTENER : listener;
+// }
+//
+// @Override
+// public DataEntry getDataEntry(String key) {
+// return new VersioningKVEntryWraper(dataset.getDataEntry(Bytes.fromString(key)));
+// }
+//
+// @Override
+// public DataEntry getDataEntry(String key, long version) {
+// return new VersioningKVEntryWraper(dataset.getDataEntry(Bytes.fromString(key), version));
+// }
+//
+// /**
+// * Create or update the value associated the specified key if the version
+// * checking is passed.
+// *
+// * The value of the key will be updated only if it's latest version equals the
+// * specified version argument.
+// * If the key doesn't exist, the version checking will be ignored, and key will
+// * be created with a new sequence number as id.
+// * It also could specify the version argument to -1 to ignore the version
+// * checking.
+// *
+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// *
+// * @param key The key of data;
+// * @param value The value of data;
+// * @param version The expected version of the key.
+// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then
+// * return -1;
+// */
+// @Override
+// public long setValue(Bytes key, BytesValue value, long version) {
+// byte[] bytesValue = BinaryProtocol.encode(value, BytesValue.class);
+// long v = dataset.setValue(key, bytesValue, version);
+// if (v > -1) {
+// changedListener.onChanged(key, value, v);
+// }
+// return v;
+// }
+//
+// /**
+// * Return the latest version entry associated the specified key; If the key
+// * doesn't exist, then return -1;
+// *
+// * @param key
+// * @return
+// */
+// @Override
+// public long getVersion(Bytes key) {
+// return dataset.getVersion(key);
+// }
+//
+// /**
+// * return the latest version's value;
+// *
+// * @param key
+// * @return return null if not exist;
+// */
+// @Override
+// public BytesValue getValue(Bytes key) {
+// byte[] bytesValue = dataset.getValue(key);
+// if (bytesValue == null) {
+// return null;
+// }
+// return BinaryProtocol.decodeAs(bytesValue, BytesValue.class);
+// }
+//
+// /**
+// * Return the specified version's value;
+// *
+// * @param key
+// * @param version
+// * @return return null if not exist;
+// */
+// @Override
+// public BytesValue getValue(Bytes key, long version) {
+// byte[] bytesValue = dataset.getValue(key, version);
+// if (bytesValue == null) {
+// return null;
+// }
+// return BinaryProtocol.decodeAs(bytesValue, BytesValue.class);
+// }
+//
+// @Override
+// public long getDataCount() {
+// return dataset.getDataCount();
+// }
+//
+// @Override
+// public long setValue(String key, BytesValue value, long version) {
+// byte[] bytesValue = BinaryProtocol.encode(value, BytesValue.class);
+// return dataset.setValue(key, bytesValue, version);
+// }
+//
+// @Override
+// public BytesValue getValue(String key, long version) {
+// byte[] bytesValue = dataset.getValue(key, version);
+// if (bytesValue == null) {
+// return null;
+// }
+// return BinaryProtocol.decodeAs(bytesValue, BytesValue.class);
+// }
+//
+// @Override
+// public BytesValue getValue(String key) {
+// byte[] bytesValue = dataset.getValue(key);
+// if (bytesValue == null) {
+// return null;
+// }
+// return BinaryProtocol.decodeAs(bytesValue, BytesValue.class);
+// }
+//
+// @Override
+// public long getVersion(String key) {
+// return dataset.getVersion(key);
+// }
+//
+// @Override
+// public DataEntry getDataEntry(String key) {
+// return new VersioningKVEntryWraper(dataset.getDataEntry(key));
+// }
+//
+// @Override
+// public DataEntry getDataEntry(String key, long version) {
+// return new VersioningKVEntryWraper(dataset.getDataEntry(key, version));
+// }
+// }
+
+// private static interface DataChangedListener {
+//
+// void onChanged(Bytes key, BytesValue value, long newVersion);
+//
+// }
+
+// private static class VersioningKVEntryWraper implements DataEntry {
+//
+// private DataEntry kv;
+//
+// public VersioningKVEntryWraper(DataEntry kv) {
+// this.kv = kv;
+// }
+//
+// @Override
+// public String getKey() {
+// return kv.getKey().toUTF8String();
+// }
+//
+// @Override
+// public long getVersion() {
+// return kv.getVersion();
+// }
+//
+// @Override
+// public BytesValue getValue() {
+// return BinaryProtocol.decodeAs(kv.getValue(), BytesValue.class);
+// }
+//
+// }
+
}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountHeader.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountHeader.java
new file mode 100644
index 00000000..94faeb6a
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountHeader.java
@@ -0,0 +1,12 @@
+//package com.jd.blockchain.ledger.core;
+//
+//import com.jd.blockchain.binaryproto.DataField;
+//import com.jd.blockchain.ledger.BlockchainIdentity;
+//import com.jd.blockchain.ledger.MerkleSnapshot;
+//
+//public interface MerkleAccountHeader extends MerkleSnapshot {
+//
+// @DataField(order = 1, refContract = true)
+// BlockchainIdentity getID();
+//
+//}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java
index d3e507ba..8f46e235 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java
@@ -3,31 +3,35 @@ package com.jd.blockchain.ledger.core;
import java.util.HashMap;
import java.util.Map;
-import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
-import com.jd.blockchain.ledger.AccountHeader;
-import com.jd.blockchain.ledger.BytesValue;
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.BlockchainIdentityData;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.ledger.MerkleSnapshot;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.DataEntry;
import com.jd.blockchain.utils.Transactional;
-public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQuery {
+public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQuery {
static {
DataContractRegistry.register(MerkleSnapshot.class);
- DataContractRegistry.register(AccountHeader.class);
+ DataContractRegistry.register(BlockchainIdentity.class);
}
- private final String keyPrefix;
+ private final Bytes keyPrefix;
+ /**
+ * 账户根哈希的数据集;
+ */
private MerkleDataSet merkleDataset;
/**
@@ -36,7 +40,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
*
*/
// TODO:未考虑大数据量时,由于缺少过期策略,会导致内存溢出的问题;
- private Map latestAccountsCache = new HashMap<>();
+ private Map latestAccountsCache = new HashMap<>();
private ExPolicyKVStorage baseExStorage;
@@ -44,7 +48,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
private CryptoSetting cryptoSetting;
- private boolean updated;
+ private volatile boolean updated;
private AccountAccessPolicy accessPolicy;
@@ -56,12 +60,12 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
merkleDataset.setReadonly();
}
- public MerkleAccountSet(CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage,
+ public MerkleAccountSet(CryptoSetting cryptoSetting, Bytes keyPrefix, ExPolicyKVStorage exStorage,
VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) {
this(null, cryptoSetting, keyPrefix, exStorage, verStorage, false, accessPolicy);
}
- public MerkleAccountSet(HashDigest rootHash, CryptoSetting cryptoSetting, String keyPrefix,
+ public MerkleAccountSet(HashDigest rootHash, CryptoSetting cryptoSetting, Bytes keyPrefix,
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly,
AccountAccessPolicy accessPolicy) {
this.keyPrefix = keyPrefix;
@@ -70,6 +74,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
this.baseVerStorage = verStorage;
this.merkleDataset = new MerkleDataSet(rootHash, cryptoSetting, keyPrefix, this.baseExStorage,
this.baseVerStorage, readonly);
+
this.accessPolicy = accessPolicy;
}
@@ -83,29 +88,17 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
return merkleDataset.getProof(key);
}
- public AccountHeader[] getHeaders(int fromIndex, int count) {
- byte[][] results = merkleDataset.getLatestValues(fromIndex, count);
- AccountHeader[] accounts = new AccountHeader[results.length];
+ @Override
+ public BlockchainIdentity[] getHeaders(int fromIndex, int count) {
+ DataEntry[] results = merkleDataset.getLatestDataEntries(fromIndex, count);
+ BlockchainIdentity[] ids = new BlockchainIdentity[results.length];
for (int i = 0; i < results.length; i++) {
- accounts[i] = deserialize(results[i]);
+ InnerMerkleAccount account = createAccount(results[i].getKey(), new HashDigest(results[i].getValue()),
+ results[i].getVersion(), true);
+ ids[i] = account.getID();
}
- return accounts;
- }
-
- // private VersioningAccount deserialize(byte[] txBytes) {
- //// return BinaryEncodingUtils.decode(txBytes, null, Account.class);
- // AccountHeaderData accInfo = BinaryEncodingUtils.decode(txBytes);
- //// return new BaseAccount(accInfo.getAddress(), accInfo.getPubKey(), null,
- // cryptoSetting,
- //// baseExStorage, baseVerStorage, true, accessPolicy);
- // return new VersioningAccount(accInfo.getAddress(), accInfo.getPubKey(),
- // accInfo.getRootHash(), cryptoSetting,
- // keyPrefix, baseExStorage, baseVerStorage, true, accessPolicy, accInfo.);
- // }
-
- private AccountHeader deserialize(byte[] txBytes) {
- return BinaryProtocol.decode(txBytes);
+ return ids;
}
/**
@@ -118,7 +111,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
}
@Override
- public MerkleAccount getAccount(String address) {
+ public CompositeAccount getAccount(String address) {
return getAccount(Bytes.fromBase58(address));
}
@@ -128,7 +121,8 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
* @param address
* @return
*/
- public MerkleAccount getAccount(Bytes address) {
+ @Override
+ public CompositeAccount getAccount(Bytes address) {
return this.getAccount(address, -1);
}
@@ -142,25 +136,30 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
* @return
*/
public boolean contains(Bytes address) {
- long latestVersion = getVersion(address);
+ InnerMerkleAccount acc = latestAccountsCache.get(address);
+ if (acc != null) {
+ // 无论是新注册未提交的,还是缓存已提交的账户实例,都认为是存在;
+ return true;
+ }
+ long latestVersion = merkleDataset.getVersion(address);
return latestVersion > -1;
}
/**
* 返回指定账户的版本;
* 如果账户已经注册,则返回该账户的最新版本,值大于等于 0;
- * 如果账户不存在,则返回 -1;
- * 如果指定的账户已经注册(通过 {@link #register(String, PubKey)} 方法),但尚未提交(通过
- * {@link #commit()} 方法),此方法对该账户仍然返回 0;
+ * 如果账户不存在,则返回 -1;
+ * 如果账户已经注册(通过 {@link #register(String, PubKey)} 方法),但尚未提交(通过 {@link #commit()}
+ * 方法),则返回 -1;
*
* @param address
* @return
*/
public long getVersion(Bytes address) {
- InnerVersioningAccount acc = latestAccountsCache.get(address);
+ InnerMerkleAccount acc = latestAccountsCache.get(address);
if (acc != null) {
// 已注册尚未提交,也返回 -1;
- return acc.version == -1 ? 0 : acc.version;
+ return acc.getVersion();
}
return merkleDataset.getVersion(address);
@@ -175,12 +174,12 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
* @param version 账户版本;如果指定为 -1,则返回最新版本;
* @return
*/
- public MerkleAccount getAccount(Bytes address, long version) {
+ public CompositeAccount getAccount(Bytes address, long version) {
version = version < 0 ? -1 : version;
- InnerVersioningAccount acc = latestAccountsCache.get(address);
+ InnerMerkleAccount acc = latestAccountsCache.get(address);
if (acc != null && version == -1) {
return acc;
- } else if (acc != null && acc.version == version) {
+ } else if (acc != null && acc.getVersion() == version) {
return acc;
}
@@ -194,7 +193,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
}
// 如果是不存在的,或者刚刚新增未提交的账户,则前面一步查询到的 latestVersion 小于 0, 代码不会执行到此;
- if (acc != null && acc.version != latestVersion) {
+ if (acc != null && acc.getVersion() != latestVersion) {
// 当执行到此处时,并且缓冲列表中缓存了最新的版本,
// 如果当前缓存的最新账户的版本和刚刚从存储中检索得到的最新版本不一致,可能存在外部的并发更新,这超出了系统设计的逻辑;
@@ -205,21 +204,15 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
}
// Now, be sure that "acc == null", so get account from storage;
-
- byte[] bytes = merkleDataset.getValue(address, version);
- if (bytes == null) {
- return null;
- }
-
// Set readonly for the old version account;
boolean readonly = (version > -1 && version < latestVersion) || isReadonly();
-
- // String prefix = address.concat(LedgerConsts.KEY_SEPERATOR);
- // ExPolicyKVStorage ss = PrefixAppender.prefix(prefix, baseExStorage);
- // VersioningKVStorage vs = PrefixAppender.prefix(prefix, baseVerStorage);
- // BaseAccount accDS = deserialize(bytes, cryptoSetting, ss, vs, readonly);
- String prefix = keyPrefix + address;
- acc = deserialize(bytes, cryptoSetting, prefix, baseExStorage, baseVerStorage, readonly, latestVersion);
+
+ long qVersion = version == -1 ? latestVersion : version;
+ // load account from storage;
+ acc = loadAccount(address, readonly, qVersion);
+ if (acc == null) {
+ return null;
+ }
if (!readonly) {
// cache the latest version witch enable reading and writing;
// readonly version of account not necessary to be cached;
@@ -228,6 +221,10 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
return acc;
}
+ public CompositeAccount register(Bytes address, PubKey pubKey) {
+ return register(new BlockchainIdentityData(address, pubKey));
+ }
+
/**
* 注册一个新账户;
*
@@ -239,16 +236,18 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
* @param pubKey 公钥;
* @return 注册成功的账户对象;
*/
- public MerkleAccount register(Bytes address, PubKey pubKey) {
+ public CompositeAccount register(BlockchainIdentity accountId) {
if (isReadonly()) {
throw new IllegalArgumentException("This AccountSet is readonly!");
}
+ Bytes address = accountId.getAddress();
+ PubKey pubKey = accountId.getPubKey();
verifyAddressEncoding(address, pubKey);
- InnerVersioningAccount cachedAcc = latestAccountsCache.get(address);
+ InnerMerkleAccount cachedAcc = latestAccountsCache.get(address);
if (cachedAcc != null) {
- if (cachedAcc.version < 0) {
+ if (cachedAcc.getVersion() < 0) {
// 同一个新账户已经注册,但尚未提交,所以重复注册不会引起任何变化;
return cachedAcc;
}
@@ -264,17 +263,8 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
throw new LedgerException("Account Registering was rejected for the access policy!");
}
- // String prefix = address.concat(LedgerConsts.KEY_SEPERATOR);
- // ExPolicyKVStorage accExStorage = PrefixAppender.prefix(prefix,
- // baseExStorage);
- // VersioningKVStorage accVerStorage = PrefixAppender.prefix(prefix,
- // baseVerStorage);
- // BaseAccount accDS = createInstance(address, pubKey, cryptoSetting,
- // accExStorage, accVerStorage);
-
- String prefix = keyPrefix + address;
- InnerVersioningAccount acc = createInstance(address, pubKey, cryptoSetting, prefix, baseExStorage, baseVerStorage,
- -1);
+ Bytes prefix = keyPrefix.concat(address);
+ InnerMerkleAccount acc = createInstance(accountId, cryptoSetting, prefix);
latestAccountsCache.put(address, acc);
updated = true;
@@ -288,20 +278,50 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
}
}
- private InnerVersioningAccount createInstance(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting,
- String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, long version) {
- return new InnerVersioningAccount(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage, version);
+ private InnerMerkleAccount createInstance(BlockchainIdentity header, CryptoSetting cryptoSetting, Bytes keyPrefix) {
+ return new InnerMerkleAccount(header, cryptoSetting, keyPrefix, baseExStorage, baseVerStorage);
+ }
+
+ /**
+ * 加载指定版本的账户;
+ *
+ * @param address 账户地址;
+ * @param readonly 是否只读;
+ * @param version 账户的版本;大于等于 0 ;
+ * @return
+ */
+ private InnerMerkleAccount loadAccount(Bytes address, boolean readonly, long version) {
+ byte[] rootHashBytes = merkleDataset.getValue(address, version);
+ if (rootHashBytes == null) {
+ return null;
+ }
+ HashDigest rootHash = new HashDigest(rootHashBytes);
+
+ return createAccount(address, rootHash, version, readonly);
}
- private InnerVersioningAccount deserialize(byte[] bytes, CryptoSetting cryptoSetting, String keyPrefix,
- ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, long version) {
- AccountHeader accInfo = BinaryProtocol.decode(bytes);
- return new InnerVersioningAccount(accInfo.getAddress(), accInfo.getPubKey(), accInfo.getRootHash(), cryptoSetting,
- keyPrefix, exStorage, verStorage, readonly, version);
+ private InnerMerkleAccount createAccount(Bytes address, HashDigest rootHash, long version, boolean readonly) {
+ // prefix;
+ Bytes prefix = keyPrefix.concat(address);
+
+ return new InnerMerkleAccount(address, version, rootHash, cryptoSetting, prefix, baseExStorage, baseVerStorage,
+ readonly);
}
- private byte[] serialize(AccountHeader account) {
- return BinaryProtocol.encode(account, AccountHeader.class);
+ // TODO:优化:区块链身份(地址+公钥)与其Merkle树根哈希分开独立存储;
+ // 不必作为一个整块,避免状态数据写入时频繁重写公钥,尤其某些算法的公钥可能很大;
+
+ /**
+ * 保存账户的根哈希,返回账户的新版本;
+ *
+ * @param account
+ * @return
+ */
+ private long saveAccount(InnerMerkleAccount account) {
+ // 提交更改,更新哈希;
+ account.commit();
+
+ return account.getVersion();
}
@Override
@@ -315,17 +335,10 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
return;
}
try {
- for (InnerVersioningAccount acc : latestAccountsCache.values()) {
+ for (InnerMerkleAccount acc : latestAccountsCache.values()) {
// updated or new created;
- if (acc.isUpdated() || acc.version < 0) {
- // 提交更改,更新哈希;
- acc.commit();
- byte[] value = serialize(acc);
- long ver = merkleDataset.setValue(acc.getAddress(), value, acc.version);
- if (ver < 0) {
- // Update fail;
- throw new LedgerException("Account updating fail! --[Address=" + acc.getAddress() + "]");
- }
+ if (acc.isUpdated() || acc.getVersion() < 0) {
+ saveAccount(acc);
}
}
merkleDataset.commit();
@@ -343,7 +356,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
Bytes[] addresses = new Bytes[latestAccountsCache.size()];
latestAccountsCache.keySet().toArray(addresses);
for (Bytes address : addresses) {
- InnerVersioningAccount acc = latestAccountsCache.remove(address);
+ InnerMerkleAccount acc = latestAccountsCache.remove(address);
// cancel;
if (acc.isUpdated()) {
acc.cancel();
@@ -352,107 +365,46 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
updated = false;
}
- public static class AccountHeaderData implements AccountHeader {
-
- private Bytes address;
- private PubKey pubKey;
- private HashDigest rootHash;
-
- public AccountHeaderData(Bytes address, PubKey pubKey, HashDigest rootHash) {
- this.address = address;
- this.pubKey = pubKey;
- this.rootHash = rootHash;
- }
-
- @Override
- public Bytes getAddress() {
- return address;
- }
+ /**
+ * 内部实现的账户,监听和同步账户数据的变更;
+ *
+ * @author huanghaiquan
+ *
+ */
+ private class InnerMerkleAccount extends MerkleAccount {
- @Override
- public PubKey getPubKey() {
- return pubKey;
- }
+ private long version;
- @Override
- public HashDigest getRootHash() {
- return rootHash;
+ public InnerMerkleAccount(BlockchainIdentity accountID, CryptoSetting cryptoSetting, Bytes keyPrefix,
+ ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) {
+ super(accountID, cryptoSetting, keyPrefix, exStorage, verStorage);
+ this.version = -1;
}
- }
-
- private class InnerVersioningAccount extends MerkleAccount {
-
- // private final BaseAccount account;
-
- private final long version;
-
- // public VersioningAccount(BaseAccount account, long version) {
- // this.account = account;
- // this.version = version;
- // }
-
- public InnerVersioningAccount(Bytes address, PubKey pubKey, HashDigest rootHash, CryptoSetting cryptoSetting,
- String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly,
- long version) {
- super(address, pubKey, rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly);
+ public InnerMerkleAccount(Bytes address, long version, HashDigest dataRootHash, CryptoSetting cryptoSetting,
+ Bytes keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) {
+ super(address, dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly);
this.version = version;
}
- public InnerVersioningAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix,
- ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, long version) {
- super(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage);
- this.version = version;
+ @Override
+ protected void onUpdated(String key, TypedValue value, long expectedVersion, long newVersion) {
+ updated = true;
}
- // @Override
- // public Bytes getAddress() {
- // return account.getAddress();
- // }
- //
- // @Override
- // public PubKey getPubKey() {
- // return account.getPubKey();
- // }
- //
- // @Override
- // public HashDigest getRootHash() {
- // return account.getRootHash();
- // }
- //
- // @Override
- // public MerkleProof getProof(Bytes key) {
- // return account.getProof(key);
- // }
- //
- // @Override
- // public boolean isReadonly() {
- // return account.isReadonly();
- // }
-
@Override
- public long setBytes(Bytes key, BytesValue value, long version) {
- long v = super.setBytes(key, value, version);
- if (v > -1) {
- updated = true;
+ protected void onCommited(HashDigest previousRootHash, HashDigest newRootHash) {
+ long newVersion = merkleDataset.setValue(this.getAddress(), newRootHash.toBytes(), version);
+ if (newVersion < 0) {
+ // Update fail;
+ throw new LedgerException("Account updating fail! --[Address=" + this.getAddress() + "]");
}
- return v;
+ this.version = newVersion;
}
- // @Override
- // public long getKeyVersion(Bytes key) {
- // return account.getKeyVersion(key);
- // }
- //
- // @Override
- // public byte[] getBytes(Bytes key) {
- // return account.getBytes(key);
- // }
- //
- // @Override
- // public byte[] getBytes(Bytes key, long version) {
- // return account.getBytes(key, version);
- // }
+ public long getVersion() {
+ return version;
+ }
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataCluster.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataCluster.java
new file mode 100644
index 00000000..41339c58
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataCluster.java
@@ -0,0 +1,74 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.Map;
+
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.CryptoSetting;
+import com.jd.blockchain.ledger.MerkleSnapshot;
+import com.jd.blockchain.storage.service.ExPolicyKVStorage;
+import com.jd.blockchain.storage.service.VersioningKVStorage;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.Transactional;
+
+public class MerkleDataCluster implements Transactional, MerkleSnapshot {
+
+ private boolean readonly;
+
+ private MerkleDataSet rootDS;
+
+ private Map partitions;
+
+ /**
+ * Create an empty readable {@link MerkleDataCluster} instance;
+ */
+ public MerkleDataCluster(CryptoSetting setting, Bytes keyPrefix, ExPolicyKVStorage exPolicyStorage,
+ VersioningKVStorage versioningStorage) {
+ this(null, setting, keyPrefix, exPolicyStorage, versioningStorage, false);
+ }
+
+ /**
+ * Create an {@link MerkleDataCluster} instance;
+ *
+ * @param rootHash root hash of this {@link MerkleDataCluster} instance;
+ * @param readonly whether read only;
+ */
+ public MerkleDataCluster(HashDigest rootHash, CryptoSetting setting, Bytes keyPrefix,
+ ExPolicyKVStorage exPolicyStorage, VersioningKVStorage versioningStorage, boolean readonly) {
+ this.rootDS = new MerkleDataSet(rootHash, setting, keyPrefix, exPolicyStorage, versioningStorage, readonly);
+ }
+
+ @Override
+ public HashDigest getRootHash() {
+ return rootDS.getRootHash();
+ }
+
+ @Override
+ public boolean isUpdated() {
+ return rootDS.isUpdated();
+ }
+
+// public VersioningMap getPartition(Bytes name) {
+// return getPartition(name, false);
+// }
+//
+// public VersioningMap getPartition(Bytes name, boolean create) {
+//
+// }
+//
+// public VersioningMap createPartition(Bytes name) {
+//
+// }
+
+ @Override
+ public void commit() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void cancel() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java
index 3dd99df0..15de35b5 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java
@@ -1,11 +1,12 @@
package com.jd.blockchain.ledger.core;
import com.jd.blockchain.ledger.MerkleProof;
-import com.jd.blockchain.storage.service.VersioningKVEntry;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.DataEntry;
public interface MerkleDataEntry {
- VersioningKVEntry getData();
+ DataEntry getData();
MerkleProof getProof();
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataNodeEncoder.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataNodeEncoder.java
new file mode 100644
index 00000000..1b4cb0f7
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataNodeEncoder.java
@@ -0,0 +1,14 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.ledger.core.MerkleTree.DataNode;
+import com.jd.blockchain.utils.Bytes;
+
+public interface MerkleDataNodeEncoder {
+
+ byte getFormatVersion();
+
+ DataNode create(short hashAlgorithm, long sn, Bytes key, long version, byte[] hashedData);
+
+ DataNode resolve(byte[] bytes);
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataNodeEncoder_V0.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataNodeEncoder_V0.java
new file mode 100644
index 00000000..aa47aa6f
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataNodeEncoder_V0.java
@@ -0,0 +1,128 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.crypto.HashFunction;
+import com.jd.blockchain.ledger.core.MerkleTree.DataNode;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.io.BytesUtils;
+import com.jd.blockchain.utils.io.NumberMask;
+
+/**
+ * The first version of the DataNode binary sequence encoder, which's version
+ * number is 0.
+ *
+ *
+ * This version of DataNode binary sequence is composed of sn(8 bytes),
+ * key(variable size), version(8 bytes) and node hash(32 bytes for SHA256);
+ *
+ *
+ * In this version, the node hash is computed from bytes sequence composing of
+ * sn, key, version and original value of the key;
+ *
+ *
+ * For the purpose of upgrading the version of DataNode binary format, we use
+ * the first byte of the binary sequence as the tag to identify the version of
+ * DataNode binary format, and reduce the maximum value of the valid range of SN
+ * to 2^56.
+ * Other versions of the implementation also follow the above rules, the version
+ * of the data node binary format is marked from 0, incremented by 1.
+ *
+ * @author huanghaiquan
+ *
+ */
+class MerkleDataNodeEncoder_V0 implements MerkleDataNodeEncoder {
+
+ @Override
+ public byte getFormatVersion() {
+ return 0;
+ }
+
+ @Override
+ public DataNode resolve(byte[] bytes) {
+ if (bytes[0] != getFormatVersion()) {
+ throw new IllegalArgumentException("Unsupported version of data node bytes sequence[" + bytes[0] + "]! ");
+ }
+
+ // resolve SN;
+ byte[] snBytes = new byte[8];
+ snBytes[0] = 0x0;
+ System.arraycopy(bytes, 1, snBytes, 1, 7);
+ long sn = BytesUtils.toLong(snBytes);
+
+ // skip bytes of SN;
+ int offset = 8;
+
+ // byte[] keyBytes = BytesEncoding.read(NumberMask.SHORT, in);
+ // String key = BytesUtils.toString(keyBytes);
+ int keySize = NumberMask.SHORT.resolveMaskedNumber(bytes, offset);
+ offset += NumberMask.SHORT.getMaskLength(keySize);
+ byte[] keyBytes = new byte[keySize];
+ System.arraycopy(bytes, offset, keyBytes, 0, keySize);
+ offset += keySize;
+ // String key = BytesUtils.toString(keyBytes);
+ Bytes key = new Bytes(keyBytes);
+
+ // long version = BytesUtils.readLong(in);
+ long version = BytesUtils.toLong(bytes, offset);
+ offset += 8;
+
+ // byte[] dataHashBytes = BytesEncoding.read(NumberMask.SHORT, in);
+ int hashSize = NumberMask.TINY.resolveMaskedNumber(bytes, offset);
+ offset += NumberMask.TINY.getMaskLength(hashSize);
+ byte[] nodeHashBytes = new byte[hashSize];
+ System.arraycopy(bytes, offset, nodeHashBytes, 0, hashSize);
+ offset += hashSize;
+ HashDigest nodeHash = new HashDigest(nodeHashBytes);
+ return new DataNode(nodeHash, sn, key, version, null, bytes);
+ }
+
+ @Deprecated
+ @Override
+ public DataNode create(short hashAlgorithm, long sn, Bytes key, long version, byte[] value) {
+ // Header is composed of sn, key and version;
+ // So the size of header is: 8 + "mask of key size" + "key bytes" + 8;
+ int keySize = key.size();
+ int maskSize = NumberMask.SHORT.getMaskLength(keySize);
+
+ int headerSize = 8 + maskSize + keySize + 8;
+ byte[] headerBytes = new byte[headerSize];
+
+ int offset = 0;
+ // write sn;
+ offset += BytesUtils.toBytes(sn, headerBytes, 0);
+
+ // write the size of key bytes;
+ NumberMask.SHORT.writeMask(keySize, headerBytes, offset);
+ offset += maskSize;
+
+ // write the key bytes;
+ offset += key.copyTo(headerBytes, offset, keySize);
+
+ // version;
+ offset += BytesUtils.toBytes(version, headerBytes, offset);
+
+ // compute node hash from the combination of header and data value;
+ byte[] dataBytes = BytesUtils.concat(headerBytes, value);
+
+ HashFunction hashFunc = Crypto.getHashFunction(hashAlgorithm);
+ HashDigest dataNodeHash = hashFunc.hash(dataBytes);
+
+ // build bytes of data node, which is composed of sn, key, version and node
+ // hash;
+ int hashMaskSize = NumberMask.TINY.getMaskLength(dataNodeHash.size());
+ int dataNodeSize = headerSize + hashMaskSize + dataNodeHash.size();
+ byte[] nodeBytes = new byte[dataNodeSize];
+
+ offset = 0;
+ System.arraycopy(headerBytes, 0, nodeBytes, offset, headerSize);
+ offset += headerSize;
+ NumberMask.TINY.writeMask(dataNodeHash.size(), nodeBytes, offset);
+ offset += hashMaskSize;
+ System.arraycopy(dataNodeHash.toBytes(), 0, nodeBytes, offset, dataNodeHash.size());
+
+ // No data hash has been computed and record in this old version of
+ // implementation;
+ return new DataNode(dataNodeHash, sn, key, version, null, nodeBytes);
+ }
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataNodeEncoder_V1.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataNodeEncoder_V1.java
new file mode 100644
index 00000000..929e7e40
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataNodeEncoder_V1.java
@@ -0,0 +1,200 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.crypto.HashFunction;
+import com.jd.blockchain.ledger.core.MerkleTree.DataNode;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.io.BytesUtils;
+import com.jd.blockchain.utils.io.NumberMask;
+
+/**
+ * The second version of the DataNode binary sequence encoder, which's version
+ * number is 1.
+ *
+ *
+ * This version of DataNode binary sequence is composed of sn(8 bytes),
+ * key(variable size), version(8 bytes), hash of original value the key, and
+ * node hash;
+ *
+ *
+ * In this version, the node hash is computed from bytes sequence composing of
+ * sn, key, version , hash of original value of the key;
+ *
+ *
+ * For the purpose of upgrading the version of DataNode binary format, we use
+ * the first byte of the binary sequence as the tag to identify the version of
+ * DataNode binary format, and reduce the maximum value of the valid range of SN
+ * to 2^56.
+ * Other versions of the implementation also follow the above rules, the version
+ * of the data node binary format is marked from 0, incremented by 1.
+ *
+ * @author huanghaiquan
+ *
+ */
+class MerkleDataNodeEncoder_V1 implements MerkleDataNodeEncoder {
+
+ @Override
+ public byte getFormatVersion() {
+ return 1;
+ }
+
+ /**
+ * Parse DataNode from it's bytes sequence;
+ *
+ * the bytes sequence is: sn + key + version + data_hash;
+ *
+ * @param bytes
+ * @return
+ */
+ @Override
+ public DataNode resolve(byte[] bytes) {
+ if (bytes[0] != getFormatVersion()) {
+ throw new IllegalArgumentException("Unsupported version of data node bytes sequence[" + bytes[0] + "]! ");
+ }
+
+ // resolve SN;
+ byte[] snBytes = new byte[8];
+ snBytes[0] = 0x0;
+ System.arraycopy(bytes, 1, snBytes, 1, 7);
+ long sn = BytesUtils.toLong(snBytes);
+
+ // skip bytes of SN;
+ int offset = 8;
+
+ // resolve key of data;
+ // First, resolve the number mask of the key size;
+ // Second, read the key bytes;
+ int keySize = NumberMask.SHORT.resolveMaskedNumber(bytes, offset);
+ offset += NumberMask.SHORT.getMaskLength(keySize);
+ byte[] keyBytes = new byte[keySize];
+ System.arraycopy(bytes, offset, keyBytes, 0, keySize);
+ offset += keySize;
+ Bytes key = new Bytes(keyBytes);
+
+ // Resolve version of key;
+ long version = BytesUtils.toLong(bytes, offset);
+ offset += 8;
+
+ // resovle data hash;
+ int dataHashSize = NumberMask.TINY.resolveMaskedNumber(bytes, offset);
+ offset += NumberMask.TINY.getMaskLength(dataHashSize);
+ byte[] dataHashBytes = new byte[dataHashSize];
+ System.arraycopy(bytes, offset, dataHashBytes, 0, dataHashSize);
+ offset += dataHashSize;
+ HashDigest dataHash = new HashDigest(dataHashBytes);
+
+ // resovle node hash;
+ int nodeHashSize = NumberMask.TINY.resolveMaskedNumber(bytes, offset);
+ offset += NumberMask.TINY.getMaskLength(nodeHashSize);
+ byte[] nodeHashBytes = new byte[nodeHashSize];
+ System.arraycopy(bytes, offset, nodeHashBytes, 0, nodeHashSize);
+ offset += nodeHashSize;
+ HashDigest nodeHash = new HashDigest(nodeHashBytes);
+
+ return new DataNode(nodeHash, sn, key, version, dataHash, bytes);
+ }
+
+ public DataNode newDataNode(short hashAlgorithm, long sn, Bytes key, long version, HashDigest dataHash) {
+ HashFunction hashFunc = Crypto.getHashFunction(hashAlgorithm);
+ return create(hashFunc, sn, key, version, dataHash);
+ }
+
+ @Override
+ public DataNode create(short hashAlgorithm, long sn, Bytes key, long version, byte[] data) {
+ HashFunction hashFunc = Crypto.getHashFunction(hashAlgorithm);
+ HashDigest dataHash = hashFunc.hash(data);
+
+ return create(hashFunc, sn, key, version, dataHash);
+ }
+
+ /**
+ * Data node's bytes sequence is composited by header( reference:
+ * {@link #buildKeyHeaderBytes(long, Bytes, long)} ) and data hash;
+ *
+ *
+ * In general, the bytes sequence is: sn + key + version + data_hash +
+ * node_hash;
+ *
+ * @param hashFunc
+ * @param sn
+ * @param key
+ * @param version
+ * @param dataHash
+ * @return
+ */
+ private DataNode create(HashFunction hashFunc, long sn, Bytes key, long version, HashDigest dataHash) {
+ byte[] headerBytes = buildKeyHeaderBytes(sn, key, version);
+ int headerSize = headerBytes.length;
+
+ // 单独对头部和数据进行哈希,以便在提供 Merkle 证明时能够不必传递原始数据即可进行哈希验证;
+ HashDigest headerHash = hashFunc.hash(headerBytes);
+ byte[] dataHashBytes = BytesUtils.concat(headerHash.getRawDigest(), dataHash.getRawDigest());
+
+ HashDigest dataNodeHash = hashFunc.hash(dataHashBytes);
+
+ int dataHashSize = dataHash.size();
+ int nodeHashSize = dataNodeHash.size();
+ int dataHashMaskSize = NumberMask.TINY.getMaskLength(dataHashSize);
+ int nodeHashMaskSize = NumberMask.TINY.getMaskLength(nodeHashSize);
+ int nodeSize = headerSize + dataHashMaskSize + dataHashSize + nodeHashMaskSize + nodeHashSize;
+ byte[] nodeBytes = new byte[nodeSize];
+
+ // write header;
+ int offset = 0;
+ System.arraycopy(headerBytes, 0, nodeBytes, offset, headerSize);
+ offset += headerSize;
+
+ // write data hash;
+ NumberMask.TINY.writeMask(dataHashSize, nodeBytes, offset);
+ offset += dataHashMaskSize;
+ System.arraycopy(dataHash.toBytes(), 0, nodeBytes, offset, dataHashSize);
+ offset += dataHashSize;
+
+ // write node hash;
+ NumberMask.TINY.writeMask(nodeHashSize, nodeBytes, offset);
+ offset += nodeHashMaskSize;
+ System.arraycopy(dataNodeHash.toBytes(), 0, nodeBytes, offset, nodeHashSize);
+
+ // set format version;
+ nodeBytes[0] = getFormatVersion();
+
+ return new DataNode(dataNodeHash, sn, key, version, dataHash, nodeBytes);
+ }
+
+ /**
+ * Header is composited by sn + key + version; Bytes sequence: sn_size(8) +
+ * number_mask_of_key_size + key_bytes + version_size(8);
+ *
+ * @param sn
+ * @param key
+ * @param version
+ * @return
+ */
+ private static byte[] buildKeyHeaderBytes(long sn, Bytes key, long version) {
+ int keySize = key.size();
+ int maskSize = NumberMask.SHORT.getMaskLength(keySize);
+
+ // Size Of header = sn + key + version;
+ // sn_size(8) + mask_size + key_size + version_size(8);
+ int headerSize = 8 + maskSize + keySize + 8;
+ byte[] headerBytes = new byte[headerSize];
+
+ // write bytes of sn;
+ int offset = 0;
+ offset += BytesUtils.toBytes(sn, headerBytes, 0);
+
+ // write bytes of key mask;
+ NumberMask.SHORT.writeMask(keySize, headerBytes, offset);
+ offset += maskSize;
+
+ // write bytes of key;
+ offset += key.copyTo(headerBytes, offset, keySize);
+
+ // write bytes of version;
+ offset += BytesUtils.toBytes(version, headerBytes, offset);
+
+ return headerBytes;
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java
index 16927b97..80217efe 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java
@@ -7,11 +7,14 @@ import com.jd.blockchain.ledger.MerkleDataNode;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy;
-import com.jd.blockchain.storage.service.VersioningKVEntry;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.storage.service.utils.BufferedKVStorage;
import com.jd.blockchain.storage.service.utils.VersioningKVData;
+import com.jd.blockchain.utils.ArrayUtils;
import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.DataEntry;
+import com.jd.blockchain.utils.DataIterator;
+import com.jd.blockchain.utils.Dataset;
import com.jd.blockchain.utils.Transactional;
import com.jd.blockchain.utils.io.BytesUtils;
@@ -23,23 +26,24 @@ import com.jd.blockchain.utils.io.BytesUtils;
* @author huanghaiquan
*
*/
-public class MerkleDataSet implements Transactional, MerkleProvable {
+public class MerkleDataSet implements Transactional, MerkleProvable, Dataset {
/**
* 4 MB MaxSize of value;
*/
public static final int MAX_SIZE_OF_VALUE = 4 * 1024 * 1024;
- public static final String ORIG_KEY_SEPERATOR = LedgerConsts.KEY_SEPERATOR;
-
- public static final String SN_PREFIX = "SN" + ORIG_KEY_SEPERATOR;
- public static final String DATA_PREFIX = "KV" + ORIG_KEY_SEPERATOR;
- public static final String MERKLE_TREE_PREFIX = "MKL" + ORIG_KEY_SEPERATOR;
+ public static final Bytes SN_PREFIX = Bytes.fromString("SN" + LedgerConsts.KEY_SEPERATOR);
+ public static final Bytes DATA_PREFIX = Bytes.fromString("KV" + LedgerConsts.KEY_SEPERATOR);
+ public static final Bytes MERKLE_TREE_PREFIX = Bytes.fromString("MKL" + LedgerConsts.KEY_SEPERATOR);
private final Bytes snKeyPrefix;
private final Bytes dataKeyPrefix;
private final Bytes merkleKeyPrefix;
+ @SuppressWarnings("unchecked")
+ private static final DataEntry[] EMPTY_ENTRIES = new DataEntry[0];
+
private BufferedKVStorage bufferedStorage;
private VersioningKVStorage valueStorage;
@@ -71,6 +75,18 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
*/
public MerkleDataSet(CryptoSetting setting, String keyPrefix, ExPolicyKVStorage exPolicyStorage,
VersioningKVStorage versioningStorage) {
+ this(setting, Bytes.fromString(keyPrefix), exPolicyStorage, versioningStorage);
+ }
+
+ /**
+ * 创建一个新的 MerkleDataSet;
+ *
+ * @param setting 密码设置;
+ * @param exPolicyStorage 默克尔树的存储;
+ * @param versioningStorage 数据的存储;
+ */
+ public MerkleDataSet(CryptoSetting setting, Bytes keyPrefix, ExPolicyKVStorage exPolicyStorage,
+ VersioningKVStorage versioningStorage) {
// 缓冲对KV的写入;
this.bufferedStorage = new BufferedKVStorage(exPolicyStorage, versioningStorage, false);
@@ -79,15 +95,15 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
// bufferedStorage);
// this.snStorage = PrefixAppender.prefix(SN_PREFIX, (ExPolicyKVStorage)
// bufferedStorage);
- snKeyPrefix = Bytes.fromString(keyPrefix + SN_PREFIX);
- dataKeyPrefix = Bytes.fromString(keyPrefix + DATA_PREFIX);
+ snKeyPrefix = keyPrefix.concat(SN_PREFIX);
+ dataKeyPrefix = keyPrefix.concat(DATA_PREFIX);
this.valueStorage = bufferedStorage;
this.snStorage = bufferedStorage;
// MerkleTree 本身是可缓冲的;
// ExPolicyKVStorage merkleTreeStorage =
// PrefixAppender.prefix(MERKLE_TREE_PREFIX, exPolicyStorage);
- merkleKeyPrefix = Bytes.fromString(keyPrefix + MERKLE_TREE_PREFIX);
+ merkleKeyPrefix = keyPrefix.concat(MERKLE_TREE_PREFIX);
ExPolicyKVStorage merkleTreeStorage = exPolicyStorage;
this.merkleTree = new MerkleTree(setting, merkleKeyPrefix, merkleTreeStorage);
this.snGenerator = new MerkleSequenceSNGenerator(merkleTree);
@@ -104,17 +120,33 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
*/
public MerkleDataSet(HashDigest merkleRootHash, CryptoSetting setting, String keyPrefix,
ExPolicyKVStorage exPolicyStorage, VersioningKVStorage versioningStorage, boolean readonly) {
+ this(merkleRootHash, setting, Bytes.fromString(keyPrefix), exPolicyStorage, versioningStorage, readonly);
+ }
+
+ /**
+ * 从指定的 Merkle 根构建的 MerkleDataSet;
+ *
+ * @param dataStorage
+ * @param defaultMerkleHashAlgorithm
+ * @param verifyMerkleHashOnLoad
+ * @param merkleTreeStorage
+ * @param snGenerator
+ */
+ public MerkleDataSet(HashDigest merkleRootHash, CryptoSetting setting, Bytes keyPrefix,
+ ExPolicyKVStorage exPolicyStorage, VersioningKVStorage versioningStorage, boolean readonly) {
// 缓冲对KV的写入;
this.bufferedStorage = new BufferedKVStorage(exPolicyStorage, versioningStorage, false);
// 把存储数据值、SN、Merkle节点的 key 分别加入独立的前缀,避免针对 key 的注入攻击;
- snKeyPrefix = Bytes.fromString(keyPrefix + SN_PREFIX);
- dataKeyPrefix = Bytes.fromString(keyPrefix + DATA_PREFIX);
+// snKeyPrefix = Bytes.fromString(keyPrefix + SN_PREFIX);
+// dataKeyPrefix = Bytes.fromString(keyPrefix + DATA_PREFIX);
+ snKeyPrefix = keyPrefix.concat(SN_PREFIX);
+ dataKeyPrefix = keyPrefix.concat(DATA_PREFIX);
this.valueStorage = bufferedStorage;
this.snStorage = bufferedStorage;
// MerkleTree 本身是可缓冲的;
- merkleKeyPrefix = Bytes.fromString(keyPrefix + MERKLE_TREE_PREFIX);
+ merkleKeyPrefix = keyPrefix.concat(MERKLE_TREE_PREFIX);
ExPolicyKVStorage merkleTreeStorage = exPolicyStorage;
this.merkleTree = new MerkleTree(merkleRootHash, setting, merkleKeyPrefix, merkleTreeStorage, readonly);
@@ -130,15 +162,21 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
this.readonly = true;
}
+ @Override
public long getDataCount() {
return merkleTree.getDataCount();
}
+ /**
+ * 返回理论上允许的最大数据索引;
+ *
+ * @return
+ */
public long getMaxIndex() {
return merkleTree.getMaxSn();
}
- public byte[][] getLatestValues(int fromIndex, int count) {
+ public byte[][] getLatestValues(long fromIndex, int count) {
if (count > LedgerConsts.MAX_LIST_COUNT) {
throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!");
}
@@ -154,24 +192,41 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return values;
}
- public VersioningKVEntry[] getLatestDataEntries(int fromIndex, int count) {
+ public DataEntry[] getLatestDataEntries(long fromIndex, int count) {
if (count > LedgerConsts.MAX_LIST_COUNT) {
throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!");
}
if (fromIndex < 0 || (fromIndex + count) > merkleTree.getDataCount()) {
throw new IllegalArgumentException("Index out of bound!");
}
- VersioningKVEntry[] values = new VersioningKVEntry[count];
+ if (count == 0) {
+ return EMPTY_ENTRIES;
+ }
+ @SuppressWarnings("unchecked")
+ DataEntry[] values = new DataEntry[count];
byte[] bytesValue;
for (int i = 0; i < count; i++) {
MerkleDataNode dataNode = merkleTree.getData(fromIndex + i);
Bytes dataKey = encodeDataKey(dataNode.getKey());
bytesValue = valueStorage.get(dataKey, dataNode.getVersion());
- values[i] = new VersioningKVData(dataNode.getKey(), dataNode.getVersion(), bytesValue);
+ values[i] = new VersioningKVData(dataNode.getKey(), dataNode.getVersion(), bytesValue);
}
return values;
}
+ public DataEntry getLatestDataEntry(long index) {
+ if (index < 0 || index + 1 > merkleTree.getDataCount()) {
+ throw new IllegalArgumentException("Index out of bound!");
+ }
+ byte[] bytesValue;
+ MerkleDataNode dataNode = merkleTree.getData(index);
+ Bytes dataKey = encodeDataKey(dataNode.getKey());
+ bytesValue = valueStorage.get(dataKey, dataNode.getVersion());
+ DataEntry entry = new VersioningKVData(dataNode.getKey(), dataNode.getVersion(),
+ bytesValue);
+ return entry;
+ }
+
/**
* get the data at the specific index;
*
@@ -192,32 +247,34 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
*/
public String getKeyAtIndex(int fromIndex) {
MerkleDataNode dataNode = merkleTree.getData(fromIndex);
- return dataNode.getKey().toUTF8String();
- }
-
- /**
- * Create or update the value associated the specified key if the version
- * checking is passed.
- *
- * The value of the key will be updated only if it's latest version equals the
- * specified version argument.
- * If the key doesn't exist, it will be created when the version arg was -1.
- *
- * If updating is performed, the version of the key increase by 1.
- * If creating is performed, the version of the key initialize by 0.
- *
- * @param key The key of data;
- * @param value The value of data;
- * @param version The expected latest version of the key.
- * @return The new version of the key.
- * If the key is new created success, then return 0;
- * If the key is updated success, then return the new version;
- * If this operation fail by version checking or other reason, then
- * return -1;
- */
- public long setValue(String key, byte[] value, long version) {
- return setValue(Bytes.fromString(key), value, version);
- }
+ // TODO: 未去掉前缀;
+ return dataNode.getKey().toUTF8String();
+ }
+
+// /**
+// * Create or update the value associated the specified key if the version
+// * checking is passed.
+// *
+// * The value of the key will be updated only if it's latest version equals the
+// * specified version argument.
+// * If the key doesn't exist, it will be created when the version arg was -1.
+// *
+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// *
+// * @param key The key of data;
+// * @param value The value of data;
+// * @param version The expected latest version of the key.
+// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then
+// * return -1;
+// */
+// @Override
+// public long setValue(String key, byte[] value, long version) {
+// return setValue(Bytes.fromString(key), value, version);
+// }
/**
* Create or update the value associated the specified key if the version
@@ -239,6 +296,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
* If this operation fail by version checking or other reason, then
* return -1;
*/
+ @Override
public long setValue(Bytes key, byte[] value, long version) {
if (readonly) {
throw new IllegalArgumentException("This merkle dataset is readonly!");
@@ -336,18 +394,19 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return mdn.getVersion();
}
- /**
- * Return the specified version's value;
- *
- * If the key with the specified version doesn't exist, then return null;
- * If the version is specified to -1, then return the latest version's value;
- *
- * @param key
- * @param version
- */
- public byte[] getValue(String key, long version) {
- return getValue(Bytes.fromString(key), version);
- }
+// /**
+// * Return the specified version's value;
+// *
+// * If the key with the specified version doesn't exist, then return null;
+// * If the version is specified to -1, then return the latest version's value;
+// *
+// * @param key
+// * @param version
+// */
+// @Override
+// public byte[] getValue(String key, long version) {
+// return getValue(Bytes.fromString(key), version);
+// }
/**
* Return the specified version's value;
@@ -358,6 +417,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
* @param key
* @param version
*/
+ @Override
public byte[] getValue(Bytes key, long version) {
long latestVersion = getMerkleVersion(key);
if (latestVersion < 0 || version > latestVersion) {
@@ -370,15 +430,16 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return valueStorage.get(dataKey, version);
}
- /**
- * Return the latest version's value;
- *
- * @param key
- * @return return null if not exist;
- */
- public byte[] getValue(String key) {
- return getValue(Bytes.fromString(key));
- }
+// /**
+// * Return the latest version's value;
+// *
+// * @param key
+// * @return return null if not exist;
+// */
+// @Override
+// public byte[] getValue(String key) {
+// return getValue(Bytes.fromString(key));
+// }
/**
* Return the latest version's value;
@@ -386,6 +447,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
* @param key
* @return return null if not exist;
*/
+ @Override
public byte[] getValue(Bytes key) {
long latestVersion = getMerkleVersion(key);
if (latestVersion < 0) {
@@ -395,16 +457,17 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return valueStorage.get(dataKey, latestVersion);
}
- /**
- * Return the latest version entry associated the specified key; If the key
- * doesn't exist, then return -1;
- *
- * @param key
- * @return
- */
- public long getVersion(String key) {
- return getMerkleVersion(Bytes.fromString(key));
- }
+// /**
+// * Return the latest version entry associated the specified key; If the key
+// * doesn't exist, then return -1;
+// *
+// * @param key
+// * @return
+// */
+// @Override
+// public long getVersion(String key) {
+// return getMerkleVersion(Bytes.fromString(key));
+// }
/**
* Return the latest version entry associated the specified key; If the key
@@ -413,33 +476,46 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
* @param key
* @return
*/
+ @Override
public long getVersion(Bytes key) {
return getMerkleVersion(key);
}
- public VersioningKVEntry getDataEntry(String key) {
- return getDataEntry(Bytes.fromString(key));
- }
+// @Override
+// public VersioningKVEntry getDataEntry(String key) {
+// return getDataEntry(key, -1);
+// }
/**
*
* @param key
* @return Null if the key doesn't exist!
*/
- public VersioningKVEntry getDataEntry(Bytes key) {
- long latestVersion = getMerkleVersion(key);
- if (latestVersion < 0) {
- return null;
- }
- Bytes dataKey = encodeDataKey(key);
- byte[] value = valueStorage.get(dataKey, latestVersion);
- if (value == null) {
- return null;
- }
- return new VersioningKVData(key, latestVersion, value);
- }
+ @Override
+ public DataEntry getDataEntry(Bytes key) {
+ return getDataEntry(key, -1);
+ }
+
+// @Override
+// public VersioningKVEntry getDataEntry(String key, long version) {
+// Bytes keyBytes = Bytes.fromString(key);
+// long latestVersion = getMerkleVersion(keyBytes);
+// if (latestVersion < 0 || version > latestVersion) {
+// // key not exist, or the specified version is out of the latest version indexed
+// // by the current merkletree;
+// return null;
+// }
+// version = version < 0 ? latestVersion : version;
+// Bytes dataKey = encodeDataKey(keyBytes);
+// byte[] value = valueStorage.get(dataKey, version);
+// if (value == null) {
+// return null;
+// }
+// return new VersioningKVData(key, version, value);
+// }
- public VersioningKVEntry getDataEntry(Bytes key, long version) {
+ @Override
+ public DataEntry getDataEntry(Bytes key, long version) {
long latestVersion = getMerkleVersion(key);
if (latestVersion < 0 || version > latestVersion) {
// key not exist, or the specified version is out of the latest version indexed
@@ -452,11 +528,21 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
if (value == null) {
return null;
}
- return new VersioningKVData(key, version, value);
+ return new VersioningKVData(key, version, value);
+ }
+
+ @Override
+ public DataIterator iterator() {
+ return new AscDataInterator(getDataCount());
+ }
+
+ @Override
+ public DataIterator iteratorDesc() {
+ return new DescDataInterator(getDataCount());
}
public MerkleDataEntry getMerkleEntry(Bytes key, long version) {
- VersioningKVEntry dataEntry = getDataEntry(key, version);
+ DataEntry dataEntry = getDataEntry(key, version);
if (dataEntry == null) {
return null;
}
@@ -465,7 +551,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
}
public MerkleDataEntry getMerkleEntry(Bytes key) {
- VersioningKVEntry dataEntry = getDataEntry(key);
+ DataEntry dataEntry = getDataEntry(key);
if (dataEntry == null) {
return null;
}
@@ -492,23 +578,23 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
}
/**
- * A wrapper for {@link VersioningKVEntry} and {@link MerkleProof};
+ * A wrapper for {@link DataEntry} and {@link MerkleProof};
*
* @author huanghaiquan
*
*/
private static class MerkleDataEntryWrapper implements MerkleDataEntry {
- private VersioningKVEntry data;
+ private DataEntry data;
private MerkleProof proof;
- public MerkleDataEntryWrapper(VersioningKVEntry data, MerkleProof proof) {
+ public MerkleDataEntryWrapper(DataEntry data, MerkleProof proof) {
this.data = data;
this.proof = proof;
}
@Override
- public VersioningKVEntry getData() {
+ public DataEntry getData() {
return data;
}
@@ -536,4 +622,119 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
merkleTree.cancel();
snGenerator = new MerkleSequenceSNGenerator(merkleTree);
}
+
+ // ----------------------------------------------------------
+
+ private class AscDataInterator implements DataIterator {
+
+ private final long total;
+
+ private long cursor = 0;
+
+ public AscDataInterator(long total) {
+ this.total = total;
+ }
+
+ @Override
+ public void skip(long count) {
+ cursor = nextCursor(count);
+ }
+
+ private long nextCursor(long skippingCount) {
+ long c = cursor + skippingCount;
+ return c > total ? total : c;
+ }
+
+ @Override
+ public DataEntry next() {
+ if (hasNext()) {
+ DataEntry entry = getLatestDataEntry(cursor);
+ cursor = nextCursor(1);
+ return entry;
+ }
+ return null;
+ }
+
+ @Override
+ public DataEntry[] next(int count) {
+ if (hasNext()) {
+ long from = cursor;
+ long nextCursor = nextCursor(count);
+ long c = nextCursor - cursor;
+ if (c > LedgerConsts.MAX_LIST_COUNT) {
+ throw new IllegalArgumentException(
+ "Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!");
+ }
+ DataEntry[] entries = getLatestDataEntries(from, (int) c);
+ cursor = nextCursor;
+ return entries;
+ }
+ return EMPTY_ENTRIES;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return cursor < total;
+ }
+
+ }
+
+ private class DescDataInterator implements DataIterator {
+
+ private final long total;
+
+ private long cursor;
+
+ public DescDataInterator(long total) {
+ this.total = total;
+ this.cursor = total - 1;
+ }
+
+ @Override
+ public void skip(long count) {
+ cursor = nextCursor(count);
+ }
+
+ private long nextCursor(long skippingCount) {
+ long c = cursor - skippingCount;
+ return c < 0 ? -1 : c;
+ }
+
+ @Override
+ public DataEntry next() {
+ if (hasNext()) {
+ DataEntry entry = getLatestDataEntry(cursor);
+ cursor = nextCursor(1);
+ return entry;
+ }
+ return null;
+ }
+
+ @Override
+ public DataEntry[] next(int count) {
+ if (hasNext()) {
+ long nextCursor = nextCursor(count);
+ long from = nextCursor + 1;
+ long c = cursor - nextCursor;
+ if (c > LedgerConsts.MAX_LIST_COUNT) {
+ throw new IllegalArgumentException(
+ "Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!");
+ }
+ DataEntry[] entries = getLatestDataEntries(from, (int) c);
+ // reverse;
+ ArrayUtils.reverse(entries);
+
+ cursor = nextCursor;
+ return entries;
+ }
+ return EMPTY_ENTRIES;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return cursor < total;
+ }
+
+ }
+
}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java
index d86facba..b34cf9fe 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java
@@ -52,8 +52,9 @@ public class MerkleTree implements Transactional {
public static final int TREE_DEGREE = 16;
- public static final int MAX_LEVEL = 15;
+ public static final int MAX_LEVEL = 14;
+ // 正好是 2 的 56 次方(7字节),将 SN 8个字节中的首个字节预留作为 DataNode 的编码格式版本标记;
public static final long MAX_DATACOUNT = power(TREE_DEGREE, MAX_LEVEL);
public static final long MAX_SN = MAX_DATACOUNT - 1;
@@ -147,14 +148,10 @@ public class MerkleTree implements Transactional {
/**
* 创建 Merkle 树;
*
- * @param rootHash
- * 节点的根Hash; 如果指定为 null,则实际上创建一个空的 Merkle Tree;
- * @param verifyOnLoad
- * 从外部存储加载节点时是否校验节点的哈希;
- * @param kvStorage
- * 保存 Merkle 节点的存储服务;
- * @param readonly
- * 是否只读;
+ * @param rootHash 节点的根Hash; 如果指定为 null,则实际上创建一个空的 Merkle Tree;
+ * @param verifyOnLoad 从外部存储加载节点时是否校验节点的哈希;
+ * @param kvStorage 保存 Merkle 节点的存储服务;
+ * @param readonly 是否只读;
*/
public MerkleTree(HashDigest rootHash, CryptoSetting setting, String keyPrefix, ExPolicyKVStorage kvStorage,
boolean readonly) {
@@ -164,14 +161,10 @@ public class MerkleTree implements Transactional {
/**
* 创建 Merkle 树;
*
- * @param rootHash
- * 节点的根Hash; 如果指定为 null,则实际上创建一个空的 Merkle Tree;
- * @param verifyOnLoad
- * 从外部存储加载节点时是否校验节点的哈希;
- * @param kvStorage
- * 保存 Merkle 节点的存储服务;
- * @param readonly
- * 是否只读;
+ * @param rootHash 节点的根Hash; 如果指定为 null,则实际上创建一个空的 Merkle Tree;
+ * @param verifyOnLoad 从外部存储加载节点时是否校验节点的哈希;
+ * @param kvStorage 保存 Merkle 节点的存储服务;
+ * @param readonly 是否只读;
*/
public MerkleTree(HashDigest rootHash, CryptoSetting setting, Bytes keyPrefix, ExPolicyKVStorage kvStorage,
boolean readonly) {
@@ -205,8 +198,7 @@ public class MerkleTree implements Transactional {
*
* 如果 sn 超出范围,则引发 {@link IndexOutOfBoundsException} ;
*
- * @param sn
- * 数据的序列号;
+ * @param sn 数据的序列号;
* @return 默克尔证明的实例;
*/
public MerkleProof getProof(long sn) {
@@ -242,13 +234,10 @@ public class MerkleTree implements Transactional {
* 注:默克尔树只保存指定数据的哈希以及关联的键,而不会保存数据原文,因此调用者需要自己处理对数据的存储;
* 此外,哈希计算是把键和数据内容拼接一起进行计算的;
*
- * @param sn
- * 与此数据唯一相关的序列号;sn 必须大于等于 0 ;
- * @param key
- * 与此数据唯一相关的键;
+ * @param sn 与此数据唯一相关的序列号;sn 必须大于等于 0 ;
+ * @param key 与此数据唯一相关的键;
* @param version
- * @param hashedData
- * 要参与哈希计算的数据内容;注:此参数值并不会被默克尔树保存;
+ * @param hashedData 要参与哈希计算的数据内容;注:此参数值并不会被默克尔树保存;
* @return
*/
public MerkleDataNode setData(long sn, String key, long version, byte[] hashedData) {
@@ -266,13 +255,10 @@ public class MerkleTree implements Transactional {
* 注:默克尔树只保存指定数据的哈希以及关联的键,而不会保存数据原文,因此调用者需要自己处理对数据的存储;
* 此外,哈希计算是把键和数据内容拼接一起进行计算的;
*
- * @param sn
- * 与此数据唯一相关的序列号;sn 必须大于等于 0 ;
- * @param key
- * 与此数据唯一相关的键;
+ * @param sn 与此数据唯一相关的序列号;sn 必须大于等于 0 ;
+ * @param key 与此数据唯一相关的键;
* @param version
- * @param hashedData
- * 要参与哈希计算的数据内容;注:此参数值并不会被默克尔树保存;
+ * @param hashedData 要参与哈希计算的数据内容;注:此参数值并不会被默克尔树保存;
* @return
*/
public MerkleDataNode setData(long sn, Bytes key, long version, byte[] hashedData) {
@@ -285,7 +271,8 @@ public class MerkleTree implements Transactional {
if (sn > MAX_SN) {
throw new IllegalArgumentException("The sn is great than MAX[" + MAX_SN + "]!");
}
- DataNode dataNode = DataNode.newDataNode(setting.getHashAlgorithm(), sn, key, version, hashedData);
+ DataNode dataNode = MerkleTreeEncoder.LATEST_DATANODE_ENCODER.create(setting.getHashAlgorithm(), sn, key,
+ version, hashedData);
updatedDataNodes.put(sn, dataNode);
return dataNode;
}
@@ -591,10 +578,8 @@ public class MerkleTree implements Transactional {
/**
* 重新计算所有子节点以及自身的哈希,并返回新加入的数据节点的数量;
*
- * @param pathNode
- * 需要重新计算 hash 的路径节点;
- * @param updatedNodes
- * 用于记录已更新节点的列表;
+ * @param pathNode 需要重新计算 hash 的路径节点;
+ * @param updatedNodes 用于记录已更新节点的列表;
* @return
*/
@SuppressWarnings("unused")
@@ -732,12 +717,10 @@ public class MerkleTree implements Transactional {
*
* 如果 sn 超出范围,则引发 {@link IndexOutOfBoundsException} ;
*
- * @param sn
- * 数据节点的序列号;
- * @param path
- * 用于记录节点路径的列表,长度必须大于等于当前默克尔树的总的层级(即 path.length 大于等于 root.level +
- * 1);
- * 如果参数为 null,则不记录;
+ * @param sn 数据节点的序列号;
+ * @param path 用于记录节点路径的列表,长度必须大于等于当前默克尔树的总的层级(即 path.length 大于等于 root.level +
+ * 1);
+ * 如果参数为 null,则不记录;
* @return 序列号对应的数据节点;
* 如果不存在,则返回 null,注意,此时指定的路径参数 path 依然写入了查找过程的路径;
*/
@@ -844,7 +827,8 @@ public class MerkleTree implements Transactional {
if (bytes == null || bytes.length == 0) {
return null;
}
- DataNode dataNode = DataNode.parse(bytes);
+
+ DataNode dataNode = MerkleTreeEncoder.resolve(bytes);
if (verify && !hashBytes.equals(dataNode.nodeHash)) {
String keyStr = hashBytes.toBase58();
String actualHashStr = dataNode.nodeHash.toBase58();
@@ -861,8 +845,7 @@ public class MerkleTree implements Transactional {
* 注:此方法不处理溢出;调用者需要自行规避;
*
* @param value
- * @param x
- * 大于等于 0 的整数;
+ * @param x 大于等于 0 的整数;
* @return
*/
private static long power(long value, int x) {
@@ -1140,14 +1123,10 @@ public class MerkleTree implements Transactional {
/**
* 创建一个路径节点;
*
- * @param hashAlgorithm
- * 生成节点采用的哈希算法;
- * @param startingSN
- * 路径节点表示的子树的起始序列号;
- * @param level
- * 路径节点的层级深度;路径节点的深度从 1 开始往上递增(数据节点作为树的深度为 0);
- * @param dataCount
- * 路径节点表示的子树所包含的数据节点的数量;
+ * @param hashAlgorithm 生成节点采用的哈希算法;
+ * @param startingSN 路径节点表示的子树的起始序列号;
+ * @param level 路径节点的层级深度;路径节点的深度从 1 开始往上递增(数据节点作为树的深度为 0);
+ * @param dataCount 路径节点表示的子树所包含的数据节点的数量;
*/
private PathNode(CryptoAlgorithm hashAlgorithm, long startingSN, int level, long dataCount) {
this(hashAlgorithm, startingSN, level, dataCount, new HashDigest[TREE_DEGREE], null);
@@ -1338,10 +1317,8 @@ public class MerkleTree implements Transactional {
/**
* 从指定的字节数组反序列化节点;
*
- * @param bytes
- * 字节数组;合法的输入应等同于 {@link #toBytes()} 方法的输出;
- * @param checkHash
- * 是否重新计算并校验节点的哈希;
+ * @param bytes 字节数组;合法的输入应等同于 {@link #toBytes()} 方法的输出;
+ * @param checkHash 是否重新计算并校验节点的哈希;
* @return
*/
private static PathNode parse(byte[] bytes, boolean checkHash) {
@@ -1429,7 +1406,7 @@ public class MerkleTree implements Transactional {
* @author huanghaiquan
*
*/
- private static class DataNode extends AbstractMerkleNode implements MerkleDataNode {
+ static class DataNode extends AbstractMerkleNode implements MerkleDataNode {
private long sn;
@@ -1437,64 +1414,17 @@ public class MerkleTree implements Transactional {
private long version;
- private byte[] dataNodeBytes;
+ private byte[] nodeBytes;
+
+ private HashDigest valueHash;
- private DataNode(long sn, Bytes key, long version, HashDigest dataHash, byte[] dataBytes) {
+ DataNode(HashDigest nodeHash, long sn, Bytes key, long version, HashDigest valueHash, byte[] nodeBytes) {
this.sn = sn;
this.key = key;
this.version = version;
- this.nodeHash = dataHash;
- this.dataNodeBytes = dataBytes;
- }
-
- @SuppressWarnings("unused")
- private static DataNode newDataNode(CryptoAlgorithm hashAlgorithm, long sn, Bytes key, long version,
- byte[] hashedData) {
- return newDataNode(hashAlgorithm.code(), sn, key, version, hashedData);
- }
-
- private static DataNode newDataNode(short hashAlgorithm, long sn, Bytes key, long version, byte[] hashedData) {
- // byte[] keyStrBytes = BytesUtils.toBytes(key);
- // int maskSize = NumberMask.SHORT.getMaskLength(keyStrBytes.length);
- int keySize = key.size();
- int maskSize = NumberMask.SHORT.getMaskLength(keySize);
-
- // int bodySize = 8 + maskSize + keyStrBytes.length + 8;// sn + key + version;
- int bodySize = 8 + maskSize + keySize + 8;// sn + key + version;
- byte[] bodyBytes = new byte[bodySize];
-
- int offset = 0;
- offset += BytesUtils.toBytes(sn, bodyBytes, 0);
-
- // NumberMask.SHORT.writeMask(keyStrBytes.length, bodyBytes, offset);
- NumberMask.SHORT.writeMask(keySize, bodyBytes, offset);
- offset += maskSize;
-
- // System.arraycopy(keyStrBytes, 0, bodyBytes, offset, keyStrBytes.length);
- // System.arraycopy(keyStrBytes, 0, bodyBytes, offset, keyStrBytes.length);
- // offset += keyStrBytes.length;
- offset += key.copyTo(bodyBytes, offset, keySize);
-
- // TODO: version;
- offset += BytesUtils.toBytes(version, bodyBytes, offset);
-
- byte[] dataBytes = BytesUtils.concat(bodyBytes, hashedData);
-
- HashFunction hashFunc = Crypto.getHashFunction(hashAlgorithm);
- HashDigest dataHash = hashFunc.hash(dataBytes);
-
- int hashMaskSize = NumberMask.TINY.getMaskLength(dataHash.size());
- int dataNodeSize = bodySize + hashMaskSize + dataHash.size();
- byte[] dataNodeBytes = new byte[dataNodeSize];
-
- offset = 0;
- System.arraycopy(bodyBytes, 0, dataNodeBytes, offset, bodySize);
- offset += bodySize;
- NumberMask.TINY.writeMask(dataHash.size(), dataNodeBytes, offset);
- offset += hashMaskSize;
- System.arraycopy(dataHash.toBytes(), 0, dataNodeBytes, offset, dataHash.size());
-
- return new DataNode(sn, key, version, dataHash, dataNodeBytes);
+ this.nodeHash = nodeHash;
+ this.valueHash = valueHash;
+ this.nodeBytes = nodeBytes;
}
@Override
@@ -1547,6 +1477,11 @@ public class MerkleTree implements Transactional {
return version;
}
+ @Override
+ public HashDigest getValueHash() {
+ return valueHash;
+ }
+
@Override
public byte[] toBytes() {
// ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -1574,38 +1509,7 @@ public class MerkleTree implements Transactional {
//
// System.arraycopy(nodeHash.toBytes(), 0, totalBytes, offset, hashSize);
- return dataNodeBytes;
- }
-
- private static DataNode parse(byte[] bytes) {
- // InputStream in = new ByteArrayInputStream(bytes);
-
- int offset = 0;
- long sn = BytesUtils.toLong(bytes, offset);
- offset += 8;
-
- // byte[] keyBytes = BytesEncoding.read(NumberMask.SHORT, in);
- // String key = BytesUtils.toString(keyBytes);
- int keySize = NumberMask.SHORT.resolveMaskedNumber(bytes, offset);
- offset += NumberMask.SHORT.getMaskLength(keySize);
- byte[] keyBytes = new byte[keySize];
- System.arraycopy(bytes, offset, keyBytes, 0, keySize);
- offset += keySize;
- // String key = BytesUtils.toString(keyBytes);
- Bytes key = new Bytes(keyBytes);
-
- // long version = BytesUtils.readLong(in);
- long version = BytesUtils.toLong(bytes, offset);
- offset += 8;
-
- // byte[] dataHashBytes = BytesEncoding.read(NumberMask.SHORT, in);
- int hashSize = NumberMask.TINY.resolveMaskedNumber(bytes, offset);
- offset += NumberMask.TINY.getMaskLength(hashSize);
- byte[] dataHashBytes = new byte[hashSize];
- System.arraycopy(bytes, offset, dataHashBytes, 0, hashSize);
- offset += hashSize;
- HashDigest dataHash = new HashDigest(dataHashBytes);
- return new DataNode(sn, key, version, dataHash, bytes);
+ return nodeBytes;
}
@Override
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTreeEncoder.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTreeEncoder.java
new file mode 100644
index 00000000..a02ba65a
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTreeEncoder.java
@@ -0,0 +1,31 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import com.jd.blockchain.ledger.core.MerkleTree.DataNode;
+
+class MerkleTreeEncoder {
+
+ static final MerkleDataNodeEncoder LATEST_DATANODE_ENCODER = new MerkleDataNodeEncoder_V1();
+
+ static final MerkleDataNodeEncoder V0_DATANODE_ENCODER = new MerkleDataNodeEncoder_V0();
+
+ static final List DATANODE_ENCODERS = Collections
+ .unmodifiableList(Arrays.asList(LATEST_DATANODE_ENCODER, V0_DATANODE_ENCODER));
+
+ /**
+ * @param bytes
+ * @return
+ */
+ static DataNode resolve(byte[] bytes) {
+ for (MerkleDataNodeEncoder encoder : MerkleTreeEncoder.DATANODE_ENCODERS) {
+ if (encoder.getFormatVersion() == bytes[0]) {
+ return encoder.resolve(bytes);
+ }
+ }
+
+ throw new IllegalStateException("Unsupported version of DataNode bytes sequence[" + bytes[0] + "]!");
+ }
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java
index 6628aad3..8efd1d10 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java
@@ -1,7 +1,7 @@
package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.PubKey;
-import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.utils.Bytes;
/**
@@ -15,7 +15,7 @@ import com.jd.blockchain.utils.Bytes;
public class OpeningAccessPolicy implements AccountAccessPolicy {
@Override
- public boolean checkDataWriting(AccountHeader account) {
+ public boolean checkDataWriting(BlockchainIdentity account) {
return true;
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java
index dbc077a8..bd629b8a 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java
@@ -28,7 +28,7 @@ public class ParticipantDataset implements Transactional, MerkleProvable, Partic
public ParticipantDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix,
ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) {
- dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly);
+ dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, Bytes.fromString(prefix), exPolicyStorage, verStorage, readonly);
}
@Override
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java
index 14673435..220b519c 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java
@@ -14,10 +14,10 @@ import com.jd.blockchain.ledger.RolePrivileges;
import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.ledger.TransactionPrivilege;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
-import com.jd.blockchain.storage.service.VersioningKVEntry;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;
+import com.jd.blockchain.utils.DataEntry;
public class RolePrivilegeDataset implements Transactional, MerkleProvable, RolePrivilegeSettings {
@@ -30,7 +30,8 @@ public class RolePrivilegeDataset implements Transactional, MerkleProvable, Role
public RolePrivilegeDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix,
ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) {
- dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly);
+ dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, Bytes.fromString(prefix), exPolicyStorage,
+ verStorage, readonly);
}
@Override
@@ -255,7 +256,7 @@ public class RolePrivilegeDataset implements Transactional, MerkleProvable, Role
public RolePrivileges getRolePrivilege(String roleName) {
// 只返回最新版本;
Bytes key = encodeKey(roleName);
- VersioningKVEntry kv = dataset.getDataEntry(key);
+ DataEntry kv = dataset.getDataEntry(key);
if (kv == null) {
return null;
}
@@ -265,7 +266,7 @@ public class RolePrivilegeDataset implements Transactional, MerkleProvable, Role
@Override
public RolePrivileges[] getRolePrivileges(int index, int count) {
- VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(index, count);
+ DataEntry[] kvEntries = dataset.getLatestDataEntries(index, count);
RolePrivileges[] pns = new RolePrivileges[kvEntries.length];
PrivilegeSet privilege;
for (int i = 0; i < pns.length; i++) {
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java
index d3ad83ba..2fde0054 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java
@@ -1,12 +1,5 @@
package com.jd.blockchain.ledger.core;
-import java.util.Set;
-
-import com.jd.blockchain.ledger.BlockchainIdentity;
-import com.jd.blockchain.ledger.LedgerPermission;
-import com.jd.blockchain.ledger.LedgerSecurityException;
-import com.jd.blockchain.ledger.TransactionPermission;
-
public class SecurityContext {
private static ThreadLocal policyHolder = new ThreadLocal();
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java
index 28c6bff4..fe336005 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java
@@ -88,7 +88,8 @@ public class TransactionSet implements Transactional, TransactionQuery {
public TransactionSet(HashDigest txRootHash, CryptoSetting setting, String keyPrefix,
ExPolicyKVStorage merkleTreeStorage, VersioningKVStorage dataStorage, boolean readonly) {
this.txStatePrefix = Bytes.fromString(keyPrefix + TX_STATE_PREFIX);
- this.txSet = new MerkleDataSet(txRootHash, setting, keyPrefix, merkleTreeStorage, dataStorage, readonly);
+ this.txSet = new MerkleDataSet(txRootHash, setting, Bytes.fromString(keyPrefix), merkleTreeStorage, dataStorage,
+ readonly);
}
/**
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java
index 49743f90..87696e86 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java
@@ -1,9 +1,9 @@
package com.jd.blockchain.ledger.core;
-import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.BytesValue;
-import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.UserInfo;
import com.jd.blockchain.utils.Bytes;
@@ -13,72 +13,73 @@ import com.jd.blockchain.utils.Bytes;
* @author huanghaiquan
*
*/
-public class UserAccount implements UserInfo {
+public class UserAccount extends AccountDecorator implements UserInfo { // implements UserInfo {
- private static final Bytes USER_INFO_PREFIX = Bytes.fromString("PROP" + LedgerConsts.KEY_SEPERATOR);
+ private static final String USER_INFO_PREFIX = "PROP" + LedgerConsts.KEY_SEPERATOR;
- private static final Bytes DATA_PUB_KEY = Bytes.fromString("DATA-PUBKEY");
+ private static final String DATA_PUB_KEY = "DATA-PUBKEY";
- private MerkleAccount baseAccount;
+ public UserAccount(CompositeAccount baseAccount) {
+ super(baseAccount);
+ }
+
+ private PubKey dataPubKey;
+
@Override
public Bytes getAddress() {
- return baseAccount.getAddress();
+ return getID().getAddress();
}
@Override
public PubKey getPubKey() {
- return baseAccount.getPubKey();
+ return getID().getPubKey();
}
-
+
@Override
- public HashDigest getRootHash() {
- return baseAccount.getRootHash();
- }
-
- public UserAccount(MerkleAccount baseAccount) {
- this.baseAccount = baseAccount;
- }
-
public PubKey getDataPubKey() {
- BytesValue pkBytes = baseAccount.getBytes(DATA_PUB_KEY);
- if (pkBytes == null) {
- return null;
+ if (dataPubKey == null) {
+ BytesValue pkBytes = getHeaders().getValue(DATA_PUB_KEY);
+ if (pkBytes == null) {
+ return null;
+ }
+ dataPubKey = new PubKey(pkBytes.getBytes().toBytes());
}
- return new PubKey(pkBytes.getValue().toBytes());
+ return dataPubKey;
}
- public long setDataPubKey(PubKey pubKey) {
- byte[] pkBytes = pubKey.toBytes();
- return baseAccount.setBytes(DATA_PUB_KEY, BytesData.fromBytes(pkBytes), -1);
+ public void setDataPubKey(PubKey pubKey) {
+ long version = getHeaders().getVersion(DATA_PUB_KEY);
+ setDataPubKey(pubKey, version);
}
- public long setDataPubKey(PubKey pubKey, long version) {
- byte[] pkBytes = pubKey.toBytes();
- return baseAccount.setBytes(DATA_PUB_KEY, BytesData.fromBytes(pkBytes), version);
+ public void setDataPubKey(PubKey pubKey, long version) {
+ TypedValue value = TypedValue.fromPubKey(dataPubKey);
+ long newVersion = getHeaders().setValue(DATA_PUB_KEY, value, version);
+ if (newVersion > -1) {
+ dataPubKey = pubKey;
+ } else {
+ throw new LedgerException("Data public key was updated failed!");
+ }
}
public long setProperty(String key, String value, long version) {
- return setProperty(Bytes.fromString(key), value, version);
+ return getHeaders().setValue(encodePropertyKey(key), TypedValue.fromText(value), version);
}
- public long setProperty(Bytes key, String value, long version) {
- return baseAccount.setBytes(encodePropertyKey(key), BytesData.fromText(value), version);
+ public String getProperty(String key) {
+ BytesValue value = getHeaders().getValue(encodePropertyKey(key));
+ return value == null ? null : value.getBytes().toUTF8String();
}
- public String getProperty(Bytes key) {
- BytesValue value = baseAccount.getBytes(encodePropertyKey(key));
- return value == null ? null : value.getValue().toUTF8String();
+ public String getProperty(String key, long version) {
+ BytesValue value = getHeaders().getValue(encodePropertyKey(key), version);
+ return value == null ? null : value.getBytes().toUTF8String();
}
- public String getProperty(Bytes key, long version) {
- BytesValue value = baseAccount.getBytes(encodePropertyKey(key), version);
- return value == null ? null : value.getValue().toUTF8String();
+ private String encodePropertyKey(String key) {
+ return USER_INFO_PREFIX+key;
}
- private Bytes encodePropertyKey(Bytes key) {
- // return key.concatTo(USER_INFO_PREFIX);
- return USER_INFO_PREFIX.concat(key);
- }
}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java
index a2e25356..bc71711d 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java
@@ -2,7 +2,7 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
-import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.MerkleProof;
@@ -21,19 +21,20 @@ public class UserAccountSet implements Transactional, UserAccountQuery {
public UserAccountSet(CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage simpleStorage,
VersioningKVStorage versioningStorage, AccountAccessPolicy accessPolicy) {
- accountSet = new MerkleAccountSet(cryptoSetting, keyPrefix, simpleStorage, versioningStorage, accessPolicy);
+ accountSet = new MerkleAccountSet(cryptoSetting, Bytes.fromString(keyPrefix), simpleStorage, versioningStorage,
+ accessPolicy);
}
public UserAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix,
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly,
AccountAccessPolicy accessPolicy) {
- accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly,
- accessPolicy);
+ accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, Bytes.fromString(keyPrefix), exStorage,
+ verStorage, readonly, accessPolicy);
}
@Override
- public AccountHeader[] getHeaders(int fromIndex, int count) {
- return accountSet.getHeaders(fromIndex,count);
+ public BlockchainIdentity[] getHeaders(int fromIndex, int count) {
+ return accountSet.getHeaders(fromIndex, count);
}
/**
@@ -49,7 +50,7 @@ public class UserAccountSet implements Transactional, UserAccountQuery {
public boolean isReadonly() {
return accountSet.isReadonly();
}
-
+
void setReadonly() {
accountSet.setReadonly();
}
@@ -63,7 +64,7 @@ public class UserAccountSet implements Transactional, UserAccountQuery {
public MerkleProof getProof(Bytes key) {
return accountSet.getProof(key);
}
-
+
@Override
public UserAccount getAccount(String address) {
return getAccount(Bytes.fromBase58(address));
@@ -71,7 +72,7 @@ public class UserAccountSet implements Transactional, UserAccountQuery {
@Override
public UserAccount getAccount(Bytes address) {
- MerkleAccount baseAccount = accountSet.getAccount(address);
+ CompositeAccount baseAccount = accountSet.getAccount(address);
return new UserAccount(baseAccount);
}
@@ -82,7 +83,7 @@ public class UserAccountSet implements Transactional, UserAccountQuery {
@Override
public UserAccount getAccount(Bytes address, long version) {
- MerkleAccount baseAccount = accountSet.getAccount(address, version);
+ CompositeAccount baseAccount = accountSet.getAccount(address, version);
return new UserAccount(baseAccount);
}
@@ -93,14 +94,12 @@ public class UserAccountSet implements Transactional, UserAccountQuery {
*
* 如果指定的地址和公钥不匹配,则会引发 {@link LedgerException} 异常;
*
- * @param address
- * 区块链地址;
- * @param pubKey
- * 公钥;
+ * @param address 区块链地址;
+ * @param pubKey 公钥;
* @return 注册成功的用户对象;
*/
public UserAccount register(Bytes address, PubKey pubKey) {
- MerkleAccount baseAccount = accountSet.register(address, pubKey);
+ CompositeAccount baseAccount = accountSet.register(address, pubKey);
return new UserAccount(baseAccount);
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataset.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataset.java
index 25ecd85a..8aa45ebc 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataset.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataset.java
@@ -13,10 +13,10 @@ import com.jd.blockchain.ledger.RolesPolicy;
import com.jd.blockchain.ledger.UserRoles;
import com.jd.blockchain.ledger.UserAuthorizationSettings;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
-import com.jd.blockchain.storage.service.VersioningKVEntry;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;
+import com.jd.blockchain.utils.DataEntry;
/**
* User-Role authorization data set;
@@ -35,7 +35,7 @@ public class UserRoleDataset implements Transactional, MerkleProvable, UserAutho
public UserRoleDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix,
ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) {
- dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly);
+ dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, Bytes.fromString(prefix), exPolicyStorage, verStorage, readonly);
}
@Override
@@ -168,7 +168,7 @@ public class UserRoleDataset implements Transactional, MerkleProvable, UserAutho
@Override
public UserRoles getUserRoles(Bytes userAddress) {
// 只返回最新版本;
- VersioningKVEntry kv = dataset.getDataEntry(userAddress);
+ DataEntry kv = dataset.getDataEntry(userAddress);
if (kv == null) {
return null;
}
@@ -178,7 +178,7 @@ public class UserRoleDataset implements Transactional, MerkleProvable, UserAutho
@Override
public UserRoles[] getUserRoles() {
- VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(0, (int) dataset.getDataCount());
+ DataEntry[] kvEntries = dataset.getLatestDataEntries(0, (int) dataset.getDataCount());
UserRoles[] pns = new UserRoles[kvEntries.length];
RoleSet roleset;
for (int i = 0; i < pns.length; i++) {
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractLedgerContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractLedgerContext.java
index 0d0d3c3d..fe3f9826 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractLedgerContext.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractLedgerContext.java
@@ -5,7 +5,24 @@ import java.util.List;
import com.jd.blockchain.contract.LedgerContext;
import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.ledger.*;
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.BytesValue;
+import com.jd.blockchain.ledger.ContractInfo;
+import com.jd.blockchain.ledger.DataAccountKVSetOperation;
+import com.jd.blockchain.ledger.DataAccountRegisterOperation;
+import com.jd.blockchain.ledger.TypedKVEntry;
+import com.jd.blockchain.ledger.KVInfoVO;
+import com.jd.blockchain.ledger.LedgerAdminInfo;
+import com.jd.blockchain.ledger.LedgerBlock;
+import com.jd.blockchain.ledger.LedgerInfo;
+import com.jd.blockchain.ledger.LedgerMetadata;
+import com.jd.blockchain.ledger.LedgerTransaction;
+import com.jd.blockchain.ledger.Operation;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.TransactionState;
+import com.jd.blockchain.ledger.TypedValue;
+import com.jd.blockchain.ledger.UserInfo;
+import com.jd.blockchain.ledger.UserRegisterOperation;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.transaction.BlockchainQueryService;
import com.jd.blockchain.transaction.DataAccountKVSetOperationBuilder;
@@ -150,22 +167,22 @@ public class ContractLedgerContext implements LedgerContext {
}
@Override
- public AccountHeader getDataAccount(HashDigest ledgerHash, String address) {
+ public BlockchainIdentity getDataAccount(HashDigest ledgerHash, String address) {
return innerQueryService.getDataAccount(ledgerHash, address);
}
@Override
- public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) {
+ public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) {
return innerQueryService.getDataEntries(ledgerHash, address, keys);
}
@Override
- public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
+ public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
return innerQueryService.getDataEntries(ledgerHash, address, kvInfoVO);
}
@Override
- public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {
+ public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {
return innerQueryService.getDataEntries(ledgerHash, address, fromIndex, count);
}
@@ -182,17 +199,17 @@ public class ContractLedgerContext implements LedgerContext {
// ---------------------------user()----------------------------
@Override
- public AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count) {
+ public BlockchainIdentity[] getUsers(HashDigest ledgerHash, int fromIndex, int count) {
return innerQueryService.getUsers(ledgerHash, fromIndex, count);
}
@Override
- public AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) {
+ public BlockchainIdentity[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) {
return innerQueryService.getDataAccounts(ledgerHash, fromIndex, count);
}
@Override
- public AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) {
+ public BlockchainIdentity[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) {
return innerQueryService.getContractAccounts(ledgerHash, fromIndex, count);
}
@@ -268,7 +285,7 @@ public class ContractLedgerContext implements LedgerContext {
@Override
public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) {
- BytesValue bytesValue = BytesData.fromText(value);
+ BytesValue bytesValue = TypedValue.fromText(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op);
return this;
@@ -276,7 +293,7 @@ public class ContractLedgerContext implements LedgerContext {
@Override
public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) {
- BytesValue bytesValue = BytesData.fromBytes(value);
+ BytesValue bytesValue = TypedValue.fromBytes(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op);
return this;
@@ -284,7 +301,7 @@ public class ContractLedgerContext implements LedgerContext {
@Override
public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) {
- BytesValue bytesValue = BytesData.fromInt64(value);
+ BytesValue bytesValue = TypedValue.fromInt64(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op);
return this;
@@ -301,7 +318,7 @@ public class ContractLedgerContext implements LedgerContext {
@Override
public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) {
- BytesValue bytesValue = BytesData.fromJSON(value);
+ BytesValue bytesValue = TypedValue.fromJSON(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op);
return this;
@@ -309,7 +326,7 @@ public class ContractLedgerContext implements LedgerContext {
@Override
public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) {
- BytesValue bytesValue = BytesData.fromXML(value);
+ BytesValue bytesValue = TypedValue.fromXML(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op);
return this;
@@ -317,7 +334,7 @@ public class ContractLedgerContext implements LedgerContext {
@Override
public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) {
- BytesValue bytesValue = BytesData.fromBytes(value);
+ BytesValue bytesValue = TypedValue.fromBytes(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op);
return this;
@@ -325,7 +342,7 @@ public class ContractLedgerContext implements LedgerContext {
@Override
public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) {
- BytesValue bytesValue = BytesData.fromImage(value);
+ BytesValue bytesValue = TypedValue.fromImage(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op);
return this;
@@ -333,7 +350,7 @@ public class ContractLedgerContext implements LedgerContext {
@Override
public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) {
- BytesValue bytesValue = BytesData.fromTimestamp(value);
+ BytesValue bytesValue = TypedValue.fromTimestamp(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op);
return this;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java
index 0f9fdb2b..dfab3f1c 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java
@@ -5,6 +5,7 @@ import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.DataAccountKVSetOperation.KVWriteEntry;
import com.jd.blockchain.ledger.DataVersionConflictException;
import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerQuery;
@@ -37,7 +38,7 @@ public class DataAccountKVSetOperationHandle extends AbstractLedgerOperationHand
KVWriteEntry[] writeSet = kvWriteOp.getWriteSet();
long v = -1L;
for (KVWriteEntry kvw : writeSet) {
- v = account.setBytes(Bytes.fromString(kvw.getKey()), kvw.getValue(), kvw.getExpectedVersion());
+ v = account.getDataset().setValue(kvw.getKey(), TypedValue.wrap(kvw.getValue()), kvw.getExpectedVersion());
if (v < 0) {
throw new DataVersionConflictException();
}
diff --git a/source/ledger/ledger-core/src/test/java/com/jd/blockchain/ledger/core/MerkleDataNodeEncoderTest.java b/source/ledger/ledger-core/src/test/java/com/jd/blockchain/ledger/core/MerkleDataNodeEncoderTest.java
new file mode 100644
index 00000000..d8757e0e
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/com/jd/blockchain/ledger/core/MerkleDataNodeEncoderTest.java
@@ -0,0 +1,153 @@
+package com.jd.blockchain.ledger.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.Random;
+
+import org.junit.Test;
+
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.crypto.HashFunction;
+import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
+import com.jd.blockchain.ledger.core.MerkleTree.DataNode;
+import com.jd.blockchain.utils.Bytes;
+
+public class MerkleDataNodeEncoderTest {
+
+ @Test
+ public void testEnocoderV0() {
+
+
+ Random rand = new Random();
+
+ byte[] data = new byte[512];
+ byte[] keyBytes = new byte[256];
+
+ rand.nextBytes(data);
+ rand.nextBytes(keyBytes);
+ Bytes key = new Bytes(keyBytes);
+
+ long sn = 1024;
+ long version = 1;
+ doTestV0(sn, version, key, data);
+
+ sn = 0;
+ version = 1000;
+ doTestV0(sn, version, key, data);
+
+ sn = (1 << 56) -1;
+ version = 1000;
+ doTestV0(sn, version, key, data);
+ }
+
+ private void doTestV0(long sn, long version, Bytes key, byte[] data) {
+ MerkleDataNodeEncoder encoderV0 = new MerkleDataNodeEncoder_V0();
+ DataNode nodeV0 = encoderV0.create(ClassicAlgorithm.SHA256.code(), sn, key, version, data);
+
+ assertNull(nodeV0.getValueHash());
+
+ assertEquals(sn, nodeV0.getSN());
+ assertEquals(version, nodeV0.getVersion());
+ assertEquals(key, nodeV0.getKey());
+
+ byte[] nodeBytes = nodeV0.toBytes();
+
+ DataNode nodeV0_reversed = encoderV0.resolve(nodeBytes);
+ assertNull(nodeV0_reversed.getValueHash());
+
+ assertEquals(nodeV0.getNodeHash(), nodeV0_reversed.getNodeHash());
+ assertEquals(encoderV0.getFormatVersion(), nodeBytes[0]);
+
+ assertEquals(sn, nodeV0_reversed.getSN());
+ assertEquals(version, nodeV0_reversed.getVersion());
+ assertEquals(key, nodeV0_reversed.getKey());
+ }
+
+ @Test
+ public void testEnocoderV1() {
+ Random rand = new Random();
+
+ byte[] data = new byte[512];
+ byte[] keyBytes = new byte[256];
+
+ rand.nextBytes(data);
+ rand.nextBytes(keyBytes);
+ Bytes key = new Bytes(keyBytes);
+
+ long sn = 1024;
+ long version = 1;
+ doTestV1(sn, version, key, data);
+
+ sn = 0;
+ version = 10088;
+ doTestV1(sn, version, key, data);
+
+ sn = (1 << 56) -1;
+ version = 1000;
+ doTestV1(sn, version, key, data);
+ }
+
+ private void doTestV1(long sn, long version, Bytes key, byte[] data) {
+ HashFunction hashFunc = Crypto.getHashFunction(ClassicAlgorithm.SHA256);
+ HashDigest dataHash = hashFunc.hash(data);
+
+ MerkleDataNodeEncoder encoderV1 = new MerkleDataNodeEncoder_V1();
+ DataNode node = encoderV1.create(ClassicAlgorithm.SHA256.code(), sn, key, version, data);
+
+ assertEquals(dataHash, node.getValueHash());
+
+ assertEquals(sn, node.getSN());
+ assertEquals(version, node.getVersion());
+ assertEquals(key, node.getKey());
+
+ byte[] nodeBytes = node.toBytes();
+
+ DataNode node_reversed = encoderV1.resolve(nodeBytes);
+
+ assertEquals(dataHash, node_reversed.getValueHash());
+ assertEquals(node.getNodeHash(), node_reversed.getNodeHash());
+ assertEquals(encoderV1.getFormatVersion(), nodeBytes[0]);
+
+ assertEquals(sn, node_reversed.getSN());
+ assertEquals(version, node_reversed.getVersion());
+ assertEquals(key, node_reversed.getKey());
+ }
+
+ @Test
+ public void testCompatibility() {
+ Random rand = new Random();
+
+ byte[] data = new byte[512];
+ byte[] keyBytes = new byte[256];
+
+ rand.nextBytes(data);
+ rand.nextBytes(keyBytes);
+
+ Bytes key = new Bytes(keyBytes);
+
+ long sn = 1024;
+ long version = 1;
+
+
+ PreviousDataNode pdataNode = PreviousDataNode.newDataNode(ClassicAlgorithm.SHA256.code(), sn, key, version,
+ data);
+
+ MerkleDataNodeEncoder encoderV0 = new MerkleDataNodeEncoder_V0();
+ DataNode dataNode = encoderV0.create(ClassicAlgorithm.SHA256.code(), sn, key, version, data);
+
+ assertEquals(pdataNode.getNodeHash(), dataNode.getNodeHash());
+ assertEquals(pdataNode.getSN(), dataNode.getSN());
+ assertEquals(pdataNode.getVersion(), dataNode.getVersion());
+ assertEquals(pdataNode.getKey(), dataNode.getKey());
+
+ DataNode dataNode_reversed = encoderV0.resolve(pdataNode.toBytes());
+
+ assertNull(dataNode_reversed.getValueHash());
+ assertEquals(pdataNode.getNodeHash(), dataNode_reversed.getNodeHash());
+ assertEquals(pdataNode.getSN(), dataNode_reversed.getSN());
+ assertEquals(pdataNode.getVersion(), dataNode_reversed.getVersion());
+ assertEquals(pdataNode.getKey(), dataNode_reversed.getKey());
+ }
+}
diff --git a/source/ledger/ledger-core/src/test/java/com/jd/blockchain/ledger/core/PreviousDataNode.java b/source/ledger/ledger-core/src/test/java/com/jd/blockchain/ledger/core/PreviousDataNode.java
new file mode 100644
index 00000000..49f0039c
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/com/jd/blockchain/ledger/core/PreviousDataNode.java
@@ -0,0 +1,191 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.CryptoAlgorithm;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.crypto.HashFunction;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.io.BytesUtils;
+import com.jd.blockchain.utils.io.NumberMask;
+
+
+
+/**
+ * A copy of previous version of com.jd.blockchain.ledger.core.MerkleTree.DataNode;
+ *
+ * @author huanghaiquan
+ *
+ */
+public class PreviousDataNode {
+
+ private HashDigest nodeHash;
+
+ private long sn;
+
+ private Bytes key;
+
+ private long version;
+
+ private byte[] dataNodeBytes;
+
+ private PreviousDataNode(long sn, Bytes key, long version, HashDigest dataHash, byte[] dataBytes) {
+ this.sn = sn;
+ this.key = key;
+ this.version = version;
+ this.nodeHash = dataHash;
+ this.dataNodeBytes = dataBytes;
+ }
+
+ static PreviousDataNode newDataNode(CryptoAlgorithm hashAlgorithm, long sn, Bytes key, long version,
+ byte[] hashedData) {
+ return newDataNode(hashAlgorithm.code(), sn, key, version, hashedData);
+ }
+
+ static PreviousDataNode newDataNode(short hashAlgorithm, long sn, Bytes key, long version, byte[] hashedData) {
+ // byte[] keyStrBytes = BytesUtils.toBytes(key);
+ // int maskSize = NumberMask.SHORT.getMaskLength(keyStrBytes.length);
+ int keySize = key.size();
+ int maskSize = NumberMask.SHORT.getMaskLength(keySize);
+
+ // int bodySize = 8 + maskSize + keyStrBytes.length + 8;// sn + key + version;
+ int bodySize = 8 + maskSize + keySize + 8;// sn + key + version;
+ byte[] bodyBytes = new byte[bodySize];
+
+ int offset = 0;
+ offset += BytesUtils.toBytes(sn, bodyBytes, 0);
+
+ // NumberMask.SHORT.writeMask(keyStrBytes.length, bodyBytes, offset);
+ NumberMask.SHORT.writeMask(keySize, bodyBytes, offset);
+ offset += maskSize;
+
+ // System.arraycopy(keyStrBytes, 0, bodyBytes, offset, keyStrBytes.length);
+ // System.arraycopy(keyStrBytes, 0, bodyBytes, offset, keyStrBytes.length);
+ // offset += keyStrBytes.length;
+ offset += key.copyTo(bodyBytes, offset, keySize);
+
+ // TODO: version;
+ offset += BytesUtils.toBytes(version, bodyBytes, offset);
+
+ byte[] dataBytes = BytesUtils.concat(bodyBytes, hashedData);
+
+ HashFunction hashFunc = Crypto.getHashFunction(hashAlgorithm);
+ HashDigest dataHash = hashFunc.hash(dataBytes);
+
+ int hashMaskSize = NumberMask.TINY.getMaskLength(dataHash.size());
+ int dataNodeSize = bodySize + hashMaskSize + dataHash.size();
+ byte[] dataNodeBytes = new byte[dataNodeSize];
+
+ offset = 0;
+ System.arraycopy(bodyBytes, 0, dataNodeBytes, offset, bodySize);
+ offset += bodySize;
+ NumberMask.TINY.writeMask(dataHash.size(), dataNodeBytes, offset);
+ offset += hashMaskSize;
+ System.arraycopy(dataHash.toBytes(), 0, dataNodeBytes, offset, dataHash.size());
+
+ return new PreviousDataNode(sn, key, version, dataHash, dataNodeBytes);
+ }
+
+ public HashDigest getNodeHash() {
+ return nodeHash;
+ }
+
+ protected long getStartingSN() {
+ return sn;
+ }
+
+ protected long getDataCount() {
+ return 1;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.jd.blockchain.ledger.core.MerkleDataNode#getLevel()
+ */
+ public int getLevel() {
+ return 0;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.jd.blockchain.ledger.core.MerkleDataNode#getSN()
+ */
+ public long getSN() {
+ return sn;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.jd.blockchain.ledger.core.MerkleDataNode#getKey()
+ */
+ public Bytes getKey() {
+ return key;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.jd.blockchain.ledger.core.MerkleDataNode#getVersion()
+ */
+ public long getVersion() {
+ return version;
+ }
+
+ public byte[] toBytes() {
+ return dataNodeBytes;
+ }
+
+ static PreviousDataNode parse(byte[] bytes) {
+ // InputStream in = new ByteArrayInputStream(bytes);
+
+ int offset = 0;
+ long sn = BytesUtils.toLong(bytes, offset);
+ offset += 8;
+
+ // byte[] keyBytes = BytesEncoding.read(NumberMask.SHORT, in);
+ // String key = BytesUtils.toString(keyBytes);
+ int keySize = NumberMask.SHORT.resolveMaskedNumber(bytes, offset);
+ offset += NumberMask.SHORT.getMaskLength(keySize);
+ byte[] keyBytes = new byte[keySize];
+ System.arraycopy(bytes, offset, keyBytes, 0, keySize);
+ offset += keySize;
+ // String key = BytesUtils.toString(keyBytes);
+ Bytes key = new Bytes(keyBytes);
+
+ // long version = BytesUtils.readLong(in);
+ long version = BytesUtils.toLong(bytes, offset);
+ offset += 8;
+
+ // byte[] dataHashBytes = BytesEncoding.read(NumberMask.SHORT, in);
+ int hashSize = NumberMask.TINY.resolveMaskedNumber(bytes, offset);
+ offset += NumberMask.TINY.getMaskLength(hashSize);
+ byte[] dataHashBytes = new byte[hashSize];
+ System.arraycopy(bytes, offset, dataHashBytes, 0, hashSize);
+ offset += hashSize;
+ HashDigest dataHash = new HashDigest(dataHashBytes);
+ return new PreviousDataNode(sn, key, version, dataHash, bytes);
+ }
+
+ @Override
+ public int hashCode() {
+ return nodeHash.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof PreviousDataNode) {
+ PreviousDataNode node1 = (PreviousDataNode) obj;
+ return this.nodeHash.equals(node1.nodeHash);
+ }
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContractImpl.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContractImpl.java
index 60ee6864..a0bf65be 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContractImpl.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContractImpl.java
@@ -3,7 +3,7 @@ package test.com.jd.blockchain.ledger;
import com.jd.blockchain.contract.ContractEventContext;
import com.jd.blockchain.contract.ContractLifecycleAware;
import com.jd.blockchain.contract.EventProcessingAware;
-import com.jd.blockchain.ledger.KVDataEntry;
+import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.utils.Bytes;
public class TxTestContractImpl implements TxTestContract, ContractLifecycleAware, EventProcessingAware {
@@ -16,7 +16,7 @@ public class TxTestContractImpl implements TxTestContract, ContractLifecycleAwar
@Override
public boolean testReadable() {
- KVDataEntry v1 = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(),
+ TypedKVEntry v1 = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(),
dataAddress.toBase58(), KEY)[0];
String text1 = (String) v1.getValue();
System.out.printf("k1=%s, version=%s \r\n", text1, v1.getVersion());
@@ -26,7 +26,7 @@ public class TxTestContractImpl implements TxTestContract, ContractLifecycleAwar
System.out.printf("new value = %s\r\n", newValue);
eventContext.getLedger().dataAccount(dataAddress).setText(KEY, newValue, v1.getVersion());
- KVDataEntry v2 = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(),
+ TypedKVEntry v2 = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(),
dataAddress.toBase58(), KEY)[0];
System.out.printf("---- read new value ----\r\nk1=%s, version=%s \r\n", v2.getValue(), v2.getVersion());
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java
index 812a8758..99bd2076 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java
@@ -14,11 +14,12 @@ import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
-import com.jd.blockchain.ledger.core.MerkleAccountSet;
-import com.jd.blockchain.ledger.core.MerkleAccount;
+import com.jd.blockchain.ledger.core.CompositeAccount;
import com.jd.blockchain.ledger.core.CryptoConfig;
+import com.jd.blockchain.ledger.core.MerkleAccountSet;
import com.jd.blockchain.ledger.core.OpeningAccessPolicy;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
+import com.jd.blockchain.utils.Bytes;
public class AccountSetTest {
@@ -43,12 +44,13 @@ public class AccountSetTest {
cryptoConf.setHashAlgorithm(ClassicAlgorithm.SHA256);
String keyPrefix = "";
- MerkleAccountSet accset = new MerkleAccountSet(cryptoConf, keyPrefix, storage, storage, accessPolicy);
+ MerkleAccountSet accset = new MerkleAccountSet(cryptoConf, Bytes.fromString(keyPrefix), storage, storage, accessPolicy);
BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate();
accset.register(userKey.getAddress(), userKey.getPubKey());
-
- MerkleAccount userAcc = accset.getAccount(userKey.getAddress());
+
+ //尚未提交之前,可以检索到账户的存在,但版本仍然标记为 -1;
+ CompositeAccount userAcc = accset.getAccount(userKey.getAddress());
assertNotNull(userAcc);
assertTrue(accset.contains(userKey.getAddress()));
@@ -56,13 +58,13 @@ public class AccountSetTest {
HashDigest rootHash = accset.getRootHash();
assertNotNull(rootHash);
- MerkleAccountSet reloadAccSet = new MerkleAccountSet(rootHash, cryptoConf, keyPrefix, storage, storage, true, accessPolicy);
- MerkleAccount reloadUserAcc = reloadAccSet.getAccount(userKey.getAddress());
+ MerkleAccountSet reloadAccSet = new MerkleAccountSet(rootHash, cryptoConf, Bytes.fromString(keyPrefix), storage, storage, true, accessPolicy);
+ CompositeAccount reloadUserAcc = reloadAccSet.getAccount(userKey.getAddress());
assertNotNull(reloadUserAcc);
assertTrue(reloadAccSet.contains(userKey.getAddress()));
- assertEquals(userAcc.getAddress(), reloadUserAcc.getAddress());
- assertEquals(userAcc.getPubKey(), reloadUserAcc.getPubKey());
+ assertEquals(userAcc.getID().getAddress(), reloadUserAcc.getID().getAddress());
+ assertEquals(userAcc.getID().getPubKey(), reloadUserAcc.getID().getPubKey());
}
}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BaseAccountTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BaseAccountTest.java
index 51c8232b..9d55b19e 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BaseAccountTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BaseAccountTest.java
@@ -2,6 +2,7 @@ package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import org.junit.Test;
@@ -12,9 +13,9 @@ import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
-import com.jd.blockchain.ledger.BytesData;
-import com.jd.blockchain.ledger.core.MerkleAccount;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.core.CryptoConfig;
+import com.jd.blockchain.ledger.core.MerkleAccount;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
import com.jd.blockchain.utils.Bytes;
@@ -48,38 +49,39 @@ public class BaseAccountTest {
BlockchainKeypair bck = BlockchainKeyGenerator.getInstance().generate();
// 新建账户;
- MerkleAccount baseAccount = new MerkleAccount(bck.getIdentity(), cryptoConf, keyPrefix, testStorage, testStorage);
- assertFalse(baseAccount.isUpdated());// 空的账户;
+ MerkleAccount baseAccount = new MerkleAccount(bck.getIdentity(), cryptoConf, Bytes.fromString(keyPrefix),
+ testStorage, testStorage);
+ assertTrue(baseAccount.isUpdated());//初始化新账户时,先写入PubKey;
assertFalse(baseAccount.isReadonly());
// 在空白状态下写入数据;
- long v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), 0);
+ long v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A"), 0);
// 预期失败;
assertEquals(-1, v);
- v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), 1);
+ v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A"), 1);
// 预期失败;
assertEquals(-1, v);
- v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), -1);
+ v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A"), -1);
// 预期成功;
assertEquals(0, v);
- v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A-1"), -1);
+ v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A-1"), -1);
// 已经存在版本,指定版本号-1,预期导致失败;
assertEquals(-1, v);
baseAccount.commit();
v = 0;
for (int i = 0; i < 10; i++) {
- long s = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A_" + i), v);
+ long s = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A_" + i), v);
baseAccount.commit();
// 预期成功;
assertEquals(v + 1, s);
v++;
}
- v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A_" + v), v + 1);
+ v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A_" + v), v + 1);
// 预期成功;
assertEquals(-1, v);
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java
index 3232c385..de1d224f 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java
@@ -16,14 +16,35 @@ import static org.mockito.Mockito.when;
import java.io.InputStream;
import java.util.Random;
-import com.jd.blockchain.utils.io.BytesUtils;
-import com.jd.blockchain.ledger.*;
import org.junit.Test;
import org.mockito.Mockito;
import com.jd.blockchain.binaryproto.BinaryProtocol;
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;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerTransaction;
+import com.jd.blockchain.ledger.NodeRequest;
+import com.jd.blockchain.ledger.OperationResult;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.ParticipantRegisterOperation;
+import com.jd.blockchain.ledger.ParticipantStateUpdateOperation;
+import com.jd.blockchain.ledger.TransactionContent;
+import com.jd.blockchain.ledger.TransactionContentBody;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.TransactionRequest;
+import com.jd.blockchain.ledger.TransactionRequestBuilder;
+import com.jd.blockchain.ledger.TransactionResponse;
+import com.jd.blockchain.ledger.TransactionState;
+import com.jd.blockchain.ledger.TypedValue;
+import com.jd.blockchain.ledger.UserRegisterOperation;
import com.jd.blockchain.ledger.core.DefaultOperationHandleRegisteration;
import com.jd.blockchain.ledger.core.LedgerDataQuery;
import com.jd.blockchain.ledger.core.LedgerDataset;
@@ -43,6 +64,8 @@ import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
import com.jd.blockchain.transaction.BooleanValueHolder;
import com.jd.blockchain.transaction.TxBuilder;
import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.DataEntry;
+import com.jd.blockchain.utils.io.BytesUtils;
import test.com.jd.blockchain.ledger.TxTestContract;
import test.com.jd.blockchain.ledger.TxTestContractImpl;
@@ -132,7 +155,7 @@ public class ContractInvokingTest {
assertEquals(1, opResults.length);
assertEquals(0, opResults[0].getIndex());
- byte[] expectedRetnBytes = BinaryProtocol.encode(BytesData.fromInt64(issueAmount), BytesValue.class);
+ byte[] expectedRetnBytes = BinaryProtocol.encode(TypedValue.fromInt64(issueAmount), BytesValue.class);
byte[] reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class);
assertArrayEquals(expectedRetnBytes, reallyRetnBytes);
@@ -218,9 +241,9 @@ public class ContractInvokingTest {
TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare();
txResultHandle.commit();
- BytesValue latestValue = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getBytes(key,
+ BytesValue latestValue = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getValue(key,
-1);
- System.out.printf("latest value=[%s] %s \r\n", latestValue.getType(), latestValue.getValue().toUTF8String());
+ System.out.printf("latest value=[%s] %s \r\n", latestValue.getType(), latestValue.getBytes().toUTF8String());
boolean readable = readableHolder.get();
assertTrue(readable);
@@ -278,14 +301,14 @@ public class ContractInvokingTest {
}
});
// 预期数据都能够正常写入;
- KVDataEntry kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K1",
+ DataEntry kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K1",
0);
- KVDataEntry kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K2",
+ DataEntry kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K2",
0);
assertEquals(0, kv1.getVersion());
assertEquals(0, kv2.getVersion());
- assertEquals("V1-0", kv1.getValue());
- assertEquals("V2-0", kv2.getValue());
+ assertEquals("V1-0", kv1.getValue().stringValue());
+ assertEquals("V2-0", kv2.getValue().stringValue());
// 构建基于接口调用合约的交易请求,用于测试合约调用;
buildBlock(ledgerRepo, ledgerManager, opReg, new TxDefinitor() {
@@ -299,12 +322,12 @@ public class ContractInvokingTest {
}
});
// 预期数据都能够正常写入;
- kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K1", 1);
- kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K2", 1);
+ kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K1", 1);
+ kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K2", 1);
assertEquals(1, kv1.getVersion());
assertEquals(1, kv2.getVersion());
- assertEquals("V1-1", kv1.getValue());
- assertEquals("V2-1", kv2.getValue());
+ assertEquals("V1-1", kv1.getValue().stringValue());
+ assertEquals("V2-1", kv2.getValue().stringValue());
// 构建基于接口调用合约的交易请求,用于测试合约调用;
buildBlock(ledgerRepo, ledgerManager, opReg, new TxDefinitor() {
@@ -314,16 +337,17 @@ public class ContractInvokingTest {
contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K1", "V1-2",
1);
contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K2", "V2-2",
- 0);
+ 0);//预期会回滚;
}
});
- // 预期数据都能够正常写入;
- kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K1", 1);
+ // 预期数据回滚,账本没有发生变更;
+ kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K1", 1);
assertEquals(1, kv1.getVersion());
- assertEquals("V1-1", kv1.getValue());
- kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K1", 2);
- assertEquals(-1, kv1.getVersion());
- assertEquals(null, kv1.getValue());
+ assertEquals("V1-1", kv1.getValue().stringValue());
+ kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K1", 2);
+ assertNull(kv1);
+ kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K2", 1);
+ assertEquals(1, kv2.getVersion());
}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java
index a50cd41e..53e9eb4d 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java
@@ -1,22 +1,12 @@
package test.com.jd.blockchain.ledger.core;
-import static org.junit.Assert.assertEquals;
-
import java.util.Random;
import org.junit.Before;
-import org.junit.Test;
-import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
-import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.crypto.PubKey;
-import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
-import com.jd.blockchain.crypto.service.sm.SMAlgorithm;
-import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.UserInfo;
-import com.jd.blockchain.ledger.core.MerkleAccountSet;
-import com.jd.blockchain.utils.Bytes;
/**
* Created by zhangshuang3 on 2018/9/3.
@@ -35,27 +25,27 @@ public class LedgerAccountTest {
rand.nextBytes(seed);
rand.nextBytes(settingValue);
rand.nextBytes(rawDigestBytes);
- DataContractRegistry.register(AccountHeader.class);
+ DataContractRegistry.register(BlockchainIdentity.class);
DataContractRegistry.register(UserInfo.class);
}
- @Test
- public void testSerialize_AccountHeader() {
- String address = "xxxxxxxxxxxx";
- PubKey pubKey = new PubKey(SMAlgorithm.SM2, rawDigestBytes);
- HashDigest hashDigest = new HashDigest(ClassicAlgorithm.SHA256, rawDigestBytes);
- MerkleAccountSet.AccountHeaderData accountHeaderData = new MerkleAccountSet.AccountHeaderData(Bytes.fromString(address),
- pubKey, hashDigest);
-
- // encode and decode
- byte[] encodeBytes = BinaryProtocol.encode(accountHeaderData, AccountHeader.class);
- AccountHeader deAccountHeaderData = BinaryProtocol.decode(encodeBytes);
-
- // verify start
- assertEquals(accountHeaderData.getAddress(), deAccountHeaderData.getAddress());
- assertEquals(accountHeaderData.getPubKey(), deAccountHeaderData.getPubKey());
- assertEquals(accountHeaderData.getRootHash(), deAccountHeaderData.getRootHash());
-
- }
+// @Test
+// public void testSerialize_AccountHeader() {
+// String address = "xxxxxxxxxxxx";
+// PubKey pubKey = new PubKey(SMAlgorithm.SM2, rawDigestBytes);
+// HashDigest hashDigest = new HashDigest(ClassicAlgorithm.SHA256, rawDigestBytes);
+// MerkleAccountSet.AccountHeaderData accountHeaderData = new MerkleAccountSet.AccountHeaderData(Bytes.fromString(address),
+// pubKey, hashDigest);
+//
+// // encode and decode
+// byte[] encodeBytes = BinaryProtocol.encode(accountHeaderData, AccountHeader.class);
+// AccountHeader deAccountHeaderData = BinaryProtocol.decode(encodeBytes);
+//
+// // verify start
+// assertEquals(accountHeaderData.getAddress(), deAccountHeaderData.getAddress());
+// assertEquals(accountHeaderData.getPubKey(), deAccountHeaderData.getPubKey());
+// assertEquals(accountHeaderData.getRootHash(), deAccountHeaderData.getRootHash());
+
+// }
}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java
index 97979205..78f04762 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java
@@ -8,12 +8,9 @@ import org.junit.Before;
import org.junit.Test;
import com.jd.blockchain.binaryproto.DataContractRegistry;
-import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.Crypto;
-import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.SignatureFunction;
-import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
@@ -25,7 +22,7 @@ import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionState;
-import com.jd.blockchain.ledger.core.CryptoConfig;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerEditor;
@@ -33,11 +30,6 @@ import com.jd.blockchain.ledger.core.LedgerTransactionContext;
import com.jd.blockchain.ledger.core.LedgerTransactionalEditor;
import com.jd.blockchain.ledger.core.UserAccount;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
-import com.jd.blockchain.transaction.ConsensusParticipantData;
-import com.jd.blockchain.transaction.LedgerInitData;
-import com.jd.blockchain.utils.Bytes;
-import com.jd.blockchain.utils.io.BytesUtils;
-import com.jd.blockchain.utils.net.NetworkAddress;
public class LedgerEditorTest {
@@ -102,7 +94,7 @@ public class LedgerEditorTest {
DataAccount dataAccount = ldgDS.getDataAccountSet().register(dataKP.getAddress(), dataKP.getPubKey(), null);
- dataAccount.setBytes(Bytes.fromString("A"), "abc", -1);
+ dataAccount.getDataset().setValue("A", TypedValue.fromText("abc"), -1);
LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS);
LedgerBlock block = ldgEdt.prepare();
@@ -115,9 +107,9 @@ public class LedgerEditorTest {
assertEquals(0, block.getHeight());
// 验证数据读写的一致性;
- BytesValue bytes = dataAccount.getBytes("A");
+ BytesValue bytes = dataAccount.getDataset().getValue("A");
assertEquals(DataType.TEXT, bytes.getType());
- String textValue = bytes.getValue().toUTF8String();
+ String textValue = bytes.getBytes().toUTF8String();
assertEquals("abc", textValue);
}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerTestUtils.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerTestUtils.java
index d3595755..a9c8a683 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerTestUtils.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerTestUtils.java
@@ -44,12 +44,18 @@ public class LedgerTestUtils {
partiKeys[1] = BlockchainKeyGenerator.getInstance().generate();
return createLedgerInitSetting(partiKeys);
}
-
- public static LedgerInitSetting createLedgerInitSetting(BlockchainKeypair[] partiKeys) {
+
+ public static CryptoProvider[] getContextProviders() {
CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}
+
+ return supportedProviders;
+ }
+
+ public static LedgerInitSetting createLedgerInitSetting(BlockchainKeypair[] partiKeys) {
+ CryptoProvider[] supportedProviders =getContextProviders();
CryptoConfig defCryptoSetting = new CryptoConfig();
defCryptoSetting.setSupportedProviders(supportedProviders);
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleAccountSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleAccountSetTest.java
new file mode 100644
index 00000000..f3bb67da
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleAccountSetTest.java
@@ -0,0 +1,58 @@
+package test.com.jd.blockchain.ledger.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.ledger.BlockchainKeyGenerator;
+import com.jd.blockchain.ledger.BlockchainKeypair;
+import com.jd.blockchain.ledger.TypedValue;
+import com.jd.blockchain.ledger.core.CompositeAccount;
+import com.jd.blockchain.ledger.core.CryptoConfig;
+import com.jd.blockchain.ledger.core.MerkleAccountSet;
+import com.jd.blockchain.ledger.core.OpeningAccessPolicy;
+import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
+import com.jd.blockchain.utils.Bytes;
+
+public class MerkleAccountSetTest {
+
+ @Test
+ public void testRegister() {
+ final OpeningAccessPolicy POLICY = new OpeningAccessPolicy();
+
+ final MemoryKVStorage STORAGE = new MemoryKVStorage();
+
+ Bytes KEY_PREFIX = Bytes.fromString("/ACCOUNT");
+
+ CryptoConfig cryptoConfig = new CryptoConfig();
+ cryptoConfig.setSupportedProviders(LedgerTestUtils.getContextProviders());
+ cryptoConfig.setAutoVerifyHash(true);
+ cryptoConfig.setHashAlgorithm(Crypto.getAlgorithm("SHA256"));
+
+ MerkleAccountSet accountset = new MerkleAccountSet(cryptoConfig, KEY_PREFIX, STORAGE, STORAGE, POLICY);
+
+ BlockchainKeypair key1 = BlockchainKeyGenerator.getInstance().generate();
+ accountset.register(key1.getIdentity());
+
+ accountset.commit();
+
+ CompositeAccount acc1 = accountset.getAccount(key1.getAddress());
+ assertNotNull(acc1);
+ assertEquals(0, accountset.getVersion(key1.getAddress()));
+
+ acc1.getDataset().setValue("K1", TypedValue.fromText("V0"), -1);
+
+ TypedValue v1 = acc1.getDataset().getValue("K1");
+ assertNotNull(v1);
+ assertEquals(0, acc1.getDataset().getVersion("K1"));
+
+ accountset.commit();
+
+ v1 = acc1.getDataset().getValue("K1");
+ assertNotNull(v1);
+ assertEquals(0, acc1.getDataset().getVersion("K1"));
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleDataSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleDataSetTest.java
index a90806d6..a8ab595b 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleDataSetTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleDataSetTest.java
@@ -23,9 +23,11 @@ import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.ledger.core.CryptoConfig;
import com.jd.blockchain.ledger.core.MerkleDataSet;
-import com.jd.blockchain.storage.service.VersioningKVEntry;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.DataEntry;
+import com.jd.blockchain.utils.Dataset;
+import com.jd.blockchain.utils.DatasetHelper;
import com.jd.blockchain.utils.io.BytesUtils;
public class MerkleDataSetTest {
@@ -53,9 +55,9 @@ public class MerkleDataSetTest {
MemoryKVStorage storage = new MemoryKVStorage();
MerkleDataSet mds = new MerkleDataSet(cryptoConfig, keyPrefix, storage, storage);
- mds.setValue("A", "A".getBytes(), -1);
- mds.setValue("B", "B".getBytes(), -1);
- mds.setValue("C", "C".getBytes(), -1);
+ mds.setValue(Bytes.fromString("A"), "A".getBytes(), -1);
+ mds.setValue(Bytes.fromString("B"), "B".getBytes(), -1);
+ mds.setValue(Bytes.fromString("C"), "C".getBytes(), -1);
mds.commit();
@@ -85,22 +87,23 @@ public class MerkleDataSetTest {
MemoryKVStorage storage = new MemoryKVStorage();
MerkleDataSet mds = new MerkleDataSet(cryptoConfig, keyPrefix, storage, storage);
- mds.setValue("A", "A".getBytes(), -1);
- mds.setValue("B", "B".getBytes(), -1);
- mds.setValue("C", "C".getBytes(), -1);
+ Dataset ds = DatasetHelper.map(mds);
+ ds.setValue("A", "A".getBytes(), -1);
+ ds.setValue("B", "B".getBytes(), -1);
+ ds.setValue("C", "C".getBytes(), -1);
mds.commit();
- byte[] va = mds.getValue("A");
+ byte[] va = ds.getValue("A");
assertNotNull(va);
assertEquals("A", new String(va));
- byte[] vc = mds.getValue("C");
- VersioningKVEntry ventry = mds.getDataEntry("C");
+ byte[] vc = ds.getValue("C");
+ DataEntry ventry = ds.getDataEntry("C");
assertNotNull(vc);
assertNotNull(ventry);
assertEquals("C", new String(vc));
- assertEquals("C", ventry.getKey().toUTF8String());
+ assertEquals("C", ventry.getKey());
HashDigest root1 = mds.getRootHash();
@@ -111,8 +114,8 @@ public class MerkleDataSetTest {
int expStorageCount = 10;
assertEquals(expStorageCount, storage.getStorageCount());
- mds.setValue("B", "B".getBytes(), 0);
- mds.setValue("C", "C".getBytes(), 0);
+ ds.setValue("B", "B".getBytes(), 0);
+ ds.setValue("C", "C".getBytes(), 0);
mds.commit();
HashDigest root2 = mds.getRootHash();
assertNotEquals(root1, root2);
@@ -122,7 +125,7 @@ public class MerkleDataSetTest {
expStorageCount = expStorageCount + 3;
assertEquals(expStorageCount, storage.getStorageCount());
- mds.setValue("D", "DValue".getBytes(), -1);
+ ds.setValue("D", "DValue".getBytes(), -1);
mds.commit();
HashDigest root3 = mds.getRootHash();
assertNotEquals(root2, root3);
@@ -135,31 +138,31 @@ public class MerkleDataSetTest {
assertEquals(expStorageCount, storage.getStorageCount());
// Check rollback function: Add some keys, and then rollback;
- long v = mds.setValue("E", "E-values".getBytes(), -1);
+ long v = ds.setValue("E", "E-values".getBytes(), -1);
assertEquals(v, 0);
- String expEValue = new String(mds.getValue("E"));
+ String expEValue = new String(ds.getValue("E"));
assertEquals(expEValue, "E-values");
- v = mds.setValue("F", "F-values".getBytes(), -1);
+ v = ds.setValue("F", "F-values".getBytes(), -1);
assertEquals(v, 0);
- String expFValue = new String(mds.getValue("F"));
+ String expFValue = new String(ds.getValue("F"));
assertEquals(expFValue, "F-values");
- v = mds.setValue("E", "E-values-1".getBytes(), 0);
+ v = ds.setValue("E", "E-values-1".getBytes(), 0);
assertEquals(v, 1);
- expEValue = new String(mds.getValue("E"));
+ expEValue = new String(ds.getValue("E"));
assertEquals(expEValue, "E-values-1");
mds.cancel();
- byte[] bv = mds.getValue("E");
+ byte[] bv = ds.getValue("E");
assertNull(bv);
- bv = mds.getValue("F");
+ bv = ds.getValue("F");
assertNull(bv);
- v = mds.getVersion("E");
+ v = ds.getVersion("E");
assertEquals(-1, v);
- v = mds.getVersion("F");
+ v = ds.getVersion("F");
assertEquals(-1, v);
// Expect that states has been recover;
@@ -194,10 +197,11 @@ public class MerkleDataSetTest {
MemoryKVStorage storage = new MemoryKVStorage();
MerkleDataSet mds = new MerkleDataSet(cryptoConfig, keyPrefix, storage, storage);
+ Dataset ds = DatasetHelper.map(mds);
// 初始的时候没有任何数据,总是返回 null;
- VersioningKVEntry verKVEntry = mds.getDataEntry("NULL_KEY");
- byte[] vbytes = mds.getValue("NULL_KEY");
+ DataEntry verKVEntry = ds.getDataEntry("NULL_KEY");
+ byte[] vbytes = ds.getValue("NULL_KEY");
assertNull(verKVEntry);
assertNull(vbytes);
@@ -217,7 +221,7 @@ public class MerkleDataSetTest {
for (int i = 0; i < count; i++) {
key = "data" + i;
rand.nextBytes(data);
- v = mds.setValue(key, data, -1);
+ v = ds.setValue(key, data, -1);
dataVersions.put(key, v);
dataValues.put(key + "_" + v, data);
assertEquals(v, 0);
@@ -237,7 +241,7 @@ public class MerkleDataSetTest {
KeySnapshot ks = new KeySnapshot();
ks.proof = proof;
- ks.maxVersion = mds.getVersion(key);
+ ks.maxVersion = ds.getVersion(key);
snapshot.put(key, ks);
}
@@ -271,7 +275,7 @@ public class MerkleDataSetTest {
key = "data" + i;
rand.nextBytes(data);
expVer = dataVersions.get(key);
- v = mds.setValue(key, data, expVer);
+ v = ds.setValue(key, data, expVer);
assertEquals(v, expVer + 1);
@@ -300,7 +304,7 @@ public class MerkleDataSetTest {
KeySnapshot ks = new KeySnapshot();
ks.proof = proof;
- ks.maxVersion = mds.getVersion(key);
+ ks.maxVersion = ds.getVersion(key);
snapshot.put(key, ks);
}
history.put(rootHash, snapshot);
@@ -316,6 +320,7 @@ public class MerkleDataSetTest {
MerkleDataSet mdsReload = new MerkleDataSet(hisRootHash, cryptoConfig, keyPrefix, storage, storage,
true);
+ Dataset dsReload = DatasetHelper.map(mdsReload);
assertEquals(hisRootHash, mdsReload.getRootHash());
// verify every keys;
@@ -323,7 +328,7 @@ public class MerkleDataSetTest {
key = "data" + i;
// 最新版本一致;
long expLatestVersion = snapshot.get(key).maxVersion;
- long actualLatestVersion = mdsReload.getVersion(key);
+ long actualLatestVersion = dsReload.getVersion(key);
assertEquals(expLatestVersion, actualLatestVersion);
// 数据证明一致;
@@ -339,7 +344,7 @@ public class MerkleDataSetTest {
for (long j = 0; j < actualLatestVersion; j++) {
String keyver = key + "_" + j;
byte[] expValue = dataValues.get(keyver);
- byte[] actualValue = mdsReload.getValue(key, j);
+ byte[] actualValue = dsReload.getValue(key, j);
assertTrue(BytesUtils.equals(expValue, actualValue));
}
}
@@ -365,10 +370,11 @@ public class MerkleDataSetTest {
MemoryKVStorage storage = new MemoryKVStorage();
MerkleDataSet mds = new MerkleDataSet(cryptoConfig, keyPrefix, storage, storage);
+ Dataset ds = DatasetHelper.map(mds);
// 初始的时候没有任何数据,总是返回 null;
- VersioningKVEntry verKVEntry = mds.getDataEntry("NULL_KEY");
- byte[] vbytes = mds.getValue("NULL_KEY");
+ DataEntry verKVEntry = ds.getDataEntry("NULL_KEY");
+ byte[] vbytes = ds.getValue("NULL_KEY");
assertNull(verKVEntry);
assertNull(vbytes);
@@ -388,7 +394,7 @@ public class MerkleDataSetTest {
MerkleProof proof;
for (int i = 0; i < count; i++) {
key = "data" + i;
- v = mds.setValue(key, data, -1);
+ v = ds.setValue(key, data, -1);
dataVersions.put(key, v);
// dataValues.put(key + "_" + v, data);
assertEquals(v, 0);
@@ -408,7 +414,7 @@ public class MerkleDataSetTest {
KeySnapshot ks = new KeySnapshot();
ks.proof = proof;
- ks.maxVersion = mds.getVersion(key);
+ ks.maxVersion = ds.getVersion(key);
snapshot.put(key, ks);
}
@@ -418,6 +424,7 @@ public class MerkleDataSetTest {
// verify;
{
MerkleDataSet mdsReload = new MerkleDataSet(rootHash, cryptoConfig, keyPrefix, storage, storage, true);
+ Dataset dsReload = DatasetHelper.map(mdsReload);
// verify every keys;
Map snapshot = history.get(rootHash);
MerkleProof expProof;
@@ -429,7 +436,7 @@ public class MerkleDataSetTest {
expProof = snapshot.get(key).proof;
assertEquals(expProof.toString(), proof.toString());
- byte[] value = mdsReload.getValue(key);
+ byte[] value = dsReload.getValue(key);
assertTrue(BytesUtils.equals(data, value));
}
}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleTreeTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleTreeTest.java
index afe8e435..ee3a7509 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleTreeTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleTreeTest.java
@@ -556,6 +556,9 @@ public class MerkleTreeTest {
/**
* 测试从存储重新加载 Merkle 树的正确性;
*/
+ /**
+ *
+ */
@Test
public void testMerkleReload() {
CryptoSetting setting = Mockito.mock(CryptoSetting.class);
@@ -563,7 +566,7 @@ public class MerkleTreeTest {
when(setting.getAutoVerifyHash()).thenReturn(true);
// 保存所有写入的数据节点的 SN-Hash 映射表;
- TreeMap dataNodes = new TreeMap<>();
+ TreeMap expectedDataNodes = new TreeMap<>();
MerkleNode nd;
// 测试从空的树开始,顺序增加数据节点;
@@ -580,7 +583,7 @@ public class MerkleTreeTest {
for (int i = 0; i < count; i++) {
rand.nextBytes(dataBuf);
nd = mkt.setData(sn, "KEY-" + sn, 0, dataBuf);
- dataNodes.put(sn, nd.getNodeHash());
+ expectedDataNodes.put(sn, nd.getNodeHash());
sn++;
}
mkt.commit();
@@ -610,6 +613,24 @@ public class MerkleTreeTest {
// 预期扩展为 4 层16叉树,由 3 层满16叉树扩展 1 新分支(4个路径节点)而形成;
long expectedNodes = getMaxPathNodeCount(3) + 4 + 4097;
assertEquals(expectedNodes, storage.getCount());
+
+ //重新加载,判断数据是否正确;
+ MerkleTree r1_mkt = new MerkleTree(r1_rootHash, setting, keyPrefix, storage, true);
+ {
+ // 验证每一个数据节点都产生了存在性证明;
+ MerkleProof proof = null;
+ HashDigest expectedNodeHash = null;
+ MerkleDataNode reallyDataNode = null;
+ for (long n = 0; n < maxSN; n++) {
+ expectedNodeHash = expectedDataNodes.get(n);
+ reallyDataNode = r1_mkt.getData(n);
+ assertEquals(expectedNodeHash, reallyDataNode.getNodeHash());
+
+ proof = r1_mkt.getProof(n);
+ assertNotNull(proof);
+ assertEquals(expectedNodeHash, proof.getHash(0));
+ }
+ }
}
// 覆盖到每一路分支修改数据节点;
@@ -621,7 +642,7 @@ public class MerkleTreeTest {
rand.nextBytes(dataBuf);
sn = i;
nd = mkt.setData(sn, "KEY-" + sn, 0, dataBuf);
- dataNodes.put(sn, nd.getNodeHash());
+ expectedDataNodes.put(sn, nd.getNodeHash());
}
mkt.commit();
@@ -658,16 +679,18 @@ public class MerkleTreeTest {
rand.nextBytes(dataBuf);
sn = maxSN + 1 + i;
nd = mkt.setData(sn, "KEY-" + sn, 0, dataBuf);
- dataNodes.put(sn, nd.getNodeHash());
+ expectedDataNodes.put(sn, nd.getNodeHash());
}
mkt.commit();
- // 验证每一个数据节点都产生了存在性证明;
- MerkleProof proof = null;
- for (Long n : dataNodes.keySet()) {
- proof = mkt.getProof(n.longValue());
- assertNotNull(proof);
- assertEquals(dataNodes.get(n), proof.getHash(0));
+ {
+ // 验证每一个数据节点都产生了存在性证明;
+ MerkleProof proof = null;
+ for (Long n : expectedDataNodes.keySet()) {
+ proof = mkt.getProof(n.longValue());
+ assertNotNull(proof);
+ assertEquals(expectedDataNodes.get(n), proof.getHash(0));
+ }
}
// 记录一次提交的根哈希以及部分节点信息,用于后续的加载校验;
@@ -700,6 +723,7 @@ public class MerkleTreeTest {
assertEquals(r1_proof1, r1_mkt.getProof(r1_sn1).toString());
assertEquals(r1_proof2, r1_mkt.getProof(r1_sn2).toString());
+
// 从第 2 轮提交的 Merkle 根哈希加载;
// 第 2 轮生成的 Merkle 树是对第 1 轮的数据的全部节点的修改,因此同一个 SN 的节点的证明是不同的;
MerkleTree r2_mkt = new MerkleTree(r2_rootHash, setting, keyPrefix, storage, true);
@@ -730,13 +754,16 @@ public class MerkleTreeTest {
assertEquals(r3_proof3, r3_mkt.getProof(r3_sn3).toString());
// 验证每一个数据节点都产生了存在性证明;
- for (Long n : dataNodes.keySet()) {
- proof = r3_mkt.getProof(n.longValue());
- assertNotNull(proof);
- assertEquals(dataNodes.get(n), proof.getHash(0));
+ {
+ MerkleProof proof = null;
+ for (Long n : expectedDataNodes.keySet()) {
+ proof = r3_mkt.getProof(n.longValue());
+ assertNotNull(proof);
+ assertEquals(expectedDataNodes.get(n), proof.getHash(0));
+ }
}
}
-
+
@SuppressWarnings("unused")
private static int getLevel(long dataCount) {
if (dataCount < 0) {
@@ -772,8 +799,7 @@ public class MerkleTreeTest {
* 注:此方法不处理溢出;调用者需要自行规避;
*
* @param value
- * @param x
- * 大于等于 0 的整数;
+ * @param x 大于等于 0 的整数;
* @return
*/
private static long power(long value, int x) {
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java
index 6a1b6ed8..3d7f179b 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java
@@ -332,24 +332,25 @@ public class TransactionBatchProcessorTest {
newBlock = newBlockEditor.prepare();
newBlockEditor.commit();
- BytesValue v1_0 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K1",
+ BytesValue v1_0 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K1",
0);
- BytesValue v1_1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K1",
+ BytesValue v1_1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K1",
1);
- BytesValue v2 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K2",
+ BytesValue v2 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K2",
0);
- BytesValue v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K3",
+ BytesValue v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("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());
+ assertEquals("V-1-1", v1_0.getBytes().toUTF8String());
+ assertEquals("V-1-2", v1_1.getBytes().toUTF8String());
+ assertEquals("V-2-1", v2.getBytes().toUTF8String());
+ assertEquals("V-3-1", v3.getBytes().toUTF8String());
// 提交多笔数据写入的交易,包含存在数据版本冲突的交易,验证交易是否正确回滚;
// 先写一笔正确的交易; k3 的版本将变为 1 ;
@@ -365,32 +366,47 @@ public class TransactionBatchProcessorTest {
txbatchProcessor.schedule(txreq5);
// 预期会产生版本冲突异常; DataVersionConflictionException;
- TransactionResponse resp = txbatchProcessor.schedule(txreq6);
- assertFalse(resp.isSuccess());
+ DataVersionConflictException versionConflictionException = null;
+ try {
+ txbatchProcessor.schedule(txreq6);
+ } catch (DataVersionConflictException e) {
+ versionConflictionException = e;
+ }
+ assertNotNull(versionConflictionException);
- // 提交新区块
newBlock = newBlockEditor.prepare();
newBlockEditor.commit();
- // 预期区块高度为3
- assertEquals(3, ledgerRepo.getLatestBlockHeight());
-
- BytesValue v1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K1");
- v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K3");
+ BytesValue v1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K1");
+ v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K3");
// k1 的版本仍然为1,没有更新;
long k1_version = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress())
- .getDataVersion("K1");
+ .getDataset().getVersion("K1");
assertEquals(1, k1_version);
- // K3 的版本增1
+
long k3_version = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress())
- .getDataVersion("K3");
+ .getDataset().getVersion("K3");
assertEquals(1, k3_version);
assertNotNull(v1);
assertNotNull(v3);
- assertEquals("V-1-2", v1.getValue().toUTF8String());
- assertEquals("V-3-2", v3.getValue().toUTF8String());
+ assertEquals("V-1-2", v1.getBytes().toUTF8String());
+ assertEquals("V-3-2", v3.getBytes().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());
}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionSetTest.java
index cd5ebc9f..63ee3e64 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionSetTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionSetTest.java
@@ -164,8 +164,8 @@ public class TransactionSetTest {
for (int i = 0; i < acutualKVWriteSet.length; i++) {
assertEquals(expKVWriteSet[i].getKey(), acutualKVWriteSet[i].getKey());
assertEquals(expKVWriteSet[i].getExpectedVersion(), acutualKVWriteSet[i].getExpectedVersion());
- assertTrue(BytesUtils.equals(expKVWriteSet[i].getValue().getValue().toBytes(),
- acutualKVWriteSet[i].getValue().getValue().toBytes()));
+ assertTrue(BytesUtils.equals(expKVWriteSet[i].getValue().getBytes().toBytes(),
+ acutualKVWriteSet[i].getValue().getBytes().toBytes()));
}
ContractCodeDeployOperation actualContractDplOp = (ContractCodeDeployOperation) actualOperations[3];
diff --git a/source/ledger/ledger-model/pom.xml b/source/ledger/ledger-model/pom.xml
index b0ea6b32..1fcc2240 100644
--- a/source/ledger/ledger-model/pom.xml
+++ b/source/ledger/ledger-model/pom.xml
@@ -6,7 +6,7 @@
com.jd.blockchain
ledger
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
ledger-model
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Account.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Account.java
new file mode 100644
index 00000000..28694160
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Account.java
@@ -0,0 +1,11 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.utils.Dataset;
+
+public interface Account {
+
+ BlockchainIdentity getID();
+
+ Dataset getDataset();
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AccountHeader.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AccountHeader.java
index 16f2794b..fcc530de 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AccountHeader.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AccountHeader.java
@@ -1,20 +1,20 @@
-package com.jd.blockchain.ledger;
-
-import com.jd.blockchain.binaryproto.DataContract;
-import com.jd.blockchain.binaryproto.DataField;
-import com.jd.blockchain.binaryproto.PrimitiveType;
-import com.jd.blockchain.consts.DataCodes;
-import com.jd.blockchain.crypto.PubKey;
-import com.jd.blockchain.utils.Bytes;
-
-@DataContract(code= DataCodes.ACCOUNT_HEADER)
-public interface AccountHeader extends MerkleSnapshot{
-
- @DataField(order=1, primitiveType = PrimitiveType.BYTES)
- Bytes getAddress();
-
- @DataField(order=2, primitiveType = PrimitiveType.BYTES)
- PubKey getPubKey();
-
-
-}
+//package com.jd.blockchain.ledger;
+//
+//import com.jd.blockchain.binaryproto.DataContract;
+//import com.jd.blockchain.binaryproto.DataField;
+//import com.jd.blockchain.binaryproto.PrimitiveType;
+//import com.jd.blockchain.consts.DataCodes;
+//import com.jd.blockchain.crypto.PubKey;
+//import com.jd.blockchain.utils.Bytes;
+//
+//@Deprecated
+//@DataContract(code= DataCodes.ACCOUNT_HEADER)
+//public interface AccountHeader { //extends MerkleSnapshot{
+//
+// @DataField(order = 1, primitiveType = PrimitiveType.BYTES)
+// Bytes getAddress();
+//
+// @DataField(order = 2, primitiveType=PrimitiveType.BYTES)
+// PubKey getPubKey();
+//
+//}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesData.java
deleted file mode 100644
index ca4e9cb0..00000000
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesData.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package com.jd.blockchain.ledger;
-
-import com.jd.blockchain.utils.Bytes;
-import com.jd.blockchain.utils.io.BytesUtils;
-
-/**
- *
- * @author huanghaiquan
- *
- */
-public class BytesData implements BytesValue {
- DataType type;
- Bytes value;
-
- private BytesData(DataType type, byte[] bytes) {
- this.type = type;
- this.value = new Bytes(bytes);
- }
-
- private BytesData(DataType type, Bytes bytes) {
- this.type = type;
- this.value = bytes;
- }
-
- public static BytesValue fromType(DataType type, byte[] value) {
- return new BytesData(type, value);
- }
-
- public static BytesValue fromBytes(byte[] value) {
- return new BytesData(DataType.BYTES, value);
- }
-
- public static BytesValue fromBytes(Bytes value) {
- return new BytesData(DataType.BYTES, value);
- }
-
- public static BytesValue fromImage(byte[] value) {
- return new BytesData(DataType.IMG, value);
- }
-
- public static BytesValue fromImage(Bytes value) {
- return new BytesData(DataType.IMG, value);
- }
-
- /**
- * 以 UTF-8 编码从字符串转换为字节数组值;
- *
- * @param value
- * @return
- */
- public static BytesValue fromText(String value) {
- return new BytesData(DataType.TEXT, BytesUtils.toBytes(value));
- }
-
- /**
- * 以 UTF-8 编码把字节数组值转换为字符串;
- *
- * @param bytesValue
- * @return
- */
- public static String toText(BytesValue bytesValue) {
- if (bytesValue == null) {
- return null;
- }
- if (bytesValue.getType() != DataType.TEXT) {
- throw new ValueTypeCastException("The expected value type is " + DataType.TEXT.toString()
- + ", but it is actually " + bytesValue.getType().toString() + "!");
- }
- return bytesValue.getValue().toUTF8String();
- }
-
- public static BytesValue fromJSON(String value) {
- return new BytesData(DataType.JSON, BytesUtils.toBytes(value));
- }
-
- public static BytesValue fromXML(String value) {
- return new BytesData(DataType.XML, BytesUtils.toBytes(value));
- }
-
- public static BytesValue fromInt32(int value) {
- return new BytesData(DataType.INT32, BytesUtils.toBytes(value));
- }
-
- public static BytesValue fromInt64(long value) {
- return new BytesData(DataType.INT64, BytesUtils.toBytes(value));
- }
-
- public static BytesValue fromInt16(short value) {
- return new BytesData(DataType.INT16, BytesUtils.toBytes(value));
- }
-
- public static BytesValue fromInt8(byte value) {
- return new BytesData(DataType.INT8, BytesUtils.toBytes(value));
- }
-
- public static BytesValue fromTimestamp(long value) {
- return new BytesData(DataType.TIMESTAMP, BytesUtils.toBytes(value));
- }
-
- public static BytesValue fromBoolean(boolean value) {
- return new BytesData(DataType.BOOLEAN, BytesUtils.toBytes(value));
- }
-
- @Override
- public DataType getType() {
- return this.type;
- }
-
- public void setType(DataType type) {
- this.type = type;
- }
-
- @Override
- public Bytes getValue() {
- return this.value;
- }
-
-}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesDataList.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesDataList.java
index f7aef959..a7541a41 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesDataList.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesDataList.java
@@ -14,18 +14,18 @@ public class BytesDataList implements BytesValueList {
}
public static BytesValueList singleText(String value) {
- return new BytesDataList(BytesData.fromText(value));
+ return new BytesDataList(TypedValue.fromText(value));
}
public static BytesValueList singleLong(long value) {
- return new BytesDataList(BytesData.fromInt64(value));
+ return new BytesDataList(TypedValue.fromInt64(value));
}
public static BytesValueList singleInt(int value) {
- return new BytesDataList(BytesData.fromInt32(value));
+ return new BytesDataList(TypedValue.fromInt32(value));
}
public static BytesValueList singleBoolean(boolean value) {
- return new BytesDataList(BytesData.fromBoolean(value));
+ return new BytesDataList(TypedValue.fromBoolean(value));
}
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValue.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValue.java
index 6e7b9b46..47d4ad16 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValue.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValue.java
@@ -29,6 +29,6 @@ public interface BytesValue {
* @return
*/
@DataField(order = 1, primitiveType = PrimitiveType.BYTES)
- Bytes getValue();
+ Bytes getBytes();
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java
index baee5868..6579f1c4 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java
@@ -68,7 +68,7 @@ public class BytesValueEncoding {
}
// 将对象序列化
byte[] serialBytes = BinaryProtocol.encode(value, type);
- return BytesData.fromType(DataType.DATA_CONTRACT, serialBytes);
+ return TypedValue.fromType(DataType.DATA_CONTRACT, serialBytes);
}
BytesValueResolver bytesValueResolver = CLASS_RESOLVER_MAP.get(type);
if (bytesValueResolver == null) {
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractInfo.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractInfo.java
index cb1da5c4..047e3c51 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractInfo.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractInfo.java
@@ -5,9 +5,10 @@ import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;
-@DataContract(code= DataCodes.CONTRACT)
-public interface ContractInfo extends AccountHeader {
+@DataContract(code= DataCodes.CONTRACT_ACCOUNT_HEADER)
+public interface ContractInfo extends BlockchainIdentity, MerkleSnapshot {
@DataField(order=4, primitiveType= PrimitiveType.BYTES)
byte[] getChainCode();
+
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataType.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataType.java
index 1cb8fce3..6395bcc2 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataType.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataType.java
@@ -106,6 +106,20 @@ public enum DataType {
* DataContract 数据;
*/
DATA_CONTRACT((byte) (BaseType.EXT | 0x01));
+
+
+
+ public static final boolean BOOLEAN_DEFAULT_VALUE = false;
+
+ public static final byte INT8_DEFAULT_VALUE = 0;
+
+ public static final short INT16_DEFAULT_VALUE = 0;
+
+ public static final int INT32_DEFAULT_VALUE = 0;
+
+ public static final long INT64_DEFAULT_VALUE = 0;
+
+
@EnumField(type = PrimitiveType.INT8)
public final byte CODE;
@@ -114,6 +128,51 @@ public enum DataType {
this.CODE = code;
}
+ /**
+ * 是否表示“文本类型”或“文本衍生类型”;
+ *
+ * @return
+ */
+ public boolean isText() {
+ return BaseType.TEXT == (BaseType.TEXT & CODE);
+ }
+
+ /**
+ * 是否表示“字节类型”或“字节衍生类型”;
+ *
+ * @return
+ */
+ public boolean isBytes() {
+ return BaseType.BYTES == (BaseType.BYTES & CODE);
+ }
+
+ /**
+ * 是否表示“整数类型”或“整数衍生类型”;
+ *
+ * @return
+ */
+ public boolean isInteger() {
+ return BaseType.INTEGER == (BaseType.INTEGER & CODE);
+ }
+
+ /**
+ * 是否表示“布尔类型”;
+ *
+ * @return
+ */
+ public boolean isBoolean() {
+ return BaseType.BOOLEAN == (BaseType.BOOLEAN & CODE);
+ }
+
+ /**
+ * 是否表示“扩展类型”;
+ *
+ * @return
+ */
+ public boolean isExt() {
+ return BaseType.EXT == (BaseType.EXT & CODE);
+ }
+
public static DataType valueOf(byte code) {
for (DataType dataType : DataType.values()) {
if (dataType.CODE == code) {
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/HashProof.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/HashProof.java
new file mode 100644
index 00000000..4b2dd9c5
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/HashProof.java
@@ -0,0 +1,44 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.crypto.HashDigest;
+
+public interface HashProof {
+ /**
+ * 最大层级数;
+ * 叶子节点(即数据节点)的层级为 0,数据节点之上的每一级父节点的层级加 1, 最大层级便是根节点的层级;
+ *
+ * @return
+ *
+ * @see MerkleTree#getLevel()
+ */
+ int getLevels();
+
+ /**
+ * 返回证明中指定层级的节点的哈希;
+ *
+ *
+ * @param level
+ * 参数值为 0 返回的是数据节点的哈希;
+ * 参数值为 {@link #getLevels()} 返回的是根节点的哈希;
+ * @return
+ */
+ HashDigest getHash(int level);
+
+ /**
+ * 返回根节点的哈希;
+ *
+ * @return
+ */
+ default HashDigest getRootHash() {
+ return getHash(getLevels());
+ }
+
+ /**
+ * 返回数据节点的哈希;
+ *
+ * @return
+ */
+ default HashDigest getDataHash() {
+ return getHash(0);
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataObject.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataObject.java
deleted file mode 100644
index 1e8247ee..00000000
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataObject.java
+++ /dev/null
@@ -1,616 +0,0 @@
-package com.jd.blockchain.ledger;
-
-import java.math.BigInteger;
-import java.util.Date;
-
-import com.jd.blockchain.binaryproto.PrimitiveType;
-import com.jd.blockchain.utils.Bytes;
-import com.jd.blockchain.utils.io.ByteArray;
-import com.jd.blockchain.utils.io.BytesUtils;
-
-/**
- * KV数据项;
- *
- *
- *
- * {@link KVDataObject} 被设计为只读对象;
- *
- * @author huanghaiquan
- *
- */
-public class KVDataObject implements KVDataEntry {
-
- private String key;
-
- private long version;
-
- private BytesValue bytesValue;
-
- public KVDataObject(String key, long version, BytesValue bytesValue) {
- this.key = key;
- this.version = version < 0 ? -1 : version;
- this.bytesValue = bytesValue;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.jd.blockchain.ledger.KVDataEntry#getKey()
- */
- @Override
- public String getKey() {
- return key;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.jd.blockchain.ledger.KVDataEntry#getVersion()
- */
- @Override
- public long getVersion() {
- return version;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.jd.blockchain.ledger.KVDataEntry#getType()
- */
- @Override
- public DataType getType() {
- return bytesValue == null ? DataType.NIL : bytesValue.getType();
- }
-
- @Override
- public Object getValue() {
- if (bytesValue == null) {
- return null;
- }
-
- switch (getType()) {
- case NIL:
- return null;
- case TEXT:
- return bytesValue.getValue().toUTF8String();
- case BYTES:
- return ByteArray.toHex(bytesValue.getValue().toBytes());
- case INT64:
- return BytesUtils.toLong(bytesValue.getValue().toBytes());
- case JSON:
- return bytesValue.getValue().toUTF8String();
- case XML:
- return bytesValue.getValue().toUTF8String();
-
- default:
- throw new IllegalStateException("Unsupported value type[" + getType() + "] to resolve!");
- }
- }
-
- /**
- * 是否为空值;
- *
- *
- * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#NIL} 时返回 true,其它情况返回 false;
- *
- *
- * @return
- */
- public boolean isNil() {
- return bytesValue == null || DataType.NIL == bytesValue.getType();
- }
-
- /**
- * 字节数组形式的原始内容;
- *
- * @return
- */
- Bytes bytesArray() {
- return bytesValue.getValue();
- }
-
- /**
- * 返回 8 位整数值;
- *
- *
- * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT8} 有效;
- *
- *
- * 无效类型将引发 {@link IllegalStateException} 异常;
- *
- * @return
- */
- public byte tinyValue() {
- if (DataType.INT8 == getType()) {
- return bytesValue.getValue().toBytes()[0];
- }
- throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT8, getType()));
- }
-
- /**
- * 返回 16 位整数值;
- *
- *
- * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT16} 有效;
- *
- *
- * 无效类型将引发 {@link IllegalStateException} 异常;
- *
- * @return
- */
- public short shortValue() {
- if (DataType.INT16 == getType()) {
- return BytesUtils.toShort(bytesValue.getValue().toBytes(), 0);
- }
- throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT16, getType()));
- }
-
- /**
- * 返回 32 位整数值;
- *
- *
- * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT32} 有效;
- *
- *
- * 无效类型将引发 {@link IllegalStateException} 异常;
- *
- * @return
- */
- public int intValue() {
- if (DataType.INT32 == getType()) {
- return BytesUtils.toInt(bytesValue.getValue().toBytes(), 0);
- }
- throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT32, getType()));
- }
-
- /**
- * 返回 64 位整数值;
- *
- *
- * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT64} 有效;
- *
- *
- * 无效类型将引发 {@link IllegalStateException} 异常;
- *
- * @return
- */
- public long longValue() {
- if (DataType.INT64 == getType()) {
- return BytesUtils.toLong(bytesValue.getValue().toBytes(), 0);
- }
- throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT64, getType()));
-
- }
-
- /**
- * 返回大整数值;
- *
- *
- * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#BIG_INT} 有效;
- *
- *
- * 无效类型将引发 {@link IllegalStateException} 异常;
- *
- * @return
- */
- public BigInteger bigIntValue() {
- if (DataType.BIG_INT == getType()) {
- return new BigInteger(bytesValue.getValue().toBytes());
- }
- throw new IllegalStateException(
- String.format("Expected type [%s], but [%s]", DataType.BIG_INT, getType()));
- }
-
- /**
- * 返回布尔值;
- *
- *
- * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#BIG_INT} 有效;
- *
- *
- * 无效类型将引发 {@link IllegalStateException} 异常;
- *
- * @return
- */
- public boolean boolValue() {
- if (DataType.BOOLEAN == getType()) {
- return BytesUtils.toBoolean(bytesValue.getValue().toBytes()[0]);
- }
- throw new IllegalStateException(
- String.format("Expected type [%s], but [%s]", DataType.BOOLEAN, getType()));
- }
-
- /**
- * 返回日期时间值;
- *
- *
- * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TIMESTAMP} 有效;
- *
- *
- * 无效类型将引发 {@link IllegalStateException} 异常;
- *
- * @return
- */
- public Date datetimeValue() {
- if (DataType.TIMESTAMP == getType()) {
- long ts = BytesUtils.toLong(bytesValue.getValue().toBytes());
- return new Date(ts);
- }
- throw new IllegalStateException(
- String.format("Expected type [%s], but [%s]", DataType.TIMESTAMP, getType()));
- }
-
- /**
- * 返回大整数值;
- *
- *
- * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TEXT} /
- * {@link PrimitiveType#JSON} / {@link PrimitiveType#XML} 有效;
- *
- *
- * 无效类型将引发 {@link IllegalStateException} 异常;
- *
- * @return
- */
- public String stringValue() {
- DataType type = getType();
- if (DataType.TEXT == type || DataType.JSON == type || DataType.XML == type) {
- return bytesValue.getValue().toUTF8String();
- }
- throw new IllegalStateException(String.format("Expected type [%s] or [%s] or [%s] , but [%s]",
- PrimitiveType.TEXT, DataType.JSON, DataType.XML, type));
- }
-
-// // ----------------
-// public KVDataEntry nextVersionNil() {
-// return nilState(key, version + 1);
-// }
-//
-// public KVDataEntry nextVersionBoolean(boolean value) {
-// return booleanState(key, version + 1, value);
-// }
-//
-// public KVDataEntry nextVersionTiny(byte value) {
-// return tinyState(key, version + 1, value);
-// }
-//
-// public KVDataEntry nextVersionShort(short value) {
-// return shortState(key, version + 1, value);
-// }
-//
-// public KVDataEntry nextVersionInt(int value) {
-// return intState(key, version + 1, value);
-// }
-//
-// public KVDataEntry nextVersionLong(long value) {
-// return longState(key, version + 1, value);
-// }
-//
-// public KVDataEntry nextVersionDatetime(Date value) {
-// return datetimeState(key, version + 1, value);
-// }
-//
-// public KVDataEntry nextVersionJson(String value) {
-// return jsonState(key, version + 1, value);
-// }
-//
-// public KVDataEntry nextVersionXml(String value) {
-// return xmlState(key, version + 1, value);
-// }
-//
-// public KVDataEntry nextVersionBigInt(BigInteger value) {
-// return bigIntState(key, version + 1, value);
-// }
-//
-// public KVDataEntry nextVersionText(boolean encrypted, String value) {
-// return textState(key, version + 1, encrypted, value);
-// }
-//
-// public KVDataEntry nextVersionBytes(boolean encrypted, byte[] value) {
-// return bytesState(key, version + 1, encrypted, value);
-// }
-//
-// public KVDataEntry nextVersionImage(boolean encrypted, byte[] value) {
-// return imageState(key, version + 1, encrypted, value);
-// }
-//
-// public KVDataEntry nextVersionVideo(boolean encrypted, byte[] value) {
-// return videoState(key, version + 1, encrypted, value);
-// }
-//
-// public KVDataEntry nextVersionLocation(boolean encrypted, byte[] value) {
-// return locationState(key, version + 1, encrypted, value);
-// }
-// // ----------------
-//
-// public KVDataEntry newNil() {
-// return nilState(key, version);
-// }
-//
-// public KVDataEntry newBoolean(boolean value) {
-// return booleanState(key, version, value);
-// }
-//
-// public KVDataEntry newTiny(byte value) {
-// return tinyState(key, version, value);
-// }
-//
-// public KVDataEntry newShort(short value) {
-// return shortState(key, version, value);
-// }
-//
-// public KVDataEntry newInt(int value) {
-// return intState(key, version, value);
-// }
-//
-// public KVDataObject newLong(long value) {
-// return longState(key, version, value);
-// }
-//
-// public KVDataEntry newDatetime(Date value) {
-// return datetimeState(key, version, value);
-// }
-//
-// public KVDataEntry newJson(String value) {
-// return jsonState(key, version, value);
-// }
-//
-// public KVDataEntry newXml(String value) {
-// return xmlState(key, version, value);
-// }
-//
-// public KVDataEntry newBigInt(BigInteger value) {
-// return bigIntState(key, version, value);
-// }
-//
-// public KVDataEntry newText(boolean encrypted, String value) {
-// return textState(key, version, encrypted, value);
-// }
-//
-// public KVDataEntry newBytes(boolean encrypted, byte[] value) {
-// return bytesState(key, version, encrypted, value);
-// }
-//
-// public KVDataEntry newImage(boolean encrypted, byte[] value) {
-// return imageState(key, version, encrypted, value);
-// }
-//
-// public KVDataEntry newVideo(boolean encrypted, byte[] value) {
-// return videoState(key, version, encrypted, value);
-// }
-//
-// public KVDataEntry newLocation(boolean encrypted, byte[] value) {
-// return locationState(key, version, encrypted, value);
-// }
-//
-// // ----------------
-//
-// public KVDataEntry newNil(long version) {
-// return nilState(key, version);
-// }
-//
-// public KVDataEntry newBoolean(long version, boolean value) {
-// return booleanState(key, version, value);
-// }
-//
-// public KVDataEntry newTiny(long version, byte value) {
-// return tinyState(key, version, value);
-// }
-//
-// public KVDataEntry newShort(long version, short value) {
-// return shortState(key, version, value);
-// }
-//
-// public KVDataEntry newInt(long version, int value) {
-// return intState(key, version, value);
-// }
-//
-// public KVDataEntry newLong(long version, long value) {
-// return longState(key, version, value);
-// }
-//
-// public KVDataEntry newDatetime(long version, Date value) {
-// return datetimeState(key, version, value);
-// }
-//
-// public KVDataEntry newJson(long version, String value) {
-// return jsonState(key, version, value);
-// }
-//
-// public KVDataEntry newXml(long version, String value) {
-// return xmlState(key, version, value);
-// }
-//
-// public KVDataEntry newBigInt(long version, BigInteger value) {
-// return bigIntState(key, version, value);
-// }
-//
-// public KVDataEntry newText(long version, boolean encrypted, String value) {
-// return textState(key, version, encrypted, value);
-// }
-//
-// public KVDataEntry newBytes(long version, boolean encrypted, byte[] value) {
-// return bytesState(key, version, encrypted, value);
-// }
-//
-// public KVDataEntry newImage(long version, boolean encrypted, byte[] value) {
-// return imageState(key, version, encrypted, value);
-// }
-//
-// public KVDataEntry newVideo(long version, boolean encrypted, byte[] value) {
-// return videoState(key, version, encrypted, value);
-// }
-//
-// public KVDataEntry newLocation(long version, boolean encrypted, byte[] value) {
-// return locationState(key, version, encrypted, value);
-// }
-//
-// // ----------------
-//
-// public static KVDataEntry booleanState(String key, boolean value) {
-// return booleanState(key, -1, value);
-// }
-//
-// public static KVDataEntry tinyState(String key, byte value) {
-// return tinyState(key, -1, value);
-// }
-//
-// public static KVDataEntry shortState(String key, short value) {
-// return shortState(key, -1, value);
-// }
-//
-// public static KVDataEntry intState(String key, int value) {
-// return intState(key, -1, value);
-// }
-//
-// public static KVDataEntry longState(String key, long value) {
-// return longState(key, -1, value);
-// }
-//
-// public static KVDataEntry datetimeState(String key, Date value) {
-// return datetimeState(key, -1, value);
-// }
-//
-// public static KVDataEntry jsonState(String key, String value) {
-// return jsonState(key, -1, value);
-// }
-//
-// public static KVDataEntry xmlState(String key, String value) {
-// return xmlState(key, -1, value);
-// }
-//
-// public static KVDataEntry bigIntState(String key, BigInteger value) {
-// return bigIntState(key, -1, value);
-// }
-//
-// public static KVDataObject textState(String key, String value) {
-// return textState(key, -1, false, value);
-// }
-//
-// public static KVDataEntry bytesState(String key, byte[] value) {
-// return bytesState(key, -1, false, value);
-// }
-//
-// public static KVDataEntry imageState(String key, byte[] value) {
-// return imageState(key, -1, false, value);
-// }
-//
-// public static KVDataEntry videoState(String key, byte[] value) {
-// return videoState(key, -1, false, value);
-// }
-//
-// public static KVDataEntry locationState(String key, byte[] value) {
-// return locationState(key, -1, false, value);
-// }
-//
-// // ----------------
-//
-// public static KVDataEntry textState(String key, boolean encrypted, String value) {
-// return textState(key, -1, encrypted, value);
-// }
-//
-// public static KVDataEntry bytesState(String key, boolean encrypted, byte[] value) {
-// return bytesState(key, -1, encrypted, value);
-// }
-//
-// public static KVDataEntry imageState(String key, boolean encrypted, byte[] value) {
-// return imageState(key, -1, encrypted, value);
-// }
-//
-// public static KVDataEntry videoState(String key, boolean encrypted, byte[] value) {
-// return videoState(key, -1, encrypted, value);
-// }
-//
-// public static KVDataEntry locationState(String key, boolean encrypted, byte[] value) {
-// return locationState(key, -1, encrypted, value);
-// }
-//
-// // ----------------------
-//
-// public static KVDataEntry nilState(String key) {
-// return new KVDataObject(key, ValueType.NIL, -1, false, BytesUtils.EMPTY_BYTES);
-// }
-//
-// public static KVDataEntry nilState(String key, long version) {
-// return new KVDataObject(key, ValueType.NIL, version, false, BytesUtils.EMPTY_BYTES);
-// }
-//
-// public static KVDataEntry booleanState(String key, long version, boolean value) {
-// byte[] v = { value ? (byte) 1 : (byte) 0 };
-// return new KVDataObject(key, ValueType.BOOLEAN, version, false, v);
-// }
-//
-// public static KVDataEntry tinyState(String key, long version, byte value) {
-// byte[] v = { value };
-// return new KVDataObject(key, ValueType.INT8, version, false, v);
-// }
-//
-// public static KVDataEntry shortState(String key, long version, short value) {
-// byte[] v = BytesUtils.toBytes(value);
-// return new KVDataObject(key, ValueType.INT16, version, false, v);
-// }
-//
-// public static KVDataEntry intState(String key, long version, int value) {
-// byte[] v = BytesUtils.toBytes(value);
-// return new KVDataObject(key, ValueType.INT32, version, false, v);
-// }
-//
-// public static KVDataObject longState(String key, long version, long value) {
-// byte[] v = BytesUtils.toBytes(value);
-// return new KVDataObject(key, ValueType.INT64, version, false, v);
-// }
-//
-// public static KVDataEntry datetimeState(String key, long version, Date value) {
-// byte[] v = BytesUtils.toBytes(value.getTime());
-// return new KVDataObject(key, ValueType.DATETIME, version, false, v);
-// }
-//
-// public static KVDataObject textState(String key, long version, boolean encrypted, String value) {
-// try {
-// byte[] v = value.getBytes("UTF-8");
-// return new KVDataObject(key, ValueType.TEXT, version, encrypted, v);
-// } catch (UnsupportedEncodingException e) {
-// throw new IllegalStateException(e.getMessage(), e);
-// }
-// }
-//
-// public static KVDataEntry jsonState(String key, long version, String value) {
-// try {
-// byte[] v = value.getBytes("UTF-8");
-// return new KVDataObject(key, ValueType.JSON, version, false, v);
-// } catch (UnsupportedEncodingException e) {
-// throw new IllegalStateException(e.getMessage(), e);
-// }
-// }
-//
-// public static KVDataEntry xmlState(String key, long version, String value) {
-// try {
-// byte[] v = value.getBytes("UTF-8");
-// return new KVDataObject(key, ValueType.XML, version, false, v);
-// } catch (UnsupportedEncodingException e) {
-// throw new IllegalStateException(e.getMessage(), e);
-// }
-// }
-//
-// public static KVDataEntry bigIntState(String key, long version, BigInteger value) {
-// byte[] v = value.toByteArray();
-// return new KVDataObject(key, ValueType.BIG_INT, version, false, v);
-// }
-//
-// public static KVDataEntry bytesState(String key, long version, boolean encrypted, byte[] value) {
-// return new KVDataObject(key, ValueType.BYTES, version, encrypted, value);
-// }
-//
-// public static KVDataEntry imageState(String key, long version, boolean encrypted, byte[] value) {
-// return new KVDataObject(key, ValueType.IMG, version, encrypted, value);
-// }
-//
-// public static KVDataEntry videoState(String key, long version, boolean encrypted, byte[] value) {
-// return new KVDataObject(key, ValueType.VIDEO, version, encrypted, value);
-// }
-//
-// public static KVDataEntry locationState(String key, long version, boolean encrypted, byte[] value) {
-// return new KVDataObject(key, ValueType.LOCATION, version, encrypted, value);
-// }
-
-}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleDataNode.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleDataNode.java
index c2014877..43e9d32f 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleDataNode.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleDataNode.java
@@ -1,5 +1,6 @@
package com.jd.blockchain.ledger;
+import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.utils.Bytes;
public interface MerkleDataNode extends MerkleNode {
@@ -9,5 +10,7 @@ public interface MerkleDataNode extends MerkleNode {
Bytes getKey();
long getVersion();
+
+ HashDigest getValueHash();
}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleProof.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleProof.java
index 1463f736..75721f7f 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleProof.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleProof.java
@@ -1,8 +1,6 @@
package com.jd.blockchain.ledger;
-import com.jd.blockchain.crypto.HashDigest;
-
-public interface MerkleProof {
+public interface MerkleProof extends HashProof {
/**
* 所证明的数据节点的序列号;
@@ -11,62 +9,46 @@ public interface MerkleProof {
*/
long getSN();
- /**
- * 最大层级数;
- * 叶子节点(即数据节点)的层级为 0,数据节点之上的每一级父节点的层级加 1, 最大层级便是根节点的层级;
- *
- * @return
- *
- * @see MerkleTree#getLevel()
- */
- int getLevels();
-
- /**
- * 返回证明中指定层级的节点的哈希;
- *
- *
- * @param level
- * 参数值为 0 返回的是数据节点的哈希;
- * 参数值为 {@link #getLevels()} 返回的是根节点的哈希;
- * @return
- */
- HashDigest getHash(int level);
-
- MerkleNode getNode(int level);
-
// /**
-// * 返回证明中指定层级的数据起始序号;
+// * 最大层级数;
+// * 叶子节点(即数据节点)的层级为 0,数据节点之上的每一级父节点的层级加 1, 最大层级便是根节点的层级;
// *
-// * @param level
// * @return
+// *
+// * @see MerkleTree#getLevel()
// */
-// long getStartingSN(int level);
-
+// int getLevels();
+//
// /**
-// * 返回证明中指定层级的数据记录总数;
+// * 返回证明中指定层级的节点的哈希;
+// *
// *
// * @param level
+// * 参数值为 0 返回的是数据节点的哈希;
+// * 参数值为 {@link #getLevels()} 返回的是根节点的哈希;
// * @return
// */
-// long getDataCount(int level);
+// HashDigest getHash(int level);
- /**
- * 返回根节点的哈希;
- *
- * @return
- */
- default HashDigest getRootHash() {
- return getHash(getLevels());
- }
+ MerkleNode getNode(int level);
/**
- * 返回数据节点的哈希;
- *
- * @return
- */
- default HashDigest getDataHash() {
- return getHash(0);
- }
+// * 返回根节点的哈希;
+// *
+// * @return
+// */
+// default HashDigest getRootHash() {
+// return getHash(getLevels());
+// }
+//
+// /**
+// * 返回数据节点的哈希;
+// *
+// * @return
+// */
+// default HashDigest getDataHash() {
+// return getHash(0);
+// }
default MerkleDataNode getDataNode() {
return (MerkleDataNode)getNode(0);
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVData.java
new file mode 100644
index 00000000..dd06de98
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVData.java
@@ -0,0 +1,78 @@
+package com.jd.blockchain.ledger;
+
+/**
+ * 强类型的“键-值”数据对象;
+ *
+ *
+ *
+ * {@link TypedKVData} 被设计为只读对象;
+ *
+ * @author huanghaiquan
+ *
+ */
+public class TypedKVData implements TypedKVEntry {
+
+ private String key;
+
+ private long version;
+
+ private DataType type;
+
+ private Object value;
+
+ public TypedKVData(String key, long version, DataType type, Object value) {
+ this.key = key;
+ this.version = version;
+ this.type = type;
+ this.value = value;
+ }
+
+ public TypedKVData(String key, long version, BytesValue bytesValue) {
+ this.key = key;
+ this.version = version;
+ TypedValue typedValue;
+ if (bytesValue != null && bytesValue instanceof TypedValue) {
+ typedValue = (TypedValue) bytesValue;
+ } else {
+ typedValue = TypedValue.wrap(bytesValue);
+ }
+ this.type = typedValue.getType();
+ this.value = typedValue.getValue();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.jd.blockchain.ledger.KVDataEntry#getKey()
+ */
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.jd.blockchain.ledger.KVDataEntry#getVersion()
+ */
+ @Override
+ public long getVersion() {
+ return version;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.jd.blockchain.ledger.KVDataEntry#getType()
+ */
+ @Override
+ public DataType getType() {
+ return type;
+ }
+
+ @Override
+ public Object getValue() {
+ return value;
+ }
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataEntry.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVEntry.java
similarity index 57%
rename from source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataEntry.java
rename to source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVEntry.java
index 396cc36d..54165c61 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataEntry.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVEntry.java
@@ -1,6 +1,6 @@
package com.jd.blockchain.ledger;
-public interface KVDataEntry {
+public interface TypedKVEntry {
/**
* 键名;
@@ -33,4 +33,12 @@ public interface KVDataEntry {
*/
Object getValue();
+ default long longValue() {
+ if (getType() == DataType.INT64) {
+ Object value = getValue();
+ return value == null ? 0 : (long) value;
+ }
+ throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT64, getType()));
+ }
+
}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedValue.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedValue.java
new file mode 100644
index 00000000..65dbd298
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedValue.java
@@ -0,0 +1,454 @@
+package com.jd.blockchain.ledger;
+
+import java.math.BigInteger;
+import java.util.Date;
+
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.crypto.SignatureDigest;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.io.BytesUtils;
+
+/**
+ *
+ * @author huanghaiquan
+ *
+ */
+public class TypedValue implements BytesValue {
+
+ public static final BytesValue NIL = new TypedValue();
+
+ private DataType type;
+ private Bytes value;
+
+ private TypedValue(DataType type, byte[] bytes) {
+ this.type = type;
+ this.value = new Bytes(bytes);
+ }
+
+ private TypedValue(DataType type, Bytes bytes) {
+ this.type = type;
+ this.value = bytes;
+ }
+
+ private TypedValue(BytesValue bytesValue) {
+ if (bytesValue == null) {
+ this.type = DataType.NIL;
+ } else {
+ this.type = bytesValue.getType();
+ this.value = bytesValue.getBytes();
+ }
+ }
+
+ private TypedValue() {
+ this.type = DataType.NIL;
+ }
+
+ @Override
+ public DataType getType() {
+ return this.type;
+ }
+
+ @Override
+ public Bytes getBytes() {
+ return this.value;
+ }
+
+ public Object getValue() {
+ if (isNil()) {
+ return null;
+ }
+ switch (type) {
+ case BOOLEAN:
+ return toBoolean();
+ case INT8:
+ return toInt8();
+ case INT16:
+ return toInt16();
+ case INT32:
+ return toInt32();
+ case INT64:
+ return toInt64();
+ case BIG_INT:
+ return toBigInteger();
+ case TIMESTAMP:
+ return toDatetime();
+ case TEXT:
+ case JSON:
+ case XML:
+ return toText();
+
+ case BYTES:
+ case VIDEO:
+ case IMG:
+ case LOCATION:
+ case ENCRYPTED_DATA:
+ return toBytesArray();
+
+ case HASH_DIGEST:
+ return toHashDegist();
+ case PUB_KEY:
+ return toPubKey();
+ case SIGNATURE_DIGEST:
+ return toSignatureDigest();
+
+ case DATA_CONTRACT:
+ return toBytesArray();
+ default:
+ throw new IllegalStateException(String.format("Type [%s] has not be supported!", type));
+ }
+ }
+
+ /**
+ * 是否为空值;
+ *
+ *
+ * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#NIL} 时返回 true,其它情况返回 false;
+ *
+ *
+ * @return
+ */
+ public boolean isNil() {
+ return value == null || DataType.NIL == type;
+ }
+
+ /**
+ * 返回 8 位整数值;
+ *
+ *
+ * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT8} 有效;
+ *
+ *
+ * 无效类型将引发 {@link IllegalStateException} 异常;
+ *
+ * @return
+ */
+ public byte tinyValue() {
+ if (isNil()) {
+ return DataType.INT8_DEFAULT_VALUE;
+ }
+ if (DataType.INT8 == getType()) {
+ return toInt8();
+ }
+ throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int8!", type));
+ }
+
+ private byte toInt8() {
+ return value.toBytes()[0];
+ }
+
+ /**
+ * 返回 16 位整数值;
+ *
+ *
+ * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT16} 有效;
+ *
+ *
+ * 无效类型将引发 {@link IllegalStateException} 异常;
+ *
+ * @return
+ */
+ public short shortValue() {
+ if (isNil()) {
+ return DataType.INT16_DEFAULT_VALUE;
+ }
+ if (DataType.INT16 == getType()) {
+ return toInt16();
+ }
+ throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int16!", type));
+ }
+
+ private short toInt16() {
+ return BytesUtils.toShort(value.toBytes(), 0);
+ }
+
+ /**
+ * 返回 32 位整数值;
+ *
+ *
+ * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT32} 有效;
+ *
+ *
+ * 无效类型将引发 {@link IllegalStateException} 异常;
+ *
+ * @return
+ */
+ public int intValue() {
+ if (isNil()) {
+ return DataType.INT32_DEFAULT_VALUE;
+ }
+ if (DataType.INT32 == getType()) {
+ return toInt32();
+ }
+ throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int32!", type));
+ }
+
+ private int toInt32() {
+ return BytesUtils.toInt(value.toBytes(), 0);
+ }
+
+ /**
+ * 返回 64 位整数值;
+ *
+ *
+ * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT64} 有效;
+ *
+ *
+ * 无效类型将引发 {@link IllegalStateException} 异常;
+ *
+ * @return
+ */
+ public long longValue() {
+ if (isNil()) {
+ return DataType.INT64_DEFAULT_VALUE;
+ }
+ if (DataType.INT64 == type) {
+ return toInt64();
+ }
+ throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int64!", type));
+
+ }
+
+ private long toInt64() {
+ return BytesUtils.toLong(value.toBytes(), 0);
+ }
+
+ /**
+ * 返回大整数值;
+ *
+ *
+ * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#BIG_INT} 有效;
+ *
+ *
+ * 无效类型将引发 {@link IllegalStateException} 异常;
+ *
+ * @return
+ */
+ public BigInteger bigIntValue() {
+ if (isNil()) {
+ return null;
+ }
+ if (DataType.BIG_INT == type) {
+ return toBigInteger();
+ }
+ throw new IllegalStateException(String.format("Type [%s] cannot be convert to BigInteger!", type));
+ }
+
+ private BigInteger toBigInteger() {
+ return new BigInteger(value.toBytes());
+ }
+
+ /**
+ * 返回布尔值;
+ *
+ *
+ * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#BIG_INT} 有效;
+ *
+ *
+ * 无效类型将引发 {@link IllegalStateException} 异常;
+ *
+ * @return
+ */
+ public boolean boolValue() {
+ if (isNil()) {
+ return DataType.BOOLEAN_DEFAULT_VALUE;
+ }
+ if (DataType.BOOLEAN == type) {
+ return toBoolean();
+ }
+ throw new IllegalStateException(String.format("Type [%s] cannot be convert to boolean!", type));
+ }
+
+ private boolean toBoolean() {
+ return BytesUtils.toBoolean(value.toBytes()[0]);
+ }
+
+ /**
+ * 返回日期时间值;
+ *
+ *
+ * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TIMESTAMP} 有效;
+ *
+ *
+ * 无效类型将引发 {@link IllegalStateException} 异常;
+ *
+ * @return
+ */
+ public Date datetimeValue() {
+ if (isNil()) {
+ return null;
+ }
+ if (DataType.TIMESTAMP == type) {
+ return toDatetime();
+ }
+ throw new IllegalStateException(String.format("Type [%s] cannot be convert to datetime!", type));
+ }
+
+ private Date toDatetime() {
+ long ts = BytesUtils.toLong(value.toBytes());
+ return new Date(ts);
+ }
+
+ /**
+ * 返回文本值;
+ *
+ *
+ * 仅当数据类型 {@link #getType()} 为“文本类型”或“文本衍生类型”时有效;
+ *
+ *
+ * 无效类型将引发 {@link IllegalStateException} 异常;
+ *
+ * @return
+ */
+ public String stringValue() {
+ if (isNil()) {
+ return null;
+ }
+ if (type.isText()) {
+ return toText();
+ }
+ throw new IllegalStateException(String.format("Type [%s] cannot be convert to text!", type));
+ }
+
+ private String toText() {
+ return value.toUTF8String();
+ }
+
+ /**
+ * 返回字节数组的值;
+ *
+ *
+ * 仅当数据类型 {@link #getType()} 为“字节类型”或“字节衍生类型”时有效;
+ *
+ *
+ * 无效类型将引发 {@link IllegalStateException} 异常;
+ *
+ * @return
+ */
+ public byte[] bytesValue() {
+ if (isNil()) {
+ return null;
+ }
+ if (type.isBytes()) {
+ return toBytesArray();
+ }
+ throw new IllegalStateException(String.format("Type [%s] cannot be convert to bytes!", type));
+ }
+
+ private byte[] toBytesArray() {
+ return value.toBytes();
+ }
+
+ public HashDigest hashDigestValue() {
+ if (isNil()) {
+ return null;
+ }
+ if (DataType.HASH_DIGEST == type) {
+ return toHashDegist();
+ }
+ throw new IllegalStateException(String.format("Type [%s] cannot be convert to hash digest!", type));
+ }
+
+ private HashDigest toHashDegist() {
+ return new HashDigest(toBytesArray());
+ }
+
+ public PubKey pubKeyValue() {
+ if (isNil()) {
+ return null;
+ }
+ if (DataType.PUB_KEY == type) {
+ return toPubKey();
+ }
+ throw new IllegalStateException(String.format("Type [%s] cannot be convert to pub key!", type));
+ }
+
+ private PubKey toPubKey() {
+ return new PubKey(toBytesArray());
+ }
+
+ public SignatureDigest signatureDigestValue() {
+ if (isNil()) {
+ return null;
+ }
+ if (DataType.SIGNATURE_DIGEST == type) {
+ return toSignatureDigest();
+ }
+ throw new IllegalStateException(String.format("Type [%s] cannot be convert to signature digest!", type));
+ }
+
+ private SignatureDigest toSignatureDigest() {
+ return new SignatureDigest(toBytesArray());
+ }
+
+ public static TypedValue wrap(BytesValue value) {
+ return new TypedValue(value);
+ }
+
+ public static TypedValue fromType(DataType type, byte[] value) {
+ return new TypedValue(type, value);
+ }
+
+ public static TypedValue fromBytes(byte[] value) {
+ return new TypedValue(DataType.BYTES, value);
+ }
+
+ public static TypedValue fromBytes(Bytes value) {
+ return new TypedValue(DataType.BYTES, value);
+ }
+
+ public static TypedValue fromImage(byte[] value) {
+ return new TypedValue(DataType.IMG, value);
+ }
+
+ public static TypedValue fromImage(Bytes value) {
+ return new TypedValue(DataType.IMG, value);
+ }
+
+ /**
+ * 以 UTF-8 编码从字符串转换为字节数组值;
+ *
+ * @param value
+ * @return
+ */
+ public static TypedValue fromText(String value) {
+ return new TypedValue(DataType.TEXT, BytesUtils.toBytes(value));
+ }
+
+ public static TypedValue fromJSON(String value) {
+ return new TypedValue(DataType.JSON, BytesUtils.toBytes(value));
+ }
+
+ public static TypedValue fromXML(String value) {
+ return new TypedValue(DataType.XML, BytesUtils.toBytes(value));
+ }
+
+ public static TypedValue fromInt32(int value) {
+ return new TypedValue(DataType.INT32, BytesUtils.toBytes(value));
+ }
+
+ public static TypedValue fromInt64(long value) {
+ return new TypedValue(DataType.INT64, BytesUtils.toBytes(value));
+ }
+
+ public static TypedValue fromInt16(short value) {
+ return new TypedValue(DataType.INT16, BytesUtils.toBytes(value));
+ }
+
+ public static TypedValue fromInt8(byte value) {
+ return new TypedValue(DataType.INT8, BytesUtils.toBytes(value));
+ }
+
+ public static TypedValue fromTimestamp(long value) {
+ return new TypedValue(DataType.TIMESTAMP, BytesUtils.toBytes(value));
+ }
+
+ public static TypedValue fromBoolean(boolean value) {
+ return new TypedValue(DataType.BOOLEAN, BytesUtils.toBytes(value));
+ }
+
+ public static TypedValue fromPubKey(PubKey pubKey) {
+ return new TypedValue(DataType.PUB_KEY, pubKey.toBytes());
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedValue_.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedValue_.java
new file mode 100644
index 00000000..145344b5
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedValue_.java
@@ -0,0 +1,472 @@
+//package com.jd.blockchain.ledger;
+//
+//import java.math.BigInteger;
+//import java.util.Date;
+//
+//import com.jd.blockchain.binaryproto.PrimitiveType;
+//import com.jd.blockchain.crypto.HashDigest;
+//import com.jd.blockchain.crypto.PubKey;
+//import com.jd.blockchain.crypto.SignatureDigest;
+//import com.jd.blockchain.utils.Bytes;
+//import com.jd.blockchain.utils.io.BytesUtils;
+//
+//public class TypedValue_ {
+//
+// private BytesValue bytesValue;
+//
+// public TypedValue_(BytesValue bytesValue) {
+// this.bytesValue = bytesValue;
+// }
+//
+// public DataType getType() {
+// return bytesValue == null ? DataType.NIL : bytesValue.getType();
+// }
+//
+// public Object getValue() {
+// if (isNil()) {
+// return null;
+// }
+// switch (bytesValue.getType()) {
+// case BOOLEAN:
+// return toBoolean();
+// case INT8:
+// return toInt8();
+// case INT16:
+// return toInt16();
+// case INT32:
+// return toInt32();
+// case INT64:
+// return toInt64();
+// case BIG_INT:
+// return toBigInteger();
+// case TIMESTAMP:
+// return toDatetime();
+// case TEXT:
+// case JSON:
+// case XML:
+// return toText();
+//
+// case BYTES:
+// case VIDEO:
+// case IMG:
+// case LOCATION:
+// case ENCRYPTED_DATA:
+// return toBytesArray();
+//
+// case HASH_DIGEST:
+// return toHashDegist();
+// case PUB_KEY:
+// return toPubKey();
+// case SIGNATURE_DIGEST:
+// return toSignatureDigest();
+//
+// case DATA_CONTRACT:
+// return toBytesArray();
+// default:
+// throw new IllegalStateException(String.format("Type [%s] has not be supported!", bytesValue.getType()));
+// }
+// }
+//
+// /**
+// * 是否为空值;
+// *
+// *
+// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#NIL} 时返回 true,其它情况返回 false;
+// *
+// *
+// * @return
+// */
+// public boolean isNil() {
+// return bytesValue == null || DataType.NIL == bytesValue.getType();
+// }
+//
+// /**
+// * 返回 8 位整数值;
+// *
+// *
+// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT8} 有效;
+// *
+// *
+// * 无效类型将引发 {@link IllegalStateException} 异常;
+// *
+// * @return
+// */
+// public byte tinyValue() {
+// if (isNil()) {
+// return DataType.INT8_DEFAULT_VALUE;
+// }
+// if (DataType.INT8 == getType()) {
+// return toInt8();
+// }
+// throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int8!", bytesValue.getType()));
+// }
+//
+// private byte toInt8() {
+// return bytesValue.getValue().toBytes()[0];
+// }
+//
+// /**
+// * 返回 16 位整数值;
+// *
+// *
+// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT16} 有效;
+// *
+// *
+// * 无效类型将引发 {@link IllegalStateException} 异常;
+// *
+// * @return
+// */
+// public short shortValue() {
+// if (isNil()) {
+// return DataType.INT16_DEFAULT_VALUE;
+// }
+// if (DataType.INT16 == getType()) {
+// return toInt16();
+// }
+// throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int16!", bytesValue.getType()));
+// }
+//
+// private short toInt16() {
+// return BytesUtils.toShort(bytesValue.getValue().toBytes(), 0);
+// }
+//
+// /**
+// * 返回 32 位整数值;
+// *
+// *
+// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT32} 有效;
+// *
+// *
+// * 无效类型将引发 {@link IllegalStateException} 异常;
+// *
+// * @return
+// */
+// public int intValue() {
+// if (isNil()) {
+// return DataType.INT32_DEFAULT_VALUE;
+// }
+// if (DataType.INT32 == getType()) {
+// return toInt32();
+// }
+// throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int32!", bytesValue.getType()));
+// }
+//
+// private int toInt32() {
+// return BytesUtils.toInt(bytesValue.getValue().toBytes(), 0);
+// }
+//
+// /**
+// * 返回 64 位整数值;
+// *
+// *
+// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT64} 有效;
+// *
+// *
+// * 无效类型将引发 {@link IllegalStateException} 异常;
+// *
+// * @return
+// */
+// public long longValue() {
+// if (isNil()) {
+// return DataType.INT64_DEFAULT_VALUE;
+// }
+// if (DataType.INT64 == bytesValue.getType()) {
+// return toInt64();
+// }
+// throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int64!", bytesValue.getType()));
+//
+// }
+//
+// private long toInt64() {
+// return BytesUtils.toLong(bytesValue.getValue().toBytes(), 0);
+// }
+//
+// /**
+// * 返回大整数值;
+// *
+// *
+// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#BIG_INT} 有效;
+// *
+// *
+// * 无效类型将引发 {@link IllegalStateException} 异常;
+// *
+// * @return
+// */
+// public BigInteger bigIntValue() {
+// if (isNil()) {
+// return null;
+// }
+// if (DataType.BIG_INT == bytesValue.getType()) {
+// return toBigInteger();
+// }
+// throw new IllegalStateException(
+// String.format("Type [%s] cannot be convert to BigInteger!", bytesValue.getType()));
+// }
+//
+// private BigInteger toBigInteger() {
+// return new BigInteger(bytesValue.getValue().toBytes());
+// }
+//
+// /**
+// * 返回布尔值;
+// *
+// *
+// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#BIG_INT} 有效;
+// *
+// *
+// * 无效类型将引发 {@link IllegalStateException} 异常;
+// *
+// * @return
+// */
+// public boolean boolValue() {
+// if (isNil()) {
+// return DataType.BOOLEAN_DEFAULT_VALUE;
+// }
+// if (DataType.BOOLEAN == bytesValue.getType()) {
+// return toBoolean();
+// }
+// throw new IllegalStateException(String.format("Type [%s] cannot be convert to boolean!", bytesValue.getType()));
+// }
+//
+// private boolean toBoolean() {
+// return BytesUtils.toBoolean(bytesValue.getValue().toBytes()[0]);
+// }
+//
+// /**
+// * 返回日期时间值;
+// *
+// *
+// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TIMESTAMP} 有效;
+// *
+// *
+// * 无效类型将引发 {@link IllegalStateException} 异常;
+// *
+// * @return
+// */
+// public Date datetimeValue() {
+// if (isNil()) {
+// return null;
+// }
+// if (DataType.TIMESTAMP == bytesValue.getType()) {
+// return toDatetime();
+// }
+// throw new IllegalStateException(
+// String.format("Type [%s] cannot be convert to datetime!", bytesValue.getType()));
+// }
+//
+// private Date toDatetime() {
+// long ts = BytesUtils.toLong(bytesValue.getValue().toBytes());
+// return new Date(ts);
+// }
+//
+// /**
+// * 返回文本值;
+// *
+// *
+// * 仅当数据类型 {@link #getType()} 为“文本类型”或“文本衍生类型”时有效;
+// *
+// *
+// * 无效类型将引发 {@link IllegalStateException} 异常;
+// *
+// * @return
+// */
+// public String stringValue() {
+// if (isNil()) {
+// return null;
+// }
+// DataType type = bytesValue.getType();
+// if (type.isText()) {
+// return toText();
+// }
+// throw new IllegalStateException(String.format("Type [%s] cannot be convert to text!", type));
+// }
+//
+// private String toText() {
+// return bytesValue.getValue().toUTF8String();
+// }
+//
+// /**
+// * 返回字节数组的值;
+// *
+// *
+// * 仅当数据类型 {@link #getType()} 为“字节类型”或“字节衍生类型”时有效;
+// *
+// *
+// * 无效类型将引发 {@link IllegalStateException} 异常;
+// *
+// * @return
+// */
+// public byte[] bytesValue() {
+// if (isNil()) {
+// return null;
+// }
+// DataType type = bytesValue.getType();
+// if (type.isBytes()) {
+// return toBytesArray();
+// }
+// throw new IllegalStateException(String.format("Type [%s] cannot be convert to bytes!", type));
+// }
+//
+// private byte[] toBytesArray() {
+// return bytesValue.getValue().toBytes();
+// }
+//
+// public HashDigest hashDigestValue() {
+// if (isNil()) {
+// return null;
+// }
+// if (DataType.HASH_DIGEST == bytesValue.getType()) {
+// return toHashDegist();
+// }
+// throw new IllegalStateException(
+// String.format("Type [%s] cannot be convert to hash digest!", bytesValue.getType()));
+// }
+//
+// private HashDigest toHashDegist() {
+// return new HashDigest(toBytesArray());
+// }
+//
+// public PubKey pubKeyValue() {
+// if (isNil()) {
+// return null;
+// }
+// if (DataType.PUB_KEY == bytesValue.getType()) {
+// return toPubKey();
+// }
+// throw new IllegalStateException(String.format("Type [%s] cannot be convert to pub key!", bytesValue.getType()));
+// }
+//
+// private PubKey toPubKey() {
+// return new PubKey(toBytesArray());
+// }
+//
+// public SignatureDigest signatureDigestValue() {
+// if (isNil()) {
+// return null;
+// }
+// if (DataType.SIGNATURE_DIGEST == bytesValue.getType()) {
+// return toSignatureDigest();
+// }
+// throw new IllegalStateException(
+// String.format("Type [%s] cannot be convert to signature digest!", bytesValue.getType()));
+// }
+//
+// private SignatureDigest toSignatureDigest() {
+// return new SignatureDigest(toBytesArray());
+// }
+//
+// public BytesValue convertToBytesValue() {
+// return bytesValue == null ? TypedBytesValue.NIL : bytesValue;
+// }
+//
+// public static TypedBytesValue fromText(String key, String value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromText(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromBoolean(String key, boolean value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromBoolean(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromInt8(String key, byte value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromInt8(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromInt16(String key, short value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromInt16(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromInt32(String key, int value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromInt32(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromInt64(String key, long value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromInt64(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromBytes(String key, byte[] value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromBytes(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromTimestamp(String key, long value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromTimestamp(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromJSON(String key, String value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromJSON(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromXML(String key, String value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromXML(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromImage(String key, byte[] value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromImage(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromText(Bytes key, String value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromText(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromBoolean(Bytes key, boolean value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromBoolean(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromInt8(Bytes key, byte value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromInt8(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromInt16(Bytes key, short value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromInt16(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromInt32(Bytes key, int value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromInt32(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromInt64(Bytes key, long value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromInt64(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromBytes(Bytes key, byte[] value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromBytes(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromTimestamp(Bytes key, long value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromTimestamp(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromJSON(Bytes key, String value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromJSON(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromXML(Bytes key, String value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromXML(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+// public static TypedBytesValue fromImage(Bytes key, byte[] value, long version) {
+// BytesValue bytesValue = TypedBytesValue.fromImage(value);
+// return new TypedBytesValue(bytesValue);
+// }
+//
+//}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAccountHeader.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAccountHeader.java
new file mode 100644
index 00000000..8fc0e7a5
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAccountHeader.java
@@ -0,0 +1,12 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.consts.DataCodes;
+import com.jd.blockchain.crypto.PubKey;
+
+@DataContract(code= DataCodes.USER_ACCOUNT_HEADER)
+public interface UserAccountHeader extends BlockchainIdentity {
+
+ PubKey getDataPubKey();
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfo.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfo.java
index 48759b9f..c7b14d1a 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfo.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfo.java
@@ -2,11 +2,8 @@ package com.jd.blockchain.ledger;
import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.consts.DataCodes;
-import com.jd.blockchain.crypto.PubKey;
-@DataContract(code= DataCodes.USER)
-public interface UserInfo extends AccountHeader {
-
- PubKey getDataPubKey();
-
+@DataContract(code = DataCodes.USER_INFO)
+public interface UserInfo extends UserAccountHeader {
+
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/AbstractBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/AbstractBytesValueResolver.java
index 995d5522..d6ee0b98 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/AbstractBytesValueResolver.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/AbstractBytesValueResolver.java
@@ -47,7 +47,7 @@ public abstract class AbstractBytesValueResolver implements BytesValueResolver {
if (!isSupport(dataType)) {
throw new IllegalStateException(String.format("Un-support encode DataType[%s] Object !!!", dataType.name()));
}
- return decode(value.getValue());
+ return decode(value.getBytes());
}
protected abstract Object decode(Bytes value);
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BooleanToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BooleanToBytesValueResolver.java
index 0664fdb9..69285395 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BooleanToBytesValueResolver.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BooleanToBytesValueResolver.java
@@ -1,6 +1,6 @@
package com.jd.blockchain.ledger.resolver;
-import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataType;
import com.jd.blockchain.utils.Bytes;
@@ -21,7 +21,7 @@ public class BooleanToBytesValueResolver extends AbstractBytesValueResolver {
if (!isSupport(type)) {
throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName()));
}
- return BytesData.fromBoolean((boolean) value);
+ return TypedValue.fromBoolean((boolean) value);
}
@Override
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesToBytesValueResolver.java
index f4871515..fe71eee7 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesToBytesValueResolver.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesToBytesValueResolver.java
@@ -1,6 +1,6 @@
package com.jd.blockchain.ledger.resolver;
-import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataType;
import com.jd.blockchain.utils.Bytes;
@@ -21,9 +21,9 @@ public class BytesToBytesValueResolver extends AbstractBytesValueResolver {
throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName()));
}
if (type.equals(byte[].class)) {
- return BytesData.fromBytes((byte[]) value);
+ return TypedValue.fromBytes((byte[]) value);
}
- return BytesData.fromBytes((Bytes) value);
+ return TypedValue.fromBytes((Bytes) value);
}
@Override
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/IntegerToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/IntegerToBytesValueResolver.java
index a8400f02..075d1f76 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/IntegerToBytesValueResolver.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/IntegerToBytesValueResolver.java
@@ -1,6 +1,6 @@
package com.jd.blockchain.ledger.resolver;
-import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataType;
import com.jd.blockchain.utils.Bytes;
@@ -21,7 +21,7 @@ public class IntegerToBytesValueResolver extends AbstractBytesValueResolver {
if (!isSupport(type)) {
throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName()));
}
- return BytesData.fromInt32((int) value);
+ return TypedValue.fromInt32((int) value);
}
@Override
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/LongToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/LongToBytesValueResolver.java
index fa11bcf4..ce6dbaf9 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/LongToBytesValueResolver.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/LongToBytesValueResolver.java
@@ -1,6 +1,6 @@
package com.jd.blockchain.ledger.resolver;
-import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataType;
import com.jd.blockchain.utils.Bytes;
@@ -21,7 +21,7 @@ public class LongToBytesValueResolver extends AbstractBytesValueResolver {
if (!isSupport(type)) {
throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName()));
}
- return BytesData.fromInt64((long)value);
+ return TypedValue.fromInt64((long)value);
}
@Override
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/ShortToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/ShortToBytesValueResolver.java
index b8eea38c..ddbed5fb 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/ShortToBytesValueResolver.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/ShortToBytesValueResolver.java
@@ -1,6 +1,6 @@
package com.jd.blockchain.ledger.resolver;
-import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataType;
import com.jd.blockchain.utils.Bytes;
@@ -21,7 +21,7 @@ public class ShortToBytesValueResolver extends AbstractBytesValueResolver {
if (!isSupport(type)) {
throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName()));
}
- return BytesData.fromInt16((short)value);
+ return TypedValue.fromInt16((short)value);
}
@Override
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/StringToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/StringToBytesValueResolver.java
index dca8e5d1..0f08442e 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/StringToBytesValueResolver.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/StringToBytesValueResolver.java
@@ -1,6 +1,6 @@
package com.jd.blockchain.ledger.resolver;
-import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataType;
import com.jd.blockchain.utils.Bytes;
@@ -26,10 +26,10 @@ public class StringToBytesValueResolver extends AbstractBytesValueResolver {
// 类型判断
String valString = (String)value;
if (JSONSerializeUtils.isJSON(valString)) {
- return BytesData.fromJSON(valString);
+ return TypedValue.fromJSON(valString);
}
// 暂不处理XML格式
- return BytesData.fromText(valString);
+ return TypedValue.fromText(valString);
}
@Override
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java
index 9710b50d..f63a7f2a 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java
@@ -3,9 +3,9 @@ package com.jd.blockchain.transaction;
import org.springframework.cglib.core.Block;
import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.ContractInfo;
-import com.jd.blockchain.ledger.KVDataEntry;
+import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.KVInfoVO;
import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerBlock;
@@ -250,7 +250,7 @@ public interface BlockchainQueryService {
* @param address
* @return
*/
- AccountHeader getDataAccount(HashDigest ledgerHash, String address);
+ BlockchainIdentity getDataAccount(HashDigest ledgerHash, String address);
/**
* 返回数据账户中指定的键的最新值;
@@ -264,9 +264,9 @@ public interface BlockchainQueryService {
* @param keys
* @return
*/
- KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys);
+ TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys);
- KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO);
+ TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO);
/**
* 返回指定数据账户中KV数据的总数;
@@ -287,7 +287,7 @@ public interface BlockchainQueryService {
* 如果参数值为 -1,则返回全部的记录;
* @return
*/
- KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count);
+ TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count);
/**
* 返回合约账户信息;
@@ -306,7 +306,7 @@ public interface BlockchainQueryService {
* @param count
* @return
*/
- AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count);
+ BlockchainIdentity[] getUsers(HashDigest ledgerHash, int fromIndex, int count);
/**
* get data accounts by ledgerHash and its range;
@@ -316,7 +316,7 @@ public interface BlockchainQueryService {
* @param count
* @return
*/
- AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count);
+ BlockchainIdentity[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count);
/**
* get contract accounts by ledgerHash and its range;
@@ -326,5 +326,5 @@ public interface BlockchainQueryService {
* @param count
* @return
*/
- AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count);
+ BlockchainIdentity[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count);
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java
index b2ccef13..cec540c9 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java
@@ -1,7 +1,7 @@
package com.jd.blockchain.transaction;
import com.jd.blockchain.ledger.BytesValue;
-import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.utils.Bytes;
@@ -26,14 +26,14 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe
@Override
public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) {
- BytesValue bytesValue = BytesData.fromBytes(value);
+ BytesValue bytesValue = TypedValue.fromBytes(value);
operation.set(key, bytesValue, expVersion);
return this;
}
@Override
public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) {
- BytesValue bytesValue = BytesData.fromImage(value);
+ BytesValue bytesValue = TypedValue.fromImage(value);
operation.set(key, bytesValue, expVersion);
return this;
}
@@ -45,42 +45,42 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe
@Override
public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) {
- BytesValue bytesValue = BytesData.fromText(value);
+ BytesValue bytesValue = TypedValue.fromText(value);
operation.set(key, bytesValue, expVersion);
return this;
}
@Override
public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) {
- BytesValue bytesValue = BytesData.fromBytes(value);
+ BytesValue bytesValue = TypedValue.fromBytes(value);
operation.set(key, bytesValue, expVersion);
return this;
}
@Override
public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) {
- BytesValue bytesValue = BytesData.fromInt64(value);
+ BytesValue bytesValue = TypedValue.fromInt64(value);
operation.set(key, bytesValue, expVersion);
return this;
}
@Override
public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) {
- BytesValue bytesValue = BytesData.fromJSON(value);
+ BytesValue bytesValue = TypedValue.fromJSON(value);
operation.set(key, bytesValue, expVersion);
return this;
}
@Override
public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) {
- BytesValue bytesValue = BytesData.fromXML(value);
+ BytesValue bytesValue = TypedValue.fromXML(value);
operation.set(key, bytesValue, expVersion);
return this;
}
@Override
public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) {
- BytesValue bytesValue = BytesData.fromTimestamp(value);
+ BytesValue bytesValue = TypedValue.fromTimestamp(value);
operation.set(key, bytesValue, expVersion);
return this;
}
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesToBytesValueResolverTest.java
index 3635743c..2dfa0dbd 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesToBytesValueResolverTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesToBytesValueResolverTest.java
@@ -26,7 +26,7 @@ public class BytesToBytesValueResolverTest {
assertEquals(bytesValue.getType(), DataType.BYTES);
- assertEquals(bytesObj, bytesValue.getValue());
+ assertEquals(bytesObj, bytesValue.getBytes());
Bytes resolveBytesObj = (Bytes)resolver.decode(bytesValue);
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesValueEncodingTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesValueEncodingTest.java
index e5b624c9..f572a831 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesValueEncodingTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesValueEncodingTest.java
@@ -28,9 +28,9 @@ public class BytesValueEncodingTest {
BytesValue longBytesVal2 = BytesValueEncoding.encodeSingle(longVal, long.class);
BytesValue longBytesVal3 = BytesValueEncoding.encodeSingle(longVal, Long.class);
- assertEquals(longBytesVal1.getValue(), longBytesVal2.getValue());
+ assertEquals(longBytesVal1.getBytes(), longBytesVal2.getBytes());
assertEquals(longBytesVal1.getType(), longBytesVal2.getType());
- assertEquals(longBytesVal2.getValue(), longBytesVal3.getValue());
+ assertEquals(longBytesVal2.getBytes(), longBytesVal3.getBytes());
assertEquals(longBytesVal2.getType(), longBytesVal3.getType());
long resolveLongVal1 = (long)BytesValueEncoding.decode(longBytesVal1);
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractEventSendOpTemplateTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractEventSendOpTemplateTest.java
index d010ae6f..506d86d4 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractEventSendOpTemplateTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractEventSendOpTemplateTest.java
@@ -16,7 +16,7 @@ import org.junit.Test;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
-import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.BytesDataList;
import com.jd.blockchain.ledger.BytesValueList;
import com.jd.blockchain.ledger.ContractEventSendOperation;
@@ -41,7 +41,7 @@ public class ContractEventSendOpTemplateTest {
DataContractRegistry.register(ContractEventSendOperation.class);
DataContractRegistry.register(Operation.class);
String contractAddress = "zhangsan-address", event = "zhangsan-event";
- BytesValueList args = new BytesDataList(BytesData.fromText("zhangsan-args"));
+ BytesValueList args = new BytesDataList(TypedValue.fromText("zhangsan-args"));
data = new ContractEventSendOpTemplate(Bytes.fromString(contractAddress), event, args);
}
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DataAccountKVSetOpTemplateTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DataAccountKVSetOpTemplateTest.java
index d8b33048..6c1d4f57 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DataAccountKVSetOpTemplateTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DataAccountKVSetOpTemplateTest.java
@@ -16,7 +16,7 @@ import org.junit.Test;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
-import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate;
@@ -41,11 +41,11 @@ public class DataAccountKVSetOpTemplateTest {
String accountAddress = "zhangsandhakhdkah";
data = new DataAccountKVSetOpTemplate(Bytes.fromString(accountAddress));
KVData kvData1 =
- new KVData("test1", BytesData.fromText("zhangsan"), 9999L);
+ new KVData("test1", TypedValue.fromText("zhangsan"), 9999L);
KVData kvData2 =
- new KVData("test2", BytesData.fromText("lisi"), 9990L);
+ new KVData("test2", TypedValue.fromText("lisi"), 9990L);
KVData kvData3 =
- new KVData("test3", BytesData.fromText("wangwu"), 1990L);
+ new KVData("test3", TypedValue.fromText("wangwu"), 1990L);
data.set(kvData1);
data.set(kvData2);
data.set(kvData3);
@@ -63,7 +63,7 @@ public class DataAccountKVSetOpTemplateTest {
assertEquals(dataKv.length, resolvedKv.length);
for (int i = 0; i < dataKv.length; i++) {
assertEquals(dataKv[i].getKey(), resolvedKv[i].getKey());
- assertArrayEquals(dataKv[i].getValue().getValue().toBytes(), resolvedKv[i].getValue().getValue().toBytes());
+ assertArrayEquals(dataKv[i].getValue().getBytes().toBytes(), resolvedKv[i].getValue().getBytes().toBytes());
assertEquals(dataKv[i].getValue().getType().CODE, resolvedKv[i].getValue().getType().CODE);
assertEquals(dataKv[i].getExpectedVersion(), resolvedKv[i].getExpectedVersion());
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/IntegerToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/IntegerToBytesValueResolverTest.java
index 8e39aa85..dd9d4632 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/IntegerToBytesValueResolverTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/IntegerToBytesValueResolverTest.java
@@ -22,13 +22,13 @@ public class IntegerToBytesValueResolverTest {
BytesValue intBytesValue2 = resolver.encode(intVal, Integer.class);
- assertEquals(intBytesValue.getValue(), intBytesValue1.getValue());
+ assertEquals(intBytesValue.getBytes(), intBytesValue1.getBytes());
- assertEquals(intBytesValue.getValue(), intBytesValue2.getValue());
+ assertEquals(intBytesValue.getBytes(), intBytesValue2.getBytes());
Bytes intBytes = Bytes.fromInt(intVal);
- assertEquals(intBytes, intBytesValue.getValue());
+ assertEquals(intBytes, intBytesValue.getBytes());
assertEquals(intBytesValue.getType(), DataType.INT32);
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/KVDataTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/KVDataTest.java
index d1a6fcb9..3d54f16c 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/KVDataTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/KVDataTest.java
@@ -16,7 +16,7 @@ import org.junit.Test;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
-import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate;
import com.jd.blockchain.transaction.KVData;
@@ -38,7 +38,7 @@ public class KVDataTest {
byte[] value = "test-value".getBytes();
long expectedVersion = 9999L;
- kvData = new KVData(key, BytesData.fromBytes(value), expectedVersion);
+ kvData = new KVData(key, TypedValue.fromBytes(value), expectedVersion);
}
@Test
@@ -48,7 +48,7 @@ public class KVDataTest {
System.out.println("------Assert start ------");
assertEquals(resolvedKvData.getKey(), kvData.getKey());
assertEquals(resolvedKvData.getExpectedVersion(), kvData.getExpectedVersion());
- assertArrayEquals(resolvedKvData.getValue().getValue().toBytes(), kvData.getValue().getValue().toBytes());
+ assertArrayEquals(resolvedKvData.getValue().getBytes().toBytes(), kvData.getValue().getBytes().toBytes());
System.out.println("------Assert OK ------");
}
}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/LongToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/LongToBytesValueResolverTest.java
index 899a6415..b4d20b4c 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/LongToBytesValueResolverTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/LongToBytesValueResolverTest.java
@@ -23,13 +23,13 @@ public class LongToBytesValueResolverTest {
BytesValue longBytesValue2 = resolver.encode(longVal, Long.class);
- assertEquals(longBytesValue.getValue(), longBytesValue1.getValue());
+ assertEquals(longBytesValue.getBytes(), longBytesValue1.getBytes());
- assertEquals(longBytesValue.getValue(), longBytesValue2.getValue());
+ assertEquals(longBytesValue.getBytes(), longBytesValue2.getBytes());
Bytes longBytes = Bytes.fromLong(longVal);
- assertEquals(longBytes, longBytesValue.getValue());
+ assertEquals(longBytes, longBytesValue.getBytes());
assertEquals(longBytesValue.getType(), DataType.INT64);
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ShortToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ShortToBytesValueResolverTest.java
index b35cedd7..2e8e46be 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ShortToBytesValueResolverTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ShortToBytesValueResolverTest.java
@@ -21,7 +21,7 @@ public class ShortToBytesValueResolverTest {
Bytes shortBytes = new Bytes(BytesUtils.toBytes(shortVal));
- assertEquals(shortBytes, shortBytesValue.getValue());
+ assertEquals(shortBytes, shortBytesValue.getBytes());
assertEquals(shortBytesValue.getType(), DataType.INT16);
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/StringToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/StringToBytesValueResolverTest.java
index 17dd0c04..544f06bb 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/StringToBytesValueResolverTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/StringToBytesValueResolverTest.java
@@ -20,7 +20,7 @@ public class StringToBytesValueResolverTest {
BytesValue textBytesValue = resolver.encode(textVal);
- assertEquals(Bytes.fromString(textVal), textBytesValue.getValue());
+ assertEquals(Bytes.fromString(textVal), textBytesValue.getBytes());
assertEquals(textBytesValue.getType(), DataType.TEXT);
@@ -43,7 +43,7 @@ public class StringToBytesValueResolverTest {
Person person = new Person("zhangsan", 80);
String personJson = JSON.toJSONString(person);
BytesValue textBytesValue = resolver.encode(personJson);
- assertEquals(Bytes.fromString(personJson), textBytesValue.getValue());
+ assertEquals(Bytes.fromString(personJson), textBytesValue.getBytes());
assertEquals(textBytesValue.getType(), DataType.JSON);
}
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java
index 0404ee38..c8d8c313 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java
@@ -77,8 +77,8 @@ public class TxContentBlobTest {
for (int j = 0; j < dataKv.length; j++) {
assertEquals(dataKv[i].getKey(), resolvedKv[i].getKey());
assertEquals(dataKv[i].getExpectedVersion(), resolvedKv[i].getExpectedVersion());
- assertArrayEquals(dataKv[i].getValue().getValue().toBytes(),
- resolvedKv[i].getValue().getValue().toBytes());
+ assertArrayEquals(dataKv[i].getValue().getBytes().toBytes(),
+ resolvedKv[i].getValue().getBytes().toBytes());
}
}
}
@@ -108,8 +108,8 @@ public class TxContentBlobTest {
for (int j = 0; j < dataKv.length; j++) {
assertEquals(dataKv[i].getKey(), resolvedKv[i].getKey());
assertEquals(dataKv[i].getExpectedVersion(), resolvedKv[i].getExpectedVersion());
- assertArrayEquals(dataKv[i].getValue().getValue().toBytes(),
- resolvedKv[i].getValue().getValue().toBytes());
+ assertArrayEquals(dataKv[i].getValue().getBytes().toBytes(),
+ resolvedKv[i].getValue().getBytes().toBytes());
}
}
}
diff --git a/source/ledger/ledger-rpc/pom.xml b/source/ledger/ledger-rpc/pom.xml
index 4cfed7d1..25153901 100644
--- a/source/ledger/ledger-rpc/pom.xml
+++ b/source/ledger/ledger-rpc/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
ledger
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
ledger-rpc
diff --git a/source/ledger/pom.xml b/source/ledger/pom.xml
index 89802d22..42f6e4e4 100644
--- a/source/ledger/pom.xml
+++ b/source/ledger/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
jdchain-root
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
ledger
pom
diff --git a/source/manager/manager-booter/pom.xml b/source/manager/manager-booter/pom.xml
index 885e16d9..65668cc6 100644
--- a/source/manager/manager-booter/pom.xml
+++ b/source/manager/manager-booter/pom.xml
@@ -5,7 +5,7 @@
manager
com.jd.blockchain
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
4.0.0
diff --git a/source/manager/manager-model/pom.xml b/source/manager/manager-model/pom.xml
index 314477d3..c0a88a21 100644
--- a/source/manager/manager-model/pom.xml
+++ b/source/manager/manager-model/pom.xml
@@ -5,7 +5,7 @@
manager
com.jd.blockchain
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
4.0.0
@@ -65,6 +65,7 @@
org.rocksdb
rocksdbjni
+ ${rocksdb.version}
diff --git a/source/manager/manager-model/src/main/java/com/jd/blockchain/ump/model/UmpConstant.java b/source/manager/manager-model/src/main/java/com/jd/blockchain/ump/model/UmpConstant.java
index 216a1e85..de388c8b 100644
--- a/source/manager/manager-model/src/main/java/com/jd/blockchain/ump/model/UmpConstant.java
+++ b/source/manager/manager-model/src/main/java/com/jd/blockchain/ump/model/UmpConstant.java
@@ -16,7 +16,7 @@ public class UmpConstant {
public static final String PRIVATE_KEY_SUFFIX = ".priv";
- public static final String PUBLIC_KEY_SUFFIX = ".priv";
+ public static final String PUBLIC_KEY_SUFFIX = ".pub";
public static final String PWD_SUFFIX = ".pwd";
diff --git a/source/manager/manager-service/pom.xml b/source/manager/manager-service/pom.xml
index fef1aed0..8ee81999 100644
--- a/source/manager/manager-service/pom.xml
+++ b/source/manager/manager-service/pom.xml
@@ -5,7 +5,7 @@
manager
com.jd.blockchain
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
4.0.0
diff --git a/source/manager/manager-web/pom.xml b/source/manager/manager-web/pom.xml
index 0daaf057..b9172eed 100644
--- a/source/manager/manager-web/pom.xml
+++ b/source/manager/manager-web/pom.xml
@@ -5,7 +5,7 @@
manager
com.jd.blockchain
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
4.0.0
diff --git a/source/manager/pom.xml b/source/manager/pom.xml
index 2972bff7..7416e033 100644
--- a/source/manager/pom.xml
+++ b/source/manager/pom.xml
@@ -11,7 +11,7 @@
com.jd.blockchain
jdchain-root
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
manager
pom
diff --git a/source/peer/pom.xml b/source/peer/pom.xml
index 9029deaa..20cc29f1 100644
--- a/source/peer/pom.xml
+++ b/source/peer/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
jdchain-root
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
peer
diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java b/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java
index 741594ce..41ce1458 100644
--- a/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java
+++ b/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java
@@ -3,7 +3,6 @@ package com.jd.blockchain.peer.web;
import java.util.ArrayList;
import java.util.List;
-import com.jd.blockchain.ledger.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
@@ -14,6 +13,22 @@ import org.springframework.web.bind.annotation.RestController;
import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.BytesValue;
+import com.jd.blockchain.ledger.ContractInfo;
+import com.jd.blockchain.ledger.KVDataVO;
+import com.jd.blockchain.ledger.KVInfoVO;
+import com.jd.blockchain.ledger.LedgerAdminInfo;
+import com.jd.blockchain.ledger.LedgerBlock;
+import com.jd.blockchain.ledger.LedgerInfo;
+import com.jd.blockchain.ledger.LedgerMetadata;
+import com.jd.blockchain.ledger.LedgerTransaction;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.TransactionState;
+import com.jd.blockchain.ledger.TypedKVData;
+import com.jd.blockchain.ledger.TypedKVEntry;
+import com.jd.blockchain.ledger.TypedValue;
+import com.jd.blockchain.ledger.UserInfo;
import com.jd.blockchain.ledger.core.ContractAccountQuery;
import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.DataAccountQuery;
@@ -23,7 +38,10 @@ import com.jd.blockchain.ledger.core.ParticipantCertData;
import com.jd.blockchain.ledger.core.TransactionQuery;
import com.jd.blockchain.ledger.core.UserAccountQuery;
import com.jd.blockchain.transaction.BlockchainQueryService;
+import com.jd.blockchain.utils.ArrayUtils;
import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.DataEntry;
+import com.jd.blockchain.utils.DataIterator;
import com.jd.blockchain.utils.QueryUtil;
@RestController
@@ -72,7 +90,7 @@ public class LedgerQueryController implements BlockchainQueryService {
}
return null;
}
-
+
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/admininfo")
@Override
public LedgerAdminInfo getLedgerAdminInfo(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
@@ -326,18 +344,18 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}")
@Override
- public AccountHeader getDataAccount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ public BlockchainIdentity getDataAccount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address) {
LedgerQuery ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
- return dataAccountSet.getAccount(Bytes.fromBase58(address));
+ return dataAccountSet.getAccount(Bytes.fromBase58(address)).getID();
}
@RequestMapping(method = { RequestMethod.GET,
RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries")
@Override
- public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ public TypedKVEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address, @RequestParam("keys") String... keys) {
if (keys == null || keys.length == 0) {
return null;
@@ -347,15 +365,15 @@ public class LedgerQueryController implements BlockchainQueryService {
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address));
- KVDataEntry[] entries = new KVDataEntry[keys.length];
+ TypedKVEntry[] entries = new TypedKVEntry[keys.length];
long ver;
for (int i = 0; i < entries.length; i++) {
- ver = dataAccount.getDataVersion(Bytes.fromString(keys[i]));
+ ver = dataAccount.getDataset().getVersion(keys[i]);
if (ver < 0) {
- entries[i] = new KVDataObject(keys[i], -1, null);
+ entries[i] = new TypedKVData(keys[i], -1, null);
} else {
- BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver);
- entries[i] = new KVDataObject(keys[i], ver, value);
+ BytesValue value = dataAccount.getDataset().getValue(keys[i], ver);
+ entries[i] = new TypedKVData(keys[i], ver, value);
}
}
@@ -365,7 +383,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = { RequestMethod.GET,
RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version")
@Override
- public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ public TypedKVEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address, @RequestBody KVInfoVO kvInfoVO) {
// parse kvInfoVO;
List keyList = new ArrayList<>();
@@ -396,21 +414,21 @@ public class LedgerQueryController implements BlockchainQueryService {
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address));
- KVDataEntry[] entries = new KVDataEntry[keys.length];
+ TypedKVEntry[] entries = new TypedKVEntry[keys.length];
long ver = -1;
for (int i = 0; i < entries.length; i++) {
// ver = dataAccount.getDataVersion(Bytes.fromString(keys[i]));
ver = versions[i];
if (ver < 0) {
- entries[i] = new KVDataObject(keys[i], -1, null);
+ entries[i] = new TypedKVData(keys[i], -1, null);
} else {
- if (dataAccount.getDataEntriesTotalCount() == 0
- || dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null) {
+ if (dataAccount.getDataset().getDataCount() == 0
+ || dataAccount.getDataset().getValue(keys[i], ver) == null) {
// is the address is not exist; the result is null;
- entries[i] = new KVDataObject(keys[i], -1, null);
+ entries[i] = new TypedKVData(keys[i], -1, null);
} else {
- BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver);
- entries[i] = new KVDataObject(keys[i], ver, value);
+ BytesValue value = dataAccount.getDataset().getValue(keys[i], ver);
+ entries[i] = new TypedKVData(keys[i], ver, value);
}
}
}
@@ -421,7 +439,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = { RequestMethod.GET,
RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries")
@Override
- public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ public TypedKVEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
@@ -431,27 +449,33 @@ public class LedgerQueryController implements BlockchainQueryService {
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address));
- int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataEntriesTotalCount());
- return dataAccount.getDataEntries(pages[0], pages[1]);
+// int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataset().getDataCount());
+// return dataAccount.getDataEntries(pages[0], pages[1]);
+
+ DataIterator iterator = dataAccount.getDataset().iterator();
+ iterator.skip(fromIndex);
+ DataEntry[] dataEntries = iterator.next(count);
+ TypedKVEntry[] typedKVEntries = ArrayUtils.castTo(dataEntries, TypedKVEntry.class,
+ e -> e == null ? null : new TypedKVData(e.getKey(), e.getVersion(), e.getValue()));
+ return typedKVEntries;
}
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries/count")
@Override
public long getDataEntriesTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address) {
-
LedgerQuery ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address));
- return dataAccount.getDataEntriesTotalCount();
+ return dataAccount.getDataset().getDataCount();
}
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}")
@Override
public ContractInfo getContract(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "address") String address) {
+ @PathVariable(name = "address") String address) {
LedgerQuery ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block);
@@ -468,7 +492,7 @@ public class LedgerQueryController implements BlockchainQueryService {
*/
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users")
@Override
- public AccountHeader[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ public BlockchainIdentity[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
LedgerQuery ledger = ledgerService.getLedger(ledgerHash);
@@ -488,7 +512,7 @@ public class LedgerQueryController implements BlockchainQueryService {
*/
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts")
@Override
- public AccountHeader[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ public BlockchainIdentity[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
LedgerQuery ledger = ledgerService.getLedger(ledgerHash);
@@ -500,7 +524,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts")
@Override
- public AccountHeader[] getContractAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ public BlockchainIdentity[] getContractAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
LedgerQuery ledger = ledgerService.getLedger(ledgerHash);
diff --git a/source/pom.xml b/source/pom.xml
index 777775fc..5b9d0c10 100644
--- a/source/pom.xml
+++ b/source/pom.xml
@@ -11,7 +11,7 @@
com.jd.blockchain
jdchain-root
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
pom
jdchain
@@ -36,8 +36,8 @@
0.3.0.RELEASE
- 1.1.0.RELEASE
- 1.1.0.RELEASE
+ 1.2.0-SNAPSHOT
+ 1.2.0-SNAPSHOT
2.4
3.3.0
1.2.2
@@ -67,7 +67,7 @@
3.3.6
3.0.1
2.9.0
- 5.15.10
+ 6.3.6
3.4.6
3.5.12
3.5.3
diff --git a/source/runtime/pom.xml b/source/runtime/pom.xml
index ec80c4b7..03c60442 100644
--- a/source/runtime/pom.xml
+++ b/source/runtime/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
jdchain-root
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
runtime
pom
diff --git a/source/runtime/runtime-context/pom.xml b/source/runtime/runtime-context/pom.xml
index ade4b9c4..ee955aa2 100644
--- a/source/runtime/runtime-context/pom.xml
+++ b/source/runtime/runtime-context/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
runtime
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
runtime-context
diff --git a/source/runtime/runtime-modular-booter/pom.xml b/source/runtime/runtime-modular-booter/pom.xml
index e39129c4..bb812b18 100644
--- a/source/runtime/runtime-modular-booter/pom.xml
+++ b/source/runtime/runtime-modular-booter/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
runtime
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
runtime-modular-booter
\ No newline at end of file
diff --git a/source/runtime/runtime-modular/pom.xml b/source/runtime/runtime-modular/pom.xml
index 0bbb87d4..afccee46 100644
--- a/source/runtime/runtime-modular/pom.xml
+++ b/source/runtime/runtime-modular/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
runtime
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
runtime-modular
diff --git a/source/sdk/pom.xml b/source/sdk/pom.xml
index 56757bbe..177972f5 100644
--- a/source/sdk/pom.xml
+++ b/source/sdk/pom.xml
@@ -4,7 +4,7 @@
com.jd.blockchain
jdchain-root
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
sdk
pom
diff --git a/source/sdk/sdk-base/pom.xml b/source/sdk/sdk-base/pom.xml
index 7c49f607..35f3d418 100644
--- a/source/sdk/sdk-base/pom.xml
+++ b/source/sdk/sdk-base/pom.xml
@@ -4,7 +4,7 @@
com.jd.blockchain
sdk
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
sdk-base
diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java
index e4aea5a0..46bb8d12 100644
--- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java
+++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java
@@ -39,14 +39,14 @@ import com.jd.blockchain.utils.io.BytesUtils;
public class ClientResolveUtil {
- public static KVDataEntry[] read(KVDataEntry[] kvDataEntries) {
+ public static TypedKVEntry[] read(TypedKVEntry[] kvDataEntries) {
if (kvDataEntries == null || kvDataEntries.length == 0) {
return kvDataEntries;
}
- KVDataEntry[] resolveKvDataEntries = new KVDataEntry[kvDataEntries.length];
+ TypedKVEntry[] resolveKvDataEntries = new TypedKVEntry[kvDataEntries.length];
// kvDataEntries是代理对象,需要处理
for (int i = 0; i < kvDataEntries.length; i++) {
- KVDataEntry kvDataEntry = kvDataEntries[i];
+ TypedKVEntry kvDataEntry = kvDataEntries[i];
String key = kvDataEntry.getKey();
long version = kvDataEntry.getVersion();
DataType dataType = kvDataEntry.getType();
@@ -108,7 +108,7 @@ public class ClientResolveUtil {
public static Object readValueByBytesValue(BytesValue bytesValue) {
DataType dataType = bytesValue.getType();
- Bytes saveVal = bytesValue.getValue();
+ Bytes saveVal = bytesValue.getBytes();
Object showVal;
switch (dataType) {
case BYTES:
@@ -147,11 +147,11 @@ public class ClientResolveUtil {
long expectedVersion = currWriteSetObj.getLong("expectedVersion");
JSONObject valueObj = currWriteSetObj.getJSONObject("value");
String typeStr = valueObj.getString("type");
- // Base58Utils.decode(valueObj.getJSONObject("value").getString("value"))
- String realValBase58 = valueObj.getJSONObject("value").getString("value");
+ // Base58Utils.decode(valueObj.getJSONObject("bytes").getString("value"))
+ String realValBase58 = valueObj.getJSONObject("bytes").getString("value");
String key = currWriteSetObj.getString("key");
DataType dataType = DataType.valueOf(typeStr);
- BytesValue bytesValue = BytesData.fromType(dataType, Base58Utils.decode(realValBase58));
+ BytesValue bytesValue = TypedValue.fromType(dataType, Base58Utils.decode(realValBase58));
KVData kvData = new KVData(key, bytesValue, expectedVersion);
kvOperation.set(kvData);
}
@@ -200,7 +200,7 @@ public class ClientResolveUtil {
JSONObject pubKeyObj = currConsensusParticipant.getJSONObject("pubKey");
String pubKeyBase58 = pubKeyObj.getString("value");
// 生成ParticipantNode对象
- ParticipantCertData participantCertData = new ParticipantCertData(id, address, name, new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes()));
+ ParticipantCertData participantCertData = new ParticipantCertData(id, address, name, new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes()), null);
participantNodes[i] = participantCertData;
}
ledgerInitSettingData.setConsensusParticipants(participantNodes);
@@ -294,11 +294,12 @@ public class ClientResolveUtil {
this.pubKey = participantNode.getPubKey();
}
- public ParticipantCertData(int id, Bytes address, String name, PubKey pubKey) {
+ public ParticipantCertData(int id, Bytes address, String name, PubKey pubKey, ParticipantNodeState participantNodeState) {
this.id = id;
this.address = address;
this.name = name;
this.pubKey = pubKey;
+
this.participantNodeState = participantNodeState;
}
@@ -329,7 +330,7 @@ public class ClientResolveUtil {
}
- public static class KvData implements KVDataEntry {
+ public static class KvData implements TypedKVEntry {
private String key;
diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java
index ff1c9176..9984cef5 100644
--- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java
+++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java
@@ -1,9 +1,9 @@
package com.jd.blockchain.sdk.proxy;
import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.ContractInfo;
-import com.jd.blockchain.ledger.KVDataEntry;
+import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.KVInfoVO;
import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerBlock;
@@ -156,25 +156,25 @@ public abstract class BlockchainServiceProxy implements BlockchainService {
}
@Override
- public AccountHeader getDataAccount(HashDigest ledgerHash, String address) {
+ public BlockchainIdentity getDataAccount(HashDigest ledgerHash, String address) {
return getQueryService(ledgerHash).getDataAccount(ledgerHash, address);
}
@Override
- public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) {
- KVDataEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, keys);
+ public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) {
+ TypedKVEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, keys);
return ClientResolveUtil.read(kvDataEntries);
}
@Override
- public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
- KVDataEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, kvInfoVO);
+ public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
+ TypedKVEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, kvInfoVO);
return ClientResolveUtil.read(kvDataEntries);
}
@Override
- public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {
- KVDataEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, fromIndex, count);
+ public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {
+ TypedKVEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, fromIndex, count);
return ClientResolveUtil.read(kvDataEntries);
}
@@ -189,17 +189,17 @@ public abstract class BlockchainServiceProxy implements BlockchainService {
}
@Override
- public AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count) {
+ public BlockchainIdentity[] getUsers(HashDigest ledgerHash, int fromIndex, int count) {
return getQueryService(ledgerHash).getUsers(ledgerHash, fromIndex, count);
}
@Override
- public AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) {
+ public BlockchainIdentity[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) {
return getQueryService(ledgerHash).getDataAccounts(ledgerHash, fromIndex, count);
}
@Override
- public AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) {
+ public BlockchainIdentity[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) {
return getQueryService(ledgerHash).getContractAccounts(ledgerHash, fromIndex, count);
}
}
diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java
index ccd5ceec..d13fa436 100644
--- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java
+++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java
@@ -487,7 +487,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService
*/
@HttpAction(method=HttpMethod.GET, path="ledgers/{ledgerHash}/accounts/address/{address}")
@Override
- AccountHeader getDataAccount(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
+ BlockchainIdentity getDataAccount(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
@PathParam(name="address") String address);
/**
@@ -504,13 +504,13 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService
*/
@HttpAction(method=HttpMethod.POST, path="ledgers/{ledgerHash}/accounts/{address}/entries")
@Override
- KVDataEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
+ TypedKVEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
@PathParam(name="address") String address,
@RequestParam(name="keys", array = true) String... keys);
@HttpAction(method=HttpMethod.POST, path="ledgers/{ledgerHash}/accounts/{address}/entries-version")
@Override
- KVDataEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
+ TypedKVEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
@PathParam(name="address") String address,
@RequestBody KVInfoVO kvInfoVO);
@@ -531,7 +531,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService
*/
@HttpAction(method = HttpMethod.POST, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries")
@Override
- KVDataEntry[] getDataEntries(@PathParam(name = "ledgerHash") HashDigest ledgerHash,
+ TypedKVEntry[] getDataEntries(@PathParam(name = "ledgerHash") HashDigest ledgerHash,
@PathParam(name = "address") String address,
@RequestParam(name = "fromIndex", required = false) int fromIndex,
@RequestParam(name = "count", required = false) int count);
@@ -569,7 +569,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService
*/
@HttpAction(method = HttpMethod.GET, path = "ledgers/{ledgerHash}/users")
@Override
- AccountHeader[] getUsers(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
+ BlockchainIdentity[] getUsers(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
@RequestParam(name="fromIndex", required = false) int fromIndex,
@RequestParam(name="count", required = false) int count);
@@ -582,7 +582,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService
*/
@HttpAction(method = HttpMethod.GET, path = "ledgers/{ledgerHash}/accounts")
@Override
- AccountHeader[] getDataAccounts(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
+ BlockchainIdentity[] getDataAccounts(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
@RequestParam(name="fromIndex", required = false) int fromIndex,
@RequestParam(name="count", required = false) int count);
@@ -595,7 +595,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService
*/
@HttpAction(method = HttpMethod.GET, path = "ledgers/{ledgerHash}/contracts")
@Override
- AccountHeader[] getContractAccounts(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
+ BlockchainIdentity[] getContractAccounts(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
@RequestParam(name="fromIndex", required = false) int fromIndex,
@RequestParam(name="count", required = false) int count);
diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/service/NodeSigningAppender.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/service/NodeSigningAppender.java
index 52f576e4..0014c28a 100644
--- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/service/NodeSigningAppender.java
+++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/service/NodeSigningAppender.java
@@ -8,13 +8,10 @@ import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.HashFunction;
-import com.jd.blockchain.crypto.SignatureDigest;
-import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.NodeRequest;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionResponse;
-import com.jd.blockchain.transaction.DigitalSignatureBlob;
import com.jd.blockchain.transaction.SignatureUtils;
import com.jd.blockchain.transaction.TransactionService;
import com.jd.blockchain.transaction.TxRequestMessage;
diff --git a/source/sdk/sdk-client/pom.xml b/source/sdk/sdk-client/pom.xml
index c8f7b0cd..6cca87b7 100644
--- a/source/sdk/sdk-client/pom.xml
+++ b/source/sdk/sdk-client/pom.xml
@@ -4,7 +4,7 @@
com.jd.blockchain
sdk
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
sdk-client
diff --git a/source/sdk/sdk-samples/pom.xml b/source/sdk/sdk-samples/pom.xml
index ba4e9909..11b66a9f 100644
--- a/source/sdk/sdk-samples/pom.xml
+++ b/source/sdk/sdk-samples/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
sdk
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
sdk-samples
diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java
index d662378d..1782d985 100644
--- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java
+++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java
@@ -9,8 +9,8 @@ import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.contract.EventProcessingAware;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockchainIdentity;
-import com.jd.blockchain.ledger.KVDataEntry;
-import com.jd.blockchain.ledger.KVDataObject;
+import com.jd.blockchain.ledger.TypedKVEntry;
+import com.jd.blockchain.ledger.TypedKVData;
import com.jd.blockchain.utils.Bytes;
/**
@@ -47,16 +47,16 @@ public class AssetContractImpl implements EventProcessingAware, AssetContract {
}
// 查询当前值;
- KVDataEntry[] kvEntries = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS, KEY_TOTAL,
+ TypedKVEntry[] kvEntries = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS, KEY_TOTAL,
assetHolderAddress);
// 计算资产的发行总数;
- KVDataObject currTotal = (KVDataObject) kvEntries[0];
+ TypedKVData currTotal = (TypedKVData) kvEntries[0];
long newTotal = currTotal.longValue() + amount;
eventContext.getLedger().dataAccount(ASSET_ADDRESS).setInt64(KEY_TOTAL, newTotal, currTotal.getVersion());
// 分配到持有者账户;
- KVDataObject holderAmount = (KVDataObject) kvEntries[1];
+ TypedKVData holderAmount = (TypedKVData) kvEntries[1];
long newHodlerAmount = holderAmount.longValue() + amount;
eventContext.getLedger().dataAccount(ASSET_ADDRESS)
.setInt64(assetHolderAddress, newHodlerAmount, holderAmount.getVersion()).setText("K2", "info2", -1)
@@ -77,10 +77,10 @@ public class AssetContractImpl implements EventProcessingAware, AssetContract {
checkSignerPermission(fromAddress);
// 查询现有的余额;
- KVDataEntry[] origBalances = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS,
+ TypedKVEntry[] origBalances = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS,
fromAddress, toAddress);
- KVDataEntry fromBalanceKV = origBalances[0];
- KVDataEntry toBalanceKV = origBalances[1];
+ TypedKVEntry fromBalanceKV = origBalances[0];
+ TypedKVEntry toBalanceKV = origBalances[1];
long fromBalance = fromBalanceKV.getVersion() == -1 ? 0 : (long) fromBalanceKV.getValue();
long toBalance = toBalanceKV.getVersion() == -1 ? 0 : (long) toBalanceKV.getValue();
diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Query.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Query.java
index 3205fd73..a3e44d95 100644
--- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Query.java
+++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Query.java
@@ -4,7 +4,7 @@ import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
-import com.jd.blockchain.ledger.KVDataEntry;
+import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.Transaction;
@@ -67,7 +67,7 @@ public class SDKDemo_Query {
// 获取数据;
String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf==";
String[] objKeys = new String[] { "x001", "x002" };
- KVDataEntry[] kvData = service.getDataEntries(LEDGER_HASH, commerceAccount, objKeys);
+ TypedKVEntry[] kvData = service.getDataEntries(LEDGER_HASH, commerceAccount, objKeys);
long payloadVersion = kvData[0].getVersion();
diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java
index 9d43b199..caae0d6d 100644
--- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java
+++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java
@@ -6,7 +6,7 @@ import static com.jd.blockchain.transaction.ContractReturnValue.decode;
import com.jd.blockchain.contract.TransferContract;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
-import com.jd.blockchain.ledger.KVDataEntry;
+import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.PreparedTransaction;
import com.jd.blockchain.ledger.TransactionResponse;
import com.jd.blockchain.ledger.TransactionTemplate;
@@ -106,11 +106,11 @@ public class SDK_Contract_Demo extends SDK_Base_Demo {
}
private long readByKvOperation(String address, String account) {
- KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account);
+ TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account);
if (kvDataEntries == null || kvDataEntries.length == 0) {
throw new IllegalStateException(String.format("Ledger %s Service inner Error !!!", ledgerHash.toBase58()));
}
- KVDataEntry kvDataEntry = kvDataEntries[0];
+ TypedKVEntry kvDataEntry = kvDataEntries[0];
if (kvDataEntry.getVersion() == -1) {
return 0L;
}
diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Random_Demo.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Random_Demo.java
index c73a7f91..868f3269 100644
--- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Random_Demo.java
+++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Random_Demo.java
@@ -79,11 +79,11 @@ public class SDK_Contract_Random_Demo extends SDK_Base_Demo {
}
private long readByKvOperation(String address, String account) {
- KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account);
+ TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account);
if (kvDataEntries == null || kvDataEntries.length == 0) {
throw new IllegalStateException(String.format("Ledger %s Service inner Error !!!", ledgerHash.toBase58()));
}
- KVDataEntry kvDataEntry = kvDataEntries[0];
+ TypedKVEntry kvDataEntry = kvDataEntries[0];
if (kvDataEntry.getVersion() == -1) {
return 0L;
}
diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_InsertData_Demo.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_InsertData_Demo.java
index 3a89c7a6..d90b5233 100644
--- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_InsertData_Demo.java
+++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_InsertData_Demo.java
@@ -107,9 +107,9 @@ public class SDK_InsertData_Demo extends SDK_Base_Demo {
// KVDataEntry[] kvData = blockchainService.getDataEntries(ledgerHash, commerceAccount, objKeys);
// 获取数据账户下所有的KV列表
- KVDataEntry[] kvData = blockchainService.getDataEntries(ledgerHash, commerceAccount, 0, 100);
+ TypedKVEntry[] kvData = blockchainService.getDataEntries(ledgerHash, commerceAccount, 0, 100);
if (kvData != null && kvData.length > 0) {
- for (KVDataEntry kvDatum : kvData) {
+ for (TypedKVEntry kvDatum : kvData) {
System.out.println("kvData.key=" + kvDatum.getKey());
System.out.println("kvData.version=" + kvDatum.getVersion());
System.out.println("kvData.type=" + kvDatum.getType());
diff --git a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java
index 3851d6a7..3d291811 100644
--- a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java
+++ b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java
@@ -19,12 +19,12 @@ import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.crypto.SignatureFunction;
-import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.EndpointRequest;
-import com.jd.blockchain.ledger.KVDataEntry;
+import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInfo;
import com.jd.blockchain.ledger.LedgerTransaction;
@@ -98,7 +98,7 @@ public class SDK_GateWay_Query_Test_ {
System.out.println("contractCount=" + count);
count = service.getContractCount(ledgerHash, hashDigest);
System.out.println("contractCount=" + count);
- AccountHeader contract = service.getContract(ledgerHash, "12345678");
+ BlockchainIdentity contract = service.getContract(ledgerHash, "12345678");
System.out.println(contract);
LedgerBlock block = service.getBlock(ledgerHash, hashDigest);
@@ -109,7 +109,7 @@ public class SDK_GateWay_Query_Test_ {
count = service.getDataAccountCount(ledgerHash, hashDigest);
System.out.println("dataAccountCount=" + count);
- AccountHeader dataAccount = service.getDataAccount(ledgerHash, "1245633");
+ BlockchainIdentity dataAccount = service.getDataAccount(ledgerHash, "1245633");
System.out.println(dataAccount.getAddress());
count = service.getTransactionCount(ledgerHash, hashDigest);
@@ -149,8 +149,8 @@ public class SDK_GateWay_Query_Test_ {
String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf==";
String[] objKeys = new String[] { "x001", "x002" };
- KVDataEntry[] kvData = service.getDataEntries(ledgerHash, commerceAccount, objKeys);
- for (KVDataEntry kvDatum : kvData) {
+ TypedKVEntry[] kvData = service.getDataEntries(ledgerHash, commerceAccount, objKeys);
+ for (TypedKVEntry kvDatum : kvData) {
System.out.println("kvData.key=" + kvDatum.getKey());
System.out.println("kvData.version=" + kvDatum.getVersion());
System.out.println("kvData.value=" + kvDatum.getValue());
diff --git a/source/storage/pom.xml b/source/storage/pom.xml
index 7bd095b7..ce1595a4 100644
--- a/source/storage/pom.xml
+++ b/source/storage/pom.xml
@@ -3,7 +3,7 @@
com.jd.blockchain
jdchain-root
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
storage
pom
diff --git a/source/storage/storage-composite/pom.xml b/source/storage/storage-composite/pom.xml
index 499c1c0b..9957f4d3 100644
--- a/source/storage/storage-composite/pom.xml
+++ b/source/storage/storage-composite/pom.xml
@@ -4,7 +4,7 @@
com.jd.blockchain
storage
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
storage-composite
@@ -56,7 +56,7 @@
\ No newline at end of file
diff --git a/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBConnectionFactory.java b/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBConnectionFactory.java
index 46165c47..eb5b09f2 100644
--- a/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBConnectionFactory.java
+++ b/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBConnectionFactory.java
@@ -26,7 +26,7 @@ public class RocksDBConnectionFactory implements DbConnectionFactory {
public static final String URI_SCHEME = "rocksdb";
public static final Pattern URI_PATTER = Pattern
- .compile("^\\w+\\://(/)?\\w+(/.*)*$");
+ .compile("^\\w+\\://(/)?\\w+(\\:)?([/\\\\].*)*$");
private Map connections = new ConcurrentHashMap<>();
@@ -40,7 +40,7 @@ public class RocksDBConnectionFactory implements DbConnectionFactory {
if (!URI_PATTER.matcher(dbConnectionString).matches()) {
throw new IllegalArgumentException("Illegal format of rocksdb connection string!");
}
- URI dbUri = URI.create(dbConnectionString);
+ URI dbUri = URI.create(dbConnectionString.replace("\\", "/"));
if (!support(dbUri.getScheme())) {
throw new IllegalArgumentException(
String.format("Not supported db connection string with scheme \"%s\"!", dbUri.getScheme()));
@@ -49,9 +49,6 @@ public class RocksDBConnectionFactory implements DbConnectionFactory {
String uriHead = dbPrefix();
int beginIndex = dbConnectionString.indexOf(uriHead);
String dbPath = dbConnectionString.substring(beginIndex + uriHead.length());
- if (!dbPath.startsWith(File.separator)) {
- dbPath = File.separator + dbPath;
- }
RocksDBConnection conn = connections.get(dbPath);
if (conn != null) {
diff --git a/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBVersioningStorage.java b/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBVersioningStorage.java
index 978fd8c5..98c47325 100644
--- a/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBVersioningStorage.java
+++ b/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBVersioningStorage.java
@@ -7,9 +7,9 @@ import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.collections4.map.LRUMap;
import org.rocksdb.*;
-import com.jd.blockchain.storage.service.VersioningKVEntry;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.DataEntry;
import com.jd.blockchain.utils.io.BytesUtils;
/**
@@ -127,7 +127,7 @@ public class RocksDBVersioningStorage implements VersioningKVStorage {
}
@Override
- public VersioningKVEntry getEntry(Bytes key, long version) {
+ public DataEntry getEntry(Bytes key, long version) {
byte[] value = get(key, version);
if (value == null) {
return null;
@@ -226,7 +226,7 @@ public class RocksDBVersioningStorage implements VersioningKVStorage {
}
}
- private static class VersioningKVData implements VersioningKVEntry {
+ private static class VersioningKVData implements DataEntry {
private Bytes key;
diff --git a/source/storage/storage-rocksdb/src/test/java/test/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBStorageTest.java b/source/storage/storage-rocksdb/src/test/java/test/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBStorageTest.java
index c930d961..d33b809f 100644
--- a/source/storage/storage-rocksdb/src/test/java/test/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBStorageTest.java
+++ b/source/storage/storage-rocksdb/src/test/java/test/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBStorageTest.java
@@ -1,5 +1,6 @@
package test.com.jd.blockchain.storage.service.impl.rocksdb;
+import static com.jd.blockchain.storage.service.impl.rocksdb.RocksDBConnectionFactory.URI_PATTER;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -7,6 +8,8 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
import org.junit.Test;
@@ -133,4 +136,18 @@ public class RocksDBStorageTest {
return dbURI;
}
+ @Test
+ // test rocksDB uri patter
+ public void testRocksDBUriPatter() {
+ Map cases = new HashMap<>();
+ cases.put("rocksdb:///home/peer0/rocksdb", true);
+ cases.put("rocksdb://D:\\home\\rocksdb", true);
+ cases.put("rocksdb://\\home\\rocksdb", false);
+ cases.put("rocksdb://:\\home\\rocksdb", false);
+ cases.put("rocksdb://D:\\home\\", true);
+ cases.put("rocksdb:///home/peer0/", true);
+ for(Map.Entry entity : cases.entrySet()) {
+ assertEquals(URI_PATTER.matcher(entity.getKey()).matches(), entity.getValue());
+ }
+ }
}
diff --git a/source/storage/storage-service/pom.xml b/source/storage/storage-service/pom.xml
index f21649fb..c6672b83 100644
--- a/source/storage/storage-service/pom.xml
+++ b/source/storage/storage-service/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
storage
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
storage-service
diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVEntry.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVEntry.java
deleted file mode 100644
index a18f6740..00000000
--- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVEntry.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.jd.blockchain.storage.service;
-
-import com.jd.blockchain.utils.Bytes;
-
-/**
- * 版本化的键值数据项;
- *
- * @author huanghaiquan
- *
- */
-public interface VersioningKVEntry {
-
-// String getKey();
- Bytes getKey();
-
- long getVersion();
-
- byte[] getValue();
-
-}
\ No newline at end of file
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 711606d3..980cc32c 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
@@ -1,6 +1,7 @@
package com.jd.blockchain.storage.service;
import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.DataEntry;
/**
* Versioning Key-Value Storage
@@ -40,7 +41,7 @@ public interface VersioningKVStorage extends BatchStorageService {
* @param version
* @return
*/
- VersioningKVEntry getEntry(Bytes key, long version);
+ DataEntry getEntry(Bytes key, long version);
/**
* Return the specified verson's value;
diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/BufferedKVStorage.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/BufferedKVStorage.java
index 7b292248..b038a87e 100644
--- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/BufferedKVStorage.java
+++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/BufferedKVStorage.java
@@ -7,10 +7,10 @@ import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
-import com.jd.blockchain.storage.service.VersioningKVEntry;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;
+import com.jd.blockchain.utils.DataEntry;
/**
* {@link BufferedKVStorage} 缓冲写入的KV存储;
@@ -77,9 +77,9 @@ public class BufferedKVStorage implements VersioningKVStorage, ExPolicyKVStorage
}
return ws.getLatestVersion();
}
-
+
@Override
- public VersioningKVEntry getEntry(Bytes key, long version) {
+ public DataEntry getEntry(Bytes key, long version) {
VersioningWritingSet ws = versioningCache.get(key);
if (ws == null) {
return origVersioningStorage.getEntry(key, version);
@@ -484,7 +484,7 @@ public class BufferedKVStorage implements VersioningKVStorage, ExPolicyKVStorage
return startingVersion;
}
- public VersioningKVEntry getEntry(long version) {
+ public DataEntry getEntry(long version) {
byte[] value = get(version);
if (value == null) {
return null;
@@ -505,7 +505,7 @@ public class BufferedKVStorage implements VersioningKVStorage, ExPolicyKVStorage
}
}
- private static class VersioningKVData implements VersioningKVEntry {
+ private static class VersioningKVData implements DataEntry {
private Bytes key;
diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java
index 0c2192a3..a0f36c0d 100644
--- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java
+++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java
@@ -5,9 +5,9 @@ import java.util.Set;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.KVStorageService;
-import com.jd.blockchain.storage.service.VersioningKVEntry;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.DataEntry;
import com.jd.blockchain.utils.io.BytesMap;
public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage, KVStorageService, BytesMap {
@@ -21,7 +21,7 @@ public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage,
}
@Override
- public VersioningKVEntry getEntry(Bytes key, long version) {
+ public DataEntry getEntry(Bytes key, long version) {
return verStorage.getEntry(key, version);
}
diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java
index 684c75fe..73816055 100644
--- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java
+++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java
@@ -1,24 +1,23 @@
package com.jd.blockchain.storage.service.utils;
-import com.jd.blockchain.storage.service.VersioningKVEntry;
-import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.DataEntry;
-public class VersioningKVData implements VersioningKVEntry {
+public class VersioningKVData implements DataEntry {
- private Bytes key;
+ private K key;
private long version;
- private byte[] value;
+ private V value;
- public VersioningKVData(Bytes key, long version, byte[] value) {
+ public VersioningKVData(K key, long version, V value) {
this.key = key;
this.version = version;
this.value = value;
}
@Override
- public Bytes getKey() {
+ public K getKey() {
return key;
}
@@ -28,7 +27,7 @@ public class VersioningKVData implements VersioningKVEntry {
}
@Override
- public byte[] getValue() {
+ public V getValue() {
return value;
}
diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVStorageMap.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVStorageMap.java
index 3c4855e3..1c6b8def 100644
--- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVStorageMap.java
+++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVStorageMap.java
@@ -5,9 +5,9 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-import com.jd.blockchain.storage.service.VersioningKVEntry;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.DataEntry;
import com.jd.blockchain.utils.io.BytesMap;
public class VersioningKVStorageMap implements VersioningKVStorage, BytesMap {
@@ -42,7 +42,7 @@ public class VersioningKVStorageMap implements VersioningKVStorage, BytesMap
com.jd.blockchain
jdchain-root
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
test
pom
diff --git a/source/test/test-consensus-client/pom.xml b/source/test/test-consensus-client/pom.xml
index 73394904..9a202d4d 100644
--- a/source/test/test-consensus-client/pom.xml
+++ b/source/test/test-consensus-client/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
test
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
test-consensus-client
diff --git a/source/test/test-consensus-node/pom.xml b/source/test/test-consensus-node/pom.xml
index ecc6532f..49362e12 100644
--- a/source/test/test-consensus-node/pom.xml
+++ b/source/test/test-consensus-node/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
test
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
test-consensus-node
@@ -38,7 +38,7 @@
com.jd.blockchain
consensus-bftsmart
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
org.springframework.boot
diff --git a/source/test/test-integration/pom.xml b/source/test/test-integration/pom.xml
index fcd52e7e..37e3a382 100644
--- a/source/test/test-integration/pom.xml
+++ b/source/test/test-integration/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
test
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
test-integration
diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java
index 70ca67b7..0ffcbb3e 100644
--- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java
+++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java
@@ -21,12 +21,12 @@ import com.jd.blockchain.crypto.KeyGenUtils;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig;
-import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
-import com.jd.blockchain.ledger.KVDataEntry;
+import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInfo;
import com.jd.blockchain.ledger.LedgerInitProperties;
@@ -216,8 +216,8 @@ public class IntegrationTest {
ledgerOfNode0.retrieveLatestBlock(); // 更新内存
// 先验证应答
- KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, dataAccountAddress, dataKey);
- for (KVDataEntry kvDataEntry : kvDataEntries) {
+ TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, dataAccountAddress, dataKey);
+ for (TypedKVEntry kvDataEntry : kvDataEntries) {
String valHexText = (String) kvDataEntry.getValue();
byte[] valBytes = HexUtils.decode(valHexText);
String valText = new String(valBytes);
@@ -420,7 +420,7 @@ public class IntegrationTest {
UserInfo userInfo = blockchainService.getUser(ledgerHash, userAddress.toString());
// getDataAccount
- AccountHeader accountHeader = blockchainService.getDataAccount(ledgerHash, dataAddress.toString());
+ BlockchainIdentity accountHeader = blockchainService.getDataAccount(ledgerHash, dataAddress.toString());
// getDataEntries
@@ -660,9 +660,9 @@ public class IntegrationTest {
LedgerQuery ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash);
LedgerBlock block = ledgerOfNode0.getBlock(txResp.getBlockHeight());
BytesValue val1InDb = ledgerOfNode0.getDataAccountSet(block).getAccount(contractDataKey.getAddress())
- .getBytes("A");
+ .getDataset().getValue("A");
BytesValue val2InDb = ledgerOfNode0.getDataAccountSet(block).getAccount(contractDataKey.getAddress())
- .getBytes(KEY_TOTAL);
+ .getDataset().getValue(KEY_TOTAL);
}
/**
diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java
index 19429524..a109e456 100644
--- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java
+++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java
@@ -316,8 +316,8 @@ public class IntegrationBase {
assertEquals(txResp.getContentHash(), transactionHash);
assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash());
- KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, daAddress, dataKey);
- for (KVDataEntry kvDataEntry : kvDataEntries) {
+ TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, daAddress, dataKey);
+ for (TypedKVEntry kvDataEntry : kvDataEntries) {
assertEquals(dataKey, kvDataEntry.getKey());
String valHexText = (String) kvDataEntry.getValue();
assertEquals(dataVal, valHexText);
diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestAll4Redis.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestAll4Redis.java
index 50ccb64c..6c8c762c 100644
--- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestAll4Redis.java
+++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestAll4Redis.java
@@ -1,8 +1,39 @@
package test.com.jd.blockchain.intgr;
-import com.jd.blockchain.crypto.*;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Random;
+
+import org.junit.Test;
+import org.springframework.core.io.ClassPathResource;
+
+import com.jd.blockchain.crypto.AddressEncoding;
+import com.jd.blockchain.crypto.AsymmetricKeypair;
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.crypto.KeyGenUtils;
+import com.jd.blockchain.crypto.PrivKey;
+import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig;
-import com.jd.blockchain.ledger.*;
+import com.jd.blockchain.ledger.BlockchainKeyGenerator;
+import com.jd.blockchain.ledger.BlockchainKeypair;
+import com.jd.blockchain.ledger.BytesValue;
+import com.jd.blockchain.ledger.DataAccountKVSetOperation;
+import com.jd.blockchain.ledger.TypedKVEntry;
+import com.jd.blockchain.ledger.LedgerBlock;
+import com.jd.blockchain.ledger.LedgerInfo;
+import com.jd.blockchain.ledger.LedgerInitProperties;
+import com.jd.blockchain.ledger.PreparedTransaction;
+import com.jd.blockchain.ledger.TransactionResponse;
+import com.jd.blockchain.ledger.TransactionState;
+import com.jd.blockchain.ledger.TransactionTemplate;
import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.DataAccountQuery;
import com.jd.blockchain.ledger.core.LedgerManage;
@@ -17,19 +48,10 @@ import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.codec.HexUtils;
import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback;
import com.jd.blockchain.utils.net.NetworkAddress;
-import org.junit.Test;
-import org.springframework.core.io.ClassPathResource;
+
import test.com.jd.blockchain.intgr.contract.AssetContract;
import test.com.jd.blockchain.intgr.initializer.LedgerInitializeWeb4SingleStepsTest;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Random;
-
-import static org.junit.Assert.*;
-
public class IntegrationTestAll4Redis {
public static final String PASSWORD = "abc";
@@ -214,21 +236,21 @@ public class IntegrationTestAll4Redis {
assertEquals(ledgerRepository.retrieveLatestBlockHeight(), txResp.getBlockHeight());
assertEquals("Value_A_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
- .getAccount(dataKey.getAddress()).getBytes("A").getValue().toUTF8String());
+ .getAccount(dataKey.getAddress()).getDataset().getValue("A").getBytes().toUTF8String());
assertEquals("Value_B_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
- .getAccount(dataKey.getAddress()).getBytes("B").getValue().toUTF8String());
+ .getAccount(dataKey.getAddress()).getDataset().getValue("B").getBytes().toUTF8String());
assertEquals("Value_C_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
- .getAccount(dataKey.getAddress()).getBytes("C").getValue().toUTF8String());
+ .getAccount(dataKey.getAddress()).getDataset().getValue("C").getBytes().toUTF8String());
assertEquals("Value_D_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
- .getAccount(dataKey.getAddress()).getBytes("D").getValue().toUTF8String());
+ .getAccount(dataKey.getAddress()).getDataset().getValue("D").getBytes().toUTF8String());
assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
- .getAccount(dataKey.getAddress()).getDataVersion("A"));
+ .getAccount(dataKey.getAddress()).getDataset().getVersion("A"));
assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
- .getAccount(dataKey.getAddress()).getDataVersion("B"));
+ .getAccount(dataKey.getAddress()).getDataset().getVersion("B"));
assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
- .getAccount(dataKey.getAddress()).getDataVersion("C"));
+ .getAccount(dataKey.getAddress()).getDataset().getVersion("C"));
assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
- .getAccount(dataKey.getAddress()).getDataVersion("D"));
+ .getAccount(dataKey.getAddress()).getDataset().getVersion("D"));
return;
}
@@ -280,9 +302,9 @@ public class IntegrationTestAll4Redis {
assertEquals(txResp.getContentHash(), prepTx.getHash());
assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash());
- KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, dataAccountAddress.toString(),
+ TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, dataAccountAddress.toString(),
dataKey);
- for (KVDataEntry kvDataEntry : kvDataEntries) {
+ for (TypedKVEntry kvDataEntry : kvDataEntries) {
assertEquals(dataKey, kvDataEntry.getKey());
String valHexText = (String) kvDataEntry.getValue();
byte[] valBytes = HexUtils.decode(valHexText);
@@ -449,9 +471,9 @@ public class IntegrationTestAll4Redis {
AsymmetricKeypair key = Crypto.getSignatureFunction("ED25519").generateKeypair();
PubKey pubKey = key.getPubKey();
Bytes dataAddress = AddressEncoding.generateAddress(pubKey);
- assertEquals(dataAddress, dataAccountSet.getAccount(dataAddress).getAddress());
+ assertEquals(dataAddress, dataAccountSet.getAccount(dataAddress).getID().getAddress());
assertEquals("hello",
- dataAccountSet.getAccount(dataAddress).getBytes(KEY_TOTAL, -1).getValue().toUTF8String());
+ dataAccountSet.getAccount(dataAddress).getDataset().getValue(KEY_TOTAL, -1).getBytes().toUTF8String());
// 验证userAccount,从合约内部赋值,然后外部验证;内部定义动态key,外部不便于得到,临时屏蔽;
// UserAccountSet userAccountSet =
@@ -479,11 +501,11 @@ public class IntegrationTestAll4Redis {
// 验证结果;
LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight());
BytesValue val1InDb = ledgerRepository.getDataAccountSet(block).getAccount(contractDataKey.getAddress())
- .getBytes("A");
+ .getDataset().getValue("A");
BytesValue val2InDb = ledgerRepository.getDataAccountSet(block).getAccount(contractDataKey.getAddress())
- .getBytes(KEY_TOTAL);
- assertEquals("Value_A_0", val1InDb.getValue().toUTF8String());
- assertEquals("total value,dataAccount", val2InDb.getValue().toUTF8String());
+ .getDataset().getValue(KEY_TOTAL);
+ assertEquals("Value_A_0", val1InDb.getBytes().toUTF8String());
+ assertEquals("total value,dataAccount", val2InDb.getBytes().toUTF8String());
}
/**
diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java
index c6361d89..e029dc09 100644
--- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java
+++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java
@@ -23,7 +23,7 @@ import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
-import com.jd.blockchain.ledger.KVDataEntry;
+import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInitProperties;
import com.jd.blockchain.ledger.PreparedTransaction;
@@ -214,7 +214,7 @@ public class IntegrationTestDataAccount {
e.printStackTrace();
}
- KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHashs[0], dataAddr.toBase58(), "A", "B",
+ TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHashs[0], dataAddr.toBase58(), "A", "B",
"C", "D");
for (int i = 0; i < kvDataEntries.length; i++) {
Object result = kvDataEntries[i].getValue();
diff --git a/source/test/test-ledger/pom.xml b/source/test/test-ledger/pom.xml
index 884c2eb8..fa9421da 100644
--- a/source/test/test-ledger/pom.xml
+++ b/source/test/test-ledger/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
test
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
test-ledger
diff --git a/source/test/test-ledger/src/main/java/test/perf/com/jd/blockchain/ledger/MerkleDatasetPerformanceTester.java b/source/test/test-ledger/src/main/java/test/perf/com/jd/blockchain/ledger/MerkleDatasetPerformanceTester.java
index 7b5faffb..a71efcee 100644
--- a/source/test/test-ledger/src/main/java/test/perf/com/jd/blockchain/ledger/MerkleDatasetPerformanceTester.java
+++ b/source/test/test-ledger/src/main/java/test/perf/com/jd/blockchain/ledger/MerkleDatasetPerformanceTester.java
@@ -14,6 +14,7 @@ import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.storage.service.impl.redis.RedisConnectionFactory;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
+import com.jd.blockchain.utils.Bytes;
public class MerkleDatasetPerformanceTester {
@@ -156,12 +157,12 @@ public class MerkleDatasetPerformanceTester {
for (int i = 0; i < round; i++) {
for (int j = 0; j < batchCount; j++) {
key = "data_" + startTs + "_" + randomId + "_" + (i * batchCount + j);
- long v = mds.getVersion(key);
- mds.setValue(key, data, v);
+ long v = mds.getVersion(Bytes.fromString(key));
+ mds.setValue(Bytes.fromString(key), data, v);
}
mds.commit();
rootHash = mds.getRootHash();
- mds = new MerkleDataSet(rootHash, cryptoConfig, MKL_KEY_PREFIX, exStorage, verStorage, false);
+ mds = new MerkleDataSet(rootHash, cryptoConfig, Bytes.fromString(MKL_KEY_PREFIX), exStorage, verStorage, false);
}
long elapsedTs = System.currentTimeMillis() - startTs;
diff --git a/source/tools/pom.xml b/source/tools/pom.xml
index 75a03f8b..aada0db1 100644
--- a/source/tools/pom.xml
+++ b/source/tools/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
jdchain-root
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
tools
pom
diff --git a/source/tools/tools-initializer-booter/pom.xml b/source/tools/tools-initializer-booter/pom.xml
index cb1603fa..06dd8b35 100644
--- a/source/tools/tools-initializer-booter/pom.xml
+++ b/source/tools/tools-initializer-booter/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
tools
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
tools-initializer-booter
diff --git a/source/tools/tools-initializer/pom.xml b/source/tools/tools-initializer/pom.xml
index 4a627f71..be338342 100644
--- a/source/tools/tools-initializer/pom.xml
+++ b/source/tools/tools-initializer/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
tools
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
tools-initializer
diff --git a/source/tools/tools-keygen-booter/pom.xml b/source/tools/tools-keygen-booter/pom.xml
index 3a859eec..d6d8c7ea 100644
--- a/source/tools/tools-keygen-booter/pom.xml
+++ b/source/tools/tools-keygen-booter/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
tools
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
tools-keygen-booter
diff --git a/source/tools/tools-keygen/pom.xml b/source/tools/tools-keygen/pom.xml
index f18d5d50..2be928a4 100644
--- a/source/tools/tools-keygen/pom.xml
+++ b/source/tools/tools-keygen/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
tools
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
tools-keygen
diff --git a/source/utils/pom.xml b/source/utils/pom.xml
index cda7fe58..a74e5bb8 100644
--- a/source/utils/pom.xml
+++ b/source/utils/pom.xml
@@ -4,7 +4,7 @@
com.jd.blockchain
jdchain-root
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
utils
pom
diff --git a/source/utils/utils-common/pom.xml b/source/utils/utils-common/pom.xml
index 6109546c..f9458f84 100644
--- a/source/utils/utils-common/pom.xml
+++ b/source/utils/utils-common/pom.xml
@@ -4,7 +4,7 @@
com.jd.blockchain
utils
- 1.1.1.RELEASE
+ 1.2.0-SNAPSHOT
utils-common
diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java
index 79773915..cea92cbc 100644
--- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java
+++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java
@@ -9,17 +9,29 @@ import java.util.*;
*/
public abstract class ArrayUtils {
private ArrayUtils() {
-
+
}
-
+
+ public static R[] castTo(T[] objs, Class clazz, CastFunction cf) {
+ if (objs == null) {
+ return null;
+ }
+ @SuppressWarnings("unchecked")
+ R[] array = (R[]) Array.newInstance(clazz, objs.length);
+ for (int i = 0; i < objs.length; i++) {
+ array[i] = cf.cast(objs[i]);
+ }
+ return array;
+ }
+
public static T[] singleton(T obj, Class clazz) {
@SuppressWarnings("unchecked")
T[] array = (T[]) Array.newInstance(clazz, 1);
array[0] = obj;
return array;
}
-
- public static T[] toArray(Iterator itr, Class clazz){
+
+ public static T[] toArray(Iterator itr, Class clazz) {
List lst = new LinkedList();
while (itr.hasNext()) {
T t = (T) itr.next();
@@ -30,19 +42,19 @@ public abstract class ArrayUtils {
lst.toArray(array);
return array;
}
-
- public static T[] toArray(Collection collection, Class clazz){
+
+ public static T[] toArray(Collection collection, Class clazz) {
@SuppressWarnings("unchecked")
T[] array = (T[]) Array.newInstance(clazz, collection.size());
collection.toArray(array);
return array;
}
-
- public static List asList(T[] array){
+
+ public static List asList(T[] array) {
return asList(array, 0, array.length);
}
-
- public static Set asSet(T[] array){
+
+ public static Set asSet(T[] array) {
if (array == null || array.length == 0) {
return Collections.emptySet();
}
@@ -52,8 +64,8 @@ public abstract class ArrayUtils {
}
return set;
}
-
- public static SortedSet asSortedSet(T[] array){
+
+ public static SortedSet asSortedSet(T[] array) {
if (array == null || array.length == 0) {
return Collections.emptySortedSet();
}
@@ -63,12 +75,12 @@ public abstract class ArrayUtils {
}
return set;
}
-
- public static List asList(T[] array, int fromIndex){
+
+ public static List asList(T[] array, int fromIndex) {
return asList(array, fromIndex, array.length);
}
-
- public static List asList(T[] array, int fromIndex, int toIndex){
+
+ public static List asList(T[] array, int fromIndex, int toIndex) {
if (toIndex < fromIndex) {
throw new IllegalArgumentException("The toIndex less than fromIndex!");
}
@@ -78,10 +90,33 @@ public abstract class ArrayUtils {
if (toIndex > array.length) {
throw new IllegalArgumentException("The toIndex great than the length of array!");
}
-
+
if (fromIndex == toIndex) {
return Collections.emptyList();
}
return new ReadonlyArrayListWrapper(array, fromIndex, toIndex);
}
+
+ public static interface CastFunction {
+ public R cast(T data);
+ }
+
+ /**
+ * Reverse all elements of the specified array;
+ *
+ * @param
+ * @param array
+ */
+ public static void reverse(T[] array) {
+ if (array == null || array.length < 2) {
+ return;
+ }
+
+ T t;
+ for (int i = 0, j = array.length - 1; i < j; i++, j--) {
+ t = array[i];
+ array[i] = array[j];
+ array[j] = t;
+ }
+ }
}
diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BaseConstant.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BaseConstant.java
index 4548dbad..890748e5 100644
--- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BaseConstant.java
+++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BaseConstant.java
@@ -1,7 +1,5 @@
package com.jd.blockchain.utils;
-import java.io.File;
-
/**
*
* @author zhaogw
diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataEntry.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataEntry.java
new file mode 100644
index 00000000..b02fa524
--- /dev/null
+++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataEntry.java
@@ -0,0 +1,17 @@
+package com.jd.blockchain.utils;
+
+/**
+ * Versioning Key-Value data entry;
+ *
+ * @author huanghaiquan
+ *
+ */
+public interface DataEntry {
+
+ public K getKey();
+
+ public long getVersion();
+
+ public V getValue();
+
+}
\ No newline at end of file
diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataIterator.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataIterator.java
new file mode 100644
index 00000000..13a8a0d0
--- /dev/null
+++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataIterator.java
@@ -0,0 +1,21 @@
+package com.jd.blockchain.utils;
+
+/**
+ * 数据迭代器;
+ *
+ * @author huanghaiquan
+ *
+ * @param
+ * @param
+ */
+public interface DataIterator {
+
+ void skip(long count);
+
+ DataEntry next();
+
+ DataEntry[] next(int count);
+
+ boolean hasNext();
+
+}
diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataTypeUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataTypeUtils.java
deleted file mode 100644
index 05952868..00000000
--- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataTypeUtils.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.jd.blockchain.utils;
-
-import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.springframework.util.TypeUtils;
-
-public abstract class DataTypeUtils {
-
- private static Map, Class>> wrapperTypes = new HashMap, Class>>();
-
- static{
- wrapperTypes.put(long.class, Long.class);
- wrapperTypes.put(int.class, Integer.class);
- wrapperTypes.put(char.class, Character.class);
- wrapperTypes.put(byte.class, Byte.class);
- wrapperTypes.put(boolean.class, Boolean.class);
- }
-
- public static boolean isAssignable(Type lhsType, Type rhsType) {
- boolean assignable = TypeUtils.isAssignable(lhsType, rhsType);
- if (assignable) {
- return true;
- }
- if (lhsType instanceof Class) {
- Class> lhsClass = (Class>) lhsType;
-
- }
-
- return false;
- }
-
-}
diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Dataset.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Dataset.java
new file mode 100644
index 00000000..2a82bd19
--- /dev/null
+++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Dataset.java
@@ -0,0 +1,101 @@
+package com.jd.blockchain.utils;
+
+/**
+ * Key-Value data set;
+ *
+ * @author huanghaiquan
+ *
+ * @param
+ * @param
+ */
+public interface Dataset {
+
+ /**
+ * Total count of data entries;
+ *
+ * @return
+ */
+ long getDataCount();
+
+ /**
+ * Create or update the value associated the specified key if the version
+ * checking is passed.
+ *
+ * The value of the key will be updated only if it's latest version equals the
+ * specified version argument.
+ * If the key doesn't exist, it will be created when the version arg was -1.
+ *
+ * If updating is performed, the version of the key increase by 1.
+ * If creating is performed, the version of the key initialize by 0.
+ *
+ * @param key The key of data;
+ * @param value The value of data;
+ * @param version The expected latest version of the key.
+ * @return The new version of the key.
+ * If the key is new created success, then return 0;
+ * If the key is updated success, then return the new version;
+ * If this operation fail by version checking or other reason, then
+ * return -1;
+ */
+ long setValue(K key, V value, long version);
+
+ /**
+ * Return the specified version's value;
+ *
+ * If the key with the specified version doesn't exist, then return null;
+ * If the version is specified to -1, then return the latest version's value;
+ *
+ * @param key
+ * @param version
+ */
+ V getValue(K key, long version);
+
+ /**
+ * Return the value of the latest version;
+ *
+ * @param key
+ * @return return null if not exist;
+ */
+ V getValue(K key);
+
+ /**
+ * Return the latest version number of the specified key;
+ *
+ * @param key
+ * @return The version number of the specified key; If the key doesn't exist,
+ * then return -1;
+ */
+ long getVersion(K key);
+
+ /**
+ * Return the data entry with the specified key;
+ *
+ * @param key
+ * @return Null if the key doesn't exist!
+ */
+ DataEntry getDataEntry(K key);
+
+ /**
+ * Return the data entry with the specified key and version;
+ *
+ * @param key
+ * @param version
+ * @return Null if the key doesn't exist!
+ */
+ DataEntry getDataEntry(K key, long version);
+
+ /**
+ * Ascending iterator;
+ *
+ * @return
+ */
+ DataIterator iterator();
+
+ /**
+ * Descending iterator;
+ *
+ * @return
+ */
+ DataIterator iteratorDesc();
+
+}
\ No newline at end of file
diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DatasetHelper.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DatasetHelper.java
new file mode 100644
index 00000000..acbdce51
--- /dev/null
+++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DatasetHelper.java
@@ -0,0 +1,382 @@
+package com.jd.blockchain.utils;
+
+/**
+ * Helper for {@link Dataset};
+ *
+ * @author huanghaiquan
+ *
+ */
+public class DatasetHelper {
+
+ public static final TypeMapper UTF8_STRING_BYTES_MAPPER = new TypeMapper() {
+
+ @Override
+ public Bytes encode(String t2) {
+ return Bytes.fromString(t2);
+ }
+
+ @Override
+ public String decode(Bytes t1) {
+ return t1.toUTF8String();
+ }
+ };
+
+ public static final TypeMapper BYTES_UTF8_STRING_MAPPER = new TypeMapper() {
+
+ @Override
+ public String encode(Bytes t1) {
+ return t1.toUTF8String();
+ }
+
+ @Override
+ public Bytes decode(String t2) {
+ return Bytes.fromString(t2);
+ }
+ };
+
+ /**
+ * 适配两个不同类型参数的数据集;
+ *
+ * @param 适配输入的 键 类型;
+ * @param 适配输出的 键 类型;
+ * @param 适配输入的 值 类型;
+ * @param 适配输出的 值 类型;
+ * @param dataset 数据集;
+ * @param keyMapper 键的映射配置;
+ * @param valueMapper 值的映射配置;
+ * @return
+ */
+ public static Dataset map(Dataset dataset) {
+ return new TypeAdapter(dataset, UTF8_STRING_BYTES_MAPPER, new EmptyMapper());
+ }
+
+ /**
+ * 适配两个不同类型参数的数据集;
+ *
+ * @param 适配输入的 键 类型;
+ * @param 适配输出的 键 类型;
+ * @param 适配输入的 值 类型;
+ * @param 适配输出的 值 类型;
+ * @param dataset 数据集;
+ * @param keyMapper 键的映射配置;
+ * @param valueMapper 值的映射配置;
+ * @return
+ */
+ public static Dataset map(Dataset dataset, TypeMapper valueMapper) {
+ return new TypeAdapter(dataset, UTF8_STRING_BYTES_MAPPER, valueMapper);
+ }
+
+ /**
+ * 适配两个不同类型参数的数据集;
+ *
+ * @param 适配输入的 键 类型;
+ * @param 适配输出的 键 类型;
+ * @param 适配输入的 值 类型;
+ * @param 适配输出的 值 类型;
+ * @param dataset 数据集;
+ * @param keyMapper 键的映射配置;
+ * @param valueMapper 值的映射配置;
+ * @return
+ */
+ public static Dataset map(Dataset dataset, TypeMapper keyMapper,
+ TypeMapper valueMapper) {
+ return new TypeAdapter(dataset, keyMapper, valueMapper);
+ }
+
+ /**
+ * 监听对数据集的变更;
+ *
+ * @param 键 类型;
+ * @param 值 类型;
+ * @param dataset 要监听的数据集;
+ * @param listener 要植入的监听器;
+ * @return 植入监听器的数据集实例;
+ */
+ public static Dataset listen(Dataset dataset, DataChangedListener listener) {
+ return new DatasetUpdatingMonitor(dataset, listener);
+ }
+
+ /**
+ * 数据修改监听器;
+ *
+ * @author huanghaiquan
+ *
+ * @param
+ * @param
+ */
+ public static interface DataChangedListener {
+
+ void onChanged(K key, V value, long expectedVersion, long newVersion);
+
+ }
+
+ /**
+ * 类型映射接口;
+ *
+ * @author huanghaiquan
+ *
+ * @param
+ * @param
+ */
+ public static interface TypeMapper {
+
+ T1 encode(T2 t2);
+
+ T2 decode(T1 t1);
+
+ }
+
+ private static class EmptyMapper implements TypeMapper {
+
+ @Override
+ public T encode(T t) {
+ return t;
+ }
+
+ @Override
+ public T decode(T t) {
+ return t;
+ }
+
+ }
+
+ private static class DatasetUpdatingMonitor implements Dataset {
+
+ private Dataset dataset;
+
+ private DataChangedListener listener;
+
+ public DatasetUpdatingMonitor(Dataset dataset, DataChangedListener listener) {
+ this.dataset = dataset;
+ this.listener = listener;
+ }
+
+ @Override
+ public long getDataCount() {
+ return dataset.getDataCount();
+ }
+
+ @Override
+ public long setValue(K key, V value, long version) {
+ long newVersion = dataset.setValue(key, value, version);
+ if (newVersion > -1) {
+ listener.onChanged(key, value, version, newVersion);
+ }
+ return newVersion;
+ }
+
+ @Override
+ public V getValue(K key, long version) {
+ return dataset.getValue(key, version);
+ }
+
+ @Override
+ public V getValue(K key) {
+ return dataset.getValue(key);
+ }
+
+ @Override
+ public long getVersion(K key) {
+ return dataset.getVersion(key);
+ }
+
+ @Override
+ public DataEntry getDataEntry(K key) {
+ return dataset.getDataEntry(key);
+ }
+
+ @Override
+ public DataEntry getDataEntry(K key, long version) {
+ return dataset.getDataEntry(key, version);
+ }
+
+ @Override
+ public DataIterator iterator() {
+ return dataset.iterator();
+ }
+
+ @Override
+ public DataIterator iteratorDesc() {
+ return dataset.iteratorDesc();
+ }
+
+ }
+
+ /**
+ * 类型适配器;
+ *
+ * @author huanghaiquan
+ *
+ * @param
+ * @param
+ * @param
+ * @param
+ */
+ private static class TypeAdapter implements Dataset {
+ private Dataset dataset;
+ private TypeMapper keyMapper;
+ private TypeMapper valueMapper;
+
+ public TypeAdapter(Dataset dataset, TypeMapper keyMapper, TypeMapper valueMapper) {
+ this.dataset = dataset;
+ this.keyMapper = keyMapper;
+ this.valueMapper = valueMapper;
+ }
+
+ @Override
+ public long getDataCount() {
+ return dataset.getDataCount();
+ }
+
+ @Override
+ public long setValue(K2 key, V2 value, long version) {
+ K1 key1 = keyMapper.encode(key);
+ V1 value1 = valueMapper.encode(value);
+ return dataset.setValue(key1, value1, version);
+ }
+
+ @Override
+ public V2 getValue(K2 key, long version) {
+ K1 k = keyMapper.encode(key);
+ V1 v = dataset.getValue(k, version);
+ if (v == null) {
+ return null;
+ }
+ return valueMapper.decode(v);
+ }
+
+ @Override
+ public V2 getValue(K2 key) {
+ K1 k = keyMapper.encode(key);
+ V1 v = dataset.getValue(k);
+ if (v == null) {
+ return null;
+ }
+ return valueMapper.decode(v);
+ }
+
+ @Override
+ public long getVersion(K2 key) {
+ K1 k = keyMapper.encode(key);
+ return dataset.getVersion(k);
+ }
+
+ @Override
+ public DataEntry getDataEntry(K2 key) {
+ K1 k = keyMapper.encode(key);
+ DataEntry entry = dataset.getDataEntry(k);
+ if (entry == null) {
+ return null;
+ }
+ V2 v = valueMapper.decode(entry.getValue());
+ return new KeyValueEntry