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 e3e2506c..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 @@ -121,12 +121,16 @@ public interface DataCodes { public static final int ACCOUNT_HEADER = 0x710; - public static final int USER = 0x800; + 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 = 0xA00; + 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/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ReadContractImpl.java b/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ReadContractImpl.java index e3d720a5..2f6e0610 100644 --- a/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ReadContractImpl.java +++ b/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ReadContractImpl.java @@ -1,7 +1,7 @@ package com.jd.blockchain.contract; import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.KVDataEntry; +import com.jd.blockchain.ledger.TypedKVEntry; @Contract public class ReadContractImpl implements EventProcessingAware, ReadContract { @@ -24,7 +24,7 @@ public class ReadContractImpl implements EventProcessingAware, ReadContract { @Override @ContractEvent(name = "read-key") public String read(String address, String key) { - KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, key); + TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, key); if (kvDataEntries != null && kvDataEntries.length == 1) { return kvDataEntries[0].getValue().toString(); @@ -35,7 +35,7 @@ public class ReadContractImpl implements EventProcessingAware, ReadContract { @Override @ContractEvent(name = "version-key") public Long readVersion(String address, String key) { - KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, key); + TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, key); if (kvDataEntries != null && kvDataEntries.length == 1) { return kvDataEntries[0].getVersion(); diff --git a/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/TransferContractImpl.java b/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/TransferContractImpl.java index c312dd4f..d29ee281 100644 --- a/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/TransferContractImpl.java +++ b/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/TransferContractImpl.java @@ -2,7 +2,7 @@ package com.jd.blockchain.contract; import com.alibaba.fastjson.JSON; import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.KVDataEntry; +import com.jd.blockchain.ledger.TypedKVEntry; import com.jd.blockchain.ledger.KVDataVO; import com.jd.blockchain.ledger.KVInfoVO; @@ -14,7 +14,7 @@ public class TransferContractImpl implements EventProcessingAware, TransferContr @Override public String create(String address, String account, long money) { - KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); + TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); // 肯定有返回值,但若不存在则返回version=-1 if (kvDataEntries != null && kvDataEntries.length > 0) { long currVersion = kvDataEntries[0].getVersion(); @@ -32,13 +32,13 @@ public class TransferContractImpl implements EventProcessingAware, TransferContr @Override public String transfer(String address, String from, String to, long money) { // 首先查询余额 - KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, from, to); + TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, from, to); if (kvDataEntries == null || kvDataEntries.length != 2) { throw new IllegalStateException(String.format("%s -> %s - %s may be not created !!!", address, from, to)); } else { // 判断from账号中钱数量是否足够 long fromMoney = 0L, toMoney = 0L, fromVersion = 0L, toVersion = 0L; - for (KVDataEntry kvDataEntry : kvDataEntries) { + for (TypedKVEntry kvDataEntry : kvDataEntries) { if (kvDataEntry.getKey().equals(from)) { fromMoney = (long) kvDataEntry.getValue(); fromVersion = kvDataEntry.getVersion(); @@ -62,7 +62,7 @@ public class TransferContractImpl implements EventProcessingAware, TransferContr @Override public long read(String address, String account) { - KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); + TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); if (kvDataEntries == null || kvDataEntries.length == 0) { return -1; } @@ -71,7 +71,7 @@ public class TransferContractImpl implements EventProcessingAware, TransferContr @Override public String readAll(String address, String account) { - KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); + TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); // 获取最新的版本号 if (kvDataEntries == null || kvDataEntries.length == 0) { return ""; @@ -91,7 +91,7 @@ public class TransferContractImpl implements EventProcessingAware, TransferContr KVInfoVO kvInfoVO = new KVInfoVO(kvDataVOS); - KVDataEntry[] allEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, kvInfoVO); + TypedKVEntry[] allEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, kvInfoVO); return JSON.toJSONString(allEntries); } diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java index 50f528ba..12dfb4f5 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java @@ -23,9 +23,9 @@ import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.gateway.PeerService; import com.jd.blockchain.gateway.service.DataRetrievalService; -import com.jd.blockchain.ledger.AccountHeader; +import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.ContractInfo; -import com.jd.blockchain.ledger.KVDataEntry; +import com.jd.blockchain.ledger.TypedKVEntry; import com.jd.blockchain.ledger.KVInfoVO; import com.jd.blockchain.ledger.LedgerAdminInfo; import com.jd.blockchain.ledger.LedgerBlock; @@ -252,7 +252,7 @@ public class BlockBrowserController implements BlockchainExtendQueryService { @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}") @Override - public AccountHeader getDataAccount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, + public BlockchainIdentity getDataAccount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "address") String address) { return peerService.getQueryService().getDataAccount(ledgerHash, address); @@ -261,7 +261,7 @@ public class BlockBrowserController implements BlockchainExtendQueryService { @RequestMapping(method = { RequestMethod.GET, RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries") @Override - public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash, + public TypedKVEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash, @PathVariable("address") String address, @RequestParam("keys") String... keys) { return peerService.getQueryService().getDataEntries(ledgerHash, address, keys); } @@ -269,7 +269,7 @@ public class BlockBrowserController implements BlockchainExtendQueryService { @RequestMapping(method = { RequestMethod.GET, RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version") @Override - public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash, + public TypedKVEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash, @PathVariable("address") String address, @RequestBody KVInfoVO kvInfoVO) { return peerService.getQueryService().getDataEntries(ledgerHash, address, kvInfoVO); } @@ -277,7 +277,7 @@ public class BlockBrowserController implements BlockchainExtendQueryService { @RequestMapping(method = { RequestMethod.GET, RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries") @Override - public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash, + public TypedKVEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash, @PathVariable("address") String address, @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { @@ -594,7 +594,7 @@ public class BlockBrowserController implements BlockchainExtendQueryService { */ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users") @Override - public AccountHeader[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, + public BlockchainIdentity[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { return peerService.getQueryService().getUsers(ledgerHash, fromIndex, count); @@ -602,7 +602,7 @@ public class BlockBrowserController implements BlockchainExtendQueryService { @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts") @Override - public AccountHeader[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, + public BlockchainIdentity[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { return peerService.getQueryService().getDataAccounts(ledgerHash, fromIndex, count); @@ -610,7 +610,7 @@ public class BlockBrowserController implements BlockchainExtendQueryService { @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts") @Override - public AccountHeader[] getContractAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, + public BlockchainIdentity[] getContractAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { return peerService.getQueryService().getContractAccounts(ledgerHash, fromIndex, count); diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountAccessPolicy.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountAccessPolicy.java index 2e025bf2..3ffa5536 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountAccessPolicy.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountAccessPolicy.java @@ -2,7 +2,7 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.AccountHeader; +import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.utils.Bytes; /** @@ -19,7 +19,7 @@ public interface AccountAccessPolicy { * @param account * @return Return true if it satisfies this policy, or false if it doesn't; */ - boolean checkDataWriting(AccountHeader account); + boolean checkDataWriting(BlockchainIdentity account); boolean checkRegistering(Bytes address, PubKey pubKey); 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 new file mode 100644 index 00000000..399631ce --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountDecorator.java @@ -0,0 +1,45 @@ +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.Account; +import com.jd.blockchain.ledger.BlockchainIdentity; +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.Dataset; + +public class AccountDecorator implements Account, HashProvable, MerkleSnapshot{ + + private CompositeAccount mklAccount; + + public AccountDecorator(CompositeAccount mklAccount) { + this.mklAccount = mklAccount; + } + + protected Dataset getHeaders() { + return mklAccount.getHeaders(); + } + + + @Override + public HashDigest getRootHash() { + return mklAccount.getRootHash(); + } + + @Override + public HashProof getProof(Bytes key) { + return mklAccount.getProof(key); + } + + @Override + public BlockchainIdentity getID() { + return mklAccount.getID(); + } + + @Override + public Dataset getDataset() { + return mklAccount.getDataset(); + } + +} 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/CompositeAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CompositeAccount.java new file mode 100644 index 00000000..5630917e --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CompositeAccount.java @@ -0,0 +1,12 @@ +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.ledger.Account; +import com.jd.blockchain.ledger.MerkleSnapshot; +import com.jd.blockchain.ledger.TypedValue; +import com.jd.blockchain.utils.Dataset; + +public interface CompositeAccount extends Account, MerkleSnapshot, HashProvable{ + + Dataset getHeaders(); + +} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java index 69dfac2c..19c76463 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java @@ -1,81 +1,72 @@ package com.jd.blockchain.ledger.core; -import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.BytesData; import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.ContractInfo; -import com.jd.blockchain.ledger.MerkleProof; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.utils.Bytes; -public class ContractAccount implements ContractInfo { +public class ContractAccount extends AccountDecorator implements ContractInfo { - private static final Bytes CONTRACT_INFO_PREFIX = Bytes.fromString("INFO" + LedgerConsts.KEY_SEPERATOR); + private static final String CONTRACT_INFO_PREFIX = "INFO" + LedgerConsts.KEY_SEPERATOR; - private static final Bytes CHAIN_CODE_KEY = Bytes.fromString("CHAIN-CODE"); + private static final String CHAIN_CODE_KEY = "CHAIN-CODE"; - private MerkleAccount accBase; - - public ContractAccount(MerkleAccount accBase) { - this.accBase = accBase; + public ContractAccount(CompositeAccount mklAccount) { + super(mklAccount); } @Override public Bytes getAddress() { - return accBase.getAddress(); + return getID().getAddress(); } @Override public PubKey getPubKey() { - return accBase.getPubKey(); - } - - @Override - public HashDigest getRootHash() { - return accBase.getRootHash(); + return getID().getPubKey(); } - public MerkleProof getChaincodeProof() { - return accBase.getProof(CHAIN_CODE_KEY); - } - - public MerkleProof getPropertyProof(Bytes key) { - return accBase.getProof(encodePropertyKey(key)); - } +// public MerkleProof getChaincodeProof() { +// return getHeaders().getProof(CHAIN_CODE_KEY); +// } +// +// public MerkleProof getPropertyProof(Bytes key) { +// return getHeaders().getProof(encodePropertyKey(key)); +// } public long setChaincode(byte[] chaincode, long version) { - BytesValue bytesValue = BytesData.fromBytes(chaincode); - return accBase.setBytes(CHAIN_CODE_KEY, bytesValue, version); + TypedValue bytesValue = TypedValue.fromBytes(chaincode); + return getHeaders().setValue(CHAIN_CODE_KEY, bytesValue, version); } public byte[] getChainCode() { - return accBase.getBytes(CHAIN_CODE_KEY).getValue().toBytes(); + return getHeaders().getValue(CHAIN_CODE_KEY).getBytes().toBytes(); } public byte[] getChainCode(long version) { - return accBase.getBytes(CHAIN_CODE_KEY, version).getValue().toBytes(); + return getHeaders().getValue(CHAIN_CODE_KEY, version).getBytes().toBytes(); } public long getChaincodeVersion() { - return accBase.getVersion(CHAIN_CODE_KEY); + return getHeaders().getVersion(CHAIN_CODE_KEY); } - public long setProperty(Bytes key, String value, long version) { - BytesValue bytesValue = BytesData.fromText(value); - return accBase.setBytes(encodePropertyKey(key), bytesValue, version); + public long setProperty(String key, String value, long version) { + TypedValue bytesValue = TypedValue.fromText(value); + return getHeaders().setValue(encodePropertyKey(key), bytesValue, version); } - public String getProperty(Bytes key) { - BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key)); - return BytesData.toText(bytesValue); + public String getProperty(String key) { + BytesValue bytesValue = getHeaders().getValue(encodePropertyKey(key)); + return TypedValue.wrap(bytesValue).stringValue(); } - public String getProperty(Bytes key, long version) { - BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key), version); - return BytesData.toText(bytesValue); + public String getProperty(String key, long version) { + BytesValue bytesValue = getHeaders().getValue(encodePropertyKey(key), version); + return TypedValue.wrap(bytesValue).stringValue(); } - private Bytes encodePropertyKey(Bytes key) { + private String encodePropertyKey(String key) { return CONTRACT_INFO_PREFIX.concat(key); } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java index 5f4c7855..c4ee0408 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java @@ -2,7 +2,7 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.AccountHeader; +import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.DigitalSignature; import com.jd.blockchain.ledger.MerkleProof; @@ -17,17 +17,18 @@ public class ContractAccountSet implements Transactional, ContractAccountQuery { public ContractAccountSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { - accountSet = new MerkleAccountSet(cryptoSetting, prefix, exStorage, verStorage, accessPolicy); + accountSet = new MerkleAccountSet(cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage, accessPolicy); } public ContractAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, AccountAccessPolicy accessPolicy) { - accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy); + accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage, + readonly, accessPolicy); } @Override - public AccountHeader[] getHeaders(int fromIndex, int count) { + public BlockchainIdentity[] getHeaders(int fromIndex, int count) { return accountSet.getHeaders(fromIndex, count); } @@ -66,7 +67,7 @@ public class ContractAccountSet implements Transactional, ContractAccountQuery { @Override public ContractAccount getAccount(Bytes address) { - MerkleAccount accBase = accountSet.getAccount(address); + CompositeAccount accBase = accountSet.getAccount(address); return new ContractAccount(accBase); } @@ -77,7 +78,7 @@ public class ContractAccountSet implements Transactional, ContractAccountQuery { @Override public ContractAccount getAccount(Bytes address, long version) { - MerkleAccount accBase = accountSet.getAccount(address, version); + CompositeAccount accBase = accountSet.getAccount(address, version); return new ContractAccount(accBase); } @@ -92,7 +93,7 @@ public class ContractAccountSet implements Transactional, ContractAccountQuery { */ public ContractAccount deploy(Bytes address, PubKey pubKey, DigitalSignature addressSignature, byte[] chaincode) { // TODO: 校验和记录合约地址签名; - MerkleAccount accBase = accountSet.register(address, pubKey); + CompositeAccount accBase = accountSet.register(address, pubKey); ContractAccount contractAcc = new ContractAccount(accBase); contractAcc.setChaincode(chaincode, -1); return contractAcc; @@ -107,7 +108,7 @@ public class ContractAccountSet implements Transactional, ContractAccountQuery { * @return 返回链码的新版本号; */ public long update(Bytes address, byte[] chaincode, long version) { - MerkleAccount accBase = accountSet.getAccount(address); + CompositeAccount accBase = accountSet.getAccount(address); ContractAccount contractAcc = new ContractAccount(accBase); return contractAcc.setChaincode(chaincode, version); } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java index afaab416..4814cdf6 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java @@ -1,268 +1,234 @@ package com.jd.blockchain.ledger.core; -import com.jd.blockchain.binaryproto.BinaryProtocol; -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.AccountHeader; -import com.jd.blockchain.ledger.BytesData; -import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.KVDataEntry; -import com.jd.blockchain.ledger.KVDataObject; -import com.jd.blockchain.ledger.MerkleProof; -import com.jd.blockchain.utils.Bytes; - -public class DataAccount implements AccountHeader, MerkleProvable { - - private MerkleAccount baseAccount; - - public DataAccount(MerkleAccount accBase) { - this.baseAccount = accBase; - } - - @Override - public Bytes getAddress() { - return baseAccount.getAddress(); - } - - @Override - public PubKey getPubKey() { - return baseAccount.getPubKey(); - } - - @Override - public HashDigest getRootHash() { - return baseAccount.getRootHash(); - } - - /** - * 返回指定数据的存在性证明; - */ - @Override - public MerkleProof getProof(Bytes key) { - return baseAccount.getProof(key); - } +public class DataAccount extends AccountDecorator { + + public DataAccount(CompositeAccount mklAccount) { + super(mklAccount); + } + +// /** +// * Create or update the value associated the specified key if the version +// * checking is passed.
+// * +// * The value of the key will be updated only if it's latest version equals the +// * specified version argument.
+// * If the key doesn't exist, the version checking will be ignored, and key will +// * be created with a new sequence number as id.
+// * It also could specify the version argument to -1 to ignore the version +// * checking. +// *

+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// * +// * @param key The key of data; +// * @param value The value of data; +// * @param version The expected version of the key. +// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then +// * return -1; +// */ +// public long setBytes(Bytes key, BytesValue value, long version) { +// return super.getDataset().setValue(key, value, version); +// } + +// +// /** +// * Create or update the value associated the specified key if the version +// * checking is passed.
+// * +// * The value of the key will be updated only if it's latest version equals the +// * specified version argument.
+// * If the key doesn't exist, the version checking will be ignored, and key will +// * be created with a new sequence number as id.
+// * It also could specify the version argument to -1 to ignore the version +// * checking. +// *

+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// * +// * @param key The key of data; +// * @param value The value of data; +// * @param version The expected version of the key. +// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then +// * return -1; +// */ +// public long setBytes(Bytes key, String value, long version) { +// BytesValue bytesValue = TypedValue.fromText(value); +// return baseAccount.setValue(key, bytesValue, version); +// } +// +// /** +// * Create or update the value associated the specified key if the version +// * checking is passed.
+// * +// * The value of the key will be updated only if it's latest version equals the +// * specified version argument.
+// * If the key doesn't exist, the version checking will be ignored, and key will +// * be created with a new sequence number as id.
+// * It also could specify the version argument to -1 to ignore the version +// * checking. +// *

+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// * +// * @param key The key of data; +// * @param value The value of data; +// * @param version The expected version of the key. +// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then +// * return -1; +// */ +// public long setBytes(Bytes key, byte[] value, long version) { +// BytesValue bytesValue = TypedValue.fromBytes(value); +// return baseAccount.setValue(key, bytesValue, version); +// } +// +// /** +// * Return the latest version entry associated the specified key; If the key +// * doesn't exist, then return -1; +// * +// * @param key +// * @return +// */ +// public long getDataVersion(String key) { +// return baseAccount.getVersion(Bytes.fromString(key)); +// } +// +// /** +// * Return the latest version entry associated the specified key; If the key +// * doesn't exist, then return -1; +// * +// * @param key +// * @return +// */ +// public long getDataVersion(Bytes key) { +// return baseAccount.getVersion(key); +// } +// +// /** +// * return the latest version's value; +// * +// * @param key +// * @return return null if not exist; +// */ +// public BytesValue getBytes(String key) { +// return baseAccount.getValue(Bytes.fromString(key)); +// } +// +// /** +// * return the latest version's value; +// * +// * @param key +// * @return return null if not exist; +// */ +// public BytesValue getBytes(Bytes key) { +// return baseAccount.getValue(key); +// } +// +// /** +// * return the specified version's value; +// * +// * @param key +// * @param version +// * @return return null if not exist; +// */ +// public BytesValue getBytes(String key, long version) { +// return baseAccount.getValue(Bytes.fromString(key), version); +// } +// +// /** +// * return the specified version's value; +// * +// * @param key +// * @param version +// * @return return null if not exist; +// */ +// public BytesValue getBytes(Bytes key, long version) { +// return baseAccount.getValue(key, version); +// } - - /** - * Create or update the value associated the specified key if the version - * checking is passed.
- * - * The value of the key will be updated only if it's latest version equals the - * specified version argument.
- * If the key doesn't exist, the version checking will be ignored, and key will - * be created with a new sequence number as id.
- * It also could specify the version argument to -1 to ignore the version - * checking. - *

- * If updating is performed, the version of the key increase by 1.
- * If creating is performed, the version of the key initialize by 0.
- * - * @param key The key of data; - * @param value The value of data; - * @param version The expected version of the key. - * @return The new version of the key.
- * If the key is new created success, then return 0;
- * If the key is updated success, then return the new version;
- * If this operation fail by version checking or other reason, then - * return -1; - */ - public long setBytes(Bytes key, BytesValue value, long version) { - return baseAccount.setBytes(key, value, version); - } - - /** - * Create or update the value associated the specified key if the version - * checking is passed.
- * - * The value of the key will be updated only if it's latest version equals the - * specified version argument.
- * If the key doesn't exist, the version checking will be ignored, and key will - * be created with a new sequence number as id.
- * It also could specify the version argument to -1 to ignore the version - * checking. - *

- * If updating is performed, the version of the key increase by 1.
- * If creating is performed, the version of the key initialize by 0.
- * - * @param key The key of data; - * @param value The value of data; - * @param version The expected version of the key. - * @return The new version of the key.
- * If the key is new created success, then return 0;
- * If the key is updated success, then return the new version;
- * If this operation fail by version checking or other reason, then - * return -1; - */ - public long setBytes(Bytes key, String value, long version) { - BytesValue bytesValue = BytesData.fromText(value); - return baseAccount.setBytes(key, bytesValue, version); - } - - /** - * Create or update the value associated the specified key if the version - * checking is passed.
- * - * The value of the key will be updated only if it's latest version equals the - * specified version argument.
- * If the key doesn't exist, the version checking will be ignored, and key will - * be created with a new sequence number as id.
- * It also could specify the version argument to -1 to ignore the version - * checking. - *

- * If updating is performed, the version of the key increase by 1.
- * If creating is performed, the version of the key initialize by 0.
- * - * @param key The key of data; - * @param value The value of data; - * @param version The expected version of the key. - * @return The new version of the key.
- * If the key is new created success, then return 0;
- * If the key is updated success, then return the new version;
- * If this operation fail by version checking or other reason, then - * return -1; - */ - public long setBytes(Bytes key, byte[] value, long version) { - BytesValue bytesValue = BytesData.fromBytes(value); - return baseAccount.setBytes(key, bytesValue, version); - } - - /** - * Return the latest version entry associated the specified key; If the key - * doesn't exist, then return -1; - * - * @param key - * @return - */ - public long getDataVersion(String key) { - return baseAccount.getVersion(Bytes.fromString(key)); - } - - /** - * Return the latest version entry associated the specified key; If the key - * doesn't exist, then return -1; - * - * @param key - * @return - */ - public long getDataVersion(Bytes key) { - return baseAccount.getVersion(key); - } - - /** - * return the latest version's value; - * - * @param key - * @return return null if not exist; - */ - public BytesValue getBytes(String key) { - return baseAccount.getBytes(Bytes.fromString(key)); - } - - /** - * return the latest version's value; - * - * @param key - * @return return null if not exist; - */ - public BytesValue getBytes(Bytes key) { - return baseAccount.getBytes(key); - } - - /** - * return the specified version's value; - * - * @param key - * @param version - * @return return null if not exist; - */ - public BytesValue getBytes(String key, long version) { - return baseAccount.getBytes(Bytes.fromString(key), version); - } - - /** - * return the specified version's value; - * - * @param key - * @param version - * @return return null if not exist; - */ - public BytesValue getBytes(Bytes key, long version) { - return baseAccount.getBytes(key, version); - } - /** - * @param key - * @param version - * @return - */ - public KVDataEntry getDataEntry(String key, long version) { - return getDataEntry(Bytes.fromString(key), version); - } - /** - * @param key - * @param version - * @return - */ - public KVDataEntry getDataEntry(Bytes key, long version) { - BytesValue value = baseAccount.getBytes(key, version); - if (value == null) { - return new KVDataObject(key.toUTF8String(), -1, null); - }else { - return new KVDataObject(key.toUTF8String(), version, value); - } - } - - /** - * return the specified index's KVDataEntry; - * - * @param fromIndex - * @param count - * @return return null if not exist; - */ - - public KVDataEntry[] getDataEntries(int fromIndex, int count) { - if (count == 0 || getDataEntriesTotalCount() == 0) { - return null; - } - - if (count == -1 || count > getDataEntriesTotalCount()) { - fromIndex = 0; - count = (int)getDataEntriesTotalCount(); - } - - if (fromIndex < 0 || fromIndex > getDataEntriesTotalCount() - 1) { - fromIndex = 0; - } - - KVDataEntry[] kvDataEntries = new KVDataEntry[count]; - byte[] value; - String key; - long ver; - for (int i = 0; i < count; i++) { - value = baseAccount.dataset.getValuesAtIndex(fromIndex); - key = baseAccount.dataset.getKeyAtIndex(fromIndex); - ver = baseAccount.dataset.getVersion(key); - BytesValue decodeData = BinaryProtocol.decode(value); - kvDataEntries[i] = new KVDataObject(key, ver, decodeData); - fromIndex++; - } - - return kvDataEntries; - } - - /** - * return the dataAccount's kv total count; - * - * @param - * @param - * @return return total count; - */ - public long getDataEntriesTotalCount() { - if(baseAccount == null){ - return 0; - } - return baseAccount.dataset.getDataCount(); - } +// /** +// * @param key +// * @param version +// * @return +// */ +// public KVDataEntry getDataEntry(String key, long version) { +// return getDataEntry(Bytes.fromString(key), version); +// } +// +// /** +// * @param key +// * @param version +// * @return +// */ +// public KVDataEntry getDataEntry(Bytes key, long version) { +// BytesValue value = baseAccount.getValue(key, version); +// if (value == null) { +// return new KVDataObject(key.toUTF8String(), -1, null); +// }else { +// return new KVDataObject(key.toUTF8String(), version, value); +// } +// } +// +// /** +// * return the specified index's KVDataEntry; +// * +// * @param fromIndex +// * @param count +// * @return return null if not exist; +// */ +// +// public KVDataEntry[] getDataEntries(int fromIndex, int count) { +// if (count == 0 || getDataEntriesTotalCount() == 0) { +// return null; +// } +// +// if (count == -1 || count > getDataEntriesTotalCount()) { +// fromIndex = 0; +// count = (int)getDataEntriesTotalCount(); +// } +// +// if (fromIndex < 0 || fromIndex > getDataEntriesTotalCount() - 1) { +// fromIndex = 0; +// } +// +// KVDataEntry[] kvDataEntries = new KVDataEntry[count]; +// byte[] value; +// String key; +// long ver; +// for (int i = 0; i < count; i++) { +// value = baseAccount.dataset.getValuesAtIndex(fromIndex); +// key = baseAccount.dataset.getKeyAtIndex(fromIndex); +// ver = baseAccount.dataset.getVersion(key); +// BytesValue decodeData = BinaryProtocol.decode(value); +// kvDataEntries[i] = new KVDataObject(key, ver, decodeData); +// fromIndex++; +// } +// +// return kvDataEntries; +// } +// +// /** +// * return the dataAccount's kv total count; +// * +// * @param +// * @param +// * @return return total count; +// */ +// public long getDataEntriesTotalCount() { +// if(baseAccount == null){ +// return 0; +// } +// return baseAccount.dataset.getDataCount(); +// } } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java index f693211b..0f849c1d 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java @@ -2,7 +2,7 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.AccountHeader; +import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.DigitalSignature; import com.jd.blockchain.ledger.MerkleProof; @@ -17,17 +17,18 @@ public class DataAccountSet implements Transactional, DataAccountQuery { public DataAccountSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { - accountSet = new MerkleAccountSet(cryptoSetting, prefix, exStorage, verStorage, accessPolicy); + accountSet = new MerkleAccountSet(cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage, accessPolicy); } public DataAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, AccountAccessPolicy accessPolicy) { - accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy); + accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage, + readonly, accessPolicy); } @Override - public AccountHeader[] getHeaders(int fromIndex, int count) { + public BlockchainIdentity[] getHeaders(int fromIndex, int count) { return accountSet.getHeaders(fromIndex, count); } @@ -64,7 +65,7 @@ public class DataAccountSet implements Transactional, DataAccountQuery { public DataAccount register(Bytes address, PubKey pubKey, DigitalSignature addressSignature) { // TODO: 未实现对地址签名的校验和记录; - MerkleAccount accBase = accountSet.register(address, pubKey); + CompositeAccount accBase = accountSet.register(address, pubKey); return new DataAccount(accBase); } @@ -82,7 +83,7 @@ public class DataAccountSet implements Transactional, DataAccountQuery { */ @Override public DataAccount getAccount(Bytes address) { - MerkleAccount accBase = accountSet.getAccount(address); + CompositeAccount accBase = accountSet.getAccount(address); if (accBase == null) { return null; } @@ -91,7 +92,7 @@ public class DataAccountSet implements Transactional, DataAccountQuery { @Override public DataAccount getAccount(Bytes address, long version) { - MerkleAccount accBase = accountSet.getAccount(address, version); + CompositeAccount accBase = accountSet.getAccount(address, version); return new DataAccount(accBase); } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyAccountSet.java index 879bf702..8cfdd7fc 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyAccountSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyAccountSet.java @@ -1,13 +1,13 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.AccountHeader; +import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.MerkleProof; import com.jd.blockchain.utils.Bytes; public class EmptyAccountSet implements AccountQuery { - private static final AccountHeader[] EMPTY = {}; + private static final BlockchainIdentity[] EMPTY = {}; @Override public HashDigest getRootHash() { @@ -20,7 +20,7 @@ public class EmptyAccountSet implements AccountQuery { } @Override - public AccountHeader[] getHeaders(int fromIndex, int count) { + public BlockchainIdentity[] getHeaders(int fromIndex, int count) { return EMPTY; } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenericAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenericAccountSet.java new file mode 100644 index 00000000..372163e1 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenericAccountSet.java @@ -0,0 +1,92 @@ +//package com.jd.blockchain.ledger.core; +// +//import com.jd.blockchain.crypto.HashDigest; +//import com.jd.blockchain.ledger.AccountHeader; +//import com.jd.blockchain.ledger.CryptoSetting; +//import com.jd.blockchain.ledger.MerkleProof; +//import com.jd.blockchain.storage.service.ExPolicyKVStorage; +//import com.jd.blockchain.storage.service.VersioningKVStorage; +//import com.jd.blockchain.utils.Bytes; +//import com.jd.blockchain.utils.Transactional; +// +//public class GenericAccountSet> implements AccountQuery, Transactional { +// +// private Class headerType; +// +// private MerkleAccountSet merkleAccountSet; +// +// public GenericAccountSet(Class headerType, CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, +// VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { +// this(headerType, null, cryptoSetting, keyPrefix, exStorage, verStorage, false, accessPolicy); +// } +// +// public GenericAccountSet(Class headerType, HashDigest rootHash, CryptoSetting cryptoSetting, String keyPrefix, +// ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, +// AccountAccessPolicy accessPolicy) { +// this.headerType = headerType; +// this.merkleAccountSet = new MerkleAccountSet(rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly, accessPolicy); +// } +// +// @Override +// public MerkleProof getProof(Bytes address) { +// return merkleAccountSet.getProof(address); +// } +// +// @Override +// public HashDigest getRootHash() { +// return merkleAccountSet.getRootHash(); +// } +// +// @Override +// public boolean isUpdated() { +// return merkleAccountSet.isUpdated(); +// } +// +// @Override +// public void commit() { +// merkleAccountSet.commit(); +// } +// +// @Override +// public void cancel() { +// merkleAccountSet.cancel(); +// } +// +// @Override +// public H[] getHeaders(int fromIndex, int count) { +// merkleAccountSet.getHeaders(fromIndex, count) +// return null; +// } +// +// @Override +// public long getTotal() { +// // TODO Auto-generated method stub +// return 0; +// } +// +// @Override +// public boolean contains(Bytes address) { +// // TODO Auto-generated method stub +// return false; +// } +// +// @Override +// public T getAccount(String address) { +// // TODO Auto-generated method stub +// return null; +// } +// +// @Override +// public T getAccount(Bytes address) { +// // TODO Auto-generated method stub +// return null; +// } +// +// @Override +// public T getAccount(Bytes address, long version) { +// // TODO Auto-generated method stub +// return null; +// } +// +// +//} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/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/LedgerQueryService.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java index 55b989d5..c58d5a5c 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java @@ -5,11 +5,12 @@ import java.util.List; import com.jd.blockchain.contract.ContractException; import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.AccountHeader; +import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.ContractInfo; -import com.jd.blockchain.ledger.KVDataEntry; -import com.jd.blockchain.ledger.KVDataObject; +import com.jd.blockchain.ledger.TypedKVEntry; +import com.jd.blockchain.ledger.TypedValue; +import com.jd.blockchain.ledger.TypedKVData; import com.jd.blockchain.ledger.KVDataVO; import com.jd.blockchain.ledger.KVInfoVO; import com.jd.blockchain.ledger.LedgerAdminInfo; @@ -22,22 +23,25 @@ import com.jd.blockchain.ledger.ParticipantNode; import com.jd.blockchain.ledger.TransactionState; import com.jd.blockchain.ledger.UserInfo; import com.jd.blockchain.transaction.BlockchainQueryService; +import com.jd.blockchain.utils.ArrayUtils; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; +import com.jd.blockchain.utils.DataIterator; import com.jd.blockchain.utils.QueryUtil; public class LedgerQueryService implements BlockchainQueryService { - private static final KVDataEntry[] EMPTY_ENTRIES = new KVDataEntry[0]; - + private static final TypedKVEntry[] EMPTY_ENTRIES = new TypedKVEntry[0]; + private HashDigest[] ledgerHashs; private LedgerQuery ledger; public LedgerQueryService(LedgerQuery ledger) { this.ledger = ledger; - this.ledgerHashs = new HashDigest[] {ledger.getHash()}; + this.ledgerHashs = new HashDigest[] { ledger.getHash() }; } - + private void checkLedgerHash(HashDigest ledgerHash) { if (!ledgerHashs[0].equals(ledgerHash)) { throw new LedgerException("Unsupport cross chain query!"); @@ -58,7 +62,7 @@ public class LedgerQueryService implements BlockchainQueryService { ledgerInfo.setLatestBlockHeight(ledger.getLatestBlockHeight()); return ledgerInfo; } - + @Override public LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash) { checkLedgerHash(ledgerHash); @@ -270,15 +274,15 @@ public class LedgerQueryService implements BlockchainQueryService { } @Override - public AccountHeader getDataAccount(HashDigest ledgerHash, String address) { + public BlockchainIdentity getDataAccount(HashDigest ledgerHash, String address) { checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); - return dataAccountSet.getAccount(Bytes.fromBase58(address)); + return dataAccountSet.getAccount(Bytes.fromBase58(address)).getID(); } @Override - public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) { + public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) { if (keys == null || keys.length == 0) { return EMPTY_ENTRIES; } @@ -287,25 +291,26 @@ public class LedgerQueryService implements BlockchainQueryService { DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); - KVDataEntry[] entries = new KVDataEntry[keys.length]; + + TypedKVEntry[] entries = new TypedKVEntry[keys.length]; long ver; for (int i = 0; i < entries.length; i++) { final String currKey = keys[i]; - ver = dataAccount == null ? -1 : dataAccount.getDataVersion(Bytes.fromString(currKey)); + ver = dataAccount == null ? -1 : dataAccount.getDataset().getVersion(currKey); if (ver < 0) { - entries[i] = new KVDataObject(currKey, -1, null); + entries[i] = new TypedKVData(currKey, -1, null); } else { - BytesValue value = dataAccount.getBytes(Bytes.fromString(currKey), ver); - entries[i] = new KVDataObject(currKey, ver, value); + BytesValue value = dataAccount.getDataset().getValue(currKey, ver); + entries[i] = new TypedKVData(currKey, ver, value); } } return entries; } - public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) { + public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) { // parse kvInfoVO; List keyList = new ArrayList<>(); List versionList = new ArrayList<>(); @@ -335,22 +340,22 @@ public class LedgerQueryService implements BlockchainQueryService { DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); - KVDataEntry[] entries = new KVDataEntry[keys.length]; + TypedKVEntry[] entries = new TypedKVEntry[keys.length]; long ver = -1; for (int i = 0; i < entries.length; i++) { // ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); // dataAccount.getBytes(Bytes.fromString(keys[i]),1); ver = versions[i]; if (ver < 0) { - entries[i] = new KVDataObject(keys[i], -1, null); + entries[i] = new TypedKVData(keys[i], -1, null); } else { - if (dataAccount.getDataEntriesTotalCount() == 0 - || dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null) { + if (dataAccount.getDataset().getDataCount() == 0 + || dataAccount.getDataset().getValue(keys[i], ver) == null) { // is the address is not exist; the result is null; - entries[i] = new KVDataObject(keys[i], -1, null); + entries[i] = new TypedKVData(keys[i], -1, null); } else { - BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); - entries[i] = new KVDataObject(keys[i], ver, value); + BytesValue value = dataAccount.getDataset().getValue(keys[i], ver); + entries[i] = new TypedKVData(keys[i], ver, value); } } } @@ -359,14 +364,22 @@ public class LedgerQueryService implements BlockchainQueryService { } @Override - public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) { + public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) { checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); - int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataEntriesTotalCount()); - return dataAccount.getDataEntries(pages[0], pages[1]); +// int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataset().getDataCount()); +// return dataAccount.getDataset().getDataEntry(key, version).getDataEntries(pages[0], pages[1]); + + DataIterator iterator = dataAccount.getDataset().iterator(); + iterator.skip(fromIndex); + DataEntry[] dataEntries = iterator.next(count); + + TypedKVEntry[] typedKVEntries = ArrayUtils.castTo(dataEntries, TypedKVEntry.class, + e -> e == null ? null : new TypedKVData(e.getKey(), e.getVersion(), e.getValue())); + return typedKVEntries; } @Override @@ -376,7 +389,7 @@ public class LedgerQueryService implements BlockchainQueryService { DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); - return dataAccount.getDataEntriesTotalCount(); + return dataAccount.getDataset().getDataCount(); } @Override @@ -388,7 +401,7 @@ public class LedgerQueryService implements BlockchainQueryService { } @Override - public AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count) { + public BlockchainIdentity[] getUsers(HashDigest ledgerHash, int fromIndex, int count) { checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); @@ -397,7 +410,7 @@ public class LedgerQueryService implements BlockchainQueryService { } @Override - public AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) { + public BlockchainIdentity[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) { checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); @@ -406,7 +419,7 @@ public class LedgerQueryService implements BlockchainQueryService { } @Override - public AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) { + public BlockchainIdentity[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) { checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccount.java index 49ef5753..dc0169a5 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccount.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccount.java @@ -3,15 +3,21 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.AccountHeader; import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.BlockchainIdentityData; import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.CryptoSetting; +import com.jd.blockchain.ledger.HashProof; +import com.jd.blockchain.ledger.LedgerException; import com.jd.blockchain.ledger.MerkleProof; +import com.jd.blockchain.ledger.MerkleSnapshot; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.Dataset; +import com.jd.blockchain.utils.DatasetHelper; +import com.jd.blockchain.utils.DatasetHelper.DataChangedListener; +import com.jd.blockchain.utils.DatasetHelper.TypeMapper; import com.jd.blockchain.utils.Transactional; /** @@ -20,94 +26,166 @@ import com.jd.blockchain.utils.Transactional; * @author huanghaiquan * */ -public class MerkleAccount implements AccountHeader, MerkleProvable, Transactional { +public class MerkleAccount implements CompositeAccount, HashProvable, MerkleSnapshot, Transactional { - private BlockchainIdentity bcid; + private static final Bytes HEADER_PREFIX = Bytes.fromString("HD/"); + private static final Bytes DATA_PREFIX = Bytes.fromString("DT/"); - protected MerkleDataSet dataset; + private static final Bytes KEY_HEADER_ROOT = Bytes.fromString("HEADER"); + + private static final Bytes KEY_DATA_ROOT = Bytes.fromString("DATA"); + + private static final String KEY_PUBKEY = "PUBKEY"; + + private BlockchainIdentity accountID; + + private MerkleDataSet rootDataset; + + private MerkleDataSet headerDataset; + + private MerkleDataSet dataDataset; + + private Dataset typedHeader; + + private Dataset typedData; + +// private long version; /** - * Create a new Account with the specified address and pubkey;
+ * Create a new Account with the specified identity(address and pubkey);
* * At the same time, a empty merkle dataset is also created for this account, * which is used for storing data of this account.
- * - * Note that, the blockchain identity of the account is not stored in the - * account's merkle dataset, but is stored by the outer invoker; * - * @param address - * @param pubKey + * This new account will be writable.
+ * + * @param accountID Identity of this new account; + * @param cryptoSetting Settings about crypto operations; + * @param keyPrefix Prefix of all keys in this account's dataset; + * @param exStorage The base storage for existance operation; + * @param verStorage The base storage for versioning operation; */ - public MerkleAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix, + public MerkleAccount(BlockchainIdentity accountID, CryptoSetting cryptoSetting, Bytes keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) { - this(address, pubKey, null, cryptoSetting, keyPrefix, exStorage, verStorage, false); + // 初始化数据集; + initializeDatasets(null, cryptoSetting, keyPrefix, exStorage, verStorage, false); + + initPubKey(accountID.getPubKey()); + this.accountID = accountID; } /** - * Create a new Account with the specified address and pubkey;
+ * Create a account instance with the specified address and root hash; load it's + * merkle dataset from the specified root hash. This merkle dateset is used for + * storing data of this account.
* - * At the same time, a empty merkle dataset is also created for this account, - * which is used for storing data of this account.
- * - * Note that, the blockchain identity of the account is not stored in the - * account's merkle dataset, but is stored by the outer invoker; - * - * @param bcid - * @param cryptoSetting - * @param exStorage - * @param verStorage - * @param accessPolicy + * @param address Address of this account; + * @param rootHash Merkle root hash of this account; It can not be null; + * @param cryptoSetting Settings about crypto operations; + * @param keyPrefix Prefix of all keys in this account's dataset; + * @param exStorage The base storage for existance operation; + * @param verStorage The base storage for versioning operation; + * @param readonly Readonly about this account's dataset; */ - public MerkleAccount(BlockchainIdentity bcid, CryptoSetting cryptoSetting, String keyPrefix, - ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) { - this(bcid, null, cryptoSetting, keyPrefix, exStorage, verStorage, false); + public MerkleAccount(Bytes address, HashDigest rootHash, CryptoSetting cryptoSetting, Bytes keyPrefix, + ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) { + if (rootHash == null) { + throw new IllegalArgumentException("Specified a null root hash for account[" + address.toBase58() + "]!"); + } + + // 初始化数据集; + initializeDatasets(rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); + + // 初始化账户的身份; + PubKey pubKey = loadPubKey(); + this.accountID = new AccountID(address, pubKey); } - /** - * Create a account instance with the specified address and pubkey and load it's - * merkle dataset from the specified root hash. This merkle dateset is used for storing data - * of this account.
- * - * @param address - * @param pubKey - * @param dataRootHash merkle root hash of account's data; if set to a null value, - * an empty merkle dataset is created; - * @param cryptoSetting - * @param exStorage - * @param verStorage - * @param readonly - * @param accessPolicy - */ - public MerkleAccount(Bytes address, PubKey pubKey, HashDigest dataRootHash, CryptoSetting cryptoSetting, - String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) { - this(new BlockchainIdentityData(address, pubKey), dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, + private void initializeDatasets(HashDigest rootHash, CryptoSetting cryptoSetting, Bytes keyPrefix, + ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) { + // 加载“根数据集” + this.rootDataset = new MerkleDataSet(rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); + + // 初始化数据修改监听器; + DataChangedListener dataChangedListener = new DataChangedListener() { + @Override + public void onChanged(String key, TypedValue value, long expectedVersion, long newVersion) { + onUpdated(key, value, expectedVersion, newVersion); + } + }; + + TypeMapper valueMapper = new TypeMapper() { + + @Override + public byte[] encode(TypedValue t2) { + return BinaryProtocol.encode(t2, BytesValue.class); + } + + @Override + public TypedValue decode(byte[] t1) { + BytesValue v = BinaryProtocol.decodeAs(t1, BytesValue.class); + return TypedValue.wrap(v); + } + }; + + // 加载“头数据集”; + HashDigest headerRoot = loadHeaderRoot(); + Bytes headerPrefix = keyPrefix.concat(HEADER_PREFIX); + this.headerDataset = new MerkleDataSet(headerRoot, cryptoSetting, headerPrefix, exStorage, verStorage, readonly); + this.typedHeader = DatasetHelper.listen(DatasetHelper.map(headerDataset, valueMapper), dataChangedListener); + + // 加载“主数据集” + HashDigest dataRoot = loadDataRoot(); + Bytes dataPrefix = keyPrefix.concat(DATA_PREFIX); + this.dataDataset = new MerkleDataSet(dataRoot, cryptoSetting, dataPrefix, exStorage, verStorage, readonly); + this.typedData = DatasetHelper.listen(DatasetHelper.map(dataDataset, valueMapper), dataChangedListener); } - public MerkleAccount(BlockchainIdentity bcid, HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix, - ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) { - this.bcid = bcid; - this.dataset = new MerkleDataSet(dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); + private HashDigest loadHeaderRoot() { + byte[] hashBytes = rootDataset.getValue(KEY_HEADER_ROOT); + if (hashBytes == null) { + return null; + } + return new HashDigest(hashBytes); + } + + private HashDigest loadDataRoot() { + byte[] hashBytes = rootDataset.getValue(KEY_DATA_ROOT); + if (hashBytes == null) { + return null; + } + return new HashDigest(hashBytes); + } + + private long getHeaderRootVersion() { + return rootDataset.getVersion(KEY_HEADER_ROOT); + } + + private long getDataRootVersion() { + return rootDataset.getVersion(KEY_DATA_ROOT); } - /* - * (non-Javadoc) - * - * @see com.jd.blockchain.ledger.core.AccountDataSet#getAddress() - */ - @Override public Bytes getAddress() { - return bcid.getAddress(); + return accountID.getAddress(); } - /* - * (non-Javadoc) - * - * @see com.jd.blockchain.ledger.core.AccountDataSet#getPubKey() - */ - @Override public PubKey getPubKey() { - return bcid.getPubKey(); + return accountID.getPubKey(); + } + + @Override + public BlockchainIdentity getID() { + return accountID; + } + + public Dataset getHeaders() { + return typedHeader; + } + + @Override + public Dataset getDataset() { + return typedData; } /* @@ -117,12 +195,22 @@ public class MerkleAccount implements AccountHeader, MerkleProvable, Transaction */ @Override public HashDigest getRootHash() { - return dataset.getRootHash(); + return rootDataset.getRootHash(); } @Override - public MerkleProof getProof(Bytes key) { - return dataset.getProof(key); + public HashProof getProof(Bytes key) { + MerkleProof dataProof = dataDataset.getProof(key); + if (dataProof == null) { + return null; + } + MerkleProof rootProof = rootDataset.getProof(KEY_DATA_ROOT); + if (rootProof == null) { + return null; + } + HashDegistList proof = new HashDegistList(rootProof); + proof.concat(dataProof); + return proof; } /** @@ -131,90 +219,298 @@ public class MerkleAccount implements AccountHeader, MerkleProvable, Transaction * @return */ public boolean isReadonly() { - return dataset.isReadonly(); + return dataDataset.isReadonly() || headerDataset.isReadonly(); } /** - * Create or update the value associated the specified key if the version - * checking is passed.
- * - * The value of the key will be updated only if it's latest version equals the - * specified version argument.
- * If the key doesn't exist, the version checking will be ignored, and key will - * be created with a new sequence number as id.
- * It also could specify the version argument to -1 to ignore the version - * checking. - *

- * If updating is performed, the version of the key increase by 1.
- * If creating is performed, the version of the key initialize by 0.
+ * 初始化账户的公钥; * - * @param key The key of data; - * @param value The value of data; - * @param version The expected version of the key. - * @return The new version of the key.
- * If the key is new created success, then return 0;
- * If the key is updated success, then return the new version;
- * If this operation fail by version checking or other reason, then - * return -1; + * @param pubKey */ - public long setBytes(Bytes key, BytesValue value, long version) { - byte[] bytesValue = BinaryProtocol.encode(value, BytesValue.class); - return dataset.setValue(key, bytesValue, version); + private void initPubKey(PubKey pubKey) { + long v = typedHeader.setValue(KEY_PUBKEY, TypedValue.fromPubKey(pubKey), -1); + if (v < 0) { + throw new LedgerException("PubKey storage conflict!"); + } } /** - * Return the latest version entry associated the specified key; If the key - * doesn't exist, then return -1; + * 加载公钥; * - * @param key * @return */ - public long getVersion(Bytes key) { - return dataset.getVersion(key); + private PubKey loadPubKey() { + TypedValue value = typedHeader.getValue(KEY_PUBKEY); + if (value == null) { + return null; + } + return value.pubKeyValue(); } /** - * return the latest version's value; + * 当写入新值时触发此方法; * * @param key - * @return return null if not exist; + * @param value + * @param newVersion */ - public BytesValue getBytes(Bytes key) { - byte[] bytesValue = dataset.getValue(key); - if (bytesValue == null) { - return null; - } - return BinaryProtocol.decodeAs(bytesValue, BytesValue.class); + protected void onUpdated(String key, TypedValue value, long expectedVersion, long newVersion) { } /** - * Return the specified version's value; + * 当账户数据提交后触发此方法;
* - * @param key - * @param version - * @return return null if not exist; + * 此方法默认会返回新的账户版本号,等于当前版本号加 1 ; + * + * @param previousRootHash 提交前的根哈希;如果是新账户的首次提交,则为 null; + * @param newRootHash 新的根哈希; */ - public BytesValue getBytes(Bytes key, long version) { - byte[] bytesValue = dataset.getValue(key, version); - if (bytesValue == null) { - return null; - } - return BinaryProtocol.decodeAs(bytesValue, BytesValue.class); + protected void onCommited(HashDigest previousRootHash, HashDigest newRootHash) { } @Override public boolean isUpdated() { - return dataset.isUpdated(); + return headerDataset.isUpdated() || dataDataset.isUpdated() || rootDataset.isUpdated(); } @Override public void commit() { - dataset.commit(); + if (headerDataset.isUpdated()) { + headerDataset.commit(); + long version = getHeaderRootVersion(); + rootDataset.setValue(KEY_HEADER_ROOT, headerDataset.getRootHash().toBytes(), version); + } + if (dataDataset.isUpdated()) { + long version = getDataRootVersion(); + dataDataset.commit(); + rootDataset.setValue(KEY_DATA_ROOT, dataDataset.getRootHash().toBytes(), version); + } + + if (rootDataset.isUpdated()) { + HashDigest previousRootHash = rootDataset.getRootHash(); + rootDataset.commit(); + onCommited(previousRootHash, rootDataset.getRootHash()); + } } @Override public void cancel() { - dataset.cancel(); + headerDataset.cancel(); + dataDataset.cancel(); + rootDataset.cancel(); + } + + // ---------------------- + + private class AccountID implements BlockchainIdentity { + + private Bytes address; + + private PubKey pubKey; + + public AccountID(Bytes address, PubKey pubKey) { + this.address = address; + this.pubKey = pubKey; + } + + @Override + public Bytes getAddress() { + return address; + } + + @Override + public PubKey getPubKey() { + return pubKey; + } + } +// private static class MerkleDatasetAdapter implements Dataset { +// +// private static DataChangedListener NULL_LISTENER = new DataChangedListener() { +// @Override +// public void onChanged(Bytes key, BytesValue value, long newVersion) { +// } +// }; +// +// private DataChangedListener changedListener; +// +// private MerkleDataSet dataset; +// +// public MerkleDataSet getDataset() { +// return dataset; +// } +// +// @SuppressWarnings("unused") +// public MerkleDatasetAdapter(MerkleDataSet dataset) { +// this(dataset, NULL_LISTENER); +// } +// +// public MerkleDatasetAdapter(MerkleDataSet dataset, DataChangedListener listener) { +// this.dataset = dataset; +// this.changedListener = listener == null ? NULL_LISTENER : listener; +// } +// +// @Override +// public DataEntry getDataEntry(String key) { +// return new VersioningKVEntryWraper(dataset.getDataEntry(Bytes.fromString(key))); +// } +// +// @Override +// public DataEntry getDataEntry(String key, long version) { +// return new VersioningKVEntryWraper(dataset.getDataEntry(Bytes.fromString(key), version)); +// } +// +// /** +// * Create or update the value associated the specified key if the version +// * checking is passed.
+// * +// * The value of the key will be updated only if it's latest version equals the +// * specified version argument.
+// * If the key doesn't exist, the version checking will be ignored, and key will +// * be created with a new sequence number as id.
+// * It also could specify the version argument to -1 to ignore the version +// * checking. +// *

+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// * +// * @param key The key of data; +// * @param value The value of data; +// * @param version The expected version of the key. +// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then +// * return -1; +// */ +// @Override +// public long setValue(Bytes key, BytesValue value, long version) { +// byte[] bytesValue = BinaryProtocol.encode(value, BytesValue.class); +// long v = dataset.setValue(key, bytesValue, version); +// if (v > -1) { +// changedListener.onChanged(key, value, v); +// } +// return v; +// } +// +// /** +// * Return the latest version entry associated the specified key; If the key +// * doesn't exist, then return -1; +// * +// * @param key +// * @return +// */ +// @Override +// public long getVersion(Bytes key) { +// return dataset.getVersion(key); +// } +// +// /** +// * return the latest version's value; +// * +// * @param key +// * @return return null if not exist; +// */ +// @Override +// public BytesValue getValue(Bytes key) { +// byte[] bytesValue = dataset.getValue(key); +// if (bytesValue == null) { +// return null; +// } +// return BinaryProtocol.decodeAs(bytesValue, BytesValue.class); +// } +// +// /** +// * Return the specified version's value; +// * +// * @param key +// * @param version +// * @return return null if not exist; +// */ +// @Override +// public BytesValue getValue(Bytes key, long version) { +// byte[] bytesValue = dataset.getValue(key, version); +// if (bytesValue == null) { +// return null; +// } +// return BinaryProtocol.decodeAs(bytesValue, BytesValue.class); +// } +// +// @Override +// public long getDataCount() { +// return dataset.getDataCount(); +// } +// +// @Override +// public long setValue(String key, BytesValue value, long version) { +// byte[] bytesValue = BinaryProtocol.encode(value, BytesValue.class); +// return dataset.setValue(key, bytesValue, version); +// } +// +// @Override +// public BytesValue getValue(String key, long version) { +// byte[] bytesValue = dataset.getValue(key, version); +// if (bytesValue == null) { +// return null; +// } +// return BinaryProtocol.decodeAs(bytesValue, BytesValue.class); +// } +// +// @Override +// public BytesValue getValue(String key) { +// byte[] bytesValue = dataset.getValue(key); +// if (bytesValue == null) { +// return null; +// } +// return BinaryProtocol.decodeAs(bytesValue, BytesValue.class); +// } +// +// @Override +// public long getVersion(String key) { +// return dataset.getVersion(key); +// } +// +// @Override +// public DataEntry getDataEntry(String key) { +// return new VersioningKVEntryWraper(dataset.getDataEntry(key)); +// } +// +// @Override +// public DataEntry getDataEntry(String key, long version) { +// return new VersioningKVEntryWraper(dataset.getDataEntry(key, version)); +// } +// } + +// private static interface DataChangedListener { +// +// void onChanged(Bytes key, BytesValue value, long newVersion); +// +// } + +// private static class VersioningKVEntryWraper implements DataEntry { +// +// private DataEntry kv; +// +// public VersioningKVEntryWraper(DataEntry kv) { +// this.kv = kv; +// } +// +// @Override +// public String getKey() { +// return kv.getKey().toUTF8String(); +// } +// +// @Override +// public long getVersion() { +// return kv.getVersion(); +// } +// +// @Override +// public BytesValue getValue() { +// return BinaryProtocol.decodeAs(kv.getValue(), BytesValue.class); +// } +// +// } + } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountHeader.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountHeader.java new file mode 100644 index 00000000..94faeb6a --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountHeader.java @@ -0,0 +1,12 @@ +//package com.jd.blockchain.ledger.core; +// +//import com.jd.blockchain.binaryproto.DataField; +//import com.jd.blockchain.ledger.BlockchainIdentity; +//import com.jd.blockchain.ledger.MerkleSnapshot; +// +//public interface MerkleAccountHeader extends MerkleSnapshot { +// +// @DataField(order = 1, refContract = true) +// BlockchainIdentity getID(); +// +//} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java index d3e507ba..8f46e235 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java @@ -3,31 +3,35 @@ package com.jd.blockchain.ledger.core; import java.util.HashMap; import java.util.Map; -import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.AccountHeader; -import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.BlockchainIdentityData; import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.LedgerException; import com.jd.blockchain.ledger.MerkleProof; import com.jd.blockchain.ledger.MerkleSnapshot; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; import com.jd.blockchain.utils.Transactional; -public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQuery { +public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQuery { static { DataContractRegistry.register(MerkleSnapshot.class); - DataContractRegistry.register(AccountHeader.class); + DataContractRegistry.register(BlockchainIdentity.class); } - private final String keyPrefix; + private final Bytes keyPrefix; + /** + * 账户根哈希的数据集; + */ private MerkleDataSet merkleDataset; /** @@ -36,7 +40,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ * */ // TODO:未考虑大数据量时,由于缺少过期策略,会导致内存溢出的问题; - private Map latestAccountsCache = new HashMap<>(); + private Map latestAccountsCache = new HashMap<>(); private ExPolicyKVStorage baseExStorage; @@ -44,7 +48,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ private CryptoSetting cryptoSetting; - private boolean updated; + private volatile boolean updated; private AccountAccessPolicy accessPolicy; @@ -56,12 +60,12 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ merkleDataset.setReadonly(); } - public MerkleAccountSet(CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, + public MerkleAccountSet(CryptoSetting cryptoSetting, Bytes keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { this(null, cryptoSetting, keyPrefix, exStorage, verStorage, false, accessPolicy); } - public MerkleAccountSet(HashDigest rootHash, CryptoSetting cryptoSetting, String keyPrefix, + public MerkleAccountSet(HashDigest rootHash, CryptoSetting cryptoSetting, Bytes keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, AccountAccessPolicy accessPolicy) { this.keyPrefix = keyPrefix; @@ -70,6 +74,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ this.baseVerStorage = verStorage; this.merkleDataset = new MerkleDataSet(rootHash, cryptoSetting, keyPrefix, this.baseExStorage, this.baseVerStorage, readonly); + this.accessPolicy = accessPolicy; } @@ -83,29 +88,17 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ return merkleDataset.getProof(key); } - public AccountHeader[] getHeaders(int fromIndex, int count) { - byte[][] results = merkleDataset.getLatestValues(fromIndex, count); - AccountHeader[] accounts = new AccountHeader[results.length]; + @Override + public BlockchainIdentity[] getHeaders(int fromIndex, int count) { + DataEntry[] results = merkleDataset.getLatestDataEntries(fromIndex, count); + BlockchainIdentity[] ids = new BlockchainIdentity[results.length]; for (int i = 0; i < results.length; i++) { - accounts[i] = deserialize(results[i]); + InnerMerkleAccount account = createAccount(results[i].getKey(), new HashDigest(results[i].getValue()), + results[i].getVersion(), true); + ids[i] = account.getID(); } - return accounts; - } - - // private VersioningAccount deserialize(byte[] txBytes) { - //// return BinaryEncodingUtils.decode(txBytes, null, Account.class); - // AccountHeaderData accInfo = BinaryEncodingUtils.decode(txBytes); - //// return new BaseAccount(accInfo.getAddress(), accInfo.getPubKey(), null, - // cryptoSetting, - //// baseExStorage, baseVerStorage, true, accessPolicy); - // return new VersioningAccount(accInfo.getAddress(), accInfo.getPubKey(), - // accInfo.getRootHash(), cryptoSetting, - // keyPrefix, baseExStorage, baseVerStorage, true, accessPolicy, accInfo.); - // } - - private AccountHeader deserialize(byte[] txBytes) { - return BinaryProtocol.decode(txBytes); + return ids; } /** @@ -118,7 +111,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ } @Override - public MerkleAccount getAccount(String address) { + public CompositeAccount getAccount(String address) { return getAccount(Bytes.fromBase58(address)); } @@ -128,7 +121,8 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ * @param address * @return */ - public MerkleAccount getAccount(Bytes address) { + @Override + public CompositeAccount getAccount(Bytes address) { return this.getAccount(address, -1); } @@ -142,25 +136,30 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ * @return */ public boolean contains(Bytes address) { - long latestVersion = getVersion(address); + InnerMerkleAccount acc = latestAccountsCache.get(address); + if (acc != null) { + // 无论是新注册未提交的,还是缓存已提交的账户实例,都认为是存在; + return true; + } + long latestVersion = merkleDataset.getVersion(address); return latestVersion > -1; } /** * 返回指定账户的版本;
* 如果账户已经注册,则返回该账户的最新版本,值大于等于 0;
- * 如果账户不存在,则返回 -1;
- * 如果指定的账户已经注册(通过 {@link #register(String, PubKey)} 方法),但尚未提交(通过 - * {@link #commit()} 方法),此方法对该账户仍然返回 0; + * 如果账户不存在,则返回 -1;
+ * 如果账户已经注册(通过 {@link #register(String, PubKey)} 方法),但尚未提交(通过 {@link #commit()} + * 方法),则返回 -1;
* * @param address * @return */ public long getVersion(Bytes address) { - InnerVersioningAccount acc = latestAccountsCache.get(address); + InnerMerkleAccount acc = latestAccountsCache.get(address); if (acc != null) { // 已注册尚未提交,也返回 -1; - return acc.version == -1 ? 0 : acc.version; + return acc.getVersion(); } return merkleDataset.getVersion(address); @@ -175,12 +174,12 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ * @param version 账户版本;如果指定为 -1,则返回最新版本; * @return */ - public MerkleAccount getAccount(Bytes address, long version) { + public CompositeAccount getAccount(Bytes address, long version) { version = version < 0 ? -1 : version; - InnerVersioningAccount acc = latestAccountsCache.get(address); + InnerMerkleAccount acc = latestAccountsCache.get(address); if (acc != null && version == -1) { return acc; - } else if (acc != null && acc.version == version) { + } else if (acc != null && acc.getVersion() == version) { return acc; } @@ -194,7 +193,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ } // 如果是不存在的,或者刚刚新增未提交的账户,则前面一步查询到的 latestVersion 小于 0, 代码不会执行到此; - if (acc != null && acc.version != latestVersion) { + if (acc != null && acc.getVersion() != latestVersion) { // 当执行到此处时,并且缓冲列表中缓存了最新的版本, // 如果当前缓存的最新账户的版本和刚刚从存储中检索得到的最新版本不一致,可能存在外部的并发更新,这超出了系统设计的逻辑; @@ -205,21 +204,15 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ } // Now, be sure that "acc == null", so get account from storage; - - byte[] bytes = merkleDataset.getValue(address, version); - if (bytes == null) { - return null; - } - // Set readonly for the old version account; boolean readonly = (version > -1 && version < latestVersion) || isReadonly(); - - // String prefix = address.concat(LedgerConsts.KEY_SEPERATOR); - // ExPolicyKVStorage ss = PrefixAppender.prefix(prefix, baseExStorage); - // VersioningKVStorage vs = PrefixAppender.prefix(prefix, baseVerStorage); - // BaseAccount accDS = deserialize(bytes, cryptoSetting, ss, vs, readonly); - String prefix = keyPrefix + address; - acc = deserialize(bytes, cryptoSetting, prefix, baseExStorage, baseVerStorage, readonly, latestVersion); + + long qVersion = version == -1 ? latestVersion : version; + // load account from storage; + acc = loadAccount(address, readonly, qVersion); + if (acc == null) { + return null; + } if (!readonly) { // cache the latest version witch enable reading and writing; // readonly version of account not necessary to be cached; @@ -228,6 +221,10 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ return acc; } + public CompositeAccount register(Bytes address, PubKey pubKey) { + return register(new BlockchainIdentityData(address, pubKey)); + } + /** * 注册一个新账户;
* @@ -239,16 +236,18 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ * @param pubKey 公钥; * @return 注册成功的账户对象; */ - public MerkleAccount register(Bytes address, PubKey pubKey) { + public CompositeAccount register(BlockchainIdentity accountId) { if (isReadonly()) { throw new IllegalArgumentException("This AccountSet is readonly!"); } + Bytes address = accountId.getAddress(); + PubKey pubKey = accountId.getPubKey(); verifyAddressEncoding(address, pubKey); - InnerVersioningAccount cachedAcc = latestAccountsCache.get(address); + InnerMerkleAccount cachedAcc = latestAccountsCache.get(address); if (cachedAcc != null) { - if (cachedAcc.version < 0) { + if (cachedAcc.getVersion() < 0) { // 同一个新账户已经注册,但尚未提交,所以重复注册不会引起任何变化; return cachedAcc; } @@ -264,17 +263,8 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ throw new LedgerException("Account Registering was rejected for the access policy!"); } - // String prefix = address.concat(LedgerConsts.KEY_SEPERATOR); - // ExPolicyKVStorage accExStorage = PrefixAppender.prefix(prefix, - // baseExStorage); - // VersioningKVStorage accVerStorage = PrefixAppender.prefix(prefix, - // baseVerStorage); - // BaseAccount accDS = createInstance(address, pubKey, cryptoSetting, - // accExStorage, accVerStorage); - - String prefix = keyPrefix + address; - InnerVersioningAccount acc = createInstance(address, pubKey, cryptoSetting, prefix, baseExStorage, baseVerStorage, - -1); + Bytes prefix = keyPrefix.concat(address); + InnerMerkleAccount acc = createInstance(accountId, cryptoSetting, prefix); latestAccountsCache.put(address, acc); updated = true; @@ -288,20 +278,50 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ } } - private InnerVersioningAccount createInstance(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, - String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, long version) { - return new InnerVersioningAccount(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage, version); + private InnerMerkleAccount createInstance(BlockchainIdentity header, CryptoSetting cryptoSetting, Bytes keyPrefix) { + return new InnerMerkleAccount(header, cryptoSetting, keyPrefix, baseExStorage, baseVerStorage); + } + + /** + * 加载指定版本的账户; + * + * @param address 账户地址; + * @param readonly 是否只读; + * @param version 账户的版本;大于等于 0 ; + * @return + */ + private InnerMerkleAccount loadAccount(Bytes address, boolean readonly, long version) { + byte[] rootHashBytes = merkleDataset.getValue(address, version); + if (rootHashBytes == null) { + return null; + } + HashDigest rootHash = new HashDigest(rootHashBytes); + + return createAccount(address, rootHash, version, readonly); } - private InnerVersioningAccount deserialize(byte[] bytes, CryptoSetting cryptoSetting, String keyPrefix, - ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, long version) { - AccountHeader accInfo = BinaryProtocol.decode(bytes); - return new InnerVersioningAccount(accInfo.getAddress(), accInfo.getPubKey(), accInfo.getRootHash(), cryptoSetting, - keyPrefix, exStorage, verStorage, readonly, version); + private InnerMerkleAccount createAccount(Bytes address, HashDigest rootHash, long version, boolean readonly) { + // prefix; + Bytes prefix = keyPrefix.concat(address); + + return new InnerMerkleAccount(address, version, rootHash, cryptoSetting, prefix, baseExStorage, baseVerStorage, + readonly); } - private byte[] serialize(AccountHeader account) { - return BinaryProtocol.encode(account, AccountHeader.class); + // TODO:优化:区块链身份(地址+公钥)与其Merkle树根哈希分开独立存储; + // 不必作为一个整块,避免状态数据写入时频繁重写公钥,尤其某些算法的公钥可能很大; + + /** + * 保存账户的根哈希,返回账户的新版本; + * + * @param account + * @return + */ + private long saveAccount(InnerMerkleAccount account) { + // 提交更改,更新哈希; + account.commit(); + + return account.getVersion(); } @Override @@ -315,17 +335,10 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ return; } try { - for (InnerVersioningAccount acc : latestAccountsCache.values()) { + for (InnerMerkleAccount acc : latestAccountsCache.values()) { // updated or new created; - if (acc.isUpdated() || acc.version < 0) { - // 提交更改,更新哈希; - acc.commit(); - byte[] value = serialize(acc); - long ver = merkleDataset.setValue(acc.getAddress(), value, acc.version); - if (ver < 0) { - // Update fail; - throw new LedgerException("Account updating fail! --[Address=" + acc.getAddress() + "]"); - } + if (acc.isUpdated() || acc.getVersion() < 0) { + saveAccount(acc); } } merkleDataset.commit(); @@ -343,7 +356,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ Bytes[] addresses = new Bytes[latestAccountsCache.size()]; latestAccountsCache.keySet().toArray(addresses); for (Bytes address : addresses) { - InnerVersioningAccount acc = latestAccountsCache.remove(address); + InnerMerkleAccount acc = latestAccountsCache.remove(address); // cancel; if (acc.isUpdated()) { acc.cancel(); @@ -352,107 +365,46 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ updated = false; } - public static class AccountHeaderData implements AccountHeader { - - private Bytes address; - private PubKey pubKey; - private HashDigest rootHash; - - public AccountHeaderData(Bytes address, PubKey pubKey, HashDigest rootHash) { - this.address = address; - this.pubKey = pubKey; - this.rootHash = rootHash; - } - - @Override - public Bytes getAddress() { - return address; - } + /** + * 内部实现的账户,监听和同步账户数据的变更; + * + * @author huanghaiquan + * + */ + private class InnerMerkleAccount extends MerkleAccount { - @Override - public PubKey getPubKey() { - return pubKey; - } + private long version; - @Override - public HashDigest getRootHash() { - return rootHash; + public InnerMerkleAccount(BlockchainIdentity accountID, CryptoSetting cryptoSetting, Bytes keyPrefix, + ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) { + super(accountID, cryptoSetting, keyPrefix, exStorage, verStorage); + this.version = -1; } - } - - private class InnerVersioningAccount extends MerkleAccount { - - // private final BaseAccount account; - - private final long version; - - // public VersioningAccount(BaseAccount account, long version) { - // this.account = account; - // this.version = version; - // } - - public InnerVersioningAccount(Bytes address, PubKey pubKey, HashDigest rootHash, CryptoSetting cryptoSetting, - String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, - long version) { - super(address, pubKey, rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); + public InnerMerkleAccount(Bytes address, long version, HashDigest dataRootHash, CryptoSetting cryptoSetting, + Bytes keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) { + super(address, dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); this.version = version; } - public InnerVersioningAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix, - ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, long version) { - super(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage); - this.version = version; + @Override + protected void onUpdated(String key, TypedValue value, long expectedVersion, long newVersion) { + updated = true; } - // @Override - // public Bytes getAddress() { - // return account.getAddress(); - // } - // - // @Override - // public PubKey getPubKey() { - // return account.getPubKey(); - // } - // - // @Override - // public HashDigest getRootHash() { - // return account.getRootHash(); - // } - // - // @Override - // public MerkleProof getProof(Bytes key) { - // return account.getProof(key); - // } - // - // @Override - // public boolean isReadonly() { - // return account.isReadonly(); - // } - @Override - public long setBytes(Bytes key, BytesValue value, long version) { - long v = super.setBytes(key, value, version); - if (v > -1) { - updated = true; + protected void onCommited(HashDigest previousRootHash, HashDigest newRootHash) { + long newVersion = merkleDataset.setValue(this.getAddress(), newRootHash.toBytes(), version); + if (newVersion < 0) { + // Update fail; + throw new LedgerException("Account updating fail! --[Address=" + this.getAddress() + "]"); } - return v; + this.version = newVersion; } - // @Override - // public long getKeyVersion(Bytes key) { - // return account.getKeyVersion(key); - // } - // - // @Override - // public byte[] getBytes(Bytes key) { - // return account.getBytes(key); - // } - // - // @Override - // public byte[] getBytes(Bytes key, long version) { - // return account.getBytes(key, version); - // } + public long getVersion() { + return version; + } } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataCluster.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataCluster.java new file mode 100644 index 00000000..41339c58 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataCluster.java @@ -0,0 +1,74 @@ +package com.jd.blockchain.ledger.core; + +import java.util.Map; + +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.CryptoSetting; +import com.jd.blockchain.ledger.MerkleSnapshot; +import com.jd.blockchain.storage.service.ExPolicyKVStorage; +import com.jd.blockchain.storage.service.VersioningKVStorage; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.Transactional; + +public class MerkleDataCluster implements Transactional, MerkleSnapshot { + + private boolean readonly; + + private MerkleDataSet rootDS; + + private Map partitions; + + /** + * Create an empty readable {@link MerkleDataCluster} instance; + */ + public MerkleDataCluster(CryptoSetting setting, Bytes keyPrefix, ExPolicyKVStorage exPolicyStorage, + VersioningKVStorage versioningStorage) { + this(null, setting, keyPrefix, exPolicyStorage, versioningStorage, false); + } + + /** + * Create an {@link MerkleDataCluster} instance; + * + * @param rootHash root hash of this {@link MerkleDataCluster} instance; + * @param readonly whether read only; + */ + public MerkleDataCluster(HashDigest rootHash, CryptoSetting setting, Bytes keyPrefix, + ExPolicyKVStorage exPolicyStorage, VersioningKVStorage versioningStorage, boolean readonly) { + this.rootDS = new MerkleDataSet(rootHash, setting, keyPrefix, exPolicyStorage, versioningStorage, readonly); + } + + @Override + public HashDigest getRootHash() { + return rootDS.getRootHash(); + } + + @Override + public boolean isUpdated() { + return rootDS.isUpdated(); + } + +// public VersioningMap getPartition(Bytes name) { +// return getPartition(name, false); +// } +// +// public VersioningMap getPartition(Bytes name, boolean create) { +// +// } +// +// public VersioningMap createPartition(Bytes name) { +// +// } + + @Override + public void commit() { + // TODO Auto-generated method stub + + } + + @Override + public void cancel() { + // TODO Auto-generated method stub + + } + +} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java index 3dd99df0..15de35b5 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java @@ -1,11 +1,12 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.ledger.MerkleProof; -import com.jd.blockchain.storage.service.VersioningKVEntry; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; public interface MerkleDataEntry { - VersioningKVEntry getData(); + DataEntry getData(); MerkleProof getProof(); } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java index 16927b97..80217efe 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java @@ -7,11 +7,14 @@ import com.jd.blockchain.ledger.MerkleDataNode; import com.jd.blockchain.ledger.MerkleProof; import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; -import com.jd.blockchain.storage.service.VersioningKVEntry; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.storage.service.utils.BufferedKVStorage; import com.jd.blockchain.storage.service.utils.VersioningKVData; +import com.jd.blockchain.utils.ArrayUtils; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; +import com.jd.blockchain.utils.DataIterator; +import com.jd.blockchain.utils.Dataset; import com.jd.blockchain.utils.Transactional; import com.jd.blockchain.utils.io.BytesUtils; @@ -23,23 +26,24 @@ import com.jd.blockchain.utils.io.BytesUtils; * @author huanghaiquan * */ -public class MerkleDataSet implements Transactional, MerkleProvable { +public class MerkleDataSet implements Transactional, MerkleProvable, Dataset { /** * 4 MB MaxSize of value; */ public static final int MAX_SIZE_OF_VALUE = 4 * 1024 * 1024; - public static final String ORIG_KEY_SEPERATOR = LedgerConsts.KEY_SEPERATOR; - - public static final String SN_PREFIX = "SN" + ORIG_KEY_SEPERATOR; - public static final String DATA_PREFIX = "KV" + ORIG_KEY_SEPERATOR; - public static final String MERKLE_TREE_PREFIX = "MKL" + ORIG_KEY_SEPERATOR; + public static final Bytes SN_PREFIX = Bytes.fromString("SN" + LedgerConsts.KEY_SEPERATOR); + public static final Bytes DATA_PREFIX = Bytes.fromString("KV" + LedgerConsts.KEY_SEPERATOR); + public static final Bytes MERKLE_TREE_PREFIX = Bytes.fromString("MKL" + LedgerConsts.KEY_SEPERATOR); private final Bytes snKeyPrefix; private final Bytes dataKeyPrefix; private final Bytes merkleKeyPrefix; + @SuppressWarnings("unchecked") + private static final DataEntry[] EMPTY_ENTRIES = new DataEntry[0]; + private BufferedKVStorage bufferedStorage; private VersioningKVStorage valueStorage; @@ -71,6 +75,18 @@ public class MerkleDataSet implements Transactional, MerkleProvable { */ public MerkleDataSet(CryptoSetting setting, String keyPrefix, ExPolicyKVStorage exPolicyStorage, VersioningKVStorage versioningStorage) { + this(setting, Bytes.fromString(keyPrefix), exPolicyStorage, versioningStorage); + } + + /** + * 创建一个新的 MerkleDataSet; + * + * @param setting 密码设置; + * @param exPolicyStorage 默克尔树的存储; + * @param versioningStorage 数据的存储; + */ + public MerkleDataSet(CryptoSetting setting, Bytes keyPrefix, ExPolicyKVStorage exPolicyStorage, + VersioningKVStorage versioningStorage) { // 缓冲对KV的写入; this.bufferedStorage = new BufferedKVStorage(exPolicyStorage, versioningStorage, false); @@ -79,15 +95,15 @@ public class MerkleDataSet implements Transactional, MerkleProvable { // bufferedStorage); // this.snStorage = PrefixAppender.prefix(SN_PREFIX, (ExPolicyKVStorage) // bufferedStorage); - snKeyPrefix = Bytes.fromString(keyPrefix + SN_PREFIX); - dataKeyPrefix = Bytes.fromString(keyPrefix + DATA_PREFIX); + snKeyPrefix = keyPrefix.concat(SN_PREFIX); + dataKeyPrefix = keyPrefix.concat(DATA_PREFIX); this.valueStorage = bufferedStorage; this.snStorage = bufferedStorage; // MerkleTree 本身是可缓冲的; // ExPolicyKVStorage merkleTreeStorage = // PrefixAppender.prefix(MERKLE_TREE_PREFIX, exPolicyStorage); - merkleKeyPrefix = Bytes.fromString(keyPrefix + MERKLE_TREE_PREFIX); + merkleKeyPrefix = keyPrefix.concat(MERKLE_TREE_PREFIX); ExPolicyKVStorage merkleTreeStorage = exPolicyStorage; this.merkleTree = new MerkleTree(setting, merkleKeyPrefix, merkleTreeStorage); this.snGenerator = new MerkleSequenceSNGenerator(merkleTree); @@ -104,17 +120,33 @@ public class MerkleDataSet implements Transactional, MerkleProvable { */ public MerkleDataSet(HashDigest merkleRootHash, CryptoSetting setting, String keyPrefix, ExPolicyKVStorage exPolicyStorage, VersioningKVStorage versioningStorage, boolean readonly) { + this(merkleRootHash, setting, Bytes.fromString(keyPrefix), exPolicyStorage, versioningStorage, readonly); + } + + /** + * 从指定的 Merkle 根构建的 MerkleDataSet; + * + * @param dataStorage + * @param defaultMerkleHashAlgorithm + * @param verifyMerkleHashOnLoad + * @param merkleTreeStorage + * @param snGenerator + */ + public MerkleDataSet(HashDigest merkleRootHash, CryptoSetting setting, Bytes keyPrefix, + ExPolicyKVStorage exPolicyStorage, VersioningKVStorage versioningStorage, boolean readonly) { // 缓冲对KV的写入; this.bufferedStorage = new BufferedKVStorage(exPolicyStorage, versioningStorage, false); // 把存储数据值、SN、Merkle节点的 key 分别加入独立的前缀,避免针对 key 的注入攻击; - snKeyPrefix = Bytes.fromString(keyPrefix + SN_PREFIX); - dataKeyPrefix = Bytes.fromString(keyPrefix + DATA_PREFIX); +// snKeyPrefix = Bytes.fromString(keyPrefix + SN_PREFIX); +// dataKeyPrefix = Bytes.fromString(keyPrefix + DATA_PREFIX); + snKeyPrefix = keyPrefix.concat(SN_PREFIX); + dataKeyPrefix = keyPrefix.concat(DATA_PREFIX); this.valueStorage = bufferedStorage; this.snStorage = bufferedStorage; // MerkleTree 本身是可缓冲的; - merkleKeyPrefix = Bytes.fromString(keyPrefix + MERKLE_TREE_PREFIX); + merkleKeyPrefix = keyPrefix.concat(MERKLE_TREE_PREFIX); ExPolicyKVStorage merkleTreeStorage = exPolicyStorage; this.merkleTree = new MerkleTree(merkleRootHash, setting, merkleKeyPrefix, merkleTreeStorage, readonly); @@ -130,15 +162,21 @@ public class MerkleDataSet implements Transactional, MerkleProvable { this.readonly = true; } + @Override public long getDataCount() { return merkleTree.getDataCount(); } + /** + * 返回理论上允许的最大数据索引; + * + * @return + */ public long getMaxIndex() { return merkleTree.getMaxSn(); } - public byte[][] getLatestValues(int fromIndex, int count) { + public byte[][] getLatestValues(long fromIndex, int count) { if (count > LedgerConsts.MAX_LIST_COUNT) { throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); } @@ -154,24 +192,41 @@ public class MerkleDataSet implements Transactional, MerkleProvable { return values; } - public VersioningKVEntry[] getLatestDataEntries(int fromIndex, int count) { + public DataEntry[] getLatestDataEntries(long fromIndex, int count) { if (count > LedgerConsts.MAX_LIST_COUNT) { throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); } if (fromIndex < 0 || (fromIndex + count) > merkleTree.getDataCount()) { throw new IllegalArgumentException("Index out of bound!"); } - VersioningKVEntry[] values = new VersioningKVEntry[count]; + if (count == 0) { + return EMPTY_ENTRIES; + } + @SuppressWarnings("unchecked") + DataEntry[] values = new DataEntry[count]; byte[] bytesValue; for (int i = 0; i < count; i++) { MerkleDataNode dataNode = merkleTree.getData(fromIndex + i); Bytes dataKey = encodeDataKey(dataNode.getKey()); bytesValue = valueStorage.get(dataKey, dataNode.getVersion()); - values[i] = new VersioningKVData(dataNode.getKey(), dataNode.getVersion(), bytesValue); + values[i] = new VersioningKVData(dataNode.getKey(), dataNode.getVersion(), bytesValue); } return values; } + public DataEntry getLatestDataEntry(long index) { + if (index < 0 || index + 1 > merkleTree.getDataCount()) { + throw new IllegalArgumentException("Index out of bound!"); + } + byte[] bytesValue; + MerkleDataNode dataNode = merkleTree.getData(index); + Bytes dataKey = encodeDataKey(dataNode.getKey()); + bytesValue = valueStorage.get(dataKey, dataNode.getVersion()); + DataEntry entry = new VersioningKVData(dataNode.getKey(), dataNode.getVersion(), + bytesValue); + return entry; + } + /** * get the data at the specific index; * @@ -192,32 +247,34 @@ public class MerkleDataSet implements Transactional, MerkleProvable { */ public String getKeyAtIndex(int fromIndex) { MerkleDataNode dataNode = merkleTree.getData(fromIndex); - return dataNode.getKey().toUTF8String(); - } - - /** - * Create or update the value associated the specified key if the version - * checking is passed.
- * - * The value of the key will be updated only if it's latest version equals the - * specified version argument.
- * If the key doesn't exist, it will be created when the version arg was -1. - *

- * If updating is performed, the version of the key increase by 1.
- * If creating is performed, the version of the key initialize by 0.
- * - * @param key The key of data; - * @param value The value of data; - * @param version The expected latest version of the key. - * @return The new version of the key.
- * If the key is new created success, then return 0;
- * If the key is updated success, then return the new version;
- * If this operation fail by version checking or other reason, then - * return -1; - */ - public long setValue(String key, byte[] value, long version) { - return setValue(Bytes.fromString(key), value, version); - } + // TODO: 未去掉前缀; + return dataNode.getKey().toUTF8String(); + } + +// /** +// * Create or update the value associated the specified key if the version +// * checking is passed.
+// * +// * The value of the key will be updated only if it's latest version equals the +// * specified version argument.
+// * If the key doesn't exist, it will be created when the version arg was -1. +// *

+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// * +// * @param key The key of data; +// * @param value The value of data; +// * @param version The expected latest version of the key. +// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then +// * return -1; +// */ +// @Override +// public long setValue(String key, byte[] value, long version) { +// return setValue(Bytes.fromString(key), value, version); +// } /** * Create or update the value associated the specified key if the version @@ -239,6 +296,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable { * If this operation fail by version checking or other reason, then * return -1; */ + @Override public long setValue(Bytes key, byte[] value, long version) { if (readonly) { throw new IllegalArgumentException("This merkle dataset is readonly!"); @@ -336,18 +394,19 @@ public class MerkleDataSet implements Transactional, MerkleProvable { return mdn.getVersion(); } - /** - * Return the specified version's value;
- * - * If the key with the specified version doesn't exist, then return null;
- * If the version is specified to -1, then return the latest version's value; - * - * @param key - * @param version - */ - public byte[] getValue(String key, long version) { - return getValue(Bytes.fromString(key), version); - } +// /** +// * Return the specified version's value;
+// * +// * If the key with the specified version doesn't exist, then return null;
+// * If the version is specified to -1, then return the latest version's value; +// * +// * @param key +// * @param version +// */ +// @Override +// public byte[] getValue(String key, long version) { +// return getValue(Bytes.fromString(key), version); +// } /** * Return the specified version's value;
@@ -358,6 +417,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable { * @param key * @param version */ + @Override public byte[] getValue(Bytes key, long version) { long latestVersion = getMerkleVersion(key); if (latestVersion < 0 || version > latestVersion) { @@ -370,15 +430,16 @@ public class MerkleDataSet implements Transactional, MerkleProvable { return valueStorage.get(dataKey, version); } - /** - * Return the latest version's value; - * - * @param key - * @return return null if not exist; - */ - public byte[] getValue(String key) { - return getValue(Bytes.fromString(key)); - } +// /** +// * Return the latest version's value; +// * +// * @param key +// * @return return null if not exist; +// */ +// @Override +// public byte[] getValue(String key) { +// return getValue(Bytes.fromString(key)); +// } /** * Return the latest version's value; @@ -386,6 +447,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable { * @param key * @return return null if not exist; */ + @Override public byte[] getValue(Bytes key) { long latestVersion = getMerkleVersion(key); if (latestVersion < 0) { @@ -395,16 +457,17 @@ public class MerkleDataSet implements Transactional, MerkleProvable { return valueStorage.get(dataKey, latestVersion); } - /** - * Return the latest version entry associated the specified key; If the key - * doesn't exist, then return -1; - * - * @param key - * @return - */ - public long getVersion(String key) { - return getMerkleVersion(Bytes.fromString(key)); - } +// /** +// * Return the latest version entry associated the specified key; If the key +// * doesn't exist, then return -1; +// * +// * @param key +// * @return +// */ +// @Override +// public long getVersion(String key) { +// return getMerkleVersion(Bytes.fromString(key)); +// } /** * Return the latest version entry associated the specified key; If the key @@ -413,33 +476,46 @@ public class MerkleDataSet implements Transactional, MerkleProvable { * @param key * @return */ + @Override public long getVersion(Bytes key) { return getMerkleVersion(key); } - public VersioningKVEntry getDataEntry(String key) { - return getDataEntry(Bytes.fromString(key)); - } +// @Override +// public VersioningKVEntry getDataEntry(String key) { +// return getDataEntry(key, -1); +// } /** * * @param key * @return Null if the key doesn't exist! */ - public VersioningKVEntry getDataEntry(Bytes key) { - long latestVersion = getMerkleVersion(key); - if (latestVersion < 0) { - return null; - } - Bytes dataKey = encodeDataKey(key); - byte[] value = valueStorage.get(dataKey, latestVersion); - if (value == null) { - return null; - } - return new VersioningKVData(key, latestVersion, value); - } + @Override + public DataEntry getDataEntry(Bytes key) { + return getDataEntry(key, -1); + } + +// @Override +// public VersioningKVEntry getDataEntry(String key, long version) { +// Bytes keyBytes = Bytes.fromString(key); +// long latestVersion = getMerkleVersion(keyBytes); +// if (latestVersion < 0 || version > latestVersion) { +// // key not exist, or the specified version is out of the latest version indexed +// // by the current merkletree; +// return null; +// } +// version = version < 0 ? latestVersion : version; +// Bytes dataKey = encodeDataKey(keyBytes); +// byte[] value = valueStorage.get(dataKey, version); +// if (value == null) { +// return null; +// } +// return new VersioningKVData(key, version, value); +// } - public VersioningKVEntry getDataEntry(Bytes key, long version) { + @Override + public DataEntry getDataEntry(Bytes key, long version) { long latestVersion = getMerkleVersion(key); if (latestVersion < 0 || version > latestVersion) { // key not exist, or the specified version is out of the latest version indexed @@ -452,11 +528,21 @@ public class MerkleDataSet implements Transactional, MerkleProvable { if (value == null) { return null; } - return new VersioningKVData(key, version, value); + return new VersioningKVData(key, version, value); + } + + @Override + public DataIterator iterator() { + return new AscDataInterator(getDataCount()); + } + + @Override + public DataIterator iteratorDesc() { + return new DescDataInterator(getDataCount()); } public MerkleDataEntry getMerkleEntry(Bytes key, long version) { - VersioningKVEntry dataEntry = getDataEntry(key, version); + DataEntry dataEntry = getDataEntry(key, version); if (dataEntry == null) { return null; } @@ -465,7 +551,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable { } public MerkleDataEntry getMerkleEntry(Bytes key) { - VersioningKVEntry dataEntry = getDataEntry(key); + DataEntry dataEntry = getDataEntry(key); if (dataEntry == null) { return null; } @@ -492,23 +578,23 @@ public class MerkleDataSet implements Transactional, MerkleProvable { } /** - * A wrapper for {@link VersioningKVEntry} and {@link MerkleProof}; + * A wrapper for {@link DataEntry} and {@link MerkleProof}; * * @author huanghaiquan * */ private static class MerkleDataEntryWrapper implements MerkleDataEntry { - private VersioningKVEntry data; + private DataEntry data; private MerkleProof proof; - public MerkleDataEntryWrapper(VersioningKVEntry data, MerkleProof proof) { + public MerkleDataEntryWrapper(DataEntry data, MerkleProof proof) { this.data = data; this.proof = proof; } @Override - public VersioningKVEntry getData() { + public DataEntry getData() { return data; } @@ -536,4 +622,119 @@ public class MerkleDataSet implements Transactional, MerkleProvable { merkleTree.cancel(); snGenerator = new MerkleSequenceSNGenerator(merkleTree); } + + // ---------------------------------------------------------- + + private class AscDataInterator implements DataIterator { + + private final long total; + + private long cursor = 0; + + public AscDataInterator(long total) { + this.total = total; + } + + @Override + public void skip(long count) { + cursor = nextCursor(count); + } + + private long nextCursor(long skippingCount) { + long c = cursor + skippingCount; + return c > total ? total : c; + } + + @Override + public DataEntry next() { + if (hasNext()) { + DataEntry entry = getLatestDataEntry(cursor); + cursor = nextCursor(1); + return entry; + } + return null; + } + + @Override + public DataEntry[] next(int count) { + if (hasNext()) { + long from = cursor; + long nextCursor = nextCursor(count); + long c = nextCursor - cursor; + if (c > LedgerConsts.MAX_LIST_COUNT) { + throw new IllegalArgumentException( + "Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); + } + DataEntry[] entries = getLatestDataEntries(from, (int) c); + cursor = nextCursor; + return entries; + } + return EMPTY_ENTRIES; + } + + @Override + public boolean hasNext() { + return cursor < total; + } + + } + + private class DescDataInterator implements DataIterator { + + private final long total; + + private long cursor; + + public DescDataInterator(long total) { + this.total = total; + this.cursor = total - 1; + } + + @Override + public void skip(long count) { + cursor = nextCursor(count); + } + + private long nextCursor(long skippingCount) { + long c = cursor - skippingCount; + return c < 0 ? -1 : c; + } + + @Override + public DataEntry next() { + if (hasNext()) { + DataEntry entry = getLatestDataEntry(cursor); + cursor = nextCursor(1); + return entry; + } + return null; + } + + @Override + public DataEntry[] next(int count) { + if (hasNext()) { + long nextCursor = nextCursor(count); + long from = nextCursor + 1; + long c = cursor - nextCursor; + if (c > LedgerConsts.MAX_LIST_COUNT) { + throw new IllegalArgumentException( + "Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); + } + DataEntry[] entries = getLatestDataEntries(from, (int) c); + // reverse; + ArrayUtils.reverse(entries); + + cursor = nextCursor; + return entries; + } + return EMPTY_ENTRIES; + } + + @Override + public boolean hasNext() { + return cursor < total; + } + + } + } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java index 6628aad3..8efd1d10 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java @@ -1,7 +1,7 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.AccountHeader; +import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.utils.Bytes; /** @@ -15,7 +15,7 @@ import com.jd.blockchain.utils.Bytes; public class OpeningAccessPolicy implements AccountAccessPolicy { @Override - public boolean checkDataWriting(AccountHeader account) { + public boolean checkDataWriting(BlockchainIdentity account) { return true; } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java index dbc077a8..bd629b8a 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java @@ -28,7 +28,7 @@ public class ParticipantDataset implements Transactional, MerkleProvable, Partic public ParticipantDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) { - dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly); + dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, Bytes.fromString(prefix), exPolicyStorage, verStorage, readonly); } @Override diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java index 14673435..220b519c 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java @@ -14,10 +14,10 @@ import com.jd.blockchain.ledger.RolePrivileges; import com.jd.blockchain.ledger.TransactionPermission; import com.jd.blockchain.ledger.TransactionPrivilege; import com.jd.blockchain.storage.service.ExPolicyKVStorage; -import com.jd.blockchain.storage.service.VersioningKVEntry; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Transactional; +import com.jd.blockchain.utils.DataEntry; public class RolePrivilegeDataset implements Transactional, MerkleProvable, RolePrivilegeSettings { @@ -30,7 +30,8 @@ public class RolePrivilegeDataset implements Transactional, MerkleProvable, Role public RolePrivilegeDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) { - dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly); + dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, Bytes.fromString(prefix), exPolicyStorage, + verStorage, readonly); } @Override @@ -255,7 +256,7 @@ public class RolePrivilegeDataset implements Transactional, MerkleProvable, Role public RolePrivileges getRolePrivilege(String roleName) { // 只返回最新版本; Bytes key = encodeKey(roleName); - VersioningKVEntry kv = dataset.getDataEntry(key); + DataEntry kv = dataset.getDataEntry(key); if (kv == null) { return null; } @@ -265,7 +266,7 @@ public class RolePrivilegeDataset implements Transactional, MerkleProvable, Role @Override public RolePrivileges[] getRolePrivileges(int index, int count) { - VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(index, count); + DataEntry[] kvEntries = dataset.getLatestDataEntries(index, count); RolePrivileges[] pns = new RolePrivileges[kvEntries.length]; PrivilegeSet privilege; for (int i = 0; i < pns.length; i++) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java index d3ad83ba..2fde0054 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java @@ -1,12 +1,5 @@ package com.jd.blockchain.ledger.core; -import java.util.Set; - -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.LedgerPermission; -import com.jd.blockchain.ledger.LedgerSecurityException; -import com.jd.blockchain.ledger.TransactionPermission; - public class SecurityContext { private static ThreadLocal policyHolder = new ThreadLocal(); diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java index 28c6bff4..fe336005 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java @@ -88,7 +88,8 @@ public class TransactionSet implements Transactional, TransactionQuery { public TransactionSet(HashDigest txRootHash, CryptoSetting setting, String keyPrefix, ExPolicyKVStorage merkleTreeStorage, VersioningKVStorage dataStorage, boolean readonly) { this.txStatePrefix = Bytes.fromString(keyPrefix + TX_STATE_PREFIX); - this.txSet = new MerkleDataSet(txRootHash, setting, keyPrefix, merkleTreeStorage, dataStorage, readonly); + this.txSet = new MerkleDataSet(txRootHash, setting, Bytes.fromString(keyPrefix), merkleTreeStorage, dataStorage, + readonly); } /** diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java index 49743f90..87696e86 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java @@ -1,9 +1,9 @@ package com.jd.blockchain.ledger.core; -import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.LedgerException; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.UserInfo; import com.jd.blockchain.utils.Bytes; @@ -13,72 +13,73 @@ import com.jd.blockchain.utils.Bytes; * @author huanghaiquan * */ -public class UserAccount implements UserInfo { +public class UserAccount extends AccountDecorator implements UserInfo { // implements UserInfo { - private static final Bytes USER_INFO_PREFIX = Bytes.fromString("PROP" + LedgerConsts.KEY_SEPERATOR); + private static final String USER_INFO_PREFIX = "PROP" + LedgerConsts.KEY_SEPERATOR; - private static final Bytes DATA_PUB_KEY = Bytes.fromString("DATA-PUBKEY"); + private static final String DATA_PUB_KEY = "DATA-PUBKEY"; - private MerkleAccount baseAccount; + public UserAccount(CompositeAccount baseAccount) { + super(baseAccount); + } + + private PubKey dataPubKey; + @Override public Bytes getAddress() { - return baseAccount.getAddress(); + return getID().getAddress(); } @Override public PubKey getPubKey() { - return baseAccount.getPubKey(); + return getID().getPubKey(); } - + @Override - public HashDigest getRootHash() { - return baseAccount.getRootHash(); - } - - public UserAccount(MerkleAccount baseAccount) { - this.baseAccount = baseAccount; - } - public PubKey getDataPubKey() { - BytesValue pkBytes = baseAccount.getBytes(DATA_PUB_KEY); - if (pkBytes == null) { - return null; + if (dataPubKey == null) { + BytesValue pkBytes = getHeaders().getValue(DATA_PUB_KEY); + if (pkBytes == null) { + return null; + } + dataPubKey = new PubKey(pkBytes.getBytes().toBytes()); } - return new PubKey(pkBytes.getValue().toBytes()); + return dataPubKey; } - public long setDataPubKey(PubKey pubKey) { - byte[] pkBytes = pubKey.toBytes(); - return baseAccount.setBytes(DATA_PUB_KEY, BytesData.fromBytes(pkBytes), -1); + public void setDataPubKey(PubKey pubKey) { + long version = getHeaders().getVersion(DATA_PUB_KEY); + setDataPubKey(pubKey, version); } - public long setDataPubKey(PubKey pubKey, long version) { - byte[] pkBytes = pubKey.toBytes(); - return baseAccount.setBytes(DATA_PUB_KEY, BytesData.fromBytes(pkBytes), version); + public void setDataPubKey(PubKey pubKey, long version) { + TypedValue value = TypedValue.fromPubKey(dataPubKey); + long newVersion = getHeaders().setValue(DATA_PUB_KEY, value, version); + if (newVersion > -1) { + dataPubKey = pubKey; + } else { + throw new LedgerException("Data public key was updated failed!"); + } } public long setProperty(String key, String value, long version) { - return setProperty(Bytes.fromString(key), value, version); + return getHeaders().setValue(encodePropertyKey(key), TypedValue.fromText(value), version); } - public long setProperty(Bytes key, String value, long version) { - return baseAccount.setBytes(encodePropertyKey(key), BytesData.fromText(value), version); + public String getProperty(String key) { + BytesValue value = getHeaders().getValue(encodePropertyKey(key)); + return value == null ? null : value.getBytes().toUTF8String(); } - public String getProperty(Bytes key) { - BytesValue value = baseAccount.getBytes(encodePropertyKey(key)); - return value == null ? null : value.getValue().toUTF8String(); + public String getProperty(String key, long version) { + BytesValue value = getHeaders().getValue(encodePropertyKey(key), version); + return value == null ? null : value.getBytes().toUTF8String(); } - public String getProperty(Bytes key, long version) { - BytesValue value = baseAccount.getBytes(encodePropertyKey(key), version); - return value == null ? null : value.getValue().toUTF8String(); + private String encodePropertyKey(String key) { + return USER_INFO_PREFIX+key; } - private Bytes encodePropertyKey(Bytes key) { - // return key.concatTo(USER_INFO_PREFIX); - return USER_INFO_PREFIX.concat(key); - } } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java index a2e25356..bc71711d 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java @@ -2,7 +2,7 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.AccountHeader; +import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.LedgerException; import com.jd.blockchain.ledger.MerkleProof; @@ -21,19 +21,20 @@ public class UserAccountSet implements Transactional, UserAccountQuery { public UserAccountSet(CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage simpleStorage, VersioningKVStorage versioningStorage, AccountAccessPolicy accessPolicy) { - accountSet = new MerkleAccountSet(cryptoSetting, keyPrefix, simpleStorage, versioningStorage, accessPolicy); + accountSet = new MerkleAccountSet(cryptoSetting, Bytes.fromString(keyPrefix), simpleStorage, versioningStorage, + accessPolicy); } public UserAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, AccountAccessPolicy accessPolicy) { - accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly, - accessPolicy); + accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, Bytes.fromString(keyPrefix), exStorage, + verStorage, readonly, accessPolicy); } @Override - public AccountHeader[] getHeaders(int fromIndex, int count) { - return accountSet.getHeaders(fromIndex,count); + public BlockchainIdentity[] getHeaders(int fromIndex, int count) { + return accountSet.getHeaders(fromIndex, count); } /** @@ -49,7 +50,7 @@ public class UserAccountSet implements Transactional, UserAccountQuery { public boolean isReadonly() { return accountSet.isReadonly(); } - + void setReadonly() { accountSet.setReadonly(); } @@ -63,7 +64,7 @@ public class UserAccountSet implements Transactional, UserAccountQuery { public MerkleProof getProof(Bytes key) { return accountSet.getProof(key); } - + @Override public UserAccount getAccount(String address) { return getAccount(Bytes.fromBase58(address)); @@ -71,7 +72,7 @@ public class UserAccountSet implements Transactional, UserAccountQuery { @Override public UserAccount getAccount(Bytes address) { - MerkleAccount baseAccount = accountSet.getAccount(address); + CompositeAccount baseAccount = accountSet.getAccount(address); return new UserAccount(baseAccount); } @@ -82,7 +83,7 @@ public class UserAccountSet implements Transactional, UserAccountQuery { @Override public UserAccount getAccount(Bytes address, long version) { - MerkleAccount baseAccount = accountSet.getAccount(address, version); + CompositeAccount baseAccount = accountSet.getAccount(address, version); return new UserAccount(baseAccount); } @@ -93,14 +94,12 @@ public class UserAccountSet implements Transactional, UserAccountQuery { * * 如果指定的地址和公钥不匹配,则会引发 {@link LedgerException} 异常; * - * @param address - * 区块链地址; - * @param pubKey - * 公钥; + * @param address 区块链地址; + * @param pubKey 公钥; * @return 注册成功的用户对象; */ public UserAccount register(Bytes address, PubKey pubKey) { - MerkleAccount baseAccount = accountSet.register(address, pubKey); + CompositeAccount baseAccount = accountSet.register(address, pubKey); return new UserAccount(baseAccount); } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataset.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataset.java index 25ecd85a..8aa45ebc 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataset.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataset.java @@ -13,10 +13,10 @@ import com.jd.blockchain.ledger.RolesPolicy; import com.jd.blockchain.ledger.UserRoles; import com.jd.blockchain.ledger.UserAuthorizationSettings; import com.jd.blockchain.storage.service.ExPolicyKVStorage; -import com.jd.blockchain.storage.service.VersioningKVEntry; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Transactional; +import com.jd.blockchain.utils.DataEntry; /** * User-Role authorization data set; @@ -35,7 +35,7 @@ public class UserRoleDataset implements Transactional, MerkleProvable, UserAutho public UserRoleDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) { - dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly); + dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, Bytes.fromString(prefix), exPolicyStorage, verStorage, readonly); } @Override @@ -168,7 +168,7 @@ public class UserRoleDataset implements Transactional, MerkleProvable, UserAutho @Override public UserRoles getUserRoles(Bytes userAddress) { // 只返回最新版本; - VersioningKVEntry kv = dataset.getDataEntry(userAddress); + DataEntry kv = dataset.getDataEntry(userAddress); if (kv == null) { return null; } @@ -178,7 +178,7 @@ public class UserRoleDataset implements Transactional, MerkleProvable, UserAutho @Override public UserRoles[] getUserRoles() { - VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(0, (int) dataset.getDataCount()); + DataEntry[] kvEntries = dataset.getLatestDataEntries(0, (int) dataset.getDataCount()); UserRoles[] pns = new UserRoles[kvEntries.length]; RoleSet roleset; for (int i = 0; i < pns.length; i++) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractLedgerContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractLedgerContext.java index 0d0d3c3d..fe3f9826 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractLedgerContext.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractLedgerContext.java @@ -5,7 +5,24 @@ import java.util.List; import com.jd.blockchain.contract.LedgerContext; import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.*; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.ContractInfo; +import com.jd.blockchain.ledger.DataAccountKVSetOperation; +import com.jd.blockchain.ledger.DataAccountRegisterOperation; +import com.jd.blockchain.ledger.TypedKVEntry; +import com.jd.blockchain.ledger.KVInfoVO; +import com.jd.blockchain.ledger.LedgerAdminInfo; +import com.jd.blockchain.ledger.LedgerBlock; +import com.jd.blockchain.ledger.LedgerInfo; +import com.jd.blockchain.ledger.LedgerMetadata; +import com.jd.blockchain.ledger.LedgerTransaction; +import com.jd.blockchain.ledger.Operation; +import com.jd.blockchain.ledger.ParticipantNode; +import com.jd.blockchain.ledger.TransactionState; +import com.jd.blockchain.ledger.TypedValue; +import com.jd.blockchain.ledger.UserInfo; +import com.jd.blockchain.ledger.UserRegisterOperation; import com.jd.blockchain.ledger.core.OperationHandleContext; import com.jd.blockchain.transaction.BlockchainQueryService; import com.jd.blockchain.transaction.DataAccountKVSetOperationBuilder; @@ -150,22 +167,22 @@ public class ContractLedgerContext implements LedgerContext { } @Override - public AccountHeader getDataAccount(HashDigest ledgerHash, String address) { + public BlockchainIdentity getDataAccount(HashDigest ledgerHash, String address) { return innerQueryService.getDataAccount(ledgerHash, address); } @Override - public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) { + public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) { return innerQueryService.getDataEntries(ledgerHash, address, keys); } @Override - public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) { + public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) { return innerQueryService.getDataEntries(ledgerHash, address, kvInfoVO); } @Override - public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) { + public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) { return innerQueryService.getDataEntries(ledgerHash, address, fromIndex, count); } @@ -182,17 +199,17 @@ public class ContractLedgerContext implements LedgerContext { // ---------------------------user()---------------------------- @Override - public AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count) { + public BlockchainIdentity[] getUsers(HashDigest ledgerHash, int fromIndex, int count) { return innerQueryService.getUsers(ledgerHash, fromIndex, count); } @Override - public AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) { + public BlockchainIdentity[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) { return innerQueryService.getDataAccounts(ledgerHash, fromIndex, count); } @Override - public AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) { + public BlockchainIdentity[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) { return innerQueryService.getContractAccounts(ledgerHash, fromIndex, count); } @@ -268,7 +285,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { - BytesValue bytesValue = BytesData.fromText(value); + BytesValue bytesValue = TypedValue.fromText(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; @@ -276,7 +293,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { - BytesValue bytesValue = BytesData.fromBytes(value); + BytesValue bytesValue = TypedValue.fromBytes(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; @@ -284,7 +301,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { - BytesValue bytesValue = BytesData.fromInt64(value); + BytesValue bytesValue = TypedValue.fromInt64(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; @@ -301,7 +318,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { - BytesValue bytesValue = BytesData.fromJSON(value); + BytesValue bytesValue = TypedValue.fromJSON(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; @@ -309,7 +326,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { - BytesValue bytesValue = BytesData.fromXML(value); + BytesValue bytesValue = TypedValue.fromXML(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; @@ -317,7 +334,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { - BytesValue bytesValue = BytesData.fromBytes(value); + BytesValue bytesValue = TypedValue.fromBytes(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; @@ -325,7 +342,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { - BytesValue bytesValue = BytesData.fromImage(value); + BytesValue bytesValue = TypedValue.fromImage(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; @@ -333,7 +350,7 @@ public class ContractLedgerContext implements LedgerContext { @Override public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { - BytesValue bytesValue = BytesData.fromTimestamp(value); + BytesValue bytesValue = TypedValue.fromTimestamp(value); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); handle(op); return this; diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java index 0f9fdb2b..dfab3f1c 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java @@ -5,6 +5,7 @@ import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.DataAccountKVSetOperation.KVWriteEntry; import com.jd.blockchain.ledger.DataVersionConflictException; import com.jd.blockchain.ledger.LedgerPermission; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.core.DataAccount; import com.jd.blockchain.ledger.core.LedgerDataset; import com.jd.blockchain.ledger.core.LedgerQuery; @@ -37,7 +38,7 @@ public class DataAccountKVSetOperationHandle extends AbstractLedgerOperationHand KVWriteEntry[] writeSet = kvWriteOp.getWriteSet(); long v = -1L; for (KVWriteEntry kvw : writeSet) { - v = account.setBytes(Bytes.fromString(kvw.getKey()), kvw.getValue(), kvw.getExpectedVersion()); + v = account.getDataset().setValue(kvw.getKey(), TypedValue.wrap(kvw.getValue()), kvw.getExpectedVersion()); if (v < 0) { throw new DataVersionConflictException(); } diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContractImpl.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContractImpl.java index 60ee6864..a0bf65be 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContractImpl.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContractImpl.java @@ -3,7 +3,7 @@ package test.com.jd.blockchain.ledger; import com.jd.blockchain.contract.ContractEventContext; import com.jd.blockchain.contract.ContractLifecycleAware; import com.jd.blockchain.contract.EventProcessingAware; -import com.jd.blockchain.ledger.KVDataEntry; +import com.jd.blockchain.ledger.TypedKVEntry; import com.jd.blockchain.utils.Bytes; public class TxTestContractImpl implements TxTestContract, ContractLifecycleAware, EventProcessingAware { @@ -16,7 +16,7 @@ public class TxTestContractImpl implements TxTestContract, ContractLifecycleAwar @Override public boolean testReadable() { - KVDataEntry v1 = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(), + TypedKVEntry v1 = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(), dataAddress.toBase58(), KEY)[0]; String text1 = (String) v1.getValue(); System.out.printf("k1=%s, version=%s \r\n", text1, v1.getVersion()); @@ -26,7 +26,7 @@ public class TxTestContractImpl implements TxTestContract, ContractLifecycleAwar System.out.printf("new value = %s\r\n", newValue); eventContext.getLedger().dataAccount(dataAddress).setText(KEY, newValue, v1.getVersion()); - KVDataEntry v2 = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(), + TypedKVEntry v2 = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(), dataAddress.toBase58(), KEY)[0]; System.out.printf("---- read new value ----\r\nk1=%s, version=%s \r\n", v2.getValue(), v2.getVersion()); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java index 812a8758..99bd2076 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java @@ -14,11 +14,12 @@ import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.core.MerkleAccountSet; -import com.jd.blockchain.ledger.core.MerkleAccount; +import com.jd.blockchain.ledger.core.CompositeAccount; import com.jd.blockchain.ledger.core.CryptoConfig; +import com.jd.blockchain.ledger.core.MerkleAccountSet; import com.jd.blockchain.ledger.core.OpeningAccessPolicy; import com.jd.blockchain.storage.service.utils.MemoryKVStorage; +import com.jd.blockchain.utils.Bytes; public class AccountSetTest { @@ -43,12 +44,13 @@ public class AccountSetTest { cryptoConf.setHashAlgorithm(ClassicAlgorithm.SHA256); String keyPrefix = ""; - MerkleAccountSet accset = new MerkleAccountSet(cryptoConf, keyPrefix, storage, storage, accessPolicy); + MerkleAccountSet accset = new MerkleAccountSet(cryptoConf, Bytes.fromString(keyPrefix), storage, storage, accessPolicy); BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate(); accset.register(userKey.getAddress(), userKey.getPubKey()); - - MerkleAccount userAcc = accset.getAccount(userKey.getAddress()); + + //尚未提交之前,可以检索到账户的存在,但版本仍然标记为 -1; + CompositeAccount userAcc = accset.getAccount(userKey.getAddress()); assertNotNull(userAcc); assertTrue(accset.contains(userKey.getAddress())); @@ -56,13 +58,13 @@ public class AccountSetTest { HashDigest rootHash = accset.getRootHash(); assertNotNull(rootHash); - MerkleAccountSet reloadAccSet = new MerkleAccountSet(rootHash, cryptoConf, keyPrefix, storage, storage, true, accessPolicy); - MerkleAccount reloadUserAcc = reloadAccSet.getAccount(userKey.getAddress()); + MerkleAccountSet reloadAccSet = new MerkleAccountSet(rootHash, cryptoConf, Bytes.fromString(keyPrefix), storage, storage, true, accessPolicy); + CompositeAccount reloadUserAcc = reloadAccSet.getAccount(userKey.getAddress()); assertNotNull(reloadUserAcc); assertTrue(reloadAccSet.contains(userKey.getAddress())); - assertEquals(userAcc.getAddress(), reloadUserAcc.getAddress()); - assertEquals(userAcc.getPubKey(), reloadUserAcc.getPubKey()); + assertEquals(userAcc.getID().getAddress(), reloadUserAcc.getID().getAddress()); + assertEquals(userAcc.getID().getPubKey(), reloadUserAcc.getID().getPubKey()); } } diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BaseAccountTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BaseAccountTest.java index 51c8232b..9d55b19e 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BaseAccountTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BaseAccountTest.java @@ -2,6 +2,7 @@ package test.com.jd.blockchain.ledger.core; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import org.junit.Test; @@ -12,9 +13,9 @@ import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.BytesData; -import com.jd.blockchain.ledger.core.MerkleAccount; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.core.CryptoConfig; +import com.jd.blockchain.ledger.core.MerkleAccount; import com.jd.blockchain.storage.service.utils.MemoryKVStorage; import com.jd.blockchain.utils.Bytes; @@ -48,38 +49,39 @@ public class BaseAccountTest { BlockchainKeypair bck = BlockchainKeyGenerator.getInstance().generate(); // 新建账户; - MerkleAccount baseAccount = new MerkleAccount(bck.getIdentity(), cryptoConf, keyPrefix, testStorage, testStorage); - assertFalse(baseAccount.isUpdated());// 空的账户; + MerkleAccount baseAccount = new MerkleAccount(bck.getIdentity(), cryptoConf, Bytes.fromString(keyPrefix), + testStorage, testStorage); + assertTrue(baseAccount.isUpdated());//初始化新账户时,先写入PubKey; assertFalse(baseAccount.isReadonly()); // 在空白状态下写入数据; - long v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), 0); + long v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A"), 0); // 预期失败; assertEquals(-1, v); - v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), 1); + v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A"), 1); // 预期失败; assertEquals(-1, v); - v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), -1); + v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A"), -1); // 预期成功; assertEquals(0, v); - v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A-1"), -1); + v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A-1"), -1); // 已经存在版本,指定版本号-1,预期导致失败; assertEquals(-1, v); baseAccount.commit(); v = 0; for (int i = 0; i < 10; i++) { - long s = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A_" + i), v); + long s = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A_" + i), v); baseAccount.commit(); // 预期成功; assertEquals(v + 1, s); v++; } - v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A_" + v), v + 1); + v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A_" + v), v + 1); // 预期成功; assertEquals(-1, v); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java index 3232c385..de1d224f 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java @@ -16,14 +16,35 @@ import static org.mockito.Mockito.when; import java.io.InputStream; import java.util.Random; -import com.jd.blockchain.utils.io.BytesUtils; -import com.jd.blockchain.ledger.*; import org.junit.Test; import org.mockito.Mockito; import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.BlockchainKeyGenerator; +import com.jd.blockchain.ledger.BlockchainKeypair; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.DataAccountRegisterOperation; +import com.jd.blockchain.ledger.EndpointRequest; +import com.jd.blockchain.ledger.LedgerBlock; +import com.jd.blockchain.ledger.LedgerInitSetting; +import com.jd.blockchain.ledger.LedgerPermission; +import com.jd.blockchain.ledger.LedgerTransaction; +import com.jd.blockchain.ledger.NodeRequest; +import com.jd.blockchain.ledger.OperationResult; +import com.jd.blockchain.ledger.ParticipantNode; +import com.jd.blockchain.ledger.ParticipantRegisterOperation; +import com.jd.blockchain.ledger.ParticipantStateUpdateOperation; +import com.jd.blockchain.ledger.TransactionContent; +import com.jd.blockchain.ledger.TransactionContentBody; +import com.jd.blockchain.ledger.TransactionPermission; +import com.jd.blockchain.ledger.TransactionRequest; +import com.jd.blockchain.ledger.TransactionRequestBuilder; +import com.jd.blockchain.ledger.TransactionResponse; +import com.jd.blockchain.ledger.TransactionState; +import com.jd.blockchain.ledger.TypedValue; +import com.jd.blockchain.ledger.UserRegisterOperation; import com.jd.blockchain.ledger.core.DefaultOperationHandleRegisteration; import com.jd.blockchain.ledger.core.LedgerDataQuery; import com.jd.blockchain.ledger.core.LedgerDataset; @@ -43,6 +64,8 @@ import com.jd.blockchain.storage.service.utils.MemoryKVStorage; import com.jd.blockchain.transaction.BooleanValueHolder; import com.jd.blockchain.transaction.TxBuilder; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; +import com.jd.blockchain.utils.io.BytesUtils; import test.com.jd.blockchain.ledger.TxTestContract; import test.com.jd.blockchain.ledger.TxTestContractImpl; @@ -132,7 +155,7 @@ public class ContractInvokingTest { assertEquals(1, opResults.length); assertEquals(0, opResults[0].getIndex()); - byte[] expectedRetnBytes = BinaryProtocol.encode(BytesData.fromInt64(issueAmount), BytesValue.class); + byte[] expectedRetnBytes = BinaryProtocol.encode(TypedValue.fromInt64(issueAmount), BytesValue.class); byte[] reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class); assertArrayEquals(expectedRetnBytes, reallyRetnBytes); @@ -218,9 +241,9 @@ public class ContractInvokingTest { TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare(); txResultHandle.commit(); - BytesValue latestValue = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getBytes(key, + BytesValue latestValue = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getValue(key, -1); - System.out.printf("latest value=[%s] %s \r\n", latestValue.getType(), latestValue.getValue().toUTF8String()); + System.out.printf("latest value=[%s] %s \r\n", latestValue.getType(), latestValue.getBytes().toUTF8String()); boolean readable = readableHolder.get(); assertTrue(readable); @@ -278,14 +301,14 @@ public class ContractInvokingTest { } }); // 预期数据都能够正常写入; - KVDataEntry kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K1", + DataEntry kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K1", 0); - KVDataEntry kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K2", + DataEntry kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K2", 0); assertEquals(0, kv1.getVersion()); assertEquals(0, kv2.getVersion()); - assertEquals("V1-0", kv1.getValue()); - assertEquals("V2-0", kv2.getValue()); + assertEquals("V1-0", kv1.getValue().stringValue()); + assertEquals("V2-0", kv2.getValue().stringValue()); // 构建基于接口调用合约的交易请求,用于测试合约调用; buildBlock(ledgerRepo, ledgerManager, opReg, new TxDefinitor() { @@ -299,12 +322,12 @@ public class ContractInvokingTest { } }); // 预期数据都能够正常写入; - kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K1", 1); - kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K2", 1); + kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K1", 1); + kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K2", 1); assertEquals(1, kv1.getVersion()); assertEquals(1, kv2.getVersion()); - assertEquals("V1-1", kv1.getValue()); - assertEquals("V2-1", kv2.getValue()); + assertEquals("V1-1", kv1.getValue().stringValue()); + assertEquals("V2-1", kv2.getValue().stringValue()); // 构建基于接口调用合约的交易请求,用于测试合约调用; buildBlock(ledgerRepo, ledgerManager, opReg, new TxDefinitor() { @@ -314,16 +337,17 @@ public class ContractInvokingTest { contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K1", "V1-2", 1); contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K2", "V2-2", - 0); + 0);//预期会回滚; } }); - // 预期数据都能够正常写入; - kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K1", 1); + // 预期数据回滚,账本没有发生变更; + kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K1", 1); assertEquals(1, kv1.getVersion()); - assertEquals("V1-1", kv1.getValue()); - kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K1", 2); - assertEquals(-1, kv1.getVersion()); - assertEquals(null, kv1.getValue()); + assertEquals("V1-1", kv1.getValue().stringValue()); + kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K1", 2); + assertNull(kv1); + kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K2", 1); + assertEquals(1, kv2.getVersion()); } diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java index a50cd41e..53e9eb4d 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java @@ -1,22 +1,12 @@ package test.com.jd.blockchain.ledger.core; -import static org.junit.Assert.assertEquals; - import java.util.Random; import org.junit.Before; -import org.junit.Test; -import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; -import com.jd.blockchain.crypto.service.sm.SMAlgorithm; -import com.jd.blockchain.ledger.AccountHeader; +import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.UserInfo; -import com.jd.blockchain.ledger.core.MerkleAccountSet; -import com.jd.blockchain.utils.Bytes; /** * Created by zhangshuang3 on 2018/9/3. @@ -35,27 +25,27 @@ public class LedgerAccountTest { rand.nextBytes(seed); rand.nextBytes(settingValue); rand.nextBytes(rawDigestBytes); - DataContractRegistry.register(AccountHeader.class); + DataContractRegistry.register(BlockchainIdentity.class); DataContractRegistry.register(UserInfo.class); } - @Test - public void testSerialize_AccountHeader() { - String address = "xxxxxxxxxxxx"; - PubKey pubKey = new PubKey(SMAlgorithm.SM2, rawDigestBytes); - HashDigest hashDigest = new HashDigest(ClassicAlgorithm.SHA256, rawDigestBytes); - MerkleAccountSet.AccountHeaderData accountHeaderData = new MerkleAccountSet.AccountHeaderData(Bytes.fromString(address), - pubKey, hashDigest); - - // encode and decode - byte[] encodeBytes = BinaryProtocol.encode(accountHeaderData, AccountHeader.class); - AccountHeader deAccountHeaderData = BinaryProtocol.decode(encodeBytes); - - // verify start - assertEquals(accountHeaderData.getAddress(), deAccountHeaderData.getAddress()); - assertEquals(accountHeaderData.getPubKey(), deAccountHeaderData.getPubKey()); - assertEquals(accountHeaderData.getRootHash(), deAccountHeaderData.getRootHash()); - - } +// @Test +// public void testSerialize_AccountHeader() { +// String address = "xxxxxxxxxxxx"; +// PubKey pubKey = new PubKey(SMAlgorithm.SM2, rawDigestBytes); +// HashDigest hashDigest = new HashDigest(ClassicAlgorithm.SHA256, rawDigestBytes); +// MerkleAccountSet.AccountHeaderData accountHeaderData = new MerkleAccountSet.AccountHeaderData(Bytes.fromString(address), +// pubKey, hashDigest); +// +// // encode and decode +// byte[] encodeBytes = BinaryProtocol.encode(accountHeaderData, AccountHeader.class); +// AccountHeader deAccountHeaderData = BinaryProtocol.decode(encodeBytes); +// +// // verify start +// assertEquals(accountHeaderData.getAddress(), deAccountHeaderData.getAddress()); +// assertEquals(accountHeaderData.getPubKey(), deAccountHeaderData.getPubKey()); +// assertEquals(accountHeaderData.getRootHash(), deAccountHeaderData.getRootHash()); + +// } } diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java index 97979205..78f04762 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java @@ -8,12 +8,9 @@ import org.junit.Before; import org.junit.Test; import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.Crypto; -import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.SignatureFunction; -import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainKeyGenerator; @@ -25,7 +22,7 @@ import com.jd.blockchain.ledger.LedgerInitSetting; import com.jd.blockchain.ledger.LedgerTransaction; import com.jd.blockchain.ledger.TransactionRequest; import com.jd.blockchain.ledger.TransactionState; -import com.jd.blockchain.ledger.core.CryptoConfig; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.core.DataAccount; import com.jd.blockchain.ledger.core.LedgerDataset; import com.jd.blockchain.ledger.core.LedgerEditor; @@ -33,11 +30,6 @@ import com.jd.blockchain.ledger.core.LedgerTransactionContext; import com.jd.blockchain.ledger.core.LedgerTransactionalEditor; import com.jd.blockchain.ledger.core.UserAccount; import com.jd.blockchain.storage.service.utils.MemoryKVStorage; -import com.jd.blockchain.transaction.ConsensusParticipantData; -import com.jd.blockchain.transaction.LedgerInitData; -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.io.BytesUtils; -import com.jd.blockchain.utils.net.NetworkAddress; public class LedgerEditorTest { @@ -102,7 +94,7 @@ public class LedgerEditorTest { DataAccount dataAccount = ldgDS.getDataAccountSet().register(dataKP.getAddress(), dataKP.getPubKey(), null); - dataAccount.setBytes(Bytes.fromString("A"), "abc", -1); + dataAccount.getDataset().setValue("A", TypedValue.fromText("abc"), -1); LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS); LedgerBlock block = ldgEdt.prepare(); @@ -115,9 +107,9 @@ public class LedgerEditorTest { assertEquals(0, block.getHeight()); // 验证数据读写的一致性; - BytesValue bytes = dataAccount.getBytes("A"); + BytesValue bytes = dataAccount.getDataset().getValue("A"); assertEquals(DataType.TEXT, bytes.getType()); - String textValue = bytes.getValue().toUTF8String(); + String textValue = bytes.getBytes().toUTF8String(); assertEquals("abc", textValue); } diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerTestUtils.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerTestUtils.java index d3595755..a9c8a683 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerTestUtils.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerTestUtils.java @@ -44,12 +44,18 @@ public class LedgerTestUtils { partiKeys[1] = BlockchainKeyGenerator.getInstance().generate(); return createLedgerInitSetting(partiKeys); } - - public static LedgerInitSetting createLedgerInitSetting(BlockchainKeypair[] partiKeys) { + + public static CryptoProvider[] getContextProviders() { CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); } + + return supportedProviders; + } + + public static LedgerInitSetting createLedgerInitSetting(BlockchainKeypair[] partiKeys) { + CryptoProvider[] supportedProviders =getContextProviders(); CryptoConfig defCryptoSetting = new CryptoConfig(); defCryptoSetting.setSupportedProviders(supportedProviders); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleAccountSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleAccountSetTest.java new file mode 100644 index 00000000..f3bb67da --- /dev/null +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleAccountSetTest.java @@ -0,0 +1,58 @@ +package test.com.jd.blockchain.ledger.core; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; + +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.ledger.BlockchainKeyGenerator; +import com.jd.blockchain.ledger.BlockchainKeypair; +import com.jd.blockchain.ledger.TypedValue; +import com.jd.blockchain.ledger.core.CompositeAccount; +import com.jd.blockchain.ledger.core.CryptoConfig; +import com.jd.blockchain.ledger.core.MerkleAccountSet; +import com.jd.blockchain.ledger.core.OpeningAccessPolicy; +import com.jd.blockchain.storage.service.utils.MemoryKVStorage; +import com.jd.blockchain.utils.Bytes; + +public class MerkleAccountSetTest { + + @Test + public void testRegister() { + final OpeningAccessPolicy POLICY = new OpeningAccessPolicy(); + + final MemoryKVStorage STORAGE = new MemoryKVStorage(); + + Bytes KEY_PREFIX = Bytes.fromString("/ACCOUNT"); + + CryptoConfig cryptoConfig = new CryptoConfig(); + cryptoConfig.setSupportedProviders(LedgerTestUtils.getContextProviders()); + cryptoConfig.setAutoVerifyHash(true); + cryptoConfig.setHashAlgorithm(Crypto.getAlgorithm("SHA256")); + + MerkleAccountSet accountset = new MerkleAccountSet(cryptoConfig, KEY_PREFIX, STORAGE, STORAGE, POLICY); + + BlockchainKeypair key1 = BlockchainKeyGenerator.getInstance().generate(); + accountset.register(key1.getIdentity()); + + accountset.commit(); + + CompositeAccount acc1 = accountset.getAccount(key1.getAddress()); + assertNotNull(acc1); + assertEquals(0, accountset.getVersion(key1.getAddress())); + + acc1.getDataset().setValue("K1", TypedValue.fromText("V0"), -1); + + TypedValue v1 = acc1.getDataset().getValue("K1"); + assertNotNull(v1); + assertEquals(0, acc1.getDataset().getVersion("K1")); + + accountset.commit(); + + v1 = acc1.getDataset().getValue("K1"); + assertNotNull(v1); + assertEquals(0, acc1.getDataset().getVersion("K1")); + } + +} diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleDataSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleDataSetTest.java index a90806d6..a8ab595b 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleDataSetTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleDataSetTest.java @@ -23,9 +23,11 @@ import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.MerkleProof; import com.jd.blockchain.ledger.core.CryptoConfig; import com.jd.blockchain.ledger.core.MerkleDataSet; -import com.jd.blockchain.storage.service.VersioningKVEntry; import com.jd.blockchain.storage.service.utils.MemoryKVStorage; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; +import com.jd.blockchain.utils.Dataset; +import com.jd.blockchain.utils.DatasetHelper; import com.jd.blockchain.utils.io.BytesUtils; public class MerkleDataSetTest { @@ -53,9 +55,9 @@ public class MerkleDataSetTest { MemoryKVStorage storage = new MemoryKVStorage(); MerkleDataSet mds = new MerkleDataSet(cryptoConfig, keyPrefix, storage, storage); - mds.setValue("A", "A".getBytes(), -1); - mds.setValue("B", "B".getBytes(), -1); - mds.setValue("C", "C".getBytes(), -1); + mds.setValue(Bytes.fromString("A"), "A".getBytes(), -1); + mds.setValue(Bytes.fromString("B"), "B".getBytes(), -1); + mds.setValue(Bytes.fromString("C"), "C".getBytes(), -1); mds.commit(); @@ -85,22 +87,23 @@ public class MerkleDataSetTest { MemoryKVStorage storage = new MemoryKVStorage(); MerkleDataSet mds = new MerkleDataSet(cryptoConfig, keyPrefix, storage, storage); - mds.setValue("A", "A".getBytes(), -1); - mds.setValue("B", "B".getBytes(), -1); - mds.setValue("C", "C".getBytes(), -1); + Dataset ds = DatasetHelper.map(mds); + ds.setValue("A", "A".getBytes(), -1); + ds.setValue("B", "B".getBytes(), -1); + ds.setValue("C", "C".getBytes(), -1); mds.commit(); - byte[] va = mds.getValue("A"); + byte[] va = ds.getValue("A"); assertNotNull(va); assertEquals("A", new String(va)); - byte[] vc = mds.getValue("C"); - VersioningKVEntry ventry = mds.getDataEntry("C"); + byte[] vc = ds.getValue("C"); + DataEntry ventry = ds.getDataEntry("C"); assertNotNull(vc); assertNotNull(ventry); assertEquals("C", new String(vc)); - assertEquals("C", ventry.getKey().toUTF8String()); + assertEquals("C", ventry.getKey()); HashDigest root1 = mds.getRootHash(); @@ -111,8 +114,8 @@ public class MerkleDataSetTest { int expStorageCount = 10; assertEquals(expStorageCount, storage.getStorageCount()); - mds.setValue("B", "B".getBytes(), 0); - mds.setValue("C", "C".getBytes(), 0); + ds.setValue("B", "B".getBytes(), 0); + ds.setValue("C", "C".getBytes(), 0); mds.commit(); HashDigest root2 = mds.getRootHash(); assertNotEquals(root1, root2); @@ -122,7 +125,7 @@ public class MerkleDataSetTest { expStorageCount = expStorageCount + 3; assertEquals(expStorageCount, storage.getStorageCount()); - mds.setValue("D", "DValue".getBytes(), -1); + ds.setValue("D", "DValue".getBytes(), -1); mds.commit(); HashDigest root3 = mds.getRootHash(); assertNotEquals(root2, root3); @@ -135,31 +138,31 @@ public class MerkleDataSetTest { assertEquals(expStorageCount, storage.getStorageCount()); // Check rollback function: Add some keys, and then rollback; - long v = mds.setValue("E", "E-values".getBytes(), -1); + long v = ds.setValue("E", "E-values".getBytes(), -1); assertEquals(v, 0); - String expEValue = new String(mds.getValue("E")); + String expEValue = new String(ds.getValue("E")); assertEquals(expEValue, "E-values"); - v = mds.setValue("F", "F-values".getBytes(), -1); + v = ds.setValue("F", "F-values".getBytes(), -1); assertEquals(v, 0); - String expFValue = new String(mds.getValue("F")); + String expFValue = new String(ds.getValue("F")); assertEquals(expFValue, "F-values"); - v = mds.setValue("E", "E-values-1".getBytes(), 0); + v = ds.setValue("E", "E-values-1".getBytes(), 0); assertEquals(v, 1); - expEValue = new String(mds.getValue("E")); + expEValue = new String(ds.getValue("E")); assertEquals(expEValue, "E-values-1"); mds.cancel(); - byte[] bv = mds.getValue("E"); + byte[] bv = ds.getValue("E"); assertNull(bv); - bv = mds.getValue("F"); + bv = ds.getValue("F"); assertNull(bv); - v = mds.getVersion("E"); + v = ds.getVersion("E"); assertEquals(-1, v); - v = mds.getVersion("F"); + v = ds.getVersion("F"); assertEquals(-1, v); // Expect that states has been recover; @@ -194,10 +197,11 @@ public class MerkleDataSetTest { MemoryKVStorage storage = new MemoryKVStorage(); MerkleDataSet mds = new MerkleDataSet(cryptoConfig, keyPrefix, storage, storage); + Dataset ds = DatasetHelper.map(mds); // 初始的时候没有任何数据,总是返回 null; - VersioningKVEntry verKVEntry = mds.getDataEntry("NULL_KEY"); - byte[] vbytes = mds.getValue("NULL_KEY"); + DataEntry verKVEntry = ds.getDataEntry("NULL_KEY"); + byte[] vbytes = ds.getValue("NULL_KEY"); assertNull(verKVEntry); assertNull(vbytes); @@ -217,7 +221,7 @@ public class MerkleDataSetTest { for (int i = 0; i < count; i++) { key = "data" + i; rand.nextBytes(data); - v = mds.setValue(key, data, -1); + v = ds.setValue(key, data, -1); dataVersions.put(key, v); dataValues.put(key + "_" + v, data); assertEquals(v, 0); @@ -237,7 +241,7 @@ public class MerkleDataSetTest { KeySnapshot ks = new KeySnapshot(); ks.proof = proof; - ks.maxVersion = mds.getVersion(key); + ks.maxVersion = ds.getVersion(key); snapshot.put(key, ks); } @@ -271,7 +275,7 @@ public class MerkleDataSetTest { key = "data" + i; rand.nextBytes(data); expVer = dataVersions.get(key); - v = mds.setValue(key, data, expVer); + v = ds.setValue(key, data, expVer); assertEquals(v, expVer + 1); @@ -300,7 +304,7 @@ public class MerkleDataSetTest { KeySnapshot ks = new KeySnapshot(); ks.proof = proof; - ks.maxVersion = mds.getVersion(key); + ks.maxVersion = ds.getVersion(key); snapshot.put(key, ks); } history.put(rootHash, snapshot); @@ -316,6 +320,7 @@ public class MerkleDataSetTest { MerkleDataSet mdsReload = new MerkleDataSet(hisRootHash, cryptoConfig, keyPrefix, storage, storage, true); + Dataset dsReload = DatasetHelper.map(mdsReload); assertEquals(hisRootHash, mdsReload.getRootHash()); // verify every keys; @@ -323,7 +328,7 @@ public class MerkleDataSetTest { key = "data" + i; // 最新版本一致; long expLatestVersion = snapshot.get(key).maxVersion; - long actualLatestVersion = mdsReload.getVersion(key); + long actualLatestVersion = dsReload.getVersion(key); assertEquals(expLatestVersion, actualLatestVersion); // 数据证明一致; @@ -339,7 +344,7 @@ public class MerkleDataSetTest { for (long j = 0; j < actualLatestVersion; j++) { String keyver = key + "_" + j; byte[] expValue = dataValues.get(keyver); - byte[] actualValue = mdsReload.getValue(key, j); + byte[] actualValue = dsReload.getValue(key, j); assertTrue(BytesUtils.equals(expValue, actualValue)); } } @@ -365,10 +370,11 @@ public class MerkleDataSetTest { MemoryKVStorage storage = new MemoryKVStorage(); MerkleDataSet mds = new MerkleDataSet(cryptoConfig, keyPrefix, storage, storage); + Dataset ds = DatasetHelper.map(mds); // 初始的时候没有任何数据,总是返回 null; - VersioningKVEntry verKVEntry = mds.getDataEntry("NULL_KEY"); - byte[] vbytes = mds.getValue("NULL_KEY"); + DataEntry verKVEntry = ds.getDataEntry("NULL_KEY"); + byte[] vbytes = ds.getValue("NULL_KEY"); assertNull(verKVEntry); assertNull(vbytes); @@ -388,7 +394,7 @@ public class MerkleDataSetTest { MerkleProof proof; for (int i = 0; i < count; i++) { key = "data" + i; - v = mds.setValue(key, data, -1); + v = ds.setValue(key, data, -1); dataVersions.put(key, v); // dataValues.put(key + "_" + v, data); assertEquals(v, 0); @@ -408,7 +414,7 @@ public class MerkleDataSetTest { KeySnapshot ks = new KeySnapshot(); ks.proof = proof; - ks.maxVersion = mds.getVersion(key); + ks.maxVersion = ds.getVersion(key); snapshot.put(key, ks); } @@ -418,6 +424,7 @@ public class MerkleDataSetTest { // verify; { MerkleDataSet mdsReload = new MerkleDataSet(rootHash, cryptoConfig, keyPrefix, storage, storage, true); + Dataset dsReload = DatasetHelper.map(mdsReload); // verify every keys; Map snapshot = history.get(rootHash); MerkleProof expProof; @@ -429,7 +436,7 @@ public class MerkleDataSetTest { expProof = snapshot.get(key).proof; assertEquals(expProof.toString(), proof.toString()); - byte[] value = mdsReload.getValue(key); + byte[] value = dsReload.getValue(key); assertTrue(BytesUtils.equals(data, value)); } } diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java index 06bf987d..3d7f179b 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java @@ -332,24 +332,25 @@ public class TransactionBatchProcessorTest { newBlock = newBlockEditor.prepare(); newBlockEditor.commit(); - BytesValue v1_0 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K1", + BytesValue v1_0 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K1", 0); - BytesValue v1_1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K1", + BytesValue v1_1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K1", 1); - BytesValue v2 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K2", + BytesValue v2 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K2", 0); - BytesValue v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K3", + BytesValue v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K3", 0); + assertNotNull(v1_0); assertNotNull(v1_1); assertNotNull(v2); assertNotNull(v3); - assertEquals("V-1-1", v1_0.getValue().toUTF8String()); - assertEquals("V-1-2", v1_1.getValue().toUTF8String()); - assertEquals("V-2-1", v2.getValue().toUTF8String()); - assertEquals("V-3-1", v3.getValue().toUTF8String()); + assertEquals("V-1-1", v1_0.getBytes().toUTF8String()); + assertEquals("V-1-2", v1_1.getBytes().toUTF8String()); + assertEquals("V-2-1", v2.getBytes().toUTF8String()); + assertEquals("V-3-1", v3.getBytes().toUTF8String()); // 提交多笔数据写入的交易,包含存在数据版本冲突的交易,验证交易是否正确回滚; // 先写一笔正确的交易; k3 的版本将变为 1 ; @@ -376,22 +377,22 @@ 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()).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); assertNotNull(v3); - assertEquals("V-1-2", v1.getValue().toUTF8String()); - assertEquals("V-3-2", v3.getValue().toUTF8String()); + assertEquals("V-1-2", v1.getBytes().toUTF8String()); + assertEquals("V-3-2", v3.getBytes().toUTF8String()); // // 验证正确性; // ledgerManager = new LedgerManager(); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionSetTest.java index cd5ebc9f..63ee3e64 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionSetTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionSetTest.java @@ -164,8 +164,8 @@ public class TransactionSetTest { for (int i = 0; i < acutualKVWriteSet.length; i++) { assertEquals(expKVWriteSet[i].getKey(), acutualKVWriteSet[i].getKey()); assertEquals(expKVWriteSet[i].getExpectedVersion(), acutualKVWriteSet[i].getExpectedVersion()); - assertTrue(BytesUtils.equals(expKVWriteSet[i].getValue().getValue().toBytes(), - acutualKVWriteSet[i].getValue().getValue().toBytes())); + assertTrue(BytesUtils.equals(expKVWriteSet[i].getValue().getBytes().toBytes(), + acutualKVWriteSet[i].getValue().getBytes().toBytes())); } ContractCodeDeployOperation actualContractDplOp = (ContractCodeDeployOperation) actualOperations[3]; diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Account.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Account.java new file mode 100644 index 00000000..28694160 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Account.java @@ -0,0 +1,11 @@ +package com.jd.blockchain.ledger; + +import com.jd.blockchain.utils.Dataset; + +public interface Account { + + BlockchainIdentity getID(); + + Dataset getDataset(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AccountHeader.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AccountHeader.java index 16f2794b..fcc530de 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AccountHeader.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AccountHeader.java @@ -1,20 +1,20 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.binaryproto.PrimitiveType; -import com.jd.blockchain.consts.DataCodes; -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.utils.Bytes; - -@DataContract(code= DataCodes.ACCOUNT_HEADER) -public interface AccountHeader extends MerkleSnapshot{ - - @DataField(order=1, primitiveType = PrimitiveType.BYTES) - Bytes getAddress(); - - @DataField(order=2, primitiveType = PrimitiveType.BYTES) - PubKey getPubKey(); - - -} +//package com.jd.blockchain.ledger; +// +//import com.jd.blockchain.binaryproto.DataContract; +//import com.jd.blockchain.binaryproto.DataField; +//import com.jd.blockchain.binaryproto.PrimitiveType; +//import com.jd.blockchain.consts.DataCodes; +//import com.jd.blockchain.crypto.PubKey; +//import com.jd.blockchain.utils.Bytes; +// +//@Deprecated +//@DataContract(code= DataCodes.ACCOUNT_HEADER) +//public interface AccountHeader { //extends MerkleSnapshot{ +// +// @DataField(order = 1, primitiveType = PrimitiveType.BYTES) +// Bytes getAddress(); +// +// @DataField(order = 2, primitiveType=PrimitiveType.BYTES) +// PubKey getPubKey(); +// +//} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesData.java deleted file mode 100644 index ca4e9cb0..00000000 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesData.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.io.BytesUtils; - -/** - * - * @author huanghaiquan - * - */ -public class BytesData implements BytesValue { - DataType type; - Bytes value; - - private BytesData(DataType type, byte[] bytes) { - this.type = type; - this.value = new Bytes(bytes); - } - - private BytesData(DataType type, Bytes bytes) { - this.type = type; - this.value = bytes; - } - - public static BytesValue fromType(DataType type, byte[] value) { - return new BytesData(type, value); - } - - public static BytesValue fromBytes(byte[] value) { - return new BytesData(DataType.BYTES, value); - } - - public static BytesValue fromBytes(Bytes value) { - return new BytesData(DataType.BYTES, value); - } - - public static BytesValue fromImage(byte[] value) { - return new BytesData(DataType.IMG, value); - } - - public static BytesValue fromImage(Bytes value) { - return new BytesData(DataType.IMG, value); - } - - /** - * 以 UTF-8 编码从字符串转换为字节数组值; - * - * @param value - * @return - */ - public static BytesValue fromText(String value) { - return new BytesData(DataType.TEXT, BytesUtils.toBytes(value)); - } - - /** - * 以 UTF-8 编码把字节数组值转换为字符串; - * - * @param bytesValue - * @return - */ - public static String toText(BytesValue bytesValue) { - if (bytesValue == null) { - return null; - } - if (bytesValue.getType() != DataType.TEXT) { - throw new ValueTypeCastException("The expected value type is " + DataType.TEXT.toString() - + ", but it is actually " + bytesValue.getType().toString() + "!"); - } - return bytesValue.getValue().toUTF8String(); - } - - public static BytesValue fromJSON(String value) { - return new BytesData(DataType.JSON, BytesUtils.toBytes(value)); - } - - public static BytesValue fromXML(String value) { - return new BytesData(DataType.XML, BytesUtils.toBytes(value)); - } - - public static BytesValue fromInt32(int value) { - return new BytesData(DataType.INT32, BytesUtils.toBytes(value)); - } - - public static BytesValue fromInt64(long value) { - return new BytesData(DataType.INT64, BytesUtils.toBytes(value)); - } - - public static BytesValue fromInt16(short value) { - return new BytesData(DataType.INT16, BytesUtils.toBytes(value)); - } - - public static BytesValue fromInt8(byte value) { - return new BytesData(DataType.INT8, BytesUtils.toBytes(value)); - } - - public static BytesValue fromTimestamp(long value) { - return new BytesData(DataType.TIMESTAMP, BytesUtils.toBytes(value)); - } - - public static BytesValue fromBoolean(boolean value) { - return new BytesData(DataType.BOOLEAN, BytesUtils.toBytes(value)); - } - - @Override - public DataType getType() { - return this.type; - } - - public void setType(DataType type) { - this.type = type; - } - - @Override - public Bytes getValue() { - return this.value; - } - -} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesDataList.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesDataList.java index f7aef959..a7541a41 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesDataList.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesDataList.java @@ -14,18 +14,18 @@ public class BytesDataList implements BytesValueList { } public static BytesValueList singleText(String value) { - return new BytesDataList(BytesData.fromText(value)); + return new BytesDataList(TypedValue.fromText(value)); } public static BytesValueList singleLong(long value) { - return new BytesDataList(BytesData.fromInt64(value)); + return new BytesDataList(TypedValue.fromInt64(value)); } public static BytesValueList singleInt(int value) { - return new BytesDataList(BytesData.fromInt32(value)); + return new BytesDataList(TypedValue.fromInt32(value)); } public static BytesValueList singleBoolean(boolean value) { - return new BytesDataList(BytesData.fromBoolean(value)); + return new BytesDataList(TypedValue.fromBoolean(value)); } } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValue.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValue.java index 6e7b9b46..47d4ad16 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValue.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValue.java @@ -29,6 +29,6 @@ public interface BytesValue { * @return */ @DataField(order = 1, primitiveType = PrimitiveType.BYTES) - Bytes getValue(); + Bytes getBytes(); } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java index baee5868..6579f1c4 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java @@ -68,7 +68,7 @@ public class BytesValueEncoding { } // 将对象序列化 byte[] serialBytes = BinaryProtocol.encode(value, type); - return BytesData.fromType(DataType.DATA_CONTRACT, serialBytes); + return TypedValue.fromType(DataType.DATA_CONTRACT, serialBytes); } BytesValueResolver bytesValueResolver = CLASS_RESOLVER_MAP.get(type); if (bytesValueResolver == null) { diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractInfo.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractInfo.java index cb1da5c4..047e3c51 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractInfo.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractInfo.java @@ -5,9 +5,10 @@ import com.jd.blockchain.binaryproto.DataField; import com.jd.blockchain.binaryproto.PrimitiveType; import com.jd.blockchain.consts.DataCodes; -@DataContract(code= DataCodes.CONTRACT) -public interface ContractInfo extends AccountHeader { +@DataContract(code= DataCodes.CONTRACT_ACCOUNT_HEADER) +public interface ContractInfo extends BlockchainIdentity, MerkleSnapshot { @DataField(order=4, primitiveType= PrimitiveType.BYTES) byte[] getChainCode(); + } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataType.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataType.java index 1cb8fce3..6395bcc2 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataType.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataType.java @@ -106,6 +106,20 @@ public enum DataType { * DataContract 数据; */ DATA_CONTRACT((byte) (BaseType.EXT | 0x01)); + + + + public static final boolean BOOLEAN_DEFAULT_VALUE = false; + + public static final byte INT8_DEFAULT_VALUE = 0; + + public static final short INT16_DEFAULT_VALUE = 0; + + public static final int INT32_DEFAULT_VALUE = 0; + + public static final long INT64_DEFAULT_VALUE = 0; + + @EnumField(type = PrimitiveType.INT8) public final byte CODE; @@ -114,6 +128,51 @@ public enum DataType { this.CODE = code; } + /** + * 是否表示“文本类型”或“文本衍生类型”; + * + * @return + */ + public boolean isText() { + return BaseType.TEXT == (BaseType.TEXT & CODE); + } + + /** + * 是否表示“字节类型”或“字节衍生类型”; + * + * @return + */ + public boolean isBytes() { + return BaseType.BYTES == (BaseType.BYTES & CODE); + } + + /** + * 是否表示“整数类型”或“整数衍生类型”; + * + * @return + */ + public boolean isInteger() { + return BaseType.INTEGER == (BaseType.INTEGER & CODE); + } + + /** + * 是否表示“布尔类型”; + * + * @return + */ + public boolean isBoolean() { + return BaseType.BOOLEAN == (BaseType.BOOLEAN & CODE); + } + + /** + * 是否表示“扩展类型”; + * + * @return + */ + public boolean isExt() { + return BaseType.EXT == (BaseType.EXT & CODE); + } + public static DataType valueOf(byte code) { for (DataType dataType : DataType.values()) { if (dataType.CODE == code) { diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/HashProof.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/HashProof.java new file mode 100644 index 00000000..4b2dd9c5 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/HashProof.java @@ -0,0 +1,44 @@ +package com.jd.blockchain.ledger; + +import com.jd.blockchain.crypto.HashDigest; + +public interface HashProof { + /** + * 最大层级数;
+ * 叶子节点(即数据节点)的层级为 0,数据节点之上的每一级父节点的层级加 1, 最大层级便是根节点的层级; + * + * @return + * + * @see MerkleTree#getLevel() + */ + int getLevels(); + + /** + * 返回证明中指定层级的节点的哈希; + *

+ * + * @param level + * 参数值为 0 返回的是数据节点的哈希;
+ * 参数值为 {@link #getLevels()} 返回的是根节点的哈希; + * @return + */ + HashDigest getHash(int level); + + /** + * 返回根节点的哈希; + * + * @return + */ + default HashDigest getRootHash() { + return getHash(getLevels()); + } + + /** + * 返回数据节点的哈希; + * + * @return + */ + default HashDigest getDataHash() { + return getHash(0); + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataObject.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataObject.java deleted file mode 100644 index 1e8247ee..00000000 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataObject.java +++ /dev/null @@ -1,616 +0,0 @@ -package com.jd.blockchain.ledger; - -import java.math.BigInteger; -import java.util.Date; - -import com.jd.blockchain.binaryproto.PrimitiveType; -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.io.ByteArray; -import com.jd.blockchain.utils.io.BytesUtils; - -/** - * KV数据项; - * - *

- * - * {@link KVDataObject} 被设计为只读对象; - * - * @author huanghaiquan - * - */ -public class KVDataObject implements KVDataEntry { - - private String key; - - private long version; - - private BytesValue bytesValue; - - public KVDataObject(String key, long version, BytesValue bytesValue) { - this.key = key; - this.version = version < 0 ? -1 : version; - this.bytesValue = bytesValue; - } - - /* - * (non-Javadoc) - * - * @see com.jd.blockchain.ledger.KVDataEntry#getKey() - */ - @Override - public String getKey() { - return key; - } - - /* - * (non-Javadoc) - * - * @see com.jd.blockchain.ledger.KVDataEntry#getVersion() - */ - @Override - public long getVersion() { - return version; - } - - /* - * (non-Javadoc) - * - * @see com.jd.blockchain.ledger.KVDataEntry#getType() - */ - @Override - public DataType getType() { - return bytesValue == null ? DataType.NIL : bytesValue.getType(); - } - - @Override - public Object getValue() { - if (bytesValue == null) { - return null; - } - - switch (getType()) { - case NIL: - return null; - case TEXT: - return bytesValue.getValue().toUTF8String(); - case BYTES: - return ByteArray.toHex(bytesValue.getValue().toBytes()); - case INT64: - return BytesUtils.toLong(bytesValue.getValue().toBytes()); - case JSON: - return bytesValue.getValue().toUTF8String(); - case XML: - return bytesValue.getValue().toUTF8String(); - - default: - throw new IllegalStateException("Unsupported value type[" + getType() + "] to resolve!"); - } - } - - /** - * 是否为空值; - *

- * - * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#NIL} 时返回 true,其它情况返回 false; - *

- * - * @return - */ - public boolean isNil() { - return bytesValue == null || DataType.NIL == bytesValue.getType(); - } - - /** - * 字节数组形式的原始内容; - * - * @return - */ - Bytes bytesArray() { - return bytesValue.getValue(); - } - - /** - * 返回 8 位整数值; - *

- * - * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT8} 有效; - *

- * - * 无效类型将引发 {@link IllegalStateException} 异常; - * - * @return - */ - public byte tinyValue() { - if (DataType.INT8 == getType()) { - return bytesValue.getValue().toBytes()[0]; - } - throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT8, getType())); - } - - /** - * 返回 16 位整数值; - *

- * - * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT16} 有效; - *

- * - * 无效类型将引发 {@link IllegalStateException} 异常; - * - * @return - */ - public short shortValue() { - if (DataType.INT16 == getType()) { - return BytesUtils.toShort(bytesValue.getValue().toBytes(), 0); - } - throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT16, getType())); - } - - /** - * 返回 32 位整数值; - *

- * - * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT32} 有效; - *

- * - * 无效类型将引发 {@link IllegalStateException} 异常; - * - * @return - */ - public int intValue() { - if (DataType.INT32 == getType()) { - return BytesUtils.toInt(bytesValue.getValue().toBytes(), 0); - } - throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT32, getType())); - } - - /** - * 返回 64 位整数值; - *

- * - * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT64} 有效; - *

- * - * 无效类型将引发 {@link IllegalStateException} 异常; - * - * @return - */ - public long longValue() { - if (DataType.INT64 == getType()) { - return BytesUtils.toLong(bytesValue.getValue().toBytes(), 0); - } - throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT64, getType())); - - } - - /** - * 返回大整数值; - *

- * - * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#BIG_INT} 有效; - *

- * - * 无效类型将引发 {@link IllegalStateException} 异常; - * - * @return - */ - public BigInteger bigIntValue() { - if (DataType.BIG_INT == getType()) { - return new BigInteger(bytesValue.getValue().toBytes()); - } - throw new IllegalStateException( - String.format("Expected type [%s], but [%s]", DataType.BIG_INT, getType())); - } - - /** - * 返回布尔值; - *

- * - * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#BIG_INT} 有效; - *

- * - * 无效类型将引发 {@link IllegalStateException} 异常; - * - * @return - */ - public boolean boolValue() { - if (DataType.BOOLEAN == getType()) { - return BytesUtils.toBoolean(bytesValue.getValue().toBytes()[0]); - } - throw new IllegalStateException( - String.format("Expected type [%s], but [%s]", DataType.BOOLEAN, getType())); - } - - /** - * 返回日期时间值; - *

- * - * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TIMESTAMP} 有效; - *

- * - * 无效类型将引发 {@link IllegalStateException} 异常; - * - * @return - */ - public Date datetimeValue() { - if (DataType.TIMESTAMP == getType()) { - long ts = BytesUtils.toLong(bytesValue.getValue().toBytes()); - return new Date(ts); - } - throw new IllegalStateException( - String.format("Expected type [%s], but [%s]", DataType.TIMESTAMP, getType())); - } - - /** - * 返回大整数值; - *

- * - * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TEXT} / - * {@link PrimitiveType#JSON} / {@link PrimitiveType#XML} 有效; - *

- * - * 无效类型将引发 {@link IllegalStateException} 异常; - * - * @return - */ - public String stringValue() { - DataType type = getType(); - if (DataType.TEXT == type || DataType.JSON == type || DataType.XML == type) { - return bytesValue.getValue().toUTF8String(); - } - throw new IllegalStateException(String.format("Expected type [%s] or [%s] or [%s] , but [%s]", - PrimitiveType.TEXT, DataType.JSON, DataType.XML, type)); - } - -// // ---------------- -// public KVDataEntry nextVersionNil() { -// return nilState(key, version + 1); -// } -// -// public KVDataEntry nextVersionBoolean(boolean value) { -// return booleanState(key, version + 1, value); -// } -// -// public KVDataEntry nextVersionTiny(byte value) { -// return tinyState(key, version + 1, value); -// } -// -// public KVDataEntry nextVersionShort(short value) { -// return shortState(key, version + 1, value); -// } -// -// public KVDataEntry nextVersionInt(int value) { -// return intState(key, version + 1, value); -// } -// -// public KVDataEntry nextVersionLong(long value) { -// return longState(key, version + 1, value); -// } -// -// public KVDataEntry nextVersionDatetime(Date value) { -// return datetimeState(key, version + 1, value); -// } -// -// public KVDataEntry nextVersionJson(String value) { -// return jsonState(key, version + 1, value); -// } -// -// public KVDataEntry nextVersionXml(String value) { -// return xmlState(key, version + 1, value); -// } -// -// public KVDataEntry nextVersionBigInt(BigInteger value) { -// return bigIntState(key, version + 1, value); -// } -// -// public KVDataEntry nextVersionText(boolean encrypted, String value) { -// return textState(key, version + 1, encrypted, value); -// } -// -// public KVDataEntry nextVersionBytes(boolean encrypted, byte[] value) { -// return bytesState(key, version + 1, encrypted, value); -// } -// -// public KVDataEntry nextVersionImage(boolean encrypted, byte[] value) { -// return imageState(key, version + 1, encrypted, value); -// } -// -// public KVDataEntry nextVersionVideo(boolean encrypted, byte[] value) { -// return videoState(key, version + 1, encrypted, value); -// } -// -// public KVDataEntry nextVersionLocation(boolean encrypted, byte[] value) { -// return locationState(key, version + 1, encrypted, value); -// } -// // ---------------- -// -// public KVDataEntry newNil() { -// return nilState(key, version); -// } -// -// public KVDataEntry newBoolean(boolean value) { -// return booleanState(key, version, value); -// } -// -// public KVDataEntry newTiny(byte value) { -// return tinyState(key, version, value); -// } -// -// public KVDataEntry newShort(short value) { -// return shortState(key, version, value); -// } -// -// public KVDataEntry newInt(int value) { -// return intState(key, version, value); -// } -// -// public KVDataObject newLong(long value) { -// return longState(key, version, value); -// } -// -// public KVDataEntry newDatetime(Date value) { -// return datetimeState(key, version, value); -// } -// -// public KVDataEntry newJson(String value) { -// return jsonState(key, version, value); -// } -// -// public KVDataEntry newXml(String value) { -// return xmlState(key, version, value); -// } -// -// public KVDataEntry newBigInt(BigInteger value) { -// return bigIntState(key, version, value); -// } -// -// public KVDataEntry newText(boolean encrypted, String value) { -// return textState(key, version, encrypted, value); -// } -// -// public KVDataEntry newBytes(boolean encrypted, byte[] value) { -// return bytesState(key, version, encrypted, value); -// } -// -// public KVDataEntry newImage(boolean encrypted, byte[] value) { -// return imageState(key, version, encrypted, value); -// } -// -// public KVDataEntry newVideo(boolean encrypted, byte[] value) { -// return videoState(key, version, encrypted, value); -// } -// -// public KVDataEntry newLocation(boolean encrypted, byte[] value) { -// return locationState(key, version, encrypted, value); -// } -// -// // ---------------- -// -// public KVDataEntry newNil(long version) { -// return nilState(key, version); -// } -// -// public KVDataEntry newBoolean(long version, boolean value) { -// return booleanState(key, version, value); -// } -// -// public KVDataEntry newTiny(long version, byte value) { -// return tinyState(key, version, value); -// } -// -// public KVDataEntry newShort(long version, short value) { -// return shortState(key, version, value); -// } -// -// public KVDataEntry newInt(long version, int value) { -// return intState(key, version, value); -// } -// -// public KVDataEntry newLong(long version, long value) { -// return longState(key, version, value); -// } -// -// public KVDataEntry newDatetime(long version, Date value) { -// return datetimeState(key, version, value); -// } -// -// public KVDataEntry newJson(long version, String value) { -// return jsonState(key, version, value); -// } -// -// public KVDataEntry newXml(long version, String value) { -// return xmlState(key, version, value); -// } -// -// public KVDataEntry newBigInt(long version, BigInteger value) { -// return bigIntState(key, version, value); -// } -// -// public KVDataEntry newText(long version, boolean encrypted, String value) { -// return textState(key, version, encrypted, value); -// } -// -// public KVDataEntry newBytes(long version, boolean encrypted, byte[] value) { -// return bytesState(key, version, encrypted, value); -// } -// -// public KVDataEntry newImage(long version, boolean encrypted, byte[] value) { -// return imageState(key, version, encrypted, value); -// } -// -// public KVDataEntry newVideo(long version, boolean encrypted, byte[] value) { -// return videoState(key, version, encrypted, value); -// } -// -// public KVDataEntry newLocation(long version, boolean encrypted, byte[] value) { -// return locationState(key, version, encrypted, value); -// } -// -// // ---------------- -// -// public static KVDataEntry booleanState(String key, boolean value) { -// return booleanState(key, -1, value); -// } -// -// public static KVDataEntry tinyState(String key, byte value) { -// return tinyState(key, -1, value); -// } -// -// public static KVDataEntry shortState(String key, short value) { -// return shortState(key, -1, value); -// } -// -// public static KVDataEntry intState(String key, int value) { -// return intState(key, -1, value); -// } -// -// public static KVDataEntry longState(String key, long value) { -// return longState(key, -1, value); -// } -// -// public static KVDataEntry datetimeState(String key, Date value) { -// return datetimeState(key, -1, value); -// } -// -// public static KVDataEntry jsonState(String key, String value) { -// return jsonState(key, -1, value); -// } -// -// public static KVDataEntry xmlState(String key, String value) { -// return xmlState(key, -1, value); -// } -// -// public static KVDataEntry bigIntState(String key, BigInteger value) { -// return bigIntState(key, -1, value); -// } -// -// public static KVDataObject textState(String key, String value) { -// return textState(key, -1, false, value); -// } -// -// public static KVDataEntry bytesState(String key, byte[] value) { -// return bytesState(key, -1, false, value); -// } -// -// public static KVDataEntry imageState(String key, byte[] value) { -// return imageState(key, -1, false, value); -// } -// -// public static KVDataEntry videoState(String key, byte[] value) { -// return videoState(key, -1, false, value); -// } -// -// public static KVDataEntry locationState(String key, byte[] value) { -// return locationState(key, -1, false, value); -// } -// -// // ---------------- -// -// public static KVDataEntry textState(String key, boolean encrypted, String value) { -// return textState(key, -1, encrypted, value); -// } -// -// public static KVDataEntry bytesState(String key, boolean encrypted, byte[] value) { -// return bytesState(key, -1, encrypted, value); -// } -// -// public static KVDataEntry imageState(String key, boolean encrypted, byte[] value) { -// return imageState(key, -1, encrypted, value); -// } -// -// public static KVDataEntry videoState(String key, boolean encrypted, byte[] value) { -// return videoState(key, -1, encrypted, value); -// } -// -// public static KVDataEntry locationState(String key, boolean encrypted, byte[] value) { -// return locationState(key, -1, encrypted, value); -// } -// -// // ---------------------- -// -// public static KVDataEntry nilState(String key) { -// return new KVDataObject(key, ValueType.NIL, -1, false, BytesUtils.EMPTY_BYTES); -// } -// -// public static KVDataEntry nilState(String key, long version) { -// return new KVDataObject(key, ValueType.NIL, version, false, BytesUtils.EMPTY_BYTES); -// } -// -// public static KVDataEntry booleanState(String key, long version, boolean value) { -// byte[] v = { value ? (byte) 1 : (byte) 0 }; -// return new KVDataObject(key, ValueType.BOOLEAN, version, false, v); -// } -// -// public static KVDataEntry tinyState(String key, long version, byte value) { -// byte[] v = { value }; -// return new KVDataObject(key, ValueType.INT8, version, false, v); -// } -// -// public static KVDataEntry shortState(String key, long version, short value) { -// byte[] v = BytesUtils.toBytes(value); -// return new KVDataObject(key, ValueType.INT16, version, false, v); -// } -// -// public static KVDataEntry intState(String key, long version, int value) { -// byte[] v = BytesUtils.toBytes(value); -// return new KVDataObject(key, ValueType.INT32, version, false, v); -// } -// -// public static KVDataObject longState(String key, long version, long value) { -// byte[] v = BytesUtils.toBytes(value); -// return new KVDataObject(key, ValueType.INT64, version, false, v); -// } -// -// public static KVDataEntry datetimeState(String key, long version, Date value) { -// byte[] v = BytesUtils.toBytes(value.getTime()); -// return new KVDataObject(key, ValueType.DATETIME, version, false, v); -// } -// -// public static KVDataObject textState(String key, long version, boolean encrypted, String value) { -// try { -// byte[] v = value.getBytes("UTF-8"); -// return new KVDataObject(key, ValueType.TEXT, version, encrypted, v); -// } catch (UnsupportedEncodingException e) { -// throw new IllegalStateException(e.getMessage(), e); -// } -// } -// -// public static KVDataEntry jsonState(String key, long version, String value) { -// try { -// byte[] v = value.getBytes("UTF-8"); -// return new KVDataObject(key, ValueType.JSON, version, false, v); -// } catch (UnsupportedEncodingException e) { -// throw new IllegalStateException(e.getMessage(), e); -// } -// } -// -// public static KVDataEntry xmlState(String key, long version, String value) { -// try { -// byte[] v = value.getBytes("UTF-8"); -// return new KVDataObject(key, ValueType.XML, version, false, v); -// } catch (UnsupportedEncodingException e) { -// throw new IllegalStateException(e.getMessage(), e); -// } -// } -// -// public static KVDataEntry bigIntState(String key, long version, BigInteger value) { -// byte[] v = value.toByteArray(); -// return new KVDataObject(key, ValueType.BIG_INT, version, false, v); -// } -// -// public static KVDataEntry bytesState(String key, long version, boolean encrypted, byte[] value) { -// return new KVDataObject(key, ValueType.BYTES, version, encrypted, value); -// } -// -// public static KVDataEntry imageState(String key, long version, boolean encrypted, byte[] value) { -// return new KVDataObject(key, ValueType.IMG, version, encrypted, value); -// } -// -// public static KVDataEntry videoState(String key, long version, boolean encrypted, byte[] value) { -// return new KVDataObject(key, ValueType.VIDEO, version, encrypted, value); -// } -// -// public static KVDataEntry locationState(String key, long version, boolean encrypted, byte[] value) { -// return new KVDataObject(key, ValueType.LOCATION, version, encrypted, value); -// } - -} \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleProof.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleProof.java index 1463f736..75721f7f 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleProof.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleProof.java @@ -1,8 +1,6 @@ package com.jd.blockchain.ledger; -import com.jd.blockchain.crypto.HashDigest; - -public interface MerkleProof { +public interface MerkleProof extends HashProof { /** * 所证明的数据节点的序列号; @@ -11,62 +9,46 @@ public interface MerkleProof { */ long getSN(); - /** - * 最大层级数;
- * 叶子节点(即数据节点)的层级为 0,数据节点之上的每一级父节点的层级加 1, 最大层级便是根节点的层级; - * - * @return - * - * @see MerkleTree#getLevel() - */ - int getLevels(); - - /** - * 返回证明中指定层级的节点的哈希; - *

- * - * @param level - * 参数值为 0 返回的是数据节点的哈希;
- * 参数值为 {@link #getLevels()} 返回的是根节点的哈希; - * @return - */ - HashDigest getHash(int level); - - MerkleNode getNode(int level); - // /** -// * 返回证明中指定层级的数据起始序号; +// * 最大层级数;
+// * 叶子节点(即数据节点)的层级为 0,数据节点之上的每一级父节点的层级加 1, 最大层级便是根节点的层级; // * -// * @param level // * @return +// * +// * @see MerkleTree#getLevel() // */ -// long getStartingSN(int level); - +// int getLevels(); +// // /** -// * 返回证明中指定层级的数据记录总数; +// * 返回证明中指定层级的节点的哈希; +// *

// * // * @param level +// * 参数值为 0 返回的是数据节点的哈希;
+// * 参数值为 {@link #getLevels()} 返回的是根节点的哈希; // * @return // */ -// long getDataCount(int level); +// HashDigest getHash(int level); - /** - * 返回根节点的哈希; - * - * @return - */ - default HashDigest getRootHash() { - return getHash(getLevels()); - } + MerkleNode getNode(int level); /** - * 返回数据节点的哈希; - * - * @return - */ - default HashDigest getDataHash() { - return getHash(0); - } +// * 返回根节点的哈希; +// * +// * @return +// */ +// default HashDigest getRootHash() { +// return getHash(getLevels()); +// } +// +// /** +// * 返回数据节点的哈希; +// * +// * @return +// */ +// default HashDigest getDataHash() { +// return getHash(0); +// } default MerkleDataNode getDataNode() { return (MerkleDataNode)getNode(0); diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVData.java new file mode 100644 index 00000000..dd06de98 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVData.java @@ -0,0 +1,78 @@ +package com.jd.blockchain.ledger; + +/** + * 强类型的“键-值”数据对象; + * + *

+ * + * {@link TypedKVData} 被设计为只读对象; + * + * @author huanghaiquan + * + */ +public class TypedKVData implements TypedKVEntry { + + private String key; + + private long version; + + private DataType type; + + private Object value; + + public TypedKVData(String key, long version, DataType type, Object value) { + this.key = key; + this.version = version; + this.type = type; + this.value = value; + } + + public TypedKVData(String key, long version, BytesValue bytesValue) { + this.key = key; + this.version = version; + TypedValue typedValue; + if (bytesValue != null && bytesValue instanceof TypedValue) { + typedValue = (TypedValue) bytesValue; + } else { + typedValue = TypedValue.wrap(bytesValue); + } + this.type = typedValue.getType(); + this.value = typedValue.getValue(); + } + + /* + * (non-Javadoc) + * + * @see com.jd.blockchain.ledger.KVDataEntry#getKey() + */ + @Override + public String getKey() { + return key; + } + + /* + * (non-Javadoc) + * + * @see com.jd.blockchain.ledger.KVDataEntry#getVersion() + */ + @Override + public long getVersion() { + return version; + } + + /* + * (non-Javadoc) + * + * @see com.jd.blockchain.ledger.KVDataEntry#getType() + */ + @Override + public DataType getType() { + return type; + } + + @Override + public Object getValue() { + return value; + } + +} \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataEntry.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVEntry.java similarity index 57% rename from source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataEntry.java rename to source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVEntry.java index 396cc36d..54165c61 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataEntry.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVEntry.java @@ -1,6 +1,6 @@ package com.jd.blockchain.ledger; -public interface KVDataEntry { +public interface TypedKVEntry { /** * 键名; @@ -33,4 +33,12 @@ public interface KVDataEntry { */ Object getValue(); + default long longValue() { + if (getType() == DataType.INT64) { + Object value = getValue(); + return value == null ? 0 : (long) value; + } + throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT64, getType())); + } + } \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedValue.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedValue.java new file mode 100644 index 00000000..65dbd298 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedValue.java @@ -0,0 +1,454 @@ +package com.jd.blockchain.ledger; + +import java.math.BigInteger; +import java.util.Date; + +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.crypto.SignatureDigest; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.io.BytesUtils; + +/** + * + * @author huanghaiquan + * + */ +public class TypedValue implements BytesValue { + + public static final BytesValue NIL = new TypedValue(); + + private DataType type; + private Bytes value; + + private TypedValue(DataType type, byte[] bytes) { + this.type = type; + this.value = new Bytes(bytes); + } + + private TypedValue(DataType type, Bytes bytes) { + this.type = type; + this.value = bytes; + } + + private TypedValue(BytesValue bytesValue) { + if (bytesValue == null) { + this.type = DataType.NIL; + } else { + this.type = bytesValue.getType(); + this.value = bytesValue.getBytes(); + } + } + + private TypedValue() { + this.type = DataType.NIL; + } + + @Override + public DataType getType() { + return this.type; + } + + @Override + public Bytes getBytes() { + return this.value; + } + + public Object getValue() { + if (isNil()) { + return null; + } + switch (type) { + case BOOLEAN: + return toBoolean(); + case INT8: + return toInt8(); + case INT16: + return toInt16(); + case INT32: + return toInt32(); + case INT64: + return toInt64(); + case BIG_INT: + return toBigInteger(); + case TIMESTAMP: + return toDatetime(); + case TEXT: + case JSON: + case XML: + return toText(); + + case BYTES: + case VIDEO: + case IMG: + case LOCATION: + case ENCRYPTED_DATA: + return toBytesArray(); + + case HASH_DIGEST: + return toHashDegist(); + case PUB_KEY: + return toPubKey(); + case SIGNATURE_DIGEST: + return toSignatureDigest(); + + case DATA_CONTRACT: + return toBytesArray(); + default: + throw new IllegalStateException(String.format("Type [%s] has not be supported!", type)); + } + } + + /** + * 是否为空值; + *

+ * + * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#NIL} 时返回 true,其它情况返回 false; + *

+ * + * @return + */ + public boolean isNil() { + return value == null || DataType.NIL == type; + } + + /** + * 返回 8 位整数值; + *

+ * + * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT8} 有效; + *

+ * + * 无效类型将引发 {@link IllegalStateException} 异常; + * + * @return + */ + public byte tinyValue() { + if (isNil()) { + return DataType.INT8_DEFAULT_VALUE; + } + if (DataType.INT8 == getType()) { + return toInt8(); + } + throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int8!", type)); + } + + private byte toInt8() { + return value.toBytes()[0]; + } + + /** + * 返回 16 位整数值; + *

+ * + * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT16} 有效; + *

+ * + * 无效类型将引发 {@link IllegalStateException} 异常; + * + * @return + */ + public short shortValue() { + if (isNil()) { + return DataType.INT16_DEFAULT_VALUE; + } + if (DataType.INT16 == getType()) { + return toInt16(); + } + throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int16!", type)); + } + + private short toInt16() { + return BytesUtils.toShort(value.toBytes(), 0); + } + + /** + * 返回 32 位整数值; + *

+ * + * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT32} 有效; + *

+ * + * 无效类型将引发 {@link IllegalStateException} 异常; + * + * @return + */ + public int intValue() { + if (isNil()) { + return DataType.INT32_DEFAULT_VALUE; + } + if (DataType.INT32 == getType()) { + return toInt32(); + } + throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int32!", type)); + } + + private int toInt32() { + return BytesUtils.toInt(value.toBytes(), 0); + } + + /** + * 返回 64 位整数值; + *

+ * + * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT64} 有效; + *

+ * + * 无效类型将引发 {@link IllegalStateException} 异常; + * + * @return + */ + public long longValue() { + if (isNil()) { + return DataType.INT64_DEFAULT_VALUE; + } + if (DataType.INT64 == type) { + return toInt64(); + } + throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int64!", type)); + + } + + private long toInt64() { + return BytesUtils.toLong(value.toBytes(), 0); + } + + /** + * 返回大整数值; + *

+ * + * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#BIG_INT} 有效; + *

+ * + * 无效类型将引发 {@link IllegalStateException} 异常; + * + * @return + */ + public BigInteger bigIntValue() { + if (isNil()) { + return null; + } + if (DataType.BIG_INT == type) { + return toBigInteger(); + } + throw new IllegalStateException(String.format("Type [%s] cannot be convert to BigInteger!", type)); + } + + private BigInteger toBigInteger() { + return new BigInteger(value.toBytes()); + } + + /** + * 返回布尔值; + *

+ * + * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#BIG_INT} 有效; + *

+ * + * 无效类型将引发 {@link IllegalStateException} 异常; + * + * @return + */ + public boolean boolValue() { + if (isNil()) { + return DataType.BOOLEAN_DEFAULT_VALUE; + } + if (DataType.BOOLEAN == type) { + return toBoolean(); + } + throw new IllegalStateException(String.format("Type [%s] cannot be convert to boolean!", type)); + } + + private boolean toBoolean() { + return BytesUtils.toBoolean(value.toBytes()[0]); + } + + /** + * 返回日期时间值; + *

+ * + * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TIMESTAMP} 有效; + *

+ * + * 无效类型将引发 {@link IllegalStateException} 异常; + * + * @return + */ + public Date datetimeValue() { + if (isNil()) { + return null; + } + if (DataType.TIMESTAMP == type) { + return toDatetime(); + } + throw new IllegalStateException(String.format("Type [%s] cannot be convert to datetime!", type)); + } + + private Date toDatetime() { + long ts = BytesUtils.toLong(value.toBytes()); + return new Date(ts); + } + + /** + * 返回文本值; + *

+ * + * 仅当数据类型 {@link #getType()} 为“文本类型”或“文本衍生类型”时有效; + *

+ * + * 无效类型将引发 {@link IllegalStateException} 异常; + * + * @return + */ + public String stringValue() { + if (isNil()) { + return null; + } + if (type.isText()) { + return toText(); + } + throw new IllegalStateException(String.format("Type [%s] cannot be convert to text!", type)); + } + + private String toText() { + return value.toUTF8String(); + } + + /** + * 返回字节数组的值; + *

+ * + * 仅当数据类型 {@link #getType()} 为“字节类型”或“字节衍生类型”时有效; + *

+ * + * 无效类型将引发 {@link IllegalStateException} 异常; + * + * @return + */ + public byte[] bytesValue() { + if (isNil()) { + return null; + } + if (type.isBytes()) { + return toBytesArray(); + } + throw new IllegalStateException(String.format("Type [%s] cannot be convert to bytes!", type)); + } + + private byte[] toBytesArray() { + return value.toBytes(); + } + + public HashDigest hashDigestValue() { + if (isNil()) { + return null; + } + if (DataType.HASH_DIGEST == type) { + return toHashDegist(); + } + throw new IllegalStateException(String.format("Type [%s] cannot be convert to hash digest!", type)); + } + + private HashDigest toHashDegist() { + return new HashDigest(toBytesArray()); + } + + public PubKey pubKeyValue() { + if (isNil()) { + return null; + } + if (DataType.PUB_KEY == type) { + return toPubKey(); + } + throw new IllegalStateException(String.format("Type [%s] cannot be convert to pub key!", type)); + } + + private PubKey toPubKey() { + return new PubKey(toBytesArray()); + } + + public SignatureDigest signatureDigestValue() { + if (isNil()) { + return null; + } + if (DataType.SIGNATURE_DIGEST == type) { + return toSignatureDigest(); + } + throw new IllegalStateException(String.format("Type [%s] cannot be convert to signature digest!", type)); + } + + private SignatureDigest toSignatureDigest() { + return new SignatureDigest(toBytesArray()); + } + + public static TypedValue wrap(BytesValue value) { + return new TypedValue(value); + } + + public static TypedValue fromType(DataType type, byte[] value) { + return new TypedValue(type, value); + } + + public static TypedValue fromBytes(byte[] value) { + return new TypedValue(DataType.BYTES, value); + } + + public static TypedValue fromBytes(Bytes value) { + return new TypedValue(DataType.BYTES, value); + } + + public static TypedValue fromImage(byte[] value) { + return new TypedValue(DataType.IMG, value); + } + + public static TypedValue fromImage(Bytes value) { + return new TypedValue(DataType.IMG, value); + } + + /** + * 以 UTF-8 编码从字符串转换为字节数组值; + * + * @param value + * @return + */ + public static TypedValue fromText(String value) { + return new TypedValue(DataType.TEXT, BytesUtils.toBytes(value)); + } + + public static TypedValue fromJSON(String value) { + return new TypedValue(DataType.JSON, BytesUtils.toBytes(value)); + } + + public static TypedValue fromXML(String value) { + return new TypedValue(DataType.XML, BytesUtils.toBytes(value)); + } + + public static TypedValue fromInt32(int value) { + return new TypedValue(DataType.INT32, BytesUtils.toBytes(value)); + } + + public static TypedValue fromInt64(long value) { + return new TypedValue(DataType.INT64, BytesUtils.toBytes(value)); + } + + public static TypedValue fromInt16(short value) { + return new TypedValue(DataType.INT16, BytesUtils.toBytes(value)); + } + + public static TypedValue fromInt8(byte value) { + return new TypedValue(DataType.INT8, BytesUtils.toBytes(value)); + } + + public static TypedValue fromTimestamp(long value) { + return new TypedValue(DataType.TIMESTAMP, BytesUtils.toBytes(value)); + } + + public static TypedValue fromBoolean(boolean value) { + return new TypedValue(DataType.BOOLEAN, BytesUtils.toBytes(value)); + } + + public static TypedValue fromPubKey(PubKey pubKey) { + return new TypedValue(DataType.PUB_KEY, pubKey.toBytes()); + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedValue_.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedValue_.java new file mode 100644 index 00000000..145344b5 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedValue_.java @@ -0,0 +1,472 @@ +//package com.jd.blockchain.ledger; +// +//import java.math.BigInteger; +//import java.util.Date; +// +//import com.jd.blockchain.binaryproto.PrimitiveType; +//import com.jd.blockchain.crypto.HashDigest; +//import com.jd.blockchain.crypto.PubKey; +//import com.jd.blockchain.crypto.SignatureDigest; +//import com.jd.blockchain.utils.Bytes; +//import com.jd.blockchain.utils.io.BytesUtils; +// +//public class TypedValue_ { +// +// private BytesValue bytesValue; +// +// public TypedValue_(BytesValue bytesValue) { +// this.bytesValue = bytesValue; +// } +// +// public DataType getType() { +// return bytesValue == null ? DataType.NIL : bytesValue.getType(); +// } +// +// public Object getValue() { +// if (isNil()) { +// return null; +// } +// switch (bytesValue.getType()) { +// case BOOLEAN: +// return toBoolean(); +// case INT8: +// return toInt8(); +// case INT16: +// return toInt16(); +// case INT32: +// return toInt32(); +// case INT64: +// return toInt64(); +// case BIG_INT: +// return toBigInteger(); +// case TIMESTAMP: +// return toDatetime(); +// case TEXT: +// case JSON: +// case XML: +// return toText(); +// +// case BYTES: +// case VIDEO: +// case IMG: +// case LOCATION: +// case ENCRYPTED_DATA: +// return toBytesArray(); +// +// case HASH_DIGEST: +// return toHashDegist(); +// case PUB_KEY: +// return toPubKey(); +// case SIGNATURE_DIGEST: +// return toSignatureDigest(); +// +// case DATA_CONTRACT: +// return toBytesArray(); +// default: +// throw new IllegalStateException(String.format("Type [%s] has not be supported!", bytesValue.getType())); +// } +// } +// +// /** +// * 是否为空值; +// *

+// * +// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#NIL} 时返回 true,其它情况返回 false; +// *

+// * +// * @return +// */ +// public boolean isNil() { +// return bytesValue == null || DataType.NIL == bytesValue.getType(); +// } +// +// /** +// * 返回 8 位整数值; +// *

+// * +// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT8} 有效; +// *

+// * +// * 无效类型将引发 {@link IllegalStateException} 异常; +// * +// * @return +// */ +// public byte tinyValue() { +// if (isNil()) { +// return DataType.INT8_DEFAULT_VALUE; +// } +// if (DataType.INT8 == getType()) { +// return toInt8(); +// } +// throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int8!", bytesValue.getType())); +// } +// +// private byte toInt8() { +// return bytesValue.getValue().toBytes()[0]; +// } +// +// /** +// * 返回 16 位整数值; +// *

+// * +// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT16} 有效; +// *

+// * +// * 无效类型将引发 {@link IllegalStateException} 异常; +// * +// * @return +// */ +// public short shortValue() { +// if (isNil()) { +// return DataType.INT16_DEFAULT_VALUE; +// } +// if (DataType.INT16 == getType()) { +// return toInt16(); +// } +// throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int16!", bytesValue.getType())); +// } +// +// private short toInt16() { +// return BytesUtils.toShort(bytesValue.getValue().toBytes(), 0); +// } +// +// /** +// * 返回 32 位整数值; +// *

+// * +// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT32} 有效; +// *

+// * +// * 无效类型将引发 {@link IllegalStateException} 异常; +// * +// * @return +// */ +// public int intValue() { +// if (isNil()) { +// return DataType.INT32_DEFAULT_VALUE; +// } +// if (DataType.INT32 == getType()) { +// return toInt32(); +// } +// throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int32!", bytesValue.getType())); +// } +// +// private int toInt32() { +// return BytesUtils.toInt(bytesValue.getValue().toBytes(), 0); +// } +// +// /** +// * 返回 64 位整数值; +// *

+// * +// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT64} 有效; +// *

+// * +// * 无效类型将引发 {@link IllegalStateException} 异常; +// * +// * @return +// */ +// public long longValue() { +// if (isNil()) { +// return DataType.INT64_DEFAULT_VALUE; +// } +// if (DataType.INT64 == bytesValue.getType()) { +// return toInt64(); +// } +// throw new IllegalStateException(String.format("Type [%s] cannot be convert to Int64!", bytesValue.getType())); +// +// } +// +// private long toInt64() { +// return BytesUtils.toLong(bytesValue.getValue().toBytes(), 0); +// } +// +// /** +// * 返回大整数值; +// *

+// * +// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#BIG_INT} 有效; +// *

+// * +// * 无效类型将引发 {@link IllegalStateException} 异常; +// * +// * @return +// */ +// public BigInteger bigIntValue() { +// if (isNil()) { +// return null; +// } +// if (DataType.BIG_INT == bytesValue.getType()) { +// return toBigInteger(); +// } +// throw new IllegalStateException( +// String.format("Type [%s] cannot be convert to BigInteger!", bytesValue.getType())); +// } +// +// private BigInteger toBigInteger() { +// return new BigInteger(bytesValue.getValue().toBytes()); +// } +// +// /** +// * 返回布尔值; +// *

+// * +// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#BIG_INT} 有效; +// *

+// * +// * 无效类型将引发 {@link IllegalStateException} 异常; +// * +// * @return +// */ +// public boolean boolValue() { +// if (isNil()) { +// return DataType.BOOLEAN_DEFAULT_VALUE; +// } +// if (DataType.BOOLEAN == bytesValue.getType()) { +// return toBoolean(); +// } +// throw new IllegalStateException(String.format("Type [%s] cannot be convert to boolean!", bytesValue.getType())); +// } +// +// private boolean toBoolean() { +// return BytesUtils.toBoolean(bytesValue.getValue().toBytes()[0]); +// } +// +// /** +// * 返回日期时间值; +// *

+// * +// * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TIMESTAMP} 有效; +// *

+// * +// * 无效类型将引发 {@link IllegalStateException} 异常; +// * +// * @return +// */ +// public Date datetimeValue() { +// if (isNil()) { +// return null; +// } +// if (DataType.TIMESTAMP == bytesValue.getType()) { +// return toDatetime(); +// } +// throw new IllegalStateException( +// String.format("Type [%s] cannot be convert to datetime!", bytesValue.getType())); +// } +// +// private Date toDatetime() { +// long ts = BytesUtils.toLong(bytesValue.getValue().toBytes()); +// return new Date(ts); +// } +// +// /** +// * 返回文本值; +// *

+// * +// * 仅当数据类型 {@link #getType()} 为“文本类型”或“文本衍生类型”时有效; +// *

+// * +// * 无效类型将引发 {@link IllegalStateException} 异常; +// * +// * @return +// */ +// public String stringValue() { +// if (isNil()) { +// return null; +// } +// DataType type = bytesValue.getType(); +// if (type.isText()) { +// return toText(); +// } +// throw new IllegalStateException(String.format("Type [%s] cannot be convert to text!", type)); +// } +// +// private String toText() { +// return bytesValue.getValue().toUTF8String(); +// } +// +// /** +// * 返回字节数组的值; +// *

+// * +// * 仅当数据类型 {@link #getType()} 为“字节类型”或“字节衍生类型”时有效; +// *

+// * +// * 无效类型将引发 {@link IllegalStateException} 异常; +// * +// * @return +// */ +// public byte[] bytesValue() { +// if (isNil()) { +// return null; +// } +// DataType type = bytesValue.getType(); +// if (type.isBytes()) { +// return toBytesArray(); +// } +// throw new IllegalStateException(String.format("Type [%s] cannot be convert to bytes!", type)); +// } +// +// private byte[] toBytesArray() { +// return bytesValue.getValue().toBytes(); +// } +// +// public HashDigest hashDigestValue() { +// if (isNil()) { +// return null; +// } +// if (DataType.HASH_DIGEST == bytesValue.getType()) { +// return toHashDegist(); +// } +// throw new IllegalStateException( +// String.format("Type [%s] cannot be convert to hash digest!", bytesValue.getType())); +// } +// +// private HashDigest toHashDegist() { +// return new HashDigest(toBytesArray()); +// } +// +// public PubKey pubKeyValue() { +// if (isNil()) { +// return null; +// } +// if (DataType.PUB_KEY == bytesValue.getType()) { +// return toPubKey(); +// } +// throw new IllegalStateException(String.format("Type [%s] cannot be convert to pub key!", bytesValue.getType())); +// } +// +// private PubKey toPubKey() { +// return new PubKey(toBytesArray()); +// } +// +// public SignatureDigest signatureDigestValue() { +// if (isNil()) { +// return null; +// } +// if (DataType.SIGNATURE_DIGEST == bytesValue.getType()) { +// return toSignatureDigest(); +// } +// throw new IllegalStateException( +// String.format("Type [%s] cannot be convert to signature digest!", bytesValue.getType())); +// } +// +// private SignatureDigest toSignatureDigest() { +// return new SignatureDigest(toBytesArray()); +// } +// +// public BytesValue convertToBytesValue() { +// return bytesValue == null ? TypedBytesValue.NIL : bytesValue; +// } +// +// public static TypedBytesValue fromText(String key, String value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromText(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromBoolean(String key, boolean value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromBoolean(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromInt8(String key, byte value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromInt8(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromInt16(String key, short value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromInt16(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromInt32(String key, int value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromInt32(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromInt64(String key, long value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromInt64(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromBytes(String key, byte[] value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromBytes(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromTimestamp(String key, long value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromTimestamp(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromJSON(String key, String value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromJSON(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromXML(String key, String value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromXML(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromImage(String key, byte[] value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromImage(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromText(Bytes key, String value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromText(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromBoolean(Bytes key, boolean value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromBoolean(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromInt8(Bytes key, byte value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromInt8(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromInt16(Bytes key, short value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromInt16(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromInt32(Bytes key, int value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromInt32(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromInt64(Bytes key, long value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromInt64(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromBytes(Bytes key, byte[] value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromBytes(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromTimestamp(Bytes key, long value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromTimestamp(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromJSON(Bytes key, String value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromJSON(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromXML(Bytes key, String value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromXML(value); +// return new TypedBytesValue(bytesValue); +// } +// +// public static TypedBytesValue fromImage(Bytes key, byte[] value, long version) { +// BytesValue bytesValue = TypedBytesValue.fromImage(value); +// return new TypedBytesValue(bytesValue); +// } +// +//} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAccountHeader.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAccountHeader.java new file mode 100644 index 00000000..8fc0e7a5 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAccountHeader.java @@ -0,0 +1,12 @@ +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.consts.DataCodes; +import com.jd.blockchain.crypto.PubKey; + +@DataContract(code= DataCodes.USER_ACCOUNT_HEADER) +public interface UserAccountHeader extends BlockchainIdentity { + + PubKey getDataPubKey(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfo.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfo.java index 48759b9f..c7b14d1a 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfo.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfo.java @@ -2,11 +2,8 @@ package com.jd.blockchain.ledger; import com.jd.blockchain.binaryproto.DataContract; import com.jd.blockchain.consts.DataCodes; -import com.jd.blockchain.crypto.PubKey; -@DataContract(code= DataCodes.USER) -public interface UserInfo extends AccountHeader { - - PubKey getDataPubKey(); - +@DataContract(code = DataCodes.USER_INFO) +public interface UserInfo extends UserAccountHeader { + } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/AbstractBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/AbstractBytesValueResolver.java index 995d5522..d6ee0b98 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/AbstractBytesValueResolver.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/AbstractBytesValueResolver.java @@ -47,7 +47,7 @@ public abstract class AbstractBytesValueResolver implements BytesValueResolver { if (!isSupport(dataType)) { throw new IllegalStateException(String.format("Un-support encode DataType[%s] Object !!!", dataType.name())); } - return decode(value.getValue()); + return decode(value.getBytes()); } protected abstract Object decode(Bytes value); diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BooleanToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BooleanToBytesValueResolver.java index 0664fdb9..69285395 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BooleanToBytesValueResolver.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BooleanToBytesValueResolver.java @@ -1,6 +1,6 @@ package com.jd.blockchain.ledger.resolver; -import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.DataType; import com.jd.blockchain.utils.Bytes; @@ -21,7 +21,7 @@ public class BooleanToBytesValueResolver extends AbstractBytesValueResolver { if (!isSupport(type)) { throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); } - return BytesData.fromBoolean((boolean) value); + return TypedValue.fromBoolean((boolean) value); } @Override diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesToBytesValueResolver.java index f4871515..fe71eee7 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesToBytesValueResolver.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesToBytesValueResolver.java @@ -1,6 +1,6 @@ package com.jd.blockchain.ledger.resolver; -import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.DataType; import com.jd.blockchain.utils.Bytes; @@ -21,9 +21,9 @@ public class BytesToBytesValueResolver extends AbstractBytesValueResolver { throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); } if (type.equals(byte[].class)) { - return BytesData.fromBytes((byte[]) value); + return TypedValue.fromBytes((byte[]) value); } - return BytesData.fromBytes((Bytes) value); + return TypedValue.fromBytes((Bytes) value); } @Override diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/IntegerToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/IntegerToBytesValueResolver.java index a8400f02..075d1f76 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/IntegerToBytesValueResolver.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/IntegerToBytesValueResolver.java @@ -1,6 +1,6 @@ package com.jd.blockchain.ledger.resolver; -import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.DataType; import com.jd.blockchain.utils.Bytes; @@ -21,7 +21,7 @@ public class IntegerToBytesValueResolver extends AbstractBytesValueResolver { if (!isSupport(type)) { throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); } - return BytesData.fromInt32((int) value); + return TypedValue.fromInt32((int) value); } @Override diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/LongToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/LongToBytesValueResolver.java index fa11bcf4..ce6dbaf9 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/LongToBytesValueResolver.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/LongToBytesValueResolver.java @@ -1,6 +1,6 @@ package com.jd.blockchain.ledger.resolver; -import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.DataType; import com.jd.blockchain.utils.Bytes; @@ -21,7 +21,7 @@ public class LongToBytesValueResolver extends AbstractBytesValueResolver { if (!isSupport(type)) { throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); } - return BytesData.fromInt64((long)value); + return TypedValue.fromInt64((long)value); } @Override diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/ShortToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/ShortToBytesValueResolver.java index b8eea38c..ddbed5fb 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/ShortToBytesValueResolver.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/ShortToBytesValueResolver.java @@ -1,6 +1,6 @@ package com.jd.blockchain.ledger.resolver; -import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.DataType; import com.jd.blockchain.utils.Bytes; @@ -21,7 +21,7 @@ public class ShortToBytesValueResolver extends AbstractBytesValueResolver { if (!isSupport(type)) { throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); } - return BytesData.fromInt16((short)value); + return TypedValue.fromInt16((short)value); } @Override diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/StringToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/StringToBytesValueResolver.java index dca8e5d1..0f08442e 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/StringToBytesValueResolver.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/StringToBytesValueResolver.java @@ -1,6 +1,6 @@ package com.jd.blockchain.ledger.resolver; -import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.DataType; import com.jd.blockchain.utils.Bytes; @@ -26,10 +26,10 @@ public class StringToBytesValueResolver extends AbstractBytesValueResolver { // 类型判断 String valString = (String)value; if (JSONSerializeUtils.isJSON(valString)) { - return BytesData.fromJSON(valString); + return TypedValue.fromJSON(valString); } // 暂不处理XML格式 - return BytesData.fromText(valString); + return TypedValue.fromText(valString); } @Override diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java index 9710b50d..f63a7f2a 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java @@ -3,9 +3,9 @@ package com.jd.blockchain.transaction; import org.springframework.cglib.core.Block; import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.AccountHeader; +import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.ContractInfo; -import com.jd.blockchain.ledger.KVDataEntry; +import com.jd.blockchain.ledger.TypedKVEntry; import com.jd.blockchain.ledger.KVInfoVO; import com.jd.blockchain.ledger.LedgerAdminInfo; import com.jd.blockchain.ledger.LedgerBlock; @@ -250,7 +250,7 @@ public interface BlockchainQueryService { * @param address * @return */ - AccountHeader getDataAccount(HashDigest ledgerHash, String address); + BlockchainIdentity getDataAccount(HashDigest ledgerHash, String address); /** * 返回数据账户中指定的键的最新值;
@@ -264,9 +264,9 @@ public interface BlockchainQueryService { * @param keys * @return */ - KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys); + TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys); - KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO); + TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO); /** * 返回指定数据账户中KV数据的总数;
@@ -287,7 +287,7 @@ public interface BlockchainQueryService { * 如果参数值为 -1,则返回全部的记录;
* @return */ - KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count); + TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count); /** * 返回合约账户信息; @@ -306,7 +306,7 @@ public interface BlockchainQueryService { * @param count * @return */ - AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count); + BlockchainIdentity[] getUsers(HashDigest ledgerHash, int fromIndex, int count); /** * get data accounts by ledgerHash and its range; @@ -316,7 +316,7 @@ public interface BlockchainQueryService { * @param count * @return */ - AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count); + BlockchainIdentity[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count); /** * get contract accounts by ledgerHash and its range; @@ -326,5 +326,5 @@ public interface BlockchainQueryService { * @param count * @return */ - AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count); + BlockchainIdentity[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count); } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java index b2ccef13..cec540c9 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java @@ -1,7 +1,7 @@ package com.jd.blockchain.transaction; import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.utils.Bytes; @@ -26,14 +26,14 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe @Override public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { - BytesValue bytesValue = BytesData.fromBytes(value); + BytesValue bytesValue = TypedValue.fromBytes(value); operation.set(key, bytesValue, expVersion); return this; } @Override public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { - BytesValue bytesValue = BytesData.fromImage(value); + BytesValue bytesValue = TypedValue.fromImage(value); operation.set(key, bytesValue, expVersion); return this; } @@ -45,42 +45,42 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe @Override public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { - BytesValue bytesValue = BytesData.fromText(value); + BytesValue bytesValue = TypedValue.fromText(value); operation.set(key, bytesValue, expVersion); return this; } @Override public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { - BytesValue bytesValue = BytesData.fromBytes(value); + BytesValue bytesValue = TypedValue.fromBytes(value); operation.set(key, bytesValue, expVersion); return this; } @Override public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { - BytesValue bytesValue = BytesData.fromInt64(value); + BytesValue bytesValue = TypedValue.fromInt64(value); operation.set(key, bytesValue, expVersion); return this; } @Override public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { - BytesValue bytesValue = BytesData.fromJSON(value); + BytesValue bytesValue = TypedValue.fromJSON(value); operation.set(key, bytesValue, expVersion); return this; } @Override public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { - BytesValue bytesValue = BytesData.fromXML(value); + BytesValue bytesValue = TypedValue.fromXML(value); operation.set(key, bytesValue, expVersion); return this; } @Override public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { - BytesValue bytesValue = BytesData.fromTimestamp(value); + BytesValue bytesValue = TypedValue.fromTimestamp(value); operation.set(key, bytesValue, expVersion); return this; } diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesToBytesValueResolverTest.java index 3635743c..2dfa0dbd 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesToBytesValueResolverTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesToBytesValueResolverTest.java @@ -26,7 +26,7 @@ public class BytesToBytesValueResolverTest { assertEquals(bytesValue.getType(), DataType.BYTES); - assertEquals(bytesObj, bytesValue.getValue()); + assertEquals(bytesObj, bytesValue.getBytes()); Bytes resolveBytesObj = (Bytes)resolver.decode(bytesValue); diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesValueEncodingTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesValueEncodingTest.java index e5b624c9..f572a831 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesValueEncodingTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesValueEncodingTest.java @@ -28,9 +28,9 @@ public class BytesValueEncodingTest { BytesValue longBytesVal2 = BytesValueEncoding.encodeSingle(longVal, long.class); BytesValue longBytesVal3 = BytesValueEncoding.encodeSingle(longVal, Long.class); - assertEquals(longBytesVal1.getValue(), longBytesVal2.getValue()); + assertEquals(longBytesVal1.getBytes(), longBytesVal2.getBytes()); assertEquals(longBytesVal1.getType(), longBytesVal2.getType()); - assertEquals(longBytesVal2.getValue(), longBytesVal3.getValue()); + assertEquals(longBytesVal2.getBytes(), longBytesVal3.getBytes()); assertEquals(longBytesVal2.getType(), longBytesVal3.getType()); long resolveLongVal1 = (long)BytesValueEncoding.decode(longBytesVal1); diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractEventSendOpTemplateTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractEventSendOpTemplateTest.java index d010ae6f..506d86d4 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractEventSendOpTemplateTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractEventSendOpTemplateTest.java @@ -16,7 +16,7 @@ import org.junit.Test; import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.BytesDataList; import com.jd.blockchain.ledger.BytesValueList; import com.jd.blockchain.ledger.ContractEventSendOperation; @@ -41,7 +41,7 @@ public class ContractEventSendOpTemplateTest { DataContractRegistry.register(ContractEventSendOperation.class); DataContractRegistry.register(Operation.class); String contractAddress = "zhangsan-address", event = "zhangsan-event"; - BytesValueList args = new BytesDataList(BytesData.fromText("zhangsan-args")); + BytesValueList args = new BytesDataList(TypedValue.fromText("zhangsan-args")); data = new ContractEventSendOpTemplate(Bytes.fromString(contractAddress), event, args); } diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DataAccountKVSetOpTemplateTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DataAccountKVSetOpTemplateTest.java index d8b33048..6c1d4f57 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DataAccountKVSetOpTemplateTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DataAccountKVSetOpTemplateTest.java @@ -16,7 +16,7 @@ import org.junit.Test; import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; @@ -41,11 +41,11 @@ public class DataAccountKVSetOpTemplateTest { String accountAddress = "zhangsandhakhdkah"; data = new DataAccountKVSetOpTemplate(Bytes.fromString(accountAddress)); KVData kvData1 = - new KVData("test1", BytesData.fromText("zhangsan"), 9999L); + new KVData("test1", TypedValue.fromText("zhangsan"), 9999L); KVData kvData2 = - new KVData("test2", BytesData.fromText("lisi"), 9990L); + new KVData("test2", TypedValue.fromText("lisi"), 9990L); KVData kvData3 = - new KVData("test3", BytesData.fromText("wangwu"), 1990L); + new KVData("test3", TypedValue.fromText("wangwu"), 1990L); data.set(kvData1); data.set(kvData2); data.set(kvData3); @@ -63,7 +63,7 @@ public class DataAccountKVSetOpTemplateTest { assertEquals(dataKv.length, resolvedKv.length); for (int i = 0; i < dataKv.length; i++) { assertEquals(dataKv[i].getKey(), resolvedKv[i].getKey()); - assertArrayEquals(dataKv[i].getValue().getValue().toBytes(), resolvedKv[i].getValue().getValue().toBytes()); + assertArrayEquals(dataKv[i].getValue().getBytes().toBytes(), resolvedKv[i].getValue().getBytes().toBytes()); assertEquals(dataKv[i].getValue().getType().CODE, resolvedKv[i].getValue().getType().CODE); assertEquals(dataKv[i].getExpectedVersion(), resolvedKv[i].getExpectedVersion()); diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/IntegerToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/IntegerToBytesValueResolverTest.java index 8e39aa85..dd9d4632 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/IntegerToBytesValueResolverTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/IntegerToBytesValueResolverTest.java @@ -22,13 +22,13 @@ public class IntegerToBytesValueResolverTest { BytesValue intBytesValue2 = resolver.encode(intVal, Integer.class); - assertEquals(intBytesValue.getValue(), intBytesValue1.getValue()); + assertEquals(intBytesValue.getBytes(), intBytesValue1.getBytes()); - assertEquals(intBytesValue.getValue(), intBytesValue2.getValue()); + assertEquals(intBytesValue.getBytes(), intBytesValue2.getBytes()); Bytes intBytes = Bytes.fromInt(intVal); - assertEquals(intBytes, intBytesValue.getValue()); + assertEquals(intBytes, intBytesValue.getBytes()); assertEquals(intBytesValue.getType(), DataType.INT32); diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/KVDataTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/KVDataTest.java index d1a6fcb9..3d54f16c 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/KVDataTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/KVDataTest.java @@ -16,7 +16,7 @@ import org.junit.Test; import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.TypedValue; import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; import com.jd.blockchain.transaction.KVData; @@ -38,7 +38,7 @@ public class KVDataTest { byte[] value = "test-value".getBytes(); long expectedVersion = 9999L; - kvData = new KVData(key, BytesData.fromBytes(value), expectedVersion); + kvData = new KVData(key, TypedValue.fromBytes(value), expectedVersion); } @Test @@ -48,7 +48,7 @@ public class KVDataTest { System.out.println("------Assert start ------"); assertEquals(resolvedKvData.getKey(), kvData.getKey()); assertEquals(resolvedKvData.getExpectedVersion(), kvData.getExpectedVersion()); - assertArrayEquals(resolvedKvData.getValue().getValue().toBytes(), kvData.getValue().getValue().toBytes()); + assertArrayEquals(resolvedKvData.getValue().getBytes().toBytes(), kvData.getValue().getBytes().toBytes()); System.out.println("------Assert OK ------"); } } \ No newline at end of file diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/LongToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/LongToBytesValueResolverTest.java index 899a6415..b4d20b4c 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/LongToBytesValueResolverTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/LongToBytesValueResolverTest.java @@ -23,13 +23,13 @@ public class LongToBytesValueResolverTest { BytesValue longBytesValue2 = resolver.encode(longVal, Long.class); - assertEquals(longBytesValue.getValue(), longBytesValue1.getValue()); + assertEquals(longBytesValue.getBytes(), longBytesValue1.getBytes()); - assertEquals(longBytesValue.getValue(), longBytesValue2.getValue()); + assertEquals(longBytesValue.getBytes(), longBytesValue2.getBytes()); Bytes longBytes = Bytes.fromLong(longVal); - assertEquals(longBytes, longBytesValue.getValue()); + assertEquals(longBytes, longBytesValue.getBytes()); assertEquals(longBytesValue.getType(), DataType.INT64); diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ShortToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ShortToBytesValueResolverTest.java index b35cedd7..2e8e46be 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ShortToBytesValueResolverTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ShortToBytesValueResolverTest.java @@ -21,7 +21,7 @@ public class ShortToBytesValueResolverTest { Bytes shortBytes = new Bytes(BytesUtils.toBytes(shortVal)); - assertEquals(shortBytes, shortBytesValue.getValue()); + assertEquals(shortBytes, shortBytesValue.getBytes()); assertEquals(shortBytesValue.getType(), DataType.INT16); diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/StringToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/StringToBytesValueResolverTest.java index 17dd0c04..544f06bb 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/StringToBytesValueResolverTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/StringToBytesValueResolverTest.java @@ -20,7 +20,7 @@ public class StringToBytesValueResolverTest { BytesValue textBytesValue = resolver.encode(textVal); - assertEquals(Bytes.fromString(textVal), textBytesValue.getValue()); + assertEquals(Bytes.fromString(textVal), textBytesValue.getBytes()); assertEquals(textBytesValue.getType(), DataType.TEXT); @@ -43,7 +43,7 @@ public class StringToBytesValueResolverTest { Person person = new Person("zhangsan", 80); String personJson = JSON.toJSONString(person); BytesValue textBytesValue = resolver.encode(personJson); - assertEquals(Bytes.fromString(personJson), textBytesValue.getValue()); + assertEquals(Bytes.fromString(personJson), textBytesValue.getBytes()); assertEquals(textBytesValue.getType(), DataType.JSON); } diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java index 0404ee38..c8d8c313 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java @@ -77,8 +77,8 @@ public class TxContentBlobTest { for (int j = 0; j < dataKv.length; j++) { assertEquals(dataKv[i].getKey(), resolvedKv[i].getKey()); assertEquals(dataKv[i].getExpectedVersion(), resolvedKv[i].getExpectedVersion()); - assertArrayEquals(dataKv[i].getValue().getValue().toBytes(), - resolvedKv[i].getValue().getValue().toBytes()); + assertArrayEquals(dataKv[i].getValue().getBytes().toBytes(), + resolvedKv[i].getValue().getBytes().toBytes()); } } } @@ -108,8 +108,8 @@ public class TxContentBlobTest { for (int j = 0; j < dataKv.length; j++) { assertEquals(dataKv[i].getKey(), resolvedKv[i].getKey()); assertEquals(dataKv[i].getExpectedVersion(), resolvedKv[i].getExpectedVersion()); - assertArrayEquals(dataKv[i].getValue().getValue().toBytes(), - resolvedKv[i].getValue().getValue().toBytes()); + assertArrayEquals(dataKv[i].getValue().getBytes().toBytes(), + resolvedKv[i].getValue().getBytes().toBytes()); } } } diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java b/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java index ad5f3aeb..2fd0cd80 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java @@ -3,7 +3,6 @@ package com.jd.blockchain.peer.web; import java.util.ArrayList; import java.util.List; -import com.jd.blockchain.ledger.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -14,6 +13,22 @@ import org.springframework.web.bind.annotation.RestController; import com.jd.blockchain.contract.ContractException; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.ContractInfo; +import com.jd.blockchain.ledger.KVDataVO; +import com.jd.blockchain.ledger.KVInfoVO; +import com.jd.blockchain.ledger.LedgerAdminInfo; +import com.jd.blockchain.ledger.LedgerBlock; +import com.jd.blockchain.ledger.LedgerInfo; +import com.jd.blockchain.ledger.LedgerMetadata; +import com.jd.blockchain.ledger.LedgerTransaction; +import com.jd.blockchain.ledger.ParticipantNode; +import com.jd.blockchain.ledger.TransactionState; +import com.jd.blockchain.ledger.TypedKVData; +import com.jd.blockchain.ledger.TypedKVEntry; +import com.jd.blockchain.ledger.TypedValue; +import com.jd.blockchain.ledger.UserInfo; import com.jd.blockchain.ledger.core.ContractAccountQuery; import com.jd.blockchain.ledger.core.DataAccount; import com.jd.blockchain.ledger.core.DataAccountQuery; @@ -23,7 +38,10 @@ import com.jd.blockchain.ledger.core.ParticipantCertData; import com.jd.blockchain.ledger.core.TransactionQuery; import com.jd.blockchain.ledger.core.UserAccountQuery; import com.jd.blockchain.transaction.BlockchainQueryService; +import com.jd.blockchain.utils.ArrayUtils; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; +import com.jd.blockchain.utils.DataIterator; import com.jd.blockchain.utils.QueryUtil; @RestController @@ -72,7 +90,7 @@ public class LedgerQueryController implements BlockchainQueryService { } return null; } - + @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/admininfo") @Override public LedgerAdminInfo getLedgerAdminInfo(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { @@ -326,18 +344,18 @@ public class LedgerQueryController implements BlockchainQueryService { @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}") @Override - public AccountHeader getDataAccount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, + public BlockchainIdentity getDataAccount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "address") String address) { LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); - return dataAccountSet.getAccount(Bytes.fromBase58(address)); + return dataAccountSet.getAccount(Bytes.fromBase58(address)).getID(); } @RequestMapping(method = { RequestMethod.GET, RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries") @Override - public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, + public TypedKVEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "address") String address, @RequestParam("keys") String... keys) { if (keys == null || keys.length == 0) { return null; @@ -347,15 +365,15 @@ public class LedgerQueryController implements BlockchainQueryService { DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); - KVDataEntry[] entries = new KVDataEntry[keys.length]; + TypedKVEntry[] entries = new TypedKVEntry[keys.length]; long ver; for (int i = 0; i < entries.length; i++) { - ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); + ver = dataAccount.getDataset().getVersion(keys[i]); if (ver < 0) { - entries[i] = new KVDataObject(keys[i], -1, null); + entries[i] = new TypedKVData(keys[i], -1, null); } else { - BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); - entries[i] = new KVDataObject(keys[i], ver, value); + BytesValue value = dataAccount.getDataset().getValue(keys[i], ver); + entries[i] = new TypedKVData(keys[i], ver, value); } } @@ -365,7 +383,7 @@ public class LedgerQueryController implements BlockchainQueryService { @RequestMapping(method = { RequestMethod.GET, RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version") @Override - public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, + public TypedKVEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "address") String address, @RequestBody KVInfoVO kvInfoVO) { // parse kvInfoVO; List keyList = new ArrayList<>(); @@ -396,21 +414,21 @@ public class LedgerQueryController implements BlockchainQueryService { DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); - KVDataEntry[] entries = new KVDataEntry[keys.length]; + TypedKVEntry[] entries = new TypedKVEntry[keys.length]; long ver = -1; for (int i = 0; i < entries.length; i++) { // ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); ver = versions[i]; if (ver < 0) { - entries[i] = new KVDataObject(keys[i], -1, null); + entries[i] = new TypedKVData(keys[i], -1, null); } else { - if (dataAccount.getDataEntriesTotalCount() == 0 - || dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null) { + if (dataAccount.getDataset().getDataCount() == 0 + || dataAccount.getDataset().getValue(keys[i], ver) == null) { // is the address is not exist; the result is null; - entries[i] = new KVDataObject(keys[i], -1, null); + entries[i] = new TypedKVData(keys[i], -1, null); } else { - BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); - entries[i] = new KVDataObject(keys[i], ver, value); + BytesValue value = dataAccount.getDataset().getValue(keys[i], ver); + entries[i] = new TypedKVData(keys[i], ver, value); } } } @@ -421,7 +439,7 @@ public class LedgerQueryController implements BlockchainQueryService { @RequestMapping(method = { RequestMethod.GET, RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries") @Override - public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, + public TypedKVEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "address") String address, @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { @@ -431,27 +449,33 @@ public class LedgerQueryController implements BlockchainQueryService { DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); - int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataEntriesTotalCount()); - return dataAccount.getDataEntries(pages[0], pages[1]); +// int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataset().getDataCount()); +// return dataAccount.getDataEntries(pages[0], pages[1]); + + DataIterator iterator = dataAccount.getDataset().iterator(); + iterator.skip(fromIndex); + DataEntry[] dataEntries = iterator.next(count); + TypedKVEntry[] typedKVEntries = ArrayUtils.castTo(dataEntries, TypedKVEntry.class, + e -> e == null ? null : new TypedKVData(e.getKey(), e.getVersion(), e.getValue())); + return typedKVEntries; } @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries/count") @Override public long getDataEntriesTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "address") String address) { - LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); - return dataAccount.getDataEntriesTotalCount(); + return dataAccount.getDataset().getDataCount(); } @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}") @Override public ContractInfo getContract(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, - @PathVariable(name = "address") String address) { + @PathVariable(name = "address") String address) { LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); @@ -468,7 +492,7 @@ public class LedgerQueryController implements BlockchainQueryService { */ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users") @Override - public AccountHeader[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, + public BlockchainIdentity[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { LedgerQuery ledger = ledgerService.getLedger(ledgerHash); @@ -488,7 +512,7 @@ public class LedgerQueryController implements BlockchainQueryService { */ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts") @Override - public AccountHeader[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, + public BlockchainIdentity[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { LedgerQuery ledger = ledgerService.getLedger(ledgerHash); @@ -500,7 +524,7 @@ public class LedgerQueryController implements BlockchainQueryService { @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts") @Override - public AccountHeader[] getContractAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, + public BlockchainIdentity[] getContractAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { LedgerQuery ledger = ledgerService.getLedger(ledgerHash); diff --git a/source/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..4e7534a4 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java @@ -39,14 +39,14 @@ import com.jd.blockchain.utils.io.BytesUtils; public class ClientResolveUtil { - public static KVDataEntry[] read(KVDataEntry[] kvDataEntries) { + public static TypedKVEntry[] read(TypedKVEntry[] kvDataEntries) { if (kvDataEntries == null || kvDataEntries.length == 0) { return kvDataEntries; } - KVDataEntry[] resolveKvDataEntries = new KVDataEntry[kvDataEntries.length]; + TypedKVEntry[] resolveKvDataEntries = new TypedKVEntry[kvDataEntries.length]; // kvDataEntries是代理对象,需要处理 for (int i = 0; i < kvDataEntries.length; i++) { - KVDataEntry kvDataEntry = kvDataEntries[i]; + TypedKVEntry kvDataEntry = kvDataEntries[i]; String key = kvDataEntry.getKey(); long version = kvDataEntry.getVersion(); DataType dataType = kvDataEntry.getType(); @@ -108,7 +108,7 @@ public class ClientResolveUtil { public static Object readValueByBytesValue(BytesValue bytesValue) { DataType dataType = bytesValue.getType(); - Bytes saveVal = bytesValue.getValue(); + Bytes saveVal = bytesValue.getBytes(); Object showVal; switch (dataType) { case BYTES: @@ -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 = TypedValue.fromType(dataType, Base58Utils.decode(realValBase58)); KVData kvData = new KVData(key, bytesValue, expectedVersion); kvOperation.set(kvData); } @@ -200,7 +200,7 @@ public class ClientResolveUtil { JSONObject pubKeyObj = currConsensusParticipant.getJSONObject("pubKey"); String pubKeyBase58 = pubKeyObj.getString("value"); // 生成ParticipantNode对象 - ParticipantCertData participantCertData = new ParticipantCertData(id, address, name, new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes())); + ParticipantCertData participantCertData = new ParticipantCertData(id, address, name, new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes()), null); participantNodes[i] = participantCertData; } ledgerInitSettingData.setConsensusParticipants(participantNodes); @@ -294,11 +294,12 @@ public class ClientResolveUtil { this.pubKey = participantNode.getPubKey(); } - public ParticipantCertData(int id, Bytes address, String name, PubKey pubKey) { + public ParticipantCertData(int id, Bytes address, String name, PubKey pubKey, ParticipantNodeState participantNodeState) { this.id = id; this.address = address; this.name = name; this.pubKey = pubKey; + this.participantNodeState = participantNodeState; } @@ -329,7 +330,7 @@ public class ClientResolveUtil { } - public static class KvData implements KVDataEntry { + public static class KvData implements TypedKVEntry { private String key; diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java index ff1c9176..9984cef5 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java @@ -1,9 +1,9 @@ package com.jd.blockchain.sdk.proxy; import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.AccountHeader; +import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.ContractInfo; -import com.jd.blockchain.ledger.KVDataEntry; +import com.jd.blockchain.ledger.TypedKVEntry; import com.jd.blockchain.ledger.KVInfoVO; import com.jd.blockchain.ledger.LedgerAdminInfo; import com.jd.blockchain.ledger.LedgerBlock; @@ -156,25 +156,25 @@ public abstract class BlockchainServiceProxy implements BlockchainService { } @Override - public AccountHeader getDataAccount(HashDigest ledgerHash, String address) { + public BlockchainIdentity getDataAccount(HashDigest ledgerHash, String address) { return getQueryService(ledgerHash).getDataAccount(ledgerHash, address); } @Override - public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) { - KVDataEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, keys); + public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) { + TypedKVEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, keys); return ClientResolveUtil.read(kvDataEntries); } @Override - public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) { - KVDataEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, kvInfoVO); + public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) { + TypedKVEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, kvInfoVO); return ClientResolveUtil.read(kvDataEntries); } @Override - public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) { - KVDataEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, fromIndex, count); + public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) { + TypedKVEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, fromIndex, count); return ClientResolveUtil.read(kvDataEntries); } @@ -189,17 +189,17 @@ public abstract class BlockchainServiceProxy implements BlockchainService { } @Override - public AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count) { + public BlockchainIdentity[] getUsers(HashDigest ledgerHash, int fromIndex, int count) { return getQueryService(ledgerHash).getUsers(ledgerHash, fromIndex, count); } @Override - public AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) { + public BlockchainIdentity[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) { return getQueryService(ledgerHash).getDataAccounts(ledgerHash, fromIndex, count); } @Override - public AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) { + public BlockchainIdentity[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) { return getQueryService(ledgerHash).getContractAccounts(ledgerHash, fromIndex, count); } } diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java index ccd5ceec..d13fa436 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java @@ -487,7 +487,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService */ @HttpAction(method=HttpMethod.GET, path="ledgers/{ledgerHash}/accounts/address/{address}") @Override - AccountHeader getDataAccount(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, + BlockchainIdentity getDataAccount(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, @PathParam(name="address") String address); /** @@ -504,13 +504,13 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService */ @HttpAction(method=HttpMethod.POST, path="ledgers/{ledgerHash}/accounts/{address}/entries") @Override - KVDataEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, + TypedKVEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, @PathParam(name="address") String address, @RequestParam(name="keys", array = true) String... keys); @HttpAction(method=HttpMethod.POST, path="ledgers/{ledgerHash}/accounts/{address}/entries-version") @Override - KVDataEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, + TypedKVEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, @PathParam(name="address") String address, @RequestBody KVInfoVO kvInfoVO); @@ -531,7 +531,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService */ @HttpAction(method = HttpMethod.POST, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries") @Override - KVDataEntry[] getDataEntries(@PathParam(name = "ledgerHash") HashDigest ledgerHash, + TypedKVEntry[] getDataEntries(@PathParam(name = "ledgerHash") HashDigest ledgerHash, @PathParam(name = "address") String address, @RequestParam(name = "fromIndex", required = false) int fromIndex, @RequestParam(name = "count", required = false) int count); @@ -569,7 +569,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService */ @HttpAction(method = HttpMethod.GET, path = "ledgers/{ledgerHash}/users") @Override - AccountHeader[] getUsers(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, + BlockchainIdentity[] getUsers(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, @RequestParam(name="fromIndex", required = false) int fromIndex, @RequestParam(name="count", required = false) int count); @@ -582,7 +582,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService */ @HttpAction(method = HttpMethod.GET, path = "ledgers/{ledgerHash}/accounts") @Override - AccountHeader[] getDataAccounts(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, + BlockchainIdentity[] getDataAccounts(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, @RequestParam(name="fromIndex", required = false) int fromIndex, @RequestParam(name="count", required = false) int count); @@ -595,7 +595,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService */ @HttpAction(method = HttpMethod.GET, path = "ledgers/{ledgerHash}/contracts") @Override - AccountHeader[] getContractAccounts(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, + BlockchainIdentity[] getContractAccounts(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, @RequestParam(name="fromIndex", required = false) int fromIndex, @RequestParam(name="count", required = false) int count); diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java index d662378d..1782d985 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java @@ -9,8 +9,8 @@ import com.jd.blockchain.contract.ContractException; import com.jd.blockchain.contract.EventProcessingAware; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.KVDataEntry; -import com.jd.blockchain.ledger.KVDataObject; +import com.jd.blockchain.ledger.TypedKVEntry; +import com.jd.blockchain.ledger.TypedKVData; import com.jd.blockchain.utils.Bytes; /** @@ -47,16 +47,16 @@ public class AssetContractImpl implements EventProcessingAware, AssetContract { } // 查询当前值; - KVDataEntry[] kvEntries = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS, KEY_TOTAL, + TypedKVEntry[] kvEntries = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS, KEY_TOTAL, assetHolderAddress); // 计算资产的发行总数; - KVDataObject currTotal = (KVDataObject) kvEntries[0]; + TypedKVData currTotal = (TypedKVData) kvEntries[0]; long newTotal = currTotal.longValue() + amount; eventContext.getLedger().dataAccount(ASSET_ADDRESS).setInt64(KEY_TOTAL, newTotal, currTotal.getVersion()); // 分配到持有者账户; - KVDataObject holderAmount = (KVDataObject) kvEntries[1]; + TypedKVData holderAmount = (TypedKVData) kvEntries[1]; long newHodlerAmount = holderAmount.longValue() + amount; eventContext.getLedger().dataAccount(ASSET_ADDRESS) .setInt64(assetHolderAddress, newHodlerAmount, holderAmount.getVersion()).setText("K2", "info2", -1) @@ -77,10 +77,10 @@ public class AssetContractImpl implements EventProcessingAware, AssetContract { checkSignerPermission(fromAddress); // 查询现有的余额; - KVDataEntry[] origBalances = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS, + TypedKVEntry[] origBalances = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS, fromAddress, toAddress); - KVDataEntry fromBalanceKV = origBalances[0]; - KVDataEntry toBalanceKV = origBalances[1]; + TypedKVEntry fromBalanceKV = origBalances[0]; + TypedKVEntry toBalanceKV = origBalances[1]; long fromBalance = fromBalanceKV.getVersion() == -1 ? 0 : (long) fromBalanceKV.getValue(); long toBalance = toBalanceKV.getVersion() == -1 ? 0 : (long) toBalanceKV.getValue(); diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Query.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Query.java index 3205fd73..a3e44d95 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Query.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Query.java @@ -4,7 +4,7 @@ import com.jd.blockchain.crypto.Crypto; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.KVDataEntry; +import com.jd.blockchain.ledger.TypedKVEntry; import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerTransaction; import com.jd.blockchain.ledger.Transaction; @@ -67,7 +67,7 @@ public class SDKDemo_Query { // 获取数据; String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; String[] objKeys = new String[] { "x001", "x002" }; - KVDataEntry[] kvData = service.getDataEntries(LEDGER_HASH, commerceAccount, objKeys); + TypedKVEntry[] kvData = service.getDataEntries(LEDGER_HASH, commerceAccount, objKeys); long payloadVersion = kvData[0].getVersion(); diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java index 9d43b199..caae0d6d 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java @@ -6,7 +6,7 @@ import static com.jd.blockchain.transaction.ContractReturnValue.decode; import com.jd.blockchain.contract.TransferContract; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.KVDataEntry; +import com.jd.blockchain.ledger.TypedKVEntry; import com.jd.blockchain.ledger.PreparedTransaction; import com.jd.blockchain.ledger.TransactionResponse; import com.jd.blockchain.ledger.TransactionTemplate; @@ -106,11 +106,11 @@ public class SDK_Contract_Demo extends SDK_Base_Demo { } private long readByKvOperation(String address, String account) { - KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account); + TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account); if (kvDataEntries == null || kvDataEntries.length == 0) { throw new IllegalStateException(String.format("Ledger %s Service inner Error !!!", ledgerHash.toBase58())); } - KVDataEntry kvDataEntry = kvDataEntries[0]; + TypedKVEntry kvDataEntry = kvDataEntries[0]; if (kvDataEntry.getVersion() == -1) { return 0L; } diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Random_Demo.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Random_Demo.java index c73a7f91..868f3269 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Random_Demo.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Random_Demo.java @@ -79,11 +79,11 @@ public class SDK_Contract_Random_Demo extends SDK_Base_Demo { } private long readByKvOperation(String address, String account) { - KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account); + TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account); if (kvDataEntries == null || kvDataEntries.length == 0) { throw new IllegalStateException(String.format("Ledger %s Service inner Error !!!", ledgerHash.toBase58())); } - KVDataEntry kvDataEntry = kvDataEntries[0]; + TypedKVEntry kvDataEntry = kvDataEntries[0]; if (kvDataEntry.getVersion() == -1) { return 0L; } diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_InsertData_Demo.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_InsertData_Demo.java index 3a89c7a6..d90b5233 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_InsertData_Demo.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_InsertData_Demo.java @@ -107,9 +107,9 @@ public class SDK_InsertData_Demo extends SDK_Base_Demo { // KVDataEntry[] kvData = blockchainService.getDataEntries(ledgerHash, commerceAccount, objKeys); // 获取数据账户下所有的KV列表 - KVDataEntry[] kvData = blockchainService.getDataEntries(ledgerHash, commerceAccount, 0, 100); + TypedKVEntry[] kvData = blockchainService.getDataEntries(ledgerHash, commerceAccount, 0, 100); if (kvData != null && kvData.length > 0) { - for (KVDataEntry kvDatum : kvData) { + for (TypedKVEntry kvDatum : kvData) { System.out.println("kvData.key=" + kvDatum.getKey()); System.out.println("kvData.version=" + kvDatum.getVersion()); System.out.println("kvData.type=" + kvDatum.getType()); diff --git a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java index 3851d6a7..3d291811 100644 --- a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java +++ b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java @@ -19,12 +19,12 @@ import com.jd.blockchain.crypto.HashFunction; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.SignatureDigest; import com.jd.blockchain.crypto.SignatureFunction; -import com.jd.blockchain.ledger.AccountHeader; +import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.DigitalSignature; import com.jd.blockchain.ledger.EndpointRequest; -import com.jd.blockchain.ledger.KVDataEntry; +import com.jd.blockchain.ledger.TypedKVEntry; import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerInfo; import com.jd.blockchain.ledger.LedgerTransaction; @@ -98,7 +98,7 @@ public class SDK_GateWay_Query_Test_ { System.out.println("contractCount=" + count); count = service.getContractCount(ledgerHash, hashDigest); System.out.println("contractCount=" + count); - AccountHeader contract = service.getContract(ledgerHash, "12345678"); + BlockchainIdentity contract = service.getContract(ledgerHash, "12345678"); System.out.println(contract); LedgerBlock block = service.getBlock(ledgerHash, hashDigest); @@ -109,7 +109,7 @@ public class SDK_GateWay_Query_Test_ { count = service.getDataAccountCount(ledgerHash, hashDigest); System.out.println("dataAccountCount=" + count); - AccountHeader dataAccount = service.getDataAccount(ledgerHash, "1245633"); + BlockchainIdentity dataAccount = service.getDataAccount(ledgerHash, "1245633"); System.out.println(dataAccount.getAddress()); count = service.getTransactionCount(ledgerHash, hashDigest); @@ -149,8 +149,8 @@ public class SDK_GateWay_Query_Test_ { String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; String[] objKeys = new String[] { "x001", "x002" }; - KVDataEntry[] kvData = service.getDataEntries(ledgerHash, commerceAccount, objKeys); - for (KVDataEntry kvDatum : kvData) { + TypedKVEntry[] kvData = service.getDataEntries(ledgerHash, commerceAccount, objKeys); + for (TypedKVEntry kvDatum : kvData) { System.out.println("kvData.key=" + kvDatum.getKey()); System.out.println("kvData.version=" + kvDatum.getVersion()); System.out.println("kvData.value=" + kvDatum.getValue()); diff --git a/source/storage/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..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 @@ -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.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 978fd8c5..98c47325 100644 --- a/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBVersioningStorage.java +++ b/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBVersioningStorage.java @@ -7,9 +7,9 @@ import java.util.concurrent.locks.ReentrantLock; import org.apache.commons.collections4.map.LRUMap; import org.rocksdb.*; -import com.jd.blockchain.storage.service.VersioningKVEntry; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; import com.jd.blockchain.utils.io.BytesUtils; /** @@ -127,7 +127,7 @@ public class RocksDBVersioningStorage implements VersioningKVStorage { } @Override - public VersioningKVEntry getEntry(Bytes key, long version) { + public DataEntry getEntry(Bytes key, long version) { byte[] value = get(key, version); if (value == null) { return null; @@ -226,7 +226,7 @@ public class RocksDBVersioningStorage implements VersioningKVStorage { } } - private static class VersioningKVData implements VersioningKVEntry { + private static class VersioningKVData implements DataEntry { private Bytes key; diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVEntry.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVEntry.java deleted file mode 100644 index a18f6740..00000000 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVEntry.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.jd.blockchain.storage.service; - -import com.jd.blockchain.utils.Bytes; - -/** - * 版本化的键值数据项; - * - * @author huanghaiquan - * - */ -public interface VersioningKVEntry { - -// String getKey(); - Bytes getKey(); - - long getVersion(); - - byte[] getValue(); - -} \ No newline at end of file diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVStorage.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVStorage.java index 711606d3..980cc32c 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVStorage.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVStorage.java @@ -1,6 +1,7 @@ package com.jd.blockchain.storage.service; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; /** * Versioning Key-Value Storage @@ -40,7 +41,7 @@ public interface VersioningKVStorage extends BatchStorageService { * @param version * @return */ - VersioningKVEntry getEntry(Bytes key, long version); + DataEntry getEntry(Bytes key, long version); /** * Return the specified verson's value;
diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/BufferedKVStorage.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/BufferedKVStorage.java index 7b292248..b038a87e 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/BufferedKVStorage.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/BufferedKVStorage.java @@ -7,10 +7,10 @@ import java.util.concurrent.ForkJoinTask; import java.util.concurrent.RecursiveTask; import com.jd.blockchain.storage.service.ExPolicyKVStorage; -import com.jd.blockchain.storage.service.VersioningKVEntry; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Transactional; +import com.jd.blockchain.utils.DataEntry; /** * {@link BufferedKVStorage} 缓冲写入的KV存储;
@@ -77,9 +77,9 @@ public class BufferedKVStorage implements VersioningKVStorage, ExPolicyKVStorage } return ws.getLatestVersion(); } - + @Override - public VersioningKVEntry getEntry(Bytes key, long version) { + public DataEntry getEntry(Bytes key, long version) { VersioningWritingSet ws = versioningCache.get(key); if (ws == null) { return origVersioningStorage.getEntry(key, version); @@ -484,7 +484,7 @@ public class BufferedKVStorage implements VersioningKVStorage, ExPolicyKVStorage return startingVersion; } - public VersioningKVEntry getEntry(long version) { + public DataEntry getEntry(long version) { byte[] value = get(version); if (value == null) { return null; @@ -505,7 +505,7 @@ public class BufferedKVStorage implements VersioningKVStorage, ExPolicyKVStorage } } - private static class VersioningKVData implements VersioningKVEntry { + private static class VersioningKVData implements DataEntry { private Bytes key; diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java index 0c2192a3..a0f36c0d 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java @@ -5,9 +5,9 @@ import java.util.Set; import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.KVStorageService; -import com.jd.blockchain.storage.service.VersioningKVEntry; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; import com.jd.blockchain.utils.io.BytesMap; public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage, KVStorageService, BytesMap { @@ -21,7 +21,7 @@ public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage, } @Override - public VersioningKVEntry getEntry(Bytes key, long version) { + public DataEntry getEntry(Bytes key, long version) { return verStorage.getEntry(key, version); } diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java index 684c75fe..73816055 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java @@ -1,24 +1,23 @@ package com.jd.blockchain.storage.service.utils; -import com.jd.blockchain.storage.service.VersioningKVEntry; -import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; -public class VersioningKVData implements VersioningKVEntry { +public class VersioningKVData implements DataEntry { - private Bytes key; + private K key; private long version; - private byte[] value; + private V value; - public VersioningKVData(Bytes key, long version, byte[] value) { + public VersioningKVData(K key, long version, V value) { this.key = key; this.version = version; this.value = value; } @Override - public Bytes getKey() { + public K getKey() { return key; } @@ -28,7 +27,7 @@ public class VersioningKVData implements VersioningKVEntry { } @Override - public byte[] getValue() { + public V getValue() { return value; } diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVStorageMap.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVStorageMap.java index 3c4855e3..1c6b8def 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVStorageMap.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVStorageMap.java @@ -5,9 +5,9 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import com.jd.blockchain.storage.service.VersioningKVEntry; import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; import com.jd.blockchain.utils.io.BytesMap; public class VersioningKVStorageMap implements VersioningKVStorage, BytesMap { @@ -42,7 +42,7 @@ public class VersioningKVStorageMap implements VersioningKVStorage, BytesMap R[] castTo(T[] objs, Class clazz, CastFunction cf) { + if (objs == null) { + return null; + } + @SuppressWarnings("unchecked") + R[] array = (R[]) Array.newInstance(clazz, objs.length); + for (int i = 0; i < objs.length; i++) { + array[i] = cf.cast(objs[i]); + } + return array; + } + public static T[] singleton(T obj, Class clazz) { @SuppressWarnings("unchecked") T[] array = (T[]) Array.newInstance(clazz, 1); array[0] = obj; return array; } - - public static T[] toArray(Iterator itr, Class clazz){ + + public static T[] toArray(Iterator itr, Class clazz) { List lst = new LinkedList(); while (itr.hasNext()) { T t = (T) itr.next(); @@ -30,19 +42,19 @@ public abstract class ArrayUtils { lst.toArray(array); return array; } - - public static T[] toArray(Collection collection, Class clazz){ + + public static T[] toArray(Collection collection, Class clazz) { @SuppressWarnings("unchecked") T[] array = (T[]) Array.newInstance(clazz, collection.size()); collection.toArray(array); return array; } - - public static List asList(T[] array){ + + public static List asList(T[] array) { return asList(array, 0, array.length); } - - public static Set asSet(T[] array){ + + public static Set asSet(T[] array) { if (array == null || array.length == 0) { return Collections.emptySet(); } @@ -52,8 +64,8 @@ public abstract class ArrayUtils { } return set; } - - public static SortedSet asSortedSet(T[] array){ + + public static SortedSet asSortedSet(T[] array) { if (array == null || array.length == 0) { return Collections.emptySortedSet(); } @@ -63,12 +75,12 @@ public abstract class ArrayUtils { } return set; } - - public static List asList(T[] array, int fromIndex){ + + public static List asList(T[] array, int fromIndex) { return asList(array, fromIndex, array.length); } - - public static List asList(T[] array, int fromIndex, int toIndex){ + + public static List asList(T[] array, int fromIndex, int toIndex) { if (toIndex < fromIndex) { throw new IllegalArgumentException("The toIndex less than fromIndex!"); } @@ -78,10 +90,33 @@ public abstract class ArrayUtils { if (toIndex > array.length) { throw new IllegalArgumentException("The toIndex great than the length of array!"); } - + if (fromIndex == toIndex) { return Collections.emptyList(); } return new ReadonlyArrayListWrapper(array, fromIndex, toIndex); } + + public static interface CastFunction { + public R cast(T data); + } + + /** + * Reverse all elements of the specified array;
+ * + * @param + * @param array + */ + public static void reverse(T[] array) { + if (array == null || array.length < 2) { + return; + } + + T t; + for (int i = 0, j = array.length - 1; i < j; i++, j--) { + t = array[i]; + array[i] = array[j]; + array[j] = t; + } + } } diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BaseConstant.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BaseConstant.java index 4548dbad..890748e5 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BaseConstant.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BaseConstant.java @@ -1,7 +1,5 @@ package com.jd.blockchain.utils; -import java.io.File; - /** * * @author zhaogw diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataEntry.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataEntry.java new file mode 100644 index 00000000..b02fa524 --- /dev/null +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataEntry.java @@ -0,0 +1,17 @@ +package com.jd.blockchain.utils; + +/** + * Versioning Key-Value data entry; + * + * @author huanghaiquan + * + */ +public interface DataEntry { + + public K getKey(); + + public long getVersion(); + + public V getValue(); + +} \ No newline at end of file diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataIterator.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataIterator.java new file mode 100644 index 00000000..13a8a0d0 --- /dev/null +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataIterator.java @@ -0,0 +1,21 @@ +package com.jd.blockchain.utils; + +/** + * 数据迭代器; + * + * @author huanghaiquan + * + * @param + * @param + */ +public interface DataIterator { + + void skip(long count); + + DataEntry next(); + + DataEntry[] next(int count); + + boolean hasNext(); + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataTypeUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataTypeUtils.java deleted file mode 100644 index 05952868..00000000 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataTypeUtils.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.jd.blockchain.utils; - -import java.lang.reflect.Type; -import java.util.HashMap; -import java.util.Map; - -import org.springframework.util.TypeUtils; - -public abstract class DataTypeUtils { - - private static Map, Class> wrapperTypes = new HashMap, Class>(); - - static{ - wrapperTypes.put(long.class, Long.class); - wrapperTypes.put(int.class, Integer.class); - wrapperTypes.put(char.class, Character.class); - wrapperTypes.put(byte.class, Byte.class); - wrapperTypes.put(boolean.class, Boolean.class); - } - - public static boolean isAssignable(Type lhsType, Type rhsType) { - boolean assignable = TypeUtils.isAssignable(lhsType, rhsType); - if (assignable) { - return true; - } - if (lhsType instanceof Class) { - Class lhsClass = (Class) lhsType; - - } - - return false; - } - -} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Dataset.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Dataset.java new file mode 100644 index 00000000..2a82bd19 --- /dev/null +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Dataset.java @@ -0,0 +1,101 @@ +package com.jd.blockchain.utils; + +/** + * Key-Value data set; + * + * @author huanghaiquan + * + * @param + * @param + */ +public interface Dataset { + + /** + * Total count of data entries; + * + * @return + */ + long getDataCount(); + + /** + * Create or update the value associated the specified key if the version + * checking is passed.
+ * + * The value of the key will be updated only if it's latest version equals the + * specified version argument.
+ * If the key doesn't exist, it will be created when the version arg was -1. + *

+ * If updating is performed, the version of the key increase by 1.
+ * If creating is performed, the version of the key initialize by 0.
+ * + * @param key The key of data; + * @param value The value of data; + * @param version The expected latest version of the key. + * @return The new version of the key.
+ * If the key is new created success, then return 0;
+ * If the key is updated success, then return the new version;
+ * If this operation fail by version checking or other reason, then + * return -1; + */ + long setValue(K key, V value, long version); + + /** + * Return the specified version's value;
+ * + * If the key with the specified version doesn't exist, then return null;
+ * If the version is specified to -1, then return the latest version's value; + * + * @param key + * @param version + */ + V getValue(K key, long version); + + /** + * Return the value of the latest version; + * + * @param key + * @return return null if not exist; + */ + V getValue(K key); + + /** + * Return the latest version number of the specified key; + * + * @param key + * @return The version number of the specified key; If the key doesn't exist, + * then return -1; + */ + long getVersion(K key); + + /** + * Return the data entry with the specified key; + * + * @param key + * @return Null if the key doesn't exist! + */ + DataEntry getDataEntry(K key); + + /** + * Return the data entry with the specified key and version; + * + * @param key + * @param version + * @return Null if the key doesn't exist! + */ + DataEntry getDataEntry(K key, long version); + + /** + * Ascending iterator; + * + * @return + */ + DataIterator iterator(); + + /** + * Descending iterator; + * + * @return + */ + DataIterator iteratorDesc(); + +} \ No newline at end of file diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DatasetHelper.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DatasetHelper.java new file mode 100644 index 00000000..acbdce51 --- /dev/null +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DatasetHelper.java @@ -0,0 +1,382 @@ +package com.jd.blockchain.utils; + +/** + * Helper for {@link Dataset}; + * + * @author huanghaiquan + * + */ +public class DatasetHelper { + + public static final TypeMapper UTF8_STRING_BYTES_MAPPER = new TypeMapper() { + + @Override + public Bytes encode(String t2) { + return Bytes.fromString(t2); + } + + @Override + public String decode(Bytes t1) { + return t1.toUTF8String(); + } + }; + + public static final TypeMapper BYTES_UTF8_STRING_MAPPER = new TypeMapper() { + + @Override + public String encode(Bytes t1) { + return t1.toUTF8String(); + } + + @Override + public Bytes decode(String t2) { + return Bytes.fromString(t2); + } + }; + + /** + * 适配两个不同类型参数的数据集; + * + * @param 适配输入的 键 类型; + * @param 适配输出的 键 类型; + * @param 适配输入的 值 类型; + * @param 适配输出的 值 类型; + * @param dataset 数据集; + * @param keyMapper 键的映射配置; + * @param valueMapper 值的映射配置; + * @return + */ + public static Dataset map(Dataset dataset) { + return new TypeAdapter(dataset, UTF8_STRING_BYTES_MAPPER, new EmptyMapper()); + } + + /** + * 适配两个不同类型参数的数据集; + * + * @param 适配输入的 键 类型; + * @param 适配输出的 键 类型; + * @param 适配输入的 值 类型; + * @param 适配输出的 值 类型; + * @param dataset 数据集; + * @param keyMapper 键的映射配置; + * @param valueMapper 值的映射配置; + * @return + */ + public static Dataset map(Dataset dataset, TypeMapper valueMapper) { + return new TypeAdapter(dataset, UTF8_STRING_BYTES_MAPPER, valueMapper); + } + + /** + * 适配两个不同类型参数的数据集; + * + * @param 适配输入的 键 类型; + * @param 适配输出的 键 类型; + * @param 适配输入的 值 类型; + * @param 适配输出的 值 类型; + * @param dataset 数据集; + * @param keyMapper 键的映射配置; + * @param valueMapper 值的映射配置; + * @return + */ + public static Dataset map(Dataset dataset, TypeMapper keyMapper, + TypeMapper valueMapper) { + return new TypeAdapter(dataset, keyMapper, valueMapper); + } + + /** + * 监听对数据集的变更; + * + * @param 键 类型; + * @param 值 类型; + * @param dataset 要监听的数据集; + * @param listener 要植入的监听器; + * @return 植入监听器的数据集实例; + */ + public static Dataset listen(Dataset dataset, DataChangedListener listener) { + return new DatasetUpdatingMonitor(dataset, listener); + } + + /** + * 数据修改监听器; + * + * @author huanghaiquan + * + * @param + * @param + */ + public static interface DataChangedListener { + + void onChanged(K key, V value, long expectedVersion, long newVersion); + + } + + /** + * 类型映射接口; + * + * @author huanghaiquan + * + * @param + * @param + */ + public static interface TypeMapper { + + T1 encode(T2 t2); + + T2 decode(T1 t1); + + } + + private static class EmptyMapper implements TypeMapper { + + @Override + public T encode(T t) { + return t; + } + + @Override + public T decode(T t) { + return t; + } + + } + + private static class DatasetUpdatingMonitor implements Dataset { + + private Dataset dataset; + + private DataChangedListener listener; + + public DatasetUpdatingMonitor(Dataset dataset, DataChangedListener listener) { + this.dataset = dataset; + this.listener = listener; + } + + @Override + public long getDataCount() { + return dataset.getDataCount(); + } + + @Override + public long setValue(K key, V value, long version) { + long newVersion = dataset.setValue(key, value, version); + if (newVersion > -1) { + listener.onChanged(key, value, version, newVersion); + } + return newVersion; + } + + @Override + public V getValue(K key, long version) { + return dataset.getValue(key, version); + } + + @Override + public V getValue(K key) { + return dataset.getValue(key); + } + + @Override + public long getVersion(K key) { + return dataset.getVersion(key); + } + + @Override + public DataEntry getDataEntry(K key) { + return dataset.getDataEntry(key); + } + + @Override + public DataEntry getDataEntry(K key, long version) { + return dataset.getDataEntry(key, version); + } + + @Override + public DataIterator iterator() { + return dataset.iterator(); + } + + @Override + public DataIterator iteratorDesc() { + return dataset.iteratorDesc(); + } + + } + + /** + * 类型适配器; + * + * @author huanghaiquan + * + * @param + * @param + * @param + * @param + */ + private static class TypeAdapter implements Dataset { + private Dataset dataset; + private TypeMapper keyMapper; + private TypeMapper valueMapper; + + public TypeAdapter(Dataset dataset, TypeMapper keyMapper, TypeMapper valueMapper) { + this.dataset = dataset; + this.keyMapper = keyMapper; + this.valueMapper = valueMapper; + } + + @Override + public long getDataCount() { + return dataset.getDataCount(); + } + + @Override + public long setValue(K2 key, V2 value, long version) { + K1 key1 = keyMapper.encode(key); + V1 value1 = valueMapper.encode(value); + return dataset.setValue(key1, value1, version); + } + + @Override + public V2 getValue(K2 key, long version) { + K1 k = keyMapper.encode(key); + V1 v = dataset.getValue(k, version); + if (v == null) { + return null; + } + return valueMapper.decode(v); + } + + @Override + public V2 getValue(K2 key) { + K1 k = keyMapper.encode(key); + V1 v = dataset.getValue(k); + if (v == null) { + return null; + } + return valueMapper.decode(v); + } + + @Override + public long getVersion(K2 key) { + K1 k = keyMapper.encode(key); + return dataset.getVersion(k); + } + + @Override + public DataEntry getDataEntry(K2 key) { + K1 k = keyMapper.encode(key); + DataEntry entry = dataset.getDataEntry(k); + if (entry == null) { + return null; + } + V2 v = valueMapper.decode(entry.getValue()); + return new KeyValueEntry(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()); + } + + @Override + public DataIterator iterator() { + DataIterator it = dataset.iterator(); + return new DataIteratorAdapter(it, keyMapper, valueMapper); + } + + @Override + public DataIterator iteratorDesc() { + DataIterator it = dataset.iteratorDesc(); + return new DataIteratorAdapter(it, keyMapper, valueMapper); + } + + } + + private static class DataIteratorAdapter implements DataIterator { + + private DataIterator iterator; + + private TypeMapper keyMapper; + private TypeMapper valueMapper; + + public DataIteratorAdapter(DataIterator iterator, TypeMapper keyMapper, + TypeMapper valueMapper) { + this.iterator = iterator; + this.keyMapper = keyMapper; + this.valueMapper = valueMapper; + } + + @Override + public void skip(long count) { + iterator.skip(count); + } + + @Override + public DataEntry next() { + DataEntry entry = iterator.next(); + return cast(entry); + } + + private DataEntry cast(DataEntry entry) { + if (entry == null) { + return null; + } + + K2 k = keyMapper.decode(entry.getKey()); + V2 v = valueMapper.decode(entry.getValue()); + return new KeyValueEntry(k, v, entry.getVersion()); + } + + @SuppressWarnings("unchecked") + @Override + public DataEntry[] next(int count) { + DataEntry[] entries = iterator.next(count); + if (entries == null) { + return null; + } + if (entries.length == 0) { + return (DataEntry[]) entries; + } + return ArrayUtils.castTo(entries, DataEntry.class, e -> cast(e)); + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + } + + 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; + } + + } +}