Browse Source

Completed the cancellation of transaction template and prepared transaction ;

tags/1.0.0
huanghaiquan 6 years ago
parent
commit
53554a9e03
47 changed files with 1069 additions and 883 deletions
  1. +5
    -5
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
  2. +3
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java
  3. +4
    -4
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java
  4. +9
    -9
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java
  5. +7
    -7
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java
  6. +3
    -2
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java
  7. +19
    -7
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java
  8. +17
    -17
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesData.java
  9. +31
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesDataList.java
  10. +3
    -5
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PreparedTransaction.java
  11. +3
    -1
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionTemplate.java
  12. +9
    -5
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java
  13. +9
    -30
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BooleanValueHolder.java
  14. +9
    -30
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ByteValueHolder.java
  15. +3
    -15
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocation.java
  16. +0
    -26
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java
  17. +2
    -2
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractReturnValue.java
  18. +9
    -9
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java
  19. +23
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/GenericValueHolder.java
  20. +9
    -30
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/IntValueHolder.java
  21. +9
    -30
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LongValueHolder.java
  22. +24
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationCompletedContext.java
  23. +20
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationCompletedListener.java
  24. +35
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationResultHandle.java
  25. +81
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationResultHolder.java
  26. +0
    -11
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationReturnValueHandler.java
  27. +60
    -26
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java
  28. +9
    -30
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ShortValueHolder.java
  29. +15
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TransactionCancelledExeption.java
  30. +1
    -1
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java
  31. +76
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxStateManager.java
  32. +27
    -2
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java
  33. +0
    -45
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolder.java
  34. +0
    -42
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolderBase.java
  35. +34
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolderWrapper.java
  36. +38
    -35
      source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractEventSendOpTemplateTest.java
  37. +4
    -4
      source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DataAccountKVSetOpTemplateTest.java
  38. +2
    -2
      source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/KVDataTest.java
  39. +344
    -342
      source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java
  40. +4
    -4
      source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java
  41. +4
    -4
      source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDKDemo_Contract_Test.java
  42. +23
    -17
      source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java
  43. +7
    -8
      source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java
  44. +1
    -2
      source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java
  45. +57
    -57
      source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/proxy/ContractProxy.java
  46. +1
    -4
      source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/DefaultExceptionHandle.java
  47. +16
    -10
      source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/EventMulticaster.java

+ 5
- 5
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java View File

