diff --git a/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java b/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java index 80eaa4f7..cd1da3d5 100644 --- a/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java +++ b/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java @@ -122,11 +122,15 @@ public interface DataCodes { public static final int ACCOUNT_HEADER = 0x710; public static final int USER_ACCOUNT_HEADER = 0x800; + + public static final int USER_INFO = 0x801; public static final int DATA = 0x900; // contract related; public static final int CONTRACT_ACCOUNT_HEADER = 0xA00; + + public static final int CONTRACT_INFO = 0xA01; // ...0xA19 public static final int HASH = 0xB00; diff --git a/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/impl/DynamicDataContract.java b/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/impl/DynamicDataContract.java index aaa8780b..58b94e25 100644 --- a/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/impl/DynamicDataContract.java +++ b/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/impl/DynamicDataContract.java @@ -21,8 +21,6 @@ class DynamicDataContract implements InvocationHandler { private DataContractEncoderImpl contractEncoder; -// private BytesSlice contractBytes; - // 字段的数据片段列表,首个是 HeaderSlice,其次是按字段顺序排列的数据片段; private BytesSlices[] dataSlices; diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountQuery.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountQuery.java index 8f1f3cb0..23afd3fd 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountQuery.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountQuery.java @@ -1,12 +1,11 @@ package com.jd.blockchain.ledger.core; -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 interface AccountQuery extends MerkleProvable { - - AccountHeader[] getHeaders(int fromIndex, int count); - + /** * 返回总数; * @@ -14,7 +13,15 @@ public interface AccountQuery extends MerkleProvable { */ long getTotal(); + BlockchainIdentity[] getHeaders(int fromIndex, int count); + boolean contains(Bytes address); + + /** + * get proof of specified account; + */ + @Override + MerkleProof getProof(Bytes address); /** * 返回账户实例; diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/BytesKeyMap.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/BytesKeyMap.java new file mode 100644 index 00000000..e4b6ffeb --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/BytesKeyMap.java @@ -0,0 +1,8 @@ +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.VersioningMap; + +public interface BytesKeyMap extends VersioningMap { + +} 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..88583505 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 @@ -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.BytesData; +import com.jd.blockchain.ledger.TypedBytesValue; import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.ContractInfo; import com.jd.blockchain.ledger.MerkleProof; @@ -44,16 +44,16 @@ public class ContractAccount implements ContractInfo { } public long setChaincode(byte[] chaincode, long version) { - BytesValue bytesValue = BytesData.fromBytes(chaincode); - return accBase.setBytes(CHAIN_CODE_KEY, bytesValue, version); + BytesValue bytesValue = TypedBytesValue.fromBytes(chaincode); + return accBase.setValue(CHAIN_CODE_KEY, bytesValue, version); } public byte[] getChainCode() { - return accBase.getBytes(CHAIN_CODE_KEY).getValue().toBytes(); + return accBase.getValue(CHAIN_CODE_KEY).getValue().toBytes(); } public byte[] getChainCode(long version) { - return accBase.getBytes(CHAIN_CODE_KEY, version).getValue().toBytes(); + return accBase.getValue(CHAIN_CODE_KEY, version).getValue().toBytes(); } public long getChaincodeVersion() { @@ -61,18 +61,18 @@ public class ContractAccount implements ContractInfo { } public long setProperty(Bytes key, String value, long version) { - BytesValue bytesValue = BytesData.fromText(value); - return accBase.setBytes(encodePropertyKey(key), bytesValue, version); + BytesValue bytesValue = TypedBytesValue.fromText(value); + return accBase.setValue(encodePropertyKey(key), bytesValue, version); } public String getProperty(Bytes key) { - BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key)); - return BytesData.toText(bytesValue); + BytesValue bytesValue = accBase.getValue(encodePropertyKey(key)); + return TypedBytesValue.toText(bytesValue); } public String getProperty(Bytes key, long version) { - BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key), version); - return BytesData.toText(bytesValue); + BytesValue bytesValue = accBase.getValue(encodePropertyKey(key), version); + return TypedBytesValue.toText(bytesValue); } private Bytes encodePropertyKey(Bytes key) { 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..3abbdfd7 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 @@ -4,7 +4,7 @@ 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.TypedBytesValue; import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.KVDataEntry; import com.jd.blockchain.ledger.KVDataObject; @@ -67,7 +67,7 @@ public class DataAccount implements AccountHeader, MerkleProvable { * return -1; */ public long setBytes(Bytes key, BytesValue value, long version) { - return baseAccount.setBytes(key, value, version); + return baseAccount.setValue(key, value, version); } @@ -95,8 +95,8 @@ public class DataAccount implements AccountHeader, MerkleProvable { * return -1; */ public long setBytes(Bytes key, String value, long version) { - BytesValue bytesValue = BytesData.fromText(value); - return baseAccount.setBytes(key, bytesValue, version); + BytesValue bytesValue = TypedBytesValue.fromText(value); + return baseAccount.setValue(key, bytesValue, version); } /** @@ -123,8 +123,8 @@ public class DataAccount implements AccountHeader, MerkleProvable { * return -1; */ public long setBytes(Bytes key, byte[] value, long version) { - BytesValue bytesValue = BytesData.fromBytes(value); - return baseAccount.setBytes(key, bytesValue, version); + BytesValue bytesValue = TypedBytesValue.fromBytes(value); + return baseAccount.setValue(key, bytesValue, version); } /** @@ -156,7 +156,7 @@ public class DataAccount implements AccountHeader, MerkleProvable { * @return return null if not exist; */ public BytesValue getBytes(String key) { - return baseAccount.getBytes(Bytes.fromString(key)); + return baseAccount.getValue(Bytes.fromString(key)); } /** @@ -166,7 +166,7 @@ public class DataAccount implements AccountHeader, MerkleProvable { * @return return null if not exist; */ public BytesValue getBytes(Bytes key) { - return baseAccount.getBytes(key); + return baseAccount.getValue(key); } /** @@ -177,7 +177,7 @@ public class DataAccount implements AccountHeader, MerkleProvable { * @return return null if not exist; */ public BytesValue getBytes(String key, long version) { - return baseAccount.getBytes(Bytes.fromString(key), version); + return baseAccount.getValue(Bytes.fromString(key), version); } /** @@ -188,7 +188,7 @@ public class DataAccount implements AccountHeader, MerkleProvable { * @return return null if not exist; */ public BytesValue getBytes(Bytes key, long version) { - return baseAccount.getBytes(key, version); + return baseAccount.getValue(key, version); } /** @@ -206,7 +206,7 @@ public class DataAccount implements AccountHeader, MerkleProvable { * @return */ public KVDataEntry getDataEntry(Bytes key, long version) { - BytesValue value = baseAccount.getBytes(key, version); + BytesValue value = baseAccount.getValue(key, version); if (value == null) { return new KVDataObject(key.toUTF8String(), -1, null); }else { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenericAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenericAccount.java new file mode 100644 index 00000000..e374c08a --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenericAccount.java @@ -0,0 +1,83 @@ +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.TypedBytesValue; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.MerkleProof; +import com.jd.blockchain.ledger.TypedBytesValue; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.Transactional; +import com.jd.blockchain.utils.VersioningMap; + +/** + * Super Type of concrete accounts, e.g. UserAccount, DataAccount, + * ContractAccount etc.; + * + * @author huanghaiquan + * + * @param Type of Account Header; + */ +public class GenericAccount implements MerkleAccountHeader, MerkleProvable, Transactional { + + private MerkleAccount merkleAccount; + + + /** + * 头部类型; + * + * @param headerType + */ + public GenericAccount(MerkleAccount merkleAccount) { + this.merkleAccount = merkleAccount; + } + + @Override + public HashDigest getRootHash() { + return merkleAccount.getRootHash(); + } + + @Override + public MerkleProof getProof(Bytes key) { + key = buildInnerKey(key); + return merkleAccount.getProof(key); + } + + + @Override + public BlockchainIdentity getID() { + return merkleAccount.getID(); + } + + public TypedMap getDataset() { + VersioningMap state = merkleAccount.getDataset(); + return new TypedMap(state); + } + + + @Override + public boolean isUpdated() { + return merkleAccount.isUpdated(); + } + + boolean isReadonly() { + return merkleAccount.isReadonly(); + } + + @Override + public void commit() { + merkleAccount.commit(); + } + + @Override + public void cancel() { + merkleAccount.cancel(); + } + + private Bytes buildInnerKey(Bytes key) { + // TODO Auto-generated method stub + return null; + } + +} 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/HashDegistList.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/HashDegistList.java new file mode 100644 index 00000000..41dc4f3d --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/HashDegistList.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 HashDegistList implements HashProof { + + private List proofs = new ArrayList(); + + public HashDegistList() { + } + + public HashDegistList(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/LedgerAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAccount.java new file mode 100644 index 00000000..02d6c7a1 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAccount.java @@ -0,0 +1,14 @@ +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.VersioningMap; + +public interface LedgerAccount { + + BlockchainIdentity getID(); + + VersioningMap getDataset(); + +} 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..a0973e12 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,16 +3,20 @@ 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.TypedBytesValue; 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; +import com.jd.blockchain.utils.VersioningKVEntry; +import com.jd.blockchain.utils.VersioningMap; /** * 事务性的基础账户; @@ -20,28 +24,26 @@ import com.jd.blockchain.utils.Transactional; * @author huanghaiquan * */ -public class MerkleAccount implements AccountHeader, MerkleProvable, Transactional { +public class MerkleAccount implements LedgerAccount, 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_PUBKEY = Bytes.fromString("PUBKEY"); - /** - * Create a new Account with the specified 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 - */ - public MerkleAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix, - ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) { - this(address, pubKey, null, cryptoSetting, keyPrefix, exStorage, verStorage, false); - } + private static final Bytes KEY_HEADER_ROOT = Bytes.fromString("HEADER"); + + private static final Bytes KEY_DATA_ROOT = Bytes.fromString("DATA"); + + private BlockchainIdentity accountID; + + private MerkleDataSet rootDS; + + private MerkleDatasetAdapter headerDS; + + private MerkleDatasetAdapter dataDS; + + protected long version; /** * Create a new Account with the specified address and pubkey;
@@ -52,62 +54,101 @@ public class MerkleAccount implements AccountHeader, MerkleProvable, Transaction * 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 accountID 身份; + * @param version 版本; + * @param cryptoSetting 密码参数; + * @param keyPrefix 数据前缀; * @param exStorage * @param verStorage - * @param accessPolicy */ - public MerkleAccount(BlockchainIdentity bcid, CryptoSetting cryptoSetting, String keyPrefix, + public MerkleAccount(BlockchainIdentity accountID, long version, CryptoSetting cryptoSetting, Bytes keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) { - this(bcid, null, cryptoSetting, keyPrefix, exStorage, verStorage, false); + this(accountID.getAddress(), accountID.getPubKey(), version, null, cryptoSetting, keyPrefix, exStorage, + verStorage, false); + + savePubKey(accountID.getPubKey()); } /** * 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.
+ * 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 accountID identity of this account; + * @param version + * @param dataRootHash merkle root hash of account's data; if set to a null + * value, an empty merkle dataset is created; * @param cryptoSetting + * @param keyPrefix * @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, + public MerkleAccount(Bytes address, long version, HashDigest dataRootHash, CryptoSetting cryptoSetting, + Bytes keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) { + this(address, null, version, dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); + } + + private MerkleAccount(Bytes address, PubKey pubKey, long version, HashDigest dataRootHash, + CryptoSetting cryptoSetting, Bytes keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, + boolean readonly) { + this.accountID = new BlockchainIdentityProxy(address, pubKey); + this.version = version; + this.rootDS = new MerkleDataSet(dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); + + // 初始化数据; + DataChangedListener dataChangedListener = new DataChangedListener() { + @Override + public void onChanged(Bytes key, BytesValue value, long newVersion) { + onUpdated(keyPrefix, value, newVersion); + } + }; + + HashDigest headerRoot = loadHeaderRoot(); + Bytes headerPrefix = keyPrefix.concat(HEADER_PREFIX); + MerkleDataSet headerDataset = new MerkleDataSet(headerRoot, cryptoSetting, headerPrefix, exStorage, verStorage, readonly); + this.headerDS = new MerkleDatasetAdapter(headerDataset, dataChangedListener); + + HashDigest dataRoot = loadDataRoot(); + Bytes dataPrefix = keyPrefix.concat(DATA_PREFIX); + MerkleDataSet dataDataset = new MerkleDataSet(dataRoot, cryptoSetting, dataPrefix, exStorage, verStorage, + readonly); + this.dataDS = new MerkleDatasetAdapter(dataDataset, dataChangedListener); + } + + private HashDigest loadHeaderRoot() { + byte[] hashBytes = rootDS.getValue(KEY_HEADER_ROOT); + if (hashBytes == null) { + return null; + } + return new HashDigest(hashBytes); } - 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 loadDataRoot() { + byte[] hashBytes = rootDS.getValue(KEY_DATA_ROOT); + if (hashBytes == null) { + return null; + } + return new HashDigest(hashBytes); } - /* - * (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; + } + + @Override + public VersioningMap getDataset() { + return dataDS; } /* @@ -117,12 +158,22 @@ public class MerkleAccount implements AccountHeader, MerkleProvable, Transaction */ @Override public HashDigest getRootHash() { - return dataset.getRootHash(); + return rootDS.getRootHash(); } @Override - public MerkleProof getProof(Bytes key) { - return dataset.getProof(key); + public HashProof getProof(Bytes key) { + MerkleProof dataProof = dataDS.getDataset().getProof(key); + if (dataProof == null) { + return null; + } + MerkleProof rootProof = rootDS.getProof(KEY_DATA_ROOT); + if (rootProof == null) { + return null; + } + HashDegistList proof = new HashDegistList(rootProof); + proof.concat(dataProof); + return proof; } /** @@ -131,90 +182,234 @@ public class MerkleAccount implements AccountHeader, MerkleProvable, Transaction * @return */ public boolean isReadonly() { - return dataset.isReadonly(); + return dataDS.getDataset().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; - */ - public long setBytes(Bytes key, BytesValue value, long version) { - byte[] bytesValue = BinaryProtocol.encode(value, BytesValue.class); - return dataset.setValue(key, bytesValue, version); + public long getDataCount() { + return dataDS.getDataset().getDataCount(); } /** - * Return the latest version entry associated the specified key; If the key - * doesn't exist, then return -1; + * 保存公钥; * - * @param key - * @return + * @param pubKey */ - public long getVersion(Bytes key) { - return dataset.getVersion(key); + private void savePubKey(PubKey pubKey) { + long v = headerDS.setValue(KEY_PUBKEY, TypedBytesValue.fromPubKey(pubKey), -1); + if (v < 0) { + throw new LedgerException("PubKey storage conflict!"); + } } /** - * return the latest version's value; + * 加载公钥; * - * @param key - * @return return null if not exist; + * @return */ - public BytesValue getBytes(Bytes key) { - byte[] bytesValue = dataset.getValue(key); - if (bytesValue == null) { - return null; - } - return BinaryProtocol.decodeAs(bytesValue, BytesValue.class); + private PubKey loadPubKey() { + BytesValue bytesValue = headerDS.getValue(KEY_PUBKEY); + return TypedBytesValue.wrap(bytesValue).pubKeyValue(); } /** - * Return the specified version's value; + * 当写入新值时触发此方法; * * @param key - * @param version - * @return return null if not exist; + * @param value + * @param newVersion */ - 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 onUpdated(Bytes key, BytesValue value, long newVersion) { } @Override public boolean isUpdated() { - return dataset.isUpdated(); + return dataDS.getDataset().isUpdated() || headerDS.getDataset().isUpdated() || rootDS.isUpdated(); } @Override public void commit() { - dataset.commit(); + dataDS.getDataset().commit(); + headerDS.getDataset().commit(); + + rootDS.setValue(key, value, version) + + baseDS.commit(); } @Override public void cancel() { - dataset.cancel(); + baseDS.cancel(); + } + + private class BlockchainIdentityProxy implements BlockchainIdentity { + + private Bytes address; + + private PubKey pubKey; + + public BlockchainIdentityProxy(Bytes address, PubKey pubKey) { + this.address = address; + this.pubKey = pubKey; + } + + @Override + public Bytes getAddress() { + return address; + } + + @Override + public PubKey getPubKey() { + if (pubKey == null) { + pubKey = loadPubKey(); + } + return pubKey; + } + + } + + // ---------------------- + + private static class MerkleDatasetAdapter implements VersioningMap { + + 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; + } + + 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 VersioningKVEntry getDataEntry(Bytes key) { + return new VersioningKVEntryWraper(dataset.getDataEntry(key)); + } + + @Override + public VersioningKVEntry getDataEntry(Bytes key, long version) { + return new VersioningKVEntryWraper(dataset.getDataEntry(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); + } + } + + private static interface DataChangedListener { + + void onChanged(Bytes key, BytesValue value, long newVersion); + + } + + private static class VersioningKVEntryWraper implements VersioningKVEntry { + + private VersioningKVEntry kv; + + public VersioningKVEntryWraper(VersioningKVEntry kv) { + this.kv = kv; + } + + @Override + public Bytes getKey() { + return kv.getKey(); + } + + @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..0a833516 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 @@ -9,6 +9,7 @@ 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.BlockchainIdentity; import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.LedgerException; @@ -17,17 +18,24 @@ 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.RegionMap; import com.jd.blockchain.utils.Transactional; +import com.jd.blockchain.utils.VersioningMap; -public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQuery { +public abstract class MerkleAccountSet implements Transactional, MerkleProvable, AccountQuery { + + private static final Bytes ACCOUNT_ROOT_PREFIX = Bytes.fromString("ROOT/"); static { DataContractRegistry.register(MerkleSnapshot.class); DataContractRegistry.register(AccountHeader.class); } - private final String keyPrefix; - + private final Bytes keyPrefix; + + /** + * 账户根哈希的数据集; + */ private MerkleDataSet merkleDataset; /** @@ -36,7 +44,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ * */ // TODO:未考虑大数据量时,由于缺少过期策略,会导致内存溢出的问题; - private Map latestAccountsCache = new HashMap<>(); + private Map latestAccountsCache = new HashMap<>(); private ExPolicyKVStorage baseExStorage; @@ -44,7 +52,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ private CryptoSetting cryptoSetting; - private boolean updated; + private volatile boolean updated; private AccountAccessPolicy accessPolicy; @@ -56,12 +64,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 +78,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,10 +92,11 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ return merkleDataset.getProof(key); } - public AccountHeader[] getHeaders(int fromIndex, int count) { + @Override + public BlockchainIdentity[] getHeaders(int fromIndex, int count) { byte[][] results = merkleDataset.getLatestValues(fromIndex, count); - AccountHeader[] accounts = new AccountHeader[results.length]; + BlockchainIdentity[] accounts = new BlockchainIdentity[results.length]; for (int i = 0; i < results.length; i++) { accounts[i] = deserialize(results[i]); } @@ -104,8 +114,8 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ // keyPrefix, baseExStorage, baseVerStorage, true, accessPolicy, accInfo.); // } - private AccountHeader deserialize(byte[] txBytes) { - return BinaryProtocol.decode(txBytes); + private BlockchainIdentity deserialize(byte[] txBytes) { + return BinaryProtocol.decodeAs(txBytes, BlockchainIdentity.class); } /** @@ -128,6 +138,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ * @param address * @return */ + @Override public MerkleAccount getAccount(Bytes address) { return this.getAccount(address, -1); } @@ -157,7 +168,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ * @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; @@ -177,7 +188,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ */ public MerkleAccount 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) { @@ -218,8 +229,9 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ // 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); + + Bytes prefix = keyPrefix.concat(address); + acc = deserialize(bytes, cryptoSetting, prefix, readonly, latestVersion); if (!readonly) { // cache the latest version witch enable reading and writing; // readonly version of account not necessary to be cached; @@ -239,14 +251,16 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ * @param pubKey 公钥; * @return 注册成功的账户对象; */ - public MerkleAccount register(Bytes address, PubKey pubKey) { + public MerkleAccount 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) { // 同一个新账户已经注册,但尚未提交,所以重复注册不会引起任何变化; @@ -272,9 +286,8 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ // 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, -1); latestAccountsCache.put(address, acc); updated = true; @@ -288,20 +301,24 @@ 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, + long version) { + return new InnerMerkleAccount(header, version, cryptoSetting, keyPrefix, baseExStorage, baseVerStorage); } - 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 deserialize(byte[] bytes, CryptoSetting cryptoSetting, Bytes keyPrefix, boolean readonly, + long version) { + BlockchainIdentity id = BinaryProtocol.decodeAs(bytes, BlockchainIdentity.class); + + return new InnerMerkleAccount(header.getID(), version, header.getRootHash(), cryptoSetting, keyPrefix, + baseExStorage, baseVerStorage, readonly); + } - private byte[] serialize(AccountHeader account) { - return BinaryProtocol.encode(account, AccountHeader.class); + // TODO: 优化:区块链身份(地址+公钥)与其 Merkle + // 树根哈希分开独立存储;不必作为一个整块,避免状态数据写入时频繁重写公钥,尤其某些算法的公钥可能很大; + private byte[] serialize(MerkleAccountHeader account) { + return BinaryProtocol.encode(account, MerkleAccountHeader.class); } @Override @@ -315,16 +332,17 @@ 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); + long ver = merkleDataset.setValue(acc.getID().getAddress(), value, acc.version); if (ver < 0) { // Update fail; - throw new LedgerException("Account updating fail! --[Address=" + acc.getAddress() + "]"); + throw new LedgerException( + "Account updating fail! --[Address=" + acc.getID().getAddress() + "]"); } } } @@ -343,7 +361,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,108 +370,24 @@ 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; - } + private class InnerMerkleAccount extends MerkleAccount { - @Override - public Bytes getAddress() { - return address; + public InnerMerkleAccount(BlockchainIdentity accountID, long version, CryptoSetting cryptoSetting, + Bytes keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) { + super(accountID, version, cryptoSetting, keyPrefix, exStorage, verStorage); } - @Override - public PubKey getPubKey() { - return pubKey; + public InnerMerkleAccount(BlockchainIdentity accountID, long version, HashDigest dataRootHash, + CryptoSetting cryptoSetting, Bytes keyPrefix, ExPolicyKVStorage exStorage, + VersioningKVStorage verStorage, boolean readonly) { + super(accountID, version, dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); } @Override - public HashDigest getRootHash() { - return rootHash; + protected void onUpdated(Bytes key, BytesValue value, long newVersion) { + updated = true; } } - 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); - 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 - // 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; - } - return v; - } - - // @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); - // } - - } - } \ No newline at end of file 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..75894d0f 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.VersioningKVEntry; public interface MerkleDataEntry { - VersioningKVEntry getData(); + VersioningKVEntry getData(); MerkleProof getProof(); } 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..0ea23990 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,12 +7,13 @@ 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.Bytes; import com.jd.blockchain.utils.Transactional; +import com.jd.blockchain.utils.VersioningKVEntry; +import com.jd.blockchain.utils.VersioningMap; import com.jd.blockchain.utils.io.BytesUtils; /** @@ -23,7 +24,7 @@ import com.jd.blockchain.utils.io.BytesUtils; * @author huanghaiquan * */ -public class MerkleDataSet implements Transactional, MerkleProvable { +public class MerkleDataSet implements Transactional, MerkleProvable, VersioningMap { /** * 4 MB MaxSize of value; @@ -32,9 +33,9 @@ public class MerkleDataSet implements Transactional, MerkleProvable { 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" + ORIG_KEY_SEPERATOR); + public static final Bytes DATA_PREFIX = Bytes.fromString("KV" + ORIG_KEY_SEPERATOR); + public static final Bytes MERKLE_TREE_PREFIX = Bytes.fromString("MKL" + ORIG_KEY_SEPERATOR); private final Bytes snKeyPrefix; private final Bytes dataKeyPrefix; @@ -102,19 +103,21 @@ public class MerkleDataSet implements Transactional, MerkleProvable { * @param merkleTreeStorage * @param snGenerator */ - public MerkleDataSet(HashDigest merkleRootHash, CryptoSetting setting, String keyPrefix, + 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); @@ -154,20 +157,21 @@ public class MerkleDataSet implements Transactional, MerkleProvable { return values; } - public VersioningKVEntry[] getLatestDataEntries(int fromIndex, int count) { + public VersioningKVEntry[] getLatestDataEntries(int 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]; + @SuppressWarnings("unchecked") + VersioningKVEntry[] values = new VersioningKVEntry[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; } @@ -192,32 +196,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 +245,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 +343,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 +366,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 +379,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 +396,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 +406,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,20 +425,22 @@ 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)); - } +// public VersioningKVEntry getDataEntry(String key) { +// return getDataEntry(Bytes.fromString(key)); +// } /** * * @param key * @return Null if the key doesn't exist! */ - public VersioningKVEntry getDataEntry(Bytes key) { + @Override + public VersioningKVEntry getDataEntry(Bytes key) { long latestVersion = getMerkleVersion(key); if (latestVersion < 0) { return null; @@ -436,10 +450,11 @@ public class MerkleDataSet implements Transactional, MerkleProvable { if (value == null) { return null; } - return new VersioningKVData(key, latestVersion, value); + return new VersioningKVData(key, latestVersion, value); } - public VersioningKVEntry getDataEntry(Bytes key, long version) { + @Override + public VersioningKVEntry 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 +467,11 @@ public class MerkleDataSet implements Transactional, MerkleProvable { if (value == null) { return null; } - return new VersioningKVData(key, version, value); + return new VersioningKVData(key, version, value); } public MerkleDataEntry getMerkleEntry(Bytes key, long version) { - VersioningKVEntry dataEntry = getDataEntry(key, version); + VersioningKVEntry dataEntry = getDataEntry(key, version); if (dataEntry == null) { return null; } @@ -465,7 +480,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable { } public MerkleDataEntry getMerkleEntry(Bytes key) { - VersioningKVEntry dataEntry = getDataEntry(key); + VersioningKVEntry dataEntry = getDataEntry(key); if (dataEntry == null) { return null; } @@ -499,16 +514,16 @@ public class MerkleDataSet implements Transactional, MerkleProvable { */ private static class MerkleDataEntryWrapper implements MerkleDataEntry { - private VersioningKVEntry data; + private VersioningKVEntry data; private MerkleProof proof; - public MerkleDataEntryWrapper(VersioningKVEntry data, MerkleProof proof) { + public MerkleDataEntryWrapper(VersioningKVEntry data, MerkleProof proof) { this.data = data; this.proof = proof; } @Override - public VersioningKVEntry getData() { + public VersioningKVEntry getData() { return data; } 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..74d670c4 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.VersioningKVEntry; public class RolePrivilegeDataset implements Transactional, MerkleProvable, RolePrivilegeSettings { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/StringKeyMap.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/StringKeyMap.java new file mode 100644 index 00000000..227c3dd7 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/StringKeyMap.java @@ -0,0 +1,7 @@ +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.utils.VersioningMap; + +public interface StringKeyMap extends VersioningMap { + +} 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..0e7dc692 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 @@ -2,10 +2,11 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.TypedBytesValue; import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.BytesData; -import com.jd.blockchain.ledger.UserInfo; +import com.jd.blockchain.ledger.UserAccountHeader; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.VersioningMap; /** * 用户账户; @@ -13,35 +14,20 @@ import com.jd.blockchain.utils.Bytes; * @author huanghaiquan * */ -public class UserAccount implements UserInfo { +public class UserAccount extends MerkleAccount{ //implements UserInfo { private static final Bytes USER_INFO_PREFIX = Bytes.fromString("PROP" + LedgerConsts.KEY_SEPERATOR); private static final Bytes DATA_PUB_KEY = Bytes.fromString("DATA-PUBKEY"); - private MerkleAccount baseAccount; +// private MerkleAccount baseAccount; - @Override - public Bytes getAddress() { - return baseAccount.getAddress(); - } - - @Override - public PubKey getPubKey() { - return baseAccount.getPubKey(); - } - - @Override - public HashDigest getRootHash() { - return baseAccount.getRootHash(); - } - - public UserAccount(MerkleAccount baseAccount) { + public UserAccount(VersioningMap baseAccount) { this.baseAccount = baseAccount; } public PubKey getDataPubKey() { - BytesValue pkBytes = baseAccount.getBytes(DATA_PUB_KEY); + BytesValue pkBytes = baseAccount.getValue(DATA_PUB_KEY); if (pkBytes == null) { return null; } @@ -50,12 +36,12 @@ public class UserAccount implements UserInfo { public long setDataPubKey(PubKey pubKey) { byte[] pkBytes = pubKey.toBytes(); - return baseAccount.setBytes(DATA_PUB_KEY, BytesData.fromBytes(pkBytes), -1); + return baseAccount.setValue(DATA_PUB_KEY, TypedBytesValue.fromBytes(pkBytes), -1); } public long setDataPubKey(PubKey pubKey, long version) { byte[] pkBytes = pubKey.toBytes(); - return baseAccount.setBytes(DATA_PUB_KEY, BytesData.fromBytes(pkBytes), version); + return baseAccount.setValue(DATA_PUB_KEY, TypedBytesValue.fromBytes(pkBytes), version); } public long setProperty(String key, String value, long version) { @@ -63,16 +49,16 @@ public class UserAccount implements UserInfo { } public long setProperty(Bytes key, String value, long version) { - return baseAccount.setBytes(encodePropertyKey(key), BytesData.fromText(value), version); + return baseAccount.setValue(encodePropertyKey(key), TypedBytesValue.fromText(value), version); } public String getProperty(Bytes key) { - BytesValue value = baseAccount.getBytes(encodePropertyKey(key)); + BytesValue value = baseAccount.getValue(encodePropertyKey(key)); return value == null ? null : value.getValue().toUTF8String(); } public String getProperty(Bytes key, long version) { - BytesValue value = baseAccount.getBytes(encodePropertyKey(key), version); + BytesValue value = baseAccount.getValue(encodePropertyKey(key), version); return value == null ? null : value.getValue().toUTF8String(); } 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..700c0a49 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 @@ -10,6 +10,7 @@ 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; +import com.jd.blockchain.utils.VersioningMap; /** * @author huanghaiquan @@ -71,7 +72,7 @@ public class UserAccountSet implements Transactional, UserAccountQuery { @Override public UserAccount getAccount(Bytes address) { - MerkleAccount baseAccount = accountSet.getAccount(address); + VersioningMap 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); + VersioningMap baseAccount = accountSet.getAccount(address, version); return new UserAccount(baseAccount); } @@ -100,7 +101,7 @@ public class UserAccountSet implements Transactional, UserAccountQuery { * @return 注册成功的用户对象; */ public UserAccount register(Bytes address, PubKey pubKey) { - MerkleAccount baseAccount = accountSet.register(address, pubKey); + VersioningMap 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..84d71347 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.VersioningKVEntry; /** * User-Role authorization data set; 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..5c22a7dc 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 @@ -268,7 +268,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { - BytesValue bytesValue = BytesData.fromText(value); + BytesValue bytesValue = TypedBytesValue.fromText(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; @@ -276,7 +276,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { - BytesValue bytesValue = BytesData.fromBytes(value); + BytesValue bytesValue = TypedBytesValue.fromBytes(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; @@ -284,7 +284,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { - BytesValue bytesValue = BytesData.fromInt64(value); + BytesValue bytesValue = TypedBytesValue.fromInt64(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; @@ -301,7 +301,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { - BytesValue bytesValue = BytesData.fromJSON(value); + BytesValue bytesValue = TypedBytesValue.fromJSON(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; @@ -309,7 +309,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { - BytesValue bytesValue = BytesData.fromXML(value); + BytesValue bytesValue = TypedBytesValue.fromXML(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; @@ -317,7 +317,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { - BytesValue bytesValue = BytesData.fromBytes(value); + BytesValue bytesValue = TypedBytesValue.fromBytes(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; @@ -325,7 +325,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { - BytesValue bytesValue = BytesData.fromImage(value); + BytesValue bytesValue = TypedBytesValue.fromImage(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; @@ -333,7 +333,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { - BytesValue bytesValue = BytesData.fromTimestamp(value); + BytesValue bytesValue = TypedBytesValue.fromTimestamp(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; 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..8ca0fe9f 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 @@ -12,7 +12,7 @@ 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.TypedBytesValue; import com.jd.blockchain.ledger.core.MerkleAccount; import com.jd.blockchain.ledger.core.CryptoConfig; import com.jd.blockchain.storage.service.utils.MemoryKVStorage; @@ -53,33 +53,33 @@ public class BaseAccountTest { assertFalse(baseAccount.isReadonly()); // 在空白状态下写入数据; - long v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), 0); + long v = baseAccount.setValue(Bytes.fromString("A"), TypedBytesValue.fromText("VALUE_A"), 0); // 预期失败; assertEquals(-1, v); - v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), 1); + v = baseAccount.setValue(Bytes.fromString("A"), TypedBytesValue.fromText("VALUE_A"), 1); // 预期失败; assertEquals(-1, v); - v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), -1); + v = baseAccount.setValue(Bytes.fromString("A"), TypedBytesValue.fromText("VALUE_A"), -1); // 预期成功; assertEquals(0, v); - v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A-1"), -1); + v = baseAccount.setValue(Bytes.fromString("A"), TypedBytesValue.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.setValue(Bytes.fromString("A"), TypedBytesValue.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.setValue(Bytes.fromString("A"), TypedBytesValue.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..57711c42 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 @@ -132,7 +132,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(TypedBytesValue.fromInt64(issueAmount), BytesValue.class); byte[] reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class); assertArrayEquals(expectedRetnBytes, reallyRetnBytes); @@ -218,7 +218,7 @@ 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()).getValue(key, -1); System.out.printf("latest value=[%s] %s \r\n", latestValue.getType(), latestValue.getValue().toUTF8String()); 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..46ae96ae 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,9 @@ 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.VersioningKVEntry; import com.jd.blockchain.utils.io.BytesUtils; public class MerkleDataSetTest { 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 06bf987d..ff4d160f 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,13 +332,13 @@ 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()).getValue("K1", 0); - BytesValue v1_1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K1", + BytesValue v1_1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getValue("K1", 1); - BytesValue v2 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K2", + BytesValue v2 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getValue("K2", 0); - BytesValue v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K3", + BytesValue v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getValue("K3", 0); assertNotNull(v1_0); @@ -376,8 +376,8 @@ public class TransactionBatchProcessorTest { newBlock = newBlockEditor.prepare(); newBlockEditor.commit(); - BytesValue v1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K1"); - v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K3"); + BytesValue v1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getValue("K1"); + v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getValue("K3"); // k1 的版本仍然为1,没有更新; long k1_version = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()) 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..45d049ae 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 @@ -8,7 +8,7 @@ import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.utils.Bytes; @DataContract(code= DataCodes.ACCOUNT_HEADER) -public interface AccountHeader extends MerkleSnapshot{ +public interface AccountHeader { //extends MerkleSnapshot{ @DataField(order=1, primitiveType = PrimitiveType.BYTES) Bytes getAddress(); 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..7aa87c82 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(TypedBytesValue.fromText(value)); } public static BytesValueList singleLong(long value) { - return new BytesDataList(BytesData.fromInt64(value)); + return new BytesDataList(TypedBytesValue.fromInt64(value)); } public static BytesValueList singleInt(int value) { - return new BytesDataList(BytesData.fromInt32(value)); + return new BytesDataList(TypedBytesValue.fromInt32(value)); } public static BytesValueList singleBoolean(boolean value) { - return new BytesDataList(BytesData.fromBoolean(value)); + return new BytesDataList(TypedBytesValue.fromBoolean(value)); } } 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..3315c511 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 TypedBytesValue.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/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/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/TypedBytesValue.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedBytesValue.java new file mode 100644 index 00000000..6436f816 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedBytesValue.java @@ -0,0 +1,455 @@ +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 TypedBytesValue implements BytesValue { + + public static final BytesValue NIL = new TypedBytesValue(); + + private DataType type; + private Bytes value; + + private TypedBytesValue(DataType type, byte[] bytes) { + this.type = type; + this.value = new Bytes(bytes); + } + + private TypedBytesValue(DataType type, Bytes bytes) { + this.type = type; + this.value = bytes; + } + + private TypedBytesValue(BytesValue bytesValue) { + this.type = bytesValue.getType(); + this.value = bytesValue.getValue(); + } + + private TypedBytesValue() { + this.type = DataType.NIL; + } + + + @Override + public DataType getType() { + return this.type; + } + + @Override + public Bytes getValue() { + return this.value; + } + + public Object getTypedValue() { + 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 TypedBytesValue wrap(BytesValue value) { + return new TypedBytesValue(value); + } + + public static TypedBytesValue fromType(DataType type, byte[] value) { + return new TypedBytesValue(type, value); + } + + public static TypedBytesValue fromBytes(byte[] value) { + return new TypedBytesValue(DataType.BYTES, value); + } + + public static TypedBytesValue fromBytes(Bytes value) { + return new TypedBytesValue(DataType.BYTES, value); + } + + public static TypedBytesValue fromImage(byte[] value) { + return new TypedBytesValue(DataType.IMG, value); + } + + public static TypedBytesValue fromImage(Bytes value) { + return new TypedBytesValue(DataType.IMG, value); + } + + /** + * 以 UTF-8 编码从字符串转换为字节数组值; + * + * @param value + * @return + */ + public static TypedBytesValue fromText(String value) { + return new TypedBytesValue(DataType.TEXT, BytesUtils.toBytes(value)); + } + + public static TypedBytesValue fromJSON(String value) { + return new TypedBytesValue(DataType.JSON, BytesUtils.toBytes(value)); + } + + public static TypedBytesValue fromXML(String value) { + return new TypedBytesValue(DataType.XML, BytesUtils.toBytes(value)); + } + + public static TypedBytesValue fromInt32(int value) { + return new TypedBytesValue(DataType.INT32, BytesUtils.toBytes(value)); + } + + public static TypedBytesValue fromInt64(long value) { + return new TypedBytesValue(DataType.INT64, BytesUtils.toBytes(value)); + } + + public static TypedBytesValue fromInt16(short value) { + return new TypedBytesValue(DataType.INT16, BytesUtils.toBytes(value)); + } + + public static TypedBytesValue fromInt8(byte value) { + return new TypedBytesValue(DataType.INT8, BytesUtils.toBytes(value)); + } + + public static TypedBytesValue fromTimestamp(long value) { + return new TypedBytesValue(DataType.TIMESTAMP, BytesUtils.toBytes(value)); + } + + public static TypedBytesValue fromBoolean(boolean value) { + return new TypedBytesValue(DataType.BOOLEAN, BytesUtils.toBytes(value)); + } + + public static TypedBytesValue fromPubKey(PubKey pubKey) { + return new TypedBytesValue(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..0fcfd9ef --- /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 AccountHeader { + + 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 3ad9ed85..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_ACCOUNT_HEADER) -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/BooleanToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BooleanToBytesValueResolver.java index 0664fdb9..bcc688cf 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.TypedBytesValue; 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 TypedBytesValue.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..d455e471 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.TypedBytesValue; 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 TypedBytesValue.fromBytes((byte[]) value); } - return BytesData.fromBytes((Bytes) value); + return TypedBytesValue.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..6eec5e6f 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.TypedBytesValue; 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 TypedBytesValue.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..9ae9910e 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.TypedBytesValue; 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 TypedBytesValue.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..220d6121 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.TypedBytesValue; 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 TypedBytesValue.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..56da60bf 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.TypedBytesValue; 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 TypedBytesValue.fromJSON(valString); } // 暂不处理XML格式 - return BytesData.fromText(valString); + return TypedBytesValue.fromText(valString); } @Override 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..f0e1a18b 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.TypedBytesValue; 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 = TypedBytesValue.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 = TypedBytesValue.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 = TypedBytesValue.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 = TypedBytesValue.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 = TypedBytesValue.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 = TypedBytesValue.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 = TypedBytesValue.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 = TypedBytesValue.fromTimestamp(value); operation.set(key, bytesValue, expVersion); return this; } 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..271063ec 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.TypedBytesValue; 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(TypedBytesValue.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..c75eeed7 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.TypedBytesValue; 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", TypedBytesValue.fromText("zhangsan"), 9999L); KVData kvData2 = - new KVData("test2", BytesData.fromText("lisi"), 9990L); + new KVData("test2", TypedBytesValue.fromText("lisi"), 9990L); KVData kvData3 = - new KVData("test3", BytesData.fromText("wangwu"), 1990L); + new KVData("test3", TypedBytesValue.fromText("wangwu"), 1990L); data.set(kvData1); data.set(kvData2); data.set(kvData3); 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..8a914f7f 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.TypedBytesValue; 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, TypedBytesValue.fromBytes(value), expectedVersion); } @Test 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..ef63137f 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 @@ -151,7 +151,7 @@ public class ClientResolveUtil { String realValBase58 = valueObj.getJSONObject("value").getString("value"); String key = currWriteSetObj.getString("key"); DataType dataType = DataType.valueOf(typeStr); - BytesValue bytesValue = BytesData.fromType(dataType, Base58Utils.decode(realValBase58)); + BytesValue bytesValue = TypedBytesValue.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; } diff --git a/source/storage/storage-redis/src/main/java/com/jd/blockchain/storage/service/impl/redis/RedisVerioningStorage.java b/source/storage/storage-redis/src/main/java/com/jd/blockchain/storage/service/impl/redis/RedisVerioningStorage.java index 773b3748..da809c0a 100644 --- a/source/storage/storage-redis/src/main/java/com/jd/blockchain/storage/service/impl/redis/RedisVerioningStorage.java +++ b/source/storage/storage-redis/src/main/java/com/jd/blockchain/storage/service/impl/redis/RedisVerioningStorage.java @@ -1,8 +1,8 @@ package com.jd.blockchain.storage.service.impl.redis; -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.VersioningKVEntry; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; 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..40dba131 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.VersioningKVEntry; import com.jd.blockchain.utils.io.BytesUtils; /** 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..dfa26404 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.VersioningKVEntry; /** * Versioning Key-Value Storage @@ -40,7 +41,7 @@ public interface VersioningKVStorage extends BatchStorageService { * @param version * @return */ - VersioningKVEntry getEntry(Bytes key, long version); + VersioningKVEntry 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..8f334ca3 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.VersioningKVEntry; /** * {@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 VersioningKVEntry 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 VersioningKVEntry 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 VersioningKVEntry { 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..8bce7e32 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.VersioningKVEntry; import com.jd.blockchain.utils.io.BytesMap; public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage, KVStorageService, BytesMap { 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..4d1e1509 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.VersioningKVEntry; -public class VersioningKVData implements VersioningKVEntry { +public class VersioningKVData implements VersioningKVEntry { - 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..e9aee04b 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.VersioningKVEntry; import com.jd.blockchain.utils.io.BytesMap; public class VersioningKVStorageMap implements VersioningKVStorage, BytesMap { diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/RegionMap.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/RegionMap.java new file mode 100644 index 00000000..20b3da6f --- /dev/null +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/RegionMap.java @@ -0,0 +1,122 @@ +package com.jd.blockchain.utils; + +public abstract class RegionMap implements VersioningMap { + + private K region; + + private VersioningMap dataMap; + + public RegionMap(K region, VersioningMap dataMap) { + this.region = region; + this.dataMap = dataMap; + } + + @Override + public long setValue(K key, V value, long version) { + K dataKey = concatKey(region, key); + return dataMap.setValue(dataKey, value, version); + } + + @Override + public V getValue(K key, long version) { + K dataKey = concatKey(region, key); + return dataMap.getValue(dataKey, version); + } + + @Override + public V getValue(K key) { + K dataKey = concatKey(region, key); + return dataMap.getValue(dataKey); + } + + @Override + public long getVersion(K key) { + K dataKey = concatKey(region, key); + return dataMap.getVersion(dataKey); + } + + @Override + public VersioningKVEntry getDataEntry(K key) { + K dataKey = concatKey(region, key); + VersioningKVEntry entry = dataMap.getDataEntry(dataKey); + return new KVEntryWrapper(key, entry); + } + + @Override + public VersioningKVEntry getDataEntry(K key, long version) { + K dataKey = concatKey(region, key); + VersioningKVEntry entry = dataMap.getDataEntry(dataKey, version); + return new KVEntryWrapper(key, entry); + } + + /** + * 以指定的前缀组成新的key; + * + * @param prefix + * @param key + * @return + */ + protected abstract K concatKey(K prefix, K key); + + public static VersioningMap newRegion(Bytes region, VersioningMap dataMap) { + return new BytesKeyRegionMap(region, dataMap); + } + + public static VersioningMap newRegion(String region, VersioningMap dataMap) { + return new StringKeyRegionMap(region, dataMap); + } + + private static class BytesKeyRegionMap extends RegionMap { + + public BytesKeyRegionMap(Bytes region, VersioningMap dataMap) { + super(region, dataMap); + } + + @Override + protected Bytes concatKey(Bytes prefix, Bytes key) { + return prefix.concat(key); + } + + } + + private static class StringKeyRegionMap extends RegionMap { + + public StringKeyRegionMap(String region, VersioningMap dataMap) { + super(region, dataMap); + } + + @Override + protected String concatKey(String prefix, String key) { + return prefix + key; + } + + } + + private static class KVEntryWrapper implements VersioningKVEntry { + + private K key; + + private VersioningKVEntry entry; + + public KVEntryWrapper(K key, VersioningKVEntry entry) { + this.key = key; + this.entry = entry; + } + + @Override + public K getKey() { + return key; + } + + @Override + public long getVersion() { + return entry.getVersion(); + } + + @Override + public V getValue() { + return entry.getValue(); + } + + } +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/VersioningKVEntry.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/VersioningKVEntry.java new file mode 100644 index 00000000..b92eda41 --- /dev/null +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/VersioningKVEntry.java @@ -0,0 +1,17 @@ +package com.jd.blockchain.utils; + +/** + * 版本化的键值数据项; + * + * @author huanghaiquan + * + */ +public interface VersioningKVEntry{ + + K getKey(); + + long getVersion(); + + V getValue(); + +} \ No newline at end of file diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/VersioningMap.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/VersioningMap.java new file mode 100644 index 00000000..84d198a9 --- /dev/null +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/VersioningMap.java @@ -0,0 +1,116 @@ +package com.jd.blockchain.utils; + +public interface VersioningMap { + +// 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(String key, byte[] value, long 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, 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 +// */ +// byte[] getValue(String key, 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 latest version's value; +// * +// * @param key +// * @return return null if not exist; +// */ +// byte[] getValue(String key); + + /** + * Return the latest version's value; + * + * @param key + * @return return null if not exist; + */ + V getValue(K key); + +// /** +// * Return the latest version entry associated the specified key; If the key +// * doesn't exist, then return -1; +// * +// * @param key +// * @return +// */ +// long getVersion(String key); + + /** + * Return the latest version entry associated the specified key; If the key + * doesn't exist, then return -1; + * + * @param key + * @return + */ + long getVersion(K key); + + /** + * + * @param key + * @return Null if the key doesn't exist! + */ + VersioningKVEntry getDataEntry(K key); + + VersioningKVEntry getDataEntry(K key, long version); + +} \ No newline at end of file