@@ -69,7 +69,7 @@ public abstract class AbstractContractCode implements ContractCode { | |||||
if (handleMethod == null) { | if (handleMethod == null) { | ||||
throw new ContractException( | throw new ContractException( | ||||
String.format("Contract[%s:%s] has no handle method to handle event[%s]!", address.toString(), | String.format("Contract[%s:%s] has no handle method to handle event[%s]!", address.toString(), | ||||
contractDefinition.getType().getDeclaredClass().toString(), eventContext.getEvent())); | |||||
contractDefinition.getType().getName(), eventContext.getEvent())); | |||||
} | } | ||||
BytesValueList bytesValues = eventContext.getArgs(); | BytesValueList bytesValues = eventContext.getArgs(); | ||||
@@ -11,19 +11,15 @@ import com.jd.blockchain.utils.IllegalDataException; | |||||
public class ContractType { | public class ContractType { | ||||
private String name; | private String name; | ||||
private Map<String, Method> events = new HashMap<>(); | private Map<String, Method> events = new HashMap<>(); | ||||
private Map<Method, String> handleMethods = new HashMap<>(); | |||||
private Class<?> declaredClass; | |||||
private Map<Method, String> handleMethods = new HashMap<>(); | |||||
public String getName() { | public String getName() { | ||||
return name; | return name; | ||||
} | } | ||||
public Class<?> getDeclaredClass() { | |||||
return declaredClass; | |||||
} | |||||
/** | /** | ||||
* 返回声明的所有事件; | * 返回声明的所有事件; | ||||
* | * | ||||
@@ -86,7 +82,8 @@ public class ContractType { | |||||
} | } | ||||
// 接口上必须有注解 | // 接口上必须有注解 | ||||
if (!contractIntf.isAnnotationPresent(Contract.class)) { | |||||
Contract contract = contractIntf.getAnnotation(Contract.class); | |||||
if (contract == null) { | |||||
throw new IllegalDataException("It is not a Contract Type, because there is not @Contract !"); | throw new IllegalDataException("It is not a Contract Type, because there is not @Contract !"); | ||||
} | } | ||||
@@ -98,6 +95,9 @@ public class ContractType { | |||||
ContractType contractType = new ContractType(); | ContractType contractType = new ContractType(); | ||||
// 设置合约显示名字为 | |||||
contractType.name = contract.name(); | |||||
for (Method method : classMethods) { | for (Method method : classMethods) { | ||||
// if current method contains @ContractEvent,then put it in this map; | // if current method contains @ContractEvent,then put it in this map; | ||||
@@ -130,6 +130,12 @@ public class ContractType { | |||||
contractType.handleMethods.put(method, eventName); | contractType.handleMethods.put(method, eventName); | ||||
} | } | ||||
} | } | ||||
// 最起码有一个ContractEvent | |||||
if (contractType.events.isEmpty()) { | |||||
throw new IllegalStateException( | |||||
String.format("Contract Interface[%s] have none method for annotation[@ContractEvent] !", contractIntf.getName())); | |||||
} | |||||
return contractType; | return contractType; | ||||
} | } | ||||
@@ -49,8 +49,13 @@ public class BytesValueEncoding { | |||||
public static BytesValue encodeSingle(Object value, Class<?> type) { | public static BytesValue encodeSingle(Object value, Class<?> type) { | ||||
if (value == null) { | |||||
return null; | |||||
} | |||||
if (type == null) { | if (type == null) { | ||||
type = value.getClass(); | type = value.getClass(); | ||||
} else if (type.equals(void.class) || type.equals(Void.class)) { | |||||
return null; | |||||
} | } | ||||
if (type.isInterface()) { | if (type.isInterface()) { | ||||
// 判断是否含有DataContract注解 | // 判断是否含有DataContract注解 | ||||
@@ -161,6 +166,11 @@ public class BytesValueEncoding { | |||||
} | } | ||||
public static boolean supportType(Class<?> currParamType) { | public static boolean supportType(Class<?> currParamType) { | ||||
// 支持空返回值 | |||||
if (currParamType.equals(void.class) || currParamType.equals(Void.class)) { | |||||
return true; | |||||
} | |||||
if (currParamType.isInterface()) { | if (currParamType.isInterface()) { | ||||
// 接口序列化必须实现DataContract注解 | // 接口序列化必须实现DataContract注解 | ||||
if (!currParamType.isAnnotationPresent(DataContract.class)) { | if (!currParamType.isAnnotationPresent(DataContract.class)) { | ||||
@@ -36,7 +36,7 @@ public interface ContractEventSendOperation extends Operation { | |||||
* | * | ||||
* @return | * @return | ||||
*/ | */ | ||||
@DataField(order = 4, primitiveType = PrimitiveType.BYTES) | |||||
@DataField(order = 4, refContract = true) | |||||
BytesValueList getArgs(); | BytesValueList getArgs(); | ||||
} | } |
@@ -1,6 +1,6 @@ | |||||
package test.com.jd.blockchain.ledger.data; | package test.com.jd.blockchain.ledger.data; | ||||
import com.jd.blockchain.ledger.BytesValueEncoding; | |||||
import com.jd.blockchain.ledger.*; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import static org.junit.Assert.*; | import static org.junit.Assert.*; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
@@ -17,8 +17,53 @@ public class BytesValueEncodingTest { | |||||
assertTrue(BytesValueEncoding.supportType(Long.class)); | assertTrue(BytesValueEncoding.supportType(Long.class)); | ||||
assertTrue(BytesValueEncoding.supportType(String.class)); | assertTrue(BytesValueEncoding.supportType(String.class)); | ||||
assertTrue(BytesValueEncoding.supportType(Bytes.class)); | assertTrue(BytesValueEncoding.supportType(Bytes.class)); | ||||
assertTrue(BytesValueEncoding.supportType(Operation.class)); | |||||
assertFalse(BytesValueEncoding.supportType(byte.class)); | |||||
} | |||||
@Test | |||||
public void testSingle() { | |||||
long longVal = 1024L; | |||||
BytesValue longBytesVal1 = BytesValueEncoding.encodeSingle(longVal, null); | |||||
BytesValue longBytesVal2 = BytesValueEncoding.encodeSingle(longVal, long.class); | |||||
BytesValue longBytesVal3 = BytesValueEncoding.encodeSingle(longVal, Long.class); | |||||
assertEquals(longBytesVal1.getValue(), longBytesVal2.getValue()); | |||||
assertEquals(longBytesVal1.getType(), longBytesVal2.getType()); | |||||
assertEquals(longBytesVal2.getValue(), longBytesVal3.getValue()); | |||||
assertEquals(longBytesVal2.getType(), longBytesVal3.getType()); | |||||
long resolveLongVal1 = (long)BytesValueEncoding.decode(longBytesVal1); | |||||
long resolveLongVal2 = (long)BytesValueEncoding.decode(longBytesVal2); | |||||
long resolveLongVal3 = (long)BytesValueEncoding.decode(longBytesVal3); | |||||
assertEquals(resolveLongVal1, 1024L); | |||||
assertEquals(resolveLongVal2, 1024L); | |||||
assertEquals(resolveLongVal3, 1024L); | |||||
} | |||||
@Test | |||||
public void testArray() { | |||||
Object[] values = new Object[]{1024L, "zhangsan", "lisi".getBytes(), 16}; | |||||
Class<?>[] classes = new Class[]{long.class, String.class, byte[].class, int.class}; | |||||
BytesValueList bytesValueList = BytesValueEncoding.encodeArray(values, null); | |||||
BytesValueList bytesValueList1 = BytesValueEncoding.encodeArray(values, classes); | |||||
assertEquals(bytesValueList1.getValues().length, values.length); | |||||
BytesValue[] bytesValues = bytesValueList.getValues(); | |||||
assertEquals(bytesValues.length, values.length); | |||||
assertEquals(DataType.INT64, bytesValues[0].getType()); | |||||
assertEquals(DataType.TEXT, bytesValues[1].getType()); | |||||
assertEquals(DataType.BYTES, bytesValues[2].getType()); | |||||
assertEquals(DataType.INT32, bytesValues[3].getType()); | |||||
Object[] resolveObjs = BytesValueEncoding.decode(bytesValueList, classes); | |||||
assertArrayEquals(resolveObjs, values); | |||||
} | } | ||||
} | } |
@@ -37,6 +37,7 @@ public class ContractEventSendOpTemplateTest { | |||||
@Before | @Before | ||||
public void initContractEventSendOpTemplate() { | public void initContractEventSendOpTemplate() { | ||||
DataContractRegistry.register(BytesValueList.class); | |||||
DataContractRegistry.register(ContractEventSendOperation.class); | DataContractRegistry.register(ContractEventSendOperation.class); | ||||
DataContractRegistry.register(Operation.class); | DataContractRegistry.register(Operation.class); | ||||
String contractAddress = "zhangsan-address", event = "zhangsan-event"; | String contractAddress = "zhangsan-address", event = "zhangsan-event"; | ||||
@@ -24,7 +24,6 @@ public class ContractTypeTest { | |||||
public void normalTest() throws NoSuchMethodException, SecurityException { | public void normalTest() throws NoSuchMethodException, SecurityException { | ||||
ContractType contractType = ContractType.resolve(NormalContract.class); | ContractType contractType = ContractType.resolve(NormalContract.class); | ||||
assertEquals(NormalContract.class, contractType.getDeclaredClass()); | |||||
assertEquals("NORMAL-CONTRACT", contractType.getName()); | assertEquals("NORMAL-CONTRACT", contractType.getName()); | ||||
Set<String> events = contractType.getEvents(); | Set<String> events = contractType.getEvents(); | ||||
@@ -56,14 +55,14 @@ public class ContractTypeTest { | |||||
assertNull(contractType.getEvent(toStringMethod)); | assertNull(contractType.getEvent(toStringMethod)); | ||||
assertNull(contractType.getHandleMethod("NotExist")); | assertNull(contractType.getHandleMethod("NotExist")); | ||||
//解析非合约声明接口类型时,应该引发异常 ContractException; | |||||
//解析非合约声明接口类型时,应该正常,只需要实现接口(该接口定义了具体的合约类型)即可 | |||||
ContractException ex = null; | ContractException ex = null; | ||||
try { | try { | ||||
ContractType.resolve(NormalContractImpl.class); | ContractType.resolve(NormalContractImpl.class); | ||||
} catch (ContractException e) { | } catch (ContractException e) { | ||||
ex = e; | ex = e; | ||||
} | } | ||||
assertNotNull(ex); | |||||
assertNull(ex); | |||||
} | } | ||||
} | } |
@@ -29,7 +29,6 @@ import com.jd.blockchain.utils.Bytes; | |||||
* @create 2018/8/30 | * @create 2018/8/30 | ||||
* @since 1.0.0 | * @since 1.0.0 | ||||
*/ | */ | ||||
//todo 尚未测试通过,等张爽处理完再测试 | |||||
public class DataAccountKVSetOpTemplateTest { | public class DataAccountKVSetOpTemplateTest { | ||||
private DataAccountKVSetOpTemplate data; | private DataAccountKVSetOpTemplate data; | ||||
@@ -55,6 +55,7 @@ public class GatewayServiceFactory implements BlockchainServiceFactory, Closeabl | |||||
DataContractRegistry.register(ActionResponse.class); | DataContractRegistry.register(ActionResponse.class); | ||||
DataContractRegistry.register(ClientIdentifications.class); | DataContractRegistry.register(ClientIdentifications.class); | ||||
DataContractRegistry.register(ClientIdentification.class); | DataContractRegistry.register(ClientIdentification.class); | ||||
DataContractRegistry.register(BytesValueList.class); | |||||
ByteArrayObjectUtil.init(); | ByteArrayObjectUtil.init(); | ||||
} | } | ||||
@@ -23,7 +23,7 @@ import com.jd.blockchain.transaction.LongValueHolder; | |||||
import com.jd.blockchain.transaction.GenericValueHolder; | 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_ { | |||||
private BlockchainKeypair adminKey; | private BlockchainKeypair adminKey; | ||||
@@ -39,7 +39,8 @@ public class Utils { | |||||
public static final String PASSWORD = "abc"; | public static final String PASSWORD = "abc"; | ||||
public static final String[] PUB_KEYS = { "3snPdw7i7PapsDoW185c3kfK6p8s6SwiJAdEUzgnfeuUox12nxgzXu", | |||||
public static final String[] PUB_KEYS = { | |||||
"3snPdw7i7PapsDoW185c3kfK6p8s6SwiJAdEUzgnfeuUox12nxgzXu", | |||||
"3snPdw7i7Ph1SYLQt9uqVEqiuvNXjxCdGvEdN6otJsg5rbr7Aze7kf", | "3snPdw7i7Ph1SYLQt9uqVEqiuvNXjxCdGvEdN6otJsg5rbr7Aze7kf", | ||||
"3snPdw7i7PezptA6dNBkotPjmKEbTkY8fmusLBnfj8Cf7eFwhWDwKr", | "3snPdw7i7PezptA6dNBkotPjmKEbTkY8fmusLBnfj8Cf7eFwhWDwKr", | ||||
"3snPdw7i7PerZYfRzEB61SAN9tFK4yHm9wUSRtkLSSGXHkQRbB5PkS" }; | "3snPdw7i7PerZYfRzEB61SAN9tFK4yHm9wUSRtkLSSGXHkQRbB5PkS" }; | ||||
@@ -38,22 +38,22 @@ public class LedgerPerfCapabilityTest { | |||||
@Test | @Test | ||||
public void testKvStorage4Memory() { | public void testKvStorage4Memory() { | ||||
LedgerPerformanceTest.test(new String[]{SILENT, CONSENSUS}); | |||||
LedgerPerformanceTest.test(new String[]{SILENT}); | |||||
} | } | ||||
@Test | @Test | ||||
public void testUserRegister4Memory() { | public void testUserRegister4Memory() { | ||||
LedgerPerformanceTest.test(new String[]{USERTEST, SILENT, CONSENSUS}); | |||||
LedgerPerformanceTest.test(new String[]{USERTEST, SILENT}); | |||||
} | } | ||||
@Test | @Test | ||||
public void testKvStorage4Rocksdb() { | public void testKvStorage4Rocksdb() { | ||||
LedgerPerformanceTest.test(new String[]{ROCKSDB, SILENT, CONSENSUS}); | |||||
LedgerPerformanceTest.test(new String[]{ROCKSDB, SILENT}); | |||||
} | } | ||||
@Test | @Test | ||||
public void testUserRegister4Rocksdb() { | public void testUserRegister4Rocksdb() { | ||||
LedgerPerformanceTest.test(new String[]{USERTEST, ROCKSDB, SILENT, CONSENSUS}); | |||||
LedgerPerformanceTest.test(new String[]{USERTEST, ROCKSDB, SILENT}); | |||||
} | } | ||||
public void testUserRegister4Redis() { | public void testUserRegister4Redis() { | ||||
@@ -78,7 +78,7 @@ public class ContractProxy<T> implements InvocationHandler { | |||||
OperationResult opResult = operationResults[0]; | OperationResult opResult = operationResults[0]; | ||||
// 处理返回值 | // 处理返回值 | ||||
return BytesValueEncoding.encodeSingle(opResult.getResult(), method.getReturnType()); | |||||
return BytesValueEncoding.decode(opResult.getResult(), method.getReturnType()); | |||||
} | } | ||||
private boolean isExecuteContractMethod(Method method) { | private boolean isExecuteContractMethod(Method method) { | ||||
@@ -7,7 +7,7 @@ import com.jd.blockchain.mocker.contracts.AccountContractImpl; | |||||
import org.junit.Before; | import org.junit.Before; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
public class AccountMockerTest_ { | |||||
public class AccountMockerTest { | |||||
String accountFrom = "zhangsan"; | String accountFrom = "zhangsan"; | ||||
@@ -39,7 +39,7 @@ public class AccountMockerTest_ { | |||||
accountContract.create(address, accountTo, 1000L); | accountContract.create(address, accountTo, 1000L); | ||||
accountContract.print(address, accountFrom, accountTo); | |||||
// accountContract.print(address, accountFrom, accountTo); | |||||
// 开始转账 | // 开始转账 | ||||
accountContract.transfer(address, accountFrom, accountTo, 500); | accountContract.transfer(address, accountFrom, accountTo, 500); |
@@ -10,7 +10,7 @@ import com.jd.blockchain.mocker.contracts.WriteContract; | |||||
import com.jd.blockchain.mocker.contracts.WriteContractImpl; | import com.jd.blockchain.mocker.contracts.WriteContractImpl; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
public class MockTest_ { | |||||
public class MockTest { | |||||
@Test | @Test | ||||
public void test() { | public void test() { |