diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java index 5a302ca8..977f2c2e 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java @@ -4,7 +4,7 @@ import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.ledger.AccountHeader; import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.BytesValueEntry; +import com.jd.blockchain.ledger.BytesData; import com.jd.blockchain.utils.Bytes; public class ContractAccount implements AccountHeader { @@ -43,7 +43,7 @@ public class ContractAccount implements AccountHeader { } 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); } @@ -60,18 +60,18 @@ public class ContractAccount implements AccountHeader { } 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); } public String getProperty(Bytes key) { BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key)); - return BytesValueEntry.toText(bytesValue); + return BytesData.toText(bytesValue); } public String getProperty(Bytes key, long version) { BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key), version); - return BytesValueEntry.toText(bytesValue); + return BytesData.toText(bytesValue); } private Bytes encodePropertyKey(Bytes key) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java index d7092e63..792ca704 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java @@ -6,7 +6,7 @@ import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.ledger.AccountHeader; import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.BytesValueEntry; +import com.jd.blockchain.ledger.BytesData; import com.jd.blockchain.ledger.KVDataEntry; import com.jd.blockchain.ledger.KVDataObject; 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) { - BytesValue bytesValue = BytesValueEntry.fromText(value); + BytesValue bytesValue = BytesData.fromText(value); return baseAccount.setBytes(key, bytesValue, 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); } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java index f6faa1e0..b9cc88fd 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java @@ -3,7 +3,7 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.BytesValueEntry; +import com.jd.blockchain.ledger.BytesData; import com.jd.blockchain.ledger.UserInfo; import com.jd.blockchain.utils.Bytes; @@ -50,12 +50,12 @@ public class UserAccount implements UserInfo { public long setDataPubKey(PubKey pubKey) { 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) { 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) { @@ -63,7 +63,7 @@ public class UserAccount implements UserInfo { } 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) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java index 162f3408..4a0e1ed5 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java @@ -8,7 +8,7 @@ import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.AccountHeader; import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.BytesValueEntry; +import com.jd.blockchain.ledger.BytesData; import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.DataAccountRegisterOperation; import com.jd.blockchain.ledger.KVDataEntry; @@ -279,7 +279,7 @@ public class ContractLedgerContext implements LedgerContext { @Override 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); handle(op); return this; @@ -287,7 +287,7 @@ public class ContractLedgerContext implements LedgerContext { @Override 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); handle(op); return this; @@ -295,7 +295,7 @@ public class ContractLedgerContext implements LedgerContext { @Override 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); handle(op); return this; @@ -312,7 +312,7 @@ public class ContractLedgerContext implements LedgerContext { @Override 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); handle(op); return this; @@ -320,7 +320,7 @@ public class ContractLedgerContext implements LedgerContext { @Override 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); handle(op); return this; @@ -328,7 +328,7 @@ public class ContractLedgerContext implements LedgerContext { @Override 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); handle(op); return this; @@ -336,7 +336,7 @@ public class ContractLedgerContext implements LedgerContext { @Override 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); handle(op); return this; @@ -344,7 +344,7 @@ public class ContractLedgerContext implements LedgerContext { @Override 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); handle(op); return this; diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java index ac9f50b1..4a641b7d 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java @@ -12,7 +12,7 @@ import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.BytesValueEntry; +import com.jd.blockchain.ledger.BytesData; import com.jd.blockchain.ledger.core.BaseAccount; import com.jd.blockchain.ledger.core.CryptoConfig; import com.jd.blockchain.storage.service.utils.MemoryKVStorage; @@ -53,33 +53,33 @@ public class BaseAccountTest { assertFalse(baseAccount.isReadonly()); // 在空白状态下写入数据; - long v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A"), 0); + long v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), 0); // 预期失败; 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); - 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); - 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,预期导致失败; assertEquals(-1, v); baseAccount.commit(); v = 0; 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(); // 预期成功; assertEquals(v + 1, s); 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); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java index 27e234d0..20f49bd4 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java @@ -21,7 +21,7 @@ import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.BytesValueEntry; +import com.jd.blockchain.ledger.BytesData; import com.jd.blockchain.ledger.EndpointRequest; import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerInitSetting; @@ -103,6 +103,7 @@ public class ContractInvokingTest { Random rand = new Random(); TxBuilder txBuilder = new TxBuilder(ledgerHash); TestContract contractProxy = txBuilder.contract(contractAddress, TestContract.class); + TestContract contractProxy1 = txBuilder.contract(contractAddress, TestContract.class); String asset = "AK"; long issueAmount = rand.nextLong(); @@ -120,7 +121,7 @@ public class ContractInvokingTest { assertEquals(1, opResults.length); 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); assertArrayEquals(expectedRetnBytes, reallyRetnBytes); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java index c39ea445..a4b719a7 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java @@ -1,5 +1,6 @@ package test.com.jd.blockchain.ledger; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -10,10 +11,13 @@ import java.util.Random; import org.junit.Test; +import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.BlockchainKeyGenerator; 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.ContractEventSendOperation; import com.jd.blockchain.ledger.CryptoSetting; @@ -67,8 +71,8 @@ public class TransactionSetTest { BlockchainKeypair dataKey = BlockchainKeyGenerator.getInstance().generate(); 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]; rand.nextBytes(chainCode); @@ -76,7 +80,7 @@ public class TransactionSetTest { ContractCodeDeployOperation contractDplOP = txBuilder.contracts().deploy(contractKey.getIdentity(), chainCode); ContractEventSendOperation contractEvtSendOP = txBuilder.contractEvents().send(contractKey.getAddress(), "test", - "TestContractArgs".getBytes()); + BytesDataList.singleText("TestContractArgs")); TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest(); @@ -98,7 +102,8 @@ public class TransactionSetTest { txSnapshot.setContractAccountSetHash(contractAccountSetHash); 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); assertTrue(txset.isUpdated()); @@ -172,7 +177,8 @@ public class TransactionSetTest { for (int i = 0; i < acutualKVWriteSet.length; i++) { assertEquals(expKVWriteSet[i].getKey(), acutualKVWriteSet[i].getKey()); assertEquals(expKVWriteSet[i].getExpectedVersion(), acutualKVWriteSet[i].getExpectedVersion()); - assertTrue(BytesUtils.equals(expKVWriteSet[i].getValue().getValue().toBytes(), acutualKVWriteSet[i].getValue().getValue().toBytes())); + assertTrue(BytesUtils.equals(expKVWriteSet[i].getValue().getValue().toBytes(), + acutualKVWriteSet[i].getValue().getValue().toBytes())); } ContractCodeDeployOperation actualContractDplOp = (ContractCodeDeployOperation) actualOperations[3]; @@ -184,8 +190,14 @@ public class TransactionSetTest { assertEquals(contractEvtSendOP.getContractAddress(), actualContractEvtSendOp.getContractAddress()); assertEquals(contractEvtSendOP.getEvent(), 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); } } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEntry.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesData.java similarity index 63% rename from source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEntry.java rename to source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesData.java index 612c6111..ca4e9cb0 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEntry.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesData.java @@ -8,38 +8,38 @@ import com.jd.blockchain.utils.io.BytesUtils; * @author huanghaiquan * */ -public class BytesValueEntry implements BytesValue { +public class BytesData implements BytesValue { DataType type; Bytes value; - private BytesValueEntry(DataType type, byte[] bytes) { + private BytesData(DataType type, byte[] bytes) { this.type = type; this.value = new Bytes(bytes); } - private BytesValueEntry(DataType type, Bytes bytes) { + private BytesData(DataType type, Bytes bytes) { this.type = type; this.value = bytes; } public static BytesValue fromType(DataType type, byte[] value) { - return new BytesValueEntry(type, value); + return new BytesData(type, 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) { - return new BytesValueEntry(DataType.BYTES, value); + return new BytesData(DataType.BYTES, 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) { - return new BytesValueEntry(DataType.IMG, value); + return new BytesData(DataType.IMG, value); } /** @@ -49,7 +49,7 @@ public class BytesValueEntry implements BytesValue { * @return */ 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) { - return new BytesValueEntry(DataType.JSON, BytesUtils.toBytes(value)); + return new BytesData(DataType.JSON, BytesUtils.toBytes(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) { - return new BytesValueEntry(DataType.INT32, BytesUtils.toBytes(value)); + return new BytesData(DataType.INT32, BytesUtils.toBytes(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) { - return new BytesValueEntry(DataType.INT16, BytesUtils.toBytes(value)); + return new BytesData(DataType.INT16, BytesUtils.toBytes(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) { - return new BytesValueEntry(DataType.TIMESTAMP, BytesUtils.toBytes(value)); + return new BytesData(DataType.TIMESTAMP, BytesUtils.toBytes(value)); } public static BytesValue fromBoolean(boolean value) { - return new BytesValueEntry(DataType.BOOLEAN, BytesUtils.toBytes(value)); + return new BytesData(DataType.BOOLEAN, BytesUtils.toBytes(value)); } @Override diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesDataList.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesDataList.java new file mode 100644 index 00000000..f7aef959 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesDataList.java @@ -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)); + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PreparedTransaction.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PreparedTransaction.java index b7db5b59..20d4d9ad 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PreparedTransaction.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PreparedTransaction.java @@ -1,5 +1,7 @@ package com.jd.blockchain.ledger; +import java.io.Closeable; + import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; @@ -9,7 +11,7 @@ import com.jd.blockchain.crypto.HashDigest; * @author huanghaiquan * */ -public interface PreparedTransaction extends HashObject { +public interface PreparedTransaction extends HashObject, Closeable { /** * 交易内容的 Hash; @@ -55,8 +57,4 @@ public interface PreparedTransaction extends HashObject { */ TransactionResponse commit(); - /** - * 取消交易;
- */ - void cancel(); } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionTemplate.java index 3c5acdcf..0696e768 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionTemplate.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionTemplate.java @@ -1,5 +1,7 @@ package com.jd.blockchain.ledger; +import java.io.Closeable; + import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.transaction.ClientOperator; @@ -9,7 +11,7 @@ import com.jd.blockchain.transaction.ClientOperator; * @author huanghaiquan * */ -public interface TransactionTemplate extends ClientOperator { +public interface TransactionTemplate extends ClientOperator, Closeable { HashDigest getLedgerHash(); diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java index 4e7e172d..ef9b138a 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java @@ -106,15 +106,15 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe * * @return */ - public Collection getReturnValuetHandlers() { - List resultHandlers = new ArrayList(); + public Collection getReturnValuetHandlers() { + List resultHandlers = new ArrayList(); int index = 0; for (Operation op : operationList) { if (op instanceof ContractEventSendOperation) { // 操作具有返回值,创建对应的结果处理器; ContractEventSendOpTemplate opTemp = (ContractEventSendOpTemplate) op; ContractInvocation invocation = opTemp.getInvocation(); - OperationReturnValueHandler retnHandler; + OperationResultHandle retnHandler; if (invocation == null) { retnHandler = new NullOperationReturnValueHandler(index); } else { @@ -278,7 +278,7 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe * @author huanghaiquan * */ - private static class NullOperationReturnValueHandler implements OperationReturnValueHandler { + private static class NullOperationReturnValueHandler implements OperationResultHandle { private int operationIndex; @@ -292,10 +292,14 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe } @Override - public Object setReturnValue(BytesValue bytesValue) { + public Object complete(BytesValue bytesValue) { return null; } + @Override + public void complete(Throwable error) { + } + } } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BooleanValueHolder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BooleanValueHolder.java index 977a88b0..480e3d30 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BooleanValueHolder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BooleanValueHolder.java @@ -1,43 +1,22 @@ 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); } /** - * 等待结果合约调用的结果返回; + * 获取值;
* - * @return - */ - public boolean get() { - return (boolean) super.getValue(); - } - - /** - * 等待结果合约调用的结果返回; + * 此方法不堵塞,调用立即返回;
* - * @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 - * @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; } + } \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ByteValueHolder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ByteValueHolder.java index 32809d51..d9c024ff 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ByteValueHolder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ByteValueHolder.java @@ -1,43 +1,22 @@ 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); } /** - * 等待结果合约调用的结果返回; + * 获取值;
* - * @return - */ - public byte get() { - return (byte) super.getValue(); - } - - /** - * 等待结果合约调用的结果返回; + * 此方法不堵塞,调用立即返回;
* - * @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 - * @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; } + } \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocation.java index cab7df0c..2e27fca9 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocation.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocation.java @@ -1,8 +1,6 @@ package com.jd.blockchain.transaction; 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.ledger.BytesValue; @@ -14,7 +12,7 @@ import com.jd.blockchain.ledger.BytesValueEncoding; * @author huanghaiquan * */ -class ContractInvocation implements OperationReturnValueHandler { +class ContractInvocation extends OperationResultHolder { private Method method; @@ -22,12 +20,9 @@ class ContractInvocation implements OperationReturnValueHandler { private int operationIndex = -1; - private CompletableFuture returnValueFuture; - public ContractInvocation(ContractType contractType, Method method) { this.contractType = contractType; this.method = method; - this.returnValueFuture = new CompletableFuture(); } public ContractType getContractType() { @@ -47,16 +42,9 @@ class ContractInvocation implements OperationReturnValueHandler { return method.getReturnType(); } - public Future getReturnValue() { - return returnValueFuture; - } - @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()); } } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java index 82c07197..e5e7b947 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java @@ -4,10 +4,8 @@ import java.lang.reflect.Proxy; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import com.jd.blockchain.contract.EventResult; import com.jd.blockchain.contract.ContractType; import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.IllegalDataException; /** * 合约调用代理的构建器; @@ -19,8 +17,6 @@ public class ContractInvocationProxyBuilder { private Map, ContractType> contractTypes = new ConcurrentHashMap<>(); -// private Map contractOperations = new ConcurrentHashMap<>(); - public T create(String address, Class contractIntf, ContractEventSendOperationBuilder contractEventBuilder) { return create(Bytes.fromBase58(address), contractIntf, contractEventBuilder); } @@ -33,31 +29,9 @@ public class ContractInvocationProxyBuilder { T proxy = (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[] { contractIntf }, proxyHandler); -// // 创建关联关系 -// contractOperations.put(proxy, proxyHandler.opIndex()); return proxy; } -// public EventResult 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) { ContractType contractType = contractTypes.get(contractIntf); if (contractType != null) { diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractReturnValue.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractReturnValue.java index 0232a0ba..9fee9ea7 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractReturnValue.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractReturnValue.java @@ -26,9 +26,9 @@ public class ContractReturnValue { * @param call * @return */ - public static ValueHolder decode(T call) { + public static GenericValueHolder decode(T call) { ContractInvocation invocation = ContractInvocationStub.take(); - return new ValueHolder(invocation); + return new GenericValueHolder(invocation); } /** diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java index d8125022..b2ccef13 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java @@ -1,7 +1,7 @@ package com.jd.blockchain.transaction; import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.BytesValueEntry; +import com.jd.blockchain.ledger.BytesData; import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.utils.Bytes; @@ -26,14 +26,14 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe @Override public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { - BytesValue bytesValue = BytesValueEntry.fromBytes(value); + BytesValue bytesValue = BytesData.fromBytes(value); operation.set(key, bytesValue, expVersion); return this; } @Override public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { - BytesValue bytesValue = BytesValueEntry.fromImage(value); + BytesValue bytesValue = BytesData.fromImage(value); operation.set(key, bytesValue, expVersion); return this; } @@ -45,42 +45,42 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe @Override public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { - BytesValue bytesValue = BytesValueEntry.fromText(value); + BytesValue bytesValue = BytesData.fromText(value); operation.set(key, bytesValue, expVersion); return this; } @Override public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { - BytesValue bytesValue = BytesValueEntry.fromBytes(value); + BytesValue bytesValue = BytesData.fromBytes(value); operation.set(key, bytesValue, expVersion); return this; } @Override public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { - BytesValue bytesValue = BytesValueEntry.fromInt64(value); + BytesValue bytesValue = BytesData.fromInt64(value); operation.set(key, bytesValue, expVersion); return this; } @Override public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { - BytesValue bytesValue = BytesValueEntry.fromJSON(value); + BytesValue bytesValue = BytesData.fromJSON(value); operation.set(key, bytesValue, expVersion); return this; } @Override public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { - BytesValue bytesValue = BytesValueEntry.fromXML(value); + BytesValue bytesValue = BytesData.fromXML(value); operation.set(key, bytesValue, expVersion); return this; } @Override public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { - BytesValue bytesValue = BytesValueEntry.fromTimestamp(value); + BytesValue bytesValue = BytesData.fromTimestamp(value); operation.set(key, bytesValue, expVersion); return this; } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/GenericValueHolder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/GenericValueHolder.java new file mode 100644 index 00000000..1832f315 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/GenericValueHolder.java @@ -0,0 +1,23 @@ +package com.jd.blockchain.transaction; + +public class GenericValueHolder extends ValueHolderWrapper { + + GenericValueHolder(OperationResultHolder resultHolder) { + super(resultHolder); + } + + /** + * 获取值;
+ * + * 此方法不堵塞,调用立即返回;
+ * + * 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 null; + * + * @return + */ + @SuppressWarnings("unchecked") + public T get() { + return (T) super.getValue(); + } + +} \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/IntValueHolder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/IntValueHolder.java index 05394652..5e490ca3 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/IntValueHolder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/IntValueHolder.java @@ -1,43 +1,22 @@ 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); } /** - * 等待结果合约调用的结果返回; + * 获取值;
* - * @return - */ - public int get() { - return (int) super.getValue(); - } - - /** - * 等待结果合约调用的结果返回; + * 此方法不堵塞,调用立即返回;
* - * @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 - * @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; } + } \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LongValueHolder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LongValueHolder.java index 6d9b0593..e5409f29 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LongValueHolder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LongValueHolder.java @@ -1,43 +1,22 @@ 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); } /** - * 等待结果合约调用的结果返回; + * 获取值;
* - * @return - */ - public long get() { - return (long) super.getValue(); - } - - /** - * 等待结果合约调用的结果返回; + * 此方法不堵塞,调用立即返回;
* - * @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 - * @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; } + } \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationCompletedContext.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationCompletedContext.java new file mode 100644 index 00000000..1197f95b --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationCompletedContext.java @@ -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; + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationCompletedListener.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationCompletedListener.java new file mode 100644 index 00000000..c11f27dd --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationCompletedListener.java @@ -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); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationResultHandle.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationResultHandle.java new file mode 100644 index 00000000..12bc7b33 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationResultHandle.java @@ -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); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationResultHolder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationResultHolder.java new file mode 100644 index 00000000..d93f0f4f --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationResultHolder.java @@ -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 listenerMulticaster; + + /** + * 导致结束的错误; + * + * @return + */ + public Throwable getError() { + return error; + } + + /** + * 是否已经处理完成; + * + * @return + */ + public boolean isCompleted() { + return completed; + } + + /** + * 获取操作的返回值;
+ * 在操作未完成之前,总是返回 null;
+ * 可以通过 {@link #isCompleted()} 方法判断操作是否已经完成;
+ * 可以通过 {@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); + } +} \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationReturnValueHandler.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationReturnValueHandler.java deleted file mode 100644 index c490091a..00000000 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/OperationReturnValueHandler.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.BytesValue; - -interface OperationReturnValueHandler { - - int getOperationIndex(); - - Object setReturnValue(BytesValue bytesValue); - -} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java index f9636427..b2d0f107 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java @@ -1,9 +1,12 @@ package com.jd.blockchain.transaction; +import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; +import org.springframework.cglib.proxy.UndeclaredThrowableException; + import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.Crypto; @@ -25,7 +28,9 @@ public class PreparedTx implements PreparedTransaction { private TransactionService txProcessor; - private OperationReturnValueHandler[] opReturnValueHandlers; + private OperationResultHandle[] opReturnValueHandlers; + + private TxStateManager stateManager; /** * 创建一个“就绪交易”对象; @@ -34,17 +39,18 @@ public class PreparedTx implements PreparedTransaction { * @param txProcessor 交易处理服务; * @param opReturnValueHandlerList 操作返回值处理器列表; */ - public PreparedTx(TransactionRequestBuilder txReqBuilder, TransactionService txProcessor, - Collection opReturnValueHandlerList) { + public PreparedTx(TxStateManager stateManager, TransactionRequestBuilder txReqBuilder, + TransactionService txProcessor, Collection opReturnValueHandlerList) { + this.stateManager = stateManager; this.txReqBuilder = txReqBuilder; this.txProcessor = txProcessor; this.opReturnValueHandlers = opReturnValueHandlerList - .toArray(new OperationReturnValueHandler[opReturnValueHandlerList.size()]); + .toArray(new OperationResultHandle[opReturnValueHandlerList.size()]); // 按照操作索引升序排列; - Arrays.sort(opReturnValueHandlers, new Comparator() { + Arrays.sort(opReturnValueHandlers, new Comparator() { @Override - public int compare(OperationReturnValueHandler o1, OperationReturnValueHandler o2) { + public int compare(OperationResultHandle o1, OperationResultHandle o2) { return o1.getOperationIndex() - o2.getOperationIndex(); } }); @@ -78,31 +84,59 @@ public class PreparedTx implements PreparedTransaction { @Override public TransactionResponse commit() { + stateManager.commit(); + TransactionResponse txResponse = null; try { 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: 出错时清理交易上下文,释放与交易关联对异步等待资源,避免当前线程死锁; - } } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ShortValueHolder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ShortValueHolder.java index 70343c4a..f9867d65 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ShortValueHolder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ShortValueHolder.java @@ -1,43 +1,22 @@ 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); } /** - * 等待结果合约调用的结果返回; + * 获取值;
* - * @return - */ - public short get() { - return (short) super.getValue(); - } - - /** - * 等待结果合约调用的结果返回; + * 此方法不堵塞,调用立即返回;
* - * @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 - * @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; } + } \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TransactionCancelledExeption.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TransactionCancelledExeption.java new file mode 100644 index 00000000..69e37b24 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TransactionCancelledExeption.java @@ -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); + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java index bf99acdb..cb32c1bd 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java @@ -51,7 +51,7 @@ public class TxBuilder implements TransactionBuilder { return txContent; } - public Collection getReturnValuehandlers() { + public Collection getReturnValuehandlers() { return opFactory.getReturnValuetHandlers(); } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxStateManager.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxStateManager.java new file mode 100644 index 00000000..db799f1d --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxStateManager.java @@ -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 此次操作前是否已经处于关闭状态;
+ * 如果返回 true ,则表示之前已经处于关闭状态,此次操作将被忽略;
+ * 如果返回 fasle,则表示之前处于非关闭状态,此次操作将切换为关闭状态; + */ + public boolean close() { + if (state == State.CLOSED) { + return true; + } + state = State.CLOSED; + return false; + } + + private static enum State { + + /** + * 可操作; + */ + OPERABLE, + + /** + * 就绪; + */ + PREPARED, + + /** + * 已提交; + */ + COMMITTED, + + /** + * 已关闭; + */ + CLOSED + + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java index cbe7688f..9777d238 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java @@ -1,5 +1,8 @@ package com.jd.blockchain.transaction; +import java.io.IOException; +import java.util.Collection; + import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.PreparedTransaction; import com.jd.blockchain.ledger.TransactionRequestBuilder; @@ -12,8 +15,10 @@ public class TxTemplate implements TransactionTemplate { private TransactionService txService; + private TxStateManager stateManager; public TxTemplate(HashDigest ledgerHash, TransactionService txService) { + this.stateManager = new TxStateManager(); this.txBuilder = new TxBuilder(ledgerHash); this.txService = txService; } @@ -25,43 +30,63 @@ public class TxTemplate implements TransactionTemplate { @Override public PreparedTransaction prepare() { + stateManager.prepare(); TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest(); - return new PreparedTx(txReqBuilder, txService, txBuilder.getReturnValuehandlers()); + return new PreparedTx(stateManager, txReqBuilder, txService, txBuilder.getReturnValuehandlers()); } @Override public UserRegisterOperationBuilder users() { + stateManager.operate(); return txBuilder.users(); } @Override public DataAccountRegisterOperationBuilder dataAccounts() { + stateManager.operate(); return txBuilder.dataAccounts(); } - + @Override public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) { + stateManager.operate(); return txBuilder.dataAccount(accountAddress); } @Override public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) { + stateManager.operate(); return txBuilder.dataAccount(accountAddress); } @Override public ContractCodeDeployOperationBuilder contracts() { + stateManager.operate(); return txBuilder.contracts(); } @Override public T contract(Bytes address, Class contractIntf) { + stateManager.operate(); return txBuilder.contract(address, contractIntf); } @Override public T contract(String address, Class contractIntf) { + stateManager.operate(); return txBuilder.contract(address, contractIntf); } + @Override + public void close() throws IOException { + if (!stateManager.close()) { + Collection handlers = txBuilder.getReturnValuehandlers(); + if (handlers.size() > 0) { + TransactionCancelledExeption error = new TransactionCancelledExeption("Transaction template has been cancelled!"); + for (OperationResultHandle handle : handlers) { + handle.complete(error); + } + } + } + } } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolder.java deleted file mode 100644 index 6f6db109..00000000 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolder.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.jd.blockchain.transaction; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -public class ValueHolder 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); - } - } \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolderBase.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolderBase.java deleted file mode 100644 index 41d32f4e..00000000 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolderBase.java +++ /dev/null @@ -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); - } - } - } \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolderWrapper.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolderWrapper.java new file mode 100644 index 00000000..42c4f86b --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ValueHolderWrapper.java @@ -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(); + } + + /** + * 获取值;
+ * + * 此方法不堵塞,调用立即返回;
+ * + * 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 null; + * + * @return + */ + protected Object getValue() { + return valueHolder.getResult(); + } + + public void addCompletedListener(OperationCompletedListener listener) { + valueHolder.addCompletedListener(listener); + } +} \ No newline at end of file diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractEventSendOpTemplateTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractEventSendOpTemplateTest.java index fb197953..5bcba094 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractEventSendOpTemplateTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractEventSendOpTemplateTest.java @@ -8,21 +8,22 @@ */ 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.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.DataAccountKVSetOperation; import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.transaction.ContractEventSendOpTemplate; -import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; 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 @@ -32,34 +33,36 @@ import static org.junit.Assert.assertEquals; 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 ------"); + } } \ No newline at end of file diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DataAccountKVSetOpTemplateTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DataAccountKVSetOpTemplateTest.java index 005af7c6..cb77963c 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DataAccountKVSetOpTemplateTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DataAccountKVSetOpTemplateTest.java @@ -16,7 +16,7 @@ import org.junit.Test; import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.ledger.BytesValueEntry; +import com.jd.blockchain.ledger.BytesData; import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; @@ -42,11 +42,11 @@ public class DataAccountKVSetOpTemplateTest { String accountAddress = "zhangsandhakhdkah"; data = new DataAccountKVSetOpTemplate(Bytes.fromString(accountAddress)); KVData kvData1 = - new KVData("test1", BytesValueEntry.fromText("zhangsan"), 9999L); + new KVData("test1", BytesData.fromText("zhangsan"), 9999L); KVData kvData2 = - new KVData("test2", BytesValueEntry.fromText("lisi"), 9990L); + new KVData("test2", BytesData.fromText("lisi"), 9990L); KVData kvData3 = - new KVData("test3", BytesValueEntry.fromText("wangwu"), 1990L); + new KVData("test3", BytesData.fromText("wangwu"), 1990L); data.set(kvData1); data.set(kvData2); data.set(kvData3); diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/KVDataTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/KVDataTest.java index 39824505..229c308d 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/KVDataTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/KVDataTest.java @@ -16,7 +16,7 @@ import org.junit.Test; import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.ledger.BytesValueEntry; +import com.jd.blockchain.ledger.BytesData; import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; import com.jd.blockchain.transaction.KVData; @@ -38,7 +38,7 @@ public class KVDataTest { byte[] value = "test-value".getBytes(); long expectedVersion = 9999L; - kvData = new KVData(key, BytesValueEntry.fromBytes(value), expectedVersion); + kvData = new KVData(key, BytesData.fromBytes(value), expectedVersion); } @Test diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java index 1eac59c7..5419a531 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java @@ -31,346 +31,348 @@ import java.lang.reflect.Field; 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 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; + } + } } \ No newline at end of file diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java index 65074fc6..164c8bff 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java @@ -11,7 +11,7 @@ import com.jd.blockchain.ledger.PreparedTransaction; import com.jd.blockchain.ledger.TransactionResponse; import com.jd.blockchain.ledger.TransactionTemplate; import com.jd.blockchain.transaction.LongValueHolder; -import com.jd.blockchain.transaction.ValueHolder; +import com.jd.blockchain.transaction.GenericValueHolder; import com.jd.blockchain.utils.Bytes; 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); // 使用合约创建 TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); - ValueHolder result = decode(transferContract.readAll(address, account)); + GenericValueHolder result = decode(transferContract.readAll(address, account)); commit(txTpl); return result.get(); } @@ -122,7 +122,7 @@ public class SDK_Contract_Demo extends SDK_Base_Demo { TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); // 使用合约创建 TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); - ValueHolder result = decode(transferContract.transfer(address, from, to, money)); + GenericValueHolder result = decode(transferContract.transfer(address, from, to, money)); commit(txTpl); return result.get(); } @@ -142,7 +142,7 @@ public class SDK_Contract_Demo extends SDK_Base_Demo { if (useContract) { // 使用合约创建 TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); - ValueHolder result = decode(transferContract.create(address, account, money)); + GenericValueHolder result = decode(transferContract.create(address, account, money)); commit(txTpl); return result.get(); } else { diff --git a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDKDemo_Contract_Test.java b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDKDemo_Contract_Test.java index 57f7d947..e99c3bb7 100644 --- a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDKDemo_Contract_Test.java +++ b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDKDemo_Contract_Test.java @@ -20,7 +20,7 @@ import com.jd.blockchain.sdk.client.GatewayServiceFactory; import com.jd.blockchain.sdk.samples.SDKDemo_Constant; import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.transaction.LongValueHolder; -import com.jd.blockchain.transaction.ValueHolder; +import com.jd.blockchain.transaction.GenericValueHolder; import com.jd.blockchain.utils.Bytes; public class SDKDemo_Contract_Test { @@ -108,7 +108,7 @@ public class SDKDemo_Contract_Test { TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); // 使用合约创建 TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); - ValueHolder result = decode(transferContract.readAll(address, account)); + GenericValueHolder result = decode(transferContract.readAll(address, account)); commit(txTpl); return result.get(); } @@ -126,7 +126,7 @@ public class SDKDemo_Contract_Test { TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); // 使用合约创建 TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); - ValueHolder result = decode(transferContract.transfer(address, from, to, money)); + GenericValueHolder result = decode(transferContract.transfer(address, from, to, money)); commit(txTpl); return result.get(); } @@ -146,7 +146,7 @@ public class SDKDemo_Contract_Test { if (useContract) { // 使用合约创建 TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); - ValueHolder result = decode(transferContract.create(address, account, money)); + GenericValueHolder result = decode(transferContract.create(address, account, money)); commit(txTpl); return result.get(); } else { diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java index 1e318f97..cf91fbfa 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java @@ -24,6 +24,7 @@ import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; +import com.jd.blockchain.ledger.BytesDataList; import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.DataAccountRegisterOperation; import com.jd.blockchain.ledger.LedgerBlock; @@ -143,8 +144,9 @@ public class LedgerPerformanceTest { 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) { @@ -177,8 +179,9 @@ public class LedgerPerformanceTest { * @param batchCount * @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); ConsoleUtils.info("\r\n\r\n================= 准备测试交易 [注册用户] ================="); @@ -273,7 +276,7 @@ public class LedgerPerformanceTest { * @param silent */ 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); ConsoleUtils.info("\r\n\r\n================= 准备测试交易 [执行合约] ================="); @@ -285,8 +288,8 @@ public class LedgerPerformanceTest { // 准备请求 int totalCount = batchSize * batchCount; - List contractTxList = prepareContractRequests(ledgerHash, - adminKey, totalCount, false, txProc); + List contractTxList = prepareContractRequests(ledgerHash, adminKey, totalCount, false, + txProc); Prompter consolePrompter = new PresetAnswerPrompter("N"); @@ -303,6 +306,7 @@ public class LedgerPerformanceTest { } } + private static void execPerformanceTest(int batchCount, int batchSize, List txList, LedgerRepository ledger, LedgerManager ledgerManager, DefaultOperationHandleRegisteration opHandler, boolean statistic) { @@ -407,8 +411,7 @@ public class LedgerPerformanceTest { // BlockchainKeyPair dataAccountKey = // BlockchainKeyGenerator.getInstance().generate(); 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(); reqBuilder.signAsEndpoint(adminKey); txList.add(reqBuilder.buildRequest()); @@ -426,8 +429,9 @@ public class LedgerPerformanceTest { public static ConsensusProvider getConsensusProvider(String provider) { return ConsensusProviders.getProvider(provider); } - public static List prepareContractRequests(HashDigest ledgerHash, - AsymmetricKeypair adminKey, int count, boolean statistic, TransactionBatchProcessor txProc) { + + public static List prepareContractRequests(HashDigest ledgerHash, AsymmetricKeypair adminKey, + int count, boolean statistic, TransactionBatchProcessor txProc) { // deploy contract byte[] chainCode; @@ -436,7 +440,7 @@ public class LedgerPerformanceTest { InputStream input = LedgerPerformanceTest.class.getClassLoader().getResourceAsStream("example1.jar"); chainCode = new byte[input.available()]; input.read(chainCode); - }catch (IOException e){ + } catch (IOException e) { e.printStackTrace(); return null; } @@ -457,10 +461,10 @@ public class LedgerPerformanceTest { System.out.println(resp.isSuccess()); TransactionBatchResultHandle handle = txProc.prepare(); handle.commit(); - try{ + try { Thread.sleep(1000); - } catch (Exception e){ + } catch (Exception e) { e.printStackTrace(); } @@ -468,8 +472,9 @@ public class LedgerPerformanceTest { List txList = new ArrayList<>(); for (int i = 0; i < count; i++) { 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()); reqBuilder = txbuilder.prepareRequest(); reqBuilder.signAsEndpoint(adminKey); @@ -485,7 +490,8 @@ public class LedgerPerformanceTest { 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 serviceRegisterMap = new ConcurrentHashMap<>(); Prompter consolePrompter = new PresetAnswerPrompter("N"); // new ConsolePrompter(); diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java index 463d525f..b04ce95c 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java @@ -29,7 +29,6 @@ import org.apache.commons.io.FileUtils; import org.springframework.core.io.ClassPathResource; import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.contract.ContractSerializeUtils; import com.jd.blockchain.contract.ReadContract; import com.jd.blockchain.crypto.AddressEncoding; 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.DbConnectionFactory; 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.concurrent.ThreadInvoker; import com.jd.blockchain.utils.net.NetworkAddress; @@ -586,7 +585,7 @@ public class IntegrationBase { ReadContract readContract1 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); - ValueHolder result1 = decode(readContract1.read(newDataAccount.getAddress().toBase58(), key1)); + GenericValueHolder result1 = decode(readContract1.read(newDataAccount.getAddress().toBase58(), key1)); ReadContract readContract2 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); @@ -594,7 +593,7 @@ public class IntegrationBase { ReadContract readContract3 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); - ValueHolder result3 = decode(readContract3.readVersion(newDataAccount.getAddress().toBase58(), key2)); + GenericValueHolder result3 = decode(readContract3.readVersion(newDataAccount.getAddress().toBase58(), key2)); // 签名; PreparedTransaction contractPtx = txContract.prepare(); @@ -610,10 +609,10 @@ public class IntegrationBase { 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); diff --git a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java index 421e1507..49acbb2b 100644 --- a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java +++ b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java @@ -6,7 +6,6 @@ import java.util.concurrent.ConcurrentHashMap; import com.jd.blockchain.contract.ContractEventContext; import com.jd.blockchain.contract.ContractException; -import com.jd.blockchain.contract.ContractSerializeUtils; import com.jd.blockchain.contract.EventProcessingAware; import com.jd.blockchain.contract.LedgerContext; import com.jd.blockchain.crypto.HashDigest; @@ -75,7 +74,7 @@ public class MockerContractExeHandle implements OperationHandle { } // No return value; - return ContractSerializeUtils.serialize(result); + return null; } @Override diff --git a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/proxy/ContractProxy.java b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/proxy/ContractProxy.java index c01d4a26..7d1f7b47 100644 --- a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/proxy/ContractProxy.java +++ b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/proxy/ContractProxy.java @@ -1,88 +1,88 @@ 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.ContractEvent; -import com.jd.blockchain.contract.ContractSerializeUtils; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.BytesValueEncoding; import com.jd.blockchain.ledger.OperationResult; -import com.jd.blockchain.ledger.OperationResultData; import com.jd.blockchain.ledger.TransactionRequest; import com.jd.blockchain.mocker.MockerNodeContext; import com.jd.blockchain.mocker.handler.MockerContractExeHandle; import com.jd.blockchain.transaction.TxBuilder; -import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; - public class ContractProxy 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; + } } diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/DefaultExceptionHandle.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/DefaultExceptionHandle.java index 998e619c..5ff08720 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/DefaultExceptionHandle.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/DefaultExceptionHandle.java @@ -5,8 +5,6 @@ import java.lang.reflect.Method; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.jd.blockchain.utils.console.CommandConsole; - public class DefaultExceptionHandle implements ExceptionHandle { @Override @@ -21,9 +19,8 @@ public class DefaultExceptionHandle implements ExceptionHandle implements Disposable { } public EventMulticaster(Class listenerClass, Logger errorLogger) { - this(listenerClass, new ExceptionLoggingHandle(errorLogger)); + this(listenerClass, new RethrowExceptionHandler(errorLogger)); } @SuppressWarnings("unchecked") public EventMulticaster(Class listenerClass, ExceptionHandle exHandle) { + if (!listenerClass.isInterface()) { + throw new IllegalArgumentException("The specified class of listener does not represent an interface!"); + } // 初始化错误处理器; - this.exHandle = exHandle == null ? new DefaultExceptionHandle() : exHandle; + this.exHandle = exHandle == null + ? new RethrowExceptionHandler(LoggerFactory.getLogger(EventMulticaster.class)) + : exHandle; // 解析出不支持的方法; Method[] methods = ReflectionUtils.getAllDeclaredMethods(listenerClass); - List supMths = new LinkedList(); + List supMths = new ArrayList(); for (Method method : methods) { if (method.getDeclaringClass() == Object.class) { // 不支持 Object 方法; @@ -86,14 +92,14 @@ public class EventMulticaster implements Disposable { throw new UnsupportedOperationException("Unsupported method for event multicasting!"); } } - - protected void doNotify(List listeners, Method method, Object[] args){ + + protected void doNotify(List listeners, Method method, Object[] args) { for (TListener listener : listeners) { doNotifySingle(listener, method, args); } } - - protected void doNotifySingle(TListener listener, Method method, Object[] args){ + + protected void doNotifySingle(TListener listener, Method method, Object[] args) { try { ReflectionUtils.invokeMethod(method, listener, args); } catch (Exception e) { @@ -104,12 +110,12 @@ public class EventMulticaster implements Disposable { public void addListener(TListener listener) { listeners.add(listener); } - + public void removeListener(TListener listener) { listeners.remove(listener); } - public TListener broadcast() { + public TListener getBroadcaster() { return listenerProxy; }