diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountDecorator.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountDecorator.java index a0fddbe1..8e30be95 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountDecorator.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountDecorator.java @@ -2,11 +2,11 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.HashProof; import com.jd.blockchain.ledger.MerkleSnapshot; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.VersioningMap; +import com.jd.blockchain.utils.Dataset; public class AccountDecorator implements LedgerAccount, HashProvable, MerkleSnapshot{ @@ -16,7 +16,7 @@ public class AccountDecorator implements LedgerAccount, HashProvable, MerkleSnap this.mklAccount = mklAccount; } - protected VersioningMap getHeaders() { + protected Dataset getHeaders() { return mklAccount.getHeaders(); } @@ -37,7 +37,7 @@ public class AccountDecorator implements LedgerAccount, HashProvable, MerkleSnap } @Override - public VersioningMap getDataset() { + public Dataset getDataset() { return mklAccount.getDataset(); } 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 514ddf0f..b0f8104d 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 @@ -8,9 +8,9 @@ import com.jd.blockchain.utils.Bytes; public class ContractAccount extends AccountDecorator implements ContractInfo { - private static final Bytes CONTRACT_INFO_PREFIX = Bytes.fromString("INFO" + LedgerConsts.KEY_SEPERATOR); + private static final String CONTRACT_INFO_PREFIX = "INFO" + LedgerConsts.KEY_SEPERATOR; - private static final Bytes CHAIN_CODE_KEY = Bytes.fromString("CHAIN-CODE"); + private static final String CHAIN_CODE_KEY = "CHAIN-CODE"; public ContractAccount(MerkleAccount mklAccount) { super(mklAccount); @@ -35,7 +35,7 @@ public class ContractAccount extends AccountDecorator implements ContractInfo { // } public long setChaincode(byte[] chaincode, long version) { - BytesValue bytesValue = TypedValue.fromBytes(chaincode); + TypedValue bytesValue = TypedValue.fromBytes(chaincode); return getHeaders().setValue(CHAIN_CODE_KEY, bytesValue, version); } @@ -51,22 +51,22 @@ public class ContractAccount extends AccountDecorator implements ContractInfo { return getHeaders().getVersion(CHAIN_CODE_KEY); } - public long setProperty(Bytes key, String value, long version) { - BytesValue bytesValue = TypedValue.fromText(value); + public long setProperty(String key, String value, long version) { + TypedValue bytesValue = TypedValue.fromText(value); return getHeaders().setValue(encodePropertyKey(key), bytesValue, version); } - public String getProperty(Bytes key) { + public String getProperty(String key) { BytesValue bytesValue = getHeaders().getValue(encodePropertyKey(key)); return TypedValue.wrap(bytesValue).stringValue(); } - public String getProperty(Bytes key, long version) { + public String getProperty(String key, long version) { BytesValue bytesValue = getHeaders().getValue(encodePropertyKey(key), version); return TypedValue.wrap(bytesValue).stringValue(); } - private Bytes encodePropertyKey(Bytes key) { + private String encodePropertyKey(String key) { return CONTRACT_INFO_PREFIX.concat(key); } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAccount.java index 02d6c7a1..f57777ed 100644 --- 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 @@ -1,14 +1,13 @@ 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; +import com.jd.blockchain.ledger.TypedValue; +import com.jd.blockchain.utils.Dataset; public interface LedgerAccount { BlockchainIdentity getID(); - VersioningMap getDataset(); + Dataset getDataset(); } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java index 267d8fbc..b965f842 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java @@ -29,16 +29,16 @@ import com.jd.blockchain.utils.QueryUtil; public class LedgerQueryService implements BlockchainQueryService { private static final KVDataEntry[] EMPTY_ENTRIES = new KVDataEntry[0]; - + private HashDigest[] ledgerHashs; private LedgerQuery ledger; public LedgerQueryService(LedgerQuery ledger) { this.ledger = ledger; - this.ledgerHashs = new HashDigest[] {ledger.getHash()}; + this.ledgerHashs = new HashDigest[] { ledger.getHash() }; } - + private void checkLedgerHash(HashDigest ledgerHash) { if (!ledgerHashs[0].equals(ledgerHash)) { throw new LedgerException("Unsupport cross chain query!"); @@ -59,7 +59,7 @@ public class LedgerQueryService implements BlockchainQueryService { ledgerInfo.setLatestBlockHeight(ledger.getLatestBlockHeight()); return ledgerInfo; } - + @Override public LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash) { checkLedgerHash(ledgerHash); @@ -345,12 +345,12 @@ public class LedgerQueryService implements BlockchainQueryService { if (ver < 0) { entries[i] = new KVDataObject(keys[i], -1, null); } else { - if (dataAccount.getDataset().getDataEntriesTotalCount() == 0 - || dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null) { + if (dataAccount.getDataset().getDataCount() == 0 + || dataAccount.getDataset().getValue(keys[i], ver) == null) { // is the address is not exist; the result is null; entries[i] = new KVDataObject(keys[i], -1, null); } else { - BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); + BytesValue value = dataAccount.getDataset().getValue(keys[i], ver); entries[i] = new KVDataObject(keys[i], ver, value); } } @@ -366,8 +366,8 @@ public class LedgerQueryService implements BlockchainQueryService { DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); - int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataEntriesTotalCount()); - return dataAccount.getDataEntries(pages[0], pages[1]); + int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataset().getDataCount()); + return dataAccount.getDataset()..getDataEntries(pages[0], pages[1]); } @Override @@ -377,7 +377,7 @@ public class LedgerQueryService implements BlockchainQueryService { DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); - return dataAccount.getDataEntriesTotalCount(); + return dataAccount.getDataset().getDataCount(); } @Override 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 63fcc445..384b39bd 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 @@ -14,9 +14,11 @@ import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.Dataset; +import com.jd.blockchain.utils.DatasetHelper; +import com.jd.blockchain.utils.DatasetHelper.DataChangedListener; +import com.jd.blockchain.utils.DatasetHelper.TypeMapper; import com.jd.blockchain.utils.Transactional; -import com.jd.blockchain.utils.VersioningKVEntry; -import com.jd.blockchain.utils.VersioningMap; /** * 事务性的基础账户; @@ -29,21 +31,25 @@ public class MerkleAccount implements LedgerAccount, HashProvable, MerkleSnapsho private static final Bytes HEADER_PREFIX = Bytes.fromString("HD/"); private static final Bytes DATA_PREFIX = Bytes.fromString("DT/"); - private static final Bytes KEY_PUBKEY = Bytes.fromString("PUBKEY"); - private static final Bytes KEY_HEADER_ROOT = Bytes.fromString("HEADER"); private static final Bytes KEY_DATA_ROOT = Bytes.fromString("DATA"); + private static final String KEY_PUBKEY = "PUBKEY"; + private BlockchainIdentity accountID; - private MerkleDataSet rootDS; + private MerkleDataSet rootDataset; + + private MerkleDataSet headerDataset; - private MerkleDatasetAdapter headerDS; + private MerkleDataSet dataDataset; - private MerkleDatasetAdapter dataDS; + private Dataset typedHeader; - protected long version; + private Dataset typedData; + + private long version; /** * Create a new Account with the specified address and pubkey;
@@ -103,40 +109,58 @@ public class MerkleAccount implements LedgerAccount, HashProvable, MerkleSnapsho */ private MerkleAccount(Bytes address, PubKey pubKey, long version, HashDigest rootHash, CryptoSetting cryptoSetting, Bytes keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) { - // 初始化账户的身份; - this.accountID = new AutoloadingID(address, pubKey); - this.version = version; // 加载“根数据集” - this.rootDS = new MerkleDataSet(rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); + this.rootDataset = new MerkleDataSet(rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); // 初始化数据修改监听器; - DataChangedListener dataChangedListener = new DataChangedListener() { + DataChangedListener dataChangedListener = new DataChangedListener() { + @Override + public void onChanged(String key, TypedValue value, long expectedVersion, long newVersion) { + onUpdated(key, value, expectedVersion, newVersion); + } + }; + + TypeMapper valueMapper = new TypeMapper() { + + @Override + public byte[] encode(TypedValue t2) { + return BinaryProtocol.encode(t2, BytesValue.class); + } + @Override - public void onChanged(Bytes key, BytesValue value, long newVersion) { - onUpdated(keyPrefix, value, newVersion); + public TypedValue decode(byte[] t1) { + BytesValue v = BinaryProtocol.decodeAs(t1, BytesValue.class); + return TypedValue.wrap(v); } }; // 加载“头数据集”; HashDigest headerRoot = loadHeaderRoot(); Bytes headerPrefix = keyPrefix.concat(HEADER_PREFIX); - MerkleDataSet headerDataset = new MerkleDataSet(headerRoot, cryptoSetting, headerPrefix, exStorage, verStorage, + this.headerDataset = new MerkleDataSet(headerRoot, cryptoSetting, headerPrefix, exStorage, verStorage, readonly); - this.headerDS = new MerkleDatasetAdapter(headerDataset, dataChangedListener); + this.typedHeader = DatasetHelper.listen(DatasetHelper.map(headerDataset, valueMapper), 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); + this.dataDataset = new MerkleDataSet(dataRoot, cryptoSetting, dataPrefix, exStorage, verStorage, readonly); + this.typedData = DatasetHelper.listen(DatasetHelper.map(dataDataset, valueMapper), dataChangedListener); + // 初始化账户的身份; + if (pubKey == null) { + if (version < 0) { + throw new IllegalArgumentException("Specified a null PubKey for newly Account!"); + } + pubKey = loadPubKey(); + } + this.accountID = new AccountID(address, pubKey); } private HashDigest loadHeaderRoot() { - byte[] hashBytes = rootDS.getValue(KEY_HEADER_ROOT); + byte[] hashBytes = rootDataset.getValue(KEY_HEADER_ROOT); if (hashBytes == null) { return null; } @@ -144,7 +168,7 @@ public class MerkleAccount implements LedgerAccount, HashProvable, MerkleSnapsho } private HashDigest loadDataRoot() { - byte[] hashBytes = rootDS.getValue(KEY_DATA_ROOT); + byte[] hashBytes = rootDataset.getValue(KEY_DATA_ROOT); if (hashBytes == null) { return null; } @@ -152,11 +176,11 @@ public class MerkleAccount implements LedgerAccount, HashProvable, MerkleSnapsho } private long getHeaderRootVersion() { - return rootDS.getVersion(KEY_HEADER_ROOT); + return rootDataset.getVersion(KEY_HEADER_ROOT); } private long getDataRootVersion() { - return rootDS.getVersion(KEY_DATA_ROOT); + return rootDataset.getVersion(KEY_DATA_ROOT); } public Bytes getAddress() { @@ -172,13 +196,13 @@ public class MerkleAccount implements LedgerAccount, HashProvable, MerkleSnapsho return accountID; } - protected VersioningMap getHeaders() { - return headerDS; + protected Dataset getHeaders() { + return typedHeader; } @Override - public VersioningMap getDataset() { - return dataDS; + public Dataset getDataset() { + return typedData; } /* @@ -188,16 +212,16 @@ public class MerkleAccount implements LedgerAccount, HashProvable, MerkleSnapsho */ @Override public HashDigest getRootHash() { - return rootDS.getRootHash(); + return rootDataset.getRootHash(); } @Override public HashProof getProof(Bytes key) { - MerkleProof dataProof = dataDS.getDataset().getProof(key); + MerkleProof dataProof = dataDataset.getProof(key); if (dataProof == null) { return null; } - MerkleProof rootProof = rootDS.getProof(KEY_DATA_ROOT); + MerkleProof rootProof = rootDataset.getProof(KEY_DATA_ROOT); if (rootProof == null) { return null; } @@ -212,11 +236,7 @@ public class MerkleAccount implements LedgerAccount, HashProvable, MerkleSnapsho * @return */ public boolean isReadonly() { - return dataDS.getDataset().isReadonly(); - } - - public long getDataCount() { - return dataDS.getDataset().getDataCount(); + return dataDataset.isReadonly() || headerDataset.isReadonly(); } /** @@ -225,7 +245,7 @@ public class MerkleAccount implements LedgerAccount, HashProvable, MerkleSnapsho * @param pubKey */ private void initPubKey(PubKey pubKey) { - long v = headerDS.setValue(KEY_PUBKEY, TypedValue.fromPubKey(pubKey), -1); + long v = typedHeader.setValue(KEY_PUBKEY, TypedValue.fromPubKey(pubKey), -1); if (v < 0) { throw new LedgerException("PubKey storage conflict!"); } @@ -237,8 +257,8 @@ public class MerkleAccount implements LedgerAccount, HashProvable, MerkleSnapsho * @return */ private PubKey loadPubKey() { - BytesValue bytesValue = headerDS.getValue(KEY_PUBKEY); - return TypedValue.wrap(bytesValue).pubKeyValue(); + TypedValue value = typedHeader.getValue(KEY_PUBKEY); + return value.pubKeyValue(); } /** @@ -248,7 +268,7 @@ public class MerkleAccount implements LedgerAccount, HashProvable, MerkleSnapsho * @param value * @param newVersion */ - protected void onUpdated(Bytes key, BytesValue value, long newVersion) { + protected void onUpdated(String key, TypedValue value, long expectedVersion, long newVersion) { } /** @@ -266,44 +286,44 @@ public class MerkleAccount implements LedgerAccount, HashProvable, MerkleSnapsho @Override public boolean isUpdated() { - return dataDS.getDataset().isUpdated() || headerDS.getDataset().isUpdated() || rootDS.isUpdated(); + return headerDataset.isUpdated() || dataDataset.isUpdated() || rootDataset.isUpdated(); } @Override public void commit() { - if (headerDS.dataset.isUpdated()) { - headerDS.getDataset().commit(); + if (headerDataset.isUpdated()) { + headerDataset.commit(); long version = getHeaderRootVersion(); - rootDS.setValue(KEY_HEADER_ROOT, headerDS.dataset.getRootHash().toBytes(), version); + rootDataset.setValue(KEY_HEADER_ROOT, headerDataset.getRootHash().toBytes(), version); } - if (dataDS.dataset.isUpdated()) { + if (dataDataset.isUpdated()) { long version = getDataRootVersion(); - dataDS.getDataset().commit(); - rootDS.setValue(KEY_DATA_ROOT, dataDS.dataset.getRootHash().toBytes(), version); + dataDataset.commit(); + rootDataset.setValue(KEY_DATA_ROOT, dataDataset.getRootHash().toBytes(), version); } - if (rootDS.isUpdated()) { - rootDS.commit(); - this.version = onCommited(rootDS.getRootHash(), version); + if (rootDataset.isUpdated()) { + rootDataset.commit(); + this.version = onCommited(rootDataset.getRootHash(), version); } } @Override public void cancel() { - headerDS.getDataset().cancel(); - dataDS.getDataset().cancel(); - rootDS.cancel(); + headerDataset.cancel(); + dataDataset.cancel(); + rootDataset.cancel(); } // ---------------------- - private class AutoloadingID implements BlockchainIdentity { + private class AccountID implements BlockchainIdentity { private Bytes address; private PubKey pubKey; - public AutoloadingID(Bytes address, PubKey pubKey) { + public AccountID(Bytes address, PubKey pubKey) { this.address = address; this.pubKey = pubKey; } @@ -315,155 +335,201 @@ public class MerkleAccount implements LedgerAccount, HashProvable, MerkleSnapsho @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); - + public long getVersion() { + return version; } - 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); - } - - } +// private static class MerkleDatasetAdapter implements Dataset { +// +// private static DataChangedListener NULL_LISTENER = new DataChangedListener() { +// @Override +// public void onChanged(Bytes key, BytesValue value, long newVersion) { +// } +// }; +// +// private DataChangedListener changedListener; +// +// private MerkleDataSet dataset; +// +// public MerkleDataSet getDataset() { +// return dataset; +// } +// +// @SuppressWarnings("unused") +// public MerkleDatasetAdapter(MerkleDataSet dataset) { +// this(dataset, NULL_LISTENER); +// } +// +// public MerkleDatasetAdapter(MerkleDataSet dataset, DataChangedListener listener) { +// this.dataset = dataset; +// this.changedListener = listener == null ? NULL_LISTENER : listener; +// } +// +// @Override +// public DataEntry getDataEntry(String key) { +// return new VersioningKVEntryWraper(dataset.getDataEntry(Bytes.fromString(key))); +// } +// +// @Override +// public DataEntry getDataEntry(String key, long version) { +// return new VersioningKVEntryWraper(dataset.getDataEntry(Bytes.fromString(key), version)); +// } +// +// /** +// * Create or update the value associated the specified key if the version +// * checking is passed.
+// * +// * The value of the key will be updated only if it's latest version equals the +// * specified version argument.
+// * If the key doesn't exist, the version checking will be ignored, and key will +// * be created with a new sequence number as id.
+// * It also could specify the version argument to -1 to ignore the version +// * checking. +// *

+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// * +// * @param key The key of data; +// * @param value The value of data; +// * @param version The expected version of the key. +// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then +// * return -1; +// */ +// @Override +// public long setValue(Bytes key, BytesValue value, long version) { +// byte[] bytesValue = BinaryProtocol.encode(value, BytesValue.class); +// long v = dataset.setValue(key, bytesValue, version); +// if (v > -1) { +// changedListener.onChanged(key, value, v); +// } +// return v; +// } +// +// /** +// * Return the latest version entry associated the specified key; If the key +// * doesn't exist, then return -1; +// * +// * @param key +// * @return +// */ +// @Override +// public long getVersion(Bytes key) { +// return dataset.getVersion(key); +// } +// +// /** +// * return the latest version's value; +// * +// * @param key +// * @return return null if not exist; +// */ +// @Override +// public BytesValue getValue(Bytes key) { +// byte[] bytesValue = dataset.getValue(key); +// if (bytesValue == null) { +// return null; +// } +// return BinaryProtocol.decodeAs(bytesValue, BytesValue.class); +// } +// +// /** +// * Return the specified version's value; +// * +// * @param key +// * @param version +// * @return return null if not exist; +// */ +// @Override +// public BytesValue getValue(Bytes key, long version) { +// byte[] bytesValue = dataset.getValue(key, version); +// if (bytesValue == null) { +// return null; +// } +// return BinaryProtocol.decodeAs(bytesValue, BytesValue.class); +// } +// +// @Override +// public long getDataCount() { +// return dataset.getDataCount(); +// } +// +// @Override +// public long setValue(String key, BytesValue value, long version) { +// byte[] bytesValue = BinaryProtocol.encode(value, BytesValue.class); +// return dataset.setValue(key, bytesValue, version); +// } +// +// @Override +// public BytesValue getValue(String key, long version) { +// byte[] bytesValue = dataset.getValue(key, version); +// if (bytesValue == null) { +// return null; +// } +// return BinaryProtocol.decodeAs(bytesValue, BytesValue.class); +// } +// +// @Override +// public BytesValue getValue(String key) { +// byte[] bytesValue = dataset.getValue(key); +// if (bytesValue == null) { +// return null; +// } +// return BinaryProtocol.decodeAs(bytesValue, BytesValue.class); +// } +// +// @Override +// public long getVersion(String key) { +// return dataset.getVersion(key); +// } +// +// @Override +// public DataEntry getDataEntry(String key) { +// return new VersioningKVEntryWraper(dataset.getDataEntry(key)); +// } +// +// @Override +// public DataEntry getDataEntry(String key, long version) { +// return new VersioningKVEntryWraper(dataset.getDataEntry(key, version)); +// } +// } + +// private static interface DataChangedListener { +// +// void onChanged(Bytes key, BytesValue value, long newVersion); +// +// } + +// private static class VersioningKVEntryWraper implements DataEntry { +// +// private DataEntry kv; +// +// public VersioningKVEntryWraper(DataEntry kv) { +// this.kv = kv; +// } +// +// @Override +// public String getKey() { +// return kv.getKey().toUTF8String(); +// } +// +// @Override +// public long getVersion() { +// return kv.getVersion(); +// } +// +// @Override +// public BytesValue getValue() { +// return BinaryProtocol.decodeAs(kv.getValue(), BytesValue.class); +// } +// +// } } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java index 3768c13f..6952c89e 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java @@ -3,27 +3,25 @@ package com.jd.blockchain.ledger.core; import java.util.HashMap; import java.util.Map; -import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.BlockchainIdentityData; -import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.LedgerException; import com.jd.blockchain.ledger.MerkleProof; import com.jd.blockchain.ledger.MerkleSnapshot; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; import com.jd.blockchain.utils.Transactional; public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQuery { -// private static final Bytes ACCOUNT_ROOT_PREFIX = Bytes.fromString("ROOT/"); - static { DataContractRegistry.register(MerkleSnapshot.class); DataContractRegistry.register(BlockchainIdentity.class); @@ -92,28 +90,14 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ @Override public BlockchainIdentity[] getHeaders(int fromIndex, int count) { - byte[][] results = merkleDataset.getLatestValues(fromIndex, count); + DataEntry[] results = merkleDataset.getLatestDataEntries(fromIndex, count); - BlockchainIdentity[] accounts = new BlockchainIdentity[results.length]; + BlockchainIdentity[] ids = new BlockchainIdentity[results.length]; for (int i = 0; i < results.length; i++) { - accounts[i] = deserialize(results[i]); + InnerMerkleAccount account = createAccount(results[i].getKey(), new HashDigest(results[i].getValue()), results[i].getVersion(), true); + ids[i] = account.getID(); } - return accounts; - } - - // private VersioningAccount deserialize(byte[] txBytes) { - //// return BinaryEncodingUtils.decode(txBytes, null, Account.class); - // AccountHeaderData accInfo = BinaryEncodingUtils.decode(txBytes); - //// return new BaseAccount(accInfo.getAddress(), accInfo.getPubKey(), null, - // cryptoSetting, - //// baseExStorage, baseVerStorage, true, accessPolicy); - // return new VersioningAccount(accInfo.getAddress(), accInfo.getPubKey(), - // accInfo.getRootHash(), cryptoSetting, - // keyPrefix, baseExStorage, baseVerStorage, true, accessPolicy, accInfo.); - // } - - private BlockchainIdentity deserialize(byte[] txBytes) { - return BinaryProtocol.decodeAs(txBytes, BlockchainIdentity.class); + return ids; } /** @@ -158,9 +142,9 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ /** * 返回指定账户的版本;
* 如果账户已经注册,则返回该账户的最新版本,值大于等于 0;
- * 如果账户不存在,则返回 -1;
- * 如果指定的账户已经注册(通过 {@link #register(String, PubKey)} 方法),但尚未提交(通过 - * {@link #commit()} 方法),此方法对该账户仍然返回 0; + * 如果账户不存在,则返回 -1;
+ * 如果账户已经注册(通过 {@link #register(String, PubKey)} 方法),但尚未提交(通过 {@link #commit()} + * 方法),则返回 -1;
* * @param address * @return @@ -169,7 +153,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ InnerMerkleAccount acc = latestAccountsCache.get(address); if (acc != null) { // 已注册尚未提交,也返回 -1; - return acc.version == -1 ? 0 : acc.version; + return acc.getVersion(); } return merkleDataset.getVersion(address); @@ -189,7 +173,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ InnerMerkleAccount acc = latestAccountsCache.get(address); if (acc != null && version == -1) { return acc; - } else if (acc != null && acc.version == version) { + } else if (acc != null && acc.getVersion() == version) { return acc; } @@ -203,7 +187,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ } // 如果是不存在的,或者刚刚新增未提交的账户,则前面一步查询到的 latestVersion 小于 0, 代码不会执行到此; - if (acc != null && acc.version != latestVersion) { + if (acc != null && acc.getVersion() != latestVersion) { // 当执行到此处时,并且缓冲列表中缓存了最新的版本, // 如果当前缓存的最新账户的版本和刚刚从存储中检索得到的最新版本不一致,可能存在外部的并发更新,这超出了系统设计的逻辑; @@ -256,7 +240,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ InnerMerkleAccount cachedAcc = latestAccountsCache.get(address); if (cachedAcc != null) { - if (cachedAcc.version < 0) { + if (cachedAcc.getVersion() < 0) { // 同一个新账户已经注册,但尚未提交,所以重复注册不会引起任何变化; return cachedAcc; } @@ -272,14 +256,6 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ throw new LedgerException("Account Registering was rejected for the access policy!"); } - // String prefix = address.concat(LedgerConsts.KEY_SEPERATOR); - // ExPolicyKVStorage accExStorage = PrefixAppender.prefix(prefix, - // baseExStorage); - // VersioningKVStorage accVerStorage = PrefixAppender.prefix(prefix, - // baseVerStorage); - // BaseAccount accDS = createInstance(address, pubKey, cryptoSetting, - // accExStorage, accVerStorage); - Bytes prefix = keyPrefix.concat(address); InnerMerkleAccount acc = createInstance(accountId, cryptoSetting, prefix); latestAccountsCache.put(address, acc); @@ -300,17 +276,21 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ } private InnerMerkleAccount loadAccount(Bytes address, boolean readonly, long version) { - // prefix; - Bytes prefix = keyPrefix.concat(address); byte[] rootHashBytes = merkleDataset.getValue(address, version); if (rootHashBytes == null) { return null; } HashDigest rootHash = new HashDigest(rootHashBytes); + return createAccount(address, rootHash, version, readonly); + } + + private InnerMerkleAccount createAccount(Bytes address,HashDigest rootHash, long version, boolean readonly) { + // prefix; + Bytes prefix = keyPrefix.concat(address); + return new InnerMerkleAccount(address, version, rootHash, cryptoSetting, prefix, baseExStorage, baseVerStorage, readonly); - } // TODO:优化:区块链身份(地址+公钥)与其Merkle树根哈希分开独立存储; @@ -324,14 +304,9 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ */ private long saveAccount(InnerMerkleAccount account) { // 提交更改,更新哈希; - long version = account.version; account.commit(); - long newVersion = merkleDataset.setValue(account.getAddress(), account.getRootHash().toBytes(), version); - if (newVersion < 0) { - // Update fail; - throw new LedgerException("Account updating fail! --[Address=" + account.getAddress() + "]"); - } - return newVersion; + + return account.getVersion(); } @Override @@ -347,7 +322,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ try { for (InnerMerkleAccount acc : latestAccountsCache.values()) { // updated or new created; - if (acc.isUpdated() || acc.version < 0) { + if (acc.isUpdated() || acc.getVersion() < 0) { saveAccount(acc); } } @@ -394,10 +369,20 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ } @Override - protected void onUpdated(Bytes key, BytesValue value, long newVersion) { + protected void onUpdated(String key, TypedValue value, long expectedVersion, long newVersion) { updated = true; } + @Override + protected long onCommited(HashDigest newRootHash, long currentVersion) { + long newVersion = merkleDataset.setValue(this.getAddress(), newRootHash.toBytes(), currentVersion); + if (newVersion < 0) { + // Update fail; + throw new LedgerException("Account updating fail! --[Address=" + this.getAddress() + "]"); + } + return newVersion; + } + } } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataCluster.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataCluster.java index dd3836f7..5865c3fd 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataCluster.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataCluster.java @@ -10,7 +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; +import com.jd.blockchain.utils.Dataset; public class MerkleDataCluster implements Transactional, MerkleSnapshot { 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 75894d0f..15de35b5 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java @@ -2,11 +2,11 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.ledger.MerkleProof; import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.VersioningKVEntry; +import com.jd.blockchain.utils.DataEntry; public interface MerkleDataEntry { - VersioningKVEntry getData(); + DataEntry getData(); MerkleProof getProof(); } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java index 896a8f37..2e31c27e 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 @@ -12,8 +12,8 @@ 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.DataEntry; +import com.jd.blockchain.utils.Dataset; import com.jd.blockchain.utils.io.BytesUtils; /** @@ -24,7 +24,7 @@ import com.jd.blockchain.utils.io.BytesUtils; * @author huanghaiquan * */ -public class MerkleDataSet implements Transactional, MerkleProvable, VersioningMap { +public class MerkleDataSet implements Transactional, MerkleProvable, Dataset { /** * 4 MB MaxSize of value; @@ -70,6 +70,18 @@ public class MerkleDataSet implements Transactional, MerkleProvable, VersioningM */ public MerkleDataSet(CryptoSetting setting, String keyPrefix, ExPolicyKVStorage exPolicyStorage, VersioningKVStorage versioningStorage) { + this(setting, Bytes.fromString(keyPrefix), exPolicyStorage, versioningStorage); + } + + /** + * 创建一个新的 MerkleDataSet; + * + * @param setting 密码设置; + * @param exPolicyStorage 默克尔树的存储; + * @param versioningStorage 数据的存储; + */ + public MerkleDataSet(CryptoSetting setting, Bytes keyPrefix, ExPolicyKVStorage exPolicyStorage, + VersioningKVStorage versioningStorage) { // 缓冲对KV的写入; this.bufferedStorage = new BufferedKVStorage(exPolicyStorage, versioningStorage, false); @@ -78,20 +90,34 @@ public class MerkleDataSet implements Transactional, MerkleProvable, VersioningM // bufferedStorage); // this.snStorage = PrefixAppender.prefix(SN_PREFIX, (ExPolicyKVStorage) // bufferedStorage); - snKeyPrefix = Bytes.fromString(keyPrefix + SN_PREFIX); - dataKeyPrefix = Bytes.fromString(keyPrefix + DATA_PREFIX); + snKeyPrefix = keyPrefix.concat(SN_PREFIX); + dataKeyPrefix = keyPrefix.concat(DATA_PREFIX); this.valueStorage = bufferedStorage; this.snStorage = bufferedStorage; // MerkleTree 本身是可缓冲的; // ExPolicyKVStorage merkleTreeStorage = // PrefixAppender.prefix(MERKLE_TREE_PREFIX, exPolicyStorage); - merkleKeyPrefix = Bytes.fromString(keyPrefix + MERKLE_TREE_PREFIX); + merkleKeyPrefix = keyPrefix.concat(MERKLE_TREE_PREFIX); ExPolicyKVStorage merkleTreeStorage = exPolicyStorage; this.merkleTree = new MerkleTree(setting, merkleKeyPrefix, merkleTreeStorage); this.snGenerator = new MerkleSequenceSNGenerator(merkleTree); } + /** + * 从指定的 Merkle 根构建的 MerkleDataSet; + * + * @param dataStorage + * @param defaultMerkleHashAlgorithm + * @param verifyMerkleHashOnLoad + * @param merkleTreeStorage + * @param snGenerator + */ + public MerkleDataSet(HashDigest merkleRootHash, CryptoSetting setting, String keyPrefix, + ExPolicyKVStorage exPolicyStorage, VersioningKVStorage versioningStorage, boolean readonly) { + this(merkleRootHash, setting, Bytes.fromString(keyPrefix), exPolicyStorage, versioningStorage, readonly); + } + /** * 从指定的 Merkle 根构建的 MerkleDataSet; * @@ -131,6 +157,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable, VersioningM this.readonly = true; } + @Override public long getDataCount() { return merkleTree.getDataCount(); } @@ -155,7 +182,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable, VersioningM return values; } - public VersioningKVEntry[] getLatestDataEntries(int fromIndex, int count) { + public DataEntry[] getLatestDataEntries(int fromIndex, int count) { if (count > LedgerConsts.MAX_LIST_COUNT) { throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); } @@ -163,7 +190,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable, VersioningM throw new IllegalArgumentException("Index out of bound!"); } @SuppressWarnings("unchecked") - VersioningKVEntry[] values = new VersioningKVEntry[count]; + DataEntry[] values = new DataEntry[count]; byte[] bytesValue; for (int i = 0; i < count; i++) { MerkleDataNode dataNode = merkleTree.getData(fromIndex + i); @@ -194,7 +221,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable, VersioningM */ public String getKeyAtIndex(int fromIndex) { MerkleDataNode dataNode = merkleTree.getData(fromIndex); - //TODO: 未去掉前缀; + // TODO: 未去掉前缀; return dataNode.getKey().toUTF8String(); } @@ -428,8 +455,9 @@ public class MerkleDataSet implements Transactional, MerkleProvable, VersioningM return getMerkleVersion(key); } -// public VersioningKVEntry getDataEntry(String key) { -// return getDataEntry(Bytes.fromString(key)); +// @Override +// public VersioningKVEntry getDataEntry(String key) { +// return getDataEntry(key, -1); // } /** @@ -438,21 +466,30 @@ public class MerkleDataSet implements Transactional, MerkleProvable, VersioningM * @return Null if the key doesn't exist! */ @Override - public VersioningKVEntry getDataEntry(Bytes key) { - long latestVersion = getMerkleVersion(key); - if (latestVersion < 0) { - return null; - } - Bytes dataKey = encodeDataKey(key); - byte[] value = valueStorage.get(dataKey, latestVersion); - if (value == null) { - return null; - } - return new VersioningKVData(key, latestVersion, value); + public DataEntry getDataEntry(Bytes key) { + return getDataEntry(key, -1); } +// @Override +// public VersioningKVEntry getDataEntry(String key, long version) { +// Bytes keyBytes = Bytes.fromString(key); +// long latestVersion = getMerkleVersion(keyBytes); +// if (latestVersion < 0 || version > latestVersion) { +// // key not exist, or the specified version is out of the latest version indexed +// // by the current merkletree; +// return null; +// } +// version = version < 0 ? latestVersion : version; +// Bytes dataKey = encodeDataKey(keyBytes); +// byte[] value = valueStorage.get(dataKey, version); +// if (value == null) { +// return null; +// } +// return new VersioningKVData(key, version, value); +// } + @Override - public VersioningKVEntry getDataEntry(Bytes key, long version) { + public DataEntry getDataEntry(Bytes key, long version) { long latestVersion = getMerkleVersion(key); if (latestVersion < 0 || version > latestVersion) { // key not exist, or the specified version is out of the latest version indexed @@ -469,7 +506,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable, VersioningM } public MerkleDataEntry getMerkleEntry(Bytes key, long version) { - VersioningKVEntry dataEntry = getDataEntry(key, version); + DataEntry dataEntry = getDataEntry(key, version); if (dataEntry == null) { return null; } @@ -478,7 +515,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable, VersioningM } public MerkleDataEntry getMerkleEntry(Bytes key) { - VersioningKVEntry dataEntry = getDataEntry(key); + DataEntry dataEntry = getDataEntry(key); if (dataEntry == null) { return null; } @@ -505,23 +542,23 @@ public class MerkleDataSet implements Transactional, MerkleProvable, VersioningM } /** - * A wrapper for {@link VersioningKVEntry} and {@link MerkleProof}; + * A wrapper for {@link DataEntry} and {@link MerkleProof}; * * @author huanghaiquan * */ private static class MerkleDataEntryWrapper implements MerkleDataEntry { - private VersioningKVEntry data; + private DataEntry data; private MerkleProof proof; - public MerkleDataEntryWrapper(VersioningKVEntry data, MerkleProof proof) { + public MerkleDataEntryWrapper(DataEntry data, MerkleProof proof) { this.data = data; this.proof = proof; } @Override - public VersioningKVEntry getData() { + public DataEntry getData() { return data; } 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 483b5667..220b519c 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java @@ -17,7 +17,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.VersioningKVEntry; +import com.jd.blockchain.utils.DataEntry; public class RolePrivilegeDataset implements Transactional, MerkleProvable, RolePrivilegeSettings { @@ -256,7 +256,7 @@ public class RolePrivilegeDataset implements Transactional, MerkleProvable, Role public RolePrivileges getRolePrivilege(String roleName) { // 只返回最新版本; Bytes key = encodeKey(roleName); - VersioningKVEntry kv = dataset.getDataEntry(key); + DataEntry kv = dataset.getDataEntry(key); if (kv == null) { return null; } @@ -266,7 +266,7 @@ public class RolePrivilegeDataset implements Transactional, MerkleProvable, Role @Override public RolePrivileges[] getRolePrivileges(int index, int count) { - VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(index, count); + DataEntry[] kvEntries = dataset.getLatestDataEntries(index, count); RolePrivileges[] pns = new RolePrivileges[kvEntries.length]; PrivilegeSet privilege; for (int i = 0; i < pns.length; i++) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java index 2a3eda4f..df3231c4 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 @@ -15,9 +15,9 @@ import com.jd.blockchain.utils.Bytes; */ public class UserAccount extends AccountDecorator implements UserInfo { // implements UserInfo { - private static final Bytes USER_INFO_PREFIX = Bytes.fromString("PROP" + LedgerConsts.KEY_SEPERATOR); + private static final String USER_INFO_PREFIX = "PROP" + LedgerConsts.KEY_SEPERATOR; - private static final Bytes DATA_PUB_KEY = Bytes.fromString("DATA-PUBKEY"); + private static final String DATA_PUB_KEY = "DATA-PUBKEY"; public UserAccount(MerkleAccount mklAccount) { super(mklAccount); @@ -64,25 +64,21 @@ public class UserAccount extends AccountDecorator implements UserInfo { // imple } public long setProperty(String key, String value, long version) { - return setProperty(Bytes.fromString(key), value, version); - } - - public long setProperty(Bytes key, String value, long version) { return getHeaders().setValue(encodePropertyKey(key), TypedValue.fromText(value), version); } - public String getProperty(Bytes key) { + public String getProperty(String key) { BytesValue value = getHeaders().getValue(encodePropertyKey(key)); return value == null ? null : value.getValue().toUTF8String(); } - public String getProperty(Bytes key, long version) { + public String getProperty(String key, long version) { BytesValue value = getHeaders().getValue(encodePropertyKey(key), version); return value == null ? null : value.getValue().toUTF8String(); } - private Bytes encodePropertyKey(Bytes key) { - return USER_INFO_PREFIX.concat(key); + private String encodePropertyKey(String key) { + return USER_INFO_PREFIX+key; } 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 e4eb37cc..8aa45ebc 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataset.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataset.java @@ -16,7 +16,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.VersioningKVEntry; +import com.jd.blockchain.utils.DataEntry; /** * User-Role authorization data set; @@ -168,7 +168,7 @@ public class UserRoleDataset implements Transactional, MerkleProvable, UserAutho @Override public UserRoles getUserRoles(Bytes userAddress) { // 只返回最新版本; - VersioningKVEntry kv = dataset.getDataEntry(userAddress); + DataEntry kv = dataset.getDataEntry(userAddress); if (kv == null) { return null; } @@ -178,7 +178,7 @@ public class UserRoleDataset implements Transactional, MerkleProvable, UserAutho @Override public UserRoles[] getUserRoles() { - VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(0, (int) dataset.getDataCount()); + DataEntry[] kvEntries = dataset.getLatestDataEntries(0, (int) dataset.getDataCount()); UserRoles[] pns = new UserRoles[kvEntries.length]; RoleSet roleset; for (int i = 0; i < pns.length; i++) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java index a6758fb0..dfab3f1c 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java @@ -5,6 +5,7 @@ import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.DataAccountKVSetOperation.KVWriteEntry; import com.jd.blockchain.ledger.DataVersionConflictException; import com.jd.blockchain.ledger.LedgerPermission; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.core.DataAccount; import com.jd.blockchain.ledger.core.LedgerDataset; import com.jd.blockchain.ledger.core.LedgerQuery; @@ -37,7 +38,7 @@ public class DataAccountKVSetOperationHandle extends AbstractLedgerOperationHand KVWriteEntry[] writeSet = kvWriteOp.getWriteSet(); long v = -1L; for (KVWriteEntry kvw : writeSet) { - v = account.getDataset().setValue(Bytes.fromString(kvw.getKey()), kvw.getValue(), kvw.getExpectedVersion()); + v = account.getDataset().setValue(kvw.getKey(), TypedValue.wrap(kvw.getValue()), kvw.getExpectedVersion()); if (v < 0) { throw new DataVersionConflictException(); } diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java index 1c05e28c..6a99be27 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java @@ -14,9 +14,9 @@ import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.core.MerkleAccountSet; -import com.jd.blockchain.ledger.core.MerkleAccount; import com.jd.blockchain.ledger.core.CryptoConfig; +import com.jd.blockchain.ledger.core.MerkleAccount; +import com.jd.blockchain.ledger.core.MerkleAccountSet; import com.jd.blockchain.ledger.core.OpeningAccessPolicy; import com.jd.blockchain.storage.service.utils.MemoryKVStorage; import com.jd.blockchain.utils.Bytes; 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 25a9091f..9d55b19e 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BaseAccountTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BaseAccountTest.java @@ -55,33 +55,33 @@ public class BaseAccountTest { assertFalse(baseAccount.isReadonly()); // 在空白状态下写入数据; - long v = baseAccount.getDataset().setValue(Bytes.fromString("A"), TypedValue.fromText("VALUE_A"), 0); + long v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A"), 0); // 预期失败; assertEquals(-1, v); - v = baseAccount.getDataset().setValue(Bytes.fromString("A"), TypedValue.fromText("VALUE_A"), 1); + v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A"), 1); // 预期失败; assertEquals(-1, v); - v = baseAccount.getDataset().setValue(Bytes.fromString("A"), TypedValue.fromText("VALUE_A"), -1); + v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A"), -1); // 预期成功; assertEquals(0, v); - v = baseAccount.getDataset().setValue(Bytes.fromString("A"), TypedValue.fromText("VALUE_A-1"), -1); + v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A-1"), -1); // 已经存在版本,指定版本号-1,预期导致失败; assertEquals(-1, v); baseAccount.commit(); v = 0; for (int i = 0; i < 10; i++) { - long s = baseAccount.getDataset().setValue(Bytes.fromString("A"), TypedValue.fromText("VALUE_A_" + i), v); + long s = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A_" + i), v); baseAccount.commit(); // 预期成功; assertEquals(v + 1, s); v++; } - v = baseAccount.getDataset().setValue(Bytes.fromString("A"), TypedValue.fromText("VALUE_A_" + v), v + 1); + v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A_" + v), v + 1); // 预期成功; assertEquals(-1, v); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java index 4e91c1fb..4af4c707 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 @@ -301,7 +301,7 @@ public class ContractInvokingTest { } }); // 预期数据都能够正常写入; - KVDataEntry kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K1", + KVDataEntry kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K1", 0); KVDataEntry kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K2", 0); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java index a50cd41e..53e9eb4d 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java @@ -1,22 +1,12 @@ package test.com.jd.blockchain.ledger.core; -import static org.junit.Assert.assertEquals; - import java.util.Random; import org.junit.Before; -import org.junit.Test; -import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; -import com.jd.blockchain.crypto.service.sm.SMAlgorithm; -import com.jd.blockchain.ledger.AccountHeader; +import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.UserInfo; -import com.jd.blockchain.ledger.core.MerkleAccountSet; -import com.jd.blockchain.utils.Bytes; /** * Created by zhangshuang3 on 2018/9/3. @@ -35,27 +25,27 @@ public class LedgerAccountTest { rand.nextBytes(seed); rand.nextBytes(settingValue); rand.nextBytes(rawDigestBytes); - DataContractRegistry.register(AccountHeader.class); + DataContractRegistry.register(BlockchainIdentity.class); DataContractRegistry.register(UserInfo.class); } - @Test - public void testSerialize_AccountHeader() { - String address = "xxxxxxxxxxxx"; - PubKey pubKey = new PubKey(SMAlgorithm.SM2, rawDigestBytes); - HashDigest hashDigest = new HashDigest(ClassicAlgorithm.SHA256, rawDigestBytes); - MerkleAccountSet.AccountHeaderData accountHeaderData = new MerkleAccountSet.AccountHeaderData(Bytes.fromString(address), - pubKey, hashDigest); - - // encode and decode - byte[] encodeBytes = BinaryProtocol.encode(accountHeaderData, AccountHeader.class); - AccountHeader deAccountHeaderData = BinaryProtocol.decode(encodeBytes); - - // verify start - assertEquals(accountHeaderData.getAddress(), deAccountHeaderData.getAddress()); - assertEquals(accountHeaderData.getPubKey(), deAccountHeaderData.getPubKey()); - assertEquals(accountHeaderData.getRootHash(), deAccountHeaderData.getRootHash()); - - } +// @Test +// public void testSerialize_AccountHeader() { +// String address = "xxxxxxxxxxxx"; +// PubKey pubKey = new PubKey(SMAlgorithm.SM2, rawDigestBytes); +// HashDigest hashDigest = new HashDigest(ClassicAlgorithm.SHA256, rawDigestBytes); +// MerkleAccountSet.AccountHeaderData accountHeaderData = new MerkleAccountSet.AccountHeaderData(Bytes.fromString(address), +// pubKey, hashDigest); +// +// // encode and decode +// byte[] encodeBytes = BinaryProtocol.encode(accountHeaderData, AccountHeader.class); +// AccountHeader deAccountHeaderData = BinaryProtocol.decode(encodeBytes); +// +// // verify start +// assertEquals(accountHeaderData.getAddress(), deAccountHeaderData.getAddress()); +// assertEquals(accountHeaderData.getPubKey(), deAccountHeaderData.getPubKey()); +// assertEquals(accountHeaderData.getRootHash(), deAccountHeaderData.getRootHash()); + +// } } diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java index 97979205..0bd470a7 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java @@ -8,12 +8,9 @@ import org.junit.Before; import org.junit.Test; import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.Crypto; -import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.SignatureFunction; -import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainKeyGenerator; @@ -25,7 +22,7 @@ import com.jd.blockchain.ledger.LedgerInitSetting; import com.jd.blockchain.ledger.LedgerTransaction; import com.jd.blockchain.ledger.TransactionRequest; import com.jd.blockchain.ledger.TransactionState; -import com.jd.blockchain.ledger.core.CryptoConfig; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.core.DataAccount; import com.jd.blockchain.ledger.core.LedgerDataset; import com.jd.blockchain.ledger.core.LedgerEditor; @@ -33,11 +30,6 @@ import com.jd.blockchain.ledger.core.LedgerTransactionContext; import com.jd.blockchain.ledger.core.LedgerTransactionalEditor; import com.jd.blockchain.ledger.core.UserAccount; import com.jd.blockchain.storage.service.utils.MemoryKVStorage; -import com.jd.blockchain.transaction.ConsensusParticipantData; -import com.jd.blockchain.transaction.LedgerInitData; -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.io.BytesUtils; -import com.jd.blockchain.utils.net.NetworkAddress; public class LedgerEditorTest { @@ -102,7 +94,7 @@ public class LedgerEditorTest { DataAccount dataAccount = ldgDS.getDataAccountSet().register(dataKP.getAddress(), dataKP.getPubKey(), null); - dataAccount.setBytes(Bytes.fromString("A"), "abc", -1); + dataAccount.getDataset().setValue("A", TypedValue.fromText("abc"), -1); LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS); LedgerBlock block = ldgEdt.prepare(); @@ -115,7 +107,7 @@ public class LedgerEditorTest { assertEquals(0, block.getHeight()); // 验证数据读写的一致性; - BytesValue bytes = dataAccount.getBytes("A"); + BytesValue bytes = dataAccount.getDataset().getValue("A"); assertEquals(DataType.TEXT, bytes.getType()); String textValue = bytes.getValue().toUTF8String(); assertEquals("abc", textValue); 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 46ae96ae..a8ab595b 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleDataSetTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleDataSetTest.java @@ -25,7 +25,9 @@ import com.jd.blockchain.ledger.core.CryptoConfig; import com.jd.blockchain.ledger.core.MerkleDataSet; 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.DataEntry; +import com.jd.blockchain.utils.Dataset; +import com.jd.blockchain.utils.DatasetHelper; import com.jd.blockchain.utils.io.BytesUtils; public class MerkleDataSetTest { @@ -53,9 +55,9 @@ public class MerkleDataSetTest { MemoryKVStorage storage = new MemoryKVStorage(); MerkleDataSet mds = new MerkleDataSet(cryptoConfig, keyPrefix, storage, storage); - mds.setValue("A", "A".getBytes(), -1); - mds.setValue("B", "B".getBytes(), -1); - mds.setValue("C", "C".getBytes(), -1); + mds.setValue(Bytes.fromString("A"), "A".getBytes(), -1); + mds.setValue(Bytes.fromString("B"), "B".getBytes(), -1); + mds.setValue(Bytes.fromString("C"), "C".getBytes(), -1); mds.commit(); @@ -85,22 +87,23 @@ public class MerkleDataSetTest { MemoryKVStorage storage = new MemoryKVStorage(); MerkleDataSet mds = new MerkleDataSet(cryptoConfig, keyPrefix, storage, storage); - mds.setValue("A", "A".getBytes(), -1); - mds.setValue("B", "B".getBytes(), -1); - mds.setValue("C", "C".getBytes(), -1); + Dataset ds = DatasetHelper.map(mds); + ds.setValue("A", "A".getBytes(), -1); + ds.setValue("B", "B".getBytes(), -1); + ds.setValue("C", "C".getBytes(), -1); mds.commit(); - byte[] va = mds.getValue("A"); + byte[] va = ds.getValue("A"); assertNotNull(va); assertEquals("A", new String(va)); - byte[] vc = mds.getValue("C"); - VersioningKVEntry ventry = mds.getDataEntry("C"); + byte[] vc = ds.getValue("C"); + DataEntry ventry = ds.getDataEntry("C"); assertNotNull(vc); assertNotNull(ventry); assertEquals("C", new String(vc)); - assertEquals("C", ventry.getKey().toUTF8String()); + assertEquals("C", ventry.getKey()); HashDigest root1 = mds.getRootHash(); @@ -111,8 +114,8 @@ public class MerkleDataSetTest { int expStorageCount = 10; assertEquals(expStorageCount, storage.getStorageCount()); - mds.setValue("B", "B".getBytes(), 0); - mds.setValue("C", "C".getBytes(), 0); + ds.setValue("B", "B".getBytes(), 0); + ds.setValue("C", "C".getBytes(), 0); mds.commit(); HashDigest root2 = mds.getRootHash(); assertNotEquals(root1, root2); @@ -122,7 +125,7 @@ public class MerkleDataSetTest { expStorageCount = expStorageCount + 3; assertEquals(expStorageCount, storage.getStorageCount()); - mds.setValue("D", "DValue".getBytes(), -1); + ds.setValue("D", "DValue".getBytes(), -1); mds.commit(); HashDigest root3 = mds.getRootHash(); assertNotEquals(root2, root3); @@ -135,31 +138,31 @@ public class MerkleDataSetTest { assertEquals(expStorageCount, storage.getStorageCount()); // Check rollback function: Add some keys, and then rollback; - long v = mds.setValue("E", "E-values".getBytes(), -1); + long v = ds.setValue("E", "E-values".getBytes(), -1); assertEquals(v, 0); - String expEValue = new String(mds.getValue("E")); + String expEValue = new String(ds.getValue("E")); assertEquals(expEValue, "E-values"); - v = mds.setValue("F", "F-values".getBytes(), -1); + v = ds.setValue("F", "F-values".getBytes(), -1); assertEquals(v, 0); - String expFValue = new String(mds.getValue("F")); + String expFValue = new String(ds.getValue("F")); assertEquals(expFValue, "F-values"); - v = mds.setValue("E", "E-values-1".getBytes(), 0); + v = ds.setValue("E", "E-values-1".getBytes(), 0); assertEquals(v, 1); - expEValue = new String(mds.getValue("E")); + expEValue = new String(ds.getValue("E")); assertEquals(expEValue, "E-values-1"); mds.cancel(); - byte[] bv = mds.getValue("E"); + byte[] bv = ds.getValue("E"); assertNull(bv); - bv = mds.getValue("F"); + bv = ds.getValue("F"); assertNull(bv); - v = mds.getVersion("E"); + v = ds.getVersion("E"); assertEquals(-1, v); - v = mds.getVersion("F"); + v = ds.getVersion("F"); assertEquals(-1, v); // Expect that states has been recover; @@ -194,10 +197,11 @@ public class MerkleDataSetTest { MemoryKVStorage storage = new MemoryKVStorage(); MerkleDataSet mds = new MerkleDataSet(cryptoConfig, keyPrefix, storage, storage); + Dataset ds = DatasetHelper.map(mds); // 初始的时候没有任何数据,总是返回 null; - VersioningKVEntry verKVEntry = mds.getDataEntry("NULL_KEY"); - byte[] vbytes = mds.getValue("NULL_KEY"); + DataEntry verKVEntry = ds.getDataEntry("NULL_KEY"); + byte[] vbytes = ds.getValue("NULL_KEY"); assertNull(verKVEntry); assertNull(vbytes); @@ -217,7 +221,7 @@ public class MerkleDataSetTest { for (int i = 0; i < count; i++) { key = "data" + i; rand.nextBytes(data); - v = mds.setValue(key, data, -1); + v = ds.setValue(key, data, -1); dataVersions.put(key, v); dataValues.put(key + "_" + v, data); assertEquals(v, 0); @@ -237,7 +241,7 @@ public class MerkleDataSetTest { KeySnapshot ks = new KeySnapshot(); ks.proof = proof; - ks.maxVersion = mds.getVersion(key); + ks.maxVersion = ds.getVersion(key); snapshot.put(key, ks); } @@ -271,7 +275,7 @@ public class MerkleDataSetTest { key = "data" + i; rand.nextBytes(data); expVer = dataVersions.get(key); - v = mds.setValue(key, data, expVer); + v = ds.setValue(key, data, expVer); assertEquals(v, expVer + 1); @@ -300,7 +304,7 @@ public class MerkleDataSetTest { KeySnapshot ks = new KeySnapshot(); ks.proof = proof; - ks.maxVersion = mds.getVersion(key); + ks.maxVersion = ds.getVersion(key); snapshot.put(key, ks); } history.put(rootHash, snapshot); @@ -316,6 +320,7 @@ public class MerkleDataSetTest { MerkleDataSet mdsReload = new MerkleDataSet(hisRootHash, cryptoConfig, keyPrefix, storage, storage, true); + Dataset dsReload = DatasetHelper.map(mdsReload); assertEquals(hisRootHash, mdsReload.getRootHash()); // verify every keys; @@ -323,7 +328,7 @@ public class MerkleDataSetTest { key = "data" + i; // 最新版本一致; long expLatestVersion = snapshot.get(key).maxVersion; - long actualLatestVersion = mdsReload.getVersion(key); + long actualLatestVersion = dsReload.getVersion(key); assertEquals(expLatestVersion, actualLatestVersion); // 数据证明一致; @@ -339,7 +344,7 @@ public class MerkleDataSetTest { for (long j = 0; j < actualLatestVersion; j++) { String keyver = key + "_" + j; byte[] expValue = dataValues.get(keyver); - byte[] actualValue = mdsReload.getValue(key, j); + byte[] actualValue = dsReload.getValue(key, j); assertTrue(BytesUtils.equals(expValue, actualValue)); } } @@ -365,10 +370,11 @@ public class MerkleDataSetTest { MemoryKVStorage storage = new MemoryKVStorage(); MerkleDataSet mds = new MerkleDataSet(cryptoConfig, keyPrefix, storage, storage); + Dataset ds = DatasetHelper.map(mds); // 初始的时候没有任何数据,总是返回 null; - VersioningKVEntry verKVEntry = mds.getDataEntry("NULL_KEY"); - byte[] vbytes = mds.getValue("NULL_KEY"); + DataEntry verKVEntry = ds.getDataEntry("NULL_KEY"); + byte[] vbytes = ds.getValue("NULL_KEY"); assertNull(verKVEntry); assertNull(vbytes); @@ -388,7 +394,7 @@ public class MerkleDataSetTest { MerkleProof proof; for (int i = 0; i < count; i++) { key = "data" + i; - v = mds.setValue(key, data, -1); + v = ds.setValue(key, data, -1); dataVersions.put(key, v); // dataValues.put(key + "_" + v, data); assertEquals(v, 0); @@ -408,7 +414,7 @@ public class MerkleDataSetTest { KeySnapshot ks = new KeySnapshot(); ks.proof = proof; - ks.maxVersion = mds.getVersion(key); + ks.maxVersion = ds.getVersion(key); snapshot.put(key, ks); } @@ -418,6 +424,7 @@ public class MerkleDataSetTest { // verify; { MerkleDataSet mdsReload = new MerkleDataSet(rootHash, cryptoConfig, keyPrefix, storage, storage, true); + Dataset dsReload = DatasetHelper.map(mdsReload); // verify every keys; Map snapshot = history.get(rootHash); MerkleProof expProof; @@ -429,7 +436,7 @@ public class MerkleDataSetTest { expProof = snapshot.get(key).proof; assertEquals(expProof.toString(), proof.toString()); - byte[] value = mdsReload.getValue(key); + byte[] value = dsReload.getValue(key); assertTrue(BytesUtils.equals(data, value)); } } diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java index ff4d160f..e1442bc3 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()).getValue("K1", + BytesValue v1_0 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K1", 0); - BytesValue v1_1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getValue("K1", + BytesValue v1_1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K1", 1); - BytesValue v2 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getValue("K2", + BytesValue v2 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K2", 0); - BytesValue v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getValue("K3", + BytesValue v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K3", 0); assertNotNull(v1_0); @@ -376,16 +376,16 @@ public class TransactionBatchProcessorTest { newBlock = newBlockEditor.prepare(); newBlockEditor.commit(); - BytesValue v1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getValue("K1"); - v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getValue("K3"); + BytesValue v1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K1"); + v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K3"); // k1 的版本仍然为1,没有更新; long k1_version = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()) - .getDataVersion("K1"); + .getDataset().getVersion("K1"); assertEquals(1, k1_version); long k3_version = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()) - .getDataVersion("K3"); + .getDataset().getVersion("K3"); assertEquals(1, k3_version); assertNotNull(v1); 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 da809c0a..000bb20e 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 @@ -2,7 +2,7 @@ package com.jd.blockchain.storage.service.impl.redis; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.VersioningKVEntry; +import com.jd.blockchain.utils.DataEntry; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; @@ -45,7 +45,7 @@ public class RedisVerioningStorage implements VersioningKVStorage { } @Override - public VersioningKVEntry getEntry(Bytes key, long version) { + public DataEntry getEntry(Bytes key, long version) { byte[] value = get(key, version); if (value == null) { return null; @@ -101,7 +101,7 @@ public class RedisVerioningStorage implements VersioningKVStorage { } - private static class VersioningKVData implements VersioningKVEntry{ + private static class VersioningKVData implements DataEntry{ private Bytes key; diff --git a/source/storage/storage-rocksdb/src/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 40dba131..98c47325 100644 --- a/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBVersioningStorage.java +++ b/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBVersioningStorage.java @@ -9,7 +9,7 @@ import org.rocksdb.*; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.VersioningKVEntry; +import com.jd.blockchain.utils.DataEntry; import com.jd.blockchain.utils.io.BytesUtils; /** @@ -127,7 +127,7 @@ public class RocksDBVersioningStorage implements VersioningKVStorage { } @Override - public VersioningKVEntry getEntry(Bytes key, long version) { + public DataEntry getEntry(Bytes key, long version) { byte[] value = get(key, version); if (value == null) { return null; @@ -226,7 +226,7 @@ public class RocksDBVersioningStorage implements VersioningKVStorage { } } - private static class VersioningKVData implements VersioningKVEntry { + private static class VersioningKVData implements DataEntry { private Bytes key; diff --git a/source/storage/storage-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 dfa26404..980cc32c 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVStorage.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVStorage.java @@ -1,7 +1,7 @@ package com.jd.blockchain.storage.service; import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.VersioningKVEntry; +import com.jd.blockchain.utils.DataEntry; /** * Versioning Key-Value Storage @@ -41,7 +41,7 @@ public interface VersioningKVStorage extends BatchStorageService { * @param version * @return */ - VersioningKVEntry getEntry(Bytes key, long version); + DataEntry getEntry(Bytes key, long version); /** * Return the specified verson's value;
diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/BufferedKVStorage.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/BufferedKVStorage.java index 8f334ca3..b038a87e 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/BufferedKVStorage.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/BufferedKVStorage.java @@ -10,7 +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.VersioningKVEntry; +import com.jd.blockchain.utils.DataEntry; /** * {@link BufferedKVStorage} 缓冲写入的KV存储;
@@ -79,7 +79,7 @@ public class BufferedKVStorage implements VersioningKVStorage, ExPolicyKVStorage } @Override - public VersioningKVEntry getEntry(Bytes key, long version) { + public DataEntry getEntry(Bytes key, long version) { VersioningWritingSet ws = versioningCache.get(key); if (ws == null) { return origVersioningStorage.getEntry(key, version); @@ -484,7 +484,7 @@ public class BufferedKVStorage implements VersioningKVStorage, ExPolicyKVStorage return startingVersion; } - public VersioningKVEntry getEntry(long version) { + public DataEntry getEntry(long version) { byte[] value = get(version); if (value == null) { return null; @@ -505,7 +505,7 @@ public class BufferedKVStorage implements VersioningKVStorage, ExPolicyKVStorage } } - private static class VersioningKVData implements VersioningKVEntry { + private static class VersioningKVData implements DataEntry { private Bytes key; diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java index 8bce7e32..a0f36c0d 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java @@ -7,7 +7,7 @@ import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.KVStorageService; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.VersioningKVEntry; +import com.jd.blockchain.utils.DataEntry; import com.jd.blockchain.utils.io.BytesMap; public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage, KVStorageService, BytesMap { @@ -21,7 +21,7 @@ public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage, } @Override - public VersioningKVEntry getEntry(Bytes key, long version) { + public DataEntry getEntry(Bytes key, long version) { return verStorage.getEntry(key, version); } diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java index 4d1e1509..73816055 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java @@ -1,8 +1,8 @@ package com.jd.blockchain.storage.service.utils; -import com.jd.blockchain.utils.VersioningKVEntry; +import com.jd.blockchain.utils.DataEntry; -public class VersioningKVData implements VersioningKVEntry { +public class VersioningKVData implements DataEntry { private K key; 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 e9aee04b..1c6b8def 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVStorageMap.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVStorageMap.java @@ -7,7 +7,7 @@ import java.util.concurrent.ConcurrentHashMap; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.VersioningKVEntry; +import com.jd.blockchain.utils.DataEntry; import com.jd.blockchain.utils.io.BytesMap; public class VersioningKVStorageMap implements VersioningKVStorage, BytesMap { @@ -42,7 +42,7 @@ public class VersioningKVStorageMap implements VersioningKVStorage, BytesMap { + + public K getKey(); + + public long getVersion(); + + public V getValue(); + +} \ No newline at end of file diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/VersioningMap.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Dataset.java similarity index 95% rename from source/utils/utils-common/src/main/java/com/jd/blockchain/utils/VersioningMap.java rename to source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Dataset.java index 84d198a9..33ad1f7c 100644 --- 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/Dataset.java @@ -1,8 +1,8 @@ package com.jd.blockchain.utils; -public interface VersioningMap { +public interface Dataset { -// long getDataCount(); + long getDataCount(); // /** // * Create or update the value associated the specified key if the version @@ -109,8 +109,8 @@ public interface VersioningMap { * @param key * @return Null if the key doesn't exist! */ - VersioningKVEntry getDataEntry(K key); + DataEntry getDataEntry(K key); - VersioningKVEntry getDataEntry(K key, long version); + DataEntry getDataEntry(K key, long version); } \ No newline at end of file diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DatasetHelper.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DatasetHelper.java new file mode 100644 index 00000000..de96f665 --- /dev/null +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DatasetHelper.java @@ -0,0 +1,301 @@ +package com.jd.blockchain.utils; + +public class DatasetHelper { + + + + public static final TypeMapper UTF8_STRING_BYTES_MAPPER = new TypeMapper() { + + @Override + public Bytes encode(String t2) { + return Bytes.fromString(t2); + } + + @Override + public String decode(Bytes t1) { + return t1.toUTF8String(); + } + }; + + public static final TypeMapper BYTES_UTF8_STRING_MAPPER = new TypeMapper() { + + @Override + public String encode(Bytes t1) { + return t1.toUTF8String(); + } + + @Override + public Bytes decode(String t2) { + return Bytes.fromString(t2); + } + }; + + /** + * 适配两个不同类型参数的数据集; + * + * @param 适配输入的 键 类型; + * @param 适配输出的 键 类型; + * @param 适配输入的 值 类型; + * @param 适配输出的 值 类型; + * @param dataset 数据集; + * @param keyMapper 键的映射配置; + * @param valueMapper 值的映射配置; + * @return + */ + public static Dataset map(Dataset dataset) { + return new TypeAdapter(dataset, UTF8_STRING_BYTES_MAPPER, new EmptyMapper()); + } + + /** + * 适配两个不同类型参数的数据集; + * + * @param 适配输入的 键 类型; + * @param 适配输出的 键 类型; + * @param 适配输入的 值 类型; + * @param 适配输出的 值 类型; + * @param dataset 数据集; + * @param keyMapper 键的映射配置; + * @param valueMapper 值的映射配置; + * @return + */ + public static Dataset map(Dataset dataset, TypeMapper valueMapper) { + return new TypeAdapter(dataset, UTF8_STRING_BYTES_MAPPER, valueMapper); + } + + /** + * 适配两个不同类型参数的数据集; + * + * @param 适配输入的 键 类型; + * @param 适配输出的 键 类型; + * @param 适配输入的 值 类型; + * @param 适配输出的 值 类型; + * @param dataset 数据集; + * @param keyMapper 键的映射配置; + * @param valueMapper 值的映射配置; + * @return + */ + public static Dataset map(Dataset dataset, TypeMapper keyMapper, + TypeMapper valueMapper) { + return new TypeAdapter(dataset, keyMapper, valueMapper); + } + + /** + * 监听对数据集的变更; + * + * @param 键 类型; + * @param 值 类型; + * @param dataset 要监听的数据集; + * @param listener 要植入的监听器; + * @return 植入监听器的数据集实例; + */ + public static Dataset listen(Dataset dataset, DataChangedListener listener) { + return new DatasetUpdatingMonitor(dataset, listener); + } + + /** + * 数据修改监听器; + * + * @author huanghaiquan + * + * @param + * @param + */ + public static interface DataChangedListener { + + void onChanged(K key, V value, long expectedVersion, long newVersion); + + } + + /** + * 类型映射接口; + * + * @author huanghaiquan + * + * @param + * @param + */ + public static interface TypeMapper { + + T1 encode(T2 t2); + + T2 decode(T1 t1); + + } + + private static class EmptyMapper implements TypeMapper{ + + @Override + public T encode(T t) { + return t; + } + + @Override + public T decode(T t) { + return t; + } + + } + + private static class DatasetUpdatingMonitor implements Dataset { + + private Dataset dataset; + + private DataChangedListener listener; + + public DatasetUpdatingMonitor(Dataset dataset, DataChangedListener listener) { + this.dataset = dataset; + this.listener = listener; + } + + @Override + public long getDataCount() { + return dataset.getDataCount(); + } + + @Override + public long setValue(K key, V value, long version) { + long newVersion = dataset.setValue(key, value, version); + if (newVersion > -1) { + listener.onChanged(key, value, version, newVersion); + } + return newVersion; + } + + @Override + public V getValue(K key, long version) { + return dataset.getValue(key, version); + } + + @Override + public V getValue(K key) { + return dataset.getValue(key); + } + + @Override + public long getVersion(K key) { + return dataset.getVersion(key); + } + + @Override + public DataEntry getDataEntry(K key) { + return dataset.getDataEntry(key); + } + + @Override + public DataEntry getDataEntry(K key, long version) { + return dataset.getDataEntry(key, version); + } + + } + + /** + * 类型适配器; + * + * @author huanghaiquan + * + * @param + * @param + * @param + * @param + */ + private static class TypeAdapter implements Dataset { + private Dataset dataset; + private TypeMapper keyMapper; + private TypeMapper valueMapper; + + public TypeAdapter(Dataset dataset, TypeMapper keyMapper, TypeMapper valueMapper) { + this.dataset = dataset; + this.keyMapper = keyMapper; + this.valueMapper = valueMapper; + } + + @Override + public long getDataCount() { + return dataset.getDataCount(); + } + + @Override + public long setValue(K2 key, V2 value, long version) { + K1 key1 = keyMapper.encode(key); + V1 value1 = valueMapper.encode(value); + return dataset.setValue(key1, value1, version); + } + + @Override + public V2 getValue(K2 key, long version) { + K1 k = keyMapper.encode(key); + V1 v = dataset.getValue(k, version); + if (v == null) { + return null; + } + return valueMapper.decode(v); + } + + @Override + public V2 getValue(K2 key) { + K1 k = keyMapper.encode(key); + V1 v = dataset.getValue(k); + if (v == null) { + return null; + } + return valueMapper.decode(v); + } + + @Override + public long getVersion(K2 key) { + K1 k = keyMapper.encode(key); + return dataset.getVersion(k); + } + + @Override + public DataEntry getDataEntry(K2 key) { + K1 k = keyMapper.encode(key); + DataEntry entry = dataset.getDataEntry(k); + if (entry == null) { + return null; + } + V2 v = valueMapper.decode(entry.getValue()); + return new KeyValueEntry(key, v, entry.getVersion()); + } + + @Override + public DataEntry getDataEntry(K2 key, long version) { + K1 k = keyMapper.encode(key); + DataEntry entry = dataset.getDataEntry(k, version); + if (entry == null) { + return null; + } + V2 v = valueMapper.decode(entry.getValue()); + return new KeyValueEntry(key, v, entry.getVersion()); + } + + } + + private static class KeyValueEntry implements DataEntry { + + private K key; + + private V value; + + private long version; + + public KeyValueEntry(K key, V value, long version) { + this.key = key; + this.value = value; + this.version = version; + } + + public K getKey() { + return key; + } + + public long getVersion() { + return version; + } + + public V getValue() { + return value; + } + + } +} 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 deleted file mode 100644 index 20b3da6f..00000000 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/RegionMap.java +++ /dev/null @@ -1,122 +0,0 @@ -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 deleted file mode 100644 index b92eda41..00000000 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/VersioningKVEntry.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.jd.blockchain.utils; - -/** - * 版本化的键值数据项; - * - * @author huanghaiquan - * - */ -public interface VersioningKVEntry{ - - K getKey(); - - long getVersion(); - - V getValue(); - -} \ No newline at end of file