# Conflicts: # source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java # source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java # source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java # source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java # source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestAll4Redis.javatags/1.0.0
| @@ -30,9 +30,9 @@ public enum PrimitiveType { | |||||
| INT64((byte) (DataType.NUMERIC | 0x04)), | INT64((byte) (DataType.NUMERIC | 0x04)), | ||||
| /** | /** | ||||
| * 日期时间; | |||||
| * 时间戳; | |||||
| */ | */ | ||||
| DATETIME((byte) (DataType.NUMERIC | 0x08)), | |||||
| TIMESTAMP((byte) (DataType.NUMERIC | 0x08)), | |||||
| /** | /** | ||||
| * 文本数据; | * 文本数据; | ||||
| @@ -1,5 +1,6 @@ | |||||
| package com.jd.blockchain.contract.engine; | package com.jd.blockchain.contract.engine; | ||||
| import com.jd.blockchain.ledger.BytesValue; | |||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| /** | /** | ||||
| @@ -2,6 +2,7 @@ package com.jd.blockchain.contract.jvm; | |||||
| import com.jd.blockchain.contract.engine.ContractCode; | import com.jd.blockchain.contract.engine.ContractCode; | ||||
| import com.jd.blockchain.contract.engine.ContractEngine; | import com.jd.blockchain.contract.engine.ContractEngine; | ||||
| import com.jd.blockchain.ledger.BytesValue; | |||||
| import com.jd.blockchain.runtime.Module; | import com.jd.blockchain.runtime.Module; | ||||
| import com.jd.blockchain.runtime.RuntimeContext; | import com.jd.blockchain.runtime.RuntimeContext; | ||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| @@ -19,7 +19,7 @@ public interface AccountAccessPolicy { | |||||
| * @param account | * @param account | ||||
| * @return Return true if it satisfies this policy, or false if it doesn't; | * @return Return true if it satisfies this policy, or false if it doesn't; | ||||
| */ | */ | ||||
| boolean checkCommitting(AccountHeader account); | |||||
| boolean checkDataWriting(AccountHeader account); | |||||
| boolean checkRegistering(Bytes address, PubKey pubKey); | boolean checkRegistering(Bytes address, PubKey pubKey); | ||||
| @@ -9,7 +9,9 @@ import com.jd.blockchain.crypto.AddressEncoding; | |||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
| import com.jd.blockchain.ledger.AccountHeader; | import com.jd.blockchain.ledger.AccountHeader; | ||||
| import com.jd.blockchain.ledger.BytesValue; | |||||
| import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
| import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| @@ -160,10 +162,8 @@ public class AccountSet implements Transactional, MerkleProvable { | |||||
| * | * | ||||
| * 只有最新版本的账户才能可写的,其它都是只读; | * 只有最新版本的账户才能可写的,其它都是只读; | ||||
| * | * | ||||
| * @param address | |||||
| * 账户地址; | |||||
| * @param version | |||||
| * 账户版本;如果指定为 -1,则返回最新版本; | |||||
| * @param address 账户地址; | |||||
| * @param version 账户版本;如果指定为 -1,则返回最新版本; | |||||
| * @return | * @return | ||||
| */ | */ | ||||
| public BaseAccount getAccount(Bytes address, long version) { | public BaseAccount getAccount(Bytes address, long version) { | ||||
| @@ -226,10 +226,8 @@ public class AccountSet implements Transactional, MerkleProvable { | |||||
| * | * | ||||
| * 如果指定的地址和公钥不匹配,则会引发 {@link LedgerException} 异常; | * 如果指定的地址和公钥不匹配,则会引发 {@link LedgerException} 异常; | ||||
| * | * | ||||
| * @param address | |||||
| * 区块链地址; | |||||
| * @param pubKey | |||||
| * 公钥; | |||||
| * @param address 区块链地址; | |||||
| * @param pubKey 公钥; | |||||
| * @return 注册成功的账户对象; | * @return 注册成功的账户对象; | ||||
| */ | */ | ||||
| public BaseAccount register(Bytes address, PubKey pubKey) { | public BaseAccount register(Bytes address, PubKey pubKey) { | ||||
| @@ -283,15 +281,14 @@ public class AccountSet implements Transactional, MerkleProvable { | |||||
| private VersioningAccount createInstance(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, | private VersioningAccount createInstance(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, | ||||
| String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, long version) { | String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, long version) { | ||||
| return new VersioningAccount(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage, accessPolicy, | |||||
| version); | |||||
| return new VersioningAccount(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage, version); | |||||
| } | } | ||||
| private VersioningAccount deserialize(byte[] bytes, CryptoSetting cryptoSetting, String keyPrefix, | private VersioningAccount deserialize(byte[] bytes, CryptoSetting cryptoSetting, String keyPrefix, | ||||
| ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, long version) { | ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, long version) { | ||||
| AccountHeader accInfo = BinaryProtocol.decode(bytes); | AccountHeader accInfo = BinaryProtocol.decode(bytes); | ||||
| return new VersioningAccount(accInfo.getAddress(), accInfo.getPubKey(), accInfo.getRootHash(), cryptoSetting, | return new VersioningAccount(accInfo.getAddress(), accInfo.getPubKey(), accInfo.getRootHash(), cryptoSetting, | ||||
| keyPrefix, exStorage, verStorage, readonly, accessPolicy, version); | |||||
| keyPrefix, exStorage, verStorage, readonly, version); | |||||
| } | } | ||||
| private byte[] serialize(AccountHeader account) { | private byte[] serialize(AccountHeader account) { | ||||
| @@ -388,15 +385,14 @@ public class AccountSet implements Transactional, MerkleProvable { | |||||
| public VersioningAccount(Bytes address, PubKey pubKey, HashDigest rootHash, CryptoSetting cryptoSetting, | public VersioningAccount(Bytes address, PubKey pubKey, HashDigest rootHash, CryptoSetting cryptoSetting, | ||||
| String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, | String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, | ||||
| AccountAccessPolicy accessPolicy, long version) { | |||||
| super(address, pubKey, rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly, accessPolicy); | |||||
| long version) { | |||||
| super(address, pubKey, rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); | |||||
| this.version = version; | this.version = version; | ||||
| } | } | ||||
| public VersioningAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix, | public VersioningAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix, | ||||
| ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy, | |||||
| long version) { | |||||
| super(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage, accessPolicy); | |||||
| ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, long version) { | |||||
| super(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage); | |||||
| this.version = version; | this.version = version; | ||||
| } | } | ||||
| @@ -426,7 +422,7 @@ public class AccountSet implements Transactional, MerkleProvable { | |||||
| // } | // } | ||||
| @Override | @Override | ||||
| public long setBytes(Bytes key, byte[] value, long version) { | |||||
| public long setBytes(Bytes key, BytesValue value, long version) { | |||||
| long v = super.setBytes(key, value, version); | long v = super.setBytes(key, value, version); | ||||
| if (v > -1) { | if (v > -1) { | ||||
| updated = true; | updated = true; | ||||
| @@ -1,10 +1,12 @@ | |||||
| package com.jd.blockchain.ledger.core; | package com.jd.blockchain.ledger.core; | ||||
| import com.jd.blockchain.binaryproto.BinaryProtocol; | |||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
| import com.jd.blockchain.ledger.AccountHeader; | import com.jd.blockchain.ledger.AccountHeader; | ||||
| import com.jd.blockchain.ledger.BlockchainIdentity; | import com.jd.blockchain.ledger.BlockchainIdentity; | ||||
| import com.jd.blockchain.ledger.BlockchainIdentityData; | import com.jd.blockchain.ledger.BlockchainIdentityData; | ||||
| import com.jd.blockchain.ledger.BytesValue; | |||||
| import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
| import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
| import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
| @@ -23,8 +25,6 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional | |||||
| protected MerkleDataSet dataset; | protected MerkleDataSet dataset; | ||||
| private AccountAccessPolicy accessPolicy; | |||||
| /** | /** | ||||
| * Create a new Account with the specified address and pubkey; <br> | * Create a new Account with the specified address and pubkey; <br> | ||||
| * | * | ||||
| @@ -38,8 +38,8 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional | |||||
| * @param pubKey | * @param pubKey | ||||
| */ | */ | ||||
| public BaseAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix, | public BaseAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix, | ||||
| ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { | |||||
| this(address, pubKey, null, cryptoSetting, keyPrefix, exStorage, verStorage, false, accessPolicy); | |||||
| ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) { | |||||
| this(address, pubKey, null, cryptoSetting, keyPrefix, exStorage, verStorage, false); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -58,8 +58,8 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional | |||||
| * @param accessPolicy | * @param accessPolicy | ||||
| */ | */ | ||||
| public BaseAccount(BlockchainIdentity bcid, CryptoSetting cryptoSetting, String keyPrefix, | public BaseAccount(BlockchainIdentity bcid, CryptoSetting cryptoSetting, String keyPrefix, | ||||
| ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { | |||||
| this(bcid, null, cryptoSetting, keyPrefix, exStorage, verStorage, false, accessPolicy); | |||||
| ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) { | |||||
| this(bcid, null, cryptoSetting, keyPrefix, exStorage, verStorage, false); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -69,9 +69,8 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional | |||||
| * | * | ||||
| * @param address | * @param address | ||||
| * @param pubKey | * @param pubKey | ||||
| * @param dataRootHash | |||||
| * merkle root hash of account's data; if null be set, create a new | |||||
| * empty merkle dataset; | |||||
| * @param dataRootHash merkle root hash of account's data; if null be set, | |||||
| * create a new empty merkle dataset; | |||||
| * @param cryptoSetting | * @param cryptoSetting | ||||
| * @param exStorage | * @param exStorage | ||||
| * @param verStorage | * @param verStorage | ||||
| @@ -79,18 +78,15 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional | |||||
| * @param accessPolicy | * @param accessPolicy | ||||
| */ | */ | ||||
| public BaseAccount(Bytes address, PubKey pubKey, HashDigest dataRootHash, CryptoSetting cryptoSetting, | public BaseAccount(Bytes address, PubKey pubKey, HashDigest dataRootHash, CryptoSetting cryptoSetting, | ||||
| String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, | |||||
| AccountAccessPolicy accessPolicy) { | |||||
| String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) { | |||||
| this(new BlockchainIdentityData(address, pubKey), dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, | this(new BlockchainIdentityData(address, pubKey), dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, | ||||
| readonly, accessPolicy); | |||||
| readonly); | |||||
| } | } | ||||
| public BaseAccount(BlockchainIdentity bcid, HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix, | public BaseAccount(BlockchainIdentity bcid, HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix, | ||||
| ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, | |||||
| AccountAccessPolicy accessPolicy) { | |||||
| ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) { | |||||
| this.bcid = bcid; | this.bcid = bcid; | ||||
| this.dataset = new MerkleDataSet(dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); | this.dataset = new MerkleDataSet(dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); | ||||
| this.accessPolicy = accessPolicy; | |||||
| } | } | ||||
| /* | /* | ||||
| @@ -151,21 +147,18 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional | |||||
| * If updating is performed, the version of the key increase by 1. <br> | * If updating is performed, the version of the key increase by 1. <br> | ||||
| * If creating is performed, the version of the key initialize by 0. <br> | * If creating is performed, the version of the key initialize by 0. <br> | ||||
| * | * | ||||
| * @param key | |||||
| * The key of data; | |||||
| * @param value | |||||
| * The value of data; | |||||
| * @param version | |||||
| * The expected version of the key. | |||||
| * @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. <br> | * @return The new version of the key. <br> | ||||
| * If the key is new created success, then return 0; <br> | * If the key is new created success, then return 0; <br> | ||||
| * If the key is updated success, then return the new version;<br> | * If the key is updated success, then return the new version;<br> | ||||
| * If this operation fail by version checking or other reason, then | * If this operation fail by version checking or other reason, then | ||||
| * return -1; | * return -1; | ||||
| */ | */ | ||||
| public long setBytes(Bytes key, byte[] value, long version) { | |||||
| // TODO: 支持多种数据类型; | |||||
| return dataset.setValue(key, value, version); | |||||
| public long setBytes(Bytes key, BytesValue value, long version) { | |||||
| byte[] bytesValue = BinaryProtocol.encode(value, BytesValue.class); | |||||
| return dataset.setValue(key, bytesValue, version); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -185,8 +178,12 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional | |||||
| * @param key | * @param key | ||||
| * @return return null if not exist; | * @return return null if not exist; | ||||
| */ | */ | ||||
| public byte[] getBytes(Bytes key) { | |||||
| return dataset.getValue(key); | |||||
| public BytesValue getBytes(Bytes key) { | |||||
| byte[] bytesValue = dataset.getValue(key); | |||||
| if (bytesValue == null) { | |||||
| return null; | |||||
| } | |||||
| return BinaryProtocol.decodeAs(bytesValue, BytesValue.class); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -196,8 +193,12 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional | |||||
| * @param version | * @param version | ||||
| * @return return null if not exist; | * @return return null if not exist; | ||||
| */ | */ | ||||
| public byte[] getBytes(Bytes key, long version) { | |||||
| return dataset.getValue(key, version); | |||||
| public BytesValue getBytes(Bytes key, long version) { | |||||
| byte[] bytesValue = dataset.getValue(key, version); | |||||
| if (bytesValue == null) { | |||||
| return null; | |||||
| } | |||||
| return BinaryProtocol.decodeAs(bytesValue, BytesValue.class); | |||||
| } | } | ||||
| @Override | @Override | ||||
| @@ -207,10 +208,6 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional | |||||
| @Override | @Override | ||||
| public void commit() { | public void commit() { | ||||
| if (!accessPolicy.checkCommitting(this)) { | |||||
| throw new LedgerException("Account Committing was rejected for the access policy!"); | |||||
| } | |||||
| dataset.commit(); | dataset.commit(); | ||||
| } | } | ||||
| @@ -3,8 +3,9 @@ package com.jd.blockchain.ledger.core; | |||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
| import com.jd.blockchain.ledger.AccountHeader; | import com.jd.blockchain.ledger.AccountHeader; | ||||
| import com.jd.blockchain.ledger.BytesValue; | |||||
| import com.jd.blockchain.ledger.BytesValueEntry; | |||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| import com.jd.blockchain.utils.io.BytesUtils; | |||||
| public class ContractAccount implements AccountHeader { | public class ContractAccount implements AccountHeader { | ||||
| @@ -42,15 +43,16 @@ public class ContractAccount implements AccountHeader { | |||||
| } | } | ||||
| public long setChaincode(byte[] chaincode, long version) { | public long setChaincode(byte[] chaincode, long version) { | ||||
| return accBase.setBytes(CHAIN_CODE_KEY, chaincode, version); | |||||
| BytesValue bytesValue = BytesValueEntry.fromBytes(chaincode); | |||||
| return accBase.setBytes(CHAIN_CODE_KEY, bytesValue, version); | |||||
| } | } | ||||
| public byte[] getChainCode() { | public byte[] getChainCode() { | ||||
| return accBase.getBytes(CHAIN_CODE_KEY); | |||||
| return accBase.getBytes(CHAIN_CODE_KEY).getValue().toBytes(); | |||||
| } | } | ||||
| public byte[] getChainCode(long version) { | public byte[] getChainCode(long version) { | ||||
| return accBase.getBytes(CHAIN_CODE_KEY, version); | |||||
| return accBase.getBytes(CHAIN_CODE_KEY, version).getValue().toBytes(); | |||||
| } | } | ||||
| public long getChaincodeVersion() { | public long getChaincodeVersion() { | ||||
| @@ -58,15 +60,18 @@ public class ContractAccount implements AccountHeader { | |||||
| } | } | ||||
| public long setProperty(Bytes key, String value, long version) { | public long setProperty(Bytes key, String value, long version) { | ||||
| return accBase.setBytes(encodePropertyKey(key), BytesUtils.toBytes(value), version); | |||||
| BytesValue bytesValue = BytesValueEntry.fromText(value); | |||||
| return accBase.setBytes(encodePropertyKey(key), bytesValue, version); | |||||
| } | } | ||||
| public String getProperty(Bytes key) { | public String getProperty(Bytes key) { | ||||
| return BytesUtils.toString(accBase.getBytes(encodePropertyKey(key))); | |||||
| BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key)); | |||||
| return BytesValueEntry.toText(bytesValue); | |||||
| } | } | ||||
| public String getProperty(Bytes key, long version) { | public String getProperty(Bytes key, long version) { | ||||
| return BytesUtils.toString(accBase.getBytes(encodePropertyKey(key), version)); | |||||
| BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key), version); | |||||
| return BytesValueEntry.toText(bytesValue); | |||||
| } | } | ||||
| private Bytes encodePropertyKey(Bytes key) { | private Bytes encodePropertyKey(Bytes key) { | ||||
| @@ -5,6 +5,7 @@ import java.util.HashMap; | |||||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | import com.jd.blockchain.crypto.CryptoAlgorithm; | ||||
| import com.jd.blockchain.crypto.CryptoProvider; | import com.jd.blockchain.crypto.CryptoProvider; | ||||
| import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| public class CryptoConfig implements CryptoSetting { | public class CryptoConfig implements CryptoSetting { | ||||
| @@ -6,10 +6,10 @@ import com.jd.blockchain.crypto.HashDigest; | |||||
| import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
| import com.jd.blockchain.ledger.AccountHeader; | import com.jd.blockchain.ledger.AccountHeader; | ||||
| import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
| import com.jd.blockchain.ledger.BytesValueEntry; | |||||
| import com.jd.blockchain.ledger.KVDataEntry; | import com.jd.blockchain.ledger.KVDataEntry; | ||||
| import com.jd.blockchain.ledger.KVDataObject; | import com.jd.blockchain.ledger.KVDataObject; | ||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils; | |||||
| public class DataAccount implements AccountHeader, MerkleProvable { | public class DataAccount implements AccountHeader, MerkleProvable { | ||||
| @@ -41,10 +41,22 @@ public class DataAccount implements AccountHeader, MerkleProvable { | |||||
| public MerkleProof getProof(Bytes key) { | public MerkleProof getProof(Bytes key) { | ||||
| return baseAccount.getProof(key); | return baseAccount.getProof(key); | ||||
| } | } | ||||
| public long setBytes(Bytes key, byte[] value, long version) { | |||||
| public long setBytes(Bytes key, BytesValue value, long version) { | |||||
| return baseAccount.setBytes(key, value, version); | return baseAccount.setBytes(key, value, version); | ||||
| } | } | ||||
| public long setBytes(Bytes key, String value, long version) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromText(value); | |||||
| return baseAccount.setBytes(key, bytesValue, version); | |||||
| } | |||||
| public long setBytes(Bytes key, byte[] value, long version) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromBytes(value); | |||||
| return baseAccount.setBytes(key, bytesValue, version); | |||||
| } | |||||
| /** | /** | ||||
| * Return the latest version entry associated the specified key; If the key | * Return the latest version entry associated the specified key; If the key | ||||
| @@ -74,7 +86,7 @@ public class DataAccount implements AccountHeader, MerkleProvable { | |||||
| * @param key | * @param key | ||||
| * @return return null if not exist; | * @return return null if not exist; | ||||
| */ | */ | ||||
| public byte[] getBytes(String key) { | |||||
| public BytesValue getBytes(String key) { | |||||
| return baseAccount.getBytes(Bytes.fromString(key)); | return baseAccount.getBytes(Bytes.fromString(key)); | ||||
| } | } | ||||
| @@ -84,7 +96,7 @@ public class DataAccount implements AccountHeader, MerkleProvable { | |||||
| * @param key | * @param key | ||||
| * @return return null if not exist; | * @return return null if not exist; | ||||
| */ | */ | ||||
| public byte[] getBytes(Bytes key) { | |||||
| public BytesValue getBytes(Bytes key) { | |||||
| return baseAccount.getBytes(key); | return baseAccount.getBytes(key); | ||||
| } | } | ||||
| @@ -95,7 +107,7 @@ public class DataAccount implements AccountHeader, MerkleProvable { | |||||
| * @param version | * @param version | ||||
| * @return return null if not exist; | * @return return null if not exist; | ||||
| */ | */ | ||||
| public byte[] getBytes(String key, long version) { | |||||
| public BytesValue getBytes(String key, long version) { | |||||
| return baseAccount.getBytes(Bytes.fromString(key), version); | return baseAccount.getBytes(Bytes.fromString(key), version); | ||||
| } | } | ||||
| @@ -106,7 +118,7 @@ public class DataAccount implements AccountHeader, MerkleProvable { | |||||
| * @param version | * @param version | ||||
| * @return return null if not exist; | * @return return null if not exist; | ||||
| */ | */ | ||||
| public byte[] getBytes(Bytes key, long version) { | |||||
| public BytesValue getBytes(Bytes key, long version) { | |||||
| return baseAccount.getBytes(key, version); | return baseAccount.getBytes(key, version); | ||||
| } | } | ||||
| @@ -119,7 +131,6 @@ public class DataAccount implements AccountHeader, MerkleProvable { | |||||
| */ | */ | ||||
| public KVDataEntry[] getDataEntries(int fromIndex, int count) { | public KVDataEntry[] getDataEntries(int fromIndex, int count) { | ||||
| if (getDataEntriesTotalCount() == 0 || count == 0) { | if (getDataEntriesTotalCount() == 0 || count == 0) { | ||||
| return null; | return null; | ||||
| } | } | ||||
| @@ -142,7 +153,7 @@ public class DataAccount implements AccountHeader, MerkleProvable { | |||||
| key = baseAccount.dataset.getKeyAtIndex(fromIndex); | key = baseAccount.dataset.getKeyAtIndex(fromIndex); | ||||
| ver = baseAccount.dataset.getVersion(key); | ver = baseAccount.dataset.getVersion(key); | ||||
| BytesValue decodeData = BinaryProtocol.decode(value); | BytesValue decodeData = BinaryProtocol.decode(value); | ||||
| kvDataEntries[i] = new KVDataObject(key, ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes()); | |||||
| kvDataEntries[i] = new KVDataObject(key, ver, decodeData); | |||||
| fromIndex++; | fromIndex++; | ||||
| } | } | ||||
| @@ -162,5 +173,4 @@ public class DataAccount implements AccountHeader, MerkleProvable { | |||||
| } | } | ||||
| return baseAccount.dataset.getDataCount(); | return baseAccount.dataset.getDataCount(); | ||||
| } | } | ||||
| } | } | ||||
| @@ -10,6 +10,7 @@ import com.jd.blockchain.binaryproto.DataContractRegistry; | |||||
| import com.jd.blockchain.crypto.Crypto; | import com.jd.blockchain.crypto.Crypto; | ||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.crypto.HashFunction; | import com.jd.blockchain.crypto.HashFunction; | ||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| import com.jd.blockchain.ledger.LedgerInitSetting; | import com.jd.blockchain.ledger.LedgerInitSetting; | ||||
| import com.jd.blockchain.ledger.ParticipantNode; | import com.jd.blockchain.ledger.ParticipantNode; | ||||
| import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
| @@ -1,6 +1,7 @@ | |||||
| package com.jd.blockchain.ledger.core; | package com.jd.blockchain.ledger.core; | ||||
| import com.jd.blockchain.ledger.LedgerBlock; | import com.jd.blockchain.ledger.LedgerBlock; | ||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| import com.jd.blockchain.ledger.LedgerTransaction; | import com.jd.blockchain.ledger.LedgerTransaction; | ||||
| import com.jd.blockchain.ledger.TransactionRequest; | import com.jd.blockchain.ledger.TransactionRequest; | ||||
| @@ -1,6 +1,7 @@ | |||||
| package com.jd.blockchain.ledger.core; | package com.jd.blockchain.ledger.core; | ||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| /** | /** | ||||
| * 账本管理器; | * 账本管理器; | ||||
| @@ -2,6 +2,7 @@ package com.jd.blockchain.ledger.core; | |||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
| import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; | import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; | ||||
| import com.jd.blockchain.storage.service.VersioningKVEntry; | import com.jd.blockchain.storage.service.VersioningKVEntry; | ||||
| @@ -19,6 +19,7 @@ import com.jd.blockchain.crypto.Crypto; | |||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.crypto.HashFunction; | import com.jd.blockchain.crypto.HashFunction; | ||||
| import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
| import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; | import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; | ||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| @@ -5,6 +5,7 @@ import com.jd.blockchain.binaryproto.DataContractRegistry; | |||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.ledger.ParticipantNode; | import com.jd.blockchain.ledger.ParticipantNode; | ||||
| import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
| import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| @@ -0,0 +1,9 @@ | |||||
| package com.jd.blockchain.ledger.core; | |||||
| import java.util.SortedSet; | |||||
| public interface PermissionService { | |||||
| boolean checkLedgerPermission(); | |||||
| } | |||||
| @@ -1,11 +0,0 @@ | |||||
| package com.jd.blockchain.ledger.core; | |||||
| import java.util.SortedSet; | |||||
| public interface Privilege { | |||||
| SortedSet<Byte> getOpCodes(); | |||||
| long getVersion(); | |||||
| } | |||||
| @@ -4,6 +4,6 @@ public interface PrivilegeModelSetting { | |||||
| long getLatestVersion(); | long getLatestVersion(); | ||||
| Privilege getPrivilege(long version); | |||||
| PermissionService getPrivilege(long version); | |||||
| } | } | ||||
| @@ -4,6 +4,7 @@ import com.jd.blockchain.binaryproto.BinaryProtocol; | |||||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | import com.jd.blockchain.binaryproto.DataContractRegistry; | ||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| import com.jd.blockchain.ledger.LedgerTransaction; | import com.jd.blockchain.ledger.LedgerTransaction; | ||||
| import com.jd.blockchain.ledger.TransactionState; | import com.jd.blockchain.ledger.TransactionState; | ||||
| import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
| @@ -2,9 +2,10 @@ package com.jd.blockchain.ledger.core; | |||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
| import com.jd.blockchain.ledger.BytesValue; | |||||
| import com.jd.blockchain.ledger.BytesValueEntry; | |||||
| import com.jd.blockchain.ledger.UserInfo; | import com.jd.blockchain.ledger.UserInfo; | ||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| import com.jd.blockchain.utils.io.BytesUtils; | |||||
| /** | /** | ||||
| * 用户账户; | * 用户账户; | ||||
| @@ -40,21 +41,21 @@ public class UserAccount implements UserInfo { | |||||
| } | } | ||||
| public PubKey getDataPubKey() { | public PubKey getDataPubKey() { | ||||
| byte[] pkBytes = baseAccount.getBytes(DATA_PUB_KEY); | |||||
| BytesValue pkBytes = baseAccount.getBytes(DATA_PUB_KEY); | |||||
| if (pkBytes == null) { | if (pkBytes == null) { | ||||
| return null; | return null; | ||||
| } | } | ||||
| return new PubKey(pkBytes); | |||||
| return new PubKey(pkBytes.getValue().toBytes()); | |||||
| } | } | ||||
| public long setDataPubKey(PubKey pubKey) { | public long setDataPubKey(PubKey pubKey) { | ||||
| byte[] pkBytes = pubKey.toBytes(); | byte[] pkBytes = pubKey.toBytes(); | ||||
| return baseAccount.setBytes(DATA_PUB_KEY, pkBytes, -1); | |||||
| return baseAccount.setBytes(DATA_PUB_KEY, BytesValueEntry.fromBytes(pkBytes), -1); | |||||
| } | } | ||||
| public long setDataPubKey(PubKey pubKey, long version) { | public long setDataPubKey(PubKey pubKey, long version) { | ||||
| byte[] pkBytes = pubKey.toBytes(); | byte[] pkBytes = pubKey.toBytes(); | ||||
| return baseAccount.setBytes(DATA_PUB_KEY, pkBytes, version); | |||||
| return baseAccount.setBytes(DATA_PUB_KEY, BytesValueEntry.fromBytes(pkBytes), version); | |||||
| } | } | ||||
| public long setProperty(String key, String value, long version) { | public long setProperty(String key, String value, long version) { | ||||
| @@ -62,15 +63,17 @@ public class UserAccount implements UserInfo { | |||||
| } | } | ||||
| public long setProperty(Bytes key, String value, long version) { | public long setProperty(Bytes key, String value, long version) { | ||||
| return baseAccount.setBytes(encodePropertyKey(key), BytesUtils.toBytes(value), version); | |||||
| return baseAccount.setBytes(encodePropertyKey(key), BytesValueEntry.fromText(value), version); | |||||
| } | } | ||||
| public String getProperty(Bytes key) { | public String getProperty(Bytes key) { | ||||
| return BytesUtils.toString(baseAccount.getBytes(encodePropertyKey(key))); | |||||
| BytesValue value = baseAccount.getBytes(encodePropertyKey(key)); | |||||
| return value == null ? null : value.getValue().toUTF8String(); | |||||
| } | } | ||||
| public String getProperty(Bytes key, long version) { | public String getProperty(Bytes key, long version) { | ||||
| return BytesUtils.toString(baseAccount.getBytes(encodePropertyKey(key), version)); | |||||
| BytesValue value = baseAccount.getBytes(encodePropertyKey(key), version); | |||||
| return value == null ? null : value.getValue().toUTF8String(); | |||||
| } | } | ||||
| private Bytes encodePropertyKey(Bytes key) { | private Bytes encodePropertyKey(Bytes key) { | ||||
| @@ -4,6 +4,7 @@ import com.jd.blockchain.crypto.HashDigest; | |||||
| import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
| import com.jd.blockchain.ledger.AccountHeader; | import com.jd.blockchain.ledger.AccountHeader; | ||||
| import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
| import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| @@ -8,8 +8,8 @@ import javax.annotation.PostConstruct; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| import com.jd.blockchain.ledger.UserRegisterOperation; | import com.jd.blockchain.ledger.UserRegisterOperation; | ||||
| import com.jd.blockchain.ledger.core.LedgerException; | |||||
| import com.jd.blockchain.ledger.core.OperationHandle; | import com.jd.blockchain.ledger.core.OperationHandle; | ||||
| import com.jd.blockchain.ledger.core.impl.handles.ContractCodeDeployOperationHandle; | import com.jd.blockchain.ledger.core.impl.handles.ContractCodeDeployOperationHandle; | ||||
| import com.jd.blockchain.ledger.core.impl.handles.ContractEventSendOperationHandle; | import com.jd.blockchain.ledger.core.impl.handles.ContractEventSendOperationHandle; | ||||
| @@ -8,10 +8,10 @@ import com.jd.blockchain.crypto.CryptoAlgorithm; | |||||
| import com.jd.blockchain.crypto.CryptoProvider; | import com.jd.blockchain.crypto.CryptoProvider; | ||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| import com.jd.blockchain.ledger.LedgerInitSetting; | import com.jd.blockchain.ledger.LedgerInitSetting; | ||||
| import com.jd.blockchain.ledger.core.LedgerConsts; | import com.jd.blockchain.ledger.core.LedgerConsts; | ||||
| import com.jd.blockchain.ledger.core.LedgerEditor; | import com.jd.blockchain.ledger.core.LedgerEditor; | ||||
| import com.jd.blockchain.ledger.core.LedgerException; | |||||
| import com.jd.blockchain.ledger.core.LedgerManage; | import com.jd.blockchain.ledger.core.LedgerManage; | ||||
| import com.jd.blockchain.ledger.core.LedgerRepository; | import com.jd.blockchain.ledger.core.LedgerRepository; | ||||
| import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
| @@ -1,10 +1,23 @@ | |||||
| package com.jd.blockchain.ledger.core.impl; | package com.jd.blockchain.ledger.core.impl; | ||||
| import com.jd.blockchain.binaryproto.BinaryProtocol; | |||||
| import com.jd.blockchain.binaryproto.PrimitiveType; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| import com.jd.blockchain.contract.ContractException; | import com.jd.blockchain.contract.ContractException; | ||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.ledger.*; | |||||
| import com.jd.blockchain.ledger.AccountHeader; | |||||
| import com.jd.blockchain.ledger.BytesValue; | |||||
| import com.jd.blockchain.ledger.KVDataEntry; | |||||
| import com.jd.blockchain.ledger.KVDataObject; | |||||
| import com.jd.blockchain.ledger.KVDataVO; | |||||
| import com.jd.blockchain.ledger.KVInfoVO; | |||||
| 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.UserInfo; | |||||
| import com.jd.blockchain.ledger.core.ContractAccountSet; | import com.jd.blockchain.ledger.core.ContractAccountSet; | ||||
| import com.jd.blockchain.ledger.core.DataAccount; | import com.jd.blockchain.ledger.core.DataAccount; | ||||
| import com.jd.blockchain.ledger.core.DataAccountSet; | import com.jd.blockchain.ledger.core.DataAccountSet; | ||||
| @@ -16,16 +29,12 @@ import com.jd.blockchain.ledger.core.UserAccountSet; | |||||
| import com.jd.blockchain.transaction.BlockchainQueryService; | import com.jd.blockchain.transaction.BlockchainQueryService; | ||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| import com.jd.blockchain.utils.QueryUtil; | import com.jd.blockchain.utils.QueryUtil; | ||||
| import com.jd.blockchain.utils.StringUtils; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| public class LedgerQueryService implements BlockchainQueryService { | public class LedgerQueryService implements BlockchainQueryService { | ||||
| private LedgerService ledgerService; | |||||
| public LedgerQueryService(LedgerService ledgerService) { | |||||
| private LedgerService ledgerService; | |||||
| public LedgerQueryService(LedgerService ledgerService) { | |||||
| this.ledgerService = ledgerService; | this.ledgerService = ledgerService; | ||||
| } | } | ||||
| @@ -37,7 +46,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
| @Override | @Override | ||||
| public LedgerInfo getLedger(HashDigest ledgerHash) { | public LedgerInfo getLedger(HashDigest ledgerHash) { | ||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerInfo ledgerInfo =new LedgerInfo(); | |||||
| LedgerInfo ledgerInfo = new LedgerInfo(); | |||||
| ledgerInfo.setHash(ledger.getHash()); | ledgerInfo.setHash(ledger.getHash()); | ||||
| ledgerInfo.setLatestBlockHash(ledger.getLatestBlockHash()); | ledgerInfo.setLatestBlockHash(ledger.getLatestBlockHash()); | ||||
| ledgerInfo.setLatestBlockHeight(ledger.getLatestBlockHeight()); | ledgerInfo.setLatestBlockHeight(ledger.getLatestBlockHeight()); | ||||
| @@ -173,8 +182,8 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
| lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height - 1)).getTotalCount(); | lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height - 1)).getTotalCount(); | ||||
| } | } | ||||
| int currentHeightTxTotalNums = (int)ledger.getTransactionSet(ledger.getBlock(height)).getTotalCount(); | |||||
| //取当前高度的增量交易数,在增量交易里进行查找 | |||||
| int currentHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height)).getTotalCount(); | |||||
| // 取当前高度的增量交易数,在增量交易里进行查找 | |||||
| int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; | int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; | ||||
| // | // | ||||
| // if (fromIndex < 0 || fromIndex >= currentHeightTxNums) { | // if (fromIndex < 0 || fromIndex >= currentHeightTxNums) { | ||||
| @@ -187,8 +196,8 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
| // if (count > currentHeightTxNums) { | // if (count > currentHeightTxNums) { | ||||
| // count = currentHeightTxNums - fromIndex; | // count = currentHeightTxNums - fromIndex; | ||||
| // } | // } | ||||
| int indexAndCount [] = QueryUtil.calFromIndexAndCount(fromIndex,count,currentHeightTxNums); | |||||
| return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0] , indexAndCount[1]); | |||||
| int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex, count, currentHeightTxNums); | |||||
| return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0], indexAndCount[1]); | |||||
| } | } | ||||
| @Override | @Override | ||||
| @@ -203,8 +212,8 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
| lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height - 1)).getTotalCount(); | lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height - 1)).getTotalCount(); | ||||
| } | } | ||||
| int currentHeightTxTotalNums = (int)ledger.getTransactionSet(ledger.getBlock(height)).getTotalCount(); | |||||
| //取当前块hash的增量交易数,在增量交易里进行查找 | |||||
| int currentHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height)).getTotalCount(); | |||||
| // 取当前块hash的增量交易数,在增量交易里进行查找 | |||||
| int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; | int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; | ||||
| // if (fromIndex < 0 || fromIndex >= currentHeightTxNums) { | // if (fromIndex < 0 || fromIndex >= currentHeightTxNums) { | ||||
| @@ -217,8 +226,8 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
| // if (count > currentHeightTxNums) { | // if (count > currentHeightTxNums) { | ||||
| // count = currentHeightTxNums - fromIndex; | // count = currentHeightTxNums - fromIndex; | ||||
| // } | // } | ||||
| int indexAndCount [] = QueryUtil.calFromIndexAndCount(fromIndex,count,currentHeightTxNums); | |||||
| return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0] , indexAndCount[1]); | |||||
| int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex, count, currentHeightTxNums); | |||||
| return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0], indexAndCount[1]); | |||||
| } | } | ||||
| @Override | @Override | ||||
| @@ -228,7 +237,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
| TransactionSet txset = ledger.getTransactionSet(block); | TransactionSet txset = ledger.getTransactionSet(block); | ||||
| return txset.get(contentHash); | return txset.get(contentHash); | ||||
| } | } | ||||
| @Override | @Override | ||||
| public TransactionState getTransactionStateByContentHash(HashDigest ledgerHash, HashDigest contentHash) { | public TransactionState getTransactionStateByContentHash(HashDigest ledgerHash, HashDigest contentHash) { | ||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| @@ -243,7 +252,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | ||||
| return userAccountSet.getUser(address); | return userAccountSet.getUser(address); | ||||
| } | } | ||||
| @Override | @Override | ||||
| @@ -263,33 +272,32 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | ||||
| DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | ||||
| KVDataEntry[] entries = new KVDataEntry[keys.length]; | KVDataEntry[] entries = new KVDataEntry[keys.length]; | ||||
| long ver; | long ver; | ||||
| for (int i = 0; i < entries.length; i++) { | for (int i = 0; i < entries.length; i++) { | ||||
| ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); | ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); | ||||
| dataAccount.getBytes(Bytes.fromString(keys[i]),1); | |||||
| dataAccount.getBytes(Bytes.fromString(keys[i]), 1); | |||||
| if (ver < 0) { | if (ver < 0) { | ||||
| entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); | |||||
| }else { | |||||
| byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); | |||||
| BytesValue decodeData = BinaryProtocol.decode(value); | |||||
| entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes()); | |||||
| entries[i] = new KVDataObject(keys[i], -1, null); | |||||
| } else { | |||||
| BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); | |||||
| entries[i] = new KVDataObject(keys[i], ver, value); | |||||
| } | } | ||||
| } | } | ||||
| return entries; | return entries; | ||||
| } | } | ||||
| public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) { | public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) { | ||||
| //parse kvInfoVO; | |||||
| // parse kvInfoVO; | |||||
| List<String> keyList = new ArrayList<>(); | List<String> keyList = new ArrayList<>(); | ||||
| List<Long> versionList = new ArrayList<>(); | List<Long> versionList = new ArrayList<>(); | ||||
| if(kvInfoVO != null){ | |||||
| for(KVDataVO kvDataVO : kvInfoVO.getData()){ | |||||
| for(Long version : kvDataVO.getVersion()){ | |||||
| if (kvInfoVO != null) { | |||||
| for (KVDataVO kvDataVO : kvInfoVO.getData()) { | |||||
| for (Long version : kvDataVO.getVersion()) { | |||||
| keyList.add(kvDataVO.getKey()); | keyList.add(kvDataVO.getKey()); | ||||
| versionList.add(version); | versionList.add(version); | ||||
| } | } | ||||
| @@ -301,12 +309,12 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
| if (keys == null || keys.length == 0) { | if (keys == null || keys.length == 0) { | ||||
| return null; | return null; | ||||
| } | } | ||||
| if (versions == null || versions.length == 0) { | |||||
| return null; | |||||
| } | |||||
| if(keys.length != versions.length){ | |||||
| throw new ContractException("keys.length!=versions.length!"); | |||||
| } | |||||
| if (versions == null || versions.length == 0) { | |||||
| return null; | |||||
| } | |||||
| if (keys.length != versions.length) { | |||||
| throw new ContractException("keys.length!=versions.length!"); | |||||
| } | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| @@ -314,22 +322,21 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
| DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | ||||
| KVDataEntry[] entries = new KVDataEntry[keys.length]; | KVDataEntry[] entries = new KVDataEntry[keys.length]; | ||||
| long ver = -1; | |||||
| long ver = -1; | |||||
| for (int i = 0; i < entries.length; i++) { | for (int i = 0; i < entries.length; i++) { | ||||
| // ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); | // ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); | ||||
| // dataAccount.getBytes(Bytes.fromString(keys[i]),1); | // dataAccount.getBytes(Bytes.fromString(keys[i]),1); | ||||
| ver = versions[i]; | ver = versions[i]; | ||||
| if (ver < 0) { | if (ver < 0) { | ||||
| entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); | |||||
| }else { | |||||
| if(dataAccount.getDataEntriesTotalCount()==0 || | |||||
| dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null){ | |||||
| //is the address is not exist; the result is null; | |||||
| entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); | |||||
| entries[i] = new KVDataObject(keys[i], -1, null); | |||||
| } else { | |||||
| if (dataAccount.getDataEntriesTotalCount() == 0 | |||||
| || dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null) { | |||||
| // is the address is not exist; the result is null; | |||||
| entries[i] = new KVDataObject(keys[i], -1, null); | |||||
| } else { | } else { | ||||
| byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); | |||||
| BytesValue decodeData = BinaryProtocol.decode(value); | |||||
| entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes()); | |||||
| BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); | |||||
| entries[i] = new KVDataObject(keys[i], ver, value); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -381,8 +388,8 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | ||||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex,count,(int)dataAccountSet.getTotalCount()); | |||||
| return dataAccountSet.getAccounts(pages[0],pages[1]); | |||||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotalCount()); | |||||
| return dataAccountSet.getAccounts(pages[0], pages[1]); | |||||
| } | } | ||||
| @Override | @Override | ||||
| @@ -390,8 +397,8 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | ||||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex,count,(int)contractAccountSet.getTotalCount()); | |||||
| return contractAccountSet.getAccounts(pages[0],pages[1]); | |||||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) contractAccountSet.getTotalCount()); | |||||
| return contractAccountSet.getAccounts(pages[0], pages[1]); | |||||
| } | } | ||||
| private LedgerAdministration ledgerAdministration(HashDigest ledgerHash) { | private LedgerAdministration ledgerAdministration(HashDigest ledgerHash) { | ||||
| @@ -13,7 +13,6 @@ import com.jd.blockchain.ledger.core.LedgerAdministration; | |||||
| import com.jd.blockchain.ledger.core.LedgerConsts; | import com.jd.blockchain.ledger.core.LedgerConsts; | ||||
| import com.jd.blockchain.ledger.core.LedgerDataSet; | import com.jd.blockchain.ledger.core.LedgerDataSet; | ||||
| import com.jd.blockchain.ledger.core.LedgerEditor; | import com.jd.blockchain.ledger.core.LedgerEditor; | ||||
| import com.jd.blockchain.ledger.core.LedgerException; | |||||
| import com.jd.blockchain.ledger.core.LedgerRepository; | import com.jd.blockchain.ledger.core.LedgerRepository; | ||||
| import com.jd.blockchain.ledger.core.LedgerTransactionContext; | import com.jd.blockchain.ledger.core.LedgerTransactionContext; | ||||
| import com.jd.blockchain.ledger.core.TransactionSet; | import com.jd.blockchain.ledger.core.TransactionSet; | ||||
| @@ -16,7 +16,7 @@ import com.jd.blockchain.utils.Bytes; | |||||
| public class OpeningAccessPolicy implements AccountAccessPolicy { | public class OpeningAccessPolicy implements AccountAccessPolicy { | ||||
| @Override | @Override | ||||
| public boolean checkCommitting(AccountHeader account) { | |||||
| public boolean checkDataWriting(AccountHeader account) { | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -9,13 +9,13 @@ import org.slf4j.LoggerFactory; | |||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.ledger.LedgerBlock; | import com.jd.blockchain.ledger.LedgerBlock; | ||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| import com.jd.blockchain.ledger.Operation; | import com.jd.blockchain.ledger.Operation; | ||||
| import com.jd.blockchain.ledger.TransactionRequest; | import com.jd.blockchain.ledger.TransactionRequest; | ||||
| import com.jd.blockchain.ledger.TransactionResponse; | import com.jd.blockchain.ledger.TransactionResponse; | ||||
| import com.jd.blockchain.ledger.TransactionState; | import com.jd.blockchain.ledger.TransactionState; | ||||
| import com.jd.blockchain.ledger.core.LedgerDataSet; | import com.jd.blockchain.ledger.core.LedgerDataSet; | ||||
| import com.jd.blockchain.ledger.core.LedgerEditor; | import com.jd.blockchain.ledger.core.LedgerEditor; | ||||
| import com.jd.blockchain.ledger.core.LedgerException; | |||||
| import com.jd.blockchain.ledger.core.LedgerService; | import com.jd.blockchain.ledger.core.LedgerService; | ||||
| import com.jd.blockchain.ledger.core.LedgerTransactionContext; | import com.jd.blockchain.ledger.core.LedgerTransactionContext; | ||||
| import com.jd.blockchain.ledger.core.OperationHandle; | import com.jd.blockchain.ledger.core.OperationHandle; | ||||
| @@ -9,11 +9,11 @@ import com.jd.blockchain.contract.engine.ContractCode; | |||||
| import com.jd.blockchain.contract.engine.ContractEngine; | import com.jd.blockchain.contract.engine.ContractEngine; | ||||
| import com.jd.blockchain.contract.engine.ContractServiceProviders; | import com.jd.blockchain.contract.engine.ContractServiceProviders; | ||||
| import com.jd.blockchain.ledger.ContractEventSendOperation; | import com.jd.blockchain.ledger.ContractEventSendOperation; | ||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| import com.jd.blockchain.ledger.Operation; | import com.jd.blockchain.ledger.Operation; | ||||
| import com.jd.blockchain.ledger.core.ContractAccount; | import com.jd.blockchain.ledger.core.ContractAccount; | ||||
| import com.jd.blockchain.ledger.core.ContractAccountSet; | import com.jd.blockchain.ledger.core.ContractAccountSet; | ||||
| import com.jd.blockchain.ledger.core.LedgerDataSet; | import com.jd.blockchain.ledger.core.LedgerDataSet; | ||||
| import com.jd.blockchain.ledger.core.LedgerException; | |||||
| import com.jd.blockchain.ledger.core.LedgerService; | import com.jd.blockchain.ledger.core.LedgerService; | ||||
| import com.jd.blockchain.ledger.core.OperationHandle; | import com.jd.blockchain.ledger.core.OperationHandle; | ||||
| import com.jd.blockchain.ledger.core.TransactionRequestContext; | import com.jd.blockchain.ledger.core.TransactionRequestContext; | ||||
| @@ -3,10 +3,25 @@ package com.jd.blockchain.ledger.core.impl.handles; | |||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.List; | import java.util.List; | ||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.jd.blockchain.contract.LedgerContext; | import com.jd.blockchain.contract.LedgerContext; | ||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.ledger.*; | |||||
| import com.jd.blockchain.ledger.AccountHeader; | |||||
| import com.jd.blockchain.ledger.BlockchainIdentity; | |||||
| import com.jd.blockchain.ledger.BytesValue; | |||||
| import com.jd.blockchain.ledger.BytesValueEntry; | |||||
| import com.jd.blockchain.ledger.DataAccountKVSetOperation; | |||||
| import com.jd.blockchain.ledger.DataAccountRegisterOperation; | |||||
| import com.jd.blockchain.ledger.KVDataEntry; | |||||
| import com.jd.blockchain.ledger.KVInfoVO; | |||||
| 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.UserInfo; | |||||
| import com.jd.blockchain.ledger.UserRegisterOperation; | |||||
| import com.jd.blockchain.ledger.core.impl.OperationHandleContext; | import com.jd.blockchain.ledger.core.impl.OperationHandleContext; | ||||
| import com.jd.blockchain.transaction.BlockchainQueryService; | import com.jd.blockchain.transaction.BlockchainQueryService; | ||||
| import com.jd.blockchain.transaction.DataAccountKVSetOperationBuilder; | import com.jd.blockchain.transaction.DataAccountKVSetOperationBuilder; | ||||
| @@ -16,7 +31,6 @@ import com.jd.blockchain.transaction.KVData; | |||||
| import com.jd.blockchain.transaction.UserRegisterOperationBuilder; | import com.jd.blockchain.transaction.UserRegisterOperationBuilder; | ||||
| import com.jd.blockchain.transaction.UserRegisterOperationBuilderImpl; | import com.jd.blockchain.transaction.UserRegisterOperationBuilderImpl; | ||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| import com.jd.blockchain.utils.io.BytesUtils; | |||||
| public class ContractLedgerContext implements LedgerContext { | public class ContractLedgerContext implements LedgerContext { | ||||
| @@ -250,60 +264,95 @@ public class ContractLedgerContext implements LedgerContext { | |||||
| this.accountAddress = accountAddress; | this.accountAddress = accountAddress; | ||||
| } | } | ||||
| public boolean isJson(String str) { | |||||
| boolean result = false; | |||||
| try { | |||||
| Object obj = JSON.parse(str); | |||||
| result = true; | |||||
| } catch (Exception e) { | |||||
| result = false; | |||||
| } | |||||
| return result; | |||||
| } | |||||
| @Override | @Override | ||||
| public DataAccountKVSetOperation getOperation() { | public DataAccountKVSetOperation getOperation() { | ||||
| return op; | return op; | ||||
| } | } | ||||
| // @Override | |||||
| // public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) { | |||||
| // BytesValue bytesValue = BytesValueEntry.fromBytes(value); | |||||
| // this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | |||||
| // handle(op); | |||||
| // return this; | |||||
| // } | |||||
| @Override | @Override | ||||
| public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) { | |||||
| BytesValue bytesValue = new BytesValueEntry(BytesValueType.BYTES, value); | |||||
| public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromText(value); | |||||
| this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | ||||
| generatedOpList.add(op); | |||||
| opHandleContext.handle(op); | |||||
| handle(op); | |||||
| return this; | return this; | ||||
| } | } | ||||
| @Override | @Override | ||||
| public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) { | |||||
| BytesValue bytesValue; | |||||
| if (isJson(value)) { | |||||
| public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromBytes(value); | |||||
| this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | |||||
| handle(op); | |||||
| return this; | |||||
| } | |||||
| bytesValue = new BytesValueEntry(BytesValueType.JSON, BytesUtils.toBytes(value)); | |||||
| } | |||||
| else { | |||||
| bytesValue = new BytesValueEntry(BytesValueType.TEXT, BytesUtils.toBytes(value)); | |||||
| } | |||||
| @Override | |||||
| public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromInt64(value); | |||||
| this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | ||||
| generatedOpList.add(op); | |||||
| opHandleContext.handle(op); | |||||
| handle(op); | |||||
| return this; | return this; | ||||
| } | } | ||||
| // @Deprecated | |||||
| // @Override | |||||
| // public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) { | |||||
| // BytesValue bytesValue = BytesValueEntry.fromText(value); | |||||
| // this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | |||||
| // handle(op); | |||||
| // return this; | |||||
| // } | |||||
| @Override | @Override | ||||
| public DataAccountKVSetOperationBuilder set(String key, Bytes value, long expVersion) { | |||||
| BytesValue bytesValue = new BytesValueEntry(BytesValueType.BYTES, value.toBytes()); | |||||
| public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromJSON(value); | |||||
| this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | ||||
| generatedOpList.add(op); | |||||
| opHandleContext.handle(op); | |||||
| handle(op); | |||||
| return this; | |||||
| } | |||||
| @Override | |||||
| public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromXML(value); | |||||
| this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | |||||
| handle(op); | |||||
| return this; | |||||
| } | |||||
| @Override | |||||
| public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromBytes(value); | |||||
| this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | |||||
| handle(op); | |||||
| return this; | |||||
| } | |||||
| @Override | |||||
| public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromImage(value); | |||||
| this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | |||||
| handle(op); | |||||
| return this; | return this; | ||||
| } | } | ||||
| @Override | @Override | ||||
| public DataAccountKVSetOperationBuilder set(String key, long value, long expVersion) { | |||||
| BytesValue bytesValue = new BytesValueEntry(BytesValueType.INT64, BytesUtils.toBytes(value)); | |||||
| public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromTimestamp(value); | |||||
| this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | ||||
| handle(op); | |||||
| return this; | |||||
| } | |||||
| private void handle(Operation op) { | |||||
| generatedOpList.add(op); | generatedOpList.add(op); | ||||
| opHandleContext.handle(op); | opHandleContext.handle(op); | ||||
| return this; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -24,8 +24,7 @@ public class DataAccountKVSetOperationHandle implements OperationHandle{ | |||||
| DataAccount account = dataset.getDataAccountSet().getDataAccount(kvWriteOp.getAccountAddress()); | DataAccount account = dataset.getDataAccountSet().getDataAccount(kvWriteOp.getAccountAddress()); | ||||
| KVWriteEntry[] writeset = kvWriteOp.getWriteSet(); | KVWriteEntry[] writeset = kvWriteOp.getWriteSet(); | ||||
| for (KVWriteEntry kvw : writeset) { | for (KVWriteEntry kvw : writeset) { | ||||
| byte[] value = BinaryProtocol.encode(kvw.getValue(), BytesValue.class); | |||||
| account.setBytes(Bytes.fromString(kvw.getKey()), value, kvw.getExpectedVersion()); | |||||
| account.setBytes(Bytes.fromString(kvw.getKey()), kvw.getValue(), kvw.getExpectedVersion()); | |||||
| } | } | ||||
| } | } | ||||
| @@ -12,12 +12,11 @@ import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; | |||||
| import com.jd.blockchain.crypto.service.sm.SMCryptoService; | import com.jd.blockchain.crypto.service.sm.SMCryptoService; | ||||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | import com.jd.blockchain.ledger.BlockchainKeyGenerator; | ||||
| import com.jd.blockchain.ledger.BlockchainKeypair; | import com.jd.blockchain.ledger.BlockchainKeypair; | ||||
| import com.jd.blockchain.ledger.BytesValueEntry; | |||||
| import com.jd.blockchain.ledger.core.BaseAccount; | import com.jd.blockchain.ledger.core.BaseAccount; | ||||
| import com.jd.blockchain.ledger.core.CryptoConfig; | import com.jd.blockchain.ledger.core.CryptoConfig; | ||||
| import com.jd.blockchain.ledger.core.impl.OpeningAccessPolicy; | |||||
| import com.jd.blockchain.storage.service.utils.MemoryKVStorage; | import com.jd.blockchain.storage.service.utils.MemoryKVStorage; | ||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| import com.jd.blockchain.utils.io.BytesUtils; | |||||
| /** | /** | ||||
| * | * | ||||
| @@ -44,44 +43,43 @@ public class BaseAccountTest { | |||||
| cryptoConf.setAutoVerifyHash(true); | cryptoConf.setAutoVerifyHash(true); | ||||
| cryptoConf.setHashAlgorithm(ClassicAlgorithm.SHA256); | cryptoConf.setHashAlgorithm(ClassicAlgorithm.SHA256); | ||||
| OpeningAccessPolicy accPlc = new OpeningAccessPolicy(); | |||||
| // OpeningAccessPolicy accPlc = new OpeningAccessPolicy(); | |||||
| BlockchainKeypair bck = BlockchainKeyGenerator.getInstance().generate(); | BlockchainKeypair bck = BlockchainKeyGenerator.getInstance().generate(); | ||||
| // 新建账户; | // 新建账户; | ||||
| BaseAccount baseAccount = new BaseAccount(bck.getIdentity(), cryptoConf, keyPrefix, testStorage, testStorage, | |||||
| accPlc); | |||||
| BaseAccount baseAccount = new BaseAccount(bck.getIdentity(), cryptoConf, keyPrefix, testStorage, testStorage); | |||||
| assertFalse(baseAccount.isUpdated());// 空的账户; | assertFalse(baseAccount.isUpdated());// 空的账户; | ||||
| assertFalse(baseAccount.isReadonly()); | assertFalse(baseAccount.isReadonly()); | ||||
| // 在空白状态下写入数据; | // 在空白状态下写入数据; | ||||
| long v = baseAccount.setBytes(Bytes.fromString("A"), BytesUtils.toBytes("VALUE_A"), 0); | |||||
| long v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A"), 0); | |||||
| // 预期失败; | // 预期失败; | ||||
| assertEquals(-1, v); | assertEquals(-1, v); | ||||
| v = baseAccount.setBytes(Bytes.fromString("A"), BytesUtils.toBytes("VALUE_A"), 1); | |||||
| v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A"), 1); | |||||
| // 预期失败; | // 预期失败; | ||||
| assertEquals(-1, v); | assertEquals(-1, v); | ||||
| v = baseAccount.setBytes(Bytes.fromString("A"), BytesUtils.toBytes("VALUE_A"), -1); | |||||
| v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A"), -1); | |||||
| // 预期成功; | // 预期成功; | ||||
| assertEquals(0, v); | assertEquals(0, v); | ||||
| v = baseAccount.setBytes(Bytes.fromString("A"), BytesUtils.toBytes("VALUE_A-1"), -1); | |||||
| v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A-1"), -1); | |||||
| // 已经存在版本,指定版本号-1,预期导致失败; | // 已经存在版本,指定版本号-1,预期导致失败; | ||||
| assertEquals(-1, v); | assertEquals(-1, v); | ||||
| baseAccount.commit(); | baseAccount.commit(); | ||||
| v = 0; | v = 0; | ||||
| for (int i = 0; i < 10; i++) { | for (int i = 0; i < 10; i++) { | ||||
| long s = baseAccount.setBytes(Bytes.fromString("A"), BytesUtils.toBytes("VALUE_A_" + i), v); | |||||
| long s = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A_" + i), v); | |||||
| baseAccount.commit(); | baseAccount.commit(); | ||||
| // 预期成功; | // 预期成功; | ||||
| assertEquals(v + 1, s); | assertEquals(v + 1, s); | ||||
| v++; | v++; | ||||
| } | } | ||||
| v = baseAccount.setBytes(Bytes.fromString("A"), BytesUtils.toBytes("VALUE_A_" + v), v + 1); | |||||
| v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A_" + v), v + 1); | |||||
| // 预期成功; | // 预期成功; | ||||
| assertEquals(-1, v); | assertEquals(-1, v); | ||||
| @@ -1,10 +1,10 @@ | |||||
| package test.com.jd.blockchain.ledger; | package test.com.jd.blockchain.ledger; | ||||
| import static org.junit.Assert.assertArrayEquals; | |||||
| import static org.junit.Assert.assertEquals; | import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertNotNull; | import static org.junit.Assert.assertNotNull; | ||||
| import static org.junit.Assert.assertNull; | import static org.junit.Assert.assertNull; | ||||
| import org.junit.Before; | |||||
| import org.junit.Test; | import org.junit.Test; | ||||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | import com.jd.blockchain.binaryproto.DataContractRegistry; | ||||
| @@ -17,6 +17,8 @@ import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; | |||||
| import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; | import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; | ||||
| import com.jd.blockchain.crypto.service.sm.SMCryptoService; | import com.jd.blockchain.crypto.service.sm.SMCryptoService; | ||||
| import com.jd.blockchain.ledger.BlockchainKeypair; | import com.jd.blockchain.ledger.BlockchainKeypair; | ||||
| import com.jd.blockchain.ledger.BytesValue; | |||||
| import com.jd.blockchain.ledger.BytesValueType; | |||||
| import com.jd.blockchain.ledger.LedgerBlock; | import com.jd.blockchain.ledger.LedgerBlock; | ||||
| import com.jd.blockchain.ledger.LedgerInitSetting; | import com.jd.blockchain.ledger.LedgerInitSetting; | ||||
| import com.jd.blockchain.ledger.LedgerTransaction; | import com.jd.blockchain.ledger.LedgerTransaction; | ||||
| @@ -37,67 +39,99 @@ import com.jd.blockchain.utils.io.BytesUtils; | |||||
| import com.jd.blockchain.utils.net.NetworkAddress; | import com.jd.blockchain.utils.net.NetworkAddress; | ||||
| public class LedgerEditerTest { | public class LedgerEditerTest { | ||||
| private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), | private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), | ||||
| SMCryptoService.class.getName() }; | SMCryptoService.class.getName() }; | ||||
| static { | static { | ||||
| DataContractRegistry.register(com.jd.blockchain.ledger.TransactionContent.class); | DataContractRegistry.register(com.jd.blockchain.ledger.TransactionContent.class); | ||||
| DataContractRegistry.register(com.jd.blockchain.ledger.UserRegisterOperation.class); | DataContractRegistry.register(com.jd.blockchain.ledger.UserRegisterOperation.class); | ||||
| DataContractRegistry.register(com.jd.blockchain.ledger.BlockBody.class); | DataContractRegistry.register(com.jd.blockchain.ledger.BlockBody.class); | ||||
| } | } | ||||
| String ledgerKeyPrefix = "LDG://"; | |||||
| SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||||
| private static final String LEDGER_KEY_PREFIX = "LDG://"; | |||||
| private SignatureFunction signatureFunction; | |||||
| // 存储; | |||||
| MemoryKVStorage storage = new MemoryKVStorage(); | |||||
| /** | |||||
| * 初始化一个; | |||||
| */ | |||||
| @Before | |||||
| public void beforeTest() { | |||||
| signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||||
| } | |||||
| TransactionRequest genesisTxReq = LedgerTestUtils.createTxRequest(null, signatureFunction); | |||||
| /** | |||||
| * @return | |||||
| */ | |||||
| private LedgerEditor createLedgerInitEditor() { | |||||
| // 存储; | |||||
| MemoryKVStorage storage = new MemoryKVStorage(); | |||||
| // 创建初始化配置; | |||||
| LedgerInitSetting initSetting = createLedgerInitSetting(); | |||||
| // 创建初始化配置; | |||||
| LedgerInitSetting initSetting = createLedgerInitSetting(); | |||||
| // 创建账本; | |||||
| LedgerEditor ldgEdt = LedgerTransactionalEditor.createEditor(initSetting, ledgerKeyPrefix, storage, storage); | |||||
| LedgerTransactionContext txCtx = ldgEdt.newTransaction(genesisTxReq); | |||||
| LedgerDataSet ldgDS = txCtx.getDataSet(); | |||||
| // 创建账本; | |||||
| return LedgerTransactionalEditor.createEditor(initSetting, LEDGER_KEY_PREFIX, storage, storage); | |||||
| } | |||||
| AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair(); | |||||
| private LedgerTransactionContext createGenisisTx(LedgerEditor ldgEdt) { | |||||
| TransactionRequest genesisTxReq = LedgerTestUtils.createTxRequest(null, signatureFunction); | |||||
| LedgerTransactionContext txCtx = ldgEdt.newTransaction(genesisTxReq); | |||||
| return txCtx; | |||||
| } | |||||
| @SuppressWarnings("unused") | @SuppressWarnings("unused") | ||||
| @Test | @Test | ||||
| public void testWriteDataAccoutKvOp() { | public void testWriteDataAccoutKvOp() { | ||||
| LedgerEditor ldgEdt = createLedgerInitEditor(); | |||||
| LedgerTransactionContext genisisTxCtx = createGenisisTx(ldgEdt); | |||||
| LedgerDataSet ldgDS = genisisTxCtx.getDataSet(); | |||||
| AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair(); | |||||
| BlockchainKeypair dataKP = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | BlockchainKeypair dataKP = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | ||||
| DataAccount dataAccount = ldgDS.getDataAccountSet().register(dataKP.getAddress(), dataKP.getPubKey(), null); | DataAccount dataAccount = ldgDS.getDataAccountSet().register(dataKP.getAddress(), dataKP.getPubKey(), null); | ||||
| dataAccount.setBytes(Bytes.fromString("A"), "abc".getBytes(), -1); | |||||
| dataAccount.setBytes(Bytes.fromString("A"), "abc", -1); | |||||
| LedgerTransaction tx = txCtx.commit(TransactionState.SUCCESS); | |||||
| LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS); | |||||
| LedgerBlock block = ldgEdt.prepare(); | LedgerBlock block = ldgEdt.prepare(); | ||||
| // 提交数据,写入存储; | // 提交数据,写入存储; | ||||
| ldgEdt.commit(); | ldgEdt.commit(); | ||||
| byte[] bytes = dataAccount.getBytes("A"); | |||||
| assertArrayEquals("abc".getBytes(), bytes); | |||||
| // 预期这是第1个区块; | |||||
| assertNotNull(block); | |||||
| assertNotNull(block.getHash()); | |||||
| assertEquals(0, block.getHeight()); | |||||
| // 验证数据读写的一致性; | |||||
| BytesValue bytes = dataAccount.getBytes("A"); | |||||
| assertEquals(BytesValueType.TEXT, bytes.getType()); | |||||
| String textValue = bytes.getValue().toUTF8String(); | |||||
| assertEquals("abc", textValue); | |||||
| } | } | ||||
| /** | /** | ||||
| * 测试创建账本; | * 测试创建账本; | ||||
| */ | */ | ||||
| @Test | @Test | ||||
| public void testLedgerEditorCreation() { | |||||
| public void testGennesisBlockCreation() { | |||||
| LedgerEditor ldgEdt = createLedgerInitEditor(); | |||||
| LedgerTransactionContext genisisTxCtx = createGenisisTx(ldgEdt); | |||||
| LedgerDataSet ldgDS = genisisTxCtx.getDataSet(); | |||||
| AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair(); | |||||
| BlockchainKeypair userKP = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | BlockchainKeypair userKP = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | ||||
| UserAccount userAccount = ldgDS.getUserAccountSet().register(userKP.getAddress(), userKP.getPubKey()); | UserAccount userAccount = ldgDS.getUserAccountSet().register(userKP.getAddress(), userKP.getPubKey()); | ||||
| userAccount.setProperty("Name", "孙悟空", -1); | userAccount.setProperty("Name", "孙悟空", -1); | ||||
| userAccount.setProperty("Age", "10000", -1); | userAccount.setProperty("Age", "10000", -1); | ||||
| LedgerTransaction tx = txCtx.commit(TransactionState.SUCCESS); | |||||
| LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS); | |||||
| TransactionRequest genesisTxReq = genisisTxCtx.getRequestTX(); | |||||
| assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash()); | assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash()); | ||||
| assertEquals(0, tx.getBlockHeight()); | assertEquals(0, tx.getBlockHeight()); | ||||
| @@ -116,7 +150,7 @@ public class LedgerEditerTest { | |||||
| private LedgerInitSetting createLedgerInitSetting() { | private LedgerInitSetting createLedgerInitSetting() { | ||||
| SignatureFunction signFunc = Crypto.getSignatureFunction("ED25519"); | SignatureFunction signFunc = Crypto.getSignatureFunction("ED25519"); | ||||
| CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; | CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; | ||||
| for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { | for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { | ||||
| supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); | supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); | ||||
| @@ -257,7 +257,7 @@ public class LedgerTransactionDataTest { | |||||
| // contentBlob.setSubjectAccount(id.getAddress()); | // contentBlob.setSubjectAccount(id.getAddress()); | ||||
| // contentBlob.setSequenceNumber(1); | // contentBlob.setSequenceNumber(1); | ||||
| DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress()) | DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress()) | ||||
| .set("Name", ByteArray.fromString("AAA", "UTF-8"), -1).getOperation(); | |||||
| .setText("Name", "AAA", -1).getOperation(); | |||||
| contentBlob.addOperation(kvsetOP); | contentBlob.addOperation(kvsetOP); | ||||
| return contentBlob; | return contentBlob; | ||||
| } | } | ||||
| @@ -68,7 +68,7 @@ public class TransactionSetTest { | |||||
| DataAccountRegisterOperation dataAccRegOp = txBuilder.dataAccounts().register(dataKey.getIdentity()); | DataAccountRegisterOperation dataAccRegOp = txBuilder.dataAccounts().register(dataKey.getIdentity()); | ||||
| DataAccountKVSetOperation kvsetOP = txBuilder.dataAccount(dataKey.getAddress()) | DataAccountKVSetOperation kvsetOP = txBuilder.dataAccount(dataKey.getAddress()) | ||||
| .set("A", "Value_A_0".getBytes(), -1).set("B", "Value_B_0".getBytes(), -1).getOperation(); | |||||
| .setText("A", "Value_A_0", -1).setText("B", "Value_B_0", -1).getOperation(); | |||||
| byte[] chainCode = new byte[128]; | byte[] chainCode = new byte[128]; | ||||
| rand.nextBytes(chainCode); | rand.nextBytes(chainCode); | ||||
| @@ -4,7 +4,7 @@ import com.jd.blockchain.binaryproto.DataContract; | |||||
| import com.jd.blockchain.binaryproto.DataField; | import com.jd.blockchain.binaryproto.DataField; | ||||
| import com.jd.blockchain.binaryproto.PrimitiveType; | import com.jd.blockchain.binaryproto.PrimitiveType; | ||||
| import com.jd.blockchain.consts.DataCodes; | import com.jd.blockchain.consts.DataCodes; | ||||
| import com.jd.blockchain.utils.io.BytesSlice; | |||||
| import com.jd.blockchain.utils.Bytes; | |||||
| /** | /** | ||||
| * BytesValue is the base structure of Value in Blockchain Account; | * BytesValue is the base structure of Value in Blockchain Account; | ||||
| @@ -29,6 +29,6 @@ public interface BytesValue { | |||||
| * @return | * @return | ||||
| */ | */ | ||||
| @DataField(order = 1, primitiveType = PrimitiveType.BYTES) | @DataField(order = 1, primitiveType = PrimitiveType.BYTES) | ||||
| BytesSlice getValue(); | |||||
| Bytes getValue(); | |||||
| } | } | ||||
| @@ -1,31 +1,114 @@ | |||||
| package com.jd.blockchain.ledger; | package com.jd.blockchain.ledger; | ||||
| import com.jd.blockchain.utils.io.BytesSlice; | |||||
| import com.jd.blockchain.utils.Bytes; | |||||
| import com.jd.blockchain.utils.io.BytesUtils; | |||||
| /** | /** | ||||
| * Created by zhangshuang3 on 2018/12/3. | |||||
| * | |||||
| * @author huanghaiquan | |||||
| * | |||||
| */ | */ | ||||
| public class BytesValueEntry implements BytesValue{ | |||||
| BytesValueType type; | |||||
| BytesSlice slice; | |||||
| public BytesValueEntry(BytesValueType type, byte[] bytes) { | |||||
| this.type = type; | |||||
| this.slice = new BytesSlice(bytes); | |||||
| } | |||||
| @Override | |||||
| public BytesValueType getType() { | |||||
| return this.type; | |||||
| } | |||||
| public void setType(BytesValueType type) { | |||||
| this.type = type; | |||||
| } | |||||
| @Override | |||||
| public BytesSlice getValue() { | |||||
| return this.slice; | |||||
| } | |||||
| public class BytesValueEntry implements BytesValue { | |||||
| BytesValueType type; | |||||
| Bytes value; | |||||
| private BytesValueEntry(BytesValueType type, byte[] bytes) { | |||||
| this.type = type; | |||||
| this.value = new Bytes(bytes); | |||||
| } | |||||
| private BytesValueEntry(BytesValueType type, Bytes bytes) { | |||||
| this.type = type; | |||||
| this.value = bytes; | |||||
| } | |||||
| public static BytesValue fromBytes(byte[] value) { | |||||
| return new BytesValueEntry(BytesValueType.BYTES, value); | |||||
| } | |||||
| public static BytesValue fromBytes(Bytes value) { | |||||
| return new BytesValueEntry(BytesValueType.BYTES, value); | |||||
| } | |||||
| public static BytesValue fromImage(byte[] value) { | |||||
| return new BytesValueEntry(BytesValueType.IMG, value); | |||||
| } | |||||
| public static BytesValue fromImage(Bytes value) { | |||||
| return new BytesValueEntry(BytesValueType.IMG, value); | |||||
| } | |||||
| /** | |||||
| * 以 UTF-8 编码从字符串转换为字节数组值; | |||||
| * | |||||
| * @param value | |||||
| * @return | |||||
| */ | |||||
| public static BytesValue fromText(String value) { | |||||
| return new BytesValueEntry(BytesValueType.TEXT, BytesUtils.toBytes(value)); | |||||
| } | |||||
| /** | |||||
| * 以 UTF-8 编码把字节数组值转换为字符串; | |||||
| * | |||||
| * @param bytesValue | |||||
| * @return | |||||
| */ | |||||
| public static String toText(BytesValue bytesValue) { | |||||
| if (bytesValue == null) { | |||||
| return null; | |||||
| } | |||||
| if (bytesValue.getType() != BytesValueType.TEXT) { | |||||
| throw new ValueTypeCastException("The expected value type is " + BytesValueType.TEXT.toString() | |||||
| + ", but it is actually " + bytesValue.getType().toString() + "!"); | |||||
| } | |||||
| return bytesValue.getValue().toUTF8String(); | |||||
| } | |||||
| public static BytesValue fromJSON(String value) { | |||||
| return new BytesValueEntry(BytesValueType.JSON, BytesUtils.toBytes(value)); | |||||
| } | |||||
| public static BytesValue fromXML(String value) { | |||||
| return new BytesValueEntry(BytesValueType.XML, BytesUtils.toBytes(value)); | |||||
| } | |||||
| public static BytesValue fromInt32(int value) { | |||||
| return new BytesValueEntry(BytesValueType.INT32, BytesUtils.toBytes(value)); | |||||
| } | |||||
| public static BytesValue fromInt64(long value) { | |||||
| return new BytesValueEntry(BytesValueType.INT64, BytesUtils.toBytes(value)); | |||||
| } | |||||
| public static BytesValue fromInt16(short value) { | |||||
| return new BytesValueEntry(BytesValueType.INT16, BytesUtils.toBytes(value)); | |||||
| } | |||||
| public static BytesValue fromInt8(byte value) { | |||||
| return new BytesValueEntry(BytesValueType.INT8, BytesUtils.toBytes(value)); | |||||
| } | |||||
| public static BytesValue fromTimestamp(long value) { | |||||
| return new BytesValueEntry(BytesValueType.TIMESTAMP, BytesUtils.toBytes(value)); | |||||
| } | |||||
| public static BytesValue fromBoolean(boolean value) { | |||||
| return new BytesValueEntry(BytesValueType.BOOLEAN, BytesUtils.toBytes(value)); | |||||
| } | |||||
| @Override | |||||
| public BytesValueType getType() { | |||||
| return this.type; | |||||
| } | |||||
| public void setType(BytesValueType type) { | |||||
| this.type = type; | |||||
| } | |||||
| @Override | |||||
| public Bytes getValue() { | |||||
| return this.value; | |||||
| } | |||||
| } | } | ||||
| @@ -37,9 +37,9 @@ public enum BytesValueType { | |||||
| INT64(PrimitiveType.INT64.CODE), | INT64(PrimitiveType.INT64.CODE), | ||||
| /** | /** | ||||
| * 日期时间; | |||||
| * 时间戳; | |||||
| */ | */ | ||||
| DATETIME(PrimitiveType.DATETIME.CODE), | |||||
| TIMESTAMP(PrimitiveType.TIMESTAMP.CODE), | |||||
| /** | /** | ||||
| * 文本数据; | * 文本数据; | ||||
| @@ -81,7 +81,6 @@ public enum BytesValueType { | |||||
| */ | */ | ||||
| LOCATION(PrimitiveType.LOCATION.CODE); | LOCATION(PrimitiveType.LOCATION.CODE); | ||||
| @EnumField(type = PrimitiveType.INT8) | @EnumField(type = PrimitiveType.INT8) | ||||
| public final byte CODE; | public final byte CODE; | ||||
| @@ -1,7 +1,5 @@ | |||||
| package com.jd.blockchain.ledger; | package com.jd.blockchain.ledger; | ||||
| import com.jd.blockchain.binaryproto.PrimitiveType; | |||||
| public interface KVDataEntry { | public interface KVDataEntry { | ||||
| /** | /** | ||||
| @@ -27,11 +25,12 @@ public interface KVDataEntry { | |||||
| * | * | ||||
| * @return | * @return | ||||
| */ | */ | ||||
| PrimitiveType getType(); | |||||
| BytesValueType getType(); | |||||
| /** | /** | ||||
| * 值; | * 值; | ||||
| * @return | * @return | ||||
| */ | */ | ||||
| Object getValue(); | Object getValue(); | ||||
| } | } | ||||
| @@ -1,11 +1,10 @@ | |||||
| package com.jd.blockchain.ledger; | package com.jd.blockchain.ledger; | ||||
| import java.io.ByteArrayInputStream; | |||||
| import java.io.UnsupportedEncodingException; | |||||
| import java.math.BigInteger; | import java.math.BigInteger; | ||||
| import java.util.Date; | import java.util.Date; | ||||
| import com.jd.blockchain.binaryproto.PrimitiveType; | 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.ByteArray; | ||||
| import com.jd.blockchain.utils.io.BytesUtils; | import com.jd.blockchain.utils.io.BytesUtils; | ||||
| @@ -25,13 +24,10 @@ public class KVDataObject implements KVDataEntry { | |||||
| private long version; | private long version; | ||||
| private PrimitiveType type; | |||||
| private BytesValue bytesValue; | |||||
| private byte[] bytesValue; | |||||
| public KVDataObject(String key, long version, PrimitiveType type, byte[] bytesValue) { | |||||
| public KVDataObject(String key, long version, BytesValue bytesValue) { | |||||
| this.key = key; | this.key = key; | ||||
| this.type = type; | |||||
| this.version = version < 0 ? -1 : version; | this.version = version < 0 ? -1 : version; | ||||
| this.bytesValue = bytesValue; | this.bytesValue = bytesValue; | ||||
| } | } | ||||
| @@ -62,8 +58,8 @@ public class KVDataObject implements KVDataEntry { | |||||
| * @see com.jd.blockchain.ledger.KVDataEntry#getType() | * @see com.jd.blockchain.ledger.KVDataEntry#getType() | ||||
| */ | */ | ||||
| @Override | @Override | ||||
| public PrimitiveType getType() { | |||||
| return type; | |||||
| public BytesValueType getType() { | |||||
| return bytesValue == null ? BytesValueType.NIL : bytesValue.getType(); | |||||
| } | } | ||||
| @Override | @Override | ||||
| @@ -72,24 +68,20 @@ public class KVDataObject implements KVDataEntry { | |||||
| return null; | return null; | ||||
| } | } | ||||
| try { | |||||
| switch (type) { | |||||
| case NIL: | |||||
| return null; | |||||
| case TEXT: | |||||
| return new String(bytesValue, "UTF-8"); | |||||
| case BYTES: | |||||
| return ByteArray.toHex(bytesValue); | |||||
| case INT64: | |||||
| return BytesUtils.readLong(new ByteArrayInputStream(bytesValue)); | |||||
| case JSON: | |||||
| return new String(bytesValue, "UTF-8"); | |||||
| 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(); | |||||
| default: | |||||
| throw new IllegalStateException("Unsupported value type[" + type + "] to resolve!"); | |||||
| } | |||||
| } catch (UnsupportedEncodingException e) { | |||||
| throw new IllegalStateException(e.getMessage(), e); | |||||
| default: | |||||
| throw new IllegalStateException("Unsupported value type[" + getType() + "] to resolve!"); | |||||
| } | } | ||||
| } | } | ||||
| @@ -103,7 +95,7 @@ public class KVDataObject implements KVDataEntry { | |||||
| * @return | * @return | ||||
| */ | */ | ||||
| public boolean isNil() { | public boolean isNil() { | ||||
| return PrimitiveType.NIL == type; | |||||
| return bytesValue == null || BytesValueType.NIL == bytesValue.getType(); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -111,8 +103,8 @@ public class KVDataObject implements KVDataEntry { | |||||
| * | * | ||||
| * @return | * @return | ||||
| */ | */ | ||||
| ByteArray bytesArray() { | |||||
| return ByteArray.wrapReadonly(bytesValue); | |||||
| Bytes bytesArray() { | |||||
| return bytesValue.getValue(); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -127,10 +119,10 @@ public class KVDataObject implements KVDataEntry { | |||||
| * @return | * @return | ||||
| */ | */ | ||||
| public byte tinyValue() { | public byte tinyValue() { | ||||
| if (PrimitiveType.INT8 == type) { | |||||
| return bytesValue[0]; | |||||
| if (BytesValueType.INT8 == getType()) { | |||||
| return bytesValue.getValue().toBytes()[0]; | |||||
| } | } | ||||
| throw new IllegalStateException(String.format("Expected type [%s], but [%s]", PrimitiveType.INT8, type)); | |||||
| throw new IllegalStateException(String.format("Expected type [%s], but [%s]", BytesValueType.INT8, getType())); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -145,10 +137,10 @@ public class KVDataObject implements KVDataEntry { | |||||
| * @return | * @return | ||||
| */ | */ | ||||
| public short shortValue() { | public short shortValue() { | ||||
| if (PrimitiveType.INT16 == type) { | |||||
| return BytesUtils.toShort(bytesValue, 0); | |||||
| if (BytesValueType.INT16 == getType()) { | |||||
| return BytesUtils.toShort(bytesValue.getValue().toBytes(), 0); | |||||
| } | } | ||||
| throw new IllegalStateException(String.format("Expected type [%s], but [%s]", PrimitiveType.INT16, type)); | |||||
| throw new IllegalStateException(String.format("Expected type [%s], but [%s]", BytesValueType.INT16, getType())); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -163,10 +155,10 @@ public class KVDataObject implements KVDataEntry { | |||||
| * @return | * @return | ||||
| */ | */ | ||||
| public int intValue() { | public int intValue() { | ||||
| if (PrimitiveType.INT32 == type) { | |||||
| return BytesUtils.toInt(bytesValue, 0); | |||||
| if (BytesValueType.INT32 == getType()) { | |||||
| return BytesUtils.toInt(bytesValue.getValue().toBytes(), 0); | |||||
| } | } | ||||
| throw new IllegalStateException(String.format("Expected type [%s], but [%s]", PrimitiveType.INT32, type)); | |||||
| throw new IllegalStateException(String.format("Expected type [%s], but [%s]", BytesValueType.INT32, getType())); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -181,10 +173,10 @@ public class KVDataObject implements KVDataEntry { | |||||
| * @return | * @return | ||||
| */ | */ | ||||
| public long longValue() { | public long longValue() { | ||||
| if (PrimitiveType.INT64 == type) { | |||||
| return BytesUtils.toLong(bytesValue, 0); | |||||
| if (BytesValueType.INT64 == getType()) { | |||||
| return BytesUtils.toLong(bytesValue.getValue().toBytes(), 0); | |||||
| } | } | ||||
| throw new IllegalStateException(String.format("Expected type [%s], but [%s]", PrimitiveType.INT64, type)); | |||||
| throw new IllegalStateException(String.format("Expected type [%s], but [%s]", BytesValueType.INT64, getType())); | |||||
| } | } | ||||
| @@ -200,10 +192,11 @@ public class KVDataObject implements KVDataEntry { | |||||
| * @return | * @return | ||||
| */ | */ | ||||
| public BigInteger bigIntValue() { | public BigInteger bigIntValue() { | ||||
| if (PrimitiveType.BIG_INT == type) { | |||||
| return new BigInteger(bytesValue); | |||||
| if (BytesValueType.BIG_INT == getType()) { | |||||
| return new BigInteger(bytesValue.getValue().toBytes()); | |||||
| } | } | ||||
| throw new IllegalStateException(String.format("Expected type [%s], but [%s]", PrimitiveType.BIG_INT, type)); | |||||
| throw new IllegalStateException( | |||||
| String.format("Expected type [%s], but [%s]", BytesValueType.BIG_INT, getType())); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -218,17 +211,18 @@ public class KVDataObject implements KVDataEntry { | |||||
| * @return | * @return | ||||
| */ | */ | ||||
| public boolean boolValue() { | public boolean boolValue() { | ||||
| if (PrimitiveType.BOOLEAN == type) { | |||||
| return bytesValue[0] != 0; | |||||
| if (BytesValueType.BOOLEAN == getType()) { | |||||
| return BytesUtils.toBoolean(bytesValue.getValue().toBytes()[0]); | |||||
| } | } | ||||
| throw new IllegalStateException(String.format("Expected type [%s], but [%s]", PrimitiveType.BOOLEAN, type)); | |||||
| throw new IllegalStateException( | |||||
| String.format("Expected type [%s], but [%s]", BytesValueType.BOOLEAN, getType())); | |||||
| } | } | ||||
| /** | /** | ||||
| * 返回日期时间值; | * 返回日期时间值; | ||||
| * <p> | * <p> | ||||
| * | * | ||||
| * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#DATETIME} 有效; | |||||
| * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TIMESTAMP} 有效; | |||||
| * <p> | * <p> | ||||
| * | * | ||||
| * 无效类型将引发 {@link IllegalStateException} 异常; | * 无效类型将引发 {@link IllegalStateException} 异常; | ||||
| @@ -236,19 +230,20 @@ public class KVDataObject implements KVDataEntry { | |||||
| * @return | * @return | ||||
| */ | */ | ||||
| public Date datetimeValue() { | public Date datetimeValue() { | ||||
| if (PrimitiveType.DATETIME == type) { | |||||
| long ts = BytesUtils.toLong(bytesValue); | |||||
| if (BytesValueType.TIMESTAMP == getType()) { | |||||
| long ts = BytesUtils.toLong(bytesValue.getValue().toBytes()); | |||||
| return new Date(ts); | return new Date(ts); | ||||
| } | } | ||||
| throw new IllegalStateException(String.format("Expected type [%s], but [%s]", PrimitiveType.DATETIME, type)); | |||||
| throw new IllegalStateException( | |||||
| String.format("Expected type [%s], but [%s]", BytesValueType.TIMESTAMP, getType())); | |||||
| } | } | ||||
| /** | /** | ||||
| * 返回大整数值; | * 返回大整数值; | ||||
| * <p> | * <p> | ||||
| * | * | ||||
| * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TEXT} / {@link PrimitiveType#JSON} / | |||||
| * {@link PrimitiveType#XML} 有效; | |||||
| * 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TEXT} / | |||||
| * {@link PrimitiveType#JSON} / {@link PrimitiveType#XML} 有效; | |||||
| * <p> | * <p> | ||||
| * | * | ||||
| * 无效类型将引发 {@link IllegalStateException} 异常; | * 无效类型将引发 {@link IllegalStateException} 异常; | ||||
| @@ -256,15 +251,12 @@ public class KVDataObject implements KVDataEntry { | |||||
| * @return | * @return | ||||
| */ | */ | ||||
| public String stringValue() { | public String stringValue() { | ||||
| if (PrimitiveType.TEXT == type || PrimitiveType.JSON == type || PrimitiveType.XML == type) { | |||||
| try { | |||||
| return new String(bytesValue, "UTF-8"); | |||||
| } catch (UnsupportedEncodingException e) { | |||||
| throw new IllegalStateException(e.getMessage(), e); | |||||
| } | |||||
| BytesValueType type = getType(); | |||||
| if (BytesValueType.TEXT == type || BytesValueType.JSON == type || BytesValueType.XML == type) { | |||||
| return bytesValue.getValue().toUTF8String(); | |||||
| } | } | ||||
| throw new IllegalStateException(String.format("Expected type [%s] or [%s] or [%s] , but [%s]", PrimitiveType.TEXT, | |||||
| PrimitiveType.JSON, PrimitiveType.XML, type)); | |||||
| throw new IllegalStateException(String.format("Expected type [%s] or [%s] or [%s] , but [%s]", | |||||
| PrimitiveType.TEXT, BytesValueType.JSON, BytesValueType.XML, type)); | |||||
| } | } | ||||
| // // ---------------- | // // ---------------- | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.jd.blockchain.ledger.core; | |||||
| package com.jd.blockchain.ledger; | |||||
| public class LedgerException extends RuntimeException { | public class LedgerException extends RuntimeException { | ||||
| @@ -0,0 +1,15 @@ | |||||
| package com.jd.blockchain.ledger; | |||||
| public class LedgerPermissionException extends LedgerException { | |||||
| private static final long serialVersionUID = 6077975401474519117L; | |||||
| public LedgerPermissionException(String message) { | |||||
| super(message); | |||||
| } | |||||
| public LedgerPermissionException(String message, Throwable cause) { | |||||
| super(message, cause); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,68 @@ | |||||
| package com.jd.blockchain.ledger; | |||||
| /** | |||||
| * 权限类型; | |||||
| * | |||||
| * @author huanghaiquan | |||||
| * | |||||
| */ | |||||
| public enum PermissionType { | |||||
| /** | |||||
| * 账户权限配置; | |||||
| */ | |||||
| SET_PRIVILEGE(1), | |||||
| /** | |||||
| * 注册参与方; | |||||
| */ | |||||
| REG_PARTICIPANT(2), | |||||
| /** | |||||
| * 配置账本;包括除了{@link #SET_PRIVILEGE}、 {@link #REG_PARTICIPANT} 之外的其它账本设置,例如:设置密码参数、共识参数等; | |||||
| */ | |||||
| CONFIG_LEDGER(4), | |||||
| /** | |||||
| * 用户注册; | |||||
| */ | |||||
| REG_USER(8), | |||||
| /** | |||||
| * 注册数据账户; | |||||
| */ | |||||
| REG_DATA_ACCOUNT(16), | |||||
| /** | |||||
| * 部署新的合约代码; | |||||
| */ | |||||
| DEPLOY_CONTRACT(32), | |||||
| /** | |||||
| * 写入用户信息; | |||||
| */ | |||||
| SET_USER(1024), | |||||
| /** | |||||
| * 写入数据; | |||||
| */ | |||||
| SET_DATA(2048), | |||||
| /** | |||||
| * 写入数据; | |||||
| */ | |||||
| INVOKE_CONTRACT(4096), | |||||
| /** | |||||
| * 升级合约代码; | |||||
| */ | |||||
| UPDATE_CONTRACT(8192); | |||||
| public final int CODE; | |||||
| private PermissionType(int code) { | |||||
| this.CODE = code; | |||||
| } | |||||
| } | |||||
| @@ -1,42 +0,0 @@ | |||||
| package com.jd.blockchain.ledger; | |||||
| /** | |||||
| * 权限类型; | |||||
| * | |||||
| * @author huanghaiquan | |||||
| * | |||||
| */ | |||||
| public enum PrivilegeType { | |||||
| /** | |||||
| * 账户注册; | |||||
| */ | |||||
| ACCOUNT_REGISTER(1), | |||||
| /** | |||||
| * 账户权限配置; | |||||
| */ | |||||
| PRIVILEGE_CONFIG(2), | |||||
| /** | |||||
| * 状态数据写入; | |||||
| */ | |||||
| STATE_WRITE(4), | |||||
| /** | |||||
| * 合约应用部署; | |||||
| */ | |||||
| CONTRACT_APP_DEPLOY(8), | |||||
| /** | |||||
| * 合约应用调用; | |||||
| */ | |||||
| CONTRACT_APP_INVOKE(16); | |||||
| public final int CODE; | |||||
| private PrivilegeType(int code) { | |||||
| this.CODE = code; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,17 @@ | |||||
| package com.jd.blockchain.ledger; | |||||
| public class ValueTypeCastException extends LedgerException { | |||||
| private static final long serialVersionUID = 6641080037721006099L; | |||||
| public ValueTypeCastException(String message) { | |||||
| super(message); | |||||
| } | |||||
| public ValueTypeCastException(String message, Throwable cause) { | |||||
| super(message, cause); | |||||
| } | |||||
| } | |||||
| @@ -148,43 +148,80 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe | |||||
| return innerBuilder.getOperation(); | return innerBuilder.getOperation(); | ||||
| } | } | ||||
| @Override | |||||
| public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) { | |||||
| innerBuilder.set(key, value, expVersion); | |||||
| private void addOperation() { | |||||
| if (op == null) { | if (op == null) { | ||||
| op = innerBuilder.getOperation(); | op = innerBuilder.getOperation(); | ||||
| operationList.add(op); | operationList.add(op); | ||||
| } | } | ||||
| } | |||||
| // @Override | |||||
| // public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) { | |||||
| // innerBuilder.set(key, value, expVersion); | |||||
| // addOperation(); | |||||
| // return this; | |||||
| // } | |||||
| @Override | |||||
| public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { | |||||
| innerBuilder.setText(key, value, expVersion); | |||||
| addOperation(); | |||||
| return this; | return this; | ||||
| } | } | ||||
| @Override | @Override | ||||
| public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) { | |||||
| innerBuilder.set(key, value, expVersion); | |||||
| if (op == null) { | |||||
| op = innerBuilder.getOperation(); | |||||
| operationList.add(op); | |||||
| } | |||||
| public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { | |||||
| innerBuilder.setInt64(key, value, expVersion); | |||||
| addOperation(); | |||||
| return this; | return this; | ||||
| } | } | ||||
| @Override | @Override | ||||
| public DataAccountKVSetOperationBuilder set(String key, long value, long expVersion) { | |||||
| innerBuilder.set(key, value, expVersion); | |||||
| if (op == null) { | |||||
| op = innerBuilder.getOperation(); | |||||
| operationList.add(op); | |||||
| } | |||||
| public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { | |||||
| innerBuilder.setBytes(key, value, expVersion); | |||||
| addOperation(); | |||||
| return this; | return this; | ||||
| } | } | ||||
| @Override | @Override | ||||
| public DataAccountKVSetOperationBuilder set(String key, Bytes value, long expVersion) { | |||||
| innerBuilder.set(key, value, expVersion); | |||||
| if (op == null) { | |||||
| op = innerBuilder.getOperation(); | |||||
| operationList.add(op); | |||||
| } | |||||
| public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { | |||||
| innerBuilder.setBytes(key, value, expVersion); | |||||
| addOperation(); | |||||
| return this; | |||||
| } | |||||
| @Override | |||||
| public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { | |||||
| innerBuilder.setImage(key, value, expVersion); | |||||
| addOperation(); | |||||
| return this; | |||||
| } | |||||
| // @Override | |||||
| // public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) { | |||||
| // innerBuilder.setText(key, value, expVersion); | |||||
| // addOperation(); | |||||
| // return this; | |||||
| // } | |||||
| @Override | |||||
| public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { | |||||
| innerBuilder.setJSON(key, value, expVersion); | |||||
| addOperation(); | |||||
| return this; | |||||
| } | |||||
| @Override | |||||
| public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { | |||||
| innerBuilder.setXML(key, value, expVersion); | |||||
| addOperation(); | |||||
| return this; | |||||
| } | |||||
| @Override | |||||
| public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { | |||||
| innerBuilder.setTimestamp(key, value, expVersion); | |||||
| addOperation(); | |||||
| return this; | return this; | ||||
| } | } | ||||
| @@ -3,6 +3,10 @@ package com.jd.blockchain.transaction; | |||||
| import com.jd.blockchain.ledger.DataAccountKVSetOperation; | import com.jd.blockchain.ledger.DataAccountKVSetOperation; | ||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| /** | |||||
| * @author huanghaiquan | |||||
| * | |||||
| */ | |||||
| public interface DataAccountKVSetOperationBuilder { | public interface DataAccountKVSetOperationBuilder { | ||||
| /** | /** | ||||
| @@ -12,8 +16,22 @@ public interface DataAccountKVSetOperationBuilder { | |||||
| */ | */ | ||||
| DataAccountKVSetOperation getOperation(); | DataAccountKVSetOperation getOperation(); | ||||
| // /** | |||||
| // * 写入字节数组; | |||||
| // * | |||||
| // * @param key | |||||
| // * 键; | |||||
| // * @param value | |||||
| // * 值;byte[]格式 | |||||
| // * @param expVersion | |||||
| // * 预期的当前版本;如果版本不匹配,则写入失败; | |||||
| // * @return | |||||
| // */ | |||||
| // @Deprecated | |||||
| // DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion); | |||||
| /** | /** | ||||
| * 写入键值; | |||||
| * 写入字节数组; | |||||
| * | * | ||||
| * @param key | * @param key | ||||
| * 键; | * 键; | ||||
| @@ -23,7 +41,21 @@ public interface DataAccountKVSetOperationBuilder { | |||||
| * 预期的当前版本;如果版本不匹配,则写入失败; | * 预期的当前版本;如果版本不匹配,则写入失败; | ||||
| * @return | * @return | ||||
| */ | */ | ||||
| DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion); | |||||
| DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion); | |||||
| /** | |||||
| * 写入字节数组; | |||||
| * | |||||
| * @param key | |||||
| * 键; | |||||
| * @param value | |||||
| * 值;Bytes格式 | |||||
| * @param expVersion | |||||
| * 预期的当前版本;如果版本不匹配,则写入失败; | |||||
| * @return | |||||
| */ | |||||
| DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion); | |||||
| /** | /** | ||||
| * 写入键值; | * 写入键值; | ||||
| * | * | ||||
| @@ -35,21 +67,76 @@ public interface DataAccountKVSetOperationBuilder { | |||||
| * 预期的当前版本;如果版本不匹配,则写入失败; | * 预期的当前版本;如果版本不匹配,则写入失败; | ||||
| * @return | * @return | ||||
| */ | */ | ||||
| DataAccountKVSetOperationBuilder set(String key, String value, long expVersion); | |||||
| DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion); | |||||
| // /** | |||||
| // * 写入文本键值; | |||||
| // * | |||||
| // * @param key | |||||
| // * 键; | |||||
| // * @param value | |||||
| // * 值;String格式 | |||||
| // * @param expVersion | |||||
| // * 预期的当前版本;如果版本不匹配,则写入失败; | |||||
| // * @return | |||||
| // */ | |||||
| // @Deprecated | |||||
| // DataAccountKVSetOperationBuilder set(String key, String value, long expVersion); | |||||
| /** | /** | ||||
| * 写入键值; | |||||
| * 写入文本键值; | |||||
| * | * | ||||
| * @param key | * @param key | ||||
| * 键; | * 键; | ||||
| * @param value | * @param value | ||||
| * 值;Bytes格式 | |||||
| * 值;String格式 | |||||
| * @param expVersion | * @param expVersion | ||||
| * 预期的当前版本;如果版本不匹配,则写入失败; | * 预期的当前版本;如果版本不匹配,则写入失败; | ||||
| * @return | * @return | ||||
| */ | */ | ||||
| DataAccountKVSetOperationBuilder set(String key, Bytes value, long expVersion); | |||||
| DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion); | |||||
| /** | /** | ||||
| * 写入键值; | |||||
| * 写入JSON键值; | |||||
| * | |||||
| * @param key | |||||
| * 键; | |||||
| * @param value | |||||
| * 值;String格式 | |||||
| * @param expVersion | |||||
| * 预期的当前版本;如果版本不匹配,则写入失败; | |||||
| * @return | |||||
| */ | |||||
| DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion); | |||||
| /** | |||||
| * 写入XML键值; | |||||
| * | |||||
| * @param key | |||||
| * 键; | |||||
| * @param value | |||||
| * 值;String格式 | |||||
| * @param expVersion | |||||
| * 预期的当前版本;如果版本不匹配,则写入失败; | |||||
| * @return | |||||
| */ | |||||
| DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion); | |||||
| /** | |||||
| * 写入64位整数; | |||||
| * | |||||
| * @param key | |||||
| * 键; | |||||
| * @param value | |||||
| * 值;long格式 | |||||
| * @param expVersion | |||||
| * 预期的当前版本;如果版本不匹配,则写入失败; | |||||
| * @return | |||||
| */ | |||||
| DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion); | |||||
| /** | |||||
| * 写入时间戳; | |||||
| * | * | ||||
| * @param key | * @param key | ||||
| * 键; | * 键; | ||||
| @@ -59,6 +146,6 @@ public interface DataAccountKVSetOperationBuilder { | |||||
| * 预期的当前版本;如果版本不匹配,则写入失败; | * 预期的当前版本;如果版本不匹配,则写入失败; | ||||
| * @return | * @return | ||||
| */ | */ | ||||
| DataAccountKVSetOperationBuilder set(String key, long value, long expVersion); | |||||
| DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion); | |||||
| } | } | ||||
| @@ -3,15 +3,12 @@ package com.jd.blockchain.transaction; | |||||
| import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
| import com.jd.blockchain.ledger.BytesValueEntry; | import com.jd.blockchain.ledger.BytesValueEntry; | ||||
| import com.jd.blockchain.ledger.DataAccountKVSetOperation; | import com.jd.blockchain.ledger.DataAccountKVSetOperation; | ||||
| import com.jd.blockchain.ledger.BytesValueType; | |||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| import com.jd.blockchain.utils.io.BytesUtils; | |||||
| import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; | |||||
| public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOperationBuilder{ | |||||
| public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOperationBuilder { | |||||
| private DataAccountKVSetOpTemplate operation; | private DataAccountKVSetOpTemplate operation; | ||||
| public DataAccountKVSetOperationBuilderImpl(Bytes accountAddress) { | public DataAccountKVSetOperationBuilderImpl(Bytes accountAddress) { | ||||
| operation = new DataAccountKVSetOpTemplate(accountAddress); | operation = new DataAccountKVSetOpTemplate(accountAddress); | ||||
| } | } | ||||
| @@ -21,35 +18,69 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe | |||||
| return operation; | return operation; | ||||
| } | } | ||||
| // @Deprecated | |||||
| // @Override | |||||
| // public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) { | |||||
| // return setBytes(key, value, expVersion); | |||||
| // } | |||||
| @Override | @Override | ||||
| public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) { | |||||
| BytesValue bytesValue = new BytesValueEntry(BytesValueType.BYTES, value); | |||||
| public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromBytes(value); | |||||
| operation.set(key, bytesValue, expVersion); | operation.set(key, bytesValue, expVersion); | ||||
| return this; | return this; | ||||
| } | } | ||||
| @Override | @Override | ||||
| public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) { | |||||
| BytesValue bytesValue; | |||||
| if (JSONSerializeUtils.isJSON(value)) { | |||||
| bytesValue = new BytesValueEntry(BytesValueType.JSON, BytesUtils.toBytes(value)); | |||||
| } | |||||
| else { | |||||
| bytesValue = new BytesValueEntry(BytesValueType.TEXT, BytesUtils.toBytes(value)); | |||||
| } | |||||
| public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromImage(value); | |||||
| operation.set(key, bytesValue, expVersion); | operation.set(key, bytesValue, expVersion); | ||||
| return this; | return this; | ||||
| } | } | ||||
| // @Override | |||||
| // public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) { | |||||
| // return setText(key, value, expVersion); | |||||
| // } | |||||
| @Override | @Override | ||||
| public DataAccountKVSetOperationBuilder set(String key, Bytes value, long expVersion) { | |||||
| BytesValue bytesValue = new BytesValueEntry(BytesValueType.BYTES, value.toBytes()); | |||||
| public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromText(value); | |||||
| operation.set(key, bytesValue, expVersion); | operation.set(key, bytesValue, expVersion); | ||||
| return this; | return this; | ||||
| } | } | ||||
| @Override | |||||
| public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromBytes(value); | |||||
| operation.set(key, bytesValue, expVersion); | |||||
| return this; | |||||
| } | |||||
| @Override | |||||
| public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromInt64(value); | |||||
| operation.set(key, bytesValue, expVersion); | |||||
| return this; | |||||
| } | |||||
| @Override | |||||
| public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromJSON(value); | |||||
| operation.set(key, bytesValue, expVersion); | |||||
| return this; | |||||
| } | |||||
| @Override | |||||
| public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromXML(value); | |||||
| operation.set(key, bytesValue, expVersion); | |||||
| return this; | |||||
| } | |||||
| @Override | @Override | ||||
| public DataAccountKVSetOperationBuilder set(String key, long value, long expVersion) { | |||||
| BytesValue bytesValue = new BytesValueEntry(BytesValueType.INT64, BytesUtils.toBytes(value)); | |||||
| public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { | |||||
| BytesValue bytesValue = BytesValueEntry.fromTimestamp(value); | |||||
| operation.set(key, bytesValue, expVersion); | operation.set(key, bytesValue, expVersion); | ||||
| return this; | return this; | ||||
| } | } | ||||
| @@ -13,14 +13,16 @@ public interface DataAccountOperator { | |||||
| DataAccountRegisterOperationBuilder dataAccounts(); | DataAccountRegisterOperationBuilder dataAccounts(); | ||||
| /** | /** | ||||
| * 写入数据; | |||||
| * 写入数据; <br> | |||||
| * | |||||
| * @param accountAddress | * @param accountAddress | ||||
| * @return | * @return | ||||
| */ | */ | ||||
| DataAccountKVSetOperationBuilder dataAccount(String accountAddress); | DataAccountKVSetOperationBuilder dataAccount(String accountAddress); | ||||
| /** | /** | ||||
| * 写入数据; | * 写入数据; | ||||
| * | |||||
| * @param accountAddress | * @param accountAddress | ||||
| * @return | * @return | ||||
| */ | */ | ||||
| @@ -1,6 +1,6 @@ | |||||
| package com.jd.blockchain.transaction; | package com.jd.blockchain.transaction; | ||||
| import com.jd.blockchain.ledger.PrivilegeType; | |||||
| import com.jd.blockchain.ledger.PermissionType; | |||||
| /** | /** | ||||
| * 账户权限设置操作; | * 账户权限设置操作; | ||||
| @@ -16,10 +16,10 @@ import com.jd.blockchain.ledger.PrivilegeType; | |||||
| */ | */ | ||||
| public interface PrivilegeSettingOperationBuilder { | public interface PrivilegeSettingOperationBuilder { | ||||
| PrivilegeSettingOperationBuilder setThreshhold(PrivilegeType privilege, long threshhold); | |||||
| PrivilegeSettingOperationBuilder setThreshhold(PermissionType privilege, long threshhold); | |||||
| PrivilegeSettingOperationBuilder enable(PrivilegeType privilege, String address, int weight); | |||||
| PrivilegeSettingOperationBuilder enable(PermissionType privilege, String address, int weight); | |||||
| PrivilegeSettingOperationBuilder disable(PrivilegeType privilege, String address); | |||||
| PrivilegeSettingOperationBuilder disable(PermissionType privilege, String address); | |||||
| } | } | ||||
| @@ -8,22 +8,21 @@ | |||||
| */ | */ | ||||
| package test.com.jd.blockchain.ledger.data; | package test.com.jd.blockchain.ledger.data; | ||||
| import static org.junit.Assert.assertArrayEquals; | |||||
| import static org.junit.Assert.assertEquals; | |||||
| import org.junit.Before; | |||||
| import org.junit.Test; | |||||
| import com.jd.blockchain.binaryproto.BinaryProtocol; | import com.jd.blockchain.binaryproto.BinaryProtocol; | ||||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | import com.jd.blockchain.binaryproto.DataContractRegistry; | ||||
| import com.jd.blockchain.ledger.BytesValueEntry; | import com.jd.blockchain.ledger.BytesValueEntry; | ||||
| import com.jd.blockchain.ledger.DataAccountKVSetOperation; | import com.jd.blockchain.ledger.DataAccountKVSetOperation; | ||||
| import com.jd.blockchain.ledger.BytesValueType; | |||||
| import com.jd.blockchain.ledger.Operation; | import com.jd.blockchain.ledger.Operation; | ||||
| import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; | import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; | ||||
| import com.jd.blockchain.transaction.KVData; | import com.jd.blockchain.transaction.KVData; | ||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| import org.junit.Before; | |||||
| import org.junit.Test; | |||||
| import static org.junit.Assert.assertArrayEquals; | |||||
| import static org.junit.Assert.assertEquals; | |||||
| /** | /** | ||||
| * | * | ||||
| * @author shaozhuguang | * @author shaozhuguang | ||||
| @@ -43,11 +42,11 @@ public class DataAccountKVSetOpTemplateTest { | |||||
| String accountAddress = "zhangsandhakhdkah"; | String accountAddress = "zhangsandhakhdkah"; | ||||
| data = new DataAccountKVSetOpTemplate(Bytes.fromString(accountAddress)); | data = new DataAccountKVSetOpTemplate(Bytes.fromString(accountAddress)); | ||||
| KVData kvData1 = | KVData kvData1 = | ||||
| new KVData("test1", new BytesValueEntry(BytesValueType.TEXT, "zhangsan".getBytes()), 9999L); | |||||
| new KVData("test1", BytesValueEntry.fromText("zhangsan"), 9999L); | |||||
| KVData kvData2 = | KVData kvData2 = | ||||
| new KVData("test2", new BytesValueEntry(BytesValueType.TEXT, "lisi".getBytes()), 9990L); | |||||
| new KVData("test2", BytesValueEntry.fromText("lisi"), 9990L); | |||||
| KVData kvData3 = | KVData kvData3 = | ||||
| new KVData("test3", new BytesValueEntry(BytesValueType.TEXT, "wangwu".getBytes()), 1990L); | |||||
| new KVData("test3", BytesValueEntry.fromText("wangwu"), 1990L); | |||||
| data.set(kvData1); | data.set(kvData1); | ||||
| data.set(kvData2); | data.set(kvData2); | ||||
| data.set(kvData3); | data.set(kvData3); | ||||
| @@ -8,20 +8,19 @@ | |||||
| */ | */ | ||||
| package test.com.jd.blockchain.ledger.data; | package test.com.jd.blockchain.ledger.data; | ||||
| import static org.junit.Assert.assertArrayEquals; | |||||
| import static org.junit.Assert.assertEquals; | |||||
| import org.junit.Before; | |||||
| import org.junit.Test; | |||||
| import com.jd.blockchain.binaryproto.BinaryProtocol; | import com.jd.blockchain.binaryproto.BinaryProtocol; | ||||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | import com.jd.blockchain.binaryproto.DataContractRegistry; | ||||
| import com.jd.blockchain.ledger.BytesValueEntry; | import com.jd.blockchain.ledger.BytesValueEntry; | ||||
| import com.jd.blockchain.ledger.DataAccountKVSetOperation; | import com.jd.blockchain.ledger.DataAccountKVSetOperation; | ||||
| import com.jd.blockchain.ledger.BytesValueType; | |||||
| import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; | import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; | ||||
| import com.jd.blockchain.transaction.KVData; | import com.jd.blockchain.transaction.KVData; | ||||
| import org.junit.Before; | |||||
| import org.junit.Test; | |||||
| import static org.junit.Assert.assertArrayEquals; | |||||
| import static org.junit.Assert.assertEquals; | |||||
| /** | /** | ||||
| * | * | ||||
| * @author shaozhuguang | * @author shaozhuguang | ||||
| @@ -30,26 +29,26 @@ import static org.junit.Assert.assertEquals; | |||||
| */ | */ | ||||
| public class KVDataTest { | public class KVDataTest { | ||||
| private KVData kvData; | |||||
| @Before | |||||
| public void initKVData() throws Exception { | |||||
| DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class); | |||||
| String key = "test-key"; | |||||
| byte[] value = "test-value".getBytes(); | |||||
| long expectedVersion = 9999L; | |||||
| kvData = new KVData(key, new BytesValueEntry(BytesValueType.BYTES, value), expectedVersion); | |||||
| } | |||||
| @Test | |||||
| public void testSerialize_KVEntry() throws Exception { | |||||
| byte[] serialBytes = BinaryProtocol.encode(kvData, DataAccountKVSetOperation.KVWriteEntry.class); | |||||
| DataAccountKVSetOpTemplate.KVWriteEntry resolvedKvData = BinaryProtocol.decode(serialBytes); | |||||
| System.out.println("------Assert start ------"); | |||||
| assertEquals(resolvedKvData.getKey(), kvData.getKey()); | |||||
| assertEquals(resolvedKvData.getExpectedVersion(), kvData.getExpectedVersion()); | |||||
| assertArrayEquals(resolvedKvData.getValue().getValue().toBytes(), kvData.getValue().getValue().toBytes()); | |||||
| System.out.println("------Assert OK ------"); | |||||
| } | |||||
| private KVData kvData; | |||||
| @Before | |||||
| public void initKVData() throws Exception { | |||||
| DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class); | |||||
| String key = "test-key"; | |||||
| byte[] value = "test-value".getBytes(); | |||||
| long expectedVersion = 9999L; | |||||
| kvData = new KVData(key, BytesValueEntry.fromBytes(value), expectedVersion); | |||||
| } | |||||
| @Test | |||||
| public void testSerialize_KVEntry() throws Exception { | |||||
| byte[] serialBytes = BinaryProtocol.encode(kvData, DataAccountKVSetOperation.KVWriteEntry.class); | |||||
| DataAccountKVSetOpTemplate.KVWriteEntry resolvedKvData = BinaryProtocol.decode(serialBytes); | |||||
| System.out.println("------Assert start ------"); | |||||
| assertEquals(resolvedKvData.getKey(), kvData.getKey()); | |||||
| assertEquals(resolvedKvData.getExpectedVersion(), kvData.getExpectedVersion()); | |||||
| assertArrayEquals(resolvedKvData.getValue().getValue().toBytes(), kvData.getValue().getValue().toBytes()); | |||||
| System.out.println("------Assert OK ------"); | |||||
| } | |||||
| } | } | ||||
| @@ -22,7 +22,6 @@ import com.jd.blockchain.ledger.TransactionContent; | |||||
| import com.jd.blockchain.ledger.TransactionContentBody; | import com.jd.blockchain.ledger.TransactionContentBody; | ||||
| import com.jd.blockchain.transaction.BlockchainOperationFactory; | import com.jd.blockchain.transaction.BlockchainOperationFactory; | ||||
| import com.jd.blockchain.transaction.TxContentBlob; | import com.jd.blockchain.transaction.TxContentBlob; | ||||
| import com.jd.blockchain.utils.io.ByteArray; | |||||
| public class TxContentBlobTest { | public class TxContentBlobTest { | ||||
| @@ -48,7 +47,7 @@ public class TxContentBlobTest { | |||||
| contentBlob.setHash(contentHash); | contentBlob.setHash(contentHash); | ||||
| DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress()) | DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress()) | ||||
| .set("Name", ByteArray.fromString("AAA", "UTF-8"), -1).getOperation(); | |||||
| .setText("Name", "AAA", -1).getOperation(); | |||||
| contentBlob.addOperation(kvsetOP); | contentBlob.addOperation(kvsetOP); | ||||
| } | } | ||||
| @@ -37,7 +37,6 @@ import com.jd.blockchain.transaction.BlockchainOperationFactory; | |||||
| import com.jd.blockchain.transaction.DigitalSignatureBlob; | import com.jd.blockchain.transaction.DigitalSignatureBlob; | ||||
| import com.jd.blockchain.transaction.TxContentBlob; | import com.jd.blockchain.transaction.TxContentBlob; | ||||
| import com.jd.blockchain.transaction.TxRequestMessage; | import com.jd.blockchain.transaction.TxRequestMessage; | ||||
| import com.jd.blockchain.utils.io.ByteArray; | |||||
| /** | /** | ||||
| * | * | ||||
| @@ -204,7 +203,7 @@ public class TxRequestMessageTest { | |||||
| // contentBlob.setSubjectAccount(id.getAddress()); | // contentBlob.setSubjectAccount(id.getAddress()); | ||||
| // contentBlob.setSequenceNumber(1); | // contentBlob.setSequenceNumber(1); | ||||
| DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress()) | DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress()) | ||||
| .set("Name", ByteArray.fromString("AAA", "UTF-8"), -1).getOperation(); | |||||
| .setText("Name","AAA", -1).getOperation(); | |||||
| contentBlob.addOperation(kvsetOP); | contentBlob.addOperation(kvsetOP); | ||||
| return contentBlob; | return contentBlob; | ||||
| } | } | ||||
| @@ -1,14 +1,31 @@ | |||||
| package com.jd.blockchain.peer.web; | package com.jd.blockchain.peer.web; | ||||
| import com.jd.blockchain.contract.ContractException; | |||||
| import com.jd.blockchain.ledger.*; | |||||
| import com.jd.blockchain.utils.StringUtils; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.web.bind.annotation.*; | |||||
| import org.springframework.web.bind.annotation.PathVariable; | |||||
| import org.springframework.web.bind.annotation.RequestBody; | |||||
| import org.springframework.web.bind.annotation.RequestMapping; | |||||
| import org.springframework.web.bind.annotation.RequestMethod; | |||||
| import org.springframework.web.bind.annotation.RequestParam; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| import com.jd.blockchain.binaryproto.BinaryProtocol; | |||||
| import com.jd.blockchain.binaryproto.PrimitiveType; | |||||
| import com.jd.blockchain.contract.ContractException; | |||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.ledger.AccountHeader; | |||||
| import com.jd.blockchain.ledger.BytesValue; | |||||
| import com.jd.blockchain.ledger.KVDataEntry; | |||||
| import com.jd.blockchain.ledger.KVDataObject; | |||||
| import com.jd.blockchain.ledger.KVDataVO; | |||||
| import com.jd.blockchain.ledger.KVInfoVO; | |||||
| 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.UserInfo; | |||||
| import com.jd.blockchain.ledger.core.ContractAccountSet; | import com.jd.blockchain.ledger.core.ContractAccountSet; | ||||
| import com.jd.blockchain.ledger.core.DataAccount; | import com.jd.blockchain.ledger.core.DataAccount; | ||||
| import com.jd.blockchain.ledger.core.DataAccountSet; | import com.jd.blockchain.ledger.core.DataAccountSet; | ||||
| @@ -22,15 +39,12 @@ import com.jd.blockchain.transaction.BlockchainQueryService; | |||||
| import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
| import com.jd.blockchain.utils.QueryUtil; | import com.jd.blockchain.utils.QueryUtil; | ||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| @RestController | @RestController | ||||
| @RequestMapping(path = "/") | @RequestMapping(path = "/") | ||||
| public class LedgerQueryController implements BlockchainQueryService { | public class LedgerQueryController implements BlockchainQueryService { | ||||
| @Autowired | |||||
| private LedgerService ledgerService; | |||||
| @Autowired | |||||
| private LedgerService ledgerService; | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers") | @RequestMapping(method = RequestMethod.GET, path = "ledgers") | ||||
| @Override | @Override | ||||
| @@ -42,7 +56,8 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @Override | @Override | ||||
| public LedgerInfo getLedger(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { | public LedgerInfo getLedger(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { | ||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| //TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身; | |||||
| // TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher | |||||
| // ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身; | |||||
| LedgerInfo ledgerInfo = new LedgerInfo(); | LedgerInfo ledgerInfo = new LedgerInfo(); | ||||
| ledgerInfo.setHash(ledgerHash); | ledgerInfo.setHash(ledgerHash); | ||||
| ledgerInfo.setLatestBlockHash(ledger.getLatestBlockHash()); | ledgerInfo.setLatestBlockHash(ledger.getLatestBlockHash()); | ||||
| @@ -83,25 +98,27 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}") | ||||
| @Override | @Override | ||||
| public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "blockHeight") long blockHeight) { | |||||
| @PathVariable(name = "blockHeight") long blockHeight) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| //TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身; | |||||
| // TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher | |||||
| // ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身; | |||||
| return ledger.getBlock(blockHeight); | return ledger.getBlock(blockHeight); | ||||
| } | } | ||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}") | ||||
| @Override | @Override | ||||
| public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "blockHash") HashDigest blockHash) { | |||||
| @PathVariable(name = "blockHash") HashDigest blockHash) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| //TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身; | |||||
| // TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher | |||||
| // ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身; | |||||
| return ledger.getBlock(blockHash); | return ledger.getBlock(blockHash); | ||||
| } | } | ||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs/count") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs/count") | ||||
| @Override | @Override | ||||
| public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "blockHeight") long blockHeight) { | |||||
| @PathVariable(name = "blockHeight") long blockHeight) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getBlock(blockHeight); | LedgerBlock block = ledger.getBlock(blockHeight); | ||||
| TransactionSet txSet = ledger.getTransactionSet(block); | TransactionSet txSet = ledger.getTransactionSet(block); | ||||
| @@ -111,7 +128,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/txs/count") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/txs/count") | ||||
| @Override | @Override | ||||
| public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "blockHash") HashDigest blockHash) { | |||||
| @PathVariable(name = "blockHash") HashDigest blockHash) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getBlock(blockHash); | LedgerBlock block = ledger.getBlock(blockHash); | ||||
| TransactionSet txSet = ledger.getTransactionSet(block); | TransactionSet txSet = ledger.getTransactionSet(block); | ||||
| @@ -130,7 +147,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/accounts/count") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/accounts/count") | ||||
| @Override | @Override | ||||
| public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "blockHeight") long height) { | |||||
| @PathVariable(name = "blockHeight") long height) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getBlock(height); | LedgerBlock block = ledger.getBlock(height); | ||||
| DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | ||||
| @@ -140,7 +157,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/accounts/count") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/accounts/count") | ||||
| @Override | @Override | ||||
| public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "blockHash") HashDigest blockHash) { | |||||
| @PathVariable(name = "blockHash") HashDigest blockHash) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getBlock(blockHash); | LedgerBlock block = ledger.getBlock(blockHash); | ||||
| DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | ||||
| @@ -159,7 +176,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/users/count") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/users/count") | ||||
| @Override | @Override | ||||
| public long getUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public long getUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "blockHeight") long height) { | |||||
| @PathVariable(name = "blockHeight") long height) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getBlock(height); | LedgerBlock block = ledger.getBlock(height); | ||||
| UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | ||||
| @@ -169,7 +186,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/users/count") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/users/count") | ||||
| @Override | @Override | ||||
| public long getUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public long getUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "blockHash") HashDigest blockHash) { | |||||
| @PathVariable(name = "blockHash") HashDigest blockHash) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getBlock(blockHash); | LedgerBlock block = ledger.getBlock(blockHash); | ||||
| UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | ||||
| @@ -188,7 +205,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/contracts/count") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/contracts/count") | ||||
| @Override | @Override | ||||
| public long getContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public long getContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "blockHeight") long height) { | |||||
| @PathVariable(name = "blockHeight") long height) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getBlock(height); | LedgerBlock block = ledger.getBlock(height); | ||||
| ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | ||||
| @@ -198,7 +215,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/contracts/count") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/contracts/count") | ||||
| @Override | @Override | ||||
| public long getContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public long getContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "blockHash") HashDigest blockHash) { | |||||
| @PathVariable(name = "blockHash") HashDigest blockHash) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getBlock(blockHash); | LedgerBlock block = ledger.getBlock(blockHash); | ||||
| ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | ||||
| @@ -217,9 +234,9 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs") | ||||
| @Override | @Override | ||||
| public LedgerTransaction[] getTransactions(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public LedgerTransaction[] getTransactions(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "blockHeight") long blockHeight, | |||||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | |||||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | |||||
| @PathVariable(name = "blockHeight") long blockHeight, | |||||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | |||||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock ledgerBlock = ledger.getBlock(blockHeight); | LedgerBlock ledgerBlock = ledger.getBlock(blockHeight); | ||||
| @@ -230,8 +247,8 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(blockHeight - 1)).getTotalCount(); | lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(blockHeight - 1)).getTotalCount(); | ||||
| } | } | ||||
| int currentHeightTxTotalNums = (int)ledger.getTransactionSet(ledger.getBlock(blockHeight)).getTotalCount(); | |||||
| //取当前高度的增量交易数,在增量交易里进行查找 | |||||
| int currentHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(blockHeight)).getTotalCount(); | |||||
| // 取当前高度的增量交易数,在增量交易里进行查找 | |||||
| int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; | int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; | ||||
| // if (fromIndex < 0 || fromIndex >= currentHeightTxNums) { | // if (fromIndex < 0 || fromIndex >= currentHeightTxNums) { | ||||
| @@ -245,15 +262,15 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| // count = currentHeightTxNums - fromIndex; | // count = currentHeightTxNums - fromIndex; | ||||
| // } | // } | ||||
| int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex, count, currentHeightTxNums); | int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex, count, currentHeightTxNums); | ||||
| return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0] , indexAndCount[1]); | |||||
| return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0], indexAndCount[1]); | |||||
| } | } | ||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/txs") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/txs") | ||||
| @Override | @Override | ||||
| public LedgerTransaction[] getTransactions(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public LedgerTransaction[] getTransactions(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "blockHash") HashDigest blockHash, | |||||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | |||||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | |||||
| @PathVariable(name = "blockHash") HashDigest blockHash, | |||||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | |||||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock ledgerBlock = ledger.getBlock(blockHash); | LedgerBlock ledgerBlock = ledger.getBlock(blockHash); | ||||
| long height = ledgerBlock.getHeight(); | long height = ledgerBlock.getHeight(); | ||||
| @@ -264,8 +281,8 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height - 1)).getTotalCount(); | lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height - 1)).getTotalCount(); | ||||
| } | } | ||||
| int currentHeightTxTotalNums = (int)ledger.getTransactionSet(ledger.getBlock(height)).getTotalCount(); | |||||
| //取当前块hash的增量交易数,在增量交易里进行查找 | |||||
| int currentHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height)).getTotalCount(); | |||||
| // 取当前块hash的增量交易数,在增量交易里进行查找 | |||||
| int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; | int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; | ||||
| // if (fromIndex < 0 || fromIndex >= currentHeightTxNums) { | // if (fromIndex < 0 || fromIndex >= currentHeightTxNums) { | ||||
| @@ -279,13 +296,13 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| // count = currentHeightTxNums - fromIndex; | // count = currentHeightTxNums - fromIndex; | ||||
| // } | // } | ||||
| int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex, count, currentHeightTxNums); | int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex, count, currentHeightTxNums); | ||||
| return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0] , indexAndCount[1]); | |||||
| return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0], indexAndCount[1]); | |||||
| } | } | ||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/{contentHash}") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/{contentHash}") | ||||
| @Override | @Override | ||||
| public LedgerTransaction getTransactionByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public LedgerTransaction getTransactionByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "contentHash")HashDigest contentHash) { | |||||
| @PathVariable(name = "contentHash") HashDigest contentHash) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| TransactionSet txset = ledger.getTransactionSet(block); | TransactionSet txset = ledger.getTransactionSet(block); | ||||
| @@ -295,7 +312,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/state/{contentHash}") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/state/{contentHash}") | ||||
| @Override | @Override | ||||
| public TransactionState getTransactionStateByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public TransactionState getTransactionStateByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "contentHash") HashDigest contentHash) { | |||||
| @PathVariable(name = "contentHash") HashDigest contentHash) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| TransactionSet txset = ledger.getTransactionSet(block); | TransactionSet txset = ledger.getTransactionSet(block); | ||||
| @@ -305,7 +322,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users/address/{address}") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users/address/{address}") | ||||
| @Override | @Override | ||||
| public UserInfo getUser(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public UserInfo getUser(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "address") String address) { | |||||
| @PathVariable(name = "address") String address) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | ||||
| @@ -315,18 +332,18 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}") | ||||
| @Override | @Override | ||||
| public AccountHeader getDataAccount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public AccountHeader getDataAccount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "address") String address) { | |||||
| @PathVariable(name = "address") String address) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | ||||
| return dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | return dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | ||||
| } | } | ||||
| @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/{address}/entries") | |||||
| @RequestMapping(method = { RequestMethod.GET, | |||||
| RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries") | |||||
| @Override | @Override | ||||
| public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "address") String address, | |||||
| @RequestParam("keys") String... keys) { | |||||
| @PathVariable(name = "address") String address, @RequestParam("keys") String... keys) { | |||||
| if (keys == null || keys.length == 0) { | if (keys == null || keys.length == 0) { | ||||
| return null; | return null; | ||||
| } | } | ||||
| @@ -334,51 +351,50 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | ||||
| DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | ||||
| KVDataEntry[] entries = new KVDataEntry[keys.length]; | KVDataEntry[] entries = new KVDataEntry[keys.length]; | ||||
| long ver; | long ver; | ||||
| for (int i = 0; i < entries.length; i++) { | for (int i = 0; i < entries.length; i++) { | ||||
| ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); | ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); | ||||
| if (ver < 0) { | if (ver < 0) { | ||||
| entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); | |||||
| }else { | |||||
| byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); | |||||
| BytesValue decodeData = BinaryProtocol.decode(value); | |||||
| entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes()); | |||||
| entries[i] = new KVDataObject(keys[i], -1, null); | |||||
| } else { | |||||
| BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); | |||||
| entries[i] = new KVDataObject(keys[i], ver, value); | |||||
| } | } | ||||
| } | } | ||||
| return entries; | return entries; | ||||
| } | } | ||||
| @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version") | |||||
| @RequestMapping(method = { RequestMethod.GET, | |||||
| RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version") | |||||
| @Override | @Override | ||||
| public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "address") String address, | |||||
| @RequestBody KVInfoVO kvInfoVO) { | |||||
| //parse kvInfoVO; | |||||
| List<String> keyList = new ArrayList<>(); | |||||
| List<Long> versionList = new ArrayList<>(); | |||||
| if(kvInfoVO != null){ | |||||
| for(KVDataVO kvDataVO : kvInfoVO.getData()){ | |||||
| for(Long version : kvDataVO.getVersion()){ | |||||
| keyList.add(kvDataVO.getKey()); | |||||
| versionList.add(version); | |||||
| } | |||||
| } | |||||
| } | |||||
| String[] keys = keyList.toArray(new String[keyList.size()]); | |||||
| Long[] versions = versionList.toArray(new Long[versionList.size()]); | |||||
| @PathVariable(name = "address") String address, @RequestBody KVInfoVO kvInfoVO) { | |||||
| // parse kvInfoVO; | |||||
| List<String> keyList = new ArrayList<>(); | |||||
| List<Long> versionList = new ArrayList<>(); | |||||
| if (kvInfoVO != null) { | |||||
| for (KVDataVO kvDataVO : kvInfoVO.getData()) { | |||||
| for (Long version : kvDataVO.getVersion()) { | |||||
| keyList.add(kvDataVO.getKey()); | |||||
| versionList.add(version); | |||||
| } | |||||
| } | |||||
| } | |||||
| String[] keys = keyList.toArray(new String[keyList.size()]); | |||||
| Long[] versions = versionList.toArray(new Long[versionList.size()]); | |||||
| if (keys == null || keys.length == 0) { | if (keys == null || keys.length == 0) { | ||||
| return null; | |||||
| return null; | |||||
| } | } | ||||
| if (versions == null || versions.length == 0) { | if (versions == null || versions.length == 0) { | ||||
| return null; | return null; | ||||
| } | } | ||||
| if(keys.length != versions.length){ | |||||
| throw new ContractException("keys.length!=versions.length!"); | |||||
| } | |||||
| if (keys.length != versions.length) { | |||||
| throw new ContractException("keys.length!=versions.length!"); | |||||
| } | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| @@ -389,18 +405,17 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| long ver = -1; | long ver = -1; | ||||
| for (int i = 0; i < entries.length; i++) { | for (int i = 0; i < entries.length; i++) { | ||||
| // ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); | // ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); | ||||
| ver = versions[i]; | |||||
| ver = versions[i]; | |||||
| if (ver < 0) { | if (ver < 0) { | ||||
| entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); | |||||
| }else { | |||||
| if(dataAccount.getDataEntriesTotalCount()==0 || | |||||
| dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null){ | |||||
| //is the address is not exist; the result is null; | |||||
| entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); | |||||
| entries[i] = new KVDataObject(keys[i], -1, null); | |||||
| } else { | |||||
| if (dataAccount.getDataEntriesTotalCount() == 0 | |||||
| || dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null) { | |||||
| // is the address is not exist; the result is null; | |||||
| entries[i] = new KVDataObject(keys[i], -1, null); | |||||
| } else { | } else { | ||||
| byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); | |||||
| BytesValue decodeData = BinaryProtocol.decode(value); | |||||
| entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes()); | |||||
| BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); | |||||
| entries[i] = new KVDataObject(keys[i], ver, value); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -408,12 +423,13 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| return entries; | return entries; | ||||
| } | } | ||||
| @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries") | |||||
| @RequestMapping(method = { RequestMethod.GET, | |||||
| RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries") | |||||
| @Override | @Override | ||||
| public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public KVDataEntry[] 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) { | |||||
| @PathVariable(name = "address") String address, | |||||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | |||||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| @@ -426,7 +442,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries/count") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries/count") | ||||
| @Override | @Override | ||||
| public long getDataEntriesTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public long getDataEntriesTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "address") String address) { | |||||
| @PathVariable(name = "address") String address) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| @@ -439,7 +455,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}") | ||||
| @Override | @Override | ||||
| public AccountHeader getContract(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public AccountHeader getContract(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @PathVariable(name = "address") String address) { | |||||
| @PathVariable(name = "address") String address) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | ||||
| @@ -448,6 +464,7 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| /** | /** | ||||
| * get more users by fromIndex and count; | * get more users by fromIndex and count; | ||||
| * | |||||
| * @param ledgerHash | * @param ledgerHash | ||||
| * @param fromIndex | * @param fromIndex | ||||
| * @param count | * @param count | ||||
| @@ -456,44 +473,45 @@ public class LedgerQueryController implements BlockchainQueryService { | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users") | ||||
| @Override | @Override | ||||
| public AccountHeader[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public AccountHeader[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | |||||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | |||||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | |||||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | ||||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex,count,(int)userAccountSet.getTotalCount()); | |||||
| return userAccountSet.getAccounts(pages[0],pages[1]); | |||||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) userAccountSet.getTotalCount()); | |||||
| return userAccountSet.getAccounts(pages[0], pages[1]); | |||||
| } | } | ||||
| /** | /** | ||||
| * get more dataAccounts by fromIndex and count; | * get more dataAccounts by fromIndex and count; | ||||
| * | |||||
| * @param ledgerHash | * @param ledgerHash | ||||
| * @param fromIndex | * @param fromIndex | ||||
| * @param count | * @param count | ||||
| * @return | * @return | ||||
| */ | */ | ||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts") | ||||
| @Override | |||||
| @Override | |||||
| public AccountHeader[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | public AccountHeader[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | ||||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | |||||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | |||||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | |||||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
| LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
| DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | ||||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex,count,(int)dataAccountSet.getTotalCount()); | |||||
| return dataAccountSet.getAccounts(pages[0],pages[1]); | |||||
| } | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts") | |||||
| @Override | |||||
| public AccountHeader[] getContractAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | |||||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | |||||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | |||||
| LedgerBlock block = ledger.getLatestBlock(); | |||||
| ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | |||||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex,count,(int)contractAccountSet.getTotalCount()); | |||||
| return contractAccountSet.getAccounts(pages[0],pages[1]); | |||||
| } | |||||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotalCount()); | |||||
| return dataAccountSet.getAccounts(pages[0], pages[1]); | |||||
| } | |||||
| @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts") | |||||
| @Override | |||||
| public AccountHeader[] getContractAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | |||||
| @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, | |||||
| @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { | |||||
| LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | |||||
| LedgerBlock block = ledger.getLatestBlock(); | |||||
| ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | |||||
| int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) contractAccountSet.getTotalCount()); | |||||
| return contractAccountSet.getAccounts(pages[0], pages[1]); | |||||
| } | |||||
| } | } | ||||
| @@ -1,6 +1,6 @@ | |||||
| package com.jd.blockchain.sdk; | package com.jd.blockchain.sdk; | ||||
| import com.jd.blockchain.ledger.PrivilegeType; | |||||
| import com.jd.blockchain.ledger.PermissionType; | |||||
| /** | /** | ||||
| * 权限设置;<br> | * 权限设置;<br> | ||||
| @@ -16,6 +16,6 @@ public interface PrivilegeSetting { | |||||
| long getMask(String address); | long getMask(String address); | ||||
| boolean isEnable(String address, PrivilegeType privilege); | |||||
| boolean isEnable(String address, PermissionType privilege); | |||||
| } | } | ||||
| @@ -11,7 +11,6 @@ import com.jd.blockchain.crypto.HashDigest; | |||||
| import com.jd.blockchain.ledger.BlockchainIdentity; | import com.jd.blockchain.ledger.BlockchainIdentity; | ||||
| import com.jd.blockchain.ledger.KVDataEntry; | import com.jd.blockchain.ledger.KVDataEntry; | ||||
| import com.jd.blockchain.ledger.KVDataObject; | import com.jd.blockchain.ledger.KVDataObject; | ||||
| import com.jd.blockchain.utils.io.BytesUtils; | |||||
| /** | /** | ||||
| * 示例:一个“资产管理”智能合约的实现; | * 示例:一个“资产管理”智能合约的实现; | ||||
| @@ -53,14 +52,14 @@ public class AssetContractImpl implements EventProcessingAwire, AssetContract { | |||||
| // 计算资产的发行总数; | // 计算资产的发行总数; | ||||
| KVDataObject currTotal = (KVDataObject) kvEntries[0]; | KVDataObject currTotal = (KVDataObject) kvEntries[0]; | ||||
| long newTotal = currTotal.longValue() + amount; | long newTotal = currTotal.longValue() + amount; | ||||
| eventContext.getLedger().dataAccount(ASSET_ADDRESS).set(KEY_TOTAL, BytesUtils.toBytes(newTotal), | |||||
| eventContext.getLedger().dataAccount(ASSET_ADDRESS).setInt64(KEY_TOTAL, newTotal, | |||||
| currTotal.getVersion()); | currTotal.getVersion()); | ||||
| // 分配到持有者账户; | // 分配到持有者账户; | ||||
| KVDataObject holderAmount = (KVDataObject) kvEntries[1]; | KVDataObject holderAmount = (KVDataObject) kvEntries[1]; | ||||
| long newHodlerAmount = holderAmount.longValue() + amount; | long newHodlerAmount = holderAmount.longValue() + amount; | ||||
| eventContext.getLedger().dataAccount(ASSET_ADDRESS).set(assetHolderAddress, BytesUtils.toBytes(newHodlerAmount), | |||||
| holderAmount.getVersion()).set("K2", (byte[])null, -1).set("k3", (byte[])null, 3); | |||||
| eventContext.getLedger().dataAccount(ASSET_ADDRESS).setInt64(assetHolderAddress, newHodlerAmount, | |||||
| holderAmount.getVersion()).setText("K2", "info2", -1).setText("k3", "info3", 3); | |||||
| } | } | ||||
| @@ -59,7 +59,7 @@ public class SDKDemo_InsertData { | |||||
| // 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引; | // 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引; | ||||
| String commodityDataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | String commodityDataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | ||||
| Commodity commodity1 = new Commodity(); | Commodity commodity1 = new Commodity(); | ||||
| txTemp.dataAccount(commodityDataAccount).set("ASSET_CODE", commodity1.getCode().getBytes(), -1); | |||||
| txTemp.dataAccount(commodityDataAccount).setText("ASSET_CODE", commodity1.getCode(), -1); | |||||
| // TX 准备就绪; | // TX 准备就绪; | ||||
| PreparedTransaction prepTx = txTemp.prepare(); | PreparedTransaction prepTx = txTemp.prepare(); | ||||
| @@ -87,13 +87,13 @@ public class SDK_GateWay_BatchInsertData_Test_ { | |||||
| String dataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | String dataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | ||||
| String key1 = "jd_key1"; | String key1 = "jd_key1"; | ||||
| byte[] val1 = "www.jd.com".getBytes(); | |||||
| String val1 = "www.jd.com"; | |||||
| String key2 = "jd_key2"; | String key2 = "jd_key2"; | ||||
| byte[] val2 = "www.jd.com".getBytes(); | |||||
| String val2 = "www.jd.com"; | |||||
| txTemp.dataAccount(dataAccount).set(key1, val1, -1); | |||||
| txTemp.dataAccount(dataAccount).set(key2, val2, -1); | |||||
| txTemp.dataAccount(dataAccount).setText(key1, val1, -1); | |||||
| txTemp.dataAccount(dataAccount).setText(key2, val2, -1); | |||||
| // TX 准备就绪; | // TX 准备就绪; | ||||
| PreparedTransaction prepTx = txTemp.prepare(); | PreparedTransaction prepTx = txTemp.prepare(); | ||||
| @@ -84,9 +84,9 @@ public class SDK_GateWay_InsertData_Test_ { | |||||
| String dataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | String dataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | ||||
| String dataKey = "jd_code"; | String dataKey = "jd_code"; | ||||
| byte[] dataVal = "www.jd.com".getBytes(); | |||||
| String dataVal = "www.jd.com"; | |||||
| txTemp.dataAccount(dataAccount).set(dataKey, dataVal, -1); | |||||
| txTemp.dataAccount(dataAccount).setText(dataKey, dataVal, -1); | |||||
| // TX 准备就绪; | // TX 准备就绪; | ||||
| PreparedTransaction prepTx = txTemp.prepare(); | PreparedTransaction prepTx = txTemp.prepare(); | ||||
| @@ -1,13 +1,39 @@ | |||||
| package test.com.jd.blockchain.intgr; | package test.com.jd.blockchain.intgr; | ||||
| import java.io.File; | |||||
| import java.io.FileInputStream; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.util.Properties; | |||||
| import java.util.Random; | |||||
| import java.util.concurrent.CountDownLatch; | |||||
| import org.springframework.core.io.ClassPathResource; | |||||
| import com.jd.blockchain.consensus.ConsensusProvider; | import com.jd.blockchain.consensus.ConsensusProvider; | ||||
| import com.jd.blockchain.consensus.ConsensusProviders; | import com.jd.blockchain.consensus.ConsensusProviders; | ||||
| import com.jd.blockchain.consensus.ConsensusSettings; | import com.jd.blockchain.consensus.ConsensusSettings; | ||||
| import com.jd.blockchain.crypto.AddressEncoding; | |||||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | import com.jd.blockchain.crypto.AsymmetricKeypair; | ||||
| import com.jd.blockchain.crypto.Crypto; | |||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.crypto.PrivKey; | import com.jd.blockchain.crypto.PrivKey; | ||||
| import com.jd.blockchain.crypto.PubKey; | |||||
| import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; | import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; | ||||
| import com.jd.blockchain.ledger.*; | |||||
| import com.jd.blockchain.ledger.AccountHeader; | |||||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||||
| import com.jd.blockchain.ledger.BytesValue; | |||||
| import com.jd.blockchain.ledger.DataAccountKVSetOperation; | |||||
| import com.jd.blockchain.ledger.KVDataEntry; | |||||
| import com.jd.blockchain.ledger.LedgerBlock; | |||||
| import com.jd.blockchain.ledger.LedgerInfo; | |||||
| import com.jd.blockchain.ledger.ParticipantNode; | |||||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||||
| import com.jd.blockchain.ledger.TransactionResponse; | |||||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||||
| import com.jd.blockchain.ledger.UserInfo; | |||||
| import com.jd.blockchain.ledger.core.DataAccountSet; | |||||
| import com.jd.blockchain.ledger.core.LedgerManage; | import com.jd.blockchain.ledger.core.LedgerManage; | ||||
| import com.jd.blockchain.ledger.core.LedgerRepository; | import com.jd.blockchain.ledger.core.LedgerRepository; | ||||
| import com.jd.blockchain.ledger.core.impl.LedgerManager; | import com.jd.blockchain.ledger.core.impl.LedgerManager; | ||||
| @@ -23,18 +49,10 @@ import com.jd.blockchain.utils.Bytes; | |||||
| import com.jd.blockchain.utils.codec.HexUtils; | import com.jd.blockchain.utils.codec.HexUtils; | ||||
| import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; | import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; | ||||
| import com.jd.blockchain.utils.net.NetworkAddress; | import com.jd.blockchain.utils.net.NetworkAddress; | ||||
| import org.springframework.core.io.ClassPathResource; | |||||
| import test.com.jd.blockchain.intgr.IntegratedContext.Node; | import test.com.jd.blockchain.intgr.IntegratedContext.Node; | ||||
| import test.com.jd.blockchain.intgr.perf.LedgerInitializeWebTest; | import test.com.jd.blockchain.intgr.perf.LedgerInitializeWebTest; | ||||
| import java.io.File; | |||||
| import java.io.FileInputStream; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.util.Properties; | |||||
| import java.util.Random; | |||||
| import java.util.concurrent.CountDownLatch; | |||||
| public class IntegrationTest { | public class IntegrationTest { | ||||
| // 合约测试使用的初始化数据; | // 合约测试使用的初始化数据; | ||||
| BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate(); | BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate(); | ||||
| @@ -179,9 +197,9 @@ public class IntegrationTest { | |||||
| String dataAccount = dataAccountAddress; | String dataAccount = dataAccountAddress; | ||||
| String dataKey = "jingdong" + new Random().nextInt(100000); | String dataKey = "jingdong" + new Random().nextInt(100000); | ||||
| byte[] dataVal = "www.jd.com".getBytes(); | |||||
| String dataVal = "www.jd.com"; | |||||
| txTemp.dataAccount(dataAccount).set(dataKey, dataVal, -1); | |||||
| txTemp.dataAccount(dataAccount).setText(dataKey, dataVal, -1); | |||||
| // TX 准备就绪; | // TX 准备就绪; | ||||
| PreparedTransaction prepTx = txTemp.prepare(); | PreparedTransaction prepTx = txTemp.prepare(); | ||||
| @@ -530,87 +548,87 @@ public class IntegrationTest { | |||||
| } | } | ||||
| } | } | ||||
| // private LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash, | |||||
| // BlockchainService blockchainService, IntegratedContext context) { | |||||
| // // valid the basic data in contract; | |||||
| // prepareContractData(adminKey, ledgerHash, blockchainService, context); | |||||
| // | |||||
| // BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate(); | |||||
| // | |||||
| // // 定义交易; | |||||
| // TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||||
| // byte[] contractCode = getChainCodeBytes(); | |||||
| // | |||||
| // txTpl.users().register(userKey.getIdentity()); | |||||
| // | |||||
| // txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); | |||||
| // | |||||
| // // 签名; | |||||
| // PreparedTransaction ptx = txTpl.prepare(); | |||||
| // ptx.sign(adminKey); | |||||
| // | |||||
| // // 提交并等待共识返回; | |||||
| // TransactionResponse txResp = ptx.commit(); | |||||
| // | |||||
| // // 验证结果; | |||||
| // txResp.getContentHash(); | |||||
| // | |||||
| // Node node0 = context.getNode(0); | |||||
| // LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); | |||||
| // LedgerBlock block = ledgerOfNode0.getBlock(txResp.getBlockHeight()); | |||||
| // byte[] contractCodeInDb = ledgerOfNode0.getContractAccountSet(block).getContract(contractDeployKey.getAddress()) | |||||
| // .getChainCode(); | |||||
| // txContentHash = ptx.getHash(); | |||||
| // | |||||
| // // execute the contract; | |||||
| // testContractExe(adminKey, ledgerHash, userKey, blockchainService, context); | |||||
| // | |||||
| // return block; | |||||
| // } | |||||
| // private void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair userKey, | |||||
| // BlockchainService blockchainService, IntegratedContext context) { | |||||
| // LedgerInfo ledgerInfo = blockchainService.getLedger(ledgerHash); | |||||
| // LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight() - 1); | |||||
| // | |||||
| // // 定义交易; | |||||
| // TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||||
| // | |||||
| // txTpl.contractEvents().send(contractDeployKey.getAddress(), eventName, | |||||
| // ("888##abc##" + contractDataKey.getAddress() + "##" + previousBlock.getHash().toBase58() + "##" | |||||
| // + userKey.getAddress() + "##" + contractDeployKey.getAddress() + "##" + txContentHash.toBase58() | |||||
| // + "##SOME-VALUE").getBytes()); | |||||
| // | |||||
| // // 签名; | |||||
| // PreparedTransaction ptx = txTpl.prepare(); | |||||
| // ptx.sign(adminKey); | |||||
| // | |||||
| // // 提交并等待共识返回; | |||||
| // TransactionResponse txResp = ptx.commit(); | |||||
| // | |||||
| // // 验证结果; | |||||
| // txResp.getContentHash(); | |||||
| // | |||||
| // LedgerInfo latestLedgerInfo = blockchainService.getLedger(ledgerHash); | |||||
| // | |||||
| // Node node0 = context.getNode(0); | |||||
| // LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); | |||||
| // LedgerBlock backgroundLedgerBlock = ledgerOfNode0.retrieveLatestBlock(); | |||||
| // | |||||
| // // 验证合约中的赋值,外部可以获得; | |||||
| // DataAccountSet dataAccountSet = ledgerOfNode0.getDataAccountSet(backgroundLedgerBlock); | |||||
| // AsymmetricKeypair key = Crypto.getSignatureFunction("ED25519").generateKeypair(); | |||||
| // PubKey pubKey = key.getPubKey(); | |||||
| // Bytes dataAddress = AddressEncoding.generateAddress(pubKey); | |||||
| // | |||||
| // // 验证userAccount,从合约内部赋值,然后外部验证;由于目前不允许输入重复的key,所以在内部合约中构建的key,不便于在外展示,屏蔽之; | |||||
| // // UserAccountSet userAccountSet = | |||||
| // // ledgerOfNode0.getUserAccountSet(backgroundLedgerBlock); | |||||
| // // PubKey userPubKey = new PubKey(CryptoAlgorithm.ED25519, | |||||
| // // userPubKeyVal.getBytes()); | |||||
| // // String userAddress = AddressEncoding.generateAddress(userPubKey); | |||||
| // // assertEquals(userAddress, userAccountSet.getUser(userAddress).getAddress()); | |||||
| // } | |||||
| private LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash, | |||||
| BlockchainService blockchainService, IntegratedContext context) { | |||||
| // valid the basic data in contract; | |||||
| prepareContractData(adminKey, ledgerHash, blockchainService, context); | |||||
| BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate(); | |||||
| // 定义交易; | |||||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||||
| byte[] contractCode = getChainCodeBytes(); | |||||
| txTpl.users().register(userKey.getIdentity()); | |||||
| txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); | |||||
| // 签名; | |||||
| PreparedTransaction ptx = txTpl.prepare(); | |||||
| ptx.sign(adminKey); | |||||
| // 提交并等待共识返回; | |||||
| TransactionResponse txResp = ptx.commit(); | |||||
| // 验证结果; | |||||
| txResp.getContentHash(); | |||||
| Node node0 = context.getNode(0); | |||||
| LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); | |||||
| LedgerBlock block = ledgerOfNode0.getBlock(txResp.getBlockHeight()); | |||||
| byte[] contractCodeInDb = ledgerOfNode0.getContractAccountSet(block).getContract(contractDeployKey.getAddress()) | |||||
| .getChainCode(); | |||||
| txContentHash = ptx.getHash(); | |||||
| // execute the contract; | |||||
| testContractExe(adminKey, ledgerHash, userKey, blockchainService, context); | |||||
| return block; | |||||
| } | |||||
| private void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair userKey, | |||||
| BlockchainService blockchainService, IntegratedContext context) { | |||||
| LedgerInfo ledgerInfo = blockchainService.getLedger(ledgerHash); | |||||
| LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight() - 1); | |||||
| // 定义交易; | |||||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||||
| txTpl.contractEvents().send(contractDeployKey.getAddress(), eventName, | |||||
| ("888##abc##" + contractDataKey.getAddress() + "##" + previousBlock.getHash().toBase58() + "##" | |||||
| + userKey.getAddress() + "##" + contractDeployKey.getAddress() + "##" + txContentHash.toBase58() | |||||
| + "##SOME-VALUE").getBytes()); | |||||
| // 签名; | |||||
| PreparedTransaction ptx = txTpl.prepare(); | |||||
| ptx.sign(adminKey); | |||||
| // 提交并等待共识返回; | |||||
| TransactionResponse txResp = ptx.commit(); | |||||
| // 验证结果; | |||||
| txResp.getContentHash(); | |||||
| LedgerInfo latestLedgerInfo = blockchainService.getLedger(ledgerHash); | |||||
| Node node0 = context.getNode(0); | |||||
| LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); | |||||
| LedgerBlock backgroundLedgerBlock = ledgerOfNode0.retrieveLatestBlock(); | |||||
| // 验证合约中的赋值,外部可以获得; | |||||
| DataAccountSet dataAccountSet = ledgerOfNode0.getDataAccountSet(backgroundLedgerBlock); | |||||
| AsymmetricKeypair key = Crypto.getSignatureFunction("ED25519").generateKeypair(); | |||||
| PubKey pubKey = key.getPubKey(); | |||||
| Bytes dataAddress = AddressEncoding.generateAddress(pubKey); | |||||
| // 验证userAccount,从合约内部赋值,然后外部验证;由于目前不允许输入重复的key,所以在内部合约中构建的key,不便于在外展示,屏蔽之; | |||||
| // UserAccountSet userAccountSet = | |||||
| // ledgerOfNode0.getUserAccountSet(backgroundLedgerBlock); | |||||
| // PubKey userPubKey = new PubKey(CryptoAlgorithm.ED25519, | |||||
| // userPubKeyVal.getBytes()); | |||||
| // String userAddress = AddressEncoding.generateAddress(userPubKey); | |||||
| // assertEquals(userAddress, userAccountSet.getUser(userAddress).getAddress()); | |||||
| } | |||||
| private void prepareContractData(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService, | private void prepareContractData(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService, | ||||
| IntegratedContext context) { | IntegratedContext context) { | ||||
| @@ -620,11 +638,11 @@ public class IntegrationTest { | |||||
| // 注册数据账户,并验证最终写入; | // 注册数据账户,并验证最终写入; | ||||
| txTpl.dataAccounts().register(contractDataKey.getIdentity()); | txTpl.dataAccounts().register(contractDataKey.getIdentity()); | ||||
| DataAccountKVSetOperation kvsetOP = txTpl.dataAccount(contractDataKey.getAddress()) | DataAccountKVSetOperation kvsetOP = txTpl.dataAccount(contractDataKey.getAddress()) | ||||
| .set("A", "Value_A_0".getBytes(), -1).set("B", "Value_B_0".getBytes(), -1) | |||||
| .set(KEY_TOTAL, "total value,dataAccount".getBytes(), -1) | |||||
| .set(KEY_ABC, "abc value,dataAccount".getBytes(), -1) | |||||
| .setText("A", "Value_A_0", -1).setText("B", "Value_B_0", -1) | |||||
| .setText(KEY_TOTAL, "total value,dataAccount", -1) | |||||
| .setText(KEY_ABC, "abc value,dataAccount", -1) | |||||
| // 所有的模拟数据都在这个dataAccount中填充; | // 所有的模拟数据都在这个dataAccount中填充; | ||||
| .set("ledgerHash", ledgerHash.getRawDigest(), -1).getOperation(); | |||||
| .setBytes("ledgerHash", ledgerHash.getRawDigest(), -1).getOperation(); | |||||
| // 签名; | // 签名; | ||||
| PreparedTransaction ptx = txTpl.prepare(); | PreparedTransaction ptx = txTpl.prepare(); | ||||
| @@ -638,9 +656,9 @@ public class IntegrationTest { | |||||
| LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); | LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); | ||||
| LedgerBlock block = ledgerOfNode0.getBlock(txResp.getBlockHeight()); | LedgerBlock block = ledgerOfNode0.getBlock(txResp.getBlockHeight()); | ||||
| byte[] val1InDb = ledgerOfNode0.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress()) | |||||
| BytesValue val1InDb = ledgerOfNode0.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress()) | |||||
| .getBytes("A"); | .getBytes("A"); | ||||
| byte[] val2InDb = ledgerOfNode0.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress()) | |||||
| BytesValue val2InDb = ledgerOfNode0.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress()) | |||||
| .getBytes(KEY_TOTAL); | .getBytes(KEY_TOTAL); | ||||
| } | } | ||||
| @@ -16,9 +16,9 @@ import com.jd.blockchain.binaryproto.DataContractRegistry; | |||||
| import com.jd.blockchain.consensus.ConsensusProvider; | import com.jd.blockchain.consensus.ConsensusProvider; | ||||
| import com.jd.blockchain.consensus.ConsensusProviders; | import com.jd.blockchain.consensus.ConsensusProviders; | ||||
| import com.jd.blockchain.consensus.ConsensusSettings; | import com.jd.blockchain.consensus.ConsensusSettings; | ||||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | import com.jd.blockchain.crypto.AsymmetricKeypair; | ||||
| import com.jd.blockchain.crypto.Crypto; | import com.jd.blockchain.crypto.Crypto; | ||||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||||
| import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
| import com.jd.blockchain.crypto.PrivKey; | import com.jd.blockchain.crypto.PrivKey; | ||||
| import com.jd.blockchain.ledger.BlockchainIdentity; | import com.jd.blockchain.ledger.BlockchainIdentity; | ||||
| @@ -54,7 +54,6 @@ import com.jd.blockchain.transaction.TxBuilder; | |||||
| import com.jd.blockchain.utils.ArgumentSet; | import com.jd.blockchain.utils.ArgumentSet; | ||||
| import com.jd.blockchain.utils.ConsoleUtils; | import com.jd.blockchain.utils.ConsoleUtils; | ||||
| import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; | import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; | ||||
| import com.jd.blockchain.utils.io.BytesUtils; | |||||
| import com.jd.blockchain.utils.io.FileUtils; | import com.jd.blockchain.utils.io.FileUtils; | ||||
| import com.jd.blockchain.utils.net.NetworkAddress; | import com.jd.blockchain.utils.net.NetworkAddress; | ||||
| @@ -408,8 +407,8 @@ public class LedgerPerformanceTest { | |||||
| // BlockchainKeyPair dataAccountKey = | // BlockchainKeyPair dataAccountKey = | ||||
| // BlockchainKeyGenerator.getInstance().generate(); | // BlockchainKeyGenerator.getInstance().generate(); | ||||
| BlockchainIdentity targetAccount = dataAccounts[count % dataAccounts.length]; | BlockchainIdentity targetAccount = dataAccounts[count % dataAccounts.length]; | ||||
| txbuilder.dataAccount(targetAccount.getAddress()).set("key-" + startTs + "-" + i, | |||||
| BytesUtils.toBytes("value-" + i), -1L); | |||||
| txbuilder.dataAccount(targetAccount.getAddress()).setText("key-" + startTs + "-" + i, | |||||
| "value-" + i, -1L); | |||||
| TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest(); | TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest(); | ||||
| reqBuilder.signAsEndpoint(adminKey); | reqBuilder.signAsEndpoint(adminKey); | ||||
| txList.add(reqBuilder.buildRequest()); | txList.add(reqBuilder.buildRequest()); | ||||
| @@ -46,7 +46,6 @@ import java.util.concurrent.atomic.AtomicLong; | |||||
| import static org.junit.Assert.*; | import static org.junit.Assert.*; | ||||
| /** | /** | ||||
| * | * | ||||
| * @author shaozhuguang | * @author shaozhuguang | ||||
| @@ -57,436 +56,440 @@ import static org.junit.Assert.*; | |||||
| public class IntegrationBase { | public class IntegrationBase { | ||||
| public static String KEY_TOTAL = "total"; | public static String KEY_TOTAL = "total"; | ||||
| static { | |||||
| DataContractRegistry.register(LedgerInitOperation.class); | |||||
| DataContractRegistry.register(UserRegisterOperation.class); | |||||
| } | |||||
| static { | |||||
| DataContractRegistry.register(LedgerInitOperation.class); | |||||
| DataContractRegistry.register(UserRegisterOperation.class); | |||||
| } | |||||
| public static final String PASSWORD = "abc"; | |||||
| public static final String PASSWORD = "abc"; | |||||
| public static final String[] PUB_KEYS = { "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9", | |||||
| "3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX", | |||||
| "3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x", | |||||
| "3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk" }; | |||||
| public static final String[] PUB_KEYS = { "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9", | |||||
| "3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX", | |||||
| "3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x", | |||||
| "3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk" }; | |||||
| public static final String[] PRIV_KEYS = { | |||||
| "177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x", | |||||
| "177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT", | |||||
| "177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF", | |||||
| "177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns" }; | |||||
| public static final String[] PRIV_KEYS = { | |||||
| "177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x", | |||||
| "177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT", | |||||
| "177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF", | |||||
| "177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns" }; | |||||
| public static final AtomicLong validLong = new AtomicLong(); | |||||
| public static final AtomicLong validLong = new AtomicLong(); | |||||
| public static KeyPairResponse testSDK_RegisterUser(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService) { | |||||
| // 注册用户,并验证最终写入; | |||||
| BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); | |||||
| public static KeyPairResponse testSDK_RegisterUser(AsymmetricKeypair adminKey, HashDigest ledgerHash, | |||||
| BlockchainService blockchainService) { | |||||
| // 注册用户,并验证最终写入; | |||||
| BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); | |||||
| // 定义交易; | |||||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||||
| txTpl.users().register(user.getIdentity()); | |||||
| // 定义交易; | |||||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||||
| txTpl.users().register(user.getIdentity()); | |||||
| // 签名; | |||||
| PreparedTransaction ptx = txTpl.prepare(); | |||||
| // 签名; | |||||
| PreparedTransaction ptx = txTpl.prepare(); | |||||
| HashDigest transactionHash = ptx.getHash(); | |||||
| HashDigest transactionHash = ptx.getHash(); | |||||
| ptx.sign(adminKey); | |||||
| ptx.sign(adminKey); | |||||
| // 提交并等待共识返回; | |||||
| TransactionResponse txResp = ptx.commit(); | |||||
| // 提交并等待共识返回; | |||||
| TransactionResponse txResp = ptx.commit(); | |||||
| KeyPairResponse keyPairResponse = new KeyPairResponse(); | |||||
| keyPairResponse.keyPair = user; | |||||
| keyPairResponse.txResp = txResp; | |||||
| keyPairResponse.txHash = transactionHash; | |||||
| return keyPairResponse; | |||||
| } | |||||
| KeyPairResponse keyPairResponse = new KeyPairResponse(); | |||||
| keyPairResponse.keyPair = user; | |||||
| keyPairResponse.txResp = txResp; | |||||
| keyPairResponse.txHash = transactionHash; | |||||
| return keyPairResponse; | |||||
| } | |||||
| public static KeyPairResponse testSDK_RegisterDataAccount(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService) { | |||||
| // 注册数据账户,并验证最终写入; | |||||
| BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||||
| public static KeyPairResponse testSDK_RegisterDataAccount(AsymmetricKeypair adminKey, HashDigest ledgerHash, | |||||
| BlockchainService blockchainService) { | |||||
| // 注册数据账户,并验证最终写入; | |||||
| BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||||
| // 定义交易; | |||||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||||
| txTpl.dataAccounts().register(dataAccount.getIdentity()); | |||||
| // 定义交易; | |||||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||||
| txTpl.dataAccounts().register(dataAccount.getIdentity()); | |||||
| txTpl.dataAccount(dataAccount.getAddress()).set("total", 200, -1); | txTpl.dataAccount(dataAccount.getAddress()).set("total", 200, -1); | ||||
| // txTpl.dataAccount(dataAccount.getAddress()).set("param1", "v", -1); | // txTpl.dataAccount(dataAccount.getAddress()).set("param1", "v", -1); | ||||
| // txTpl.dataAccount(dataAccount.getAddress()).set("param2", 200, -1); | // txTpl.dataAccount(dataAccount.getAddress()).set("param2", 200, -1); | ||||
| // 签名; | |||||
| PreparedTransaction ptx = txTpl.prepare(); | |||||
| HashDigest transactionHash = ptx.getHash(); | |||||
| ptx.sign(adminKey); | |||||
| // 提交并等待共识返回; | |||||
| TransactionResponse txResp = ptx.commit(); | |||||
| KeyPairResponse keyPairResponse = new KeyPairResponse(); | |||||
| keyPairResponse.keyPair = dataAccount; | |||||
| keyPairResponse.txResp = txResp; | |||||
| keyPairResponse.txHash = transactionHash; | |||||
| return keyPairResponse; | |||||
| } | |||||
| public static KvResponse testSDK_InsertData(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService, | |||||
| Bytes dataAccount) { | |||||
| // 在本地定义注册账号的 TX; | |||||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); | |||||
| // -------------------------------------- | |||||
| // 将商品信息写入到指定的账户中; | |||||
| // 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引; | |||||
| String dataKey = "jingdong" + System.currentTimeMillis() + new Random().nextInt(100000); | |||||
| byte[] dataVal = "www.jd.com".getBytes(); | |||||
| txTemp.dataAccount(dataAccount).set(dataKey, dataVal, -1); | |||||
| // TX 准备就绪; | |||||
| PreparedTransaction prepTx = txTemp.prepare(); | |||||
| HashDigest transactionHash = prepTx.getHash(); | |||||
| // 使用私钥进行签名; | |||||
| prepTx.sign(adminKey); | |||||
| // 提交交易; | |||||
| TransactionResponse txResp = prepTx.commit(); | |||||
| KvResponse kvResponse = new KvResponse(); | |||||
| kvResponse.ledgerHash = ledgerHash; | |||||
| kvResponse.dataAccount = dataAccount; | |||||
| kvResponse.txResp = txResp; | |||||
| kvResponse.txHash = transactionHash; | |||||
| kvResponse.key = dataKey; | |||||
| kvResponse.value = dataVal; | |||||
| return kvResponse; | |||||
| } | |||||
| public static void validKeyPair(IntegrationBase.KeyPairResponse keyPairResponse, LedgerRepository ledgerRepository, KeyPairType keyPairType) { | |||||
| TransactionResponse txResp = keyPairResponse.txResp; | |||||
| HashDigest transactionHash = keyPairResponse.txHash; | |||||
| BlockchainKeypair keyPair = keyPairResponse.keyPair; | |||||
| long index = validLong.incrementAndGet(); | |||||
| System.out.printf("validKeyPair start %s \r\n", index); | |||||
| ledgerRepository.retrieveLatestBlock(); | |||||
| assertEquals(txResp.getExecutionState(), TransactionState.SUCCESS); | |||||
| assertEquals(txResp.getBlockHeight(), ledgerRepository.getLatestBlockHeight()); | |||||
| assertEquals(txResp.getContentHash(), transactionHash); | |||||
| assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash()); | |||||
| if (keyPairType == KeyPairType.USER) { | |||||
| assertTrue(ledgerRepository.getUserAccountSet(ledgerRepository.getLatestBlock()).contains(keyPair.getAddress())); | |||||
| } | |||||
| if (keyPairType == KeyPairType.DATAACCOUNT) { | |||||
| assertNotNull(ledgerRepository.getDataAccountSet(ledgerRepository.getLatestBlock()) | |||||
| .getDataAccount(keyPair.getAddress())); | |||||
| } | |||||
| System.out.printf("validKeyPair end %s \r\n", index); | |||||
| } | |||||
| public static void validKeyPair(IntegrationBase.KeyPairResponse keyPairResponse, LedgerRepository ledgerRepository, KeyPairType keyPairType, CountDownLatch countDownLatch) { | |||||
| TransactionResponse txResp = keyPairResponse.txResp; | |||||
| HashDigest transactionHash = keyPairResponse.txHash; | |||||
| BlockchainKeypair keyPair = keyPairResponse.keyPair; | |||||
| ledgerRepository.retrieveLatestBlock(); | |||||
| assertEquals(txResp.getExecutionState(), TransactionState.SUCCESS); | |||||
| assertEquals(txResp.getBlockHeight(), ledgerRepository.getLatestBlockHeight()); | |||||
| assertEquals(txResp.getContentHash(), transactionHash); | |||||
| assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash()); | |||||
| if (keyPairType == KeyPairType.USER) { | |||||
| assertTrue(ledgerRepository.getUserAccountSet(ledgerRepository.getLatestBlock()).contains(keyPair.getAddress())); | |||||
| } | |||||
| if (keyPairType == KeyPairType.DATAACCOUNT) { | |||||
| assertNotNull(ledgerRepository.getDataAccountSet(ledgerRepository.getLatestBlock()) | |||||
| .getDataAccount(keyPair.getAddress())); | |||||
| } | |||||
| countDownLatch.countDown(); | |||||
| } | |||||
| public static void validKvWrite(IntegrationBase.KvResponse kvResponse, LedgerRepository ledgerRepository, BlockchainService blockchainService) { | |||||
| // 先验证应答 | |||||
| TransactionResponse txResp = kvResponse.getTxResp(); | |||||
| HashDigest transactionHash = kvResponse.getTxHash(); | |||||
| HashDigest ledgerHash = kvResponse.getLedgerHash(); | |||||
| String daAddress = kvResponse.getDataAccount().toBase58(); | |||||
| String dataKey = kvResponse.getKey(); | |||||
| byte[] dataVal = kvResponse.getValue(); | |||||
| ledgerRepository.retrieveLatestBlock(); | |||||
| assertEquals(TransactionState.SUCCESS, txResp.getExecutionState()); | |||||
| assertEquals(txResp.getBlockHeight(), ledgerRepository.getLatestBlockHeight()); | |||||
| assertEquals(txResp.getContentHash(), transactionHash); | |||||
| assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash()); | |||||
| KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, daAddress, dataKey); | |||||
| for (KVDataEntry kvDataEntry : kvDataEntries) { | |||||
| assertEquals(dataKey, kvDataEntry.getKey()); | |||||
| String valHexText = (String) kvDataEntry.getValue(); | |||||
| byte[] valBytes = HexUtils.decode(valHexText); | |||||
| boolean isEqual = Arrays.equals(dataVal, valBytes); | |||||
| assertTrue(isEqual); | |||||
| } | |||||
| } | |||||
| public static LedgerRepository[] buildLedgers(LedgerBindingConfig[] bindingConfigs, DbConnectionFactory[] dbConnectionFactories){ | |||||
| int[] ids = {0, 1, 2, 3}; | |||||
| LedgerRepository[] ledgers = new LedgerRepository[ids.length]; | |||||
| LedgerManager[] ledgerManagers = new LedgerManager[ids.length]; | |||||
| for (int i = 0; i < ids.length; i++) { | |||||
| ledgerManagers[i] = new LedgerManager(); | |||||
| HashDigest ledgerHash = bindingConfigs[0].getLedgerHashs()[0]; | |||||
| DbConnection conn = dbConnectionFactories[i].connect(bindingConfigs[i].getLedger(ledgerHash).getDbConnection().getUri()); | |||||
| ledgers[i] = ledgerManagers[i].register(ledgerHash, conn.getStorageService()); | |||||
| } | |||||
| return ledgers; | |||||
| } | |||||
| public static void testConsistencyAmongNodes(LedgerRepository[] ledgers) { | |||||
| LedgerRepository ledger0 = ledgers[0]; | |||||
| LedgerBlock latestBlock0 = ledger0.retrieveLatestBlock(); | |||||
| for (int i = 1; i < ledgers.length; i++) { | |||||
| LedgerRepository otherLedger = ledgers[i]; | |||||
| LedgerBlock otherLatestBlock = otherLedger.retrieveLatestBlock(); | |||||
| assertEquals(ledger0.getHash(), otherLedger.getHash()); | |||||
| assertEquals(ledger0.getLatestBlockHeight(), otherLedger.getLatestBlockHeight()); | |||||
| assertEquals(ledger0.getLatestBlockHash(), otherLedger.getLatestBlockHash()); | |||||
| assertEquals(latestBlock0.getHeight(), otherLatestBlock.getHeight()); | |||||
| assertEquals(latestBlock0.getHash(), otherLatestBlock.getHash()); | |||||
| assertEquals(latestBlock0.getAdminAccountHash(), otherLatestBlock.getAdminAccountHash()); | |||||
| assertEquals(latestBlock0.getTransactionSetHash(), otherLatestBlock.getTransactionSetHash()); | |||||
| assertEquals(latestBlock0.getUserAccountSetHash(), otherLatestBlock.getUserAccountSetHash()); | |||||
| assertEquals(latestBlock0.getDataAccountSetHash(), otherLatestBlock.getDataAccountSetHash()); | |||||
| assertEquals(latestBlock0.getContractAccountSetHash(), otherLatestBlock.getContractAccountSetHash()); | |||||
| assertEquals(latestBlock0.getPreviousHash(), otherLatestBlock.getPreviousHash()); | |||||
| } | |||||
| } | |||||
| public static PeerTestRunner[] peerNodeStart(HashDigest ledgerHash, String dbType) { | |||||
| NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 12000); | |||||
| LedgerBindingConfig bindingConfig0 = loadBindingConfig(0, ledgerHash, dbType); | |||||
| PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, bindingConfig0); | |||||
| NetworkAddress peerSrvAddr1 = new NetworkAddress("127.0.0.1", 12010); | |||||
| LedgerBindingConfig bindingConfig1 = loadBindingConfig(1, ledgerHash, dbType); | |||||
| PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, bindingConfig1); | |||||
| NetworkAddress peerSrvAddr2 = new NetworkAddress("127.0.0.1", 12020); | |||||
| LedgerBindingConfig bindingConfig2 = loadBindingConfig(2, ledgerHash, dbType); | |||||
| PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, bindingConfig2); | |||||
| NetworkAddress peerSrvAddr3 = new NetworkAddress("127.0.0.1", 12030); | |||||
| LedgerBindingConfig bindingConfig3 = loadBindingConfig(3, ledgerHash, dbType); | |||||
| PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, bindingConfig3); | |||||
| ThreadInvoker.AsyncCallback<Object> peerStarting0 = peer0.start(); | |||||
| ThreadInvoker.AsyncCallback<Object> peerStarting1 = peer1.start(); | |||||
| ThreadInvoker.AsyncCallback<Object> peerStarting2 = peer2.start(); | |||||
| ThreadInvoker.AsyncCallback<Object> peerStarting3 = peer3.start(); | |||||
| peerStarting0.waitReturn(); | |||||
| peerStarting1.waitReturn(); | |||||
| peerStarting2.waitReturn(); | |||||
| peerStarting3.waitReturn(); | |||||
| return new PeerTestRunner[]{peer0, peer1, peer2, peer3}; | |||||
| } | |||||
| public static LedgerBindingConfig loadBindingConfig(int id, HashDigest ledgerHash, String dbType) { | |||||
| LedgerBindingConfig ledgerBindingConfig; | |||||
| String newLedger = ledgerHash.toBase58(); | |||||
| String resourceClassPath = "ledger-binding-" + dbType + "-" + id + ".conf"; | |||||
| String ledgerBindingUrl = IntegrationBase.class.getResource("/") + resourceClassPath; | |||||
| try { | |||||
| URL url = new URL(ledgerBindingUrl); | |||||
| File ledgerBindingConf = new File(url.getPath()); | |||||
| System.out.printf("URL-ledgerBindingConf = %s \r\n", url.getPath()); | |||||
| if (ledgerBindingConf.exists()) { | |||||
| List<String> readLines = FileUtils.readLines(ledgerBindingConf); | |||||
| List<String> writeLines = new ArrayList<>(); | |||||
| if (readLines != null && !readLines.isEmpty()) { | |||||
| String oldLedgerLine = null; | |||||
| for (String readLine : readLines) { | |||||
| if (readLine.startsWith("ledger")) { | |||||
| oldLedgerLine = readLine; | |||||
| break; | |||||
| } | |||||
| } | |||||
| String[] oldLedgerArray = oldLedgerLine.split("="); | |||||
| String oldLedger = oldLedgerArray[1]; | |||||
| if (!oldLedger.equalsIgnoreCase(newLedger)) { | |||||
| for (String readLine : readLines) { | |||||
| String newLine = readLine.replace(oldLedger, newLedger); | |||||
| if (dbType.equalsIgnoreCase("rocksdb")) { | |||||
| if (newLine.contains("db.uri")) { | |||||
| String[] propArray = newLine.split("="); | |||||
| String dbKey = propArray[0]; | |||||
| String dbValue = LedgerInitConsensusConfig.rocksdbConnectionStrings[id]; | |||||
| newLine = dbKey + "=" + dbValue; | |||||
| } | |||||
| } | |||||
| writeLines.add(newLine); | |||||
| } | |||||
| } else if(dbType.equalsIgnoreCase("rocksdb")) { | |||||
| for (String readLine : readLines) { | |||||
| String newLine = readLine; | |||||
| if (readLine.contains("db.uri")) { | |||||
| String[] propArray = readLine.split("="); | |||||
| String dbKey = propArray[0]; | |||||
| String dbValue = LedgerInitConsensusConfig.rocksdbConnectionStrings[id]; | |||||
| newLine = dbKey + "=" + dbValue; | |||||
| } | |||||
| writeLines.add(newLine); | |||||
| } | |||||
| } | |||||
| if (!writeLines.isEmpty()) { | |||||
| FileUtils.writeLines(ledgerBindingConf, writeLines); | |||||
| } | |||||
| } | |||||
| } | |||||
| } catch (Exception e) { | |||||
| } | |||||
| ClassPathResource res = new ClassPathResource(resourceClassPath); | |||||
| try(InputStream in = res.getInputStream()){ | |||||
| ledgerBindingConfig = LedgerBindingConfig.resolve(in); | |||||
| } catch (IOException e) { | |||||
| throw new IllegalStateException(e.getMessage(), e); | |||||
| } | |||||
| return ledgerBindingConfig; | |||||
| } | |||||
| public static class KeyPairResponse { | |||||
| HashDigest txHash; | |||||
| BlockchainKeypair keyPair; | |||||
| TransactionResponse txResp; | |||||
| public BlockchainKeypair getKeyPair() { | |||||
| return keyPair; | |||||
| } | |||||
| public TransactionResponse getTxResp() { | |||||
| return txResp; | |||||
| } | |||||
| public HashDigest getTxHash() { | |||||
| return txHash; | |||||
| } | |||||
| } | |||||
| public static class KvResponse { | |||||
| Bytes dataAccount; | |||||
| HashDigest ledgerHash; | |||||
| HashDigest txHash; | |||||
| TransactionResponse txResp; | |||||
| String key; | |||||
| byte[] value; | |||||
| public HashDigest getTxHash() { | |||||
| return txHash; | |||||
| } | |||||
| public TransactionResponse getTxResp() { | |||||
| return txResp; | |||||
| } | |||||
| public String getKey() { | |||||
| return key; | |||||
| } | |||||
| public byte[] getValue() { | |||||
| return value; | |||||
| } | |||||
| public HashDigest getLedgerHash() { | |||||
| return ledgerHash; | |||||
| } | |||||
| public Bytes getDataAccount() { | |||||
| return dataAccount; | |||||
| } | |||||
| } | |||||
| public enum KeyPairType { | |||||
| USER, | |||||
| DATAACCOUNT | |||||
| } | |||||
| // 合约测试使用的初始化数据; | |||||
| // 签名; | |||||
| PreparedTransaction ptx = txTpl.prepare(); | |||||
| HashDigest transactionHash = ptx.getHash(); | |||||
| ptx.sign(adminKey); | |||||
| // 提交并等待共识返回; | |||||
| TransactionResponse txResp = ptx.commit(); | |||||
| KeyPairResponse keyPairResponse = new KeyPairResponse(); | |||||
| keyPairResponse.keyPair = dataAccount; | |||||
| keyPairResponse.txResp = txResp; | |||||
| keyPairResponse.txHash = transactionHash; | |||||
| return keyPairResponse; | |||||
| } | |||||
| public static KvResponse testSDK_InsertData(AsymmetricKeypair adminKey, HashDigest ledgerHash, | |||||
| BlockchainService blockchainService, Bytes dataAccount) { | |||||
| // 在本地定义注册账号的 TX; | |||||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); | |||||
| // -------------------------------------- | |||||
| // 将商品信息写入到指定的账户中; | |||||
| // 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引; | |||||
| String dataKey = "jingdong" + System.currentTimeMillis() + new Random().nextInt(100000); | |||||
| String dataVal = "www.jd.com"; | |||||
| txTemp.dataAccount(dataAccount).setText(dataKey, dataVal, -1); | |||||
| // TX 准备就绪; | |||||
| PreparedTransaction prepTx = txTemp.prepare(); | |||||
| HashDigest transactionHash = prepTx.getHash(); | |||||
| // 使用私钥进行签名; | |||||
| prepTx.sign(adminKey); | |||||
| // 提交交易; | |||||
| TransactionResponse txResp = prepTx.commit(); | |||||
| KvResponse kvResponse = new KvResponse(); | |||||
| kvResponse.ledgerHash = ledgerHash; | |||||
| kvResponse.dataAccount = dataAccount; | |||||
| kvResponse.txResp = txResp; | |||||
| kvResponse.txHash = transactionHash; | |||||
| kvResponse.key = dataKey; | |||||
| kvResponse.value = dataVal; | |||||
| return kvResponse; | |||||
| } | |||||
| public static void validKeyPair(IntegrationBase.KeyPairResponse keyPairResponse, LedgerRepository ledgerRepository, | |||||
| KeyPairType keyPairType) { | |||||
| TransactionResponse txResp = keyPairResponse.txResp; | |||||
| HashDigest transactionHash = keyPairResponse.txHash; | |||||
| BlockchainKeypair keyPair = keyPairResponse.keyPair; | |||||
| long index = validLong.incrementAndGet(); | |||||
| System.out.printf("validKeyPair start %s \r\n", index); | |||||
| ledgerRepository.retrieveLatestBlock(); | |||||
| assertEquals(txResp.getExecutionState(), TransactionState.SUCCESS); | |||||
| assertEquals(txResp.getBlockHeight(), ledgerRepository.getLatestBlockHeight()); | |||||
| assertEquals(txResp.getContentHash(), transactionHash); | |||||
| assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash()); | |||||
| if (keyPairType == KeyPairType.USER) { | |||||
| assertTrue(ledgerRepository.getUserAccountSet(ledgerRepository.getLatestBlock()) | |||||
| .contains(keyPair.getAddress())); | |||||
| } | |||||
| if (keyPairType == KeyPairType.DATAACCOUNT) { | |||||
| assertNotNull(ledgerRepository.getDataAccountSet(ledgerRepository.getLatestBlock()) | |||||
| .getDataAccount(keyPair.getAddress())); | |||||
| } | |||||
| System.out.printf("validKeyPair end %s \r\n", index); | |||||
| } | |||||
| public static void validKeyPair(IntegrationBase.KeyPairResponse keyPairResponse, LedgerRepository ledgerRepository, | |||||
| KeyPairType keyPairType, CountDownLatch countDownLatch) { | |||||
| TransactionResponse txResp = keyPairResponse.txResp; | |||||
| HashDigest transactionHash = keyPairResponse.txHash; | |||||
| BlockchainKeypair keyPair = keyPairResponse.keyPair; | |||||
| ledgerRepository.retrieveLatestBlock(); | |||||
| assertEquals(txResp.getExecutionState(), TransactionState.SUCCESS); | |||||
| assertEquals(txResp.getBlockHeight(), ledgerRepository.getLatestBlockHeight()); | |||||
| assertEquals(txResp.getContentHash(), transactionHash); | |||||
| assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash()); | |||||
| if (keyPairType == KeyPairType.USER) { | |||||
| assertTrue(ledgerRepository.getUserAccountSet(ledgerRepository.getLatestBlock()) | |||||
| .contains(keyPair.getAddress())); | |||||
| } | |||||
| if (keyPairType == KeyPairType.DATAACCOUNT) { | |||||
| assertNotNull(ledgerRepository.getDataAccountSet(ledgerRepository.getLatestBlock()) | |||||
| .getDataAccount(keyPair.getAddress())); | |||||
| } | |||||
| countDownLatch.countDown(); | |||||
| } | |||||
| public static void validKvWrite(IntegrationBase.KvResponse kvResponse, LedgerRepository ledgerRepository, | |||||
| BlockchainService blockchainService) { | |||||
| // 先验证应答 | |||||
| TransactionResponse txResp = kvResponse.getTxResp(); | |||||
| HashDigest transactionHash = kvResponse.getTxHash(); | |||||
| HashDigest ledgerHash = kvResponse.getLedgerHash(); | |||||
| String daAddress = kvResponse.getDataAccount().toBase58(); | |||||
| String dataKey = kvResponse.getKey(); | |||||
| String dataVal = kvResponse.getValue(); | |||||
| ledgerRepository.retrieveLatestBlock(); | |||||
| assertEquals(TransactionState.SUCCESS, txResp.getExecutionState()); | |||||
| assertEquals(txResp.getBlockHeight(), ledgerRepository.getLatestBlockHeight()); | |||||
| assertEquals(txResp.getContentHash(), transactionHash); | |||||
| assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash()); | |||||
| KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, daAddress, dataKey); | |||||
| for (KVDataEntry kvDataEntry : kvDataEntries) { | |||||
| assertEquals(dataKey, kvDataEntry.getKey()); | |||||
| String valHexText = (String) kvDataEntry.getValue(); | |||||
| assertEquals(dataVal, valHexText); | |||||
| } | |||||
| } | |||||
| public static LedgerRepository[] buildLedgers(LedgerBindingConfig[] bindingConfigs, | |||||
| DbConnectionFactory[] dbConnectionFactories) { | |||||
| int[] ids = { 0, 1, 2, 3 }; | |||||
| LedgerRepository[] ledgers = new LedgerRepository[ids.length]; | |||||
| LedgerManager[] ledgerManagers = new LedgerManager[ids.length]; | |||||
| for (int i = 0; i < ids.length; i++) { | |||||
| ledgerManagers[i] = new LedgerManager(); | |||||
| HashDigest ledgerHash = bindingConfigs[0].getLedgerHashs()[0]; | |||||
| DbConnection conn = dbConnectionFactories[i] | |||||
| .connect(bindingConfigs[i].getLedger(ledgerHash).getDbConnection().getUri()); | |||||
| ledgers[i] = ledgerManagers[i].register(ledgerHash, conn.getStorageService()); | |||||
| } | |||||
| return ledgers; | |||||
| } | |||||
| public static void testConsistencyAmongNodes(LedgerRepository[] ledgers) { | |||||
| LedgerRepository ledger0 = ledgers[0]; | |||||
| LedgerBlock latestBlock0 = ledger0.retrieveLatestBlock(); | |||||
| for (int i = 1; i < ledgers.length; i++) { | |||||
| LedgerRepository otherLedger = ledgers[i]; | |||||
| LedgerBlock otherLatestBlock = otherLedger.retrieveLatestBlock(); | |||||
| assertEquals(ledger0.getHash(), otherLedger.getHash()); | |||||
| assertEquals(ledger0.getLatestBlockHeight(), otherLedger.getLatestBlockHeight()); | |||||
| assertEquals(ledger0.getLatestBlockHash(), otherLedger.getLatestBlockHash()); | |||||
| assertEquals(latestBlock0.getHeight(), otherLatestBlock.getHeight()); | |||||
| assertEquals(latestBlock0.getHash(), otherLatestBlock.getHash()); | |||||
| assertEquals(latestBlock0.getAdminAccountHash(), otherLatestBlock.getAdminAccountHash()); | |||||
| assertEquals(latestBlock0.getTransactionSetHash(), otherLatestBlock.getTransactionSetHash()); | |||||
| assertEquals(latestBlock0.getUserAccountSetHash(), otherLatestBlock.getUserAccountSetHash()); | |||||
| assertEquals(latestBlock0.getDataAccountSetHash(), otherLatestBlock.getDataAccountSetHash()); | |||||
| assertEquals(latestBlock0.getContractAccountSetHash(), otherLatestBlock.getContractAccountSetHash()); | |||||
| assertEquals(latestBlock0.getPreviousHash(), otherLatestBlock.getPreviousHash()); | |||||
| } | |||||
| } | |||||
| public static PeerTestRunner[] peerNodeStart(HashDigest ledgerHash, String dbType) { | |||||
| NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 12000); | |||||
| LedgerBindingConfig bindingConfig0 = loadBindingConfig(0, ledgerHash, dbType); | |||||
| PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, bindingConfig0); | |||||
| NetworkAddress peerSrvAddr1 = new NetworkAddress("127.0.0.1", 12010); | |||||
| LedgerBindingConfig bindingConfig1 = loadBindingConfig(1, ledgerHash, dbType); | |||||
| PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, bindingConfig1); | |||||
| NetworkAddress peerSrvAddr2 = new NetworkAddress("127.0.0.1", 12020); | |||||
| LedgerBindingConfig bindingConfig2 = loadBindingConfig(2, ledgerHash, dbType); | |||||
| PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, bindingConfig2); | |||||
| NetworkAddress peerSrvAddr3 = new NetworkAddress("127.0.0.1", 12030); | |||||
| LedgerBindingConfig bindingConfig3 = loadBindingConfig(3, ledgerHash, dbType); | |||||
| PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, bindingConfig3); | |||||
| ThreadInvoker.AsyncCallback<Object> peerStarting0 = peer0.start(); | |||||
| ThreadInvoker.AsyncCallback<Object> peerStarting1 = peer1.start(); | |||||
| ThreadInvoker.AsyncCallback<Object> peerStarting2 = peer2.start(); | |||||
| ThreadInvoker.AsyncCallback<Object> peerStarting3 = peer3.start(); | |||||
| peerStarting0.waitReturn(); | |||||
| peerStarting1.waitReturn(); | |||||
| peerStarting2.waitReturn(); | |||||
| peerStarting3.waitReturn(); | |||||
| return new PeerTestRunner[] { peer0, peer1, peer2, peer3 }; | |||||
| } | |||||
| public static LedgerBindingConfig loadBindingConfig(int id, HashDigest ledgerHash, String dbType) { | |||||
| LedgerBindingConfig ledgerBindingConfig; | |||||
| String newLedger = ledgerHash.toBase58(); | |||||
| String resourceClassPath = "ledger-binding-" + dbType + "-" + id + ".conf"; | |||||
| String ledgerBindingUrl = IntegrationBase.class.getResource("/") + resourceClassPath; | |||||
| try { | |||||
| URL url = new URL(ledgerBindingUrl); | |||||
| File ledgerBindingConf = new File(url.getPath()); | |||||
| System.out.printf("URL-ledgerBindingConf = %s \r\n", url.getPath()); | |||||
| if (ledgerBindingConf.exists()) { | |||||
| List<String> readLines = FileUtils.readLines(ledgerBindingConf); | |||||
| List<String> writeLines = new ArrayList<>(); | |||||
| if (readLines != null && !readLines.isEmpty()) { | |||||
| String oldLedgerLine = null; | |||||
| for (String readLine : readLines) { | |||||
| if (readLine.startsWith("ledger")) { | |||||
| oldLedgerLine = readLine; | |||||
| break; | |||||
| } | |||||
| } | |||||
| String[] oldLedgerArray = oldLedgerLine.split("="); | |||||
| String oldLedger = oldLedgerArray[1]; | |||||
| if (!oldLedger.equalsIgnoreCase(newLedger)) { | |||||
| for (String readLine : readLines) { | |||||
| String newLine = readLine.replace(oldLedger, newLedger); | |||||
| if (dbType.equalsIgnoreCase("rocksdb")) { | |||||
| if (newLine.contains("db.uri")) { | |||||
| String[] propArray = newLine.split("="); | |||||
| String dbKey = propArray[0]; | |||||
| String dbValue = LedgerInitConsensusConfig.rocksdbConnectionStrings[id]; | |||||
| newLine = dbKey + "=" + dbValue; | |||||
| } | |||||
| } | |||||
| writeLines.add(newLine); | |||||
| } | |||||
| } else if (dbType.equalsIgnoreCase("rocksdb")) { | |||||
| for (String readLine : readLines) { | |||||
| String newLine = readLine; | |||||
| if (readLine.contains("db.uri")) { | |||||
| String[] propArray = readLine.split("="); | |||||
| String dbKey = propArray[0]; | |||||
| String dbValue = LedgerInitConsensusConfig.rocksdbConnectionStrings[id]; | |||||
| newLine = dbKey + "=" + dbValue; | |||||
| } | |||||
| writeLines.add(newLine); | |||||
| } | |||||
| } | |||||
| if (!writeLines.isEmpty()) { | |||||
| FileUtils.writeLines(ledgerBindingConf, writeLines); | |||||
| } | |||||
| } | |||||
| } | |||||
| } catch (Exception e) { | |||||
| } | |||||
| ClassPathResource res = new ClassPathResource(resourceClassPath); | |||||
| try (InputStream in = res.getInputStream()) { | |||||
| ledgerBindingConfig = LedgerBindingConfig.resolve(in); | |||||
| } catch (IOException e) { | |||||
| throw new IllegalStateException(e.getMessage(), e); | |||||
| } | |||||
| return ledgerBindingConfig; | |||||
| } | |||||
| public static class KeyPairResponse { | |||||
| HashDigest txHash; | |||||
| BlockchainKeypair keyPair; | |||||
| TransactionResponse txResp; | |||||
| public BlockchainKeypair getKeyPair() { | |||||
| return keyPair; | |||||
| } | |||||
| public TransactionResponse getTxResp() { | |||||
| return txResp; | |||||
| } | |||||
| public HashDigest getTxHash() { | |||||
| return txHash; | |||||
| } | |||||
| } | |||||
| public static class KvResponse { | |||||
| Bytes dataAccount; | |||||
| HashDigest ledgerHash; | |||||
| HashDigest txHash; | |||||
| TransactionResponse txResp; | |||||
| String key; | |||||
| String value; | |||||
| public HashDigest getTxHash() { | |||||
| return txHash; | |||||
| } | |||||
| public TransactionResponse getTxResp() { | |||||
| return txResp; | |||||
| } | |||||
| public String getKey() { | |||||
| return key; | |||||
| } | |||||
| public String getValue() { | |||||
| return value; | |||||
| } | |||||
| public HashDigest getLedgerHash() { | |||||
| return ledgerHash; | |||||
| } | |||||
| public Bytes getDataAccount() { | |||||
| return dataAccount; | |||||
| } | |||||
| } | |||||
| public enum KeyPairType { | |||||
| USER, DATAACCOUNT | |||||
| } | |||||
| // 合约测试使用的初始化数据; | |||||
| static BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate(); | static BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate(); | ||||
| static BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); | static BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); | ||||
| // 保存资产总数的键; | |||||
| // 第二个参数; | |||||
| // 保存资产总数的键; | |||||
| // 第二个参数; | |||||
| private static String contractZipName = "contract.jar"; | private static String contractZipName = "contract.jar"; | ||||
| static HashDigest txContentHash; | static HashDigest txContentHash; | ||||
| public static LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash, | public static LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash, | ||||
| BlockchainService blockchainService,LedgerRepository ledgerRepository) { | |||||
| BlockchainService blockchainService, LedgerRepository ledgerRepository) { | |||||
| KeyPairResponse keyPairResponse = testSDK_RegisterDataAccount(adminKey,ledgerHash,blockchainService); | KeyPairResponse keyPairResponse = testSDK_RegisterDataAccount(adminKey,ledgerHash,blockchainService); | ||||
| System.out.println("adminKey="+ AddressEncoding.generateAddress(adminKey.getPubKey())); | |||||
| BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate(); | |||||
| System.out.println("userKey="+userKey.getAddress()); | |||||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||||
| txTpl.users().register(userKey.getIdentity()); | |||||
| System.out.println("adminKey=" + AddressEncoding.generateAddress(adminKey.getPubKey())); | |||||
| BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate(); | |||||
| System.out.println("userKey=" + userKey.getAddress()); | |||||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||||
| txTpl.users().register(userKey.getIdentity()); | |||||
| // 定义交易; | |||||
| byte[] contractCode = getChainCodeBytes(); | |||||
| txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); | |||||
| // 定义交易; | |||||
| byte[] contractCode = getChainCodeBytes(); | |||||
| txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); | |||||
| // 签名; | |||||
| PreparedTransaction ptx = txTpl.prepare(); | |||||
| ptx.sign(adminKey); | |||||
| // 签名; | |||||
| PreparedTransaction ptx = txTpl.prepare(); | |||||
| ptx.sign(adminKey); | |||||
| // 提交并等待共识返回; | |||||
| TransactionResponse txResp = ptx.commit(); | |||||
| assertTrue(txResp.isSuccess()); | |||||
| // 提交并等待共识返回; | |||||
| TransactionResponse txResp = ptx.commit(); | |||||
| assertTrue(txResp.isSuccess()); | |||||
| // 验证结果hash;请求的hash=相应的内容hash; | |||||
| // 验证结果; | |||||
| assertEquals(ptx.getHash(),txResp.getContentHash()); | assertEquals(ptx.getHash(),txResp.getContentHash()); | ||||
| LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); | |||||
| byte[] contractCodeInDb = ledgerRepository.getContractAccountSet(block).getContract(contractDeployKey.getAddress()) | |||||
| .getChainCode(); | |||||
| assertArrayEquals(contractCode, contractCodeInDb); | |||||
| LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); | |||||
| byte[] contractCodeInDb = ledgerRepository.getContractAccountSet(block) | |||||
| .getContract(contractDeployKey.getAddress()).getChainCode(); | |||||
| assertArrayEquals(contractCode, contractCodeInDb); | |||||
| // execute the contract; | |||||
| // execute the contract; | |||||
| testContractExe(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); | testContractExe(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); | ||||
| testContractExe1(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); | testContractExe1(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); | ||||
| return block; | |||||
| } | |||||
| return block; | |||||
| } | |||||
| private static <T> void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair dataKey, | private static <T> void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair dataKey, | ||||
| BlockchainService blockchainService,LedgerRepository ledgerRepository) { | |||||
| LedgerInfo ledgerInfo = blockchainService.getLedger(ledgerHash); | |||||
| LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight() - 1); | |||||
| BlockchainService blockchainService, LedgerRepository ledgerRepository) { | |||||
| LedgerInfo ledgerInfo = blockchainService.getLedger(ledgerHash); | |||||
| LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight() - 1); | |||||
| // 定义交易; | |||||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||||
| // 定义交易; | |||||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||||
| Byte byteObj = Byte.parseByte("123"); | Byte byteObj = Byte.parseByte("123"); | ||||
| // txTpl.contract(contractDeployKey.getAddress(),AssetContract2.class).issue(byteObj, | // txTpl.contract(contractDeployKey.getAddress(),AssetContract2.class).issue(byteObj, | ||||
| @@ -494,14 +497,14 @@ public class IntegrationBase { | |||||
| txTpl.contract(contractDeployKey.getAddress(),AssetContract2.class).issue(byteObj, | txTpl.contract(contractDeployKey.getAddress(),AssetContract2.class).issue(byteObj, | ||||
| dataKey.getAddress().toBase58(),Bytes.fromString("123321")); | dataKey.getAddress().toBase58(),Bytes.fromString("123321")); | ||||
| // 签名; | |||||
| PreparedTransaction ptx = txTpl.prepare(); | |||||
| ptx.sign(adminKey); | |||||
| // 签名; | |||||
| PreparedTransaction ptx = txTpl.prepare(); | |||||
| ptx.sign(adminKey); | |||||
| // 提交并等待共识返回; | |||||
| TransactionResponse txResp = ptx.commit(); | |||||
| // 提交并等待共识返回; | |||||
| TransactionResponse txResp = ptx.commit(); | |||||
| // 验证结果; | |||||
| // 验证结果; | |||||
| Assert.assertTrue(txResp.isSuccess()); | Assert.assertTrue(txResp.isSuccess()); | ||||
| assertEquals(ptx.getHash(),txResp.getContentHash()); | assertEquals(ptx.getHash(),txResp.getContentHash()); | ||||
| LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); | LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); | ||||
| @@ -529,43 +532,43 @@ public class IntegrationBase { | |||||
| TransactionResponse txResp = ptx.commit(); | TransactionResponse txResp = ptx.commit(); | ||||
| // 验证结果; | // 验证结果; | ||||
| Assert.assertTrue(txResp.isSuccess()); | |||||
| Assert.assertTrue(txResp.isSuccess()); | |||||
| assertEquals(ptx.getHash(),txResp.getContentHash()); | assertEquals(ptx.getHash(),txResp.getContentHash()); | ||||
| LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); | LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); | ||||
| KVDataEntry[] kvDataEntries = ledgerRepository.getDataAccountSet(block).getDataAccount(dataKey.getAddress()).getDataEntries(1,2); | KVDataEntry[] kvDataEntries = ledgerRepository.getDataAccountSet(block).getDataAccount(dataKey.getAddress()).getDataEntries(1,2); | ||||
| assertEquals("value1",kvDataEntries[0].getValue().toString()); | assertEquals("value1",kvDataEntries[0].getValue().toString()); | ||||
| assertEquals(888L,kvDataEntries[1].getValue()); | assertEquals(888L,kvDataEntries[1].getValue()); | ||||
| } | |||||
| } | |||||
| /** | |||||
| * 根据合约构建字节数组; | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| /** | |||||
| * 根据合约构建字节数组; | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| private static byte[] getChainCodeBytes() { | private static byte[] getChainCodeBytes() { | ||||
| // 构建合约的字节数组; | |||||
| byte[] contractCode = null; | |||||
| File file = null; | |||||
| InputStream input = null; | |||||
| try { | |||||
| ClassPathResource contractPath = new ClassPathResource(contractZipName); | |||||
| file = new File(contractPath.getURI()); | |||||
| assertTrue("contract zip file is not exist.", file.exists() == true); | |||||
| input = new FileInputStream(file); | |||||
| // 这种暴力的读取压缩包,在class解析时有问题,所有需要改进; | |||||
| contractCode = new byte[input.available()]; | |||||
| input.read(contractCode); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } finally { | |||||
| try { | |||||
| if (input != null) { | |||||
| input.close(); | |||||
| } | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| return contractCode; | |||||
| } | |||||
| // 构建合约的字节数组; | |||||
| byte[] contractCode = null; | |||||
| File file = null; | |||||
| InputStream input = null; | |||||
| try { | |||||
| ClassPathResource contractPath = new ClassPathResource(contractZipName); | |||||
| file = new File(contractPath.getURI()); | |||||
| assertTrue("contract zip file is not exist.", file.exists() == true); | |||||
| input = new FileInputStream(file); | |||||
| // 这种暴力的读取压缩包,在class解析时有问题,所有需要改进; | |||||
| contractCode = new byte[input.available()]; | |||||
| input.read(contractCode); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } finally { | |||||
| try { | |||||
| if (input != null) { | |||||
| input.close(); | |||||
| } | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| return contractCode; | |||||
| } | |||||
| } | } | ||||
| @@ -2,6 +2,7 @@ package test.com.jd.blockchain.intgr; | |||||
| import com.jd.blockchain.crypto.*; | import com.jd.blockchain.crypto.*; | ||||
| import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; | import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; | ||||
| import com.jd.blockchain.ledger.BytesValue; | |||||
| import com.jd.blockchain.ledger.*; | import com.jd.blockchain.ledger.*; | ||||
| import com.jd.blockchain.ledger.core.DataAccount; | import com.jd.blockchain.ledger.core.DataAccount; | ||||
| import com.jd.blockchain.ledger.core.DataAccountSet; | import com.jd.blockchain.ledger.core.DataAccountSet; | ||||
| @@ -201,9 +202,9 @@ public class IntegrationTestAll4Redis { | |||||
| txTpl.dataAccounts().register(dataKey.getIdentity()); | txTpl.dataAccounts().register(dataKey.getIdentity()); | ||||
| // add kv ops for data account | // add kv ops for data account | ||||
| DataAccountKVSetOperation dataKvsetOP = txTpl.dataAccount(dataKey.getAddress()) | |||||
| .set("A", "Value_A_0".getBytes(), -1).set("B", "Value_B_0".getBytes(), -1) | |||||
| .set("C", "Value_C_0".getBytes(), -1).set("D", "Value_D_0".getBytes(), -1).getOperation(); | |||||
| DataAccountKVSetOperation dataKvsetOP = txTpl.dataAccount(dataKey.getAddress()).setText("A", "Value_A_0", -1) | |||||
| .setText("B", "Value_B_0", -1).setText("C", "Value_C_0", -1).setText("D", "Value_D_0", -1) | |||||
| .getOperation(); | |||||
| // 签名; | // 签名; | ||||
| PreparedTransaction ptx = txTpl.prepare(); | PreparedTransaction ptx = txTpl.prepare(); | ||||
| @@ -215,18 +216,14 @@ public class IntegrationTestAll4Redis { | |||||
| assertTrue(txResp.isSuccess()); | assertTrue(txResp.isSuccess()); | ||||
| assertEquals(ledgerRepository.retrieveLatestBlockHeight(), txResp.getBlockHeight()); | assertEquals(ledgerRepository.retrieveLatestBlockHeight(), txResp.getBlockHeight()); | ||||
| assertArrayEquals("Value_A_0".getBytes(), | |||||
| ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) | |||||
| .getDataAccount(dataKey.getAddress()).getBytes("A")); | |||||
| assertArrayEquals("Value_B_0".getBytes(), | |||||
| ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) | |||||
| .getDataAccount(dataKey.getAddress()).getBytes("B")); | |||||
| assertArrayEquals("Value_C_0".getBytes(), | |||||
| ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) | |||||
| .getDataAccount(dataKey.getAddress()).getBytes("C")); | |||||
| assertArrayEquals("Value_D_0".getBytes(), | |||||
| ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) | |||||
| .getDataAccount(dataKey.getAddress()).getBytes("D")); | |||||
| assertEquals("Value_A_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) | |||||
| .getDataAccount(dataKey.getAddress()).getBytes("A").getValue().toUTF8String()); | |||||
| assertEquals("Value_B_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) | |||||
| .getDataAccount(dataKey.getAddress()).getBytes("B").getValue().toUTF8String()); | |||||
| assertEquals("Value_C_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) | |||||
| .getDataAccount(dataKey.getAddress()).getBytes("C").getValue().toUTF8String()); | |||||
| assertEquals("Value_D_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) | |||||
| .getDataAccount(dataKey.getAddress()).getBytes("D").getValue().toUTF8String()); | |||||
| assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) | assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) | ||||
| .getDataAccount(dataKey.getAddress()).getDataVersion("A")); | .getDataAccount(dataKey.getAddress()).getDataVersion("A")); | ||||
| assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) | assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) | ||||
| @@ -253,8 +250,8 @@ public class IntegrationTestAll4Redis { | |||||
| } | } | ||||
| private void testSDK_InsertData(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService, | |||||
| Bytes dataAccountAddress, LedgerRepository ledgerRepository) { | |||||
| private void testSDK_InsertData(AsymmetricKeypair adminKey, HashDigest ledgerHash, | |||||
| BlockchainService blockchainService, Bytes dataAccountAddress, LedgerRepository ledgerRepository) { | |||||
| // 在本地定义注册账号的 TX; | // 在本地定义注册账号的 TX; | ||||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); | TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); | ||||
| @@ -265,9 +262,9 @@ public class IntegrationTestAll4Redis { | |||||
| Bytes dataAccount = dataAccountAddress; | Bytes dataAccount = dataAccountAddress; | ||||
| String dataKey = "jingdong" + new Random().nextInt(100000); | String dataKey = "jingdong" + new Random().nextInt(100000); | ||||
| byte[] dataVal = "www.jd.com".getBytes(); | |||||
| String dataVal = "www.jd.com"; | |||||
| txTemp.dataAccount(dataAccount).set(dataKey, dataVal, -1); | |||||
| txTemp.dataAccount(dataAccount).setText(dataKey, dataVal, -1); | |||||
| // TX 准备就绪; | // TX 准备就绪; | ||||
| PreparedTransaction prepTx = txTemp.prepare(); | PreparedTransaction prepTx = txTemp.prepare(); | ||||
| @@ -392,11 +389,10 @@ public class IntegrationTestAll4Redis { | |||||
| .getDataAccount(contractDataKey.getAddress()); | .getDataAccount(contractDataKey.getAddress()); | ||||
| DataAccountKVSetOperation kvsetOP = txTpl.dataAccount(contractDataKey.getAddress()) | DataAccountKVSetOperation kvsetOP = txTpl.dataAccount(contractDataKey.getAddress()) | ||||
| .set("A", "Value_A_0".getBytes(), -1).set("B", "Value_B_0".getBytes(), -1) | |||||
| .set(KEY_TOTAL, "total value,dataAccount".getBytes(), -1) | |||||
| .set(KEY_ABC, "abc value,dataAccount".getBytes(), -1) | |||||
| .setText("A", "Value_A_0", -1).setText("B", "Value_B_0", -1) | |||||
| .setText(KEY_TOTAL, "total value,dataAccount", -1).setText(KEY_ABC, "abc value,dataAccount", -1) | |||||
| // 所有的模拟数据都在这个dataAccount中填充; | // 所有的模拟数据都在这个dataAccount中填充; | ||||
| .set("ledgerHash", ledgerHash.getRawDigest(), -1).getOperation(); | |||||
| .setBytes("ledgerHash", ledgerHash.getRawDigest(), -1).getOperation(); | |||||
| byte[] contractCode = getChainCodeBytes(); | byte[] contractCode = getChainCodeBytes(); | ||||
| txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); | txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); | ||||
| @@ -457,7 +453,8 @@ public class IntegrationTestAll4Redis { | |||||
| PubKey pubKey = key.getPubKey(); | PubKey pubKey = key.getPubKey(); | ||||
| Bytes dataAddress = AddressEncoding.generateAddress(pubKey); | Bytes dataAddress = AddressEncoding.generateAddress(pubKey); | ||||
| assertEquals(dataAddress, dataAccountSet.getDataAccount(dataAddress).getAddress()); | assertEquals(dataAddress, dataAccountSet.getDataAccount(dataAddress).getAddress()); | ||||
| assertEquals("hello", new String(dataAccountSet.getDataAccount(dataAddress).getBytes(KEY_TOTAL, -1))); | |||||
| assertEquals("hello", | |||||
| dataAccountSet.getDataAccount(dataAddress).getBytes(KEY_TOTAL, -1).getValue().toUTF8String()); | |||||
| // 验证userAccount,从合约内部赋值,然后外部验证;内部定义动态key,外部不便于得到,临时屏蔽; | // 验证userAccount,从合约内部赋值,然后外部验证;内部定义动态key,外部不便于得到,临时屏蔽; | ||||
| // UserAccountSet userAccountSet = | // UserAccountSet userAccountSet = | ||||
| @@ -468,8 +465,8 @@ public class IntegrationTestAll4Redis { | |||||
| // assertEquals(userAddress, userAccountSet.getUser(userAddress).getAddress()); | // assertEquals(userAddress, userAccountSet.getUser(userAddress).getAddress()); | ||||
| } | } | ||||
| private void prepareContractData(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService, | |||||
| LedgerRepository ledgerRepository) { | |||||
| private void prepareContractData(AsymmetricKeypair adminKey, HashDigest ledgerHash, | |||||
| BlockchainService blockchainService, LedgerRepository ledgerRepository) { | |||||
| // 定义交易; | // 定义交易; | ||||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | ||||
| @@ -484,12 +481,12 @@ public class IntegrationTestAll4Redis { | |||||
| // 验证结果; | // 验证结果; | ||||
| LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); | LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); | ||||
| byte[] val1InDb = ledgerRepository.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress()) | |||||
| BytesValue val1InDb = ledgerRepository.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress()) | |||||
| .getBytes("A"); | .getBytes("A"); | ||||
| byte[] val2InDb = ledgerRepository.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress()) | |||||
| BytesValue val2InDb = ledgerRepository.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress()) | |||||
| .getBytes(KEY_TOTAL); | .getBytes(KEY_TOTAL); | ||||
| assertArrayEquals("Value_A_0".getBytes(), val1InDb); | |||||
| assertArrayEquals("total value,dataAccount".getBytes(), val2InDb); | |||||
| assertEquals("Value_A_0", val1InDb.getValue().toUTF8String()); | |||||
| assertEquals("total value,dataAccount", val2InDb.getValue().toUTF8String()); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -196,8 +196,8 @@ public class IntegrationTestDataAccount { | |||||
| JsonTest jsonTest = new JsonTest("Jack"); | JsonTest jsonTest = new JsonTest("Jack"); | ||||
| // | // | ||||
| // //add kv ops for data account: Bytes, string, long, json string | // //add kv ops for data account: Bytes, string, long, json string | ||||
| DataAccountKVSetOperation dataKvsetOP = txTpl.dataAccount(dataAddr).set("A", "Value_A_0".getBytes(), -1) | |||||
| .set("B", "Value_B_0", -1).set("C", currentTime, -1).set("D", JSON.toJSONString(jsonTest), -1) | |||||
| DataAccountKVSetOperation dataKvsetOP = txTpl.dataAccount(dataAddr).setText("A", "Value_A_0", -1) | |||||
| .setText("B", "Value_B_0", -1).setInt64("C", currentTime, -1).setText("D", JSON.toJSONString(jsonTest), -1) | |||||
| .getOperation(); | .getOperation(); | ||||
| // 签名; | // 签名; | ||||
| @@ -42,321 +42,323 @@ import com.jd.blockchain.utils.io.BytesUtils; | |||||
| public class RemoteTransactionService { | public class RemoteTransactionService { | ||||
| private MsgQueueProducer txProducer; | |||||
| private final ExecutorService instanceFactory = Executors.newSingleThreadExecutor(); | |||||
| private final ArrayBlockingQueue<List<byte[]>> txBlockingQueue = new ArrayBlockingQueue(1); | |||||
| private final LinkedList<Bytes> dataAccountAddress = new LinkedList<>(); | |||||
| private Bytes defaultDataAccount; | |||||
| private static final AtomicLong keyPrefix = new AtomicLong(); | |||||
| public void userRegister(int count) throws Exception { | |||||
| initTxProducer(); | |||||
| int loop = 0; | |||||
| if (count <= 0) { | |||||
| userCreate(); | |||||
| } else { | |||||
| loop = count / CapabilitySettings.TX_SIZE_PER_SEND; | |||||
| userCreate(loop); | |||||
| } | |||||
| // 从队列中获取数据 | |||||
| if (count <= 0) { | |||||
| for (;;) { | |||||
| txRequestSend(); | |||||
| } | |||||
| } else { | |||||
| for (int i = 0; i < loop; i++) { | |||||
| txRequestSend(); | |||||
| } | |||||
| } | |||||
| closeTxProducer(); | |||||
| } | |||||
| public void dataAccountRegister(int count) throws Exception { | |||||
| initTxProducer(); | |||||
| int loop = 0; | |||||
| if (count <= 0) { | |||||
| dataAccountCreate(); | |||||
| } else { | |||||
| loop = count / CapabilitySettings.TX_SIZE_PER_SEND; | |||||
| dataAccountCreate(loop); | |||||
| } | |||||
| // 从队列中获取数据 | |||||
| if (count <= 0) { | |||||
| for (;;) { | |||||
| txRequestSend(); | |||||
| } | |||||
| } else { | |||||
| for (int i = 0; i < loop; i++) { | |||||
| txRequestSend(); | |||||
| } | |||||
| } | |||||
| closeTxProducer(); | |||||
| } | |||||
| public void userAndDataAccountRegister(int userCount, int dataAccountCount) throws Exception { | |||||
| if (userCount <= 0 || dataAccountCount <= 0) { | |||||
| throw new IllegalArgumentException("userCount and dataAccountCount can not be 0!!!"); | |||||
| } | |||||
| initTxProducer(); | |||||
| int userLoop = userCount / CapabilitySettings.TX_SIZE_PER_SEND; | |||||
| int dataAccountLoop = dataAccountCount / CapabilitySettings.TX_SIZE_PER_SEND; | |||||
| userCreate(userLoop); | |||||
| dataAccountCreate(dataAccountLoop); | |||||
| for (int i = 0, totalLoop = userLoop + dataAccountCount; i < totalLoop; i++) { | |||||
| txRequestSend(); | |||||
| } | |||||
| closeTxProducer(); | |||||
| } | |||||
| public void dataAccountRegisterAndKvStorage(int dataAccountCount, int kvCount) throws Exception { | |||||
| if (kvCount <= 0 || dataAccountCount <= 0) { | |||||
| throw new IllegalArgumentException("userCount and dataAccountCount can not be 0!!!"); | |||||
| } | |||||
| initTxProducer(); | |||||
| int dataAccountLoop = dataAccountCount / CapabilitySettings.TX_SIZE_PER_SEND; | |||||
| dataAccountCreate(dataAccountLoop); | |||||
| // 首先将数据账户写入 | |||||
| for (int i = 0; i < dataAccountLoop; i++) { | |||||
| txRequestSend(); | |||||
| } | |||||
| int kvLoop = kvCount / CapabilitySettings.TX_SIZE_PER_SEND; | |||||
| // 然后将每个数据账户都写入指定数量的kv | |||||
| Iterator<Bytes> iterator = dataAccountAddress.iterator(); | |||||
| while(iterator.hasNext()){ | |||||
| Bytes address = iterator.next(); | |||||
| kvStorageCreate(kvCount, address); | |||||
| } | |||||
| for (int i = 0, loop = kvLoop * dataAccountCount; i < loop; i++) { | |||||
| txRequestSend(); | |||||
| } | |||||
| closeTxProducer(); | |||||
| } | |||||
| public void kvStorage(int kvCount) throws Exception { | |||||
| initTxProducer(); | |||||
| dataAccountDefaultCreate(); | |||||
| try { | |||||
| txRequestSend(); | |||||
| // 确认结块成功 | |||||
| Thread.sleep(10000); | |||||
| } catch (Exception e) { | |||||
| throw e; | |||||
| } | |||||
| int kvLoop = kvCount / CapabilitySettings.TX_SIZE_PER_SEND; | |||||
| // 然后将每个数据账户都写入指定数量的kv | |||||
| Bytes address = defaultDataAccount; | |||||
| kvStorageCreate(kvLoop, address); | |||||
| for (int i = 0; i < kvLoop; i++) { | |||||
| txRequestSend(); | |||||
| } | |||||
| closeTxProducer(); | |||||
| } | |||||
| private void txRequestSend() throws Exception { | |||||
| List<byte[]> txRequests = txBlockingQueue.take(); | |||||
| if (txRequests != null && !txRequests.isEmpty()) { | |||||
| Iterator<byte[]> iterator = txRequests.iterator(); | |||||
| while(iterator.hasNext()){ | |||||
| byte[] txRequest = iterator.next(); | |||||
| try { | |||||
| txProducer.publish(txRequest); | |||||
| } catch (Exception e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| ConsoleUtils.info("[*] Transaction Request send success!!!"); | |||||
| } | |||||
| } | |||||
| private void initTxProducer() throws Exception { | |||||
| txProducer = MsgQueueFactory.newProducer(CapabilitySettings.MSG_QUEUE_URL, CapabilitySettings.TX_TOPIC); | |||||
| txProducer.connect(); | |||||
| ConsoleUtils.info("[*] Transaction Producer start success!!!"); | |||||
| } | |||||
| private void closeTxProducer() throws Exception{ | |||||
| txProducer.close(); | |||||
| } | |||||
| private void userCreate(int loop) { | |||||
| instanceFactory.execute(() -> { | |||||
| for (int index = 0; index < loop; index++) { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| try { | |||||
| LinkedList<byte[]> txSerializeBytes = userActiveCreate(); | |||||
| txBlockingQueue.put(txSerializeBytes); | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| private void userCreate() { | |||||
| // 一直在生产用户 | |||||
| instanceFactory.execute(() -> { | |||||
| for (;;) { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| try { | |||||
| LinkedList<byte[]> txSerializeBytes = userActiveCreate(); | |||||
| txBlockingQueue.put(txSerializeBytes); | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| private void dataAccountCreate(int loop) { | |||||
| dataAccountCreate(loop, false); | |||||
| } | |||||
| private void dataAccountCreate(int loop, final boolean isSave) { | |||||
| instanceFactory.execute(() -> { | |||||
| for (int index = 0; index < loop; index++) { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| try { | |||||
| LinkedList<byte[]> txSerializeBytes = dataAccountActiveCreate(isSave); | |||||
| txBlockingQueue.put(txSerializeBytes); | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| private void dataAccountDefaultCreate() { | |||||
| instanceFactory.execute(() -> { | |||||
| List<byte[]> currentBytes = new ArrayList<>(); | |||||
| TransactionRequest txRequest = dataAccountRegisterRequest(CapabilitySettings.ledgerHash, CapabilitySettings.adminKey); | |||||
| byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class); | |||||
| currentBytes.add(serializeBytes); | |||||
| try { | |||||
| txBlockingQueue.put(currentBytes); | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| }); | |||||
| } | |||||
| private void dataAccountCreate() { | |||||
| // 一直在生产用户 | |||||
| instanceFactory.execute(() -> { | |||||
| for (;;) { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| try { | |||||
| LinkedList<byte[]> txSerializeBytes = dataAccountActiveCreate(); | |||||
| txBlockingQueue.put(txSerializeBytes); | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| private void kvStorageCreate(int loop, Bytes address) { | |||||
| // 一直在生产用户 | |||||
| instanceFactory.execute(() -> { | |||||
| for (int index = 0; index < loop; index++) { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| try { | |||||
| LinkedList<byte[]> txSerializeBytes = kvActiveCreate(address); | |||||
| txBlockingQueue.put(txSerializeBytes); | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| private LinkedList<byte[]> userActiveCreate() { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| LinkedList<byte[]> txSerializeBytes = new LinkedList<>(); | |||||
| for (int i = 0; i < CapabilitySettings.TX_SIZE_PER_SEND; i++) { | |||||
| TransactionRequest txRequest = userRegisterRequest(CapabilitySettings.ledgerHash, CapabilitySettings.adminKey); | |||||
| byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class); | |||||
| txSerializeBytes.addFirst(serializeBytes); | |||||
| } | |||||
| return txSerializeBytes; | |||||
| } | |||||
| private LinkedList<byte[]> dataAccountActiveCreate() { | |||||
| return dataAccountActiveCreate(false); | |||||
| } | |||||
| private LinkedList<byte[]> dataAccountActiveCreate(boolean isSave) { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| LinkedList<byte[]> txSerializeBytes = new LinkedList<>(); | |||||
| for (int i = 0; i < CapabilitySettings.TX_SIZE_PER_SEND; i++) { | |||||
| TransactionRequest txRequest = dataAccountRegisterRequest(CapabilitySettings.ledgerHash, CapabilitySettings.adminKey, isSave); | |||||
| byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class); | |||||
| txSerializeBytes.addFirst(serializeBytes); | |||||
| } | |||||
| return txSerializeBytes; | |||||
| } | |||||
| private LinkedList<byte[]> kvActiveCreate(Bytes address) { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| LinkedList<byte[]> txSerializeBytes = new LinkedList<>(); | |||||
| for (int i = 0; i < CapabilitySettings.TX_SIZE_PER_SEND; i++) { | |||||
| TransactionRequest txRequest = kvStorageRequest(address, CapabilitySettings.ledgerHash, CapabilitySettings.adminKey); | |||||
| byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class); | |||||
| txSerializeBytes.addFirst(serializeBytes); | |||||
| } | |||||
| return txSerializeBytes; | |||||
| } | |||||
| private TransactionRequest userRegisterRequest(HashDigest ledgerHash, AsymmetricKeypair adminKey) { | |||||
| TxBuilder txbuilder = new TxBuilder(ledgerHash); | |||||
| BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate(); | |||||
| txbuilder.users().register(userKey.getIdentity()); | |||||
| TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest(); | |||||
| reqBuilder.signAsEndpoint(adminKey); | |||||
| return reqBuilder.buildRequest(); | |||||
| } | |||||
| private TransactionRequest dataAccountRegisterRequest(HashDigest ledgerHash, AsymmetricKeypair adminKey, boolean isSave) { | |||||
| TxBuilder txbuilder = new TxBuilder(ledgerHash); | |||||
| BlockchainKeypair dataAccountKey = BlockchainKeyGenerator.getInstance().generate(); | |||||
| BlockchainIdentity identity = dataAccountKey.getIdentity(); | |||||
| txbuilder.dataAccounts().register(identity); | |||||
| TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest(); | |||||
| reqBuilder.signAsEndpoint(adminKey); | |||||
| if (isSave) { | |||||
| dataAccountAddress.addFirst(identity.getAddress()); | |||||
| } | |||||
| return reqBuilder.buildRequest(); | |||||
| } | |||||
| private TransactionRequest dataAccountRegisterRequest(HashDigest ledgerHash, AsymmetricKeypair adminKey) { | |||||
| TxBuilder txbuilder = new TxBuilder(ledgerHash); | |||||
| BlockchainKeypair dataAccountKey = BlockchainKeyGenerator.getInstance().generate(); | |||||
| BlockchainIdentity identity = dataAccountKey.getIdentity(); | |||||
| txbuilder.dataAccounts().register(identity); | |||||
| TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest(); | |||||
| reqBuilder.signAsEndpoint(adminKey); | |||||
| defaultDataAccount = identity.getAddress(); | |||||
| return reqBuilder.buildRequest(); | |||||
| } | |||||
| private TransactionRequest kvStorageRequest(Bytes address, HashDigest ledgerHash, AsymmetricKeypair adminKey) { | |||||
| TxBuilder txbuilder = new TxBuilder(ledgerHash); | |||||
| long currValue = keyPrefix.getAndIncrement(); | |||||
| txbuilder.dataAccount(address).set("key-" + currValue + "-" + System.currentTimeMillis(), | |||||
| BytesUtils.toBytes("value-" + currValue), -1L); | |||||
| TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest(); | |||||
| reqBuilder.signAsEndpoint(adminKey); | |||||
| return reqBuilder.buildRequest(); | |||||
| } | |||||
| private MsgQueueProducer txProducer; | |||||
| private final ExecutorService instanceFactory = Executors.newSingleThreadExecutor(); | |||||
| private final ArrayBlockingQueue<List<byte[]>> txBlockingQueue = new ArrayBlockingQueue(1); | |||||
| private final LinkedList<Bytes> dataAccountAddress = new LinkedList<>(); | |||||
| private Bytes defaultDataAccount; | |||||
| private static final AtomicLong keyPrefix = new AtomicLong(); | |||||
| public void userRegister(int count) throws Exception { | |||||
| initTxProducer(); | |||||
| int loop = 0; | |||||
| if (count <= 0) { | |||||
| userCreate(); | |||||
| } else { | |||||
| loop = count / CapabilitySettings.TX_SIZE_PER_SEND; | |||||
| userCreate(loop); | |||||
| } | |||||
| // 从队列中获取数据 | |||||
| if (count <= 0) { | |||||
| for (;;) { | |||||
| txRequestSend(); | |||||
| } | |||||
| } else { | |||||
| for (int i = 0; i < loop; i++) { | |||||
| txRequestSend(); | |||||
| } | |||||
| } | |||||
| closeTxProducer(); | |||||
| } | |||||
| public void dataAccountRegister(int count) throws Exception { | |||||
| initTxProducer(); | |||||
| int loop = 0; | |||||
| if (count <= 0) { | |||||
| dataAccountCreate(); | |||||
| } else { | |||||
| loop = count / CapabilitySettings.TX_SIZE_PER_SEND; | |||||
| dataAccountCreate(loop); | |||||
| } | |||||
| // 从队列中获取数据 | |||||
| if (count <= 0) { | |||||
| for (;;) { | |||||
| txRequestSend(); | |||||
| } | |||||
| } else { | |||||
| for (int i = 0; i < loop; i++) { | |||||
| txRequestSend(); | |||||
| } | |||||
| } | |||||
| closeTxProducer(); | |||||
| } | |||||
| public void userAndDataAccountRegister(int userCount, int dataAccountCount) throws Exception { | |||||
| if (userCount <= 0 || dataAccountCount <= 0) { | |||||
| throw new IllegalArgumentException("userCount and dataAccountCount can not be 0!!!"); | |||||
| } | |||||
| initTxProducer(); | |||||
| int userLoop = userCount / CapabilitySettings.TX_SIZE_PER_SEND; | |||||
| int dataAccountLoop = dataAccountCount / CapabilitySettings.TX_SIZE_PER_SEND; | |||||
| userCreate(userLoop); | |||||
| dataAccountCreate(dataAccountLoop); | |||||
| for (int i = 0, totalLoop = userLoop + dataAccountCount; i < totalLoop; i++) { | |||||
| txRequestSend(); | |||||
| } | |||||
| closeTxProducer(); | |||||
| } | |||||
| public void dataAccountRegisterAndKvStorage(int dataAccountCount, int kvCount) throws Exception { | |||||
| if (kvCount <= 0 || dataAccountCount <= 0) { | |||||
| throw new IllegalArgumentException("userCount and dataAccountCount can not be 0!!!"); | |||||
| } | |||||
| initTxProducer(); | |||||
| int dataAccountLoop = dataAccountCount / CapabilitySettings.TX_SIZE_PER_SEND; | |||||
| dataAccountCreate(dataAccountLoop); | |||||
| // 首先将数据账户写入 | |||||
| for (int i = 0; i < dataAccountLoop; i++) { | |||||
| txRequestSend(); | |||||
| } | |||||
| int kvLoop = kvCount / CapabilitySettings.TX_SIZE_PER_SEND; | |||||
| // 然后将每个数据账户都写入指定数量的kv | |||||
| Iterator<Bytes> iterator = dataAccountAddress.iterator(); | |||||
| while (iterator.hasNext()) { | |||||
| Bytes address = iterator.next(); | |||||
| kvStorageCreate(kvCount, address); | |||||
| } | |||||
| for (int i = 0, loop = kvLoop * dataAccountCount; i < loop; i++) { | |||||
| txRequestSend(); | |||||
| } | |||||
| closeTxProducer(); | |||||
| } | |||||
| public void kvStorage(int kvCount) throws Exception { | |||||
| initTxProducer(); | |||||
| dataAccountDefaultCreate(); | |||||
| try { | |||||
| txRequestSend(); | |||||
| // 确认结块成功 | |||||
| Thread.sleep(10000); | |||||
| } catch (Exception e) { | |||||
| throw e; | |||||
| } | |||||
| int kvLoop = kvCount / CapabilitySettings.TX_SIZE_PER_SEND; | |||||
| // 然后将每个数据账户都写入指定数量的kv | |||||
| Bytes address = defaultDataAccount; | |||||
| kvStorageCreate(kvLoop, address); | |||||
| for (int i = 0; i < kvLoop; i++) { | |||||
| txRequestSend(); | |||||
| } | |||||
| closeTxProducer(); | |||||
| } | |||||
| private void txRequestSend() throws Exception { | |||||
| List<byte[]> txRequests = txBlockingQueue.take(); | |||||
| if (txRequests != null && !txRequests.isEmpty()) { | |||||
| Iterator<byte[]> iterator = txRequests.iterator(); | |||||
| while (iterator.hasNext()) { | |||||
| byte[] txRequest = iterator.next(); | |||||
| try { | |||||
| txProducer.publish(txRequest); | |||||
| } catch (Exception e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| ConsoleUtils.info("[*] Transaction Request send success!!!"); | |||||
| } | |||||
| } | |||||
| private void initTxProducer() throws Exception { | |||||
| txProducer = MsgQueueFactory.newProducer(CapabilitySettings.MSG_QUEUE_URL, CapabilitySettings.TX_TOPIC); | |||||
| txProducer.connect(); | |||||
| ConsoleUtils.info("[*] Transaction Producer start success!!!"); | |||||
| } | |||||
| private void closeTxProducer() throws Exception { | |||||
| txProducer.close(); | |||||
| } | |||||
| private void userCreate(int loop) { | |||||
| instanceFactory.execute(() -> { | |||||
| for (int index = 0; index < loop; index++) { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| try { | |||||
| LinkedList<byte[]> txSerializeBytes = userActiveCreate(); | |||||
| txBlockingQueue.put(txSerializeBytes); | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| private void userCreate() { | |||||
| // 一直在生产用户 | |||||
| instanceFactory.execute(() -> { | |||||
| for (;;) { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| try { | |||||
| LinkedList<byte[]> txSerializeBytes = userActiveCreate(); | |||||
| txBlockingQueue.put(txSerializeBytes); | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| private void dataAccountCreate(int loop) { | |||||
| dataAccountCreate(loop, false); | |||||
| } | |||||
| private void dataAccountCreate(int loop, final boolean isSave) { | |||||
| instanceFactory.execute(() -> { | |||||
| for (int index = 0; index < loop; index++) { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| try { | |||||
| LinkedList<byte[]> txSerializeBytes = dataAccountActiveCreate(isSave); | |||||
| txBlockingQueue.put(txSerializeBytes); | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| private void dataAccountDefaultCreate() { | |||||
| instanceFactory.execute(() -> { | |||||
| List<byte[]> currentBytes = new ArrayList<>(); | |||||
| TransactionRequest txRequest = dataAccountRegisterRequest(CapabilitySettings.ledgerHash, | |||||
| CapabilitySettings.adminKey); | |||||
| byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class); | |||||
| currentBytes.add(serializeBytes); | |||||
| try { | |||||
| txBlockingQueue.put(currentBytes); | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| }); | |||||
| } | |||||
| private void dataAccountCreate() { | |||||
| // 一直在生产用户 | |||||
| instanceFactory.execute(() -> { | |||||
| for (;;) { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| try { | |||||
| LinkedList<byte[]> txSerializeBytes = dataAccountActiveCreate(); | |||||
| txBlockingQueue.put(txSerializeBytes); | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| private void kvStorageCreate(int loop, Bytes address) { | |||||
| // 一直在生产用户 | |||||
| instanceFactory.execute(() -> { | |||||
| for (int index = 0; index < loop; index++) { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| try { | |||||
| LinkedList<byte[]> txSerializeBytes = kvActiveCreate(address); | |||||
| txBlockingQueue.put(txSerializeBytes); | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| private LinkedList<byte[]> userActiveCreate() { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| LinkedList<byte[]> txSerializeBytes = new LinkedList<>(); | |||||
| for (int i = 0; i < CapabilitySettings.TX_SIZE_PER_SEND; i++) { | |||||
| TransactionRequest txRequest = userRegisterRequest(CapabilitySettings.ledgerHash, | |||||
| CapabilitySettings.adminKey); | |||||
| byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class); | |||||
| txSerializeBytes.addFirst(serializeBytes); | |||||
| } | |||||
| return txSerializeBytes; | |||||
| } | |||||
| private LinkedList<byte[]> dataAccountActiveCreate() { | |||||
| return dataAccountActiveCreate(false); | |||||
| } | |||||
| private LinkedList<byte[]> dataAccountActiveCreate(boolean isSave) { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| LinkedList<byte[]> txSerializeBytes = new LinkedList<>(); | |||||
| for (int i = 0; i < CapabilitySettings.TX_SIZE_PER_SEND; i++) { | |||||
| TransactionRequest txRequest = dataAccountRegisterRequest(CapabilitySettings.ledgerHash, | |||||
| CapabilitySettings.adminKey, isSave); | |||||
| byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class); | |||||
| txSerializeBytes.addFirst(serializeBytes); | |||||
| } | |||||
| return txSerializeBytes; | |||||
| } | |||||
| private LinkedList<byte[]> kvActiveCreate(Bytes address) { | |||||
| // 每次生产10000个,然后放入队列中 | |||||
| LinkedList<byte[]> txSerializeBytes = new LinkedList<>(); | |||||
| for (int i = 0; i < CapabilitySettings.TX_SIZE_PER_SEND; i++) { | |||||
| TransactionRequest txRequest = kvStorageRequest(address, CapabilitySettings.ledgerHash, | |||||
| CapabilitySettings.adminKey); | |||||
| byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class); | |||||
| txSerializeBytes.addFirst(serializeBytes); | |||||
| } | |||||
| return txSerializeBytes; | |||||
| } | |||||
| private TransactionRequest userRegisterRequest(HashDigest ledgerHash, AsymmetricKeypair adminKey) { | |||||
| TxBuilder txbuilder = new TxBuilder(ledgerHash); | |||||
| BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate(); | |||||
| txbuilder.users().register(userKey.getIdentity()); | |||||
| TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest(); | |||||
| reqBuilder.signAsEndpoint(adminKey); | |||||
| return reqBuilder.buildRequest(); | |||||
| } | |||||
| private TransactionRequest dataAccountRegisterRequest(HashDigest ledgerHash, AsymmetricKeypair adminKey, | |||||
| boolean isSave) { | |||||
| TxBuilder txbuilder = new TxBuilder(ledgerHash); | |||||
| BlockchainKeypair dataAccountKey = BlockchainKeyGenerator.getInstance().generate(); | |||||
| BlockchainIdentity identity = dataAccountKey.getIdentity(); | |||||
| txbuilder.dataAccounts().register(identity); | |||||
| TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest(); | |||||
| reqBuilder.signAsEndpoint(adminKey); | |||||
| if (isSave) { | |||||
| dataAccountAddress.addFirst(identity.getAddress()); | |||||
| } | |||||
| return reqBuilder.buildRequest(); | |||||
| } | |||||
| private TransactionRequest dataAccountRegisterRequest(HashDigest ledgerHash, AsymmetricKeypair adminKey) { | |||||
| TxBuilder txbuilder = new TxBuilder(ledgerHash); | |||||
| BlockchainKeypair dataAccountKey = BlockchainKeyGenerator.getInstance().generate(); | |||||
| BlockchainIdentity identity = dataAccountKey.getIdentity(); | |||||
| txbuilder.dataAccounts().register(identity); | |||||
| TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest(); | |||||
| reqBuilder.signAsEndpoint(adminKey); | |||||
| defaultDataAccount = identity.getAddress(); | |||||
| return reqBuilder.buildRequest(); | |||||
| } | |||||
| private TransactionRequest kvStorageRequest(Bytes address, HashDigest ledgerHash, AsymmetricKeypair adminKey) { | |||||
| TxBuilder txbuilder = new TxBuilder(ledgerHash); | |||||
| long currValue = keyPrefix.getAndIncrement(); | |||||
| txbuilder.dataAccount(address).setText("key-" + currValue + "-" + System.currentTimeMillis(), | |||||
| "value-" + currValue, -1L); | |||||
| TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest(); | |||||
| reqBuilder.signAsEndpoint(adminKey); | |||||
| return reqBuilder.buildRequest(); | |||||
| } | |||||
| } | } | ||||
| @@ -1,6 +1,6 @@ | |||||
| package com.jd.blockchain.tools.initializer; | package com.jd.blockchain.tools.initializer; | ||||
| import com.jd.blockchain.ledger.core.LedgerException; | |||||
| import com.jd.blockchain.ledger.LedgerException; | |||||
| public class LedgerInitException extends LedgerException{ | public class LedgerInitException extends LedgerException{ | ||||
| @@ -235,6 +235,10 @@ public class Bytes implements BytesSerializable { | |||||
| } | } | ||||
| return new Bytes(BytesUtils.toBytes(value)); | return new Bytes(BytesUtils.toBytes(value)); | ||||
| } | } | ||||
| public String toUTF8String() { | |||||
| return BytesUtils.toString(toBytes()); | |||||
| } | |||||
| public static Bytes fromLong(long value) { | public static Bytes fromLong(long value) { | ||||
| if (value > -1 && value < MAX_CACHE) { | if (value > -1 && value < MAX_CACHE) { | ||||
| @@ -1,6 +1,11 @@ | |||||
| package com.jd.blockchain.utils.io; | package com.jd.blockchain.utils.io; | ||||
| import java.io.*; | |||||
| import java.io.ByteArrayOutputStream; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.io.ObjectOutputStream; | |||||
| import java.io.OutputStream; | |||||
| import java.io.UnsupportedEncodingException; | |||||
| import com.jd.blockchain.utils.IllegalDataException; | import com.jd.blockchain.utils.IllegalDataException; | ||||
| @@ -19,6 +24,10 @@ public class BytesUtils { | |||||
| public static final int MAX_BUFFER_SIZE = 1024 * 1024 * 1024; | public static final int MAX_BUFFER_SIZE = 1024 * 1024 * 1024; | ||||
| public static final int BUFFER_SIZE = 64; | public static final int BUFFER_SIZE = 64; | ||||
| public static final byte TRUE_BYTE = 1; | |||||
| public static final byte FALSE_BYTE = 0; | |||||
| private BytesUtils() { | private BytesUtils() { | ||||
| } | } | ||||
| @@ -28,10 +37,8 @@ public class BytesUtils { | |||||
| * | * | ||||
| * 此方法不处理两者其中之一为 null 的情形,因为无法定义相等性,所以将引发 {@link NullPointerException} 异常; | * 此方法不处理两者其中之一为 null 的情形,因为无法定义相等性,所以将引发 {@link NullPointerException} 异常; | ||||
| * | * | ||||
| * @param bytes1 | |||||
| * bytes1 | |||||
| * @param bytes2 | |||||
| * bytes2 | |||||
| * @param bytes1 bytes1 | |||||
| * @param bytes2 bytes2 | |||||
| * @return boolean | * @return boolean | ||||
| */ | */ | ||||
| public static boolean equals(byte[] bytes1, byte[] bytes2) { | public static boolean equals(byte[] bytes1, byte[] bytes2) { | ||||
| @@ -64,8 +71,7 @@ public class BytesUtils { | |||||
| * 将输入流的所有内容都读入到字节数组返回; 如果输入流的长度超出 MAX_BUFFER_SIZE 定义的值,则抛出 | * 将输入流的所有内容都读入到字节数组返回; 如果输入流的长度超出 MAX_BUFFER_SIZE 定义的值,则抛出 | ||||
| * IllegalArgumentException ; | * IllegalArgumentException ; | ||||
| * | * | ||||
| * @param in | |||||
| * in | |||||
| * @param in in | |||||
| * @return byte[] | * @return byte[] | ||||
| */ | */ | ||||
| public static byte[] copyToBytes(InputStream in) { | public static byte[] copyToBytes(InputStream in) { | ||||
| @@ -95,15 +101,11 @@ public class BytesUtils { | |||||
| /** | /** | ||||
| * 将输入流复制到输出流; | * 将输入流复制到输出流; | ||||
| * | * | ||||
| * @param in | |||||
| * 输入流; | |||||
| * @param out | |||||
| * 输出流; | |||||
| * @param maxSize | |||||
| * 最大字节大小; | |||||
| * @param in 输入流; | |||||
| * @param out 输出流; | |||||
| * @param maxSize 最大字节大小; | |||||
| * @return 返回实际复制的字节数; | * @return 返回实际复制的字节数; | ||||
| * @throws IOException | |||||
| * exception | |||||
| * @throws IOException exception | |||||
| */ | */ | ||||
| public static int copy(InputStream in, OutputStream out, int maxSize) throws IOException { | public static int copy(InputStream in, OutputStream out, int maxSize) throws IOException { | ||||
| byte[] buffer = new byte[BUFFER_SIZE]; | byte[] buffer = new byte[BUFFER_SIZE]; | ||||
| @@ -126,8 +128,7 @@ public class BytesUtils { | |||||
| /** | /** | ||||
| * 将 int 值转为4字节的二进制数组; | * 将 int 值转为4字节的二进制数组; | ||||
| * | * | ||||
| * @param value | |||||
| * value | |||||
| * @param value value | |||||
| * @return 转换后的二进制数组,高位在前,低位在后; | * @return 转换后的二进制数组,高位在前,低位在后; | ||||
| */ | */ | ||||
| public static byte[] toBytes(int value) { | public static byte[] toBytes(int value) { | ||||
| @@ -142,11 +143,14 @@ public class BytesUtils { | |||||
| return bytes; | return bytes; | ||||
| } | } | ||||
| public static byte[] toBytes(boolean value) { | |||||
| return new byte[] { value ? TRUE_BYTE : FALSE_BYTE }; | |||||
| } | |||||
| /** | /** | ||||
| * 将 long 值转为8字节的二进制数组; | * 将 long 值转为8字节的二进制数组; | ||||
| * | * | ||||
| * @param value | |||||
| * value | |||||
| * @param value value | |||||
| * @return 转换后的二进制数组,高位在前,低位在后; | * @return 转换后的二进制数组,高位在前,低位在后; | ||||
| */ | */ | ||||
| public static byte[] toBytes(long value) { | public static byte[] toBytes(long value) { | ||||
| @@ -158,10 +162,8 @@ public class BytesUtils { | |||||
| /** | /** | ||||
| * 将 int 值转为4字节的二进制数组; | * 将 int 值转为4字节的二进制数组; | ||||
| * | * | ||||
| * @param value | |||||
| * 要转换的int整数; | |||||
| * @param bytes | |||||
| * 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 0 开始的4个元素; | |||||
| * @param value 要转换的int整数; | |||||
| * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 0 开始的4个元素; | |||||
| */ | */ | ||||
| public static void toBytes(short value, byte[] bytes) { | public static void toBytes(short value, byte[] bytes) { | ||||
| toBytes(value, bytes, 0); | toBytes(value, bytes, 0); | ||||
| @@ -176,12 +178,9 @@ public class BytesUtils { | |||||
| * <p> | * <p> | ||||
| * 以“高位在前”的方式转换,即:数值的高位保存在数组地址的低位; | * 以“高位在前”的方式转换,即:数值的高位保存在数组地址的低位; | ||||
| * | * | ||||
| * @param value | |||||
| * 要转换的int整数; | |||||
| * @param bytes | |||||
| * 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素; | |||||
| * @param offset | |||||
| * 写入转换结果的起始位置; | |||||
| * @param value 要转换的int整数; | |||||
| * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素; | |||||
| * @param offset 写入转换结果的起始位置; | |||||
| * @return 返回写入的长度; | * @return 返回写入的长度; | ||||
| */ | */ | ||||
| public static int toBytes(int value, byte[] bytes, int offset) { | public static int toBytes(int value, byte[] bytes, int offset) { | ||||
| @@ -197,12 +196,9 @@ public class BytesUtils { | |||||
| * <p> | * <p> | ||||
| * 以“高位在后”的方式转换,即:数值的高位保存在数组地址的高位; | * 以“高位在后”的方式转换,即:数值的高位保存在数组地址的高位; | ||||
| * | * | ||||
| * @param value | |||||
| * 要转换的int整数; | |||||
| * @param bytes | |||||
| * 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素; | |||||
| * @param offset | |||||
| * 写入转换结果的起始位置; | |||||
| * @param value 要转换的int整数; | |||||
| * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素; | |||||
| * @param offset 写入转换结果的起始位置; | |||||
| * @return 返回写入的长度; | * @return 返回写入的长度; | ||||
| */ | */ | ||||
| public static int toBytesInReverse(int value, byte[] bytes, int offset) { | public static int toBytesInReverse(int value, byte[] bytes, int offset) { | ||||
| @@ -218,14 +214,10 @@ public class BytesUtils { | |||||
| * <p> | * <p> | ||||
| * 以“高位在后”的方式转换,即:数值的高位保存在数组地址的高位; | * 以“高位在后”的方式转换,即:数值的高位保存在数组地址的高位; | ||||
| * | * | ||||
| * @param value | |||||
| * 要转换的int整数; | |||||
| * @param bytes | |||||
| * 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素; | |||||
| * @param offset | |||||
| * 写入转换结果的起始位置; | |||||
| * @param len | |||||
| * 写入长度;必须大于 0 ,小于等于 4; | |||||
| * @param value 要转换的int整数; | |||||
| * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素; | |||||
| * @param offset 写入转换结果的起始位置; | |||||
| * @param len 写入长度;必须大于 0 ,小于等于 4; | |||||
| * @return 返回写入的长度; | * @return 返回写入的长度; | ||||
| */ | */ | ||||
| public static int toBytesInReverse(int value, byte[] bytes, int offset, int len) { | public static int toBytesInReverse(int value, byte[] bytes, int offset, int len) { | ||||
| @@ -263,12 +255,9 @@ public class BytesUtils { | |||||
| /** | /** | ||||
| * 将 long 值转为8字节的二进制数组; | * 将 long 值转为8字节的二进制数组; | ||||
| * | * | ||||
| * @param value | |||||
| * 要转换的long整数; | |||||
| * @param bytes | |||||
| * 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的8个元素; | |||||
| * @param offset | |||||
| * 写入转换结果的起始位置; | |||||
| * @param value 要转换的long整数; | |||||
| * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的8个元素; | |||||
| * @param offset 写入转换结果的起始位置; | |||||
| * @return 返回写入的长度; | * @return 返回写入的长度; | ||||
| */ | */ | ||||
| public static int toBytes(long value, byte[] bytes, int offset) { | public static int toBytes(long value, byte[] bytes, int offset) { | ||||
| @@ -312,6 +301,10 @@ public class BytesUtils { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * @param bytes | |||||
| * @return | |||||
| */ | |||||
| public static String toString(byte[] bytes) { | public static String toString(byte[] bytes) { | ||||
| return toString(bytes, DEFAULT_CHARSET); | return toString(bytes, DEFAULT_CHARSET); | ||||
| } | } | ||||
| @@ -342,11 +335,14 @@ public class BytesUtils { | |||||
| } | } | ||||
| } | } | ||||
| public static boolean toBoolean(byte value) { | |||||
| return value != FALSE_BYTE; | |||||
| } | |||||
| /** | /** | ||||
| * 按从高位到低位的顺序将指定二进制数组从位置 0 开始的 4 个字节转换为 int 整数; | * 按从高位到低位的顺序将指定二进制数组从位置 0 开始的 4 个字节转换为 int 整数; | ||||
| * | * | ||||
| * @param bytes | |||||
| * 要转换的二进制数组; | |||||
| * @param bytes 要转换的二进制数组; | |||||
| * @return 转换后的 int 整数; | * @return 转换后的 int 整数; | ||||
| */ | */ | ||||
| public static int toInt(byte[] bytes) { | public static int toInt(byte[] bytes) { | ||||
| @@ -362,10 +358,8 @@ public class BytesUtils { | |||||
| /** | /** | ||||
| * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 2 个字节转换为 short 整数; | * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 2 个字节转换为 short 整数; | ||||
| * | * | ||||
| * @param bytes | |||||
| * 要转换的二进制数组; | |||||
| * @param offset | |||||
| * 要读取数据的开始位置 | |||||
| * @param bytes 要转换的二进制数组; | |||||
| * @param offset 要读取数据的开始位置 | |||||
| * @return 转换后的 short 整数; | * @return 转换后的 short 整数; | ||||
| */ | */ | ||||
| public static short toShort(byte[] bytes, int offset) { | public static short toShort(byte[] bytes, int offset) { | ||||
| @@ -387,10 +381,8 @@ public class BytesUtils { | |||||
| /** | /** | ||||
| * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; | * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; | ||||
| * | * | ||||
| * @param bytes | |||||
| * 要转换的二进制数组; | |||||
| * @param offset | |||||
| * 要读取数据的开始位置 | |||||
| * @param bytes 要转换的二进制数组; | |||||
| * @param offset 要读取数据的开始位置 | |||||
| * @return 转换后的 int 整数; | * @return 转换后的 int 整数; | ||||
| */ | */ | ||||
| public static int toInt(byte[] bytes, int offset) { | public static int toInt(byte[] bytes, int offset) { | ||||
| @@ -407,14 +399,11 @@ public class BytesUtils { | |||||
| /** | /** | ||||
| * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; | * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; | ||||
| * | * | ||||
| * @param bytes | |||||
| * 要转换的二进制数组; | |||||
| * @param offset | |||||
| * 要读取数据的开始位置 | |||||
| * @param bytes 要转换的二进制数组; | |||||
| * @param offset 要读取数据的开始位置 | |||||
| * @return 转换后的 int 整数; | * @return 转换后的 int 整数; | ||||
| * | * | ||||
| * @param len | |||||
| * 长度;len 必须满足: len 大于等于 1 且小于等于4; | |||||
| * @param len 长度;len 必须满足: len 大于等于 1 且小于等于4; | |||||
| * @return 转换后的 int 整数; | * @return 转换后的 int 整数; | ||||
| */ | */ | ||||
| public static int toInt(byte[] bytes, int offset, int len) { | public static int toInt(byte[] bytes, int offset, int len) { | ||||
| @@ -433,18 +422,14 @@ public class BytesUtils { | |||||
| /** | /** | ||||
| * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; | * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; | ||||
| * | * | ||||
| * @param bytes | |||||
| * 要转换的二进制数组; | |||||
| * @param offset | |||||
| * 要读取数据的开始位置 | |||||
| * @param bytes 要转换的二进制数组; | |||||
| * @param offset 要读取数据的开始位置 | |||||
| * @return 转换后的 int 整数; | * @return 转换后的 int 整数; | ||||
| * | * | ||||
| * @param len | |||||
| * 长度;len 必须满足: len 大于等于 1 且小于等于4; | |||||
| * @param highAlign | |||||
| * 是否高位对齐;<br> | |||||
| * true 表示参数 bytes 的首个字节对应为整数的最高8位;<br> | |||||
| * false 表示参数 bytes 的最后字节对应为整数的最低8位; | |||||
| * @param len 长度;len 必须满足: len 大于等于 1 且小于等于4; | |||||
| * @param highAlign 是否高位对齐;<br> | |||||
| * true 表示参数 bytes 的首个字节对应为整数的最高8位;<br> | |||||
| * false 表示参数 bytes 的最后字节对应为整数的最低8位; | |||||
| * @return 转换后的 int 整数; | * @return 转换后的 int 整数; | ||||
| */ | */ | ||||
| public static int toInt(byte[] bytes, int offset, int len, boolean highAlign) { | public static int toInt(byte[] bytes, int offset, int len, boolean highAlign) { | ||||
| @@ -472,10 +457,8 @@ public class BytesUtils { | |||||
| /** | /** | ||||
| * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 8个字节转换为 long 整数; | * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 8个字节转换为 long 整数; | ||||
| * | * | ||||
| * @param bytes | |||||
| * 要转换的二进制数组; | |||||
| * @param offset | |||||
| * 要读取数据的开始位置 | |||||
| * @param bytes 要转换的二进制数组; | |||||
| * @param offset 要读取数据的开始位置 | |||||
| * @return 转换后的 long 整数; | * @return 转换后的 long 整数; | ||||
| */ | */ | ||||
| public static long toLong(byte[] bytes, int offset) { | public static long toLong(byte[] bytes, int offset) { | ||||
| @@ -495,8 +478,7 @@ public class BytesUtils { | |||||
| /** | /** | ||||
| * 从指定的输入流中读入2个字节,由前到后按由高位到低位的方式转为 short 整数; | * 从指定的输入流中读入2个字节,由前到后按由高位到低位的方式转为 short 整数; | ||||
| * | * | ||||
| * @param in | |||||
| * in | |||||
| * @param in in | |||||
| * @return short | * @return short | ||||
| */ | */ | ||||
| public static short readShort(InputStream in) { | public static short readShort(InputStream in) { | ||||
| @@ -531,8 +513,7 @@ public class BytesUtils { | |||||
| /** | /** | ||||
| * 从指定的输入流中读入4个字节,由前到后按由高位到低位的方式转为 int 整数; | * 从指定的输入流中读入4个字节,由前到后按由高位到低位的方式转为 int 整数; | ||||
| * | * | ||||
| * @param in | |||||
| * in | |||||
| * @param in in | |||||
| * @return int | * @return int | ||||
| */ | */ | ||||
| public static int readInt(InputStream in) { | public static int readInt(InputStream in) { | ||||
| @@ -658,11 +639,9 @@ public class BytesUtils { | |||||
| /** | /** | ||||
| * 从字节数组获取对象 | * 从字节数组获取对象 | ||||
| * | * | ||||
| * @param objBytes | |||||
| * objBytes | |||||
| * @param objBytes objBytes | |||||
| * @return object | * @return object | ||||
| * @throws Exception | |||||
| * exception | |||||
| * @throws Exception exception | |||||
| */ | */ | ||||
| // public static Object getObjectFromBytes(byte[] objBytes) throws Exception { | // public static Object getObjectFromBytes(byte[] objBytes) throws Exception { | ||||
| // if (objBytes == null || objBytes.length == 0) { | // if (objBytes == null || objBytes.length == 0) { | ||||
| @@ -676,11 +655,9 @@ public class BytesUtils { | |||||
| /** | /** | ||||
| * 从对象获取一个字节数组; | * 从对象获取一个字节数组; | ||||
| * | * | ||||
| * @param obj | |||||
| * obj | |||||
| * @param obj obj | |||||
| * @return byte array | * @return byte array | ||||
| * @throws Exception | |||||
| * exception | |||||
| * @throws Exception exception | |||||
| */ | */ | ||||
| public static byte[] getBytesFromObject(Object obj) throws Exception { | public static byte[] getBytesFromObject(Object obj) throws Exception { | ||||
| if (obj == null) { | if (obj == null) { | ||||