@@ -96,7 +96,7 @@ public abstract class AbstractContractCode implements ContractCode { | |||
eventContext.getEvent(), address.toString(), error.getMessage()), error); | |||
} | |||
BytesValue retnBytes = BytesValueEncoding.encode(retn, handleMethod.getReturnType()); | |||
BytesValue retnBytes = BytesValueEncoding.encodeSingle(retn, handleMethod.getReturnType()); | |||
return retnBytes; | |||
} | |||
@@ -39,7 +39,6 @@ | |||
<version>${project.version}</version> | |||
<scope>test</scope> | |||
</dependency> | |||
</dependencies> | |||
</project> |
@@ -1,24 +1,131 @@ | |||
package com.jd.blockchain.ledger; | |||
import com.jd.blockchain.binaryproto.BinaryProtocol; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.ledger.resolver.*; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.concurrent.ConcurrentHashMap; | |||
public class BytesValueEncoding { | |||
public static BytesValue encode(Object value, Class<?> type) { | |||
throw new IllegalStateException("Not implemented!"); | |||
private static final Map<Class<?>, BytesValueResolver> CLASS_RESOLVER_MAP = new ConcurrentHashMap<>(); | |||
private static final Map<DataType, BytesValueResolver> DATA_TYPE_RESOLVER_MAP = new ConcurrentHashMap<>(); | |||
static { | |||
init(); | |||
} | |||
public static BytesValueList encode(Object[] values, Class<?>[] types) { | |||
throw new IllegalStateException("Not implemented!"); | |||
private static void init() { | |||
BytesValueResolver[] resolvers = new BytesValueResolver[]{ | |||
new BytesToBytesValueResolver(), | |||
new IntegerToBytesValueResolver(), | |||
new LongToBytesValueResolver(), | |||
new ShortToBytesValueResolver(), | |||
new StringToBytesValueResolver() | |||
}; | |||
for (BytesValueResolver currResolver : resolvers) { | |||
// 填充classMAP | |||
Class<?>[] supportClasses = currResolver.supportClasses(); | |||
if (supportClasses != null && supportClasses.length > 0) { | |||
for (Class<?> clazz : supportClasses) { | |||
CLASS_RESOLVER_MAP.put(clazz, currResolver); | |||
} | |||
} | |||
// 填充dataTypeMap | |||
DataType[] supportDataTypes = currResolver.supportDataTypes(); | |||
if (supportDataTypes != null && supportDataTypes.length > 0) { | |||
for (DataType dataType : supportDataTypes) { | |||
DATA_TYPE_RESOLVER_MAP.put(dataType, currResolver); | |||
} | |||
} | |||
} | |||
} | |||
public static BytesValue encodeSingle(Object value, Class<?> type) { | |||
if (type == null) { | |||
type = value.getClass(); | |||
} | |||
if (type.isInterface()) { | |||
// 判断是否含有DataContract注解 | |||
if (!type.isAnnotationPresent(DataContract.class)) { | |||
throw new IllegalStateException(String.format("Interface[%s] can not be serialize !!!", type.getName())); | |||
} | |||
// 将对象序列化 | |||
byte[] serialBytes = BinaryProtocol.encode(value, type); | |||
return BytesData.fromType(DataType.DATA_CONTRACT, serialBytes); | |||
} | |||
BytesValueResolver bytesValueResolver = CLASS_RESOLVER_MAP.get(type); | |||
if (bytesValueResolver == null) { | |||
throw new IllegalStateException(String.format("Class[%s] can not find encoder !!!", type.getName())); | |||
} | |||
return bytesValueResolver.encode(value, type); | |||
} | |||
public static BytesValueList encodeArray(Object[] values, Class<?>[] types) { | |||
if (values == null || values.length == 0) { | |||
return null; | |||
} | |||
if (types != null && types.length != values.length) { | |||
throw new IllegalStateException("Types can be null, or types's length must be equal BytesValue[]'s !!!"); | |||
} | |||
BytesValueListData bytesValueListData = new BytesValueListData(); | |||
for (int i = 0; i < values.length; i++) { | |||
BytesValue bytesValue = encodeSingle(values[i], types == null ? null : types[i]); | |||
bytesValueListData.add(bytesValue); | |||
} | |||
return bytesValueListData; | |||
} | |||
public static Object decode(BytesValue value) { | |||
return decode(value, null); | |||
} | |||
public static Object decode(BytesValue value, Class<?> type) { | |||
throw new IllegalStateException("Not implemented!"); | |||
DataType dataType = value.getType(); | |||
BytesValueResolver valueResolver = DATA_TYPE_RESOLVER_MAP.get(dataType); | |||
if (valueResolver == null) { | |||
throw new IllegalStateException(String.format("DataType[%s] can not find encoder !!!", dataType.name())); | |||
} | |||
return type == null ? valueResolver.decode(value) : valueResolver.decode(value, type); | |||
} | |||
public static Object[] decode(BytesValueList values, Class<?>[] types) { | |||
throw new IllegalStateException("Not implemented!"); | |||
BytesValue[] bytesValues = values.getValues(); | |||
if (bytesValues == null || bytesValues.length == 0) { | |||
return null; | |||
} | |||
// 允许types为null,此时每个BytesValue按照当前的对象来处理 | |||
// 若types不为null,则types's长度必须和bytesValues一致 | |||
if (types != null && types.length != bytesValues.length) { | |||
throw new IllegalStateException("Types can be null, or types's length must be equal BytesValue[]'s !!!"); | |||
} | |||
Object[] resolveObjs = new Object[bytesValues.length]; | |||
if (types == null) { | |||
// 按照默认方式解析 | |||
for (int i = 0; i < bytesValues.length; i++) { | |||
BytesValue bytesValue = bytesValues[i]; | |||
DataType dataType = bytesValue.getType(); | |||
BytesValueResolver valueResolver = DATA_TYPE_RESOLVER_MAP.get(dataType); | |||
if (valueResolver == null) { | |||
throw new IllegalStateException(String.format("DataType[%s] can not find encoder !!!", dataType.name())); | |||
} | |||
resolveObjs[i] = valueResolver.decode(bytesValue); | |||
} | |||
return resolveObjs; | |||
} | |||
// 按照输入的Class进行解析 | |||
for (int i = 0; i < bytesValues.length; i++) { | |||
resolveObjs[i] = decode(bytesValues[i], types[i]); | |||
} | |||
return resolveObjs; | |||
} | |||
public static Object getDefaultValue(Class<?> type) { | |||
@@ -54,7 +161,29 @@ public class BytesValueEncoding { | |||
} | |||
public static boolean supportType(Class<?> currParamType) { | |||
// TODO Auto-generated method stub | |||
return false; | |||
if (currParamType.isInterface()) { | |||
// 接口序列化必须实现DataContract注解 | |||
if (!currParamType.isAnnotationPresent(DataContract.class)) { | |||
throw new IllegalStateException(String.format("Interface[%s] can not be serialize !!!", currParamType.getName())); | |||
} | |||
return true; | |||
} | |||
return CLASS_RESOLVER_MAP.containsKey(currParamType); | |||
} | |||
public static class BytesValueListData implements BytesValueList { | |||
private List<BytesValue> bytesValues = new ArrayList<>(); | |||
public void add(BytesValue bytesValue) { | |||
bytesValues.add(bytesValue); | |||
} | |||
@Override | |||
public BytesValue[] getValues() { | |||
BytesValue[] bytesValueArray = new BytesValue[bytesValues.size()]; | |||
return bytesValues.toArray(bytesValueArray); | |||
} | |||
} | |||
} |
@@ -0,0 +1,54 @@ | |||
package com.jd.blockchain.ledger.resolver; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.DataType; | |||
import com.jd.blockchain.utils.Bytes; | |||
public abstract class AbstractBytesValueResolver implements BytesValueResolver { | |||
protected boolean isSupport(Class<?> type) { | |||
if (type == null) { | |||
return false; | |||
} | |||
Class<?>[] supports = supportClasses(); | |||
if (supports != null && supports.length > 0) { | |||
for (Class<?> clazz : supports) { | |||
if (type.equals(clazz)) { | |||
return true; | |||
} | |||
} | |||
} | |||
return false; | |||
} | |||
protected boolean isSupport(DataType dataType) { | |||
if (dataType == null) { | |||
return false; | |||
} | |||
DataType[] supports = supportDataTypes(); | |||
if (supports != null && supports.length > 0) { | |||
for (DataType dt : supports) { | |||
if (dataType.equals(dt)) { | |||
return true; | |||
} | |||
} | |||
} | |||
return false; | |||
} | |||
@Override | |||
public BytesValue encode(Object value) { | |||
return encode(value, value.getClass()); | |||
} | |||
@Override | |||
public Object decode(BytesValue value) { | |||
DataType dataType = value.getType(); | |||
if (!isSupport(dataType)) { | |||
throw new IllegalStateException(String.format("Un-support encode DataType[%s] Object !!!", dataType.name())); | |||
} | |||
return decode(value.getValue()); | |||
} | |||
protected abstract Object decode(Bytes value); | |||
} |
@@ -0,0 +1,58 @@ | |||
package com.jd.blockchain.ledger.resolver; | |||
import com.jd.blockchain.ledger.BytesData; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.DataType; | |||
import com.jd.blockchain.utils.Bytes; | |||
import java.util.Set; | |||
public class BytesToBytesValueResolver extends AbstractBytesValueResolver { | |||
private final Class<?>[] supportClasses = {Bytes.class, byte[].class}; | |||
private final DataType[] supportDataTypes = {DataType.BYTES}; | |||
private final Set<Class<?>> convertClasses = initByteConvertSet(); | |||
@Override | |||
public BytesValue encode(Object value, Class<?> type) { | |||
if (!isSupport(type)) { | |||
throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); | |||
} | |||
if (type.equals(byte[].class)) { | |||
return BytesData.fromBytes((byte[]) value); | |||
} | |||
return BytesData.fromBytes((Bytes) value); | |||
} | |||
@Override | |||
public Class<?>[] supportClasses() { | |||
return supportClasses; | |||
} | |||
@Override | |||
public DataType[] supportDataTypes() { | |||
return supportDataTypes; | |||
} | |||
@Override | |||
protected Object decode(Bytes value) { | |||
return value; | |||
} | |||
@Override | |||
public Object decode(BytesValue value, Class<?> clazz) { | |||
Bytes bytesVal = (Bytes) decode(value); | |||
if (!convertClasses.contains(clazz)) { | |||
throw new IllegalStateException(String.format("Un-Support decode value to class[%s] !!!", clazz.getName())); | |||
} | |||
if (clazz.equals(String.class)) { | |||
return bytesVal.toUTF8String(); | |||
} else if (clazz.equals(byte[].class)) { | |||
return bytesVal.toBytes(); | |||
} | |||
return bytesVal; | |||
} | |||
} |
@@ -0,0 +1,80 @@ | |||
package com.jd.blockchain.ledger.resolver; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.DataType; | |||
import com.jd.blockchain.utils.Bytes; | |||
import java.util.Arrays; | |||
import java.util.HashSet; | |||
import java.util.Set; | |||
public interface BytesValueResolver { | |||
/** | |||
* Int相关的可转换Class集合 | |||
*/ | |||
Class<?>[] supportIntConvertClasses = { | |||
short.class, Short.class, int.class, Integer.class, long.class, Long.class}; | |||
/** | |||
* 字节数组(字符串)相关可转换的Class集合 | |||
*/ | |||
Class<?>[] supportByteConvertClasses = { | |||
String.class, Bytes.class, byte[].class}; | |||
default Set<Class<?>> initIntConvertSet() { | |||
return new HashSet<>(Arrays.asList(supportIntConvertClasses)); | |||
} | |||
default Set<Class<?>> initByteConvertSet() { | |||
return new HashSet<>(Arrays.asList(supportByteConvertClasses)); | |||
} | |||
/** | |||
* 将对象转换为BytesValue | |||
* | |||
* @param value | |||
* @return | |||
*/ | |||
BytesValue encode(Object value); | |||
/** | |||
* 将对象转换为BytesValue | |||
* | |||
* @param value | |||
* @param type | |||
* @return | |||
*/ | |||
BytesValue encode(Object value, Class<?> type); | |||
/** | |||
* 当前解析器支持的Class列表 | |||
* | |||
* @return | |||
*/ | |||
Class<?>[] supportClasses(); | |||
/** | |||
* 当前解析器支持的DataType列表 | |||
* | |||
* @return | |||
*/ | |||
DataType[] supportDataTypes(); | |||
/** | |||
* 将BytesValue解析为对应的Object | |||
* | |||
* @param value | |||
* @return | |||
*/ | |||
Object decode(BytesValue value); | |||
/** | |||
* 将BytesValue转换为指定Class的Object | |||
* | |||
* @param value | |||
* @param clazz | |||
* @return | |||
*/ | |||
Object decode(BytesValue value, Class<?> clazz); | |||
} |
@@ -0,0 +1,58 @@ | |||
package com.jd.blockchain.ledger.resolver; | |||
import com.jd.blockchain.ledger.BytesData; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.DataType; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.blockchain.utils.io.BytesUtils; | |||
import java.util.Set; | |||
public class IntegerToBytesValueResolver extends AbstractBytesValueResolver { | |||
private final Class<?>[] supportClasses = {Integer.class, int.class}; | |||
private final DataType[] supportDataTypes = {DataType.INT32}; | |||
private final Set<Class<?>> convertClasses = initIntConvertSet(); | |||
@Override | |||
public BytesValue encode(Object value, Class<?> type) { | |||
if (!isSupport(type)) { | |||
throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); | |||
} | |||
return BytesData.fromInt32((int) value); | |||
} | |||
@Override | |||
public Class<?>[] supportClasses() { | |||
return supportClasses; | |||
} | |||
@Override | |||
public DataType[] supportDataTypes() { | |||
return supportDataTypes; | |||
} | |||
@Override | |||
protected Object decode(Bytes value) { | |||
return BytesUtils.toInt(value.toBytes()); | |||
} | |||
@Override | |||
public Object decode(BytesValue value, Class<?> clazz) { | |||
// 支持转换为short、int、long | |||
int intVal = (int)decode(value); | |||
if (convertClasses.contains(clazz)) { | |||
// 对于short和Short需要强制类型转换 | |||
if (clazz.equals(short.class) || clazz.equals(Short.class)) { | |||
return (short) intVal; | |||
} else if (clazz.equals(long.class) || clazz.equals(Long.class)) { | |||
return (long) intVal; | |||
} | |||
return intVal; | |||
} else { | |||
throw new IllegalStateException(String.format("Un-Support decode value to class[%s] !!!", clazz.getName())); | |||
} | |||
} | |||
} |
@@ -0,0 +1,58 @@ | |||
package com.jd.blockchain.ledger.resolver; | |||
import com.jd.blockchain.ledger.BytesData; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.DataType; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.blockchain.utils.io.BytesUtils; | |||
import java.util.Set; | |||
public class LongToBytesValueResolver extends AbstractBytesValueResolver { | |||
private final Class<?>[] supportClasses = {Long.class, long.class}; | |||
private final DataType[] supportDataTypes = {DataType.INT64}; | |||
private final Set<Class<?>> convertClasses = initIntConvertSet(); | |||
@Override | |||
public BytesValue encode(Object value, Class<?> type) { | |||
if (!isSupport(type)) { | |||
throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); | |||
} | |||
return BytesData.fromInt64((long)value); | |||
} | |||
@Override | |||
public Class<?>[] supportClasses() { | |||
return supportClasses; | |||
} | |||
@Override | |||
public DataType[] supportDataTypes() { | |||
return supportDataTypes; | |||
} | |||
@Override | |||
protected Object decode(Bytes value) { | |||
return BytesUtils.toLong(value.toBytes()); | |||
} | |||
@Override | |||
public Object decode(BytesValue value, Class<?> clazz) { | |||
// 支持转换为short、int、long | |||
long longVal = (long)decode(value); | |||
if (convertClasses.contains(clazz)) { | |||
// 对于short和Short需要强制类型转换 | |||
if (clazz.equals(short.class) || clazz.equals(Short.class)) { | |||
return (short) longVal; | |||
} else if (clazz.equals(int.class) || clazz.equals(Integer.class)) { | |||
return (int) longVal; | |||
} | |||
return longVal; | |||
} else { | |||
throw new IllegalStateException(String.format("Un-Support decode value to class[%s] !!!", clazz.getName())); | |||
} | |||
} | |||
} |
@@ -0,0 +1,57 @@ | |||
package com.jd.blockchain.ledger.resolver; | |||
import com.jd.blockchain.ledger.BytesData; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.DataType; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.blockchain.utils.io.BytesUtils; | |||
import java.util.Set; | |||
public class ShortToBytesValueResolver extends AbstractBytesValueResolver { | |||
private final Class<?>[] supportClasses = {Short.class, short.class}; | |||
private final DataType[] supportDataTypes = {DataType.INT16}; | |||
private final Set<Class<?>> convertClasses = initIntConvertSet(); | |||
@Override | |||
public BytesValue encode(Object value, Class<?> type) { | |||
if (!isSupport(type)) { | |||
throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); | |||
} | |||
return BytesData.fromInt16((short)value); | |||
} | |||
@Override | |||
public Class<?>[] supportClasses() { | |||
return supportClasses; | |||
} | |||
@Override | |||
public DataType[] supportDataTypes() { | |||
return supportDataTypes; | |||
} | |||
@Override | |||
protected Object decode(Bytes value) { | |||
return BytesUtils.toShort(value.toBytes()); | |||
} | |||
@Override | |||
public Object decode(BytesValue value, Class<?> clazz) { | |||
// 支持转换为short、int、long,由short转int、long无需转换 | |||
short shortVal = (short)decode(value); | |||
if (convertClasses.contains(clazz)) { | |||
if (clazz.equals(int.class) || clazz.equals(Integer.class)) { | |||
return (int) shortVal; | |||
} else if (clazz.equals(long.class) || clazz.equals(Long.class)) { | |||
return (long) shortVal; | |||
} | |||
return shortVal; | |||
} else { | |||
throw new IllegalStateException(String.format("Un-Support decode value to class[%s] !!!", clazz.getName())); | |||
} | |||
} | |||
} |
@@ -0,0 +1,66 @@ | |||
package com.jd.blockchain.ledger.resolver; | |||
import com.jd.blockchain.ledger.BytesData; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.DataType; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.blockchain.utils.io.BytesUtils; | |||
import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; | |||
import java.util.Set; | |||
public class StringToBytesValueResolver extends AbstractBytesValueResolver { | |||
private final Class<?>[] supportClasses = {String.class}; | |||
private final DataType[] supportDataTypes = {DataType.TEXT, DataType.XML, DataType.JSON}; | |||
private final Set<Class<?>> convertClasses = initByteConvertSet(); | |||
@Override | |||
public BytesValue encode(Object value, Class<?> type) { | |||
if (!isSupport(type)) { | |||
throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); | |||
} | |||
// 类型判断 | |||
String valString = (String)value; | |||
if (JSONSerializeUtils.isJSON(valString)) { | |||
return BytesData.fromJSON(valString); | |||
} | |||
// 暂不处理XML格式 | |||
return BytesData.fromText(valString); | |||
} | |||
@Override | |||
public Class<?>[] supportClasses() { | |||
return supportClasses; | |||
} | |||
@Override | |||
public DataType[] supportDataTypes() { | |||
return supportDataTypes; | |||
} | |||
@Override | |||
protected Object decode(Bytes value) { | |||
return BytesUtils.toString(value.toBytes()); | |||
} | |||
@Override | |||
public Object decode(BytesValue value, Class<?> clazz) { | |||
// 支持三种类型对象返回,String.class,byte[].class,Bytes.class | |||
String textValue = (String)decode(value); | |||
if (!convertClasses.contains(clazz)) { | |||
throw new IllegalStateException(String.format("Un-Support decode value to class[%s] !!!", clazz.getName())); | |||
} | |||
if (clazz.equals(byte[].class)) { | |||
return BytesUtils.toBytes(textValue); | |||
} else if (clazz.equals(Bytes.class)) { | |||
return Bytes.fromString(textValue); | |||
} | |||
return textValue; | |||
} | |||
} |
@@ -53,7 +53,7 @@ public class ContractInvocationHandler implements InvocationHandler { | |||
} | |||
// 序列化调用参数; | |||
Class<?>[] argTypes = method.getParameterTypes(); | |||
BytesValueList argBytes = BytesValueEncoding.encode(args, argTypes); | |||
BytesValueList argBytes = BytesValueEncoding.encodeArray(args, argTypes); | |||
// 定义合约调用操作; | |||
ContractEventSendOpTemplate opTemplate = (ContractEventSendOpTemplate) sendOpBuilder.send(contractAddress, | |||
@@ -0,0 +1,43 @@ | |||
package test.com.jd.blockchain.ledger.data; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.DataType; | |||
import com.jd.blockchain.ledger.resolver.BytesToBytesValueResolver; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.blockchain.utils.io.BytesUtils; | |||
import static org.junit.Assert.*; | |||
import org.junit.Test; | |||
public class BytesToBytesValueResolverTest { | |||
private BytesToBytesValueResolver resolver = new BytesToBytesValueResolver(); | |||
@Test | |||
public void test() { | |||
String text = "www.jd.com"; | |||
byte[] bytes = BytesUtils.toBytes(text); | |||
Bytes bytesObj = Bytes.fromString(text); | |||
BytesValue bytesValue = resolver.encode(bytes); | |||
assertNotNull(bytesValue); | |||
assertEquals(bytesValue.getType(), DataType.BYTES); | |||
assertEquals(bytesObj, bytesValue.getValue()); | |||
Bytes resolveBytesObj = (Bytes)resolver.decode(bytesValue); | |||
assertEquals(bytesObj, resolveBytesObj); | |||
byte[] resolveBytes = (byte[])resolver.decode(bytesValue, byte[].class); | |||
assertArrayEquals(bytes, resolveBytes); | |||
String resolveText = (String)resolver.decode(bytesValue, String.class); | |||
assertEquals(text, resolveText); | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
package test.com.jd.blockchain.ledger.data; | |||
import com.jd.blockchain.ledger.BytesValueEncoding; | |||
import com.jd.blockchain.utils.Bytes; | |||
import static org.junit.Assert.*; | |||
import org.junit.Test; | |||
public class BytesValueEncodingTest { | |||
@Test | |||
public void testSupport() { | |||
assertTrue(BytesValueEncoding.supportType(byte[].class)); | |||
assertTrue(BytesValueEncoding.supportType(int.class)); | |||
assertTrue(BytesValueEncoding.supportType(Integer.class)); | |||
assertTrue(BytesValueEncoding.supportType(short.class)); | |||
assertTrue(BytesValueEncoding.supportType(Short.class)); | |||
assertTrue(BytesValueEncoding.supportType(long.class)); | |||
assertTrue(BytesValueEncoding.supportType(Long.class)); | |||
assertTrue(BytesValueEncoding.supportType(String.class)); | |||
assertTrue(BytesValueEncoding.supportType(Bytes.class)); | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
package test.com.jd.blockchain.ledger.data; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.DataType; | |||
import com.jd.blockchain.ledger.resolver.IntegerToBytesValueResolver; | |||
import static org.junit.Assert.*; | |||
import com.jd.blockchain.utils.Bytes; | |||
import org.junit.Test; | |||
public class IntegerToBytesValueResolverTest { | |||
private IntegerToBytesValueResolver resolver = new IntegerToBytesValueResolver(); | |||
@Test | |||
public void test() { | |||
int intVal = 1024; | |||
BytesValue intBytesValue = resolver.encode(intVal); | |||
BytesValue intBytesValue1 = resolver.encode(intVal, int.class); | |||
BytesValue intBytesValue2 = resolver.encode(intVal, Integer.class); | |||
assertEquals(intBytesValue.getValue(), intBytesValue1.getValue()); | |||
assertEquals(intBytesValue.getValue(), intBytesValue2.getValue()); | |||
Bytes intBytes = Bytes.fromInt(intVal); | |||
assertEquals(intBytes, intBytesValue.getValue()); | |||
assertEquals(intBytesValue.getType(), DataType.INT32); | |||
int resolveInt = (int)resolver.decode(intBytesValue); | |||
assertEquals(intVal, resolveInt); | |||
short resolveShort = (short) resolver.decode(intBytesValue, short.class); | |||
assertEquals(resolveShort, 1024); | |||
Short resolveShortObj = (Short) resolver.decode(intBytesValue, Short.class); | |||
assertEquals((short)resolveShortObj, resolveShort); | |||
long resolveLong = (long) resolver.decode(intBytesValue, long.class); | |||
assertEquals(resolveLong, 1024L); | |||
Long resolveLongObj = (Long) resolver.decode(intBytesValue, Long.class); | |||
assertEquals(resolveLong, (long) resolveLongObj); | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
package test.com.jd.blockchain.ledger.data; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.DataType; | |||
import com.jd.blockchain.ledger.resolver.IntegerToBytesValueResolver; | |||
import com.jd.blockchain.ledger.resolver.LongToBytesValueResolver; | |||
import com.jd.blockchain.utils.Bytes; | |||
import org.junit.Test; | |||
import static org.junit.Assert.assertEquals; | |||
public class LongToBytesValueResolverTest { | |||
private LongToBytesValueResolver resolver = new LongToBytesValueResolver(); | |||
@Test | |||
public void test() { | |||
long longVal = 65536L; | |||
BytesValue longBytesValue = resolver.encode(longVal); | |||
BytesValue longBytesValue1 = resolver.encode(longVal, long.class); | |||
BytesValue longBytesValue2 = resolver.encode(longVal, Long.class); | |||
assertEquals(longBytesValue.getValue(), longBytesValue1.getValue()); | |||
assertEquals(longBytesValue.getValue(), longBytesValue2.getValue()); | |||
Bytes longBytes = Bytes.fromLong(longVal); | |||
assertEquals(longBytes, longBytesValue.getValue()); | |||
assertEquals(longBytesValue.getType(), DataType.INT64); | |||
long resolveLong = (long)resolver.decode(longBytesValue); | |||
assertEquals(longVal, resolveLong); | |||
short resolveShort = (short) resolver.decode(longBytesValue, short.class); | |||
assertEquals(resolveShort, (short)65536); | |||
Short resolveShortObj = (Short) resolver.decode(longBytesValue, Short.class); | |||
assertEquals((short)resolveShortObj, resolveShort); | |||
int resolveInt = (int) resolver.decode(longBytesValue, int.class); | |||
assertEquals(resolveInt, 65536); | |||
Integer resolveIntObj = (Integer) resolver.decode(longBytesValue, Integer.class); | |||
assertEquals(resolveInt, (int) resolveIntObj); | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
package test.com.jd.blockchain.ledger.data; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.DataType; | |||
import com.jd.blockchain.ledger.resolver.ShortToBytesValueResolver; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.blockchain.utils.io.BytesUtils; | |||
import org.junit.Test; | |||
import static org.junit.Assert.assertEquals; | |||
public class ShortToBytesValueResolverTest { | |||
private ShortToBytesValueResolver resolver = new ShortToBytesValueResolver(); | |||
@Test | |||
public void test() { | |||
short shortVal = 64; | |||
BytesValue shortBytesValue = resolver.encode(shortVal); | |||
Bytes shortBytes = new Bytes(BytesUtils.toBytes(shortVal)); | |||
assertEquals(shortBytes, shortBytesValue.getValue()); | |||
assertEquals(shortBytesValue.getType(), DataType.INT16); | |||
short resolveShort = (short)resolver.decode(shortBytesValue); | |||
assertEquals(shortVal, resolveShort); | |||
int resolveInt = (int) resolver.decode(shortBytesValue, int.class); | |||
assertEquals(resolveInt, 64); | |||
Integer resolveIntObj = (Integer) resolver.decode(shortBytesValue, Integer.class); | |||
assertEquals((int)resolveIntObj, resolveShort); | |||
long resolveLong = (long) resolver.decode(shortBytesValue, long.class); | |||
assertEquals(resolveLong, 64L); | |||
Long resolveLongObj = (Long) resolver.decode(shortBytesValue, Long.class); | |||
assertEquals(resolveLong, (long) resolveLongObj); | |||
} | |||
} |
@@ -0,0 +1,79 @@ | |||
package test.com.jd.blockchain.ledger.data; | |||
import com.alibaba.fastjson.JSON; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.DataType; | |||
import com.jd.blockchain.ledger.resolver.StringToBytesValueResolver; | |||
import com.jd.blockchain.utils.Bytes; | |||
import static org.junit.Assert.*; | |||
import com.jd.blockchain.utils.io.BytesUtils; | |||
import org.junit.Test; | |||
public class StringToBytesValueResolverTest { | |||
private StringToBytesValueResolver resolver = new StringToBytesValueResolver(); | |||
@Test | |||
public void testText() { | |||
String textVal = "JDChain"; | |||
BytesValue textBytesValue = resolver.encode(textVal); | |||
assertEquals(Bytes.fromString(textVal), textBytesValue.getValue()); | |||
assertEquals(textBytesValue.getType(), DataType.TEXT); | |||
String resolveText = (String)resolver.decode(textBytesValue); | |||
assertEquals(resolveText, textVal); | |||
byte[] resolveBytes = (byte[]) resolver.decode(textBytesValue, byte[].class); | |||
assertArrayEquals(resolveBytes, BytesUtils.toBytes(textVal)); | |||
Bytes resolveBytesObj = (Bytes) resolver.decode(textBytesValue, Bytes.class); | |||
assertEquals(resolveBytesObj, Bytes.fromString(textVal)); | |||
} | |||
@Test | |||
public void testJson() { | |||
Person person = new Person("zhangsan", 80); | |||
String personJson = JSON.toJSONString(person); | |||
BytesValue textBytesValue = resolver.encode(personJson); | |||
assertEquals(Bytes.fromString(personJson), textBytesValue.getValue()); | |||
assertEquals(textBytesValue.getType(), DataType.JSON); | |||
} | |||
public static class Person { | |||
private String name; | |||
private int age; | |||
public Person() { | |||
} | |||
public Person(String name, int age) { | |||
this.name = name; | |||
this.age = age; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public void setName(String name) { | |||
this.name = name; | |||
} | |||
public int getAge() { | |||
return age; | |||
} | |||
public void setAge(int age) { | |||
this.age = age; | |||
} | |||
} | |||
} |
@@ -31,348 +31,347 @@ import java.lang.reflect.Field; | |||
public class ClientResolveUtil { | |||
public static KVDataEntry[] read(KVDataEntry[] kvDataEntries) { | |||
if (kvDataEntries == null || kvDataEntries.length == 0) { | |||
return kvDataEntries; | |||
} | |||
KVDataEntry[] resolveKvDataEntries = new KVDataEntry[kvDataEntries.length]; | |||
// kvDataEntries是代理对象,需要处理 | |||
for (int i = 0; i < kvDataEntries.length; i++) { | |||
KVDataEntry kvDataEntry = kvDataEntries[i]; | |||
String key = kvDataEntry.getKey(); | |||
long version = kvDataEntry.getVersion(); | |||
DataType dataType = kvDataEntry.getType(); | |||
KvData innerKvData = new KvData(key, version, dataType); | |||
Object valueObj = kvDataEntry.getValue(); | |||
switch (dataType) { | |||
case NIL: | |||
break; | |||
case BYTES: | |||
case TEXT: | |||
case JSON: | |||
innerKvData.setValue(valueObj.toString()); | |||
break; | |||
case INT32: | |||
innerKvData.setValue(Integer.parseInt(valueObj.toString())); | |||
break; | |||
case INT64: | |||
innerKvData.setValue(Long.parseLong(valueObj.toString())); | |||
break; | |||
default: | |||
throw new IllegalStateException("Unsupported value type[" + dataType + "] to resolve!"); | |||
} | |||
resolveKvDataEntries[i] = innerKvData; | |||
} | |||
return resolveKvDataEntries; | |||
} | |||
public static Operation read(Operation operation) { | |||
try { | |||
// Class | |||
Class<?> clazz = operation.getClass(); | |||
Field field = clazz.getSuperclass().getDeclaredField("h"); | |||
field.setAccessible(true); | |||
Object object = field.get(operation); | |||
if (object instanceof JSONObject) { | |||
JSONObject jsonObject = (JSONObject) object; | |||
if (jsonObject.containsKey("accountID")) { | |||
return convertDataAccountRegisterOperation(jsonObject); | |||
} else if (jsonObject.containsKey("userID")) { | |||
return convertUserRegisterOperation(jsonObject); | |||
} else if (jsonObject.containsKey("contractID")) { | |||
return convertContractCodeDeployOperation(jsonObject); | |||
} else if (jsonObject.containsKey("writeSet")) { | |||
return convertDataAccountKVSetOperation(jsonObject); | |||
} else if (jsonObject.containsKey("initSetting")) { | |||
return convertLedgerInitOperation(jsonObject); | |||
} else if (jsonObject.containsKey("contractAddress")) { | |||
return convertContractEventSendOperation(jsonObject); | |||
} | |||
} | |||
} catch (Exception e) { | |||
throw new RuntimeException(e); | |||
} | |||
return null; | |||
} | |||
public static Object readValueByBytesValue(BytesValue bytesValue) { | |||
DataType dataType = bytesValue.getType(); | |||
Bytes saveVal = bytesValue.getValue(); | |||
Object showVal; | |||
switch (dataType) { | |||
case BYTES: | |||
// return hex | |||
showVal = HexUtils.encode(saveVal.toBytes()); | |||
break; | |||
case TEXT: | |||
case JSON: | |||
showVal = saveVal.toUTF8String(); | |||
break; | |||
case INT64: | |||
showVal = BytesUtils.toLong(saveVal.toBytes()); | |||
break; | |||
default: | |||
showVal = HexUtils.encode(saveVal.toBytes()); | |||
break; | |||
} | |||
return showVal; | |||
} | |||
public static DataAccountRegisterOperation convertDataAccountRegisterOperation(JSONObject jsonObject) { | |||
JSONObject account = jsonObject.getJSONObject("accountID"); | |||
return new DataAccountRegisterOpTemplate(blockchainIdentity(account)); | |||
} | |||
public static DataAccountKVSetOperation convertDataAccountKVSetOperation(JSONObject jsonObject) { | |||
// 写入集合处理 | |||
JSONArray writeSetObj = jsonObject.getJSONArray("writeSet"); | |||
JSONObject accountAddrObj = jsonObject.getJSONObject("accountAddress"); | |||
String addressBase58 = accountAddrObj.getString("value"); | |||
Bytes address = Bytes.fromBase58(addressBase58); | |||
DataAccountKVSetOpTemplate kvOperation = new DataAccountKVSetOpTemplate(address); | |||
for (int i = 0; i < 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; | |||
} | |||
} | |||
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, | |||
BytesValueEncoding.encodeArray(new Object[]{argsStr}, null)); | |||
} | |||
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; | |||
} | |||
} | |||
} |
@@ -17,8 +17,7 @@ import com.jd.blockchain.utils.Bytes; | |||
public class SDK_Contract_Demo extends SDK_Base_Demo { | |||
public static void main(String[] args) { | |||
SDK_Contract_Demo demo = new SDK_Contract_Demo(); | |||
demo.executeContract(); | |||
new SDK_Contract_Demo().executeContract(); | |||
} | |||
public void executeContract() { | |||
@@ -42,7 +42,7 @@ public class CompositeConnectionFactory implements DbConnectionFactory { | |||
connectionFactoryMap.put(dbPrefix, dbConnectionFactory); | |||
} | |||
} catch (Exception e) { | |||
LOGGER.error("class:{%s} init error {%s}", clazz.getName(), e.getMessage()); | |||
LOGGER.error("class:{} init error {}", clazz.getName(), e.getMessage()); | |||
} | |||
} | |||
} | |||
@@ -9,12 +9,7 @@ import com.jd.blockchain.contract.ContractException; | |||
import com.jd.blockchain.contract.EventProcessingAware; | |||
import com.jd.blockchain.contract.LedgerContext; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.BlockchainIdentity; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.BytesValueList; | |||
import com.jd.blockchain.ledger.ContractEventSendOperation; | |||
import com.jd.blockchain.ledger.Operation; | |||
import com.jd.blockchain.ledger.TransactionRequest; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.ledger.core.LedgerDataSet; | |||
import com.jd.blockchain.ledger.core.LedgerService; | |||
import com.jd.blockchain.ledger.core.OperationHandle; | |||
@@ -74,7 +69,7 @@ public class MockerContractExeHandle implements OperationHandle { | |||
} | |||
// No return value; | |||
return null; | |||
return BytesValueEncoding.encodeSingle(result, null); | |||
} | |||
@Override | |||
@@ -78,7 +78,7 @@ public class ContractProxy<T> implements InvocationHandler { | |||
OperationResult opResult = operationResults[0]; | |||
// 处理返回值 | |||
return BytesValueEncoding.encode(opResult.getResult(), method.getReturnType()); | |||
return BytesValueEncoding.encodeSingle(opResult.getResult(), method.getReturnType()); | |||
} | |||
private boolean isExecuteContractMethod(Method method) { | |||
@@ -6,6 +6,7 @@ import java.io.InputStream; | |||
import java.io.ObjectOutputStream; | |||
import java.io.OutputStream; | |||
import java.io.UnsupportedEncodingException; | |||
import java.math.BigInteger; | |||
import com.jd.blockchain.utils.IllegalDataException; | |||
@@ -370,6 +371,10 @@ public class BytesUtils { | |||
return value; | |||
} | |||
public static short toShort(byte[] bytes) { | |||
return toShort(bytes, 0); | |||
} | |||
public static char toChar(byte[] bytes, int offset) { | |||
char value = 0; | |||
value = (char) ((value | (bytes[offset] & 0xFF)) << 8); | |||