@@ -4,7 +4,7 @@ import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
import com.jd.blockchain.ledger.AccountHeader; | import com.jd.blockchain.ledger.AccountHeader; | ||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
import com.jd.blockchain.ledger.BytesValueEntry; | |||||
import com.jd.blockchain.ledger.BytesData; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
public class ContractAccount implements AccountHeader { | public class ContractAccount implements AccountHeader { | ||||
@@ -43,7 +43,7 @@ public class ContractAccount implements AccountHeader { | |||||
} | } | ||||
public long setChaincode(byte[] chaincode, long version) { | public long setChaincode(byte[] chaincode, long version) { | ||||
BytesValue bytesValue = BytesValueEntry.fromBytes(chaincode); | |||||
BytesValue bytesValue = BytesData.fromBytes(chaincode); | |||||
return accBase.setBytes(CHAIN_CODE_KEY, bytesValue, version); | return accBase.setBytes(CHAIN_CODE_KEY, bytesValue, version); | ||||
} | } | ||||
@@ -60,18 +60,18 @@ public class ContractAccount implements AccountHeader { | |||||
} | } | ||||
public long setProperty(Bytes key, String value, long version) { | public long setProperty(Bytes key, String value, long version) { | ||||
BytesValue bytesValue = BytesValueEntry.fromText(value); | |||||
BytesValue bytesValue = BytesData.fromText(value); | |||||
return accBase.setBytes(encodePropertyKey(key), bytesValue, version); | return accBase.setBytes(encodePropertyKey(key), bytesValue, version); | ||||
} | } | ||||
public String getProperty(Bytes key) { | public String getProperty(Bytes key) { | ||||
BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key)); | BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key)); | ||||
return BytesValueEntry.toText(bytesValue); | |||||
return BytesData.toText(bytesValue); | |||||
} | } | ||||
public String getProperty(Bytes key, long version) { | public String getProperty(Bytes key, long version) { | ||||
BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key), version); | BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key), version); | ||||
return BytesValueEntry.toText(bytesValue); | |||||
return BytesData.toText(bytesValue); | |||||
} | } | ||||
private Bytes encodePropertyKey(Bytes key) { | private Bytes encodePropertyKey(Bytes key) { | ||||
@@ -6,7 +6,7 @@ import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
import com.jd.blockchain.ledger.AccountHeader; | import com.jd.blockchain.ledger.AccountHeader; | ||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
import com.jd.blockchain.ledger.BytesValueEntry; | |||||
import com.jd.blockchain.ledger.BytesData; | |||||
import com.jd.blockchain.ledger.KVDataEntry; | import com.jd.blockchain.ledger.KVDataEntry; | ||||
import com.jd.blockchain.ledger.KVDataObject; | import com.jd.blockchain.ledger.KVDataObject; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
@@ -49,12 +49,12 @@ public class DataAccount implements AccountHeader, MerkleProvable { | |||||
public long setBytes(Bytes key, String value, long version) { | public long setBytes(Bytes key, String value, long version) { | ||||
BytesValue bytesValue = BytesValueEntry.fromText(value); | |||||
BytesValue bytesValue = BytesData.fromText(value); | |||||
return baseAccount.setBytes(key, bytesValue, version); | return baseAccount.setBytes(key, bytesValue, version); | ||||
} | } | ||||
public long setBytes(Bytes key, byte[] value, long version) { | public long setBytes(Bytes key, byte[] value, long version) { | ||||
BytesValue bytesValue = BytesValueEntry.fromBytes(value); | |||||
BytesValue bytesValue = BytesData.fromBytes(value); | |||||
return baseAccount.setBytes(key, bytesValue, version); | return baseAccount.setBytes(key, bytesValue, version); | ||||
} | } | ||||
@@ -3,7 +3,7 @@ package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
import com.jd.blockchain.ledger.BytesValueEntry; | |||||
import com.jd.blockchain.ledger.BytesData; | |||||
import com.jd.blockchain.ledger.UserInfo; | import com.jd.blockchain.ledger.UserInfo; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
@@ -50,12 +50,12 @@ public class UserAccount implements UserInfo { | |||||
public long setDataPubKey(PubKey pubKey) { | public long setDataPubKey(PubKey pubKey) { | ||||
byte[] pkBytes = pubKey.toBytes(); | byte[] pkBytes = pubKey.toBytes(); | ||||
return baseAccount.setBytes(DATA_PUB_KEY, BytesValueEntry.fromBytes(pkBytes), -1); | |||||
return baseAccount.setBytes(DATA_PUB_KEY, BytesData.fromBytes(pkBytes), -1); | |||||
} | } | ||||
public long setDataPubKey(PubKey pubKey, long version) { | public long setDataPubKey(PubKey pubKey, long version) { | ||||
byte[] pkBytes = pubKey.toBytes(); | byte[] pkBytes = pubKey.toBytes(); | ||||
return baseAccount.setBytes(DATA_PUB_KEY, BytesValueEntry.fromBytes(pkBytes), version); | |||||
return baseAccount.setBytes(DATA_PUB_KEY, BytesData.fromBytes(pkBytes), version); | |||||
} | } | ||||
public long setProperty(String key, String value, long version) { | public long setProperty(String key, String value, long version) { | ||||
@@ -63,7 +63,7 @@ public class UserAccount implements UserInfo { | |||||
} | } | ||||
public long setProperty(Bytes key, String value, long version) { | public long setProperty(Bytes key, String value, long version) { | ||||
return baseAccount.setBytes(encodePropertyKey(key), BytesValueEntry.fromText(value), version); | |||||
return baseAccount.setBytes(encodePropertyKey(key), BytesData.fromText(value), version); | |||||
} | } | ||||
public String getProperty(Bytes key) { | public String getProperty(Bytes key) { | ||||
@@ -8,7 +8,7 @@ import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.AccountHeader; | import com.jd.blockchain.ledger.AccountHeader; | ||||
import com.jd.blockchain.ledger.BlockchainIdentity; | import com.jd.blockchain.ledger.BlockchainIdentity; | ||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
import com.jd.blockchain.ledger.BytesValueEntry; | |||||
import com.jd.blockchain.ledger.BytesData; | |||||
import com.jd.blockchain.ledger.DataAccountKVSetOperation; | import com.jd.blockchain.ledger.DataAccountKVSetOperation; | ||||
import com.jd.blockchain.ledger.DataAccountRegisterOperation; | import com.jd.blockchain.ledger.DataAccountRegisterOperation; | ||||
import com.jd.blockchain.ledger.KVDataEntry; | import com.jd.blockchain.ledger.KVDataEntry; | ||||
@@ -279,7 +279,7 @@ public class ContractLedgerContext implements LedgerContext { | |||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { | public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromText(value); | |||||
BytesValue bytesValue = BytesData.fromText(value); | |||||
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | ||||
handle(op); | handle(op); | ||||
return this; | return this; | ||||
@@ -287,7 +287,7 @@ public class ContractLedgerContext implements LedgerContext { | |||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { | public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromBytes(value); | |||||
BytesValue bytesValue = BytesData.fromBytes(value); | |||||
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | ||||
handle(op); | handle(op); | ||||
return this; | return this; | ||||
@@ -295,7 +295,7 @@ public class ContractLedgerContext implements LedgerContext { | |||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { | public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromInt64(value); | |||||
BytesValue bytesValue = BytesData.fromInt64(value); | |||||
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | ||||
handle(op); | handle(op); | ||||
return this; | return this; | ||||
@@ -312,7 +312,7 @@ public class ContractLedgerContext implements LedgerContext { | |||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { | public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromJSON(value); | |||||
BytesValue bytesValue = BytesData.fromJSON(value); | |||||
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | ||||
handle(op); | handle(op); | ||||
return this; | return this; | ||||
@@ -320,7 +320,7 @@ public class ContractLedgerContext implements LedgerContext { | |||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { | public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromXML(value); | |||||
BytesValue bytesValue = BytesData.fromXML(value); | |||||
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | ||||
handle(op); | handle(op); | ||||
return this; | return this; | ||||
@@ -328,7 +328,7 @@ public class ContractLedgerContext implements LedgerContext { | |||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { | public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromBytes(value); | |||||
BytesValue bytesValue = BytesData.fromBytes(value); | |||||
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | ||||
handle(op); | handle(op); | ||||
return this; | return this; | ||||
@@ -336,7 +336,7 @@ public class ContractLedgerContext implements LedgerContext { | |||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { | public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromImage(value); | |||||
BytesValue bytesValue = BytesData.fromImage(value); | |||||
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | ||||
handle(op); | handle(op); | ||||
return this; | return this; | ||||
@@ -344,7 +344,7 @@ public class ContractLedgerContext implements LedgerContext { | |||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { | public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromTimestamp(value); | |||||
BytesValue bytesValue = BytesData.fromTimestamp(value); | |||||
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); | ||||
handle(op); | handle(op); | ||||
return this; | return this; | ||||
@@ -12,7 +12,7 @@ import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; | |||||
import com.jd.blockchain.crypto.service.sm.SMCryptoService; | import com.jd.blockchain.crypto.service.sm.SMCryptoService; | ||||
import com.jd.blockchain.ledger.BlockchainKeyGenerator; | import com.jd.blockchain.ledger.BlockchainKeyGenerator; | ||||
import com.jd.blockchain.ledger.BlockchainKeypair; | import com.jd.blockchain.ledger.BlockchainKeypair; | ||||
import com.jd.blockchain.ledger.BytesValueEntry; | |||||
import com.jd.blockchain.ledger.BytesData; | |||||
import com.jd.blockchain.ledger.core.BaseAccount; | import com.jd.blockchain.ledger.core.BaseAccount; | ||||
import com.jd.blockchain.ledger.core.CryptoConfig; | import com.jd.blockchain.ledger.core.CryptoConfig; | ||||
import com.jd.blockchain.storage.service.utils.MemoryKVStorage; | import com.jd.blockchain.storage.service.utils.MemoryKVStorage; | ||||
@@ -53,33 +53,33 @@ public class BaseAccountTest { | |||||
assertFalse(baseAccount.isReadonly()); | assertFalse(baseAccount.isReadonly()); | ||||
// 在空白状态下写入数据; | // 在空白状态下写入数据; | ||||
long v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A"), 0); | |||||
long v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), 0); | |||||
// 预期失败; | // 预期失败; | ||||
assertEquals(-1, v); | assertEquals(-1, v); | ||||
v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A"), 1); | |||||
v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), 1); | |||||
// 预期失败; | // 预期失败; | ||||
assertEquals(-1, v); | assertEquals(-1, v); | ||||
v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A"), -1); | |||||
v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A"), -1); | |||||
// 预期成功; | // 预期成功; | ||||
assertEquals(0, v); | assertEquals(0, v); | ||||
v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A-1"), -1); | |||||
v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A-1"), -1); | |||||
// 已经存在版本,指定版本号-1,预期导致失败; | // 已经存在版本,指定版本号-1,预期导致失败; | ||||
assertEquals(-1, v); | assertEquals(-1, v); | ||||
baseAccount.commit(); | baseAccount.commit(); | ||||
v = 0; | v = 0; | ||||
for (int i = 0; i < 10; i++) { | for (int i = 0; i < 10; i++) { | ||||
long s = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A_" + i), v); | |||||
long s = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A_" + i), v); | |||||
baseAccount.commit(); | baseAccount.commit(); | ||||
// 预期成功; | // 预期成功; | ||||
assertEquals(v + 1, s); | assertEquals(v + 1, s); | ||||
v++; | v++; | ||||
} | } | ||||
v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A_" + v), v + 1); | |||||
v = baseAccount.setBytes(Bytes.fromString("A"), BytesData.fromText("VALUE_A_" + v), v + 1); | |||||
// 预期成功; | // 预期成功; | ||||
assertEquals(-1, v); | assertEquals(-1, v); | ||||
@@ -21,7 +21,7 @@ import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.BlockchainKeyGenerator; | import com.jd.blockchain.ledger.BlockchainKeyGenerator; | ||||
import com.jd.blockchain.ledger.BlockchainKeypair; | import com.jd.blockchain.ledger.BlockchainKeypair; | ||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
import com.jd.blockchain.ledger.BytesValueEntry; | |||||
import com.jd.blockchain.ledger.BytesData; | |||||
import com.jd.blockchain.ledger.EndpointRequest; | import com.jd.blockchain.ledger.EndpointRequest; | ||||
import com.jd.blockchain.ledger.LedgerBlock; | import com.jd.blockchain.ledger.LedgerBlock; | ||||
import com.jd.blockchain.ledger.LedgerInitSetting; | import com.jd.blockchain.ledger.LedgerInitSetting; | ||||
@@ -103,6 +103,7 @@ public class ContractInvokingTest { | |||||
Random rand = new Random(); | Random rand = new Random(); | ||||
TxBuilder txBuilder = new TxBuilder(ledgerHash); | TxBuilder txBuilder = new TxBuilder(ledgerHash); | ||||
TestContract contractProxy = txBuilder.contract(contractAddress, TestContract.class); | TestContract contractProxy = txBuilder.contract(contractAddress, TestContract.class); | ||||
TestContract contractProxy1 = txBuilder.contract(contractAddress, TestContract.class); | |||||
String asset = "AK"; | String asset = "AK"; | ||||
long issueAmount = rand.nextLong(); | long issueAmount = rand.nextLong(); | ||||
@@ -120,7 +121,7 @@ public class ContractInvokingTest { | |||||
assertEquals(1, opResults.length); | assertEquals(1, opResults.length); | ||||
assertEquals(0, opResults[0].getIndex()); | assertEquals(0, opResults[0].getIndex()); | ||||
byte[] expectedRetnBytes = BinaryProtocol.encode(BytesValueEntry.fromInt64(issueAmount), BytesValue.class); | |||||
byte[] expectedRetnBytes = BinaryProtocol.encode(BytesData.fromInt64(issueAmount), BytesValue.class); | |||||
byte[] reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class); | byte[] reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class); | ||||
assertArrayEquals(expectedRetnBytes, reallyRetnBytes); | assertArrayEquals(expectedRetnBytes, reallyRetnBytes); | ||||
@@ -1,5 +1,6 @@ | |||||
package test.com.jd.blockchain.ledger; | package test.com.jd.blockchain.ledger; | ||||
import static org.junit.Assert.assertArrayEquals; | |||||
import static org.junit.Assert.assertEquals; | import static org.junit.Assert.assertEquals; | ||||
import static org.junit.Assert.assertFalse; | import static org.junit.Assert.assertFalse; | ||||
import static org.junit.Assert.assertNotNull; | import static org.junit.Assert.assertNotNull; | ||||
@@ -10,10 +11,13 @@ import java.util.Random; | |||||
import org.junit.Test; | import org.junit.Test; | ||||
import com.jd.blockchain.binaryproto.BinaryProtocol; | |||||
import com.jd.blockchain.binaryproto.DataContractRegistry; | import com.jd.blockchain.binaryproto.DataContractRegistry; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.ledger.BlockchainKeyGenerator; | import com.jd.blockchain.ledger.BlockchainKeyGenerator; | ||||
import com.jd.blockchain.ledger.BlockchainKeypair; | import com.jd.blockchain.ledger.BlockchainKeypair; | ||||
import com.jd.blockchain.ledger.BytesDataList; | |||||
import com.jd.blockchain.ledger.BytesValueList; | |||||
import com.jd.blockchain.ledger.ContractCodeDeployOperation; | import com.jd.blockchain.ledger.ContractCodeDeployOperation; | ||||
import com.jd.blockchain.ledger.ContractEventSendOperation; | import com.jd.blockchain.ledger.ContractEventSendOperation; | ||||
import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
@@ -67,8 +71,8 @@ public class TransactionSetTest { | |||||
BlockchainKeypair dataKey = BlockchainKeyGenerator.getInstance().generate(); | BlockchainKeypair dataKey = BlockchainKeyGenerator.getInstance().generate(); | ||||
DataAccountRegisterOperation dataAccRegOp = txBuilder.dataAccounts().register(dataKey.getIdentity()); | DataAccountRegisterOperation dataAccRegOp = txBuilder.dataAccounts().register(dataKey.getIdentity()); | ||||
DataAccountKVSetOperation kvsetOP = txBuilder.dataAccount(dataKey.getAddress()) | |||||
.setText("A", "Value_A_0", -1).setText("B", "Value_B_0", -1).getOperation(); | |||||
DataAccountKVSetOperation kvsetOP = txBuilder.dataAccount(dataKey.getAddress()).setText("A", "Value_A_0", -1) | |||||
.setText("B", "Value_B_0", -1).getOperation(); | |||||
byte[] chainCode = new byte[128]; | byte[] chainCode = new byte[128]; | ||||
rand.nextBytes(chainCode); | rand.nextBytes(chainCode); | ||||
@@ -76,7 +80,7 @@ public class TransactionSetTest { | |||||
ContractCodeDeployOperation contractDplOP = txBuilder.contracts().deploy(contractKey.getIdentity(), chainCode); | ContractCodeDeployOperation contractDplOP = txBuilder.contracts().deploy(contractKey.getIdentity(), chainCode); | ||||
ContractEventSendOperation contractEvtSendOP = txBuilder.contractEvents().send(contractKey.getAddress(), "test", | ContractEventSendOperation contractEvtSendOP = txBuilder.contractEvents().send(contractKey.getAddress(), "test", | ||||
"TestContractArgs".getBytes()); | |||||
BytesDataList.singleText("TestContractArgs")); | |||||
TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest(); | TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest(); | ||||
@@ -98,7 +102,8 @@ public class TransactionSetTest { | |||||
txSnapshot.setContractAccountSetHash(contractAccountSetHash); | txSnapshot.setContractAccountSetHash(contractAccountSetHash); | ||||
long blockHeight = 8922L; | long blockHeight = 8922L; | ||||
LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txReq, TransactionState.SUCCESS, txSnapshot, null); | |||||
LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txReq, TransactionState.SUCCESS, txSnapshot, | |||||
null); | |||||
txset.add(tx); | txset.add(tx); | ||||
assertTrue(txset.isUpdated()); | assertTrue(txset.isUpdated()); | ||||
@@ -172,7 +177,8 @@ public class TransactionSetTest { | |||||
for (int i = 0; i < acutualKVWriteSet.length; i++) { | for (int i = 0; i < acutualKVWriteSet.length; i++) { | ||||
assertEquals(expKVWriteSet[i].getKey(), acutualKVWriteSet[i].getKey()); | assertEquals(expKVWriteSet[i].getKey(), acutualKVWriteSet[i].getKey()); | ||||
assertEquals(expKVWriteSet[i].getExpectedVersion(), acutualKVWriteSet[i].getExpectedVersion()); | assertEquals(expKVWriteSet[i].getExpectedVersion(), acutualKVWriteSet[i].getExpectedVersion()); | ||||
assertTrue(BytesUtils.equals(expKVWriteSet[i].getValue().getValue().toBytes(), acutualKVWriteSet[i].getValue().getValue().toBytes())); | |||||
assertTrue(BytesUtils.equals(expKVWriteSet[i].getValue().getValue().toBytes(), | |||||
acutualKVWriteSet[i].getValue().getValue().toBytes())); | |||||
} | } | ||||
ContractCodeDeployOperation actualContractDplOp = (ContractCodeDeployOperation) actualOperations[3]; | ContractCodeDeployOperation actualContractDplOp = (ContractCodeDeployOperation) actualOperations[3]; | ||||
@@ -184,8 +190,14 @@ public class TransactionSetTest { | |||||
assertEquals(contractEvtSendOP.getContractAddress(), actualContractEvtSendOp.getContractAddress()); | assertEquals(contractEvtSendOP.getContractAddress(), actualContractEvtSendOp.getContractAddress()); | ||||
assertEquals(contractEvtSendOP.getEvent(), actualContractEvtSendOp.getEvent()); | assertEquals(contractEvtSendOP.getEvent(), actualContractEvtSendOp.getEvent()); | ||||
assertEquals("test", actualContractEvtSendOp.getEvent()); | assertEquals("test", actualContractEvtSendOp.getEvent()); | ||||
assertTrue(BytesUtils.equals(contractEvtSendOP.getArgs(), actualContractEvtSendOp.getArgs())); | |||||
assertTrue(BytesUtils.equals("TestContractArgs".getBytes(), actualContractEvtSendOp.getArgs())); | |||||
byte[] expectedBytes = BinaryProtocol.encode(contractEvtSendOP.getArgs(), BytesValueList.class); | |||||
byte[] actualBytes = BinaryProtocol.encode(actualContractEvtSendOp.getArgs(), BytesValueList.class); | |||||
assertArrayEquals(expectedBytes, actualBytes); | |||||
expectedBytes = BinaryProtocol.encode(BytesDataList.singleText("TestContractArgs"), BytesValueList.class); | |||||
actualBytes = BinaryProtocol.encode(actualContractEvtSendOp.getArgs(), BytesValueList.class); | |||||
assertArrayEquals(expectedBytes, actualBytes); | |||||
} | } | ||||
} | } |
@@ -8,38 +8,38 @@ import com.jd.blockchain.utils.io.BytesUtils; | |||||
* @author huanghaiquan | * @author huanghaiquan | ||||
* | * | ||||
*/ | */ | ||||
public class BytesValueEntry implements BytesValue { | |||||
public class BytesData implements BytesValue { | |||||
DataType type; | DataType type; | ||||
Bytes value; | Bytes value; | ||||
private BytesValueEntry(DataType type, byte[] bytes) { | |||||
private BytesData(DataType type, byte[] bytes) { | |||||
this.type = type; | this.type = type; | ||||
this.value = new Bytes(bytes); | this.value = new Bytes(bytes); | ||||
} | } | ||||
private BytesValueEntry(DataType type, Bytes bytes) { | |||||
private BytesData(DataType type, Bytes bytes) { | |||||
this.type = type; | this.type = type; | ||||
this.value = bytes; | this.value = bytes; | ||||
} | } | ||||
public static BytesValue fromType(DataType type, byte[] value) { | public static BytesValue fromType(DataType type, byte[] value) { | ||||
return new BytesValueEntry(type, value); | |||||
return new BytesData(type, value); | |||||
} | } | ||||
public static BytesValue fromBytes(byte[] value) { | public static BytesValue fromBytes(byte[] value) { | ||||
return new BytesValueEntry(DataType.BYTES, value); | |||||
return new BytesData(DataType.BYTES, value); | |||||
} | } | ||||
public static BytesValue fromBytes(Bytes value) { | public static BytesValue fromBytes(Bytes value) { | ||||
return new BytesValueEntry(DataType.BYTES, value); | |||||
return new BytesData(DataType.BYTES, value); | |||||
} | } | ||||
public static BytesValue fromImage(byte[] value) { | public static BytesValue fromImage(byte[] value) { | ||||
return new BytesValueEntry(DataType.IMG, value); | |||||
return new BytesData(DataType.IMG, value); | |||||
} | } | ||||
public static BytesValue fromImage(Bytes value) { | public static BytesValue fromImage(Bytes value) { | ||||
return new BytesValueEntry(DataType.IMG, value); | |||||
return new BytesData(DataType.IMG, value); | |||||
} | } | ||||
/** | /** | ||||
@@ -49,7 +49,7 @@ public class BytesValueEntry implements BytesValue { | |||||
* @return | * @return | ||||
*/ | */ | ||||
public static BytesValue fromText(String value) { | public static BytesValue fromText(String value) { | ||||
return new BytesValueEntry(DataType.TEXT, BytesUtils.toBytes(value)); | |||||
return new BytesData(DataType.TEXT, BytesUtils.toBytes(value)); | |||||
} | } | ||||
/** | /** | ||||
@@ -70,35 +70,35 @@ public class BytesValueEntry implements BytesValue { | |||||
} | } | ||||
public static BytesValue fromJSON(String value) { | public static BytesValue fromJSON(String value) { | ||||
return new BytesValueEntry(DataType.JSON, BytesUtils.toBytes(value)); | |||||
return new BytesData(DataType.JSON, BytesUtils.toBytes(value)); | |||||
} | } | ||||
public static BytesValue fromXML(String value) { | public static BytesValue fromXML(String value) { | ||||
return new BytesValueEntry(DataType.XML, BytesUtils.toBytes(value)); | |||||
return new BytesData(DataType.XML, BytesUtils.toBytes(value)); | |||||
} | } | ||||
public static BytesValue fromInt32(int value) { | public static BytesValue fromInt32(int value) { | ||||
return new BytesValueEntry(DataType.INT32, BytesUtils.toBytes(value)); | |||||
return new BytesData(DataType.INT32, BytesUtils.toBytes(value)); | |||||
} | } | ||||
public static BytesValue fromInt64(long value) { | public static BytesValue fromInt64(long value) { | ||||
return new BytesValueEntry(DataType.INT64, BytesUtils.toBytes(value)); | |||||
return new BytesData(DataType.INT64, BytesUtils.toBytes(value)); | |||||
} | } | ||||
public static BytesValue fromInt16(short value) { | public static BytesValue fromInt16(short value) { | ||||
return new BytesValueEntry(DataType.INT16, BytesUtils.toBytes(value)); | |||||
return new BytesData(DataType.INT16, BytesUtils.toBytes(value)); | |||||
} | } | ||||
public static BytesValue fromInt8(byte value) { | public static BytesValue fromInt8(byte value) { | ||||
return new BytesValueEntry(DataType.INT8, BytesUtils.toBytes(value)); | |||||
return new BytesData(DataType.INT8, BytesUtils.toBytes(value)); | |||||
} | } | ||||
public static BytesValue fromTimestamp(long value) { | public static BytesValue fromTimestamp(long value) { | ||||
return new BytesValueEntry(DataType.TIMESTAMP, BytesUtils.toBytes(value)); | |||||
return new BytesData(DataType.TIMESTAMP, BytesUtils.toBytes(value)); | |||||
} | } | ||||
public static BytesValue fromBoolean(boolean value) { | public static BytesValue fromBoolean(boolean value) { | ||||
return new BytesValueEntry(DataType.BOOLEAN, BytesUtils.toBytes(value)); | |||||
return new BytesData(DataType.BOOLEAN, BytesUtils.toBytes(value)); | |||||
} | } | ||||
@Override | @Override |
@@ -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)); | |||||
} | |||||
} |
@@ -1,5 +1,7 @@ | |||||
package com.jd.blockchain.ledger; | package com.jd.blockchain.ledger; | ||||
import java.io.Closeable; | |||||
import com.jd.blockchain.crypto.AsymmetricKeypair; | import com.jd.blockchain.crypto.AsymmetricKeypair; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
@@ -9,7 +11,7 @@ import com.jd.blockchain.crypto.HashDigest; | |||||
* @author huanghaiquan | * @author huanghaiquan | ||||
* | * | ||||
*/ | */ | ||||
public interface PreparedTransaction extends HashObject { | |||||
public interface PreparedTransaction extends HashObject, Closeable { | |||||
/** | /** | ||||
* 交易内容的 Hash; | * 交易内容的 Hash; | ||||
@@ -55,8 +57,4 @@ public interface PreparedTransaction extends HashObject { | |||||
*/ | */ | ||||
TransactionResponse commit(); | TransactionResponse commit(); | ||||
/** | |||||
* 取消交易;<br> | |||||
*/ | |||||
void cancel(); | |||||
} | } |
@@ -1,5 +1,7 @@ | |||||
package com.jd.blockchain.ledger; | package com.jd.blockchain.ledger; | ||||
import java.io.Closeable; | |||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.transaction.ClientOperator; | import com.jd.blockchain.transaction.ClientOperator; | ||||
@@ -9,7 +11,7 @@ import com.jd.blockchain.transaction.ClientOperator; | |||||
* @author huanghaiquan | * @author huanghaiquan | ||||
* | * | ||||
*/ | */ | ||||
public interface TransactionTemplate extends ClientOperator { | |||||
public interface TransactionTemplate extends ClientOperator, Closeable { | |||||
HashDigest getLedgerHash(); | HashDigest getLedgerHash(); | ||||
@@ -106,15 +106,15 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe | |||||
* | * | ||||
* @return | * @return | ||||
*/ | */ | ||||
public Collection<OperationReturnValueHandler> getReturnValuetHandlers() { | |||||
List<OperationReturnValueHandler> resultHandlers = new ArrayList<OperationReturnValueHandler>(); | |||||
public Collection<OperationResultHandle> getReturnValuetHandlers() { | |||||
List<OperationResultHandle> resultHandlers = new ArrayList<OperationResultHandle>(); | |||||
int index = 0; | int index = 0; | ||||
for (Operation op : operationList) { | for (Operation op : operationList) { | ||||
if (op instanceof ContractEventSendOperation) { | if (op instanceof ContractEventSendOperation) { | ||||
// 操作具有返回值,创建对应的结果处理器; | // 操作具有返回值,创建对应的结果处理器; | ||||
ContractEventSendOpTemplate opTemp = (ContractEventSendOpTemplate) op; | ContractEventSendOpTemplate opTemp = (ContractEventSendOpTemplate) op; | ||||
ContractInvocation invocation = opTemp.getInvocation(); | ContractInvocation invocation = opTemp.getInvocation(); | ||||
OperationReturnValueHandler retnHandler; | |||||
OperationResultHandle retnHandler; | |||||
if (invocation == null) { | if (invocation == null) { | ||||
retnHandler = new NullOperationReturnValueHandler(index); | retnHandler = new NullOperationReturnValueHandler(index); | ||||
} else { | } else { | ||||
@@ -278,7 +278,7 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe | |||||
* @author huanghaiquan | * @author huanghaiquan | ||||
* | * | ||||
*/ | */ | ||||
private static class NullOperationReturnValueHandler implements OperationReturnValueHandler { | |||||
private static class NullOperationReturnValueHandler implements OperationResultHandle { | |||||
private int operationIndex; | private int operationIndex; | ||||
@@ -292,10 +292,14 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe | |||||
} | } | ||||
@Override | @Override | ||||
public Object setReturnValue(BytesValue bytesValue) { | |||||
public Object complete(BytesValue bytesValue) { | |||||
return null; | return null; | ||||
} | } | ||||
@Override | |||||
public void complete(Throwable error) { | |||||
} | |||||
} | } | ||||
} | } |
@@ -1,43 +1,22 @@ | |||||
package com.jd.blockchain.transaction; | package com.jd.blockchain.transaction; | ||||
import java.util.concurrent.TimeUnit; | |||||
import java.util.concurrent.TimeoutException; | |||||
public class BooleanValueHolder extends ValueHolderWrapper { | |||||
public class BooleanValueHolder extends ValueHolderBase { | |||||
BooleanValueHolder(ContractInvocation invocation) { | |||||
super(invocation); | |||||
BooleanValueHolder(OperationResultHolder resultHolder) { | |||||
super(resultHolder); | |||||
} | } | ||||
/** | /** | ||||
* 等待结果合约调用的结果返回; | |||||
* 获取值;<br> | |||||
* | * | ||||
* @return | |||||
*/ | |||||
public boolean get() { | |||||
return (boolean) super.getValue(); | |||||
} | |||||
/** | |||||
* 等待结果合约调用的结果返回; | |||||
* 此方法不堵塞,调用立即返回;<br> | |||||
* | * | ||||
* @param timeout | |||||
* @return | |||||
* @throws TimeoutException | |||||
*/ | |||||
public boolean get(long timeout) throws TimeoutException { | |||||
return get(timeout, TimeUnit.MILLISECONDS); | |||||
} | |||||
/** | |||||
* 等待结果合约调用的结果返回; | |||||
* 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 false; | |||||
* | * | ||||
* @param timeout | |||||
* @param unit | |||||
* @return | * @return | ||||
* @throws TimeoutException | |||||
*/ | */ | ||||
public boolean get(long timeout, TimeUnit unit) throws TimeoutException { | |||||
return (boolean) super.getValue(timeout, unit); | |||||
public boolean get() { | |||||
return super.isCompleted() ? (boolean) super.getValue() : false; | |||||
} | } | ||||
} | } |
@@ -1,43 +1,22 @@ | |||||
package com.jd.blockchain.transaction; | package com.jd.blockchain.transaction; | ||||
import java.util.concurrent.TimeUnit; | |||||
import java.util.concurrent.TimeoutException; | |||||
public class ByteValueHolder extends ValueHolderWrapper { | |||||
public class ByteValueHolder extends ValueHolderBase { | |||||
ByteValueHolder(ContractInvocation invocation) { | |||||
super(invocation); | |||||
ByteValueHolder(OperationResultHolder resultHolder) { | |||||
super(resultHolder); | |||||
} | } | ||||
/** | /** | ||||
* 等待结果合约调用的结果返回; | |||||
* 获取值;<br> | |||||
* | * | ||||
* @return | |||||
*/ | |||||
public byte get() { | |||||
return (byte) super.getValue(); | |||||
} | |||||
/** | |||||
* 等待结果合约调用的结果返回; | |||||
* 此方法不堵塞,调用立即返回;<br> | |||||
* | * | ||||
* @param timeout | |||||
* @return | |||||
* @throws TimeoutException | |||||
*/ | |||||
public byte get(long timeout) throws TimeoutException { | |||||
return get(timeout, TimeUnit.MILLISECONDS); | |||||
} | |||||
/** | |||||
* 等待结果合约调用的结果返回; | |||||
* 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 0; | |||||
* | * | ||||
* @param timeout | |||||
* @param unit | |||||
* @return | * @return | ||||
* @throws TimeoutException | |||||
*/ | */ | ||||
public byte get(long timeout, TimeUnit unit) throws TimeoutException { | |||||
return (byte) super.getValue(timeout, unit); | |||||
public byte get() { | |||||
return super.isCompleted() ? (byte) super.getValue() : 0; | |||||
} | } | ||||
} | } |
@@ -1,8 +1,6 @@ | |||||
package com.jd.blockchain.transaction; | package com.jd.blockchain.transaction; | ||||
import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||
import java.util.concurrent.CompletableFuture; | |||||
import java.util.concurrent.Future; | |||||
import com.jd.blockchain.contract.ContractType; | import com.jd.blockchain.contract.ContractType; | ||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
@@ -14,7 +12,7 @@ import com.jd.blockchain.ledger.BytesValueEncoding; | |||||
* @author huanghaiquan | * @author huanghaiquan | ||||
* | * | ||||
*/ | */ | ||||
class ContractInvocation implements OperationReturnValueHandler { | |||||
class ContractInvocation extends OperationResultHolder { | |||||
private Method method; | private Method method; | ||||
@@ -22,12 +20,9 @@ class ContractInvocation implements OperationReturnValueHandler { | |||||
private int operationIndex = -1; | private int operationIndex = -1; | ||||
private CompletableFuture<Object> returnValueFuture; | |||||
public ContractInvocation(ContractType contractType, Method method) { | public ContractInvocation(ContractType contractType, Method method) { | ||||
this.contractType = contractType; | this.contractType = contractType; | ||||
this.method = method; | this.method = method; | ||||
this.returnValueFuture = new CompletableFuture<Object>(); | |||||
} | } | ||||
public ContractType getContractType() { | public ContractType getContractType() { | ||||
@@ -47,16 +42,9 @@ class ContractInvocation implements OperationReturnValueHandler { | |||||
return method.getReturnType(); | return method.getReturnType(); | ||||
} | } | ||||
public Future<Object> getReturnValue() { | |||||
return returnValueFuture; | |||||
} | |||||
@Override | @Override | ||||
public Object setReturnValue(BytesValue bytesValue) { | |||||
// Resolve BytesValue to an value object with the return type; | |||||
Object returnValue = BytesValueEncoding.decode(bytesValue, method.getReturnType()); | |||||
returnValueFuture.complete(returnValue); | |||||
return returnValue; | |||||
protected Object decodeResult(BytesValue bytesValue) { | |||||
return BytesValueEncoding.decode(bytesValue, method.getReturnType()); | |||||
} | } | ||||
} | } |
@@ -4,10 +4,8 @@ import java.lang.reflect.Proxy; | |||||
import java.util.Map; | import java.util.Map; | ||||
import java.util.concurrent.ConcurrentHashMap; | import java.util.concurrent.ConcurrentHashMap; | ||||
import com.jd.blockchain.contract.EventResult; | |||||
import com.jd.blockchain.contract.ContractType; | import com.jd.blockchain.contract.ContractType; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import com.jd.blockchain.utils.IllegalDataException; | |||||
/** | /** | ||||
* 合约调用代理的构建器; | * 合约调用代理的构建器; | ||||
@@ -19,8 +17,6 @@ public class ContractInvocationProxyBuilder { | |||||
private Map<Class<?>, ContractType> contractTypes = new ConcurrentHashMap<>(); | private Map<Class<?>, ContractType> contractTypes = new ConcurrentHashMap<>(); | ||||
// private Map<Object, Integer> contractOperations = new ConcurrentHashMap<>(); | |||||
public <T> T create(String address, Class<T> contractIntf, ContractEventSendOperationBuilder contractEventBuilder) { | public <T> T create(String address, Class<T> contractIntf, ContractEventSendOperationBuilder contractEventBuilder) { | ||||
return create(Bytes.fromBase58(address), contractIntf, contractEventBuilder); | return create(Bytes.fromBase58(address), contractIntf, contractEventBuilder); | ||||
} | } | ||||
@@ -33,31 +29,9 @@ public class ContractInvocationProxyBuilder { | |||||
T proxy = (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), | T proxy = (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), | ||||
new Class<?>[] { contractIntf }, proxyHandler); | new Class<?>[] { contractIntf }, proxyHandler); | ||||
// // 创建关联关系 | |||||
// contractOperations.put(proxy, proxyHandler.opIndex()); | |||||
return proxy; | return proxy; | ||||
} | } | ||||
// public <T> EventResult<T> execute(ContractEventExecutor execute) { | |||||
// Object contractProxy = execute.execute(); | |||||
// if (contractProxy == null) { | |||||
// // 该方法执行必须要有返回值 | |||||
// throw new IllegalStateException( | |||||
// String.format("ContractEventExecutor [%s] 's return must be not empty !!!", execute.toString())); | |||||
// } | |||||
// if (!(contractProxy instanceof Proxy)) { | |||||
// throw new IllegalDataException( | |||||
// String.format("ContractEventExecutor [%s] 's return must from TxTemplate.contract()'s result !!!", | |||||
// execute.toString())); | |||||
// } | |||||
// | |||||
// Integer opIndex = contractOperations.get(contractProxy); | |||||
// if (opIndex != null && opIndex > -1) { | |||||
// return new EventResult<>(opIndex); | |||||
// } | |||||
// return null; | |||||
// } | |||||
private ContractType resolveContractType(Class<?> contractIntf) { | private ContractType resolveContractType(Class<?> contractIntf) { | ||||
ContractType contractType = contractTypes.get(contractIntf); | ContractType contractType = contractTypes.get(contractIntf); | ||||
if (contractType != null) { | if (contractType != null) { | ||||
@@ -26,9 +26,9 @@ public class ContractReturnValue { | |||||
* @param call | * @param call | ||||
* @return | * @return | ||||
*/ | */ | ||||
public static <T> ValueHolder<T> decode(T call) { | |||||
public static <T> GenericValueHolder<T> decode(T call) { | |||||
ContractInvocation invocation = ContractInvocationStub.take(); | ContractInvocation invocation = ContractInvocationStub.take(); | ||||
return new ValueHolder<T>(invocation); | |||||
return new GenericValueHolder<T>(invocation); | |||||
} | } | ||||
/** | /** | ||||
@@ -1,7 +1,7 @@ | |||||
package com.jd.blockchain.transaction; | package com.jd.blockchain.transaction; | ||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
import com.jd.blockchain.ledger.BytesValueEntry; | |||||
import com.jd.blockchain.ledger.BytesData; | |||||
import com.jd.blockchain.ledger.DataAccountKVSetOperation; | import com.jd.blockchain.ledger.DataAccountKVSetOperation; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
@@ -26,14 +26,14 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe | |||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { | public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromBytes(value); | |||||
BytesValue bytesValue = BytesData.fromBytes(value); | |||||
operation.set(key, bytesValue, expVersion); | operation.set(key, bytesValue, expVersion); | ||||
return this; | return this; | ||||
} | } | ||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { | public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromImage(value); | |||||
BytesValue bytesValue = BytesData.fromImage(value); | |||||
operation.set(key, bytesValue, expVersion); | operation.set(key, bytesValue, expVersion); | ||||
return this; | return this; | ||||
} | } | ||||
@@ -45,42 +45,42 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe | |||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { | public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromText(value); | |||||
BytesValue bytesValue = BytesData.fromText(value); | |||||
operation.set(key, bytesValue, expVersion); | operation.set(key, bytesValue, expVersion); | ||||
return this; | return this; | ||||
} | } | ||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { | public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromBytes(value); | |||||
BytesValue bytesValue = BytesData.fromBytes(value); | |||||
operation.set(key, bytesValue, expVersion); | operation.set(key, bytesValue, expVersion); | ||||
return this; | return this; | ||||
} | } | ||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { | public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromInt64(value); | |||||
BytesValue bytesValue = BytesData.fromInt64(value); | |||||
operation.set(key, bytesValue, expVersion); | operation.set(key, bytesValue, expVersion); | ||||
return this; | return this; | ||||
} | } | ||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { | public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromJSON(value); | |||||
BytesValue bytesValue = BytesData.fromJSON(value); | |||||
operation.set(key, bytesValue, expVersion); | operation.set(key, bytesValue, expVersion); | ||||
return this; | return this; | ||||
} | } | ||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { | public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromXML(value); | |||||
BytesValue bytesValue = BytesData.fromXML(value); | |||||
operation.set(key, bytesValue, expVersion); | operation.set(key, bytesValue, expVersion); | ||||
return this; | return this; | ||||
} | } | ||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { | public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { | ||||
BytesValue bytesValue = BytesValueEntry.fromTimestamp(value); | |||||
BytesValue bytesValue = BytesData.fromTimestamp(value); | |||||
operation.set(key, bytesValue, expVersion); | operation.set(key, bytesValue, expVersion); | ||||
return this; | return this; | ||||
} | } | ||||
@@ -0,0 +1,23 @@ | |||||
package com.jd.blockchain.transaction; | |||||
public class GenericValueHolder<T> extends ValueHolderWrapper { | |||||
GenericValueHolder(OperationResultHolder resultHolder) { | |||||
super(resultHolder); | |||||
} | |||||
/** | |||||
* 获取值;<br> | |||||
* | |||||
* 此方法不堵塞,调用立即返回;<br> | |||||
* | |||||
* 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 null; | |||||
* | |||||
* @return | |||||
*/ | |||||
@SuppressWarnings("unchecked") | |||||
public T get() { | |||||
return (T) super.getValue(); | |||||
} | |||||
} |
@@ -1,43 +1,22 @@ | |||||
package com.jd.blockchain.transaction; | package com.jd.blockchain.transaction; | ||||
import java.util.concurrent.TimeUnit; | |||||
import java.util.concurrent.TimeoutException; | |||||
public class IntValueHolder extends ValueHolderWrapper { | |||||
public class IntValueHolder extends ValueHolderBase { | |||||
IntValueHolder(ContractInvocation invocation) { | |||||
super(invocation); | |||||
IntValueHolder(OperationResultHolder resultHolder) { | |||||
super(resultHolder); | |||||
} | } | ||||
/** | /** | ||||
* 等待结果合约调用的结果返回; | |||||
* 获取值;<br> | |||||
* | * | ||||
* @return | |||||
*/ | |||||
public int get() { | |||||
return (int) super.getValue(); | |||||
} | |||||
/** | |||||
* 等待结果合约调用的结果返回; | |||||
* 此方法不堵塞,调用立即返回;<br> | |||||
* | * | ||||
* @param timeout | |||||
* @return | |||||
* @throws TimeoutException | |||||
*/ | |||||
public int get(long timeout) throws TimeoutException { | |||||
return get(timeout, TimeUnit.MILLISECONDS); | |||||
} | |||||
/** | |||||
* 等待结果合约调用的结果返回; | |||||
* 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 0; | |||||
* | * | ||||
* @param timeout | |||||
* @param unit | |||||
* @return | * @return | ||||
* @throws TimeoutException | |||||
*/ | */ | ||||
public int get(long timeout, TimeUnit unit) throws TimeoutException { | |||||
return (int) super.getValue(timeout, unit); | |||||
public int get() { | |||||
return super.isCompleted() ? (int) super.getValue() : 0; | |||||
} | } | ||||
} | } |
@@ -1,43 +1,22 @@ | |||||
package com.jd.blockchain.transaction; | package com.jd.blockchain.transaction; | ||||
import java.util.concurrent.TimeUnit; | |||||
import java.util.concurrent.TimeoutException; | |||||
public class LongValueHolder extends ValueHolderWrapper { | |||||
public class LongValueHolder extends ValueHolderBase { | |||||
LongValueHolder(ContractInvocation invocation) { | |||||
super(invocation); | |||||
LongValueHolder(OperationResultHolder resultHolder) { | |||||
super(resultHolder); | |||||
} | } | ||||
/** | /** | ||||
* 等待结果合约调用的结果返回; | |||||
* 获取值;<br> | |||||
* | * | ||||
* @return | |||||
*/ | |||||
public long get() { | |||||
return (long) super.getValue(); | |||||
} | |||||
/** | |||||
* 等待结果合约调用的结果返回; | |||||
* 此方法不堵塞,调用立即返回;<br> | |||||
* | * | ||||
* @param timeout | |||||
* @return | |||||
* @throws TimeoutException | |||||
*/ | |||||
public long get(long timeout) throws TimeoutException { | |||||
return get(timeout, TimeUnit.MILLISECONDS); | |||||
} | |||||
/** | |||||
* 等待结果合约调用的结果返回; | |||||
* 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 0; | |||||
* | * | ||||
* @param timeout | |||||
* @param unit | |||||
* @return | * @return | ||||
* @throws TimeoutException | |||||
*/ | */ | ||||
public long get(long timeout, TimeUnit unit) throws TimeoutException { | |||||
return (long) super.getValue(timeout, unit); | |||||
public long get() { | |||||
return super.isCompleted() ? (long) super.getValue() : 0; | |||||
} | } | ||||
} | } |
@@ -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; | |||||
} | |||||
} |
@@ -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); | |||||
} |
@@ -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); | |||||
} |
@@ -0,0 +1,81 @@ | |||||
package com.jd.blockchain.transaction; | |||||
import com.jd.blockchain.ledger.BytesValue; | |||||
import com.jd.blockchain.utils.event.EventMulticaster; | |||||
abstract class OperationResultHolder implements OperationResultHandle { | |||||
private Object value; | |||||
private Throwable error; | |||||
private volatile boolean completed; | |||||
private EventMulticaster<OperationCompletedListener> listenerMulticaster; | |||||
/** | |||||
* 导致结束的错误; | |||||
* | |||||
* @return | |||||
*/ | |||||
public Throwable getError() { | |||||
return error; | |||||
} | |||||
/** | |||||
* 是否已经处理完成; | |||||
* | |||||
* @return | |||||
*/ | |||||
public boolean isCompleted() { | |||||
return completed; | |||||
} | |||||
/** | |||||
* 获取操作的返回值; <br> | |||||
* 在操作未完成之前,总是返回 null;<br> | |||||
* 可以通过 {@link #isCompleted()} 方法判断操作是否已经完成;<br> | |||||
* 可以通过 {@link #addCompletedListener(OperationCompletedListener)} | |||||
* 方法添加监听器来监听操作完成的事件; | |||||
* | |||||
* @return | |||||
*/ | |||||
public Object getResult() { | |||||
return value; | |||||
} | |||||
/** | |||||
* 添加操作完成监听器; | |||||
* | |||||
* @param listener | |||||
*/ | |||||
public void addCompletedListener(OperationCompletedListener listener) { | |||||
listenerMulticaster.addListener(listener); | |||||
} | |||||
protected abstract Object decodeResult(BytesValue bytesValue); | |||||
@Override | |||||
public Object complete(BytesValue bytesValue) { | |||||
if (this.completed) { | |||||
throw new IllegalStateException( | |||||
"Contract invocation has been completed, and is not allowed to be completed again!"); | |||||
} | |||||
this.completed = true; | |||||
this.value = decodeResult(bytesValue); | |||||
OperationCompletedContext context = new OperationCompletedContext(getOperationIndex(), null); | |||||
listenerMulticaster.getBroadcaster().onCompleted(value, null, context); | |||||
return null; | |||||
} | |||||
@Override | |||||
public void complete(Throwable error) { | |||||
if (completed) { | |||||
return; | |||||
} | |||||
this.completed = true; | |||||
this.error = error; | |||||
OperationCompletedContext context = new OperationCompletedContext(getOperationIndex(), null); | |||||
listenerMulticaster.getBroadcaster().onCompleted(null, error, context); | |||||
} | |||||
} |
@@ -1,11 +0,0 @@ | |||||
package com.jd.blockchain.transaction; | |||||
import com.jd.blockchain.ledger.BytesValue; | |||||
interface OperationReturnValueHandler { | |||||
int getOperationIndex(); | |||||
Object setReturnValue(BytesValue bytesValue); | |||||
} |
@@ -1,9 +1,12 @@ | |||||
package com.jd.blockchain.transaction; | package com.jd.blockchain.transaction; | ||||
import java.io.IOException; | |||||
import java.util.Arrays; | import java.util.Arrays; | ||||
import java.util.Collection; | import java.util.Collection; | ||||
import java.util.Comparator; | import java.util.Comparator; | ||||
import org.springframework.cglib.proxy.UndeclaredThrowableException; | |||||
import com.jd.blockchain.binaryproto.BinaryProtocol; | import com.jd.blockchain.binaryproto.BinaryProtocol; | ||||
import com.jd.blockchain.crypto.AsymmetricKeypair; | import com.jd.blockchain.crypto.AsymmetricKeypair; | ||||
import com.jd.blockchain.crypto.Crypto; | import com.jd.blockchain.crypto.Crypto; | ||||
@@ -25,7 +28,9 @@ public class PreparedTx implements PreparedTransaction { | |||||
private TransactionService txProcessor; | private TransactionService txProcessor; | ||||
private OperationReturnValueHandler[] opReturnValueHandlers; | |||||
private OperationResultHandle[] opReturnValueHandlers; | |||||
private TxStateManager stateManager; | |||||
/** | /** | ||||
* 创建一个“就绪交易”对象; | * 创建一个“就绪交易”对象; | ||||
@@ -34,17 +39,18 @@ public class PreparedTx implements PreparedTransaction { | |||||
* @param txProcessor 交易处理服务; | * @param txProcessor 交易处理服务; | ||||
* @param opReturnValueHandlerList 操作返回值处理器列表; | * @param opReturnValueHandlerList 操作返回值处理器列表; | ||||
*/ | */ | ||||
public PreparedTx(TransactionRequestBuilder txReqBuilder, TransactionService txProcessor, | |||||
Collection<OperationReturnValueHandler> opReturnValueHandlerList) { | |||||
public PreparedTx(TxStateManager stateManager, TransactionRequestBuilder txReqBuilder, | |||||
TransactionService txProcessor, Collection<OperationResultHandle> opReturnValueHandlerList) { | |||||
this.stateManager = stateManager; | |||||
this.txReqBuilder = txReqBuilder; | this.txReqBuilder = txReqBuilder; | ||||
this.txProcessor = txProcessor; | this.txProcessor = txProcessor; | ||||
this.opReturnValueHandlers = opReturnValueHandlerList | this.opReturnValueHandlers = opReturnValueHandlerList | ||||
.toArray(new OperationReturnValueHandler[opReturnValueHandlerList.size()]); | |||||
.toArray(new OperationResultHandle[opReturnValueHandlerList.size()]); | |||||
// 按照操作索引升序排列; | // 按照操作索引升序排列; | ||||
Arrays.sort(opReturnValueHandlers, new Comparator<OperationReturnValueHandler>() { | |||||
Arrays.sort(opReturnValueHandlers, new Comparator<OperationResultHandle>() { | |||||
@Override | @Override | ||||
public int compare(OperationReturnValueHandler o1, OperationReturnValueHandler o2) { | |||||
public int compare(OperationResultHandle o1, OperationResultHandle o2) { | |||||
return o1.getOperationIndex() - o2.getOperationIndex(); | return o1.getOperationIndex() - o2.getOperationIndex(); | ||||
} | } | ||||
}); | }); | ||||
@@ -78,31 +84,59 @@ public class PreparedTx implements PreparedTransaction { | |||||
@Override | @Override | ||||
public TransactionResponse commit() { | public TransactionResponse commit() { | ||||
stateManager.commit(); | |||||
TransactionResponse txResponse = null; | |||||
try { | try { | ||||
TransactionRequest txReq = txReqBuilder.buildRequest(); | TransactionRequest txReq = txReqBuilder.buildRequest(); | ||||
// 发起交易请求; | // 发起交易请求; | ||||
TransactionResponse txResponse = txProcessor.process(txReq); | |||||
// 解析返回值;正常的情况下,返回结果列表与结果处理器列表中元素对应的操作索引是一致的; | |||||
OperationResult[] opResults = txResponse.getOperationResults(); | |||||
if (opResults != null && opResults.length > 0) { | |||||
if (opResults.length != opReturnValueHandlers.length) { | |||||
throw new IllegalStateException(String.format( | |||||
"The operation result list of tx doesn't match it's return value handler list! --[TX.Content.Hash=%s][NumOfResults=%s][NumOfHandlers=%s]", | |||||
txReq.getTransactionContent().getHash(), opResults.length, opReturnValueHandlers.length)); | |||||
} | |||||
for (int i = 0; i < opResults.length; i++) { | |||||
if (opResults[i].getIndex() != opReturnValueHandlers[i].getOperationIndex()) { | |||||
throw new IllegalStateException( | |||||
"The operation indexes of the items in the result list and in the handler list don't match!"); | |||||
} | |||||
opReturnValueHandlers[i].setReturnValue(opResults[i].getResult()); | |||||
txResponse = txProcessor.process(txReq); | |||||
stateManager.complete(); | |||||
} catch (Exception ex) { | |||||
stateManager.close(); | |||||
handleError(ex); | |||||
throw new UndeclaredThrowableException(ex); | |||||
} | |||||
if (txResponse != null) { | |||||
handleResults(txResponse); | |||||
} | |||||
return txResponse; | |||||
} | |||||
@Override | |||||
public void close() throws IOException { | |||||
if (!stateManager.close()) { | |||||
TransactionCancelledExeption error = new TransactionCancelledExeption( | |||||
"Prepared transaction has been cancelled!"); | |||||
handleError(error); | |||||
} | |||||
} | |||||
private void handleError(Throwable error) { | |||||
for (OperationResultHandle handle : opReturnValueHandlers) { | |||||
handle.complete(error); | |||||
} | |||||
} | |||||
private void handleResults(TransactionResponse txResponse) { | |||||
// 解析返回值;正常的情况下,返回结果列表与结果处理器列表中元素对应的操作索引是一致的; | |||||
OperationResult[] opResults = txResponse.getOperationResults(); | |||||
if (opResults != null && opResults.length > 0) { | |||||
if (opResults.length != opReturnValueHandlers.length) { | |||||
throw new IllegalStateException(String.format( | |||||
"The operation result list of tx doesn't match it's return value handler list! --[TX.Content.Hash=%s][NumOfResults=%s][NumOfHandlers=%s]", | |||||
txResponse.getContentHash(), opResults.length, opReturnValueHandlers.length)); | |||||
} | |||||
for (int i = 0; i < opResults.length; i++) { | |||||
if (opResults[i].getIndex() != opReturnValueHandlers[i].getOperationIndex()) { | |||||
throw new IllegalStateException( | |||||
"The operation indexes of the items in the result list and in the handler list don't match!"); | |||||
} | } | ||||
opReturnValueHandlers[i].complete(opResults[i].getResult()); | |||||
} | } | ||||
return txResponse; | |||||
} catch (Exception e) { | |||||
//TODO: 出错时清理交易上下文,释放与交易关联对异步等待资源,避免当前线程死锁; | |||||
} | } | ||||
} | } | ||||
@@ -1,43 +1,22 @@ | |||||
package com.jd.blockchain.transaction; | package com.jd.blockchain.transaction; | ||||
import java.util.concurrent.TimeUnit; | |||||
import java.util.concurrent.TimeoutException; | |||||
public class ShortValueHolder extends ValueHolderWrapper { | |||||
public class ShortValueHolder extends ValueHolderBase { | |||||
ShortValueHolder(ContractInvocation invocation) { | |||||
super(invocation); | |||||
ShortValueHolder(OperationResultHolder resultHolder) { | |||||
super(resultHolder); | |||||
} | } | ||||
/** | /** | ||||
* 等待结果合约调用的结果返回; | |||||
* 获取值;<br> | |||||
* | * | ||||
* @return | |||||
*/ | |||||
public short get() { | |||||
return (short) super.getValue(); | |||||
} | |||||
/** | |||||
* 等待结果合约调用的结果返回; | |||||
* 此方法不堵塞,调用立即返回;<br> | |||||
* | * | ||||
* @param timeout | |||||
* @return | |||||
* @throws TimeoutException | |||||
*/ | |||||
public short get(long timeout) throws TimeoutException { | |||||
return get(timeout, TimeUnit.MILLISECONDS); | |||||
} | |||||
/** | |||||
* 等待结果合约调用的结果返回; | |||||
* 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 0; | |||||
* | * | ||||
* @param timeout | |||||
* @param unit | |||||
* @return | * @return | ||||
* @throws TimeoutException | |||||
*/ | */ | ||||
public short get(long timeout, TimeUnit unit) throws TimeoutException { | |||||
return (short) super.getValue(timeout, unit); | |||||
public short get() { | |||||
return super.isCompleted() ? (short) super.getValue() : 0; | |||||
} | } | ||||
} | } |
@@ -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); | |||||
} | |||||
} |
@@ -51,7 +51,7 @@ public class TxBuilder implements TransactionBuilder { | |||||
return txContent; | return txContent; | ||||
} | } | ||||
public Collection<OperationReturnValueHandler> getReturnValuehandlers() { | |||||
public Collection<OperationResultHandle> getReturnValuehandlers() { | |||||
return opFactory.getReturnValuetHandlers(); | return opFactory.getReturnValuetHandlers(); | ||||
} | } | ||||
@@ -0,0 +1,76 @@ | |||||
package com.jd.blockchain.transaction; | |||||
class TxStateManager { | |||||
private State state = State.OPERABLE; | |||||
public void operate() { | |||||
if (state != State.OPERABLE) { | |||||
throw new IllegalStateException(String.format("Cannot define operations in %s state!", state)); | |||||
} | |||||
} | |||||
public void prepare() { | |||||
if (state != State.OPERABLE) { | |||||
throw new IllegalStateException( | |||||
String.format("Cannot switch to %s state in %s state!", State.PREPARED, state)); | |||||
} | |||||
state = State.PREPARED; | |||||
} | |||||
public void commit() { | |||||
if (state != State.PREPARED) { | |||||
throw new IllegalStateException( | |||||
String.format("Cannot switch to %s state in %s state!", State.COMMITTED, state)); | |||||
} | |||||
state = State.COMMITTED; | |||||
} | |||||
public void complete() { | |||||
if (state != State.COMMITTED) { | |||||
throw new IllegalStateException(String.format("Cannot complete normally in %s state!", state)); | |||||
} | |||||
state = State.CLOSED; | |||||
} | |||||
/** | |||||
* 关闭交易; | |||||
* | |||||
* @param error | |||||
* @return 此次操作前是否已经处于关闭状态; <br> | |||||
* 如果返回 true ,则表示之前已经处于关闭状态,此次操作将被忽略;<br> | |||||
* 如果返回 fasle,则表示之前处于非关闭状态,此次操作将切换为关闭状态; | |||||
*/ | |||||
public boolean close() { | |||||
if (state == State.CLOSED) { | |||||
return true; | |||||
} | |||||
state = State.CLOSED; | |||||
return false; | |||||
} | |||||
private static enum State { | |||||
/** | |||||
* 可操作; | |||||
*/ | |||||
OPERABLE, | |||||
/** | |||||
* 就绪; | |||||
*/ | |||||
PREPARED, | |||||
/** | |||||
* 已提交; | |||||
*/ | |||||
COMMITTED, | |||||
/** | |||||
* 已关闭; | |||||
*/ | |||||
CLOSED | |||||
} | |||||
} |
@@ -1,5 +1,8 @@ | |||||
package com.jd.blockchain.transaction; | package com.jd.blockchain.transaction; | ||||
import java.io.IOException; | |||||
import java.util.Collection; | |||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.ledger.PreparedTransaction; | import com.jd.blockchain.ledger.PreparedTransaction; | ||||
import com.jd.blockchain.ledger.TransactionRequestBuilder; | import com.jd.blockchain.ledger.TransactionRequestBuilder; | ||||
@@ -12,8 +15,10 @@ public class TxTemplate implements TransactionTemplate { | |||||
private TransactionService txService; | private TransactionService txService; | ||||
private TxStateManager stateManager; | |||||
public TxTemplate(HashDigest ledgerHash, TransactionService txService) { | public TxTemplate(HashDigest ledgerHash, TransactionService txService) { | ||||
this.stateManager = new TxStateManager(); | |||||
this.txBuilder = new TxBuilder(ledgerHash); | this.txBuilder = new TxBuilder(ledgerHash); | ||||
this.txService = txService; | this.txService = txService; | ||||
} | } | ||||
@@ -25,43 +30,63 @@ public class TxTemplate implements TransactionTemplate { | |||||
@Override | @Override | ||||
public PreparedTransaction prepare() { | public PreparedTransaction prepare() { | ||||
stateManager.prepare(); | |||||
TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest(); | TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest(); | ||||
return new PreparedTx(txReqBuilder, txService, txBuilder.getReturnValuehandlers()); | |||||
return new PreparedTx(stateManager, txReqBuilder, txService, txBuilder.getReturnValuehandlers()); | |||||
} | } | ||||
@Override | @Override | ||||
public UserRegisterOperationBuilder users() { | public UserRegisterOperationBuilder users() { | ||||
stateManager.operate(); | |||||
return txBuilder.users(); | return txBuilder.users(); | ||||
} | } | ||||
@Override | @Override | ||||
public DataAccountRegisterOperationBuilder dataAccounts() { | public DataAccountRegisterOperationBuilder dataAccounts() { | ||||
stateManager.operate(); | |||||
return txBuilder.dataAccounts(); | return txBuilder.dataAccounts(); | ||||
} | } | ||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) { | public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) { | ||||
stateManager.operate(); | |||||
return txBuilder.dataAccount(accountAddress); | return txBuilder.dataAccount(accountAddress); | ||||
} | } | ||||
@Override | @Override | ||||
public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) { | public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) { | ||||
stateManager.operate(); | |||||
return txBuilder.dataAccount(accountAddress); | return txBuilder.dataAccount(accountAddress); | ||||
} | } | ||||
@Override | @Override | ||||
public ContractCodeDeployOperationBuilder contracts() { | public ContractCodeDeployOperationBuilder contracts() { | ||||
stateManager.operate(); | |||||
return txBuilder.contracts(); | return txBuilder.contracts(); | ||||
} | } | ||||
@Override | @Override | ||||
public <T> T contract(Bytes address, Class<T> contractIntf) { | public <T> T contract(Bytes address, Class<T> contractIntf) { | ||||
stateManager.operate(); | |||||
return txBuilder.contract(address, contractIntf); | return txBuilder.contract(address, contractIntf); | ||||
} | } | ||||
@Override | @Override | ||||
public <T> T contract(String address, Class<T> contractIntf) { | public <T> T contract(String address, Class<T> contractIntf) { | ||||
stateManager.operate(); | |||||
return txBuilder.contract(address, contractIntf); | return txBuilder.contract(address, contractIntf); | ||||
} | } | ||||
@Override | |||||
public void close() throws IOException { | |||||
if (!stateManager.close()) { | |||||
Collection<OperationResultHandle> handlers = txBuilder.getReturnValuehandlers(); | |||||
if (handlers.size() > 0) { | |||||
TransactionCancelledExeption error = new TransactionCancelledExeption("Transaction template has been cancelled!"); | |||||
for (OperationResultHandle handle : handlers) { | |||||
handle.complete(error); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | } |
@@ -1,45 +0,0 @@ | |||||
package com.jd.blockchain.transaction; | |||||
import java.util.concurrent.TimeUnit; | |||||
import java.util.concurrent.TimeoutException; | |||||
public class ValueHolder<T> extends ValueHolderBase { | |||||
ValueHolder(ContractInvocation invocation) { | |||||
super(invocation); | |||||
} | |||||
/** | |||||
* 等待结果合约调用的结果返回; | |||||
* | |||||
* @return | |||||
*/ | |||||
@SuppressWarnings("unchecked") | |||||
public T get() { | |||||
return (T) super.getValue(); | |||||
} | |||||
/** | |||||
* 等待结果合约调用的结果返回; | |||||
* | |||||
* @param timeout | |||||
* @return | |||||
* @throws TimeoutException | |||||
*/ | |||||
public T get(long timeout) throws TimeoutException { | |||||
return get(timeout, TimeUnit.MILLISECONDS); | |||||
} | |||||
/** | |||||
* 等待结果合约调用的结果返回; | |||||
* | |||||
* @param timeout | |||||
* @param unit | |||||
* @return | |||||
* @throws TimeoutException | |||||
*/ | |||||
@SuppressWarnings("unchecked") | |||||
public T get(long timeout, TimeUnit unit) throws TimeoutException { | |||||
return (T) super.getValue(timeout, unit); | |||||
} | |||||
} |
@@ -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); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,34 @@ | |||||
package com.jd.blockchain.transaction; | |||||
class ValueHolderWrapper { | |||||
private OperationResultHolder valueHolder; | |||||
protected ValueHolderWrapper(OperationResultHolder valueHolder) { | |||||
this.valueHolder = valueHolder; | |||||
} | |||||
public boolean isCompleted() { | |||||
return valueHolder.isCompleted(); | |||||
} | |||||
public Throwable getError() { | |||||
return valueHolder.getError(); | |||||
} | |||||
/** | |||||
* 获取值;<br> | |||||
* | |||||
* 此方法不堵塞,调用立即返回;<br> | |||||
* | |||||
* 如果未完成时( {@link #isCompleted()} 为 false ),总是返回 null; | |||||
* | |||||
* @return | |||||
*/ | |||||
protected Object getValue() { | |||||
return valueHolder.getResult(); | |||||
} | |||||
public void addCompletedListener(OperationCompletedListener listener) { | |||||
valueHolder.addCompletedListener(listener); | |||||
} | |||||
} |
@@ -8,21 +8,22 @@ | |||||
*/ | */ | ||||
package test.com.jd.blockchain.ledger.data; | package test.com.jd.blockchain.ledger.data; | ||||
import static org.junit.Assert.assertArrayEquals; | |||||
import static org.junit.Assert.assertEquals; | |||||
import org.junit.Before; | |||||
import org.junit.Test; | |||||
import com.jd.blockchain.binaryproto.BinaryProtocol; | import com.jd.blockchain.binaryproto.BinaryProtocol; | ||||
import com.jd.blockchain.binaryproto.DataContractRegistry; | import com.jd.blockchain.binaryproto.DataContractRegistry; | ||||
import com.jd.blockchain.ledger.BytesData; | |||||
import com.jd.blockchain.ledger.BytesDataList; | |||||
import com.jd.blockchain.ledger.BytesValueList; | |||||
import com.jd.blockchain.ledger.ContractEventSendOperation; | import com.jd.blockchain.ledger.ContractEventSendOperation; | ||||
import com.jd.blockchain.ledger.DataAccountKVSetOperation; | |||||
import com.jd.blockchain.ledger.Operation; | import com.jd.blockchain.ledger.Operation; | ||||
import com.jd.blockchain.transaction.ContractEventSendOpTemplate; | import com.jd.blockchain.transaction.ContractEventSendOpTemplate; | ||||
import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import org.junit.Before; | |||||
import org.junit.Test; | |||||
import static org.junit.Assert.assertArrayEquals; | |||||
import static org.junit.Assert.assertEquals; | |||||
/** | /** | ||||
* | * | ||||
* @author shaozhuguang | * @author shaozhuguang | ||||
@@ -32,34 +33,36 @@ import static org.junit.Assert.assertEquals; | |||||
public class ContractEventSendOpTemplateTest { | public class ContractEventSendOpTemplateTest { | ||||
private ContractEventSendOpTemplate data; | |||||
private ContractEventSendOpTemplate data; | |||||
@Before | |||||
public void initContractEventSendOpTemplate() { | |||||
DataContractRegistry.register(ContractEventSendOperation.class); | |||||
DataContractRegistry.register(Operation.class); | |||||
String contractAddress = "zhangsan-address", event = "zhangsan-event"; | |||||
byte[] args = "zhangsan-args".getBytes(); | |||||
data = new ContractEventSendOpTemplate(Bytes.fromString(contractAddress), event, args); | |||||
} | |||||
@Before | |||||
public void initContractEventSendOpTemplate() { | |||||
DataContractRegistry.register(ContractEventSendOperation.class); | |||||
DataContractRegistry.register(Operation.class); | |||||
String contractAddress = "zhangsan-address", event = "zhangsan-event"; | |||||
BytesValueList args = new BytesDataList(BytesData.fromText("zhangsan-args")); | |||||
data = new ContractEventSendOpTemplate(Bytes.fromString(contractAddress), event, args); | |||||
} | |||||
@Test | |||||
public void testSerialize_ContractEventSendOperation() throws Exception { | |||||
byte[] serialBytes = BinaryProtocol.encode(data, ContractEventSendOperation.class); | |||||
ContractEventSendOperation resolvedData = BinaryProtocol.decode(serialBytes); | |||||
System.out.println("------Assert start ------"); | |||||
assertEquals(resolvedData.getContractAddress(), data.getContractAddress()); | |||||
assertEquals(resolvedData.getEvent(), data.getEvent()); | |||||
assertArrayEquals(resolvedData.getArgs(), data.getArgs()); | |||||
System.out.println("------Assert OK ------"); | |||||
} | |||||
@Test | |||||
public void testSerialize_ContractEventSendOperation() throws Exception { | |||||
byte[] serialBytes = BinaryProtocol.encode(data, ContractEventSendOperation.class); | |||||
ContractEventSendOperation resolvedData = BinaryProtocol.decode(serialBytes); | |||||
System.out.println("------Assert start ------"); | |||||
assertEquals(resolvedData.getContractAddress(), data.getContractAddress()); | |||||
assertEquals(resolvedData.getEvent(), data.getEvent()); | |||||
byte[] expectedBytes = BinaryProtocol.encode(resolvedData.getArgs(), BytesValueList.class); | |||||
byte[] actualBytes = BinaryProtocol.encode(data.getArgs(), BytesValueList.class); | |||||
assertArrayEquals(expectedBytes, actualBytes); | |||||
System.out.println("------Assert OK ------"); | |||||
} | |||||
@Test | |||||
public void testSerialize_Operation() throws Exception { | |||||
byte[] serialBytes = BinaryProtocol.encode(data, Operation.class); | |||||
Operation resolvedData = BinaryProtocol.decode(serialBytes); | |||||
System.out.println("------Assert start ------"); | |||||
System.out.println(resolvedData); | |||||
System.out.println("------Assert OK ------"); | |||||
} | |||||
@Test | |||||
public void testSerialize_Operation() throws Exception { | |||||
byte[] serialBytes = BinaryProtocol.encode(data, Operation.class); | |||||
Operation resolvedData = BinaryProtocol.decode(serialBytes); | |||||
System.out.println("------Assert start ------"); | |||||
System.out.println(resolvedData); | |||||
System.out.println("------Assert OK ------"); | |||||
} | |||||
} | } |
@@ -16,7 +16,7 @@ import org.junit.Test; | |||||
import com.jd.blockchain.binaryproto.BinaryProtocol; | import com.jd.blockchain.binaryproto.BinaryProtocol; | ||||
import com.jd.blockchain.binaryproto.DataContractRegistry; | import com.jd.blockchain.binaryproto.DataContractRegistry; | ||||
import com.jd.blockchain.ledger.BytesValueEntry; | |||||
import com.jd.blockchain.ledger.BytesData; | |||||
import com.jd.blockchain.ledger.DataAccountKVSetOperation; | import com.jd.blockchain.ledger.DataAccountKVSetOperation; | ||||
import com.jd.blockchain.ledger.Operation; | import com.jd.blockchain.ledger.Operation; | ||||
import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; | import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; | ||||
@@ -42,11 +42,11 @@ public class DataAccountKVSetOpTemplateTest { | |||||
String accountAddress = "zhangsandhakhdkah"; | String accountAddress = "zhangsandhakhdkah"; | ||||
data = new DataAccountKVSetOpTemplate(Bytes.fromString(accountAddress)); | data = new DataAccountKVSetOpTemplate(Bytes.fromString(accountAddress)); | ||||
KVData kvData1 = | KVData kvData1 = | ||||
new KVData("test1", BytesValueEntry.fromText("zhangsan"), 9999L); | |||||
new KVData("test1", BytesData.fromText("zhangsan"), 9999L); | |||||
KVData kvData2 = | KVData kvData2 = | ||||
new KVData("test2", BytesValueEntry.fromText("lisi"), 9990L); | |||||
new KVData("test2", BytesData.fromText("lisi"), 9990L); | |||||
KVData kvData3 = | KVData kvData3 = | ||||
new KVData("test3", BytesValueEntry.fromText("wangwu"), 1990L); | |||||
new KVData("test3", BytesData.fromText("wangwu"), 1990L); | |||||
data.set(kvData1); | data.set(kvData1); | ||||
data.set(kvData2); | data.set(kvData2); | ||||
data.set(kvData3); | data.set(kvData3); | ||||
@@ -16,7 +16,7 @@ import org.junit.Test; | |||||
import com.jd.blockchain.binaryproto.BinaryProtocol; | import com.jd.blockchain.binaryproto.BinaryProtocol; | ||||
import com.jd.blockchain.binaryproto.DataContractRegistry; | import com.jd.blockchain.binaryproto.DataContractRegistry; | ||||
import com.jd.blockchain.ledger.BytesValueEntry; | |||||
import com.jd.blockchain.ledger.BytesData; | |||||
import com.jd.blockchain.ledger.DataAccountKVSetOperation; | import com.jd.blockchain.ledger.DataAccountKVSetOperation; | ||||
import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; | import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; | ||||
import com.jd.blockchain.transaction.KVData; | import com.jd.blockchain.transaction.KVData; | ||||
@@ -38,7 +38,7 @@ public class KVDataTest { | |||||
byte[] value = "test-value".getBytes(); | byte[] value = "test-value".getBytes(); | ||||
long expectedVersion = 9999L; | long expectedVersion = 9999L; | ||||
kvData = new KVData(key, BytesValueEntry.fromBytes(value), expectedVersion); | |||||
kvData = new KVData(key, BytesData.fromBytes(value), expectedVersion); | |||||
} | } | ||||
@Test | @Test | ||||
@@ -31,346 +31,348 @@ import java.lang.reflect.Field; | |||||
public class ClientResolveUtil { | public class ClientResolveUtil { | ||||
public static KVDataEntry[] read(KVDataEntry[] kvDataEntries) { | |||||
if (kvDataEntries == null || kvDataEntries.length == 0) { | |||||
return kvDataEntries; | |||||
} | |||||
KVDataEntry[] resolveKvDataEntries = new KVDataEntry[kvDataEntries.length]; | |||||
// kvDataEntries是代理对象,需要处理 | |||||
for (int i = 0; i < kvDataEntries.length; i++) { | |||||
KVDataEntry kvDataEntry = kvDataEntries[i]; | |||||
String key = kvDataEntry.getKey(); | |||||
long version = kvDataEntry.getVersion(); | |||||
DataType dataType = kvDataEntry.getType(); | |||||
KvData innerKvData = new KvData(key, version, dataType); | |||||
Object valueObj = kvDataEntry.getValue(); | |||||
switch (dataType) { | |||||
case NIL: | |||||
break; | |||||
case BYTES: | |||||
case TEXT: | |||||
case JSON: | |||||
innerKvData.setValue(valueObj.toString()); | |||||
break; | |||||
case INT32: | |||||
innerKvData.setValue(Integer.parseInt(valueObj.toString())); | |||||
break; | |||||
case INT64: | |||||
innerKvData.setValue(Long.parseLong(valueObj.toString())); | |||||
break; | |||||
default: | |||||
throw new IllegalStateException("Unsupported value type[" + dataType + "] to resolve!"); | |||||
} | |||||
resolveKvDataEntries[i] = innerKvData; | |||||
} | |||||
return resolveKvDataEntries; | |||||
} | |||||
public static Operation read(Operation operation) { | |||||
try { | |||||
// Class | |||||
Class<?> clazz = operation.getClass(); | |||||
Field field = clazz.getSuperclass().getDeclaredField("h"); | |||||
field.setAccessible(true); | |||||
Object object = field.get(operation); | |||||
if (object instanceof JSONObject) { | |||||
JSONObject jsonObject = (JSONObject) object; | |||||
if (jsonObject.containsKey("accountID")) { | |||||
return convertDataAccountRegisterOperation(jsonObject); | |||||
} else if (jsonObject.containsKey("userID")) { | |||||
return convertUserRegisterOperation(jsonObject); | |||||
} else if (jsonObject.containsKey("contractID")) { | |||||
return convertContractCodeDeployOperation(jsonObject); | |||||
} else if (jsonObject.containsKey("writeSet")) { | |||||
return convertDataAccountKVSetOperation(jsonObject); | |||||
} else if (jsonObject.containsKey("initSetting")) { | |||||
return convertLedgerInitOperation(jsonObject); | |||||
} else if (jsonObject.containsKey("contractAddress")) { | |||||
return convertContractEventSendOperation(jsonObject); | |||||
} | |||||
} | |||||
} catch (Exception e) { | |||||
throw new RuntimeException(e); | |||||
} | |||||
return null; | |||||
} | |||||
public static Object readValueByBytesValue(BytesValue bytesValue) { | |||||
DataType dataType = bytesValue.getType(); | |||||
Bytes saveVal = bytesValue.getValue(); | |||||
Object showVal; | |||||
switch (dataType) { | |||||
case BYTES: | |||||
// return hex | |||||
showVal = HexUtils.encode(saveVal.toBytes()); | |||||
break; | |||||
case TEXT: | |||||
case JSON: | |||||
showVal = saveVal.toUTF8String(); | |||||
break; | |||||
case INT64: | |||||
showVal = BytesUtils.toLong(saveVal.toBytes()); | |||||
break; | |||||
default: | |||||
showVal = HexUtils.encode(saveVal.toBytes()); | |||||
break; | |||||
} | |||||
return showVal; | |||||
} | |||||
public static DataAccountRegisterOperation convertDataAccountRegisterOperation(JSONObject jsonObject) { | |||||
JSONObject account = jsonObject.getJSONObject("accountID"); | |||||
return new DataAccountRegisterOpTemplate(blockchainIdentity(account)); | |||||
} | |||||
public static DataAccountKVSetOperation convertDataAccountKVSetOperation(JSONObject jsonObject) { | |||||
// 写入集合处理 | |||||
JSONArray writeSetObj = jsonObject.getJSONArray("writeSet"); | |||||
JSONObject accountAddrObj = jsonObject.getJSONObject("accountAddress"); | |||||
String addressBase58 = accountAddrObj.getString("value"); | |||||
Bytes address = Bytes.fromBase58(addressBase58); | |||||
DataAccountKVSetOpTemplate kvOperation = new DataAccountKVSetOpTemplate(address); | |||||
for (int i = 0; i <writeSetObj.size(); i++) { | |||||
JSONObject currWriteSetObj = writeSetObj.getJSONObject(i); | |||||
long expectedVersion = currWriteSetObj.getLong("expectedVersion"); | |||||
JSONObject valueObj = currWriteSetObj.getJSONObject("value"); | |||||
String typeStr = valueObj.getString("type"); | |||||
String realValBase58 = valueObj.getString("value"); | |||||
String key = currWriteSetObj.getString("key"); | |||||
DataType dataType = DataType.valueOf(typeStr); | |||||
BytesValue bytesValue =BytesValueEntry.fromType(dataType, Base58Utils.decode(realValBase58)); | |||||
KVData kvData = new KVData(key, bytesValue, expectedVersion); | |||||
kvOperation.set(kvData); | |||||
} | |||||
return kvOperation; | |||||
} | |||||
public static LedgerInitOperation convertLedgerInitOperation(JSONObject jsonObject) { | |||||
JSONObject legerInitObj = jsonObject.getJSONObject("initSetting"); | |||||
LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData(); | |||||
String ledgerSeedStr = legerInitObj.getString("ledgerSeed"); | |||||
// 种子需要做Base64转换 | |||||
ledgerInitSettingData.setLedgerSeed(Base64.decodeBase64(BytesUtils.toBytes(ledgerSeedStr))); | |||||
String consensusProvider = legerInitObj.getString("consensusProvider"); | |||||
ledgerInitSettingData.setConsensusProvider(consensusProvider); | |||||
JSONObject cryptoSettingObj = legerInitObj.getJSONObject("cryptoSetting"); | |||||
boolean autoVerifyHash = cryptoSettingObj.getBoolean("autoVerifyHash"); | |||||
short hashAlgorithm = cryptoSettingObj.getShort("hashAlgorithm"); | |||||
CryptoConfig cryptoConfig = new CryptoConfig(); | |||||
cryptoConfig.setAutoVerifyHash(autoVerifyHash); | |||||
cryptoConfig.setHashAlgorithm(hashAlgorithm); | |||||
ledgerInitSettingData.setCryptoSetting(cryptoConfig); | |||||
JSONObject consensusSettingsObj = legerInitObj.getJSONObject("consensusSettings"); | |||||
Bytes consensusSettings = Bytes.fromBase58(consensusSettingsObj.getString("value")); | |||||
ledgerInitSettingData.setConsensusSettings(consensusSettings); | |||||
JSONArray consensusParticipantsArray = legerInitObj.getJSONArray("consensusParticipants"); | |||||
if (!consensusParticipantsArray.isEmpty()) { | |||||
ParticipantNode[] participantNodes = new ParticipantNode[consensusParticipantsArray.size()]; | |||||
for (int i = 0; i < consensusParticipantsArray.size(); i++) { | |||||
JSONObject currConsensusParticipant = consensusParticipantsArray.getJSONObject(i); | |||||
String addressBase58 = currConsensusParticipant.getString("address"); | |||||
String name = currConsensusParticipant.getString("name"); | |||||
int id = currConsensusParticipant.getInteger("id"); | |||||
JSONObject pubKeyObj = currConsensusParticipant.getJSONObject("pubKey"); | |||||
String pubKeyBase58 = pubKeyObj.getString("value"); | |||||
// 生成ParticipantNode对象 | |||||
ParticipantCertData participantCertData = new ParticipantCertData(id, addressBase58, name, new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes())); | |||||
participantNodes[i] = participantCertData; | |||||
} | |||||
ledgerInitSettingData.setConsensusParticipants(participantNodes); | |||||
} | |||||
return new LedgerInitOpTemplate(ledgerInitSettingData); | |||||
} | |||||
public static UserRegisterOperation convertUserRegisterOperation(JSONObject jsonObject) { | |||||
JSONObject user = jsonObject.getJSONObject("userID"); | |||||
return new UserRegisterOpTemplate(blockchainIdentity(user)); | |||||
} | |||||
public static ContractCodeDeployOperation convertContractCodeDeployOperation(JSONObject jsonObject) { | |||||
JSONObject contract = jsonObject.getJSONObject("contractID"); | |||||
BlockchainIdentityData blockchainIdentity = blockchainIdentity(contract); | |||||
String chainCodeStr = jsonObject.getString("chainCode"); | |||||
ContractCodeDeployOpTemplate contractCodeDeployOpTemplate = new ContractCodeDeployOpTemplate(blockchainIdentity, BytesUtils.toBytes(chainCodeStr)); | |||||
return contractCodeDeployOpTemplate; | |||||
} | |||||
public static ContractEventSendOperation convertContractEventSendOperation(JSONObject jsonObject) { | |||||
JSONObject contractAddressObj = jsonObject.getJSONObject("contractAddress"); | |||||
String contractAddress = contractAddressObj.getString("value"); | |||||
String argsStr = jsonObject.getString("args"); | |||||
String event = jsonObject.getString("event"); | |||||
return new ContractEventSendOpTemplate(Bytes.fromBase58(contractAddress), event, BytesUtils.toBytes(argsStr)); | |||||
} | |||||
private static BlockchainIdentityData blockchainIdentity(JSONObject jsonObject) { | |||||
JSONObject addressObj = jsonObject.getJSONObject("address"); | |||||
// base58值 | |||||
String addressBase58 = addressObj.getString("value"); | |||||
Bytes address = Bytes.fromBase58(addressBase58); | |||||
JSONObject pubKeyObj = jsonObject.getJSONObject("pubKey"); | |||||
// base58值 | |||||
String pubKeyBase58 = pubKeyObj.getString("value"); | |||||
PubKey pubKey = new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes()); | |||||
// 生成对应的对象 | |||||
return new BlockchainIdentityData(address, pubKey); | |||||
} | |||||
public static class CryptoConfig implements CryptoSetting { | |||||
private short hashAlgorithm; | |||||
private boolean autoVerifyHash; | |||||
@Override | |||||
public CryptoProvider[] getSupportedProviders() { | |||||
return new CryptoProvider[0]; | |||||
} | |||||
@Override | |||||
public short getHashAlgorithm() { | |||||
return hashAlgorithm; | |||||
} | |||||
@Override | |||||
public boolean getAutoVerifyHash() { | |||||
return autoVerifyHash; | |||||
} | |||||
public void setHashAlgorithm(short hashAlgorithm) { | |||||
this.hashAlgorithm = hashAlgorithm; | |||||
} | |||||
public void setAutoVerifyHash(boolean autoVerifyHash) { | |||||
this.autoVerifyHash = autoVerifyHash; | |||||
} | |||||
} | |||||
public static class ParticipantCertData implements ParticipantNode{ | |||||
private int id; | |||||
private String address; | |||||
private String name; | |||||
private PubKey pubKey; | |||||
public ParticipantCertData() { | |||||
} | |||||
public ParticipantCertData(ParticipantNode participantNode) { | |||||
this.address = participantNode.getAddress(); | |||||
this.name = participantNode.getName(); | |||||
this.pubKey = participantNode.getPubKey(); | |||||
} | |||||
public ParticipantCertData(int id, String address, String name, PubKey pubKey) { | |||||
this.id = id; | |||||
this.address = address; | |||||
this.name = name; | |||||
this.pubKey = pubKey; | |||||
} | |||||
@Override | |||||
public String getAddress() { | |||||
return address; | |||||
} | |||||
@Override | |||||
public String getName() { | |||||
return name; | |||||
} | |||||
@Override | |||||
public PubKey getPubKey() { | |||||
return pubKey; | |||||
} | |||||
public int getId() { | |||||
return id; | |||||
} | |||||
public void setId(int id) { | |||||
this.id = id; | |||||
} | |||||
} | |||||
public static class KvData implements KVDataEntry { | |||||
private String key; | |||||
private long version; | |||||
private DataType dataType; | |||||
private Object value; | |||||
public KvData() { | |||||
} | |||||
public KvData(String key, long version, DataType dataType) { | |||||
this(key, version, dataType, null); | |||||
} | |||||
public KvData(String key, long version, DataType dataType, Object value) { | |||||
this.key = key; | |||||
this.version = version; | |||||
this.dataType = dataType; | |||||
this.value = value; | |||||
} | |||||
public void setKey(String key) { | |||||
this.key = key; | |||||
} | |||||
public void setVersion(long version) { | |||||
this.version = version; | |||||
} | |||||
public void setDataType(DataType dataType) { | |||||
this.dataType = dataType; | |||||
} | |||||
public void setValue(Object value) { | |||||
this.value = value; | |||||
} | |||||
@Override | |||||
public String getKey() { | |||||
return key; | |||||
} | |||||
@Override | |||||
public long getVersion() { | |||||
return version; | |||||
} | |||||
@Override | |||||
public DataType getType() { | |||||
return dataType; | |||||
} | |||||
@Override | |||||
public Object getValue() { | |||||
return value; | |||||
} | |||||
} | |||||
public static KVDataEntry[] read(KVDataEntry[] kvDataEntries) { | |||||
if (kvDataEntries == null || kvDataEntries.length == 0) { | |||||
return kvDataEntries; | |||||
} | |||||
KVDataEntry[] resolveKvDataEntries = new KVDataEntry[kvDataEntries.length]; | |||||
// kvDataEntries是代理对象,需要处理 | |||||
for (int i = 0; i < kvDataEntries.length; i++) { | |||||
KVDataEntry kvDataEntry = kvDataEntries[i]; | |||||
String key = kvDataEntry.getKey(); | |||||
long version = kvDataEntry.getVersion(); | |||||
DataType dataType = kvDataEntry.getType(); | |||||
KvData innerKvData = new KvData(key, version, dataType); | |||||
Object valueObj = kvDataEntry.getValue(); | |||||
switch (dataType) { | |||||
case NIL: | |||||
break; | |||||
case BYTES: | |||||
case TEXT: | |||||
case JSON: | |||||
innerKvData.setValue(valueObj.toString()); | |||||
break; | |||||
case INT32: | |||||
innerKvData.setValue(Integer.parseInt(valueObj.toString())); | |||||
break; | |||||
case INT64: | |||||
innerKvData.setValue(Long.parseLong(valueObj.toString())); | |||||
break; | |||||
default: | |||||
throw new IllegalStateException("Unsupported value type[" + dataType + "] to resolve!"); | |||||
} | |||||
resolveKvDataEntries[i] = innerKvData; | |||||
} | |||||
return resolveKvDataEntries; | |||||
} | |||||
public static Operation read(Operation operation) { | |||||
try { | |||||
// Class | |||||
Class<?> clazz = operation.getClass(); | |||||
Field field = clazz.getSuperclass().getDeclaredField("h"); | |||||
field.setAccessible(true); | |||||
Object object = field.get(operation); | |||||
if (object instanceof JSONObject) { | |||||
JSONObject jsonObject = (JSONObject) object; | |||||
if (jsonObject.containsKey("accountID")) { | |||||
return convertDataAccountRegisterOperation(jsonObject); | |||||
} else if (jsonObject.containsKey("userID")) { | |||||
return convertUserRegisterOperation(jsonObject); | |||||
} else if (jsonObject.containsKey("contractID")) { | |||||
return convertContractCodeDeployOperation(jsonObject); | |||||
} else if (jsonObject.containsKey("writeSet")) { | |||||
return convertDataAccountKVSetOperation(jsonObject); | |||||
} else if (jsonObject.containsKey("initSetting")) { | |||||
return convertLedgerInitOperation(jsonObject); | |||||
} else if (jsonObject.containsKey("contractAddress")) { | |||||
return convertContractEventSendOperation(jsonObject); | |||||
} | |||||
} | |||||
} catch (Exception e) { | |||||
throw new RuntimeException(e); | |||||
} | |||||
return null; | |||||
} | |||||
public static Object readValueByBytesValue(BytesValue bytesValue) { | |||||
DataType dataType = bytesValue.getType(); | |||||
Bytes saveVal = bytesValue.getValue(); | |||||
Object showVal; | |||||
switch (dataType) { | |||||
case BYTES: | |||||
// return hex | |||||
showVal = HexUtils.encode(saveVal.toBytes()); | |||||
break; | |||||
case TEXT: | |||||
case JSON: | |||||
showVal = saveVal.toUTF8String(); | |||||
break; | |||||
case INT64: | |||||
showVal = BytesUtils.toLong(saveVal.toBytes()); | |||||
break; | |||||
default: | |||||
showVal = HexUtils.encode(saveVal.toBytes()); | |||||
break; | |||||
} | |||||
return showVal; | |||||
} | |||||
public static DataAccountRegisterOperation convertDataAccountRegisterOperation(JSONObject jsonObject) { | |||||
JSONObject account = jsonObject.getJSONObject("accountID"); | |||||
return new DataAccountRegisterOpTemplate(blockchainIdentity(account)); | |||||
} | |||||
public static DataAccountKVSetOperation convertDataAccountKVSetOperation(JSONObject jsonObject) { | |||||
// 写入集合处理 | |||||
JSONArray writeSetObj = jsonObject.getJSONArray("writeSet"); | |||||
JSONObject accountAddrObj = jsonObject.getJSONObject("accountAddress"); | |||||
String addressBase58 = accountAddrObj.getString("value"); | |||||
Bytes address = Bytes.fromBase58(addressBase58); | |||||
DataAccountKVSetOpTemplate kvOperation = new DataAccountKVSetOpTemplate(address); | |||||
for (int i = 0; i < writeSetObj.size(); i++) { | |||||
JSONObject currWriteSetObj = writeSetObj.getJSONObject(i); | |||||
long expectedVersion = currWriteSetObj.getLong("expectedVersion"); | |||||
JSONObject valueObj = currWriteSetObj.getJSONObject("value"); | |||||
String typeStr = valueObj.getString("type"); | |||||
String realValBase58 = valueObj.getString("value"); | |||||
String key = currWriteSetObj.getString("key"); | |||||
DataType dataType = DataType.valueOf(typeStr); | |||||
BytesValue bytesValue = BytesData.fromType(dataType, Base58Utils.decode(realValBase58)); | |||||
KVData kvData = new KVData(key, bytesValue, expectedVersion); | |||||
kvOperation.set(kvData); | |||||
} | |||||
return kvOperation; | |||||
} | |||||
public static LedgerInitOperation convertLedgerInitOperation(JSONObject jsonObject) { | |||||
JSONObject legerInitObj = jsonObject.getJSONObject("initSetting"); | |||||
LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData(); | |||||
String ledgerSeedStr = legerInitObj.getString("ledgerSeed"); | |||||
// 种子需要做Base64转换 | |||||
ledgerInitSettingData.setLedgerSeed(Base64.decodeBase64(BytesUtils.toBytes(ledgerSeedStr))); | |||||
String consensusProvider = legerInitObj.getString("consensusProvider"); | |||||
ledgerInitSettingData.setConsensusProvider(consensusProvider); | |||||
JSONObject cryptoSettingObj = legerInitObj.getJSONObject("cryptoSetting"); | |||||
boolean autoVerifyHash = cryptoSettingObj.getBoolean("autoVerifyHash"); | |||||
short hashAlgorithm = cryptoSettingObj.getShort("hashAlgorithm"); | |||||
CryptoConfig cryptoConfig = new CryptoConfig(); | |||||
cryptoConfig.setAutoVerifyHash(autoVerifyHash); | |||||
cryptoConfig.setHashAlgorithm(hashAlgorithm); | |||||
ledgerInitSettingData.setCryptoSetting(cryptoConfig); | |||||
JSONObject consensusSettingsObj = legerInitObj.getJSONObject("consensusSettings"); | |||||
Bytes consensusSettings = Bytes.fromBase58(consensusSettingsObj.getString("value")); | |||||
ledgerInitSettingData.setConsensusSettings(consensusSettings); | |||||
JSONArray consensusParticipantsArray = legerInitObj.getJSONArray("consensusParticipants"); | |||||
if (!consensusParticipantsArray.isEmpty()) { | |||||
ParticipantNode[] participantNodes = new ParticipantNode[consensusParticipantsArray.size()]; | |||||
for (int i = 0; i < consensusParticipantsArray.size(); i++) { | |||||
JSONObject currConsensusParticipant = consensusParticipantsArray.getJSONObject(i); | |||||
String addressBase58 = currConsensusParticipant.getString("address"); | |||||
String name = currConsensusParticipant.getString("name"); | |||||
int id = currConsensusParticipant.getInteger("id"); | |||||
JSONObject pubKeyObj = currConsensusParticipant.getJSONObject("pubKey"); | |||||
String pubKeyBase58 = pubKeyObj.getString("value"); | |||||
// 生成ParticipantNode对象 | |||||
ParticipantCertData participantCertData = new ParticipantCertData(id, addressBase58, name, | |||||
new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes())); | |||||
participantNodes[i] = participantCertData; | |||||
} | |||||
ledgerInitSettingData.setConsensusParticipants(participantNodes); | |||||
} | |||||
return new LedgerInitOpTemplate(ledgerInitSettingData); | |||||
} | |||||
public static UserRegisterOperation convertUserRegisterOperation(JSONObject jsonObject) { | |||||
JSONObject user = jsonObject.getJSONObject("userID"); | |||||
return new UserRegisterOpTemplate(blockchainIdentity(user)); | |||||
} | |||||
public static ContractCodeDeployOperation convertContractCodeDeployOperation(JSONObject jsonObject) { | |||||
JSONObject contract = jsonObject.getJSONObject("contractID"); | |||||
BlockchainIdentityData blockchainIdentity = blockchainIdentity(contract); | |||||
String chainCodeStr = jsonObject.getString("chainCode"); | |||||
ContractCodeDeployOpTemplate contractCodeDeployOpTemplate = new ContractCodeDeployOpTemplate(blockchainIdentity, | |||||
BytesUtils.toBytes(chainCodeStr)); | |||||
return contractCodeDeployOpTemplate; | |||||
} | |||||
public static ContractEventSendOperation convertContractEventSendOperation(JSONObject jsonObject) { | |||||
JSONObject contractAddressObj = jsonObject.getJSONObject("contractAddress"); | |||||
String contractAddress = contractAddressObj.getString("value"); | |||||
String argsStr = jsonObject.getString("args"); | |||||
String event = jsonObject.getString("event"); | |||||
return new ContractEventSendOpTemplate(Bytes.fromBase58(contractAddress), event, | |||||
BytesDataList.singleText(argsStr)); | |||||
} | |||||
private static BlockchainIdentityData blockchainIdentity(JSONObject jsonObject) { | |||||
JSONObject addressObj = jsonObject.getJSONObject("address"); | |||||
// base58值 | |||||
String addressBase58 = addressObj.getString("value"); | |||||
Bytes address = Bytes.fromBase58(addressBase58); | |||||
JSONObject pubKeyObj = jsonObject.getJSONObject("pubKey"); | |||||
// base58值 | |||||
String pubKeyBase58 = pubKeyObj.getString("value"); | |||||
PubKey pubKey = new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes()); | |||||
// 生成对应的对象 | |||||
return new BlockchainIdentityData(address, pubKey); | |||||
} | |||||
public static class CryptoConfig implements CryptoSetting { | |||||
private short hashAlgorithm; | |||||
private boolean autoVerifyHash; | |||||
@Override | |||||
public CryptoProvider[] getSupportedProviders() { | |||||
return new CryptoProvider[0]; | |||||
} | |||||
@Override | |||||
public short getHashAlgorithm() { | |||||
return hashAlgorithm; | |||||
} | |||||
@Override | |||||
public boolean getAutoVerifyHash() { | |||||
return autoVerifyHash; | |||||
} | |||||
public void setHashAlgorithm(short hashAlgorithm) { | |||||
this.hashAlgorithm = hashAlgorithm; | |||||
} | |||||
public void setAutoVerifyHash(boolean autoVerifyHash) { | |||||
this.autoVerifyHash = autoVerifyHash; | |||||
} | |||||
} | |||||
public static class ParticipantCertData implements ParticipantNode { | |||||
private int id; | |||||
private String address; | |||||
private String name; | |||||
private PubKey pubKey; | |||||
public ParticipantCertData() { | |||||
} | |||||
public ParticipantCertData(ParticipantNode participantNode) { | |||||
this.address = participantNode.getAddress(); | |||||
this.name = participantNode.getName(); | |||||
this.pubKey = participantNode.getPubKey(); | |||||
} | |||||
public ParticipantCertData(int id, String address, String name, PubKey pubKey) { | |||||
this.id = id; | |||||
this.address = address; | |||||
this.name = name; | |||||
this.pubKey = pubKey; | |||||
} | |||||
@Override | |||||
public String getAddress() { | |||||
return address; | |||||
} | |||||
@Override | |||||
public String getName() { | |||||
return name; | |||||
} | |||||
@Override | |||||
public PubKey getPubKey() { | |||||
return pubKey; | |||||
} | |||||
public int getId() { | |||||
return id; | |||||
} | |||||
public void setId(int id) { | |||||
this.id = id; | |||||
} | |||||
} | |||||
public static class KvData implements KVDataEntry { | |||||
private String key; | |||||
private long version; | |||||
private DataType dataType; | |||||
private Object value; | |||||
public KvData() { | |||||
} | |||||
public KvData(String key, long version, DataType dataType) { | |||||
this(key, version, dataType, null); | |||||
} | |||||
public KvData(String key, long version, DataType dataType, Object value) { | |||||
this.key = key; | |||||
this.version = version; | |||||
this.dataType = dataType; | |||||
this.value = value; | |||||
} | |||||
public void setKey(String key) { | |||||
this.key = key; | |||||
} | |||||
public void setVersion(long version) { | |||||
this.version = version; | |||||
} | |||||
public void setDataType(DataType dataType) { | |||||
this.dataType = dataType; | |||||
} | |||||
public void setValue(Object value) { | |||||
this.value = value; | |||||
} | |||||
@Override | |||||
public String getKey() { | |||||
return key; | |||||
} | |||||
@Override | |||||
public long getVersion() { | |||||
return version; | |||||
} | |||||
@Override | |||||
public DataType getType() { | |||||
return dataType; | |||||
} | |||||
@Override | |||||
public Object getValue() { | |||||
return value; | |||||
} | |||||
} | |||||
} | } |
@@ -11,7 +11,7 @@ import com.jd.blockchain.ledger.PreparedTransaction; | |||||
import com.jd.blockchain.ledger.TransactionResponse; | import com.jd.blockchain.ledger.TransactionResponse; | ||||
import com.jd.blockchain.ledger.TransactionTemplate; | import com.jd.blockchain.ledger.TransactionTemplate; | ||||
import com.jd.blockchain.transaction.LongValueHolder; | import com.jd.blockchain.transaction.LongValueHolder; | ||||
import com.jd.blockchain.transaction.ValueHolder; | |||||
import com.jd.blockchain.transaction.GenericValueHolder; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
public class SDK_Contract_Demo extends SDK_Base_Demo { | public class SDK_Contract_Demo extends SDK_Base_Demo { | ||||
@@ -92,7 +92,7 @@ public class SDK_Contract_Demo extends SDK_Base_Demo { | |||||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | ||||
// 使用合约创建 | // 使用合约创建 | ||||
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | ||||
ValueHolder<String> result = decode(transferContract.readAll(address, account)); | |||||
GenericValueHolder<String> result = decode(transferContract.readAll(address, account)); | |||||
commit(txTpl); | commit(txTpl); | ||||
return result.get(); | return result.get(); | ||||
} | } | ||||
@@ -122,7 +122,7 @@ public class SDK_Contract_Demo extends SDK_Base_Demo { | |||||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | ||||
// 使用合约创建 | // 使用合约创建 | ||||
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | ||||
ValueHolder<String> result = decode(transferContract.transfer(address, from, to, money)); | |||||
GenericValueHolder<String> result = decode(transferContract.transfer(address, from, to, money)); | |||||
commit(txTpl); | commit(txTpl); | ||||
return result.get(); | return result.get(); | ||||
} | } | ||||
@@ -142,7 +142,7 @@ public class SDK_Contract_Demo extends SDK_Base_Demo { | |||||
if (useContract) { | if (useContract) { | ||||
// 使用合约创建 | // 使用合约创建 | ||||
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | ||||
ValueHolder<String> result = decode(transferContract.create(address, account, money)); | |||||
GenericValueHolder<String> result = decode(transferContract.create(address, account, money)); | |||||
commit(txTpl); | commit(txTpl); | ||||
return result.get(); | return result.get(); | ||||
} else { | } else { | ||||
@@ -20,7 +20,7 @@ import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||||
import com.jd.blockchain.sdk.samples.SDKDemo_Constant; | import com.jd.blockchain.sdk.samples.SDKDemo_Constant; | ||||
import com.jd.blockchain.tools.keygen.KeyGenCommand; | import com.jd.blockchain.tools.keygen.KeyGenCommand; | ||||
import com.jd.blockchain.transaction.LongValueHolder; | import com.jd.blockchain.transaction.LongValueHolder; | ||||
import com.jd.blockchain.transaction.ValueHolder; | |||||
import com.jd.blockchain.transaction.GenericValueHolder; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
public class SDKDemo_Contract_Test { | public class SDKDemo_Contract_Test { | ||||
@@ -108,7 +108,7 @@ public class SDKDemo_Contract_Test { | |||||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | ||||
// 使用合约创建 | // 使用合约创建 | ||||
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | ||||
ValueHolder<String> result = decode(transferContract.readAll(address, account)); | |||||
GenericValueHolder<String> result = decode(transferContract.readAll(address, account)); | |||||
commit(txTpl); | commit(txTpl); | ||||
return result.get(); | return result.get(); | ||||
} | } | ||||
@@ -126,7 +126,7 @@ public class SDKDemo_Contract_Test { | |||||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | ||||
// 使用合约创建 | // 使用合约创建 | ||||
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | ||||
ValueHolder<String> result = decode(transferContract.transfer(address, from, to, money)); | |||||
GenericValueHolder<String> result = decode(transferContract.transfer(address, from, to, money)); | |||||
commit(txTpl); | commit(txTpl); | ||||
return result.get(); | return result.get(); | ||||
} | } | ||||
@@ -146,7 +146,7 @@ public class SDKDemo_Contract_Test { | |||||
if (useContract) { | if (useContract) { | ||||
// 使用合约创建 | // 使用合约创建 | ||||
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | ||||
ValueHolder<String> result = decode(transferContract.create(address, account, money)); | |||||
GenericValueHolder<String> result = decode(transferContract.create(address, account, money)); | |||||
commit(txTpl); | commit(txTpl); | ||||
return result.get(); | return result.get(); | ||||
} else { | } else { | ||||
@@ -24,6 +24,7 @@ import com.jd.blockchain.crypto.PrivKey; | |||||
import com.jd.blockchain.ledger.BlockchainIdentity; | import com.jd.blockchain.ledger.BlockchainIdentity; | ||||
import com.jd.blockchain.ledger.BlockchainKeyGenerator; | import com.jd.blockchain.ledger.BlockchainKeyGenerator; | ||||
import com.jd.blockchain.ledger.BlockchainKeypair; | import com.jd.blockchain.ledger.BlockchainKeypair; | ||||
import com.jd.blockchain.ledger.BytesDataList; | |||||
import com.jd.blockchain.ledger.DataAccountKVSetOperation; | import com.jd.blockchain.ledger.DataAccountKVSetOperation; | ||||
import com.jd.blockchain.ledger.DataAccountRegisterOperation; | import com.jd.blockchain.ledger.DataAccountRegisterOperation; | ||||
import com.jd.blockchain.ledger.LedgerBlock; | import com.jd.blockchain.ledger.LedgerBlock; | ||||
@@ -143,8 +144,9 @@ public class LedgerPerformanceTest { | |||||
batchCount = Integer.parseInt(args[1]); | batchCount = Integer.parseInt(args[1]); | ||||
} | } | ||||
} | } | ||||
if (contract){ | |||||
testContract(ledgerHash, testNode.getPartiKey(), ledgerManager, opHandler, batchSize, batchCount, silent); | |||||
if (contract) { | |||||
testContract(ledgerHash, testNode.getPartiKey(), ledgerManager, opHandler, batchSize, batchCount, | |||||
silent); | |||||
} | } | ||||
if (usertest) { | if (usertest) { | ||||
@@ -177,8 +179,9 @@ public class LedgerPerformanceTest { | |||||
* @param batchCount | * @param batchCount | ||||
* @param silent | * @param silent | ||||
*/ | */ | ||||
private static void testUserRegistering(HashDigest ledgerHash, AsymmetricKeypair adminKey, LedgerManager ledgerManager, | |||||
DefaultOperationHandleRegisteration opHandler, int batchSize, int batchCount, boolean silent) { | |||||
private static void testUserRegistering(HashDigest ledgerHash, AsymmetricKeypair adminKey, | |||||
LedgerManager ledgerManager, DefaultOperationHandleRegisteration opHandler, int batchSize, int batchCount, | |||||
boolean silent) { | |||||
LedgerRepository ledger = ledgerManager.getLedger(ledgerHash); | LedgerRepository ledger = ledgerManager.getLedger(ledgerHash); | ||||
ConsoleUtils.info("\r\n\r\n================= 准备测试交易 [注册用户] ================="); | ConsoleUtils.info("\r\n\r\n================= 准备测试交易 [注册用户] ================="); | ||||
@@ -273,7 +276,7 @@ public class LedgerPerformanceTest { | |||||
* @param silent | * @param silent | ||||
*/ | */ | ||||
private static void testContract(HashDigest ledgerHash, AsymmetricKeypair adminKey, LedgerManager ledgerManager, | private static void testContract(HashDigest ledgerHash, AsymmetricKeypair adminKey, LedgerManager ledgerManager, | ||||
DefaultOperationHandleRegisteration opHandler, int batchSize, int batchCount, boolean silent) { | |||||
DefaultOperationHandleRegisteration opHandler, int batchSize, int batchCount, boolean silent) { | |||||
LedgerRepository ledger = ledgerManager.getLedger(ledgerHash); | LedgerRepository ledger = ledgerManager.getLedger(ledgerHash); | ||||
ConsoleUtils.info("\r\n\r\n================= 准备测试交易 [执行合约] ================="); | ConsoleUtils.info("\r\n\r\n================= 准备测试交易 [执行合约] ================="); | ||||
@@ -285,8 +288,8 @@ public class LedgerPerformanceTest { | |||||
// 准备请求 | // 准备请求 | ||||
int totalCount = batchSize * batchCount; | int totalCount = batchSize * batchCount; | ||||
List<TransactionRequest> contractTxList = prepareContractRequests(ledgerHash, | |||||
adminKey, totalCount, false, txProc); | |||||
List<TransactionRequest> contractTxList = prepareContractRequests(ledgerHash, adminKey, totalCount, false, | |||||
txProc); | |||||
Prompter consolePrompter = new PresetAnswerPrompter("N"); | Prompter consolePrompter = new PresetAnswerPrompter("N"); | ||||
@@ -303,6 +306,7 @@ public class LedgerPerformanceTest { | |||||
} | } | ||||
} | } | ||||
private static void execPerformanceTest(int batchCount, int batchSize, List<TransactionRequest> txList, | private static void execPerformanceTest(int batchCount, int batchSize, List<TransactionRequest> txList, | ||||
LedgerRepository ledger, LedgerManager ledgerManager, DefaultOperationHandleRegisteration opHandler, | LedgerRepository ledger, LedgerManager ledgerManager, DefaultOperationHandleRegisteration opHandler, | ||||
boolean statistic) { | boolean statistic) { | ||||
@@ -407,8 +411,7 @@ public class LedgerPerformanceTest { | |||||
// BlockchainKeyPair dataAccountKey = | // BlockchainKeyPair dataAccountKey = | ||||
// BlockchainKeyGenerator.getInstance().generate(); | // BlockchainKeyGenerator.getInstance().generate(); | ||||
BlockchainIdentity targetAccount = dataAccounts[count % dataAccounts.length]; | BlockchainIdentity targetAccount = dataAccounts[count % dataAccounts.length]; | ||||
txbuilder.dataAccount(targetAccount.getAddress()).setText("key-" + startTs + "-" + i, | |||||
"value-" + i, -1L); | |||||
txbuilder.dataAccount(targetAccount.getAddress()).setText("key-" + startTs + "-" + i, "value-" + i, -1L); | |||||
TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest(); | TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest(); | ||||
reqBuilder.signAsEndpoint(adminKey); | reqBuilder.signAsEndpoint(adminKey); | ||||
txList.add(reqBuilder.buildRequest()); | txList.add(reqBuilder.buildRequest()); | ||||
@@ -426,8 +429,9 @@ public class LedgerPerformanceTest { | |||||
public static ConsensusProvider getConsensusProvider(String provider) { | public static ConsensusProvider getConsensusProvider(String provider) { | ||||
return ConsensusProviders.getProvider(provider); | return ConsensusProviders.getProvider(provider); | ||||
} | } | ||||
public static List<TransactionRequest> prepareContractRequests(HashDigest ledgerHash, | |||||
AsymmetricKeypair adminKey, int count, boolean statistic, TransactionBatchProcessor txProc) { | |||||
public static List<TransactionRequest> prepareContractRequests(HashDigest ledgerHash, AsymmetricKeypair adminKey, | |||||
int count, boolean statistic, TransactionBatchProcessor txProc) { | |||||
// deploy contract | // deploy contract | ||||
byte[] chainCode; | byte[] chainCode; | ||||
@@ -436,7 +440,7 @@ public class LedgerPerformanceTest { | |||||
InputStream input = LedgerPerformanceTest.class.getClassLoader().getResourceAsStream("example1.jar"); | InputStream input = LedgerPerformanceTest.class.getClassLoader().getResourceAsStream("example1.jar"); | ||||
chainCode = new byte[input.available()]; | chainCode = new byte[input.available()]; | ||||
input.read(chainCode); | input.read(chainCode); | ||||
}catch (IOException e){ | |||||
} catch (IOException e) { | |||||
e.printStackTrace(); | e.printStackTrace(); | ||||
return null; | return null; | ||||
} | } | ||||
@@ -457,10 +461,10 @@ public class LedgerPerformanceTest { | |||||
System.out.println(resp.isSuccess()); | System.out.println(resp.isSuccess()); | ||||
TransactionBatchResultHandle handle = txProc.prepare(); | TransactionBatchResultHandle handle = txProc.prepare(); | ||||
handle.commit(); | handle.commit(); | ||||
try{ | |||||
try { | |||||
Thread.sleep(1000); | Thread.sleep(1000); | ||||
} catch (Exception e){ | |||||
} catch (Exception e) { | |||||
e.printStackTrace(); | e.printStackTrace(); | ||||
} | } | ||||
@@ -468,8 +472,9 @@ public class LedgerPerformanceTest { | |||||
List<TransactionRequest> txList = new ArrayList<>(); | List<TransactionRequest> txList = new ArrayList<>(); | ||||
for (int i = 0; i < count; i++) { | for (int i = 0; i < count; i++) { | ||||
txbuilder = new TxBuilder(ledgerHash); | txbuilder = new TxBuilder(ledgerHash); | ||||
String args = dataIdentity.getAddress().toString() + "##"+Integer.toString(i)+ "##"+Integer.toString(i); | |||||
txbuilder.contractEvents().send(contractIdentity.getAddress(), "hello", args.getBytes()); | |||||
String args = dataIdentity.getAddress().toString() + "##" + Integer.toString(i) + "##" | |||||
+ Integer.toString(i); | |||||
txbuilder.contractEvents().send(contractIdentity.getAddress(), "print", BytesDataList.singleText("hello")); | |||||
// txbuilder.contractEvents().send(contractIdentity.getAddress(), "print", args.getBytes()); | // txbuilder.contractEvents().send(contractIdentity.getAddress(), "print", args.getBytes()); | ||||
reqBuilder = txbuilder.prepareRequest(); | reqBuilder = txbuilder.prepareRequest(); | ||||
reqBuilder.signAsEndpoint(adminKey); | reqBuilder.signAsEndpoint(adminKey); | ||||
@@ -485,7 +490,8 @@ public class LedgerPerformanceTest { | |||||
return txList; | return txList; | ||||
} | } | ||||
public static NodeContext[] initLedgers(boolean optimized, CryptoAlgorithm hashAlg, DBType dbType, String provider, String config) { | |||||
public static NodeContext[] initLedgers(boolean optimized, CryptoAlgorithm hashAlg, DBType dbType, String provider, | |||||
String config) { | |||||
Map<NetworkAddress, LedgerInitConsensusService> serviceRegisterMap = new ConcurrentHashMap<>(); | Map<NetworkAddress, LedgerInitConsensusService> serviceRegisterMap = new ConcurrentHashMap<>(); | ||||
Prompter consolePrompter = new PresetAnswerPrompter("N"); // new ConsolePrompter(); | Prompter consolePrompter = new PresetAnswerPrompter("N"); // new ConsolePrompter(); | ||||
@@ -29,7 +29,6 @@ import org.apache.commons.io.FileUtils; | |||||
import org.springframework.core.io.ClassPathResource; | import org.springframework.core.io.ClassPathResource; | ||||
import com.jd.blockchain.binaryproto.DataContractRegistry; | import com.jd.blockchain.binaryproto.DataContractRegistry; | ||||
import com.jd.blockchain.contract.ContractSerializeUtils; | |||||
import com.jd.blockchain.contract.ReadContract; | import com.jd.blockchain.contract.ReadContract; | ||||
import com.jd.blockchain.crypto.AddressEncoding; | import com.jd.blockchain.crypto.AddressEncoding; | ||||
import com.jd.blockchain.crypto.AsymmetricKeypair; | import com.jd.blockchain.crypto.AsymmetricKeypair; | ||||
@@ -51,7 +50,7 @@ import com.jd.blockchain.sdk.BlockchainService; | |||||
import com.jd.blockchain.storage.service.DbConnection; | import com.jd.blockchain.storage.service.DbConnection; | ||||
import com.jd.blockchain.storage.service.DbConnectionFactory; | import com.jd.blockchain.storage.service.DbConnectionFactory; | ||||
import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | ||||
import com.jd.blockchain.transaction.ValueHolder; | |||||
import com.jd.blockchain.transaction.GenericValueHolder; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import com.jd.blockchain.utils.concurrent.ThreadInvoker; | import com.jd.blockchain.utils.concurrent.ThreadInvoker; | ||||
import com.jd.blockchain.utils.net.NetworkAddress; | import com.jd.blockchain.utils.net.NetworkAddress; | ||||
@@ -586,7 +585,7 @@ public class IntegrationBase { | |||||
ReadContract readContract1 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); | ReadContract readContract1 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); | ||||
ValueHolder<String> result1 = decode(readContract1.read(newDataAccount.getAddress().toBase58(), key1)); | |||||
GenericValueHolder<String> result1 = decode(readContract1.read(newDataAccount.getAddress().toBase58(), key1)); | |||||
ReadContract readContract2 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); | ReadContract readContract2 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); | ||||
@@ -594,7 +593,7 @@ public class IntegrationBase { | |||||
ReadContract readContract3 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); | ReadContract readContract3 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); | ||||
ValueHolder<Long> result3 = decode(readContract3.readVersion(newDataAccount.getAddress().toBase58(), key2)); | |||||
GenericValueHolder<Long> result3 = decode(readContract3.readVersion(newDataAccount.getAddress().toBase58(), key2)); | |||||
// 签名; | // 签名; | ||||
PreparedTransaction contractPtx = txContract.prepare(); | PreparedTransaction contractPtx = txContract.prepare(); | ||||
@@ -610,10 +609,10 @@ public class IntegrationBase { | |||||
System.out.printf("readContract3.result = %s \r\n", result3.get()); | System.out.printf("readContract3.result = %s \r\n", result3.get()); | ||||
// 打印结果 | |||||
for (OperationResult or : operationResults) { | |||||
System.out.printf("操作[%s].Result = %s \r\n", or.getIndex(), ContractSerializeUtils.resolve(or.getResult())); | |||||
} | |||||
// // 打印结果 | |||||
// for (OperationResult or : operationResults) { | |||||
// System.out.printf("操作[%s].Result = %s \r\n", or.getIndex(), ContractSerializeUtils.resolve(or.getResult())); | |||||
// } | |||||
// | // | ||||
// // 验证结果 | // // 验证结果 | ||||
// assertNotNull(contractReturn); | // assertNotNull(contractReturn); | ||||
@@ -6,7 +6,6 @@ import java.util.concurrent.ConcurrentHashMap; | |||||
import com.jd.blockchain.contract.ContractEventContext; | import com.jd.blockchain.contract.ContractEventContext; | ||||
import com.jd.blockchain.contract.ContractException; | import com.jd.blockchain.contract.ContractException; | ||||
import com.jd.blockchain.contract.ContractSerializeUtils; | |||||
import com.jd.blockchain.contract.EventProcessingAware; | import com.jd.blockchain.contract.EventProcessingAware; | ||||
import com.jd.blockchain.contract.LedgerContext; | import com.jd.blockchain.contract.LedgerContext; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
@@ -75,7 +74,7 @@ public class MockerContractExeHandle implements OperationHandle { | |||||
} | } | ||||
// No return value; | // No return value; | ||||
return ContractSerializeUtils.serialize(result); | |||||
return null; | |||||
} | } | ||||
@Override | @Override | ||||
@@ -1,88 +1,88 @@ | |||||
package com.jd.blockchain.mocker.proxy; | package com.jd.blockchain.mocker.proxy; | ||||
import java.lang.annotation.Annotation; | |||||
import java.lang.reflect.InvocationHandler; | |||||
import java.lang.reflect.Method; | |||||
import com.jd.blockchain.contract.Contract; | import com.jd.blockchain.contract.Contract; | ||||
import com.jd.blockchain.contract.ContractEvent; | import com.jd.blockchain.contract.ContractEvent; | ||||
import com.jd.blockchain.contract.ContractSerializeUtils; | |||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.ledger.BlockchainIdentity; | import com.jd.blockchain.ledger.BlockchainIdentity; | ||||
import com.jd.blockchain.ledger.BytesValueEncoding; | |||||
import com.jd.blockchain.ledger.OperationResult; | import com.jd.blockchain.ledger.OperationResult; | ||||
import com.jd.blockchain.ledger.OperationResultData; | |||||
import com.jd.blockchain.ledger.TransactionRequest; | import com.jd.blockchain.ledger.TransactionRequest; | ||||
import com.jd.blockchain.mocker.MockerNodeContext; | import com.jd.blockchain.mocker.MockerNodeContext; | ||||
import com.jd.blockchain.mocker.handler.MockerContractExeHandle; | import com.jd.blockchain.mocker.handler.MockerContractExeHandle; | ||||
import com.jd.blockchain.transaction.TxBuilder; | import com.jd.blockchain.transaction.TxBuilder; | ||||
import java.lang.annotation.Annotation; | |||||
import java.lang.reflect.InvocationHandler; | |||||
import java.lang.reflect.Method; | |||||
public class ContractProxy<T> implements InvocationHandler { | public class ContractProxy<T> implements InvocationHandler { | ||||
private BlockchainIdentity identity; | |||||
private BlockchainIdentity identity; | |||||
private MockerNodeContext mockerNodeContext; | |||||
private MockerNodeContext mockerNodeContext; | |||||
private T instance; | |||||
private T instance; | |||||
private MockerContractExeHandle operationHandle; | |||||
private MockerContractExeHandle operationHandle; | |||||
public ContractProxy(BlockchainIdentity identity, MockerNodeContext mockerNodeContext, | |||||
T instance, MockerContractExeHandle operationHandle) { | |||||
this.identity = identity; | |||||
this.mockerNodeContext = mockerNodeContext; | |||||
this.instance = instance; | |||||
this.operationHandle = operationHandle; | |||||
} | |||||
public ContractProxy(BlockchainIdentity identity, MockerNodeContext mockerNodeContext, T instance, | |||||
MockerContractExeHandle operationHandle) { | |||||
this.identity = identity; | |||||
this.mockerNodeContext = mockerNodeContext; | |||||
this.instance = instance; | |||||
this.operationHandle = operationHandle; | |||||
} | |||||
@Override | |||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { | |||||
// 实际执行时,首先判断执行的是否是添加注解的方法 | |||||
if (!isExecuteContractMethod(method)) { | |||||
return method.invoke(instance, args); | |||||
} | |||||
@Override | |||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { | |||||
// 实际执行时,首先判断执行的是否是添加注解的方法 | |||||
if (!isExecuteContractMethod(method)) { | |||||
return method.invoke(instance, args); | |||||
} | |||||
// 首先发送一次执行的请求 | |||||
TxBuilder txBuilder = mockerNodeContext.txBuilder(); | |||||
// 首先发送一次执行的请求 | |||||
TxBuilder txBuilder = mockerNodeContext.txBuilder(); | |||||
Class<?> contractInft = null; | |||||
Class<?> contractInft = null; | |||||
Class<?>[] instanceInfts = instance.getClass().getInterfaces(); | |||||
Class<?>[] instanceInfts = instance.getClass().getInterfaces(); | |||||
for (Class<?> instanceInft : instanceInfts) { | |||||
if (instanceInft.isAnnotationPresent(Contract.class)) { | |||||
contractInft = instanceInft; | |||||
break; | |||||
} | |||||
} | |||||
for (Class<?> instanceInft : instanceInfts) { | |||||
if (instanceInft.isAnnotationPresent(Contract.class)) { | |||||
contractInft = instanceInft; | |||||
break; | |||||
} | |||||
} | |||||
if (contractInft == null) { | |||||
throw new IllegalStateException("This object does not implement the interface for the @Contract annotation !!!"); | |||||
} | |||||
if (contractInft == null) { | |||||
throw new IllegalStateException( | |||||
"This object does not implement the interface for the @Contract annotation !!!"); | |||||
} | |||||
// 生成代理类 | |||||
Object proxyInstance = txBuilder.contract(identity.getAddress().toBase58(), contractInft); | |||||
// 代理方式执行一次 | |||||
method.invoke(proxyInstance, args); | |||||
// 生成代理类 | |||||
Object proxyInstance = txBuilder.contract(identity.getAddress().toBase58(), contractInft); | |||||
// 代理方式执行一次 | |||||
method.invoke(proxyInstance, args); | |||||
TransactionRequest txRequest = mockerNodeContext.txRequest(txBuilder); | |||||
TransactionRequest txRequest = mockerNodeContext.txRequest(txBuilder); | |||||
// 放入到Map中 | |||||
HashDigest txHash = txRequest.getTransactionContent().getHash(); | |||||
operationHandle.registerExecutorProxy(txHash, new ExecutorProxy(instance, method, args)); | |||||
// 放入到Map中 | |||||
HashDigest txHash = txRequest.getTransactionContent().getHash(); | |||||
operationHandle.registerExecutorProxy(txHash, new ExecutorProxy(instance, method, args)); | |||||
// 提交该请求至整个区块链系统 | |||||
OperationResult[] operationResults = mockerNodeContext.txProcess(txRequest); | |||||
if (operationResults == null || operationResults.length == 0) { | |||||
return null; | |||||
} | |||||
OperationResult opResult = operationResults[0]; | |||||
// 提交该请求至整个区块链系统 | |||||
OperationResult[] operationResults = mockerNodeContext.txProcess(txRequest); | |||||
if (operationResults == null || operationResults.length == 0) { | |||||
return null; | |||||
} | |||||
OperationResult opResult = operationResults[0]; | |||||
// 处理返回值 | |||||
return ContractSerializeUtils.resolve(opResult.getResult()); | |||||
} | |||||
// 处理返回值 | |||||
return BytesValueEncoding.encode(opResult.getResult(), method.getReturnType()); | |||||
} | |||||
private boolean isExecuteContractMethod(Method method) { | |||||
Annotation annotation = method.getAnnotation(ContractEvent.class); | |||||
return annotation != null; | |||||
} | |||||
private boolean isExecuteContractMethod(Method method) { | |||||
Annotation annotation = method.getAnnotation(ContractEvent.class); | |||||
return annotation != null; | |||||
} | |||||
} | } |
@@ -5,8 +5,6 @@ import java.lang.reflect.Method; | |||||
import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
import com.jd.blockchain.utils.console.CommandConsole; | |||||
public class DefaultExceptionHandle<TListener> implements ExceptionHandle<TListener> { | public class DefaultExceptionHandle<TListener> implements ExceptionHandle<TListener> { | ||||
@Override | @Override | ||||
@@ -21,9 +19,8 @@ public class DefaultExceptionHandle<TListener> implements ExceptionHandle<TListe | |||||
} | } | ||||
argsValue = String.format(argsFormat.toString(), args); | argsValue = String.format(argsFormat.toString(), args); | ||||
} | } | ||||
String message = String.format("Error occurred on firing event!--[listener.class=%s][method=%s][args=%s]--[%s]%s", | |||||
String message = String.format("Error occurred while firing event!--[listener.class=%s][method=%s][args=%s]--[%s]%s", | |||||
listener.getClass().getName(), method.getName(), argsValue, ex.getClass().getName(), ex.getMessage()); | listener.getClass().getName(), method.getName(), argsValue, ex.getClass().getName(), ex.getMessage()); | ||||
// System.err.println(message); | |||||
logger.error(message, ex); | logger.error(message, ex); | ||||
} | } | ||||
private Logger logger = LoggerFactory.getLogger(DefaultExceptionHandle.class); | private Logger logger = LoggerFactory.getLogger(DefaultExceptionHandle.class); | ||||
@@ -3,11 +3,12 @@ package com.jd.blockchain.utils.event; | |||||
import java.lang.reflect.InvocationHandler; | import java.lang.reflect.InvocationHandler; | ||||
import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||
import java.lang.reflect.Proxy; | import java.lang.reflect.Proxy; | ||||
import java.util.LinkedList; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | import java.util.List; | ||||
import java.util.concurrent.CopyOnWriteArrayList; | import java.util.concurrent.CopyOnWriteArrayList; | ||||
import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
import org.slf4j.LoggerFactory; | |||||
import org.springframework.util.ReflectionUtils; | import org.springframework.util.ReflectionUtils; | ||||
import com.jd.blockchain.utils.Disposable; | import com.jd.blockchain.utils.Disposable; | ||||
@@ -36,17 +37,22 @@ public class EventMulticaster<TListener> implements Disposable { | |||||
} | } | ||||
public EventMulticaster(Class<TListener> listenerClass, Logger errorLogger) { | public EventMulticaster(Class<TListener> listenerClass, Logger errorLogger) { | ||||
this(listenerClass, new ExceptionLoggingHandle<TListener>(errorLogger)); | |||||
this(listenerClass, new RethrowExceptionHandler<TListener>(errorLogger)); | |||||
} | } | ||||
@SuppressWarnings("unchecked") | @SuppressWarnings("unchecked") | ||||
public EventMulticaster(Class<TListener> listenerClass, ExceptionHandle<TListener> exHandle) { | public EventMulticaster(Class<TListener> listenerClass, ExceptionHandle<TListener> exHandle) { | ||||
if (!listenerClass.isInterface()) { | |||||
throw new IllegalArgumentException("The specified class of listener does not represent an interface!"); | |||||
} | |||||
// 初始化错误处理器; | // 初始化错误处理器; | ||||
this.exHandle = exHandle == null ? new DefaultExceptionHandle<TListener>() : exHandle; | |||||
this.exHandle = exHandle == null | |||||
? new RethrowExceptionHandler<TListener>(LoggerFactory.getLogger(EventMulticaster.class)) | |||||
: exHandle; | |||||
// 解析出不支持的方法; | // 解析出不支持的方法; | ||||
Method[] methods = ReflectionUtils.getAllDeclaredMethods(listenerClass); | Method[] methods = ReflectionUtils.getAllDeclaredMethods(listenerClass); | ||||
List<Method> supMths = new LinkedList<Method>(); | |||||
List<Method> supMths = new ArrayList<Method>(); | |||||
for (Method method : methods) { | for (Method method : methods) { | ||||
if (method.getDeclaringClass() == Object.class) { | if (method.getDeclaringClass() == Object.class) { | ||||
// 不支持 Object 方法; | // 不支持 Object 方法; | ||||
@@ -86,14 +92,14 @@ public class EventMulticaster<TListener> implements Disposable { | |||||
throw new UnsupportedOperationException("Unsupported method for event multicasting!"); | throw new UnsupportedOperationException("Unsupported method for event multicasting!"); | ||||
} | } | ||||
} | } | ||||
protected void doNotify(List<TListener> listeners, Method method, Object[] args){ | |||||
protected void doNotify(List<TListener> listeners, Method method, Object[] args) { | |||||
for (TListener listener : listeners) { | for (TListener listener : listeners) { | ||||
doNotifySingle(listener, method, args); | doNotifySingle(listener, method, args); | ||||
} | } | ||||
} | } | ||||
protected void doNotifySingle(TListener listener, Method method, Object[] args){ | |||||
protected void doNotifySingle(TListener listener, Method method, Object[] args) { | |||||
try { | try { | ||||
ReflectionUtils.invokeMethod(method, listener, args); | ReflectionUtils.invokeMethod(method, listener, args); | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
@@ -104,12 +110,12 @@ public class EventMulticaster<TListener> implements Disposable { | |||||
public void addListener(TListener listener) { | public void addListener(TListener listener) { | ||||
listeners.add(listener); | listeners.add(listener); | ||||
} | } | ||||
public void removeListener(TListener listener) { | public void removeListener(TListener listener) { | ||||
listeners.remove(listener); | listeners.remove(listener); | ||||
} | } | ||||
public TListener broadcast() { | |||||
public TListener getBroadcaster() { | |||||
return listenerProxy; | return listenerProxy; | ||||
} | } | ||||