@@ -4,7 +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.BytesValue; import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.BytesData;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
public class ContractAccount implements AccountHeader { public class ContractAccount implements AccountHeader {
@@ -43,7 +43,7 @@ public class ContractAccount implements AccountHeader {
} }
public long setChaincode(byte[] chaincode, long version) { public long setChaincode(byte[] chaincode, long version) {
BytesValue bytesValue = BytesValueEntry.fromBytes(chaincode);
BytesValue bytesValue = BytesData.fromBytes(chaincode);
return accBase.setBytes(CHAIN_CODE_KEY, bytesValue, version); return accBase.setBytes(CHAIN_CODE_KEY, bytesValue, version);
} }
@@ -60,18 +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) {
BytesValue bytesValue = BytesValueEntry.fromText(value);
BytesValue bytesValue = BytesData.fromText(value);
return accBase.setBytes(encodePropertyKey(key), bytesValue, version); return accBase.setBytes(encodePropertyKey(key), bytesValue, version);
} }
public String getProperty(Bytes key) { public String getProperty(Bytes key) {
BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key)); BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key));
return BytesValueEntry.toText(bytesValue);
return BytesData.toText(bytesValue);
} }
public String getProperty(Bytes key, long version) { public String getProperty(Bytes key, long version) {
BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key), version); BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key), version);
return BytesValueEntry.toText(bytesValue);
return BytesData.toText(bytesValue);
} }
private Bytes encodePropertyKey(Bytes key) { private Bytes encodePropertyKey(Bytes key) {


+ 3
- 3
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java View File

@@ -6,7 +6,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.BytesValue; import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.BytesData;
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;
@@ -49,12 +49,12 @@ public class DataAccount implements AccountHeader, MerkleProvable {
public long setBytes(Bytes key, String value, long version) { public long setBytes(Bytes key, String value, long version) {
BytesValue bytesValue = BytesValueEntry.fromText(value);
BytesValue bytesValue = BytesData.fromText(value);
return baseAccount.setBytes(key, bytesValue, version); return baseAccount.setBytes(key, bytesValue, version);
} }
public long setBytes(Bytes key, byte[] value, long version) { public long setBytes(Bytes key, byte[] value, long version) {
BytesValue bytesValue = BytesValueEntry.fromBytes(value);
BytesValue bytesValue = BytesData.fromBytes(value);
return baseAccount.setBytes(key, bytesValue, version); return baseAccount.setBytes(key, bytesValue, version);
} }


+ 4
- 4
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java View File

@@ -3,7 +3,7 @@ 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.BytesValue;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.BytesData;
import com.jd.blockchain.ledger.UserInfo; import com.jd.blockchain.ledger.UserInfo;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
@@ -50,12 +50,12 @@ public class UserAccount implements UserInfo {
public long setDataPubKey(PubKey pubKey) { public long setDataPubKey(PubKey pubKey) {
byte[] pkBytes = pubKey.toBytes(); byte[] pkBytes = pubKey.toBytes();
return baseAccount.setBytes(DATA_PUB_KEY, BytesValueEntry.fromBytes(pkBytes), -1);
return baseAccount.setBytes(DATA_PUB_KEY, BytesData.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, BytesValueEntry.fromBytes(pkBytes), version);
return baseAccount.setBytes(DATA_PUB_KEY, BytesData.fromBytes(pkBytes), version);
} }
public long setProperty(String key, String value, long version) { public long setProperty(String key, String value, long version) {
@@ -63,7 +63,7 @@ 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), BytesValueEntry.fromText(value), version);
return baseAccount.setBytes(encodePropertyKey(key), BytesData.fromText(value), version);
} }
public String getProperty(Bytes key) { public String getProperty(Bytes key) {


+ 9
- 9
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java View File

@@ -8,7 +8,7 @@ import com.jd.blockchain.crypto.HashDigest;
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.BytesValue; import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.BytesData;
import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.DataAccountRegisterOperation; import com.jd.blockchain.ledger.DataAccountRegisterOperation;
import com.jd.blockchain.ledger.KVDataEntry; import com.jd.blockchain.ledger.KVDataEntry;
@@ -279,7 +279,7 @@ public class ContractLedgerContext implements LedgerContext {


@Override @Override
public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromText(value);
BytesValue bytesValue = BytesData.fromText(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op); handle(op);
return this; return this;
@@ -287,7 +287,7 @@ public class ContractLedgerContext implements LedgerContext {


@Override @Override
public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromBytes(value);
BytesValue bytesValue = BytesData.fromBytes(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op); handle(op);
return this; return this;
@@ -295,7 +295,7 @@ public class ContractLedgerContext implements LedgerContext {


@Override @Override
public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromInt64(value);
BytesValue bytesValue = BytesData.fromInt64(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op); handle(op);
return this; return this;
@@ -312,7 +312,7 @@ public class ContractLedgerContext implements LedgerContext {
@Override @Override
public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromJSON(value);
BytesValue bytesValue = BytesData.fromJSON(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op); handle(op);
return this; return this;
@@ -320,7 +320,7 @@ public class ContractLedgerContext implements LedgerContext {
@Override @Override
public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromXML(value);
BytesValue bytesValue = BytesData.fromXML(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op); handle(op);
return this; return this;
@@ -328,7 +328,7 @@ public class ContractLedgerContext implements LedgerContext {
@Override @Override
public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromBytes(value);
BytesValue bytesValue = BytesData.fromBytes(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op); handle(op);
return this; return this;
@@ -336,7 +336,7 @@ public class ContractLedgerContext implements LedgerContext {
@Override @Override
public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromImage(value);
BytesValue bytesValue = BytesData.fromImage(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op); handle(op);
return this; return this;
@@ -344,7 +344,7 @@ public class ContractLedgerContext implements LedgerContext {
@Override @Override
public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromTimestamp(value);
BytesValue bytesValue = BytesData.fromTimestamp(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op); handle(op);
return this; return this;


+ 7
- 7
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java View File

@@ -12,7 +12,7 @@ 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.BytesData;
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.storage.service.utils.MemoryKVStorage; import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
@@ -53,33 +53,33 @@ public class BaseAccountTest {
assertFalse(baseAccount.isReadonly()); assertFalse(baseAccount.isReadonly());


// 在空白状态下写入数据; // 在空白状态下写入数据;
long v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A"), 0);
long v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), 0);
// 预期失败; // 预期失败;
assertEquals(-1, v); assertEquals(-1, v);


v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A"), 1);
v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), 1);
// 预期失败; // 预期失败;
assertEquals(-1, v); assertEquals(-1, v);


v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A"), -1);
v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), -1);
// 预期成功; // 预期成功;
assertEquals(0, v); assertEquals(0, v);


v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A-1"), -1);
v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.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"), BytesValueEntry.fromText("VALUE_A_" + i), v);
long s = baseAccount.setBytes(Bytes.fromString("A"), BytesData.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"), BytesValueEntry.fromText("VALUE_A_" + v), v + 1);
v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A_" + v), v + 1);
// 预期成功; // 预期成功;
assertEquals(-1, v); assertEquals(-1, v);




+ 3
- 2
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java View File

@@ -21,7 +21,7 @@ import com.jd.blockchain.crypto.HashDigest;
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.BytesValue; import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.BytesData;
import com.jd.blockchain.ledger.EndpointRequest; import com.jd.blockchain.ledger.EndpointRequest;
import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInitSetting; import com.jd.blockchain.ledger.LedgerInitSetting;
@@ -103,6 +103,7 @@ public class ContractInvokingTest {
Random rand = new Random(); Random rand = new Random();
TxBuilder txBuilder = new TxBuilder(ledgerHash); TxBuilder txBuilder = new TxBuilder(ledgerHash);
TestContract contractProxy = txBuilder.contract(contractAddress, TestContract.class); TestContract contractProxy = txBuilder.contract(contractAddress, TestContract.class);
TestContract contractProxy1 = txBuilder.contract(contractAddress, TestContract.class);


String asset = "AK"; String asset = "AK";
long issueAmount = rand.nextLong(); long issueAmount = rand.nextLong();
@@ -120,7 +121,7 @@ public class ContractInvokingTest {
assertEquals(1, opResults.length); assertEquals(1, opResults.length);
assertEquals(0, opResults[0].getIndex()); assertEquals(0, opResults[0].getIndex());


byte[] expectedRetnBytes = BinaryProtocol.encode(BytesValueEntry.fromInt64(issueAmount), BytesValue.class);
byte[] expectedRetnBytes = BinaryProtocol.encode(BytesData.fromInt64(issueAmount), BytesValue.class);
byte[] reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class); byte[] reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class);
assertArrayEquals(expectedRetnBytes, reallyRetnBytes); assertArrayEquals(expectedRetnBytes, reallyRetnBytes);




+ 19
- 7
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java View File

@@ -1,5 +1,6 @@
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.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
@@ -10,10 +11,13 @@ import java.util.Random;


import org.junit.Test; import org.junit.Test;


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.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.BytesDataList;
import com.jd.blockchain.ledger.BytesValueList;
import com.jd.blockchain.ledger.ContractCodeDeployOperation; import com.jd.blockchain.ledger.ContractCodeDeployOperation;
import com.jd.blockchain.ledger.ContractEventSendOperation; import com.jd.blockchain.ledger.ContractEventSendOperation;
import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.CryptoSetting;
@@ -67,8 +71,8 @@ public class TransactionSetTest {
BlockchainKeypair dataKey = BlockchainKeyGenerator.getInstance().generate(); BlockchainKeypair dataKey = BlockchainKeyGenerator.getInstance().generate();
DataAccountRegisterOperation dataAccRegOp = txBuilder.dataAccounts().register(dataKey.getIdentity()); DataAccountRegisterOperation dataAccRegOp = txBuilder.dataAccounts().register(dataKey.getIdentity());


DataAccountKVSetOperation kvsetOP = txBuilder.dataAccount(dataKey.getAddress())
.setText("A", "Value_A_0", -1).setText("B", "Value_B_0", -1).getOperation();
DataAccountKVSetOperation kvsetOP = txBuilder.dataAccount(dataKey.getAddress()).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);
@@ -76,7 +80,7 @@ public class TransactionSetTest {
ContractCodeDeployOperation contractDplOP = txBuilder.contracts().deploy(contractKey.getIdentity(), chainCode); ContractCodeDeployOperation contractDplOP = txBuilder.contracts().deploy(contractKey.getIdentity(), chainCode);


ContractEventSendOperation contractEvtSendOP = txBuilder.contractEvents().send(contractKey.getAddress(), "test", ContractEventSendOperation contractEvtSendOP = txBuilder.contractEvents().send(contractKey.getAddress(), "test",
"TestContractArgs".getBytes());
BytesDataList.singleText("TestContractArgs"));


TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest(); TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();


@@ -98,7 +102,8 @@ public class TransactionSetTest {
txSnapshot.setContractAccountSetHash(contractAccountSetHash); txSnapshot.setContractAccountSetHash(contractAccountSetHash);


long blockHeight = 8922L; long blockHeight = 8922L;
LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txReq, TransactionState.SUCCESS, txSnapshot, null);
LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txReq, TransactionState.SUCCESS, txSnapshot,
null);
txset.add(tx); txset.add(tx);


assertTrue(txset.isUpdated()); assertTrue(txset.isUpdated());
@@ -172,7 +177,8 @@ public class TransactionSetTest {
for (int i = 0; i < acutualKVWriteSet.length; i++) { for (int i = 0; i < acutualKVWriteSet.length; i++) {
assertEquals(expKVWriteSet[i].getKey(), acutualKVWriteSet[i].getKey()); assertEquals(expKVWriteSet[i].getKey(), acutualKVWriteSet[i].getKey());
assertEquals(expKVWriteSet[i].getExpectedVersion(), acutualKVWriteSet[i].getExpectedVersion()); assertEquals(expKVWriteSet[i].getExpectedVersion(), acutualKVWriteSet[i].getExpectedVersion());
assertTrue(BytesUtils.equals(expKVWriteSet[i].getValue().getValue().toBytes(), acutualKVWriteSet[i].getValue().getValue().toBytes()));
assertTrue(BytesUtils.equals(expKVWriteSet[i].getValue().getValue().toBytes(),
acutualKVWriteSet[i].getValue().getValue().toBytes()));
} }


ContractCodeDeployOperation actualContractDplOp = (ContractCodeDeployOperation) actualOperations[3]; ContractCodeDeployOperation actualContractDplOp = (ContractCodeDeployOperation) actualOperations[3];
@@ -184,8 +190,14 @@ public class TransactionSetTest {
assertEquals(contractEvtSendOP.getContractAddress(), actualContractEvtSendOp.getContractAddress()); assertEquals(contractEvtSendOP.getContractAddress(), actualContractEvtSendOp.getContractAddress());
assertEquals(contractEvtSendOP.getEvent(), actualContractEvtSendOp.getEvent()); assertEquals(contractEvtSendOP.getEvent(), actualContractEvtSendOp.getEvent());
assertEquals("test", actualContractEvtSendOp.getEvent()); assertEquals("test", actualContractEvtSendOp.getEvent());
assertTrue(BytesUtils.equals(contractEvtSendOP.getArgs(), actualContractEvtSendOp.getArgs()));
assertTrue(BytesUtils.equals("TestContractArgs".getBytes(), actualContractEvtSendOp.getArgs()));

byte[] expectedBytes = BinaryProtocol.encode(contractEvtSendOP.getArgs(), BytesValueList.class);
byte[] actualBytes = BinaryProtocol.encode(actualContractEvtSendOp.getArgs(), BytesValueList.class);
assertArrayEquals(expectedBytes, actualBytes);
expectedBytes = BinaryProtocol.encode(BytesDataList.singleText("TestContractArgs"), BytesValueList.class);
actualBytes = BinaryProtocol.encode(actualContractEvtSendOp.getArgs(), BytesValueList.class);
assertArrayEquals(expectedBytes, actualBytes);
} }


} }

source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEntry.java → source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesData.java View File

@@ -8,38 +8,38 @@ import com.jd.blockchain.utils.io.BytesUtils;
* @author huanghaiquan * @author huanghaiquan
* *
*/ */
public class BytesValueEntry implements BytesValue {
public class BytesData implements BytesValue {
DataType type; DataType type;
Bytes value; Bytes value;


private BytesValueEntry(DataType type, byte[] bytes) {
private BytesData(DataType type, byte[] bytes) {
this.type = type; this.type = type;
this.value = new Bytes(bytes); this.value = new Bytes(bytes);
} }


private BytesValueEntry(DataType type, Bytes bytes) {
private BytesData(DataType type, Bytes bytes) {
this.type = type; this.type = type;
this.value = bytes; this.value = bytes;
} }
public static BytesValue fromType(DataType type, byte[] value) { public static BytesValue fromType(DataType type, byte[] value) {
return new BytesValueEntry(type, value);
return new BytesData(type, value);
} }


public static BytesValue fromBytes(byte[] value) { public static BytesValue fromBytes(byte[] value) {
return new BytesValueEntry(DataType.BYTES, value);
return new BytesData(DataType.BYTES, value);
} }


public static BytesValue fromBytes(Bytes value) { public static BytesValue fromBytes(Bytes value) {
return new BytesValueEntry(DataType.BYTES, value);
return new BytesData(DataType.BYTES, value);
} }


public static BytesValue fromImage(byte[] value) { public static BytesValue fromImage(byte[] value) {
return new BytesValueEntry(DataType.IMG, value);
return new BytesData(DataType.IMG, value);
} }


public static BytesValue fromImage(Bytes value) { public static BytesValue fromImage(Bytes value) {
return new BytesValueEntry(DataType.IMG, value);
return new BytesData(DataType.IMG, value);
} }


/** /**
@@ -49,7 +49,7 @@ public class BytesValueEntry implements BytesValue {
* @return * @return
*/ */
public static BytesValue fromText(String value) { public static BytesValue fromText(String value) {
return new BytesValueEntry(DataType.TEXT, BytesUtils.toBytes(value));
return new BytesData(DataType.TEXT, BytesUtils.toBytes(value));
} }


/** /**
@@ -70,35 +70,35 @@ public class BytesValueEntry implements BytesValue {
} }


public static BytesValue fromJSON(String value) { public static BytesValue fromJSON(String value) {
return new BytesValueEntry(DataType.JSON, BytesUtils.toBytes(value));
return new BytesData(DataType.JSON, BytesUtils.toBytes(value));
} }


public static BytesValue fromXML(String value) { public static BytesValue fromXML(String value) {
return new BytesValueEntry(DataType.XML, BytesUtils.toBytes(value));
return new BytesData(DataType.XML, BytesUtils.toBytes(value));
} }


public static BytesValue fromInt32(int value) { public static BytesValue fromInt32(int value) {
return new BytesValueEntry(DataType.INT32, BytesUtils.toBytes(value));
return new BytesData(DataType.INT32, BytesUtils.toBytes(value));
} }


public static BytesValue fromInt64(long value) { public static BytesValue fromInt64(long value) {
return new BytesValueEntry(DataType.INT64, BytesUtils.toBytes(value));
return new BytesData(DataType.INT64, BytesUtils.toBytes(value));
} }


public static BytesValue fromInt16(short value) { public static BytesValue fromInt16(short value) {
return new BytesValueEntry(DataType.INT16, BytesUtils.toBytes(value));
return new BytesData(DataType.INT16, BytesUtils.toBytes(value));
} }


public static BytesValue fromInt8(byte value) { public static BytesValue fromInt8(byte value) {
return new BytesValueEntry(DataType.INT8, BytesUtils.toBytes(value));
return new BytesData(DataType.INT8, BytesUtils.toBytes(value));
} }


public static BytesValue fromTimestamp(long value) { public static BytesValue fromTimestamp(long value) {
return new BytesValueEntry(DataType.TIMESTAMP, BytesUtils.toBytes(value));
return new BytesData(DataType.TIMESTAMP, BytesUtils.toBytes(value));
} }


public static BytesValue fromBoolean(boolean value) { public static BytesValue fromBoolean(boolean value) {
return new BytesValueEntry(DataType.BOOLEAN, BytesUtils.toBytes(value));
return new BytesData(DataType.BOOLEAN, BytesUtils.toBytes(value));
} }


@Override @Override

+ 31
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesDataList.java View File

@@ -0,0 +1,31 @@
package com.jd.blockchain.ledger;

public class BytesDataList implements BytesValueList {

private BytesValue[] bytesValues;

public BytesDataList(BytesValue... bytesValues) {
this.bytesValues = bytesValues;
}

@Override
public BytesValue[] getValues() {
return bytesValues;
}

public static BytesValueList singleText(String value) {
return new BytesDataList(BytesData.fromText(value));
}
public static BytesValueList singleLong(long value) {
return new BytesDataList(BytesData.fromInt64(value));
}
public static BytesValueList singleInt(int value) {
return new BytesDataList(BytesData.fromInt32(value));
}
public static BytesValueList singleBoolean(boolean value) {
return new BytesDataList(BytesData.fromBoolean(value));
}
}

+ 3
- 5
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PreparedTransaction.java View File

@@ -1,5 +1,7 @@
package com.jd.blockchain.ledger; package com.jd.blockchain.ledger;


import java.io.Closeable;

import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;


@@ -9,7 +11,7 @@ import com.jd.blockchain.crypto.HashDigest;
* @author huanghaiquan * @author huanghaiquan
* *
*/ */
public interface PreparedTransaction extends HashObject {
public interface PreparedTransaction extends HashObject, Closeable {


/** /**
* 交易内容的 Hash; * 交易内容的 Hash;
@@ -55,8 +57,4 @@ public interface PreparedTransaction extends HashObject {
*/ */
TransactionResponse commit(); TransactionResponse commit();


/**
* 取消交易;<br>
*/
void cancel();
} }

+ 3
- 1
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionTemplate.java View File

@@ -1,5 +1,7 @@
package com.jd.blockchain.ledger; package com.jd.blockchain.ledger;
import java.io.Closeable;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.transaction.ClientOperator; import com.jd.blockchain.transaction.ClientOperator;
@@ -9,7 +11,7 @@ import com.jd.blockchain.transaction.ClientOperator;
* @author huanghaiquan * @author huanghaiquan
* *
*/ */
public interface TransactionTemplate extends ClientOperator {
public interface TransactionTemplate extends ClientOperator, Closeable {
HashDigest getLedgerHash(); HashDigest getLedgerHash();


+ 9
- 5
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java View File

@@ -106,15 +106,15 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe
* *
* @return * @return
*/ */
public Collection<OperationReturnValueHandler> getReturnValuetHandlers() {
List<OperationReturnValueHandler> resultHandlers = new ArrayList<OperationReturnValueHandler>();
public Collection<OperationResultHandle> getReturnValuetHandlers() {
List<OperationResultHandle> resultHandlers = new ArrayList<OperationResultHandle>();
int index = 0; int index = 0;
for (Operation op : operationList) { for (Operation op : operationList) {
if (op instanceof ContractEventSendOperation) { if (op instanceof ContractEventSendOperation) {
// 操作具有返回值,创建对应的结果处理器; // 操作具有返回值,创建对应的结果处理器;
ContractEventSendOpTemplate opTemp = (ContractEventSendOpTemplate) op; ContractEventSendOpTemplate opTemp = (ContractEventSendOpTemplate) op;
ContractInvocation invocation = opTemp.getInvocation(); ContractInvocation invocation = opTemp.getInvocation();
OperationReturnValueHandler retnHandler;
OperationResultHandle retnHandler;
if (invocation == null) { if (invocation == null) {
retnHandler = new NullOperationReturnValueHandler(index); retnHandler = new NullOperationReturnValueHandler(index);
} else { } else {
@@ -278,7 +278,7 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe
* @author huanghaiquan * @author huanghaiquan
* *
*/ */
private static class NullOperationReturnValueHandler implements OperationReturnValueHandler {
private static class NullOperationReturnValueHandler implements OperationResultHandle {
private int operationIndex; private int operationIndex;
@@ -292,10 +292,14 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe
} }
@Override @Override
public Object setReturnValue(BytesValue bytesValue) {
public Object complete(BytesValue bytesValue) {
return null; return null;
} }
@Override
public void complete(Throwable error) {
}
} }
} }

+ 9
- 30
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BooleanValueHolder.java View File

@@ -1,43 +1,22 @@
package com.jd.blockchain.transaction; package com.jd.blockchain.transaction;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class BooleanValueHolder extends ValueHolderWrapper {


public class BooleanValueHolder extends ValueHolderBase {

BooleanValueHolder(ContractInvocation invocation) {
super(invocation);
BooleanValueHolder(OperationResultHolder resultHolder) {
super(resultHolder);
} }


/** /**
* 等待结果合约调用的结果返回;
* 获取值;<br>
* *
* @return
*/
public boolean get() {
return (boolean) super.getValue();
}

/**
* 等待结果合约调用的结果返回;
* 此方法不堵塞,调用立即返回;<br>
* *
* @param timeout
* @return
* @throws TimeoutException
*/
public boolean get(long timeout) throws TimeoutException {
return get(timeout, TimeUnit.MILLISECONDS);
}

/**
* 等待结果合约调用的结果返回;
* 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 false;
* *
* @param timeout
* @param unit
* @return * @return
* @throws TimeoutException
*/ */
public boolean get(long timeout, TimeUnit unit) throws TimeoutException {
return (boolean) super.getValue(timeout, unit);
public boolean get() {
return super.isCompleted() ? (boolean) super.getValue() : false;
} }

} }

+ 9
- 30
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ByteValueHolder.java View File

@@ -1,43 +1,22 @@
package com.jd.blockchain.transaction; package com.jd.blockchain.transaction;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class ByteValueHolder extends ValueHolderWrapper {


public class ByteValueHolder extends ValueHolderBase {

ByteValueHolder(ContractInvocation invocation) {
super(invocation);
ByteValueHolder(OperationResultHolder resultHolder) {
super(resultHolder);
} }


/** /**
* 等待结果合约调用的结果返回;
* 获取值;<br>
* *
* @return
*/
public byte get() {
return (byte) super.getValue();
}

/**
* 等待结果合约调用的结果返回;
* 此方法不堵塞,调用立即返回;<br>
* *
* @param timeout
* @return
* @throws TimeoutException
*/
public byte get(long timeout) throws TimeoutException {
return get(timeout, TimeUnit.MILLISECONDS);
}

/**
* 等待结果合约调用的结果返回;
* 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 0;
* *
* @param timeout
* @param unit
* @return * @return
* @throws TimeoutException
*/ */
public byte get(long timeout, TimeUnit unit) throws TimeoutException {
return (byte) super.getValue(timeout, unit);
public byte get() {
return super.isCompleted() ? (byte) super.getValue() : 0;
} }

} }

+ 3
- 15
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocation.java View File

@@ -1,8 +1,6 @@
package com.jd.blockchain.transaction; package com.jd.blockchain.transaction;


import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;


import com.jd.blockchain.contract.ContractType; import com.jd.blockchain.contract.ContractType;
import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.BytesValue;
@@ -14,7 +12,7 @@ import com.jd.blockchain.ledger.BytesValueEncoding;
* @author huanghaiquan * @author huanghaiquan
* *
*/ */
class ContractInvocation implements OperationReturnValueHandler {
class ContractInvocation extends OperationResultHolder {


private Method method; private Method method;


@@ -22,12 +20,9 @@ class ContractInvocation implements OperationReturnValueHandler {


private int operationIndex = -1; private int operationIndex = -1;


private CompletableFuture<Object> returnValueFuture;

public ContractInvocation(ContractType contractType, Method method) { public ContractInvocation(ContractType contractType, Method method) {
this.contractType = contractType; this.contractType = contractType;
this.method = method; this.method = method;
this.returnValueFuture = new CompletableFuture<Object>();
} }


public ContractType getContractType() { public ContractType getContractType() {
@@ -47,16 +42,9 @@ class ContractInvocation implements OperationReturnValueHandler {
return method.getReturnType(); return method.getReturnType();
} }


public Future<Object> getReturnValue() {
return returnValueFuture;
}

@Override @Override
public Object setReturnValue(BytesValue bytesValue) {
// Resolve BytesValue to an value object with the return type;
Object returnValue = BytesValueEncoding.decode(bytesValue, method.getReturnType());
returnValueFuture.complete(returnValue);
return returnValue;
protected Object decodeResult(BytesValue bytesValue) {
return BytesValueEncoding.decode(bytesValue, method.getReturnType());
} }


} }

+ 0
- 26
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java View File

@@ -4,10 +4,8 @@ import java.lang.reflect.Proxy;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import com.jd.blockchain.contract.EventResult;
import com.jd.blockchain.contract.ContractType; import com.jd.blockchain.contract.ContractType;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.IllegalDataException;
/** /**
* 合约调用代理的构建器; * 合约调用代理的构建器;
@@ -19,8 +17,6 @@ public class ContractInvocationProxyBuilder {
private Map<Class<?>, ContractType> contractTypes = new ConcurrentHashMap<>(); private Map<Class<?>, ContractType> contractTypes = new ConcurrentHashMap<>();
// private Map<Object, Integer> contractOperations = new ConcurrentHashMap<>();
public <T> T create(String address, Class<T> contractIntf, ContractEventSendOperationBuilder contractEventBuilder) { public <T> T create(String address, Class<T> contractIntf, ContractEventSendOperationBuilder contractEventBuilder) {
return create(Bytes.fromBase58(address), contractIntf, contractEventBuilder); return create(Bytes.fromBase58(address), contractIntf, contractEventBuilder);
} }
@@ -33,31 +29,9 @@ public class ContractInvocationProxyBuilder {
T proxy = (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), T proxy = (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class<?>[] { contractIntf }, proxyHandler); new Class<?>[] { contractIntf }, proxyHandler);
// // 创建关联关系
// contractOperations.put(proxy, proxyHandler.opIndex());
return proxy; return proxy;
} }
// public <T> EventResult<T> execute(ContractEventExecutor execute) {
// Object contractProxy = execute.execute();
// if (contractProxy == null) {
// // 该方法执行必须要有返回值
// throw new IllegalStateException(
// String.format("ContractEventExecutor [%s] 's return must be not empty !!!", execute.toString()));
// }
// if (!(contractProxy instanceof Proxy)) {
// throw new IllegalDataException(
// String.format("ContractEventExecutor [%s] 's return must from TxTemplate.contract()'s result !!!",
// execute.toString()));
// }
//
// Integer opIndex = contractOperations.get(contractProxy);
// if (opIndex != null && opIndex > -1) {
// return new EventResult<>(opIndex);
// }
// return null;
// }
private ContractType resolveContractType(Class<?> contractIntf) { private ContractType resolveContractType(Class<?> contractIntf) {
ContractType contractType = contractTypes.get(contractIntf); ContractType contractType = contractTypes.get(contractIntf);
if (contractType != null) { if (contractType != null) {


+ 2
- 2
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractReturnValue.java View File

@@ -26,9 +26,9 @@ public class ContractReturnValue {
* @param call * @param call
* @return * @return
*/ */
public static <T> ValueHolder<T> decode(T call) {
public static <T> GenericValueHolder<T> decode(T call) {
ContractInvocation invocation = ContractInvocationStub.take(); ContractInvocation invocation = ContractInvocationStub.take();
return new ValueHolder<T>(invocation);
return new GenericValueHolder<T>(invocation);
} }


/** /**


+ 9
- 9
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java View File

@@ -1,7 +1,7 @@
package com.jd.blockchain.transaction; 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.BytesData;
import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
@@ -26,14 +26,14 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe
@Override @Override
public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromBytes(value);
BytesValue bytesValue = BytesData.fromBytes(value);
operation.set(key, bytesValue, expVersion); operation.set(key, bytesValue, expVersion);
return this; return this;
} }
@Override @Override
public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromImage(value);
BytesValue bytesValue = BytesData.fromImage(value);
operation.set(key, bytesValue, expVersion); operation.set(key, bytesValue, expVersion);
return this; return this;
} }
@@ -45,42 +45,42 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe
@Override @Override
public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromText(value);
BytesValue bytesValue = BytesData.fromText(value);
operation.set(key, bytesValue, expVersion); operation.set(key, bytesValue, expVersion);
return this; return this;
} }
@Override @Override
public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromBytes(value);
BytesValue bytesValue = BytesData.fromBytes(value);
operation.set(key, bytesValue, expVersion); operation.set(key, bytesValue, expVersion);
return this; return this;
} }
@Override @Override
public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromInt64(value);
BytesValue bytesValue = BytesData.fromInt64(value);
operation.set(key, bytesValue, expVersion); operation.set(key, bytesValue, expVersion);
return this; return this;
} }
@Override @Override
public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromJSON(value);
BytesValue bytesValue = BytesData.fromJSON(value);
operation.set(key, bytesValue, expVersion); operation.set(key, bytesValue, expVersion);
return this; return this;
} }
@Override @Override
public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromXML(value);
BytesValue bytesValue = BytesData.fromXML(value);
operation.set(key, bytesValue, expVersion); operation.set(key, bytesValue, expVersion);
return this; return this;
} }
@Override @Override
public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromTimestamp(value);
BytesValue bytesValue = BytesData.fromTimestamp(value);
operation.set(key, bytesValue, expVersion); operation.set(key, bytesValue, expVersion);
return this; return this;
} }


+ 23
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/GenericValueHolder.java View File

@@ -0,0 +1,23 @@
package com.jd.blockchain.transaction;

public class GenericValueHolder<T> extends ValueHolderWrapper {

GenericValueHolder(OperationResultHolder resultHolder) {
super(resultHolder);
}

/**
* 获取值;<br>
*
* 此方法不堵塞,调用立即返回;<br>
*
* 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 null;
*
* @return
*/
@SuppressWarnings("unchecked")
public T get() {
return (T) super.getValue();
}

}

+ 9
- 30
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/IntValueHolder.java View File

@@ -1,43 +1,22 @@
package com.jd.blockchain.transaction; package com.jd.blockchain.transaction;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class IntValueHolder extends ValueHolderWrapper {


public class IntValueHolder extends ValueHolderBase {

IntValueHolder(ContractInvocation invocation) {
super(invocation);
IntValueHolder(OperationResultHolder resultHolder) {
super(resultHolder);
} }


/** /**
* 等待结果合约调用的结果返回;
* 获取值;<br>
* *
* @return
*/
public int get() {
return (int) super.getValue();
}

/**
* 等待结果合约调用的结果返回;
* 此方法不堵塞,调用立即返回;<br>
* *
* @param timeout
* @return
* @throws TimeoutException
*/
public int get(long timeout) throws TimeoutException {
return get(timeout, TimeUnit.MILLISECONDS);
}

/**
* 等待结果合约调用的结果返回;
* 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 0;
* *
* @param timeout
* @param unit
* @return * @return
* @throws TimeoutException
*/ */
public int get(long timeout, TimeUnit unit) throws TimeoutException {
return (int) super.getValue(timeout, unit);
public int get() {
return super.isCompleted() ? (int) super.getValue() : 0;
} }

} }

+ 9
- 30
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LongValueHolder.java View File

@@ -1,43 +1,22 @@
package com.jd.blockchain.transaction; package com.jd.blockchain.transaction;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class LongValueHolder extends ValueHolderWrapper {


public class LongValueHolder extends ValueHolderBase {

LongValueHolder(ContractInvocation invocation) {
super(invocation);
LongValueHolder(OperationResultHolder resultHolder) {
super(resultHolder);
} }


/** /**
* 等待结果合约调用的结果返回;
* 获取值;<br>
* *
* @return
*/
public long get() {
return (long) super.getValue();
}

/**
* 等待结果合约调用的结果返回;
* 此方法不堵塞,调用立即返回;<br>
* *
* @param timeout
* @return
* @throws TimeoutException
*/
public long get(long timeout) throws TimeoutException {
return get(timeout, TimeUnit.MILLISECONDS);
}

/**
* 等待结果合约调用的结果返回;
* 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 0;
* *
* @param timeout
* @param unit
* @return * @return
* @throws TimeoutException
*/ */
public long get(long timeout, TimeUnit unit) throws TimeoutException {
return (long) super.getValue(timeout, unit);
public long get() {
return super.isCompleted() ? (long) super.getValue() : 0;
} }

} }

+ 24
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationCompletedContext.java View File

@@ -0,0 +1,24 @@
package com.jd.blockchain.transaction;

import com.jd.blockchain.ledger.BytesValue;

public class OperationCompletedContext {

private int operationIndex;

private BytesValue returnBytesValue;

public OperationCompletedContext(int operationIndex, BytesValue returnBytesValue) {
this.operationIndex = operationIndex;
this.returnBytesValue = returnBytesValue;
}

public int getOperationIndex() {
return operationIndex;
}

public BytesValue getReturnBytesValue() {
return returnBytesValue;
}

}

+ 20
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationCompletedListener.java View File

@@ -0,0 +1,20 @@
package com.jd.blockchain.transaction;

/**
* 操作完成监听器;
*
* @author huanghaiquan
*
*/
public interface OperationCompletedListener {

/**
* 当操作完成时发生;
*
* @param retnValue 返回值;
* @param error 异常;如果值为非空,则表示由异常导致结束;
* @param context 上下文对象;
*/
void onCompleted(Object retnValue, Throwable error, OperationCompletedContext context);

}

+ 35
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationResultHandle.java View File

@@ -0,0 +1,35 @@
package com.jd.blockchain.transaction;

import com.jd.blockchain.ledger.BytesValue;

/**
* 操作返回值处理器;
*
* @author huanghaiquan
*
*/
interface OperationResultHandle {

/**
* 操作的索引位置;
*
* @return
*/
int getOperationIndex();

/**
* 正常地完成;
*
* @param returnBytesValue
* @return
*/
Object complete(BytesValue returnBytesValue);

/**
* 以异常方式完成;
*
* @param error
*/
void complete(Throwable error);

}

+ 81
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationResultHolder.java View File

@@ -0,0 +1,81 @@
package com.jd.blockchain.transaction;

import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.utils.event.EventMulticaster;

abstract class OperationResultHolder implements OperationResultHandle {

private Object value;

private Throwable error;

private volatile boolean completed;

private EventMulticaster<OperationCompletedListener> listenerMulticaster;

/**
* 导致结束的错误;
*
* @return
*/
public Throwable getError() {
return error;
}

/**
* 是否已经处理完成;
*
* @return
*/
public boolean isCompleted() {
return completed;
}

/**
* 获取操作的返回值; <br>
* 在操作未完成之前,总是返回 null;<br>
* 可以通过 {@link #isCompleted()} 方法判断操作是否已经完成;<br>
* 可以通过 {@link #addCompletedListener(OperationCompletedListener)}
* 方法添加监听器来监听操作完成的事件;
*
* @return
*/
public Object getResult() {
return value;
}

/**
* 添加操作完成监听器;
*
* @param listener
*/
public void addCompletedListener(OperationCompletedListener listener) {
listenerMulticaster.addListener(listener);
}

protected abstract Object decodeResult(BytesValue bytesValue);

@Override
public Object complete(BytesValue bytesValue) {
if (this.completed) {
throw new IllegalStateException(
"Contract invocation has been completed, and is not allowed to be completed again!");
}
this.completed = true;
this.value = decodeResult(bytesValue);
OperationCompletedContext context = new OperationCompletedContext(getOperationIndex(), null);
listenerMulticaster.getBroadcaster().onCompleted(value, null, context);
return null;
}

@Override
public void complete(Throwable error) {
if (completed) {
return;
}
this.completed = true;
this.error = error;
OperationCompletedContext context = new OperationCompletedContext(getOperationIndex(), null);
listenerMulticaster.getBroadcaster().onCompleted(null, error, context);
}
}

+ 0
- 11
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationReturnValueHandler.java View File

@@ -1,11 +0,0 @@
package com.jd.blockchain.transaction;

import com.jd.blockchain.ledger.BytesValue;

interface OperationReturnValueHandler {

int getOperationIndex();

Object setReturnValue(BytesValue bytesValue);

}

+ 60
- 26
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java View File

@@ -1,9 +1,12 @@
package com.jd.blockchain.transaction; package com.jd.blockchain.transaction;


import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;


import org.springframework.cglib.proxy.UndeclaredThrowableException;

import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.Crypto; import com.jd.blockchain.crypto.Crypto;
@@ -25,7 +28,9 @@ public class PreparedTx implements PreparedTransaction {


private TransactionService txProcessor; private TransactionService txProcessor;


private OperationReturnValueHandler[] opReturnValueHandlers;
private OperationResultHandle[] opReturnValueHandlers;

private TxStateManager stateManager;


/** /**
* 创建一个“就绪交易”对象; * 创建一个“就绪交易”对象;
@@ -34,17 +39,18 @@ public class PreparedTx implements PreparedTransaction {
* @param txProcessor 交易处理服务; * @param txProcessor 交易处理服务;
* @param opReturnValueHandlerList 操作返回值处理器列表; * @param opReturnValueHandlerList 操作返回值处理器列表;
*/ */
public PreparedTx(TransactionRequestBuilder txReqBuilder, TransactionService txProcessor,
Collection<OperationReturnValueHandler> opReturnValueHandlerList) {
public PreparedTx(TxStateManager stateManager, TransactionRequestBuilder txReqBuilder,
TransactionService txProcessor, Collection<OperationResultHandle> opReturnValueHandlerList) {
this.stateManager = stateManager;
this.txReqBuilder = txReqBuilder; this.txReqBuilder = txReqBuilder;
this.txProcessor = txProcessor; this.txProcessor = txProcessor;


this.opReturnValueHandlers = opReturnValueHandlerList this.opReturnValueHandlers = opReturnValueHandlerList
.toArray(new OperationReturnValueHandler[opReturnValueHandlerList.size()]);
.toArray(new OperationResultHandle[opReturnValueHandlerList.size()]);
// 按照操作索引升序排列; // 按照操作索引升序排列;
Arrays.sort(opReturnValueHandlers, new Comparator<OperationReturnValueHandler>() {
Arrays.sort(opReturnValueHandlers, new Comparator<OperationResultHandle>() {
@Override @Override
public int compare(OperationReturnValueHandler o1, OperationReturnValueHandler o2) {
public int compare(OperationResultHandle o1, OperationResultHandle o2) {
return o1.getOperationIndex() - o2.getOperationIndex(); return o1.getOperationIndex() - o2.getOperationIndex();
} }
}); });
@@ -78,31 +84,59 @@ public class PreparedTx implements PreparedTransaction {


@Override @Override
public TransactionResponse commit() { public TransactionResponse commit() {
stateManager.commit();
TransactionResponse txResponse = null;
try { try {
TransactionRequest txReq = txReqBuilder.buildRequest(); TransactionRequest txReq = txReqBuilder.buildRequest();
// 发起交易请求; // 发起交易请求;
TransactionResponse txResponse = txProcessor.process(txReq);

// 解析返回值;正常的情况下,返回结果列表与结果处理器列表中元素对应的操作索引是一致的;
OperationResult[] opResults = txResponse.getOperationResults();
if (opResults != null && opResults.length > 0) {
if (opResults.length != opReturnValueHandlers.length) {
throw new IllegalStateException(String.format(
"The operation result list of tx doesn't match it's return value handler list! --[TX.Content.Hash=%s][NumOfResults=%s][NumOfHandlers=%s]",
txReq.getTransactionContent().getHash(), opResults.length, opReturnValueHandlers.length));
}
for (int i = 0; i < opResults.length; i++) {
if (opResults[i].getIndex() != opReturnValueHandlers[i].getOperationIndex()) {
throw new IllegalStateException(
"The operation indexes of the items in the result list and in the handler list don't match!");
}
opReturnValueHandlers[i].setReturnValue(opResults[i].getResult());
txResponse = txProcessor.process(txReq);

stateManager.complete();

} catch (Exception ex) {
stateManager.close();
handleError(ex);
throw new UndeclaredThrowableException(ex);
}

if (txResponse != null) {
handleResults(txResponse);
}

return txResponse;
}

@Override
public void close() throws IOException {
if (!stateManager.close()) {
TransactionCancelledExeption error = new TransactionCancelledExeption(
"Prepared transaction has been cancelled!");
handleError(error);
}
}

private void handleError(Throwable error) {
for (OperationResultHandle handle : opReturnValueHandlers) {
handle.complete(error);
}
}

private void handleResults(TransactionResponse txResponse) {
// 解析返回值;正常的情况下,返回结果列表与结果处理器列表中元素对应的操作索引是一致的;
OperationResult[] opResults = txResponse.getOperationResults();
if (opResults != null && opResults.length > 0) {
if (opResults.length != opReturnValueHandlers.length) {
throw new IllegalStateException(String.format(
"The operation result list of tx doesn't match it's return value handler list! --[TX.Content.Hash=%s][NumOfResults=%s][NumOfHandlers=%s]",
txResponse.getContentHash(), opResults.length, opReturnValueHandlers.length));
}
for (int i = 0; i < opResults.length; i++) {
if (opResults[i].getIndex() != opReturnValueHandlers[i].getOperationIndex()) {
throw new IllegalStateException(
"The operation indexes of the items in the result list and in the handler list don't match!");
} }
opReturnValueHandlers[i].complete(opResults[i].getResult());
} }
return txResponse;
} catch (Exception e) {
//TODO: 出错时清理交易上下文,释放与交易关联对异步等待资源,避免当前线程死锁;
} }
} }




+ 9
- 30
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ShortValueHolder.java View File

@@ -1,43 +1,22 @@
package com.jd.blockchain.transaction; package com.jd.blockchain.transaction;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class ShortValueHolder extends ValueHolderWrapper {


public class ShortValueHolder extends ValueHolderBase {

ShortValueHolder(ContractInvocation invocation) {
super(invocation);
ShortValueHolder(OperationResultHolder resultHolder) {
super(resultHolder);
} }


/** /**
* 等待结果合约调用的结果返回;
* 获取值;<br>
* *
* @return
*/
public short get() {
return (short) super.getValue();
}

/**
* 等待结果合约调用的结果返回;
* 此方法不堵塞,调用立即返回;<br>
* *
* @param timeout
* @return
* @throws TimeoutException
*/
public short get(long timeout) throws TimeoutException {
return get(timeout, TimeUnit.MILLISECONDS);
}

/**
* 等待结果合约调用的结果返回;
* 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 0;
* *
* @param timeout
* @param unit
* @return * @return
* @throws TimeoutException
*/ */
public short get(long timeout, TimeUnit unit) throws TimeoutException {
return (short) super.getValue(timeout, unit);
public short get() {
return super.isCompleted() ? (short) super.getValue() : 0;
} }

} }

+ 15
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TransactionCancelledExeption.java View File

@@ -0,0 +1,15 @@
package com.jd.blockchain.transaction;

public class TransactionCancelledExeption extends RuntimeException {

private static final long serialVersionUID = -2577951411093171806L;

public TransactionCancelledExeption(String message) {
super(message);
}

public TransactionCancelledExeption(String message, Throwable cause) {
super(message, cause);
}

}

+ 1
- 1
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java View File

@@ -51,7 +51,7 @@ public class TxBuilder implements TransactionBuilder {
return txContent; return txContent;
} }


public Collection<OperationReturnValueHandler> getReturnValuehandlers() {
public Collection<OperationResultHandle> getReturnValuehandlers() {
return opFactory.getReturnValuetHandlers(); return opFactory.getReturnValuetHandlers();
} }




+ 76
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxStateManager.java View File

@@ -0,0 +1,76 @@
package com.jd.blockchain.transaction;

class TxStateManager {

private State state = State.OPERABLE;

public void operate() {
if (state != State.OPERABLE) {
throw new IllegalStateException(String.format("Cannot define operations in %s state!", state));
}
}

public void prepare() {
if (state != State.OPERABLE) {
throw new IllegalStateException(
String.format("Cannot switch to %s state in %s state!", State.PREPARED, state));
}
state = State.PREPARED;
}

public void commit() {
if (state != State.PREPARED) {
throw new IllegalStateException(
String.format("Cannot switch to %s state in %s state!", State.COMMITTED, state));
}
state = State.COMMITTED;
}

public void complete() {
if (state != State.COMMITTED) {
throw new IllegalStateException(String.format("Cannot complete normally in %s state!", state));
}
state = State.CLOSED;
}

/**
* 关闭交易;
*
* @param error
* @return 此次操作前是否已经处于关闭状态; <br>
* 如果返回 true ,则表示之前已经处于关闭状态,此次操作将被忽略;<br>
* 如果返回 fasle,则表示之前处于非关闭状态,此次操作将切换为关闭状态;
*/
public boolean close() {
if (state == State.CLOSED) {
return true;
}
state = State.CLOSED;
return false;
}

private static enum State {

/**
* 可操作;
*/
OPERABLE,

/**
* 就绪;
*/
PREPARED,

/**
* 已提交;
*/
COMMITTED,

/**
* 已关闭;
*/
CLOSED

}

}

+ 27
- 2
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java View File

@@ -1,5 +1,8 @@
package com.jd.blockchain.transaction; package com.jd.blockchain.transaction;
import java.io.IOException;
import java.util.Collection;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.PreparedTransaction; import com.jd.blockchain.ledger.PreparedTransaction;
import com.jd.blockchain.ledger.TransactionRequestBuilder; import com.jd.blockchain.ledger.TransactionRequestBuilder;
@@ -12,8 +15,10 @@ public class TxTemplate implements TransactionTemplate {
private TransactionService txService; private TransactionService txService;
private TxStateManager stateManager;
public TxTemplate(HashDigest ledgerHash, TransactionService txService) { public TxTemplate(HashDigest ledgerHash, TransactionService txService) {
this.stateManager = new TxStateManager();
this.txBuilder = new TxBuilder(ledgerHash); this.txBuilder = new TxBuilder(ledgerHash);
this.txService = txService; this.txService = txService;
} }
@@ -25,43 +30,63 @@ public class TxTemplate implements TransactionTemplate {
@Override @Override
public PreparedTransaction prepare() { public PreparedTransaction prepare() {
stateManager.prepare();
TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest(); TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
return new PreparedTx(txReqBuilder, txService, txBuilder.getReturnValuehandlers());
return new PreparedTx(stateManager, txReqBuilder, txService, txBuilder.getReturnValuehandlers());
} }
@Override @Override
public UserRegisterOperationBuilder users() { public UserRegisterOperationBuilder users() {
stateManager.operate();
return txBuilder.users(); return txBuilder.users();
} }
@Override @Override
public DataAccountRegisterOperationBuilder dataAccounts() { public DataAccountRegisterOperationBuilder dataAccounts() {
stateManager.operate();
return txBuilder.dataAccounts(); return txBuilder.dataAccounts();
} }
@Override @Override
public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) { public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) {
stateManager.operate();
return txBuilder.dataAccount(accountAddress); return txBuilder.dataAccount(accountAddress);
} }
@Override @Override
public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) { public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) {
stateManager.operate();
return txBuilder.dataAccount(accountAddress); return txBuilder.dataAccount(accountAddress);
} }
@Override @Override
public ContractCodeDeployOperationBuilder contracts() { public ContractCodeDeployOperationBuilder contracts() {
stateManager.operate();
return txBuilder.contracts(); return txBuilder.contracts();
} }
@Override @Override
public <T> T contract(Bytes address, Class<T> contractIntf) { public <T> T contract(Bytes address, Class<T> contractIntf) {
stateManager.operate();
return txBuilder.contract(address, contractIntf); return txBuilder.contract(address, contractIntf);
} }
@Override @Override
public <T> T contract(String address, Class<T> contractIntf) { public <T> T contract(String address, Class<T> contractIntf) {
stateManager.operate();
return txBuilder.contract(address, contractIntf); return txBuilder.contract(address, contractIntf);
} }
@Override
public void close() throws IOException {
if (!stateManager.close()) {
Collection<OperationResultHandle> handlers = txBuilder.getReturnValuehandlers();
if (handlers.size() > 0) {
TransactionCancelledExeption error = new TransactionCancelledExeption("Transaction template has been cancelled!");
for (OperationResultHandle handle : handlers) {
handle.complete(error);
}
}
}
}
} }

+ 0
- 45
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolder.java View File

@@ -1,45 +0,0 @@
package com.jd.blockchain.transaction;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class ValueHolder<T> extends ValueHolderBase {

ValueHolder(ContractInvocation invocation) {
super(invocation);
}

/**
* 等待结果合约调用的结果返回;
*
* @return
*/
@SuppressWarnings("unchecked")
public T get() {
return (T) super.getValue();
}

/**
* 等待结果合约调用的结果返回;
*
* @param timeout
* @return
* @throws TimeoutException
*/
public T get(long timeout) throws TimeoutException {
return get(timeout, TimeUnit.MILLISECONDS);
}

/**
* 等待结果合约调用的结果返回;
*
* @param timeout
* @param unit
* @return
* @throws TimeoutException
*/
@SuppressWarnings("unchecked")
public T get(long timeout, TimeUnit unit) throws TimeoutException {
return (T) super.getValue(timeout, unit);
}
}

+ 0
- 42
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolderBase.java View File

@@ -1,42 +0,0 @@
package com.jd.blockchain.transaction;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

class ValueHolderBase {
private ContractInvocation invocation;

protected ValueHolderBase(ContractInvocation invocation) {
this.invocation = invocation;
}

/**
* 等待结果合约调用的结果返回;
*
* @return
*/
protected Object getValue() {
try {
return invocation.getReturnValue().get();
} catch (InterruptedException | ExecutionException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}

/**
* 等待结果合约调用的结果返回;
*
* @param timeout
* @param unit
* @return
* @throws TimeoutException
*/
protected Object getValue(long timeout, TimeUnit unit) throws TimeoutException {
try {
return invocation.getReturnValue().get(timeout, unit);
} catch (InterruptedException | ExecutionException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
}

+ 34
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolderWrapper.java View File

@@ -0,0 +1,34 @@
package com.jd.blockchain.transaction;

class ValueHolderWrapper {
private OperationResultHolder valueHolder;

protected ValueHolderWrapper(OperationResultHolder valueHolder) {
this.valueHolder = valueHolder;
}

public boolean isCompleted() {
return valueHolder.isCompleted();
}

public Throwable getError() {
return valueHolder.getError();
}

/**
* 获取值;<br>
*
* 此方法不堵塞,调用立即返回;<br>
*
* 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 null;
*
* @return
*/
protected Object getValue() {
return valueHolder.getResult();
}

public void addCompletedListener(OperationCompletedListener listener) {
valueHolder.addCompletedListener(listener);
}
}

+ 38
- 35
source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractEventSendOpTemplateTest.java View File

@@ -8,21 +8,22 @@
*/ */
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.BytesData;
import com.jd.blockchain.ledger.BytesDataList;
import com.jd.blockchain.ledger.BytesValueList;
import com.jd.blockchain.ledger.ContractEventSendOperation; import com.jd.blockchain.ledger.ContractEventSendOperation;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.transaction.ContractEventSendOpTemplate; import com.jd.blockchain.transaction.ContractEventSendOpTemplate;
import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate;
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
@@ -32,34 +33,36 @@ import static org.junit.Assert.assertEquals;


public class ContractEventSendOpTemplateTest { public class ContractEventSendOpTemplateTest {


private ContractEventSendOpTemplate data;
private ContractEventSendOpTemplate data;


@Before
public void initContractEventSendOpTemplate() {
DataContractRegistry.register(ContractEventSendOperation.class);
DataContractRegistry.register(Operation.class);
String contractAddress = "zhangsan-address", event = "zhangsan-event";
byte[] args = "zhangsan-args".getBytes();
data = new ContractEventSendOpTemplate(Bytes.fromString(contractAddress), event, args);
}
@Before
public void initContractEventSendOpTemplate() {
DataContractRegistry.register(ContractEventSendOperation.class);
DataContractRegistry.register(Operation.class);
String contractAddress = "zhangsan-address", event = "zhangsan-event";
BytesValueList args = new BytesDataList(BytesData.fromText("zhangsan-args"));
data = new ContractEventSendOpTemplate(Bytes.fromString(contractAddress), event, args);
}


@Test
public void testSerialize_ContractEventSendOperation() throws Exception {
byte[] serialBytes = BinaryProtocol.encode(data, ContractEventSendOperation.class);
ContractEventSendOperation resolvedData = BinaryProtocol.decode(serialBytes);
System.out.println("------Assert start ------");
assertEquals(resolvedData.getContractAddress(), data.getContractAddress());
assertEquals(resolvedData.getEvent(), data.getEvent());
assertArrayEquals(resolvedData.getArgs(), data.getArgs());
System.out.println("------Assert OK ------");
}
@Test
public void testSerialize_ContractEventSendOperation() throws Exception {
byte[] serialBytes = BinaryProtocol.encode(data, ContractEventSendOperation.class);
ContractEventSendOperation resolvedData = BinaryProtocol.decode(serialBytes);
System.out.println("------Assert start ------");
assertEquals(resolvedData.getContractAddress(), data.getContractAddress());
assertEquals(resolvedData.getEvent(), data.getEvent());
byte[] expectedBytes = BinaryProtocol.encode(resolvedData.getArgs(), BytesValueList.class);
byte[] actualBytes = BinaryProtocol.encode(data.getArgs(), BytesValueList.class);
assertArrayEquals(expectedBytes, actualBytes);
System.out.println("------Assert OK ------");
}


@Test
public void testSerialize_Operation() throws Exception {
byte[] serialBytes = BinaryProtocol.encode(data, Operation.class);
Operation resolvedData = BinaryProtocol.decode(serialBytes);
System.out.println("------Assert start ------");
System.out.println(resolvedData);
System.out.println("------Assert OK ------");
}
@Test
public void testSerialize_Operation() throws Exception {
byte[] serialBytes = BinaryProtocol.encode(data, Operation.class);
Operation resolvedData = BinaryProtocol.decode(serialBytes);
System.out.println("------Assert start ------");
System.out.println(resolvedData);
System.out.println("------Assert OK ------");
}
} }

+ 4
- 4
source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DataAccountKVSetOpTemplateTest.java View File

@@ -16,7 +16,7 @@ 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.BytesData;
import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate;
@@ -42,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", BytesValueEntry.fromText("zhangsan"), 9999L);
new KVData("test1", BytesData.fromText("zhangsan"), 9999L);
KVData kvData2 = KVData kvData2 =
new KVData("test2", BytesValueEntry.fromText("lisi"), 9990L);
new KVData("test2", BytesData.fromText("lisi"), 9990L);
KVData kvData3 = KVData kvData3 =
new KVData("test3", BytesValueEntry.fromText("wangwu"), 1990L);
new KVData("test3", BytesData.fromText("wangwu"), 1990L);
data.set(kvData1); data.set(kvData1);
data.set(kvData2); data.set(kvData2);
data.set(kvData3); data.set(kvData3);


+ 2
- 2
source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/KVDataTest.java View File

@@ -16,7 +16,7 @@ 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.BytesData;
import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate;
import com.jd.blockchain.transaction.KVData; import com.jd.blockchain.transaction.KVData;
@@ -38,7 +38,7 @@ public class KVDataTest {
byte[] value = "test-value".getBytes(); byte[] value = "test-value".getBytes();
long expectedVersion = 9999L; long expectedVersion = 9999L;


kvData = new KVData(key, BytesValueEntry.fromBytes(value), expectedVersion);
kvData = new KVData(key, BytesData.fromBytes(value), expectedVersion);
} }


@Test @Test


+ 344
- 342
source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java View File

@@ -31,346 +31,348 @@ import java.lang.reflect.Field;


public class ClientResolveUtil { public class ClientResolveUtil {


public static KVDataEntry[] read(KVDataEntry[] kvDataEntries) {
if (kvDataEntries == null || kvDataEntries.length == 0) {
return kvDataEntries;
}
KVDataEntry[] resolveKvDataEntries = new KVDataEntry[kvDataEntries.length];
// kvDataEntries是代理对象,需要处理
for (int i = 0; i < kvDataEntries.length; i++) {
KVDataEntry kvDataEntry = kvDataEntries[i];
String key = kvDataEntry.getKey();
long version = kvDataEntry.getVersion();
DataType dataType = kvDataEntry.getType();
KvData innerKvData = new KvData(key, version, dataType);
Object valueObj = kvDataEntry.getValue();
switch (dataType) {
case NIL:
break;
case BYTES:
case TEXT:
case JSON:
innerKvData.setValue(valueObj.toString());
break;
case INT32:
innerKvData.setValue(Integer.parseInt(valueObj.toString()));
break;
case INT64:
innerKvData.setValue(Long.parseLong(valueObj.toString()));
break;
default:
throw new IllegalStateException("Unsupported value type[" + dataType + "] to resolve!");
}
resolveKvDataEntries[i] = innerKvData;
}
return resolveKvDataEntries;
}

public static Operation read(Operation operation) {

try {
// Class
Class<?> clazz = operation.getClass();
Field field = clazz.getSuperclass().getDeclaredField("h");
field.setAccessible(true);
Object object = field.get(operation);
if (object instanceof JSONObject) {
JSONObject jsonObject = (JSONObject) object;
if (jsonObject.containsKey("accountID")) {
return convertDataAccountRegisterOperation(jsonObject);
} else if (jsonObject.containsKey("userID")) {
return convertUserRegisterOperation(jsonObject);
} else if (jsonObject.containsKey("contractID")) {
return convertContractCodeDeployOperation(jsonObject);
} else if (jsonObject.containsKey("writeSet")) {
return convertDataAccountKVSetOperation(jsonObject);
} else if (jsonObject.containsKey("initSetting")) {
return convertLedgerInitOperation(jsonObject);
} else if (jsonObject.containsKey("contractAddress")) {
return convertContractEventSendOperation(jsonObject);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}

return null;
}

public static Object readValueByBytesValue(BytesValue bytesValue) {
DataType dataType = bytesValue.getType();
Bytes saveVal = bytesValue.getValue();
Object showVal;
switch (dataType) {
case BYTES:
// return hex
showVal = HexUtils.encode(saveVal.toBytes());
break;
case TEXT:
case JSON:
showVal = saveVal.toUTF8String();
break;
case INT64:
showVal = BytesUtils.toLong(saveVal.toBytes());
break;
default:
showVal = HexUtils.encode(saveVal.toBytes());
break;
}
return showVal;
}

public static DataAccountRegisterOperation convertDataAccountRegisterOperation(JSONObject jsonObject) {
JSONObject account = jsonObject.getJSONObject("accountID");
return new DataAccountRegisterOpTemplate(blockchainIdentity(account));
}

public static DataAccountKVSetOperation convertDataAccountKVSetOperation(JSONObject jsonObject) {
// 写入集合处理
JSONArray writeSetObj = jsonObject.getJSONArray("writeSet");
JSONObject accountAddrObj = jsonObject.getJSONObject("accountAddress");
String addressBase58 = accountAddrObj.getString("value");
Bytes address = Bytes.fromBase58(addressBase58);

DataAccountKVSetOpTemplate kvOperation = new DataAccountKVSetOpTemplate(address);
for (int i = 0; i <writeSetObj.size(); i++) {
JSONObject currWriteSetObj = writeSetObj.getJSONObject(i);
long expectedVersion = currWriteSetObj.getLong("expectedVersion");
JSONObject valueObj = currWriteSetObj.getJSONObject("value");
String typeStr = valueObj.getString("type");
String realValBase58 = valueObj.getString("value");
String key = currWriteSetObj.getString("key");
DataType dataType = DataType.valueOf(typeStr);
BytesValue bytesValue =BytesValueEntry.fromType(dataType, Base58Utils.decode(realValBase58));
KVData kvData = new KVData(key, bytesValue, expectedVersion);
kvOperation.set(kvData);
}

return kvOperation;
}

public static LedgerInitOperation convertLedgerInitOperation(JSONObject jsonObject) {
JSONObject legerInitObj = jsonObject.getJSONObject("initSetting");
LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData();
String ledgerSeedStr = legerInitObj.getString("ledgerSeed");

// 种子需要做Base64转换
ledgerInitSettingData.setLedgerSeed(Base64.decodeBase64(BytesUtils.toBytes(ledgerSeedStr)));

String consensusProvider = legerInitObj.getString("consensusProvider");

ledgerInitSettingData.setConsensusProvider(consensusProvider);

JSONObject cryptoSettingObj = legerInitObj.getJSONObject("cryptoSetting");
boolean autoVerifyHash = cryptoSettingObj.getBoolean("autoVerifyHash");
short hashAlgorithm = cryptoSettingObj.getShort("hashAlgorithm");

CryptoConfig cryptoConfig = new CryptoConfig();

cryptoConfig.setAutoVerifyHash(autoVerifyHash);

cryptoConfig.setHashAlgorithm(hashAlgorithm);

ledgerInitSettingData.setCryptoSetting(cryptoConfig);


JSONObject consensusSettingsObj = legerInitObj.getJSONObject("consensusSettings");
Bytes consensusSettings = Bytes.fromBase58(consensusSettingsObj.getString("value"));

ledgerInitSettingData.setConsensusSettings(consensusSettings);

JSONArray consensusParticipantsArray = legerInitObj.getJSONArray("consensusParticipants");

if (!consensusParticipantsArray.isEmpty()) {
ParticipantNode[] participantNodes = new ParticipantNode[consensusParticipantsArray.size()];
for (int i = 0; i < consensusParticipantsArray.size(); i++) {
JSONObject currConsensusParticipant = consensusParticipantsArray.getJSONObject(i);
String addressBase58 = currConsensusParticipant.getString("address");
String name = currConsensusParticipant.getString("name");
int id = currConsensusParticipant.getInteger("id");
JSONObject pubKeyObj = currConsensusParticipant.getJSONObject("pubKey");
String pubKeyBase58 = pubKeyObj.getString("value");
// 生成ParticipantNode对象
ParticipantCertData participantCertData = new ParticipantCertData(id, addressBase58, name, new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes()));
participantNodes[i] = participantCertData;
}
ledgerInitSettingData.setConsensusParticipants(participantNodes);
}

return new LedgerInitOpTemplate(ledgerInitSettingData);
}

public static UserRegisterOperation convertUserRegisterOperation(JSONObject jsonObject) {
JSONObject user = jsonObject.getJSONObject("userID");
return new UserRegisterOpTemplate(blockchainIdentity(user));
}

public static ContractCodeDeployOperation convertContractCodeDeployOperation(JSONObject jsonObject) {
JSONObject contract = jsonObject.getJSONObject("contractID");
BlockchainIdentityData blockchainIdentity = blockchainIdentity(contract);

String chainCodeStr = jsonObject.getString("chainCode");
ContractCodeDeployOpTemplate contractCodeDeployOpTemplate = new ContractCodeDeployOpTemplate(blockchainIdentity, BytesUtils.toBytes(chainCodeStr));
return contractCodeDeployOpTemplate;
}

public static ContractEventSendOperation convertContractEventSendOperation(JSONObject jsonObject) {
JSONObject contractAddressObj = jsonObject.getJSONObject("contractAddress");
String contractAddress = contractAddressObj.getString("value");
String argsStr = jsonObject.getString("args");
String event = jsonObject.getString("event");
return new ContractEventSendOpTemplate(Bytes.fromBase58(contractAddress), event, BytesUtils.toBytes(argsStr));
}

private static BlockchainIdentityData blockchainIdentity(JSONObject jsonObject) {
JSONObject addressObj = jsonObject.getJSONObject("address");
// base58值
String addressBase58 = addressObj.getString("value");
Bytes address = Bytes.fromBase58(addressBase58);

JSONObject pubKeyObj = jsonObject.getJSONObject("pubKey");
// base58值
String pubKeyBase58 = pubKeyObj.getString("value");
PubKey pubKey = new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes());

// 生成对应的对象
return new BlockchainIdentityData(address, pubKey);
}

public static class CryptoConfig implements CryptoSetting {

private short hashAlgorithm;

private boolean autoVerifyHash;

@Override
public CryptoProvider[] getSupportedProviders() {
return new CryptoProvider[0];
}

@Override
public short getHashAlgorithm() {
return hashAlgorithm;
}

@Override
public boolean getAutoVerifyHash() {
return autoVerifyHash;
}

public void setHashAlgorithm(short hashAlgorithm) {
this.hashAlgorithm = hashAlgorithm;
}

public void setAutoVerifyHash(boolean autoVerifyHash) {
this.autoVerifyHash = autoVerifyHash;
}
}

public static class ParticipantCertData implements ParticipantNode{
private int id;
private String address;
private String name;
private PubKey pubKey;

public ParticipantCertData() {
}

public ParticipantCertData(ParticipantNode participantNode) {
this.address = participantNode.getAddress();
this.name = participantNode.getName();
this.pubKey = participantNode.getPubKey();
}

public ParticipantCertData(int id, String address, String name, PubKey pubKey) {
this.id = id;
this.address = address;
this.name = name;
this.pubKey = pubKey;
}

@Override
public String getAddress() {
return address;
}

@Override
public String getName() {
return name;
}

@Override
public PubKey getPubKey() {
return pubKey;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}
}

public static class KvData implements KVDataEntry {

private String key;

private long version;

private DataType dataType;

private Object value;

public KvData() {
}

public KvData(String key, long version, DataType dataType) {
this(key, version, dataType, null);
}

public KvData(String key, long version, DataType dataType, Object value) {
this.key = key;
this.version = version;
this.dataType = dataType;
this.value = value;
}

public void setKey(String key) {
this.key = key;
}

public void setVersion(long version) {
this.version = version;
}

public void setDataType(DataType dataType) {
this.dataType = dataType;
}

public void setValue(Object value) {
this.value = value;
}

@Override
public String getKey() {
return key;
}

@Override
public long getVersion() {
return version;
}

@Override
public DataType getType() {
return dataType;
}

@Override
public Object getValue() {
return value;
}
}
public static KVDataEntry[] read(KVDataEntry[] kvDataEntries) {
if (kvDataEntries == null || kvDataEntries.length == 0) {
return kvDataEntries;
}
KVDataEntry[] resolveKvDataEntries = new KVDataEntry[kvDataEntries.length];
// kvDataEntries是代理对象,需要处理
for (int i = 0; i < kvDataEntries.length; i++) {
KVDataEntry kvDataEntry = kvDataEntries[i];
String key = kvDataEntry.getKey();
long version = kvDataEntry.getVersion();
DataType dataType = kvDataEntry.getType();
KvData innerKvData = new KvData(key, version, dataType);
Object valueObj = kvDataEntry.getValue();
switch (dataType) {
case NIL:
break;
case BYTES:
case TEXT:
case JSON:
innerKvData.setValue(valueObj.toString());
break;
case INT32:
innerKvData.setValue(Integer.parseInt(valueObj.toString()));
break;
case INT64:
innerKvData.setValue(Long.parseLong(valueObj.toString()));
break;
default:
throw new IllegalStateException("Unsupported value type[" + dataType + "] to resolve!");
}
resolveKvDataEntries[i] = innerKvData;
}
return resolveKvDataEntries;
}

public static Operation read(Operation operation) {

try {
// Class
Class<?> clazz = operation.getClass();
Field field = clazz.getSuperclass().getDeclaredField("h");
field.setAccessible(true);
Object object = field.get(operation);
if (object instanceof JSONObject) {
JSONObject jsonObject = (JSONObject) object;
if (jsonObject.containsKey("accountID")) {
return convertDataAccountRegisterOperation(jsonObject);
} else if (jsonObject.containsKey("userID")) {
return convertUserRegisterOperation(jsonObject);
} else if (jsonObject.containsKey("contractID")) {
return convertContractCodeDeployOperation(jsonObject);
} else if (jsonObject.containsKey("writeSet")) {
return convertDataAccountKVSetOperation(jsonObject);
} else if (jsonObject.containsKey("initSetting")) {
return convertLedgerInitOperation(jsonObject);
} else if (jsonObject.containsKey("contractAddress")) {
return convertContractEventSendOperation(jsonObject);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}

return null;
}

public static Object readValueByBytesValue(BytesValue bytesValue) {
DataType dataType = bytesValue.getType();
Bytes saveVal = bytesValue.getValue();
Object showVal;
switch (dataType) {
case BYTES:
// return hex
showVal = HexUtils.encode(saveVal.toBytes());
break;
case TEXT:
case JSON:
showVal = saveVal.toUTF8String();
break;
case INT64:
showVal = BytesUtils.toLong(saveVal.toBytes());
break;
default:
showVal = HexUtils.encode(saveVal.toBytes());
break;
}
return showVal;
}

public static DataAccountRegisterOperation convertDataAccountRegisterOperation(JSONObject jsonObject) {
JSONObject account = jsonObject.getJSONObject("accountID");
return new DataAccountRegisterOpTemplate(blockchainIdentity(account));
}

public static DataAccountKVSetOperation convertDataAccountKVSetOperation(JSONObject jsonObject) {
// 写入集合处理
JSONArray writeSetObj = jsonObject.getJSONArray("writeSet");
JSONObject accountAddrObj = jsonObject.getJSONObject("accountAddress");
String addressBase58 = accountAddrObj.getString("value");
Bytes address = Bytes.fromBase58(addressBase58);

DataAccountKVSetOpTemplate kvOperation = new DataAccountKVSetOpTemplate(address);
for (int i = 0; i < writeSetObj.size(); i++) {
JSONObject currWriteSetObj = writeSetObj.getJSONObject(i);
long expectedVersion = currWriteSetObj.getLong("expectedVersion");
JSONObject valueObj = currWriteSetObj.getJSONObject("value");
String typeStr = valueObj.getString("type");
String realValBase58 = valueObj.getString("value");
String key = currWriteSetObj.getString("key");
DataType dataType = DataType.valueOf(typeStr);
BytesValue bytesValue = BytesData.fromType(dataType, Base58Utils.decode(realValBase58));
KVData kvData = new KVData(key, bytesValue, expectedVersion);
kvOperation.set(kvData);
}

return kvOperation;
}

public static LedgerInitOperation convertLedgerInitOperation(JSONObject jsonObject) {
JSONObject legerInitObj = jsonObject.getJSONObject("initSetting");
LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData();
String ledgerSeedStr = legerInitObj.getString("ledgerSeed");

// 种子需要做Base64转换
ledgerInitSettingData.setLedgerSeed(Base64.decodeBase64(BytesUtils.toBytes(ledgerSeedStr)));

String consensusProvider = legerInitObj.getString("consensusProvider");

ledgerInitSettingData.setConsensusProvider(consensusProvider);

JSONObject cryptoSettingObj = legerInitObj.getJSONObject("cryptoSetting");
boolean autoVerifyHash = cryptoSettingObj.getBoolean("autoVerifyHash");
short hashAlgorithm = cryptoSettingObj.getShort("hashAlgorithm");

CryptoConfig cryptoConfig = new CryptoConfig();

cryptoConfig.setAutoVerifyHash(autoVerifyHash);

cryptoConfig.setHashAlgorithm(hashAlgorithm);

ledgerInitSettingData.setCryptoSetting(cryptoConfig);

JSONObject consensusSettingsObj = legerInitObj.getJSONObject("consensusSettings");
Bytes consensusSettings = Bytes.fromBase58(consensusSettingsObj.getString("value"));

ledgerInitSettingData.setConsensusSettings(consensusSettings);

JSONArray consensusParticipantsArray = legerInitObj.getJSONArray("consensusParticipants");

if (!consensusParticipantsArray.isEmpty()) {
ParticipantNode[] participantNodes = new ParticipantNode[consensusParticipantsArray.size()];
for (int i = 0; i < consensusParticipantsArray.size(); i++) {
JSONObject currConsensusParticipant = consensusParticipantsArray.getJSONObject(i);
String addressBase58 = currConsensusParticipant.getString("address");
String name = currConsensusParticipant.getString("name");
int id = currConsensusParticipant.getInteger("id");
JSONObject pubKeyObj = currConsensusParticipant.getJSONObject("pubKey");
String pubKeyBase58 = pubKeyObj.getString("value");
// 生成ParticipantNode对象
ParticipantCertData participantCertData = new ParticipantCertData(id, addressBase58, name,
new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes()));
participantNodes[i] = participantCertData;
}
ledgerInitSettingData.setConsensusParticipants(participantNodes);
}

return new LedgerInitOpTemplate(ledgerInitSettingData);
}

public static UserRegisterOperation convertUserRegisterOperation(JSONObject jsonObject) {
JSONObject user = jsonObject.getJSONObject("userID");
return new UserRegisterOpTemplate(blockchainIdentity(user));
}

public static ContractCodeDeployOperation convertContractCodeDeployOperation(JSONObject jsonObject) {
JSONObject contract = jsonObject.getJSONObject("contractID");
BlockchainIdentityData blockchainIdentity = blockchainIdentity(contract);

String chainCodeStr = jsonObject.getString("chainCode");
ContractCodeDeployOpTemplate contractCodeDeployOpTemplate = new ContractCodeDeployOpTemplate(blockchainIdentity,
BytesUtils.toBytes(chainCodeStr));
return contractCodeDeployOpTemplate;
}

public static ContractEventSendOperation convertContractEventSendOperation(JSONObject jsonObject) {
JSONObject contractAddressObj = jsonObject.getJSONObject("contractAddress");
String contractAddress = contractAddressObj.getString("value");
String argsStr = jsonObject.getString("args");
String event = jsonObject.getString("event");
return new ContractEventSendOpTemplate(Bytes.fromBase58(contractAddress), event,
BytesDataList.singleText(argsStr));
}

private static BlockchainIdentityData blockchainIdentity(JSONObject jsonObject) {
JSONObject addressObj = jsonObject.getJSONObject("address");
// base58值
String addressBase58 = addressObj.getString("value");
Bytes address = Bytes.fromBase58(addressBase58);

JSONObject pubKeyObj = jsonObject.getJSONObject("pubKey");
// base58值
String pubKeyBase58 = pubKeyObj.getString("value");
PubKey pubKey = new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes());

// 生成对应的对象
return new BlockchainIdentityData(address, pubKey);
}

public static class CryptoConfig implements CryptoSetting {

private short hashAlgorithm;

private boolean autoVerifyHash;

@Override
public CryptoProvider[] getSupportedProviders() {
return new CryptoProvider[0];
}

@Override
public short getHashAlgorithm() {
return hashAlgorithm;
}

@Override
public boolean getAutoVerifyHash() {
return autoVerifyHash;
}

public void setHashAlgorithm(short hashAlgorithm) {
this.hashAlgorithm = hashAlgorithm;
}

public void setAutoVerifyHash(boolean autoVerifyHash) {
this.autoVerifyHash = autoVerifyHash;
}
}

public static class ParticipantCertData implements ParticipantNode {
private int id;
private String address;
private String name;
private PubKey pubKey;

public ParticipantCertData() {
}

public ParticipantCertData(ParticipantNode participantNode) {
this.address = participantNode.getAddress();
this.name = participantNode.getName();
this.pubKey = participantNode.getPubKey();
}

public ParticipantCertData(int id, String address, String name, PubKey pubKey) {
this.id = id;
this.address = address;
this.name = name;
this.pubKey = pubKey;
}

@Override
public String getAddress() {
return address;
}

@Override
public String getName() {
return name;
}

@Override
public PubKey getPubKey() {
return pubKey;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}
}

public static class KvData implements KVDataEntry {

private String key;

private long version;

private DataType dataType;

private Object value;

public KvData() {
}

public KvData(String key, long version, DataType dataType) {
this(key, version, dataType, null);
}

public KvData(String key, long version, DataType dataType, Object value) {
this.key = key;
this.version = version;
this.dataType = dataType;
this.value = value;
}

public void setKey(String key) {
this.key = key;
}

public void setVersion(long version) {
this.version = version;
}

public void setDataType(DataType dataType) {
this.dataType = dataType;
}

public void setValue(Object value) {
this.value = value;
}

@Override
public String getKey() {
return key;
}

@Override
public long getVersion() {
return version;
}

@Override
public DataType getType() {
return dataType;
}

@Override
public Object getValue() {
return value;
}
}
} }

+ 4
- 4
source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java View File

@@ -11,7 +11,7 @@ import com.jd.blockchain.ledger.PreparedTransaction;
import com.jd.blockchain.ledger.TransactionResponse; import com.jd.blockchain.ledger.TransactionResponse;
import com.jd.blockchain.ledger.TransactionTemplate; import com.jd.blockchain.ledger.TransactionTemplate;
import com.jd.blockchain.transaction.LongValueHolder; import com.jd.blockchain.transaction.LongValueHolder;
import com.jd.blockchain.transaction.ValueHolder;
import com.jd.blockchain.transaction.GenericValueHolder;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;


public class SDK_Contract_Demo extends SDK_Base_Demo { public class SDK_Contract_Demo extends SDK_Base_Demo {
@@ -92,7 +92,7 @@ public class SDK_Contract_Demo extends SDK_Base_Demo {
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
// 使用合约创建 // 使用合约创建
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class);
ValueHolder<String> result = decode(transferContract.readAll(address, account));
GenericValueHolder<String> result = decode(transferContract.readAll(address, account));
commit(txTpl); commit(txTpl);
return result.get(); return result.get();
} }
@@ -122,7 +122,7 @@ public class SDK_Contract_Demo extends SDK_Base_Demo {
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
// 使用合约创建 // 使用合约创建
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class);
ValueHolder<String> result = decode(transferContract.transfer(address, from, to, money));
GenericValueHolder<String> result = decode(transferContract.transfer(address, from, to, money));
commit(txTpl); commit(txTpl);
return result.get(); return result.get();
} }
@@ -142,7 +142,7 @@ public class SDK_Contract_Demo extends SDK_Base_Demo {
if (useContract) { if (useContract) {
// 使用合约创建 // 使用合约创建
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class);
ValueHolder<String> result = decode(transferContract.create(address, account, money));
GenericValueHolder<String> result = decode(transferContract.create(address, account, money));
commit(txTpl); commit(txTpl);
return result.get(); return result.get();
} else { } else {


+ 4
- 4
source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDKDemo_Contract_Test.java View File

@@ -20,7 +20,7 @@ import com.jd.blockchain.sdk.client.GatewayServiceFactory;
import com.jd.blockchain.sdk.samples.SDKDemo_Constant; import com.jd.blockchain.sdk.samples.SDKDemo_Constant;
import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.tools.keygen.KeyGenCommand;
import com.jd.blockchain.transaction.LongValueHolder; import com.jd.blockchain.transaction.LongValueHolder;
import com.jd.blockchain.transaction.ValueHolder;
import com.jd.blockchain.transaction.GenericValueHolder;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;


public class SDKDemo_Contract_Test { public class SDKDemo_Contract_Test {
@@ -108,7 +108,7 @@ public class SDKDemo_Contract_Test {
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
// 使用合约创建 // 使用合约创建
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class);
ValueHolder<String> result = decode(transferContract.readAll(address, account));
GenericValueHolder<String> result = decode(transferContract.readAll(address, account));
commit(txTpl); commit(txTpl);
return result.get(); return result.get();
} }
@@ -126,7 +126,7 @@ public class SDKDemo_Contract_Test {
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
// 使用合约创建 // 使用合约创建
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class);
ValueHolder<String> result = decode(transferContract.transfer(address, from, to, money));
GenericValueHolder<String> result = decode(transferContract.transfer(address, from, to, money));
commit(txTpl); commit(txTpl);
return result.get(); return result.get();
} }
@@ -146,7 +146,7 @@ public class SDKDemo_Contract_Test {
if (useContract) { if (useContract) {
// 使用合约创建 // 使用合约创建
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class);
ValueHolder<String> result = decode(transferContract.create(address, account, money));
GenericValueHolder<String> result = decode(transferContract.create(address, account, money));
commit(txTpl); commit(txTpl);
return result.get(); return result.get();
} else { } else {


+ 23
- 17
source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java View File

@@ -24,6 +24,7 @@ import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.BlockchainIdentity;
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.BytesDataList;
import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.DataAccountRegisterOperation; import com.jd.blockchain.ledger.DataAccountRegisterOperation;
import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerBlock;
@@ -143,8 +144,9 @@ public class LedgerPerformanceTest {
batchCount = Integer.parseInt(args[1]); batchCount = Integer.parseInt(args[1]);
} }
} }
if (contract){
testContract(ledgerHash, testNode.getPartiKey(), ledgerManager, opHandler, batchSize, batchCount, silent);
if (contract) {
testContract(ledgerHash, testNode.getPartiKey(), ledgerManager, opHandler, batchSize, batchCount,
silent);
} }


if (usertest) { if (usertest) {
@@ -177,8 +179,9 @@ public class LedgerPerformanceTest {
* @param batchCount * @param batchCount
* @param silent * @param silent
*/ */
private static void testUserRegistering(HashDigest ledgerHash, AsymmetricKeypair adminKey, LedgerManager ledgerManager,
DefaultOperationHandleRegisteration opHandler, int batchSize, int batchCount, boolean silent) {
private static void testUserRegistering(HashDigest ledgerHash, AsymmetricKeypair adminKey,
LedgerManager ledgerManager, DefaultOperationHandleRegisteration opHandler, int batchSize, int batchCount,
boolean silent) {
LedgerRepository ledger = ledgerManager.getLedger(ledgerHash); LedgerRepository ledger = ledgerManager.getLedger(ledgerHash);
ConsoleUtils.info("\r\n\r\n================= 准备测试交易 [注册用户] ================="); ConsoleUtils.info("\r\n\r\n================= 准备测试交易 [注册用户] =================");


@@ -273,7 +276,7 @@ public class LedgerPerformanceTest {
* @param silent * @param silent
*/ */
private static void testContract(HashDigest ledgerHash, AsymmetricKeypair adminKey, LedgerManager ledgerManager, private static void testContract(HashDigest ledgerHash, AsymmetricKeypair adminKey, LedgerManager ledgerManager,
DefaultOperationHandleRegisteration opHandler, int batchSize, int batchCount, boolean silent) {
DefaultOperationHandleRegisteration opHandler, int batchSize, int batchCount, boolean silent) {
LedgerRepository ledger = ledgerManager.getLedger(ledgerHash); LedgerRepository ledger = ledgerManager.getLedger(ledgerHash);
ConsoleUtils.info("\r\n\r\n================= 准备测试交易 [执行合约] ================="); ConsoleUtils.info("\r\n\r\n================= 准备测试交易 [执行合约] =================");


@@ -285,8 +288,8 @@ public class LedgerPerformanceTest {


// 准备请求 // 准备请求
int totalCount = batchSize * batchCount; int totalCount = batchSize * batchCount;
List<TransactionRequest> contractTxList = prepareContractRequests(ledgerHash,
adminKey, totalCount, false, txProc);
List<TransactionRequest> contractTxList = prepareContractRequests(ledgerHash, adminKey, totalCount, false,
txProc);


Prompter consolePrompter = new PresetAnswerPrompter("N"); Prompter consolePrompter = new PresetAnswerPrompter("N");


@@ -303,6 +306,7 @@ public class LedgerPerformanceTest {
} }


} }

private static void execPerformanceTest(int batchCount, int batchSize, List<TransactionRequest> txList, private static void execPerformanceTest(int batchCount, int batchSize, List<TransactionRequest> txList,
LedgerRepository ledger, LedgerManager ledgerManager, DefaultOperationHandleRegisteration opHandler, LedgerRepository ledger, LedgerManager ledgerManager, DefaultOperationHandleRegisteration opHandler,
boolean statistic) { boolean statistic) {
@@ -407,8 +411,7 @@ 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()).setText("key-" + startTs + "-" + i,
"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());
@@ -426,8 +429,9 @@ public class LedgerPerformanceTest {
public static ConsensusProvider getConsensusProvider(String provider) { public static ConsensusProvider getConsensusProvider(String provider) {
return ConsensusProviders.getProvider(provider); return ConsensusProviders.getProvider(provider);
} }
public static List<TransactionRequest> prepareContractRequests(HashDigest ledgerHash,
AsymmetricKeypair adminKey, int count, boolean statistic, TransactionBatchProcessor txProc) {

public static List<TransactionRequest> prepareContractRequests(HashDigest ledgerHash, AsymmetricKeypair adminKey,
int count, boolean statistic, TransactionBatchProcessor txProc) {


// deploy contract // deploy contract
byte[] chainCode; byte[] chainCode;
@@ -436,7 +440,7 @@ public class LedgerPerformanceTest {
InputStream input = LedgerPerformanceTest.class.getClassLoader().getResourceAsStream("example1.jar"); InputStream input = LedgerPerformanceTest.class.getClassLoader().getResourceAsStream("example1.jar");
chainCode = new byte[input.available()]; chainCode = new byte[input.available()];
input.read(chainCode); input.read(chainCode);
}catch (IOException e){
} catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
return null; return null;
} }
@@ -457,10 +461,10 @@ public class LedgerPerformanceTest {
System.out.println(resp.isSuccess()); System.out.println(resp.isSuccess());
TransactionBatchResultHandle handle = txProc.prepare(); TransactionBatchResultHandle handle = txProc.prepare();
handle.commit(); handle.commit();
try{
try {


Thread.sleep(1000); Thread.sleep(1000);
} catch (Exception e){
} catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }


@@ -468,8 +472,9 @@ public class LedgerPerformanceTest {
List<TransactionRequest> txList = new ArrayList<>(); List<TransactionRequest> txList = new ArrayList<>();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
txbuilder = new TxBuilder(ledgerHash); txbuilder = new TxBuilder(ledgerHash);
String args = dataIdentity.getAddress().toString() + "##"+Integer.toString(i)+ "##"+Integer.toString(i);
txbuilder.contractEvents().send(contractIdentity.getAddress(), "hello", args.getBytes());
String args = dataIdentity.getAddress().toString() + "##" + Integer.toString(i) + "##"
+ Integer.toString(i);
txbuilder.contractEvents().send(contractIdentity.getAddress(), "print", BytesDataList.singleText("hello"));
// txbuilder.contractEvents().send(contractIdentity.getAddress(), "print", args.getBytes()); // txbuilder.contractEvents().send(contractIdentity.getAddress(), "print", args.getBytes());
reqBuilder = txbuilder.prepareRequest(); reqBuilder = txbuilder.prepareRequest();
reqBuilder.signAsEndpoint(adminKey); reqBuilder.signAsEndpoint(adminKey);
@@ -485,7 +490,8 @@ public class LedgerPerformanceTest {
return txList; return txList;
} }


public static NodeContext[] initLedgers(boolean optimized, CryptoAlgorithm hashAlg, DBType dbType, String provider, String config) {
public static NodeContext[] initLedgers(boolean optimized, CryptoAlgorithm hashAlg, DBType dbType, String provider,
String config) {
Map<NetworkAddress, LedgerInitConsensusService> serviceRegisterMap = new ConcurrentHashMap<>(); Map<NetworkAddress, LedgerInitConsensusService> serviceRegisterMap = new ConcurrentHashMap<>();


Prompter consolePrompter = new PresetAnswerPrompter("N"); // new ConsolePrompter(); Prompter consolePrompter = new PresetAnswerPrompter("N"); // new ConsolePrompter();


+ 7
- 8
source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java View File

@@ -29,7 +29,6 @@ import org.apache.commons.io.FileUtils;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;


import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.contract.ContractSerializeUtils;
import com.jd.blockchain.contract.ReadContract; import com.jd.blockchain.contract.ReadContract;
import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.AsymmetricKeypair;
@@ -51,7 +50,7 @@ import com.jd.blockchain.sdk.BlockchainService;
import com.jd.blockchain.storage.service.DbConnection; import com.jd.blockchain.storage.service.DbConnection;
import com.jd.blockchain.storage.service.DbConnectionFactory; import com.jd.blockchain.storage.service.DbConnectionFactory;
import com.jd.blockchain.tools.initializer.LedgerBindingConfig; import com.jd.blockchain.tools.initializer.LedgerBindingConfig;
import com.jd.blockchain.transaction.ValueHolder;
import com.jd.blockchain.transaction.GenericValueHolder;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.concurrent.ThreadInvoker; import com.jd.blockchain.utils.concurrent.ThreadInvoker;
import com.jd.blockchain.utils.net.NetworkAddress; import com.jd.blockchain.utils.net.NetworkAddress;
@@ -586,7 +585,7 @@ public class IntegrationBase {


ReadContract readContract1 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); ReadContract readContract1 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class);


ValueHolder<String> result1 = decode(readContract1.read(newDataAccount.getAddress().toBase58(), key1));
GenericValueHolder<String> result1 = decode(readContract1.read(newDataAccount.getAddress().toBase58(), key1));


ReadContract readContract2 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); ReadContract readContract2 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class);


@@ -594,7 +593,7 @@ public class IntegrationBase {


ReadContract readContract3 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); ReadContract readContract3 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class);


ValueHolder<Long> result3 = decode(readContract3.readVersion(newDataAccount.getAddress().toBase58(), key2));
GenericValueHolder<Long> result3 = decode(readContract3.readVersion(newDataAccount.getAddress().toBase58(), key2));


// 签名; // 签名;
PreparedTransaction contractPtx = txContract.prepare(); PreparedTransaction contractPtx = txContract.prepare();
@@ -610,10 +609,10 @@ public class IntegrationBase {
System.out.printf("readContract3.result = %s \r\n", result3.get()); System.out.printf("readContract3.result = %s \r\n", result3.get());




// 打印结果
for (OperationResult or : operationResults) {
System.out.printf("操作[%s].Result = %s \r\n", or.getIndex(), ContractSerializeUtils.resolve(or.getResult()));
}
// // 打印结果
// for (OperationResult or : operationResults) {
// System.out.printf("操作[%s].Result = %s \r\n", or.getIndex(), ContractSerializeUtils.resolve(or.getResult()));
// }
// //
// // 验证结果 // // 验证结果
// assertNotNull(contractReturn); // assertNotNull(contractReturn);


+ 1
- 2
source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java View File

@@ -6,7 +6,6 @@ import java.util.concurrent.ConcurrentHashMap;


import com.jd.blockchain.contract.ContractEventContext; import com.jd.blockchain.contract.ContractEventContext;
import com.jd.blockchain.contract.ContractException; import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.contract.ContractSerializeUtils;
import com.jd.blockchain.contract.EventProcessingAware; import com.jd.blockchain.contract.EventProcessingAware;
import com.jd.blockchain.contract.LedgerContext; import com.jd.blockchain.contract.LedgerContext;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
@@ -75,7 +74,7 @@ public class MockerContractExeHandle implements OperationHandle {
} }


// No return value; // No return value;
return ContractSerializeUtils.serialize(result);
return null;
} }


@Override @Override


+ 57
- 57
source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/proxy/ContractProxy.java View File

@@ -1,88 +1,88 @@
package com.jd.blockchain.mocker.proxy; package com.jd.blockchain.mocker.proxy;


import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import com.jd.blockchain.contract.Contract; import com.jd.blockchain.contract.Contract;
import com.jd.blockchain.contract.ContractEvent; import com.jd.blockchain.contract.ContractEvent;
import com.jd.blockchain.contract.ContractSerializeUtils;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BytesValueEncoding;
import com.jd.blockchain.ledger.OperationResult; import com.jd.blockchain.ledger.OperationResult;
import com.jd.blockchain.ledger.OperationResultData;
import com.jd.blockchain.ledger.TransactionRequest; import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.mocker.MockerNodeContext; import com.jd.blockchain.mocker.MockerNodeContext;
import com.jd.blockchain.mocker.handler.MockerContractExeHandle; import com.jd.blockchain.mocker.handler.MockerContractExeHandle;
import com.jd.blockchain.transaction.TxBuilder; import com.jd.blockchain.transaction.TxBuilder;


import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ContractProxy<T> implements InvocationHandler { public class ContractProxy<T> implements InvocationHandler {


private BlockchainIdentity identity;
private BlockchainIdentity identity;


private MockerNodeContext mockerNodeContext;
private MockerNodeContext mockerNodeContext;


private T instance;
private T instance;


private MockerContractExeHandle operationHandle;
private MockerContractExeHandle operationHandle;


public ContractProxy(BlockchainIdentity identity, MockerNodeContext mockerNodeContext,
T instance, MockerContractExeHandle operationHandle) {
this.identity = identity;
this.mockerNodeContext = mockerNodeContext;
this.instance = instance;
this.operationHandle = operationHandle;
}
public ContractProxy(BlockchainIdentity identity, MockerNodeContext mockerNodeContext, T instance,
MockerContractExeHandle operationHandle) {
this.identity = identity;
this.mockerNodeContext = mockerNodeContext;
this.instance = instance;
this.operationHandle = operationHandle;
}


@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 实际执行时,首先判断执行的是否是添加注解的方法
if (!isExecuteContractMethod(method)) {
return method.invoke(instance, args);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 实际执行时,首先判断执行的是否是添加注解的方法
if (!isExecuteContractMethod(method)) {
return method.invoke(instance, args);
}


// 首先发送一次执行的请求
TxBuilder txBuilder = mockerNodeContext.txBuilder();
// 首先发送一次执行的请求
TxBuilder txBuilder = mockerNodeContext.txBuilder();


Class<?> contractInft = null;
Class<?> contractInft = null;


Class<?>[] instanceInfts = instance.getClass().getInterfaces();
Class<?>[] instanceInfts = instance.getClass().getInterfaces();


for (Class<?> instanceInft : instanceInfts) {
if (instanceInft.isAnnotationPresent(Contract.class)) {
contractInft = instanceInft;
break;
}
}
for (Class<?> instanceInft : instanceInfts) {
if (instanceInft.isAnnotationPresent(Contract.class)) {
contractInft = instanceInft;
break;
}
}


if (contractInft == null) {
throw new IllegalStateException("This object does not implement the interface for the @Contract annotation !!!");
}
if (contractInft == null) {
throw new IllegalStateException(
"This object does not implement the interface for the @Contract annotation !!!");
}


// 生成代理类
Object proxyInstance = txBuilder.contract(identity.getAddress().toBase58(), contractInft);
// 代理方式执行一次
method.invoke(proxyInstance, args);
// 生成代理类
Object proxyInstance = txBuilder.contract(identity.getAddress().toBase58(), contractInft);
// 代理方式执行一次
method.invoke(proxyInstance, args);


TransactionRequest txRequest = mockerNodeContext.txRequest(txBuilder);
TransactionRequest txRequest = mockerNodeContext.txRequest(txBuilder);


// 放入到Map中
HashDigest txHash = txRequest.getTransactionContent().getHash();
operationHandle.registerExecutorProxy(txHash, new ExecutorProxy(instance, method, args));
// 放入到Map中
HashDigest txHash = txRequest.getTransactionContent().getHash();
operationHandle.registerExecutorProxy(txHash, new ExecutorProxy(instance, method, args));


// 提交该请求至整个区块链系统
OperationResult[] operationResults = mockerNodeContext.txProcess(txRequest);
if (operationResults == null || operationResults.length == 0) {
return null;
}
OperationResult opResult = operationResults[0];
// 提交该请求至整个区块链系统
OperationResult[] operationResults = mockerNodeContext.txProcess(txRequest);
if (operationResults == null || operationResults.length == 0) {
return null;
}
OperationResult opResult = operationResults[0];


// 处理返回值
return ContractSerializeUtils.resolve(opResult.getResult());
}
// 处理返回值
return BytesValueEncoding.encode(opResult.getResult(), method.getReturnType());
}


private boolean isExecuteContractMethod(Method method) {
Annotation annotation = method.getAnnotation(ContractEvent.class);
return annotation != null;
}
private boolean isExecuteContractMethod(Method method) {
Annotation annotation = method.getAnnotation(ContractEvent.class);
return annotation != null;
}
} }

+ 1
- 4
source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/DefaultExceptionHandle.java View File

@@ -5,8 +5,6 @@ import java.lang.reflect.Method;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.jd.blockchain.utils.console.CommandConsole;
public class DefaultExceptionHandle<TListener> implements ExceptionHandle<TListener> { public class DefaultExceptionHandle<TListener> implements ExceptionHandle<TListener> {
@Override @Override
@@ -21,9 +19,8 @@ public class DefaultExceptionHandle<TListener> implements ExceptionHandle<TListe
} }
argsValue = String.format(argsFormat.toString(), args); argsValue = String.format(argsFormat.toString(), args);
} }
String message = String.format("Error occurred on firing event!--[listener.class=%s][method=%s][args=%s]--[%s]%s",
String message = String.format("Error occurred while firing event!--[listener.class=%s][method=%s][args=%s]--[%s]%s",
listener.getClass().getName(), method.getName(), argsValue, ex.getClass().getName(), ex.getMessage()); listener.getClass().getName(), method.getName(), argsValue, ex.getClass().getName(), ex.getMessage());
// System.err.println(message);
logger.error(message, ex); logger.error(message, ex);
} }
private Logger logger = LoggerFactory.getLogger(DefaultExceptionHandle.class); private Logger logger = LoggerFactory.getLogger(DefaultExceptionHandle.class);


+ 16
- 10
source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/EventMulticaster.java View File

@@ -3,11 +3,12 @@ package com.jd.blockchain.utils.event;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
import com.jd.blockchain.utils.Disposable; import com.jd.blockchain.utils.Disposable;
@@ -36,17 +37,22 @@ public class EventMulticaster<TListener> implements Disposable {
} }
public EventMulticaster(Class<TListener> listenerClass, Logger errorLogger) { public EventMulticaster(Class<TListener> listenerClass, Logger errorLogger) {
this(listenerClass, new ExceptionLoggingHandle<TListener>(errorLogger));
this(listenerClass, new RethrowExceptionHandler<TListener>(errorLogger));
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public EventMulticaster(Class<TListener> listenerClass, ExceptionHandle<TListener> exHandle) { public EventMulticaster(Class<TListener> listenerClass, ExceptionHandle<TListener> exHandle) {
if (!listenerClass.isInterface()) {
throw new IllegalArgumentException("The specified class of listener does not represent an interface!");
}
// 初始化错误处理器; // 初始化错误处理器;
this.exHandle = exHandle == null ? new DefaultExceptionHandle<TListener>() : exHandle;
this.exHandle = exHandle == null
? new RethrowExceptionHandler<TListener>(LoggerFactory.getLogger(EventMulticaster.class))
: exHandle;
// 解析出不支持的方法; // 解析出不支持的方法;
Method[] methods = ReflectionUtils.getAllDeclaredMethods(listenerClass); Method[] methods = ReflectionUtils.getAllDeclaredMethods(listenerClass);
List<Method> supMths = new LinkedList<Method>();
List<Method> supMths = new ArrayList<Method>();
for (Method method : methods) { for (Method method : methods) {
if (method.getDeclaringClass() == Object.class) { if (method.getDeclaringClass() == Object.class) {
// 不支持 Object 方法; // 不支持 Object 方法;
@@ -86,14 +92,14 @@ public class EventMulticaster<TListener> implements Disposable {
throw new UnsupportedOperationException("Unsupported method for event multicasting!"); throw new UnsupportedOperationException("Unsupported method for event multicasting!");
} }
} }
protected void doNotify(List<TListener> listeners, Method method, Object[] args){
protected void doNotify(List<TListener> listeners, Method method, Object[] args) {
for (TListener listener : listeners) { for (TListener listener : listeners) {
doNotifySingle(listener, method, args); doNotifySingle(listener, method, args);
} }
} }
protected void doNotifySingle(TListener listener, Method method, Object[] args){
protected void doNotifySingle(TListener listener, Method method, Object[] args) {
try { try {
ReflectionUtils.invokeMethod(method, listener, args); ReflectionUtils.invokeMethod(method, listener, args);
} catch (Exception e) { } catch (Exception e) {
@@ -104,12 +110,12 @@ public class EventMulticaster<TListener> implements Disposable {
public void addListener(TListener listener) { public void addListener(TListener listener) {
listeners.add(listener); listeners.add(listener);
} }
public void removeListener(TListener listener) { public void removeListener(TListener listener) {
listeners.remove(listener); listeners.remove(listener);
} }
public TListener broadcast() {
public TListener getBroadcaster() {
return listenerProxy; return listenerProxy;
} }


Loading…
Cancel
Save