Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.fisco.bcos.sdk.v3.codec.ContractCodec Maven / Gradle / Ivy
/*
* Copyright 2014-2020 [fisco-dev]
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*
*/
package org.fisco.bcos.sdk.v3.codec;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.fisco.bcos.sdk.v3.codec.abi.Constant;
import org.fisco.bcos.sdk.v3.codec.datatypes.AbiTypes;
import org.fisco.bcos.sdk.v3.codec.datatypes.Address;
import org.fisco.bcos.sdk.v3.codec.datatypes.Bool;
import org.fisco.bcos.sdk.v3.codec.datatypes.DynamicArray;
import org.fisco.bcos.sdk.v3.codec.datatypes.DynamicBytes;
import org.fisco.bcos.sdk.v3.codec.datatypes.DynamicStruct;
import org.fisco.bcos.sdk.v3.codec.datatypes.StaticArray;
import org.fisco.bcos.sdk.v3.codec.datatypes.StaticStruct;
import org.fisco.bcos.sdk.v3.codec.datatypes.Type;
import org.fisco.bcos.sdk.v3.codec.datatypes.TypeReference;
import org.fisco.bcos.sdk.v3.codec.datatypes.Utf8String;
import org.fisco.bcos.sdk.v3.codec.datatypes.generated.Uint8;
import org.fisco.bcos.sdk.v3.codec.scale.FunctionReturnDecoder;
import org.fisco.bcos.sdk.v3.codec.wrapper.ABIDefinition;
import org.fisco.bcos.sdk.v3.codec.wrapper.ABIDefinitionFactory;
import org.fisco.bcos.sdk.v3.codec.wrapper.ABIObject;
import org.fisco.bcos.sdk.v3.codec.wrapper.ABIObjectFactory;
import org.fisco.bcos.sdk.v3.codec.wrapper.ContractABIDefinition;
import org.fisco.bcos.sdk.v3.codec.wrapper.ContractCodecJsonWrapper;
import org.fisco.bcos.sdk.v3.codec.wrapper.ContractCodecTools;
import org.fisco.bcos.sdk.v3.crypto.CryptoSuite;
import org.fisco.bcos.sdk.v3.crypto.hash.Hash;
import org.fisco.bcos.sdk.v3.crypto.hash.Keccak256;
import org.fisco.bcos.sdk.v3.crypto.hash.SM3Hash;
import org.fisco.bcos.sdk.v3.model.CryptoType;
import org.fisco.bcos.sdk.v3.model.EventLog;
import org.fisco.bcos.sdk.v3.utils.Hex;
import org.fisco.bcos.sdk.v3.utils.Numeric;
import org.fisco.bcos.sdk.v3.utils.ObjectMapperFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** ABI encode and decode tool */
public class ContractCodec {
private static final Logger logger = LoggerFactory.getLogger(ContractCodec.class);
private final CryptoSuite cryptoSuite;
private final Hash hashImpl;
private final boolean isWasm;
private final ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper();
private FunctionEncoderInterface functionEncoder = null;
private FunctionReturnDecoderInterface functionReturnDecoder = null;
private final ABIDefinitionFactory abiDefinitionFactory;
private final ContractCodecJsonWrapper contractCodecJsonWrapper =
new ContractCodecJsonWrapper();
@Deprecated
public ContractCodec(CryptoSuite cryptoSuite, boolean isWasm) {
this.cryptoSuite = cryptoSuite;
this.hashImpl = cryptoSuite.getHashImpl();
this.isWasm = isWasm;
if (isWasm) {
this.functionEncoder =
new org.fisco.bcos.sdk.v3.codec.scale.FunctionEncoder(this.hashImpl);
this.functionReturnDecoder = new FunctionReturnDecoder();
} else {
this.functionEncoder =
new org.fisco.bcos.sdk.v3.codec.abi.FunctionEncoder(this.hashImpl);
this.functionReturnDecoder =
new org.fisco.bcos.sdk.v3.codec.abi.FunctionReturnDecoder();
}
this.abiDefinitionFactory = new ABIDefinitionFactory(hashImpl);
}
public ContractCodec(Hash hashImpl, boolean isWasm) {
this.hashImpl = hashImpl;
this.isWasm = isWasm;
if (isWasm) {
this.functionEncoder =
new org.fisco.bcos.sdk.v3.codec.scale.FunctionEncoder(this.hashImpl);
this.functionReturnDecoder = new FunctionReturnDecoder();
} else {
this.functionEncoder =
new org.fisco.bcos.sdk.v3.codec.abi.FunctionEncoder(this.hashImpl);
this.functionReturnDecoder =
new org.fisco.bcos.sdk.v3.codec.abi.FunctionReturnDecoder();
}
this.abiDefinitionFactory = new ABIDefinitionFactory(this.hashImpl);
// for compatibility
if (this.hashImpl instanceof SM3Hash) {
this.cryptoSuite = new CryptoSuite(CryptoType.SM_TYPE);
} else if (this.hashImpl instanceof Keccak256) {
this.cryptoSuite = new CryptoSuite(CryptoType.ECDSA_TYPE);
} else {
this.cryptoSuite = null;
}
}
public boolean isWasm() {
return isWasm;
}
@Deprecated
public CryptoSuite getCryptoSuite() {
return this.cryptoSuite;
}
public ABIDefinitionFactory getAbiDefinitionFactory() {
return abiDefinitionFactory;
}
public FunctionEncoderInterface getFunctionEncoder() {
return functionEncoder;
}
private Type buildType(ABIDefinition.NamedType namedType, String param)
throws ContractCodecException, IOException {
String typeStr = namedType.getType();
ABIDefinition.Type paramType = new ABIDefinition.Type(typeStr);
Type type = null;
if (paramType.isList()) {
List elements = new ArrayList();
JsonNode jsonNode = this.objectMapper.readTree(param);
ABIDefinition.NamedType subType = new ABIDefinition.NamedType();
subType.setType(paramType.reduceDimensionAndGetType().getType());
subType.setComponents(namedType.getComponents());
for (JsonNode subNode : jsonNode) {
String subNodeStr =
subNode.isTextual()
? subNode.asText()
: this.objectMapper.writeValueAsString(subNode);
Type element = buildType(subType, subNodeStr);
elements.add(element);
}
if (elements.isEmpty()) {
Class extends Type> arrayClass = AbiTypes.getType(paramType.rawType);
type =
paramType.isFixedList()
? new StaticArray(arrayClass, elements)
: new DynamicArray(arrayClass, elements);
} else {
type =
paramType.isFixedList()
? new StaticArray(elements.get(0).getClass(), elements)
: new DynamicArray(elements.get(0).getClass(), elements);
}
return type;
} else if (typeStr.equals("tuple")) {
List components = new ArrayList<>();
JsonNode jsonNode = this.objectMapper.readTree(param);
for (ABIDefinition.NamedType component : namedType.getComponents()) {
JsonNode subNode = jsonNode.get(component.getName());
String subNodeStr =
subNode.isTextual()
? subNode.asText()
: this.objectMapper.writeValueAsString(subNode);
components.add(buildType(component, subNodeStr));
}
type =
namedType.isDynamic()
? new DynamicStruct(components)
: new StaticStruct(components);
return type;
} else {
if (typeStr.startsWith("uint")) {
int bitSize = 256;
if (!typeStr.equals("uint")) {
String bitSizeStr = typeStr.substring("uint".length());
try {
bitSize = Integer.parseInt(bitSizeStr);
} catch (NumberFormatException e) {
String errorMsg =
" unrecognized type: " + typeStr + ", error:" + e.getCause();
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
}
try {
Class> uintClass =
Class.forName(
"org.fisco.bcos.sdk.v3.codec.datatypes.generated.Uint"
+ bitSize);
type =
(Type)
uintClass
.getDeclaredConstructor(BigInteger.class)
.newInstance(new BigInteger(param));
} catch (ClassNotFoundException
| NoSuchMethodException
| InstantiationException
| IllegalAccessException
| InvocationTargetException e) {
String errorMsg =
"buildType error, type: " + typeStr + ", error: " + e.getCause();
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
return type;
}
if (typeStr.startsWith("int")) {
int bitSize = 256;
if (!typeStr.equals("int")) {
String bitSizeStr = typeStr.substring("int".length());
try {
bitSize = Integer.parseInt(bitSizeStr);
} catch (NumberFormatException e) {
String errorMsg = "unrecognized int type: " + typeStr;
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
}
try {
Class> uintClass =
Class.forName(
"org.fisco.bcos.sdk.v3.codec.datatypes.generated.Int"
+ bitSize);
type =
(Type)
uintClass
.getDeclaredConstructor(BigInteger.class)
.newInstance(new BigInteger(param));
} catch (ClassNotFoundException
| NoSuchMethodException
| InstantiationException
| IllegalAccessException
| InvocationTargetException e) {
String errorMsg = "unrecognized type: " + typeStr + ", error:" + e.getCause();
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
return type;
}
if (typeStr.equals("bool")) {
type = new Bool(Boolean.parseBoolean(param));
return type;
}
if (typeStr.equals("string")) {
type = new Utf8String(param);
return type;
}
if (typeStr.equals("bytes")) {
byte[] bytes = ContractCodecJsonWrapper.tryDecodeInputData(param);
if (bytes == null) {
bytes = param.getBytes();
}
type = new DynamicBytes(bytes);
return type;
}
if (typeStr.equals("address")) {
type = new Address(param);
return type;
}
// static bytesN
if (typeStr.startsWith("bytes")) {
String lengthStr = typeStr.substring("bytes".length());
int length;
try {
length = Integer.parseInt(lengthStr);
} catch (NumberFormatException e) {
String errorMsg = "unrecognized static byte array type: " + typeStr;
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
if (length > 32) {
String errorMsg = "the length of static byte array exceeds 32: " + typeStr;
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
byte[] bytesN = ContractCodecJsonWrapper.tryDecodeInputData(param);
if (bytesN == null) {
bytesN = param.getBytes();
}
if (bytesN.length != length) {
String errorMsg =
String.format(
"expected byte array at length %d but length of provided in data is %d",
length, bytesN.length);
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
try {
Class> bytesClass =
Class.forName(
"org.fisco.bcos.sdk.v3.codec.datatypes.generated.Bytes"
+ length);
type =
(Type)
bytesClass
.getDeclaredConstructor(byte[].class)
.newInstance(bytesN);
} catch (ClassNotFoundException
| NoSuchMethodException
| InstantiationException
| IllegalAccessException
| InvocationTargetException e) {
e.printStackTrace();
}
return type;
}
}
String errorMsg = "unrecognized type: " + typeStr;
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
// -------------------------------------------------------------------------------
// ------------------------------- encode begin --------------------------------
public byte[] encodeConstructor(String abi, String bin, List params)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
ABIDefinition abiDefinition = contractABIDefinition.getConstructor();
ABIObject inputABIObject = ABIObjectFactory.createInputObject(abiDefinition);
try {
byte[] encodeParams =
ContractCodecTools.encode(
ContractCodecTools.decodeABIObjectValue(inputABIObject, params),
isWasm);
return encodeConstructorFromBytes(bin, encodeParams);
} catch (Exception e) {
logger.error(" exception in encodeConstructor : {}", e.getMessage());
}
String errorMsg = " cannot encode in encodeConstructor with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public byte[] encodeConstructorFromString(String abi, String bin, List params)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
ABIDefinition abiDefinition = contractABIDefinition.getConstructor();
List inputTypes = abiDefinition.getInputs();
if (inputTypes.size() != params.size()) {
String errorMsg =
String.format(
" expected %d parameters but provided %d parameters",
inputTypes.size(), params.size());
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
try {
ABIObject inputObject = ABIObjectFactory.createInputObject(abiDefinition);
ABIObject abiObject = contractCodecJsonWrapper.encode(inputObject, params);
byte[] paramBytes = abiObject.encode(isWasm);
return encodeConstructorFromBytes(bin, paramBytes);
} catch (Exception e) {
String errorMsg =
" cannot encode in encodeMethodFromObject with appropriate interface ABI, cause:"
+ e.getMessage();
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
}
public byte[] encodeConstructorFromBytes(String bin, byte[] params)
throws ContractCodecException {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
if (!this.isWasm) {
outputStream.write(Hex.decode(bin));
if (params != null) {
outputStream.write(params);
}
} else {
List deployParams = new ArrayList<>();
deployParams.add(new DynamicBytes(Hex.decode(bin)));
if (params != null) {
deployParams.add(new DynamicBytes(params));
} else {
deployParams.add(new Uint8(0));
}
outputStream.write(
org.fisco.bcos.sdk.v3.codec.scale.FunctionEncoder.encodeParameters(
deployParams, null));
}
return outputStream.toByteArray();
} catch (Exception e) {
logger.error(" exception in encodeMethodFromObject : {}", e.getMessage());
String errorMsg =
" cannot encode in encodeMethodFromObject with appropriate interface ABI, cause:"
+ e.getMessage();
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
}
public byte[] encodeMethod(String abi, String methodName, List params)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
List methods = contractABIDefinition.getFunctions().get(methodName);
if (methods == null || methods.isEmpty()) {
throw new ContractCodecException(Constant.NO_APPROPRIATE_ABI_METHOD);
}
for (ABIDefinition abiDefinition : methods) {
if (abiDefinition.getInputs().size() == params.size()) {
try {
return encodeMethodByAbiDefinition(abiDefinition, params);
} catch (Exception e) {
logger.error(" exception in encodeMethodFromObject : {}", e.getMessage());
}
}
}
logger.error(Constant.NO_APPROPRIATE_ABI_METHOD);
throw new ContractCodecException(Constant.NO_APPROPRIATE_ABI_METHOD);
}
public byte[] encodeMethodByAbiDefinition(ABIDefinition abiDefinition, List params)
throws ContractCodecException {
ABIObject inputABIObject = ABIObjectFactory.createInputObject(abiDefinition);
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(abiDefinition.getMethodId(this.cryptoSuite));
outputStream.write(
ContractCodecTools.encode(
ContractCodecTools.decodeABIObjectValue(inputABIObject, params),
isWasm));
return outputStream.toByteArray();
} catch (IOException e) {
throw new ContractCodecException(Constant.NO_APPROPRIATE_ABI_METHOD);
}
}
public byte[] encodeMethodById(String abi, byte[] methodId, List params)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
ABIDefinition abiDefinition = contractABIDefinition.getABIDefinitionByMethodId(methodId);
if (abiDefinition == null) {
throw new ContractCodecException(Constant.NO_APPROPRIATE_ABI_METHOD);
}
Exception cause;
try {
return encodeMethodByAbiDefinition(abiDefinition, params);
} catch (Exception e) {
cause = e;
logger.error(" exception in encodeMethodByIdFromObject : {}", e.getMessage());
}
String errorMsg =
" cannot encode in encodeMethodByIdFromObject with appropriate interface ABI, cause:"
+ cause.getMessage();
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public byte[] encodeMethodByInterface(String methodInterface, List params)
throws ContractCodecException {
ABIDefinition abiDefinition = ABIDefinition.createABIDefinition(methodInterface);
if (abiDefinition.getInputs().size() == params.size()) {
try {
return encodeMethodByAbiDefinition(abiDefinition, params);
} catch (Exception e) {
logger.error(
" exception in encodeMethodByInterfaceFromObject : {}", e.getMessage());
}
}
String errorMsg = " cannot encode in encodeMethodByInterfaceFromObject";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public byte[] encodeMethodFromString(String abi, String methodName, List params)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
List methods = contractABIDefinition.getFunctions().get(methodName);
if (methods == null) {
logger.debug(
"Invalid methodName: {}, all the functions are: {}",
methodName,
contractABIDefinition.getFunctions());
throw new ContractCodecException(
"Invalid method "
+ methodName
+ " , supported functions are: "
+ contractABIDefinition.getFunctions().keySet());
}
for (ABIDefinition abiDefinition : methods) {
if (abiDefinition.getInputs().size() == params.size()) {
ABIObject inputObject = ABIObjectFactory.createInputObject(abiDefinition);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
byte[] methodId = abiDefinition.getMethodId(cryptoSuite);
ABIObject abiObject = contractCodecJsonWrapper.encode(inputObject, params);
byte[] encode = abiObject.encode(isWasm);
outputStream.write(methodId);
outputStream.write(encode);
return outputStream.toByteArray();
} catch (Exception e) {
logger.error(" exception in encodeMethodFromString : {}", e.getMessage());
}
}
}
String errorMsg =
" cannot encode in encodeMethodFromString with appropriate interface ABI, make sure params match";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public byte[] encodeMethodByIdFromString(String abi, byte[] methodId, List params)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
ABIDefinition abiDefinition = contractABIDefinition.getABIDefinitionByMethodId(methodId);
if (abiDefinition == null) {
logger.error(Constant.NO_APPROPRIATE_ABI_METHOD);
throw new ContractCodecException(Constant.NO_APPROPRIATE_ABI_METHOD);
}
try {
ABIObject inputObject = ABIObjectFactory.createInputObject(abiDefinition);
ABIObject abiObject = contractCodecJsonWrapper.encode(inputObject, params);
byte[] encode = abiObject.encode(isWasm);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
if (methodId != null) {
outputStream.write(methodId);
}
outputStream.write(encode);
return outputStream.toByteArray();
} catch (Exception e) {
logger.error(" exception in encodeMethodByIdFromString : {}", e.getMessage());
}
String errorMsg =
" cannot encode in encodeMethodByIdFromString with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public byte[] encodeMethodByInterfaceFromString(String methodInterface, List params)
throws ContractCodecException {
ABIDefinition abiDefinition = ABIDefinition.createABIDefinition(methodInterface);
if (abiDefinition.getInputs().size() == params.size()) {
ABIObject inputABIObject = ABIObjectFactory.createInputObject(abiDefinition);
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(abiDefinition.getMethodId(this.cryptoSuite));
outputStream.write(
ContractCodecTools.encode(
contractCodecJsonWrapper.encode(inputABIObject, params), isWasm));
return outputStream.toByteArray();
} catch (Exception e) {
logger.error(
" exception in encodeMethodByInterfaceFromString : {}", e.getMessage());
}
}
String errorMsg = " cannot encode in encodeMethodByInterfaceFromString";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
// ------------------------------- encode end -----------------------------------------------
// -------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------
// ------------------------------- decode input begin ---------------------------------------
public Pair, List> decodeMethodAndGetInputObject(
ABIDefinition abiDefinition, String input) throws ContractCodecException {
ABIObject abiObject = decodeMethodAndGetInputObjectByABIDefinition(abiDefinition, input);
return ContractCodecTools.decodeJavaObjectAndGetOutputObject(abiObject);
}
public ABIObject decodeMethodAndGetInputObjectByABIDefinition(
ABIDefinition abiDefinition, String input) throws ContractCodecException {
ABIObject inputObject = ABIObjectFactory.createInputObject(abiDefinition);
try {
boolean startWithHexPrefix = input.startsWith("0x") || input.startsWith("0X");
return ContractCodecTools.decode(
inputObject, Hex.decode(input.substring(startWithHexPrefix ? 10 : 8)), isWasm);
} catch (Exception e) {
logger.error(" exception in decodeMethodToObject : ", e);
}
String errorMsg =
" cannot decode in decodeMethodAndGetInputObject with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
@Deprecated
public List decodeMethodAndGetInputObject(String abi, String methodName, String input)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
List methods = contractABIDefinition.getFunctions().get(methodName);
for (ABIDefinition abiDefinition : methods) {
List inputs = abiDefinition.getInputs();
List> inputTypes = new ArrayList<>();
try {
for (ABIDefinition.NamedType namedType : inputs) {
inputTypes.add(TypeReference.makeTypeReference(namedType.getType(), false));
}
boolean startWithHexPrefix = input.startsWith("0x") || input.startsWith("0X");
return this.functionReturnDecoder.decode(
input.substring(startWithHexPrefix ? 10 : 8), inputTypes);
} catch (Exception e) {
logger.error("exception in decodeMethodToObject: {}, e:", e.getMessage(), e);
}
}
String errorMsg =
String.format(
"cannot decode in decodeMethodAndGetInputObject with appropriate interface ABI: methodName = %s",
methodName);
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public ABIObject decodeMethodAndGetInputABIObject(String abi, String methodName, String input)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
List methods = contractABIDefinition.getFunctions().get(methodName);
for (ABIDefinition abiDefinition : methods) {
ABIObject inputObject = ABIObjectFactory.createInputObject(abiDefinition);
try {
boolean startWithHexPrefix = Hex.hasHexPrefix(input);
return ContractCodecTools.decode(
inputObject,
Hex.decode(input.substring(startWithHexPrefix ? 10 : 8)),
isWasm);
} catch (Exception e) {
logger.error("exception in decodeMethodToObject: {}, e:", e.getMessage(), e);
}
}
String errorMsg =
String.format(
"cannot decode in decodeMethodAndGetInputABIObject with appropriate interface ABI: methodName = %s",
methodName);
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public List decodeConstructorInput(String abi, String bin, String input)
throws ContractCodecException {
String paramsInput = StringUtils.substringAfter(input, bin);
if (paramsInput.isEmpty()) { //
return new ArrayList<>();
}
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
ABIDefinition abiDefinition = contractABIDefinition.getConstructor();
return this.decodeMethodAndGetInputObject(abiDefinition, paramsInput).getLeft();
}
public List decodeConstructorInputToString(String abi, String bin, String input)
throws ContractCodecException {
String paramsInput = StringUtils.substringAfter(input, bin);
if (paramsInput.isEmpty()) { //
return new ArrayList<>();
}
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
ABIDefinition abiDefinition = contractABIDefinition.getConstructor();
ABIObject inputObject = ABIObjectFactory.createInputObject(abiDefinition);
try {
return contractCodecJsonWrapper.decode(inputObject, Hex.decode(paramsInput), isWasm);
} catch (Exception e) {
logger.error(" exception in decodeConstructorInputToString : {}", e.getMessage());
}
String errorMsg =
" cannot decode in decodeConstructorInputToString with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public List decodeMethodInput(ABIDefinition abiDefinition, String input)
throws ContractCodecException {
return this.decodeMethodAndGetInputObject(abiDefinition, input).getLeft();
}
@Deprecated
public List decodeMethodInput(String abi, String methodName, String input)
throws ContractCodecException {
return this.decodeMethodAndGetInputObject(abi, methodName, input);
}
public List decodeMethodInputById(String abi, byte[] methodId, byte[] input)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
ABIDefinition abiDefinition = contractABIDefinition.getABIDefinitionByMethodId(methodId);
if (abiDefinition == null) {
String errorMsg = " methodId " + Hex.toHexString(methodId) + " is invalid";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
ABIObject inputObject = ABIObjectFactory.createInputObject(abiDefinition);
try {
return ContractCodecTools.decodeJavaObject(
inputObject, Hex.toHexString(input).substring(8), isWasm);
} catch (Exception e) {
logger.error(" exception in decodeMethodByIdToObject : {}", e.getMessage());
}
String errorMsg = " cannot decode in decodeMethodInputById with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public List decodeMethodInputByInterface(
String abi, String methodInterface, byte[] input) throws ContractCodecException {
byte[] methodId = functionEncoder.buildMethodId(methodInterface);
return this.decodeMethodInputById(abi, methodId, input);
}
public List decodeMethodInputToString(String abi, String methodName, byte[] input)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
List methods = contractABIDefinition.getFunctions().get(methodName);
if (methods == null) {
throw new ContractCodecException(
"Invalid method "
+ methodName
+ ", supported methods are: "
+ contractABIDefinition.getFunctions().keySet());
}
for (ABIDefinition abiDefinition : methods) {
ABIObject inputObject = ABIObjectFactory.createInputObject(abiDefinition);
try {
return contractCodecJsonWrapper.decode(
inputObject, Arrays.copyOfRange(input, 4, input.length), isWasm);
} catch (Exception e) {
logger.error(" exception in decodeMethodToString : {}", e.getMessage());
}
}
String errorMsg =
" cannot decode in decodeMethodInputToString with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public List decodeMethodInputByIdToString(String abi, byte[] methodId, byte[] input)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
ABIDefinition abiDefinition = contractABIDefinition.getABIDefinitionByMethodId(methodId);
if (abiDefinition == null) {
String errorMsg = " methodId " + Hex.toHexString(methodId) + " is invalid";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
ABIObject outputABIObject = ABIObjectFactory.createInputObject(abiDefinition);
try {
return contractCodecJsonWrapper.decode(
outputABIObject, Arrays.copyOfRange(input, 4, input.length), isWasm);
} catch (UnsupportedOperationException | ClassNotFoundException e) {
logger.error(" exception in decodeMethodInputByIdToString : {}", e.getMessage());
}
String errorMsg =
" cannot decode in decodeMethodInputByIdToString with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public List decodeMethodInputByInterfaceToString(
String abi, String methodInterface, byte[] input) throws ContractCodecException {
byte[] methodId = functionEncoder.buildMethodId(methodInterface);
return this.decodeMethodInputByIdToString(abi, methodId, input);
}
// ------------------------------- decode input end ---------------------------------------
// -------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------
// ------------------------------- decode output begin --------------------------------------
public Pair, List> decodeMethodAndGetOutputObject(
ABIDefinition abiDefinition, String output) throws ContractCodecException {
ABIObject abiObject = decodeMethodAndGetOutAbiObjectByABIDefinition(abiDefinition, output);
return ContractCodecTools.decodeJavaObjectAndGetOutputObject(abiObject);
}
public Pair, List> decodeMethodOutputAndGetObject(
String abi, String methodName, String output) throws ContractCodecException {
ABIObject abiObject = decodeMethodAndGetOutputAbiObject(abi, methodName, output);
return ContractCodecTools.decodeJavaObjectAndGetOutputObject(abiObject);
}
public ABIObject decodeMethodAndGetOutAbiObjectByABIDefinition(
ABIDefinition abiDefinition, String output) throws ContractCodecException {
ABIObject outputABIObject = ABIObjectFactory.createOutputObject(abiDefinition);
try {
return ContractCodecTools.decode(outputABIObject, Hex.decode(output), isWasm);
} catch (Exception e) {
logger.error(" exception in decodeMethodAndGetAbiObjectByABIDefinition : ", e);
}
String errorMsg =
" cannot decode in decodeMethodAndGetAbiObjectByABIDefinition with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public ABIObject decodeMethodAndGetOutputAbiObject(String abi, String methodName, String output)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
List methods = contractABIDefinition.getFunctions().get(methodName);
for (ABIDefinition abiDefinition : methods) {
ABIObject outputABIObject = ABIObjectFactory.createOutputObject(abiDefinition);
try {
return ContractCodecTools.decode(outputABIObject, Hex.decode(output), isWasm);
} catch (Exception e) {
logger.error(
"exception in decodeMethodAndGetOutputAbiObject: {}, e:",
e.getMessage(),
e);
}
}
String errorMsg =
String.format(
"cannot decode in decodeMethodAndGetOutputAbiObject with appropriate interface ABI: methodName = %s",
methodName);
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
@Deprecated
public List decodeMethodAndGetOutputObject(String abi, String methodName, String output)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
List methods = contractABIDefinition.getFunctions().get(methodName);
for (ABIDefinition abiDefinition : methods) {
List outputs = abiDefinition.getOutputs();
List> outputTypes = new ArrayList<>();
try {
for (ABIDefinition.NamedType namedType : outputs) {
outputTypes.add(TypeReference.makeTypeReference(namedType.getType(), false));
}
return this.functionReturnDecoder.decode(output, outputTypes);
} catch (Exception e) {
logger.error("exception in decodeMethodToObject: {}, e:", e.getMessage(), e);
}
}
String errorMsg =
String.format(
"cannot decode in decodeMethodToObject with appropriate interface ABI: methodName = %s",
methodName);
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
@Deprecated
public List decodeMethodByABIDefinition(ABIDefinition abiDefinition, String output)
throws ContractCodecException {
List outputs = abiDefinition.getOutputs();
List> outputTypes = new ArrayList<>();
try {
for (ABIDefinition.NamedType namedType : outputs) {
outputTypes.add(TypeReference.makeTypeReference(namedType.getType(), false));
}
return this.functionReturnDecoder.decode(output, outputTypes);
} catch (Exception e) {
logger.error("exception in decodeMethodToObject: {}, e:", e.getMessage(), e);
}
String errorMsg =
String.format(
"cannot decode in decodeMethodToObject with appropriate interface ABI: methodName = %s",
abiDefinition.getMethodSignatureAsString());
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public List decodeMethod(ABIDefinition abiDefinition, String output)
throws ContractCodecException {
return this.decodeMethodAndGetOutputObject(abiDefinition, output).getLeft();
}
@Deprecated
public List decodeMethod(String abi, String methodName, String output)
throws ContractCodecException {
return this.decodeMethodAndGetOutputObject(abi, methodName, output);
}
public List decodeMethodById(String abi, byte[] methodId, byte[] output)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
ABIDefinition abiDefinition = contractABIDefinition.getABIDefinitionByMethodId(methodId);
if (abiDefinition == null) {
String errorMsg = " methodId " + Hex.toHexString(methodId) + " is invalid";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
ABIObject outputABIObject = ABIObjectFactory.createOutputObject(abiDefinition);
try {
return ContractCodecTools.decodeJavaObject(
outputABIObject, Hex.toHexString(output), isWasm);
} catch (Exception e) {
logger.error(" exception in decodeMethodByIdToObject : {}", e.getMessage());
}
String errorMsg = " cannot decode in decodeMethodToObject with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public List decodeMethodByInterface(String abi, String methodInterface, byte[] output)
throws ContractCodecException {
byte[] methodId = functionEncoder.buildMethodId(methodInterface);
return this.decodeMethodById(abi, methodId, output);
}
public List decodeMethodToString(String abi, String methodName, byte[] output)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
List methods = contractABIDefinition.getFunctions().get(methodName);
if (methods == null) {
throw new ContractCodecException(
"Invalid method "
+ methodName
+ ", supported methods are: "
+ contractABIDefinition.getFunctions().keySet());
}
for (ABIDefinition abiDefinition : methods) {
ABIObject outputABIObject = ABIObjectFactory.createOutputObject(abiDefinition);
try {
return contractCodecJsonWrapper.decode(outputABIObject, output, isWasm);
} catch (Exception e) {
logger.error(" exception in decodeMethodToString : {}", e.getMessage());
}
}
String errorMsg = " cannot decode in decodeMethodToString with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public List decodeMethodByIdToString(String abi, byte[] methodId, byte[] output)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
ABIDefinition abiDefinition = contractABIDefinition.getABIDefinitionByMethodId(methodId);
if (abiDefinition == null) {
String errorMsg = " methodId " + Hex.toHexString(methodId) + " is invalid";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
ABIObject outputABIObject = ABIObjectFactory.createOutputObject(abiDefinition);
try {
return contractCodecJsonWrapper.decode(outputABIObject, output, isWasm);
} catch (UnsupportedOperationException | ClassNotFoundException e) {
logger.error(" exception in decodeMethodByIdToString : {}", e.getMessage());
}
String errorMsg =
" cannot decode in decodeMethodByIdToString with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public List decodeMethodByInterfaceToString(
String abi, String methodInterface, byte[] output) throws ContractCodecException {
byte[] methodId = functionEncoder.buildMethodId(methodInterface);
return this.decodeMethodByIdToString(abi, methodId, output);
}
// ------------------------------- decode output end --------------------------------------
// -------------------------------------------------------------------------------------------
public List decodeEvent(String abi, String eventName, EventLog log)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
List events = contractABIDefinition.getEvents().get(eventName);
if (events == null) {
throw new ContractCodecException(
"Invalid event "
+ eventName
+ ", supported events are: "
+ contractABIDefinition.getEvents().keySet());
}
for (ABIDefinition abiDefinition : events) {
ABIObject inputObject = ABIObjectFactory.createEventInputObject(abiDefinition);
try {
List params = new ArrayList<>();
if (!log.getData().equals("0x")) {
params =
ContractCodecTools.decodeJavaObject(inputObject, log.getData(), isWasm);
}
List topics = decodeIndexedEvent(log, abiDefinition);
return this.mergeEventParamsAndTopics(abiDefinition, params, topics);
} catch (Exception e) {
logger.error(" exception in decodeEventToObject : {}", e.getMessage());
}
}
String errorMsg = " cannot decode in decodeEventToObject with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public List decodeIndexedEvent(EventLog log, ABIDefinition abiDefinition)
throws ClassNotFoundException {
List eventIndexedObject =
ABIObjectFactory.createEventIndexedObject(abiDefinition);
List topics = new ArrayList<>();
if (!log.getTopics().isEmpty()) {
topics.add(log.getTopics().get(0));
for (int i = 1; i < log.getTopics().size(); i++) {
ABIObject indexedObject = eventIndexedObject.get(i - 1);
if (indexedObject.isDynamic()) {
topics.add(log.getTopics().get(i));
} else {
List objects =
contractCodecJsonWrapper.decode(
indexedObject, Hex.decode(log.getTopics().get(i)), isWasm);
if (!objects.isEmpty()) {
topics.add(objects.get(0));
}
}
}
}
return topics;
}
public List decodeEventByTopic(String abi, String eventTopic, EventLog log)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
ABIDefinition abiDefinition =
contractABIDefinition.getABIDefinitionByEventTopic(eventTopic);
ABIObject inputObject = ABIObjectFactory.createEventInputObject(abiDefinition);
try {
List params = new ArrayList<>();
if (!log.getData().equals("0x")) {
params = ContractCodecTools.decodeJavaObject(inputObject, log.getData(), isWasm);
}
List topics = decodeIndexedEvent(log, abiDefinition);
return this.mergeEventParamsAndTopics(abiDefinition, params, topics);
} catch (Exception e) {
logger.error(" exception in decodeEventByTopicToObject : {}", e.getMessage());
}
String errorMsg =
" cannot decode in decodeEventByTopicToObject with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public List decodeEventByInterface(String abi, String eventSignature, EventLog log)
throws ContractCodecException {
byte[] methodId = functionEncoder.buildMethodId(eventSignature);
return this.decodeEventByTopic(abi, Numeric.toHexString(methodId), log);
}
public List decodeEventToString(String abi, String eventName, EventLog log)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
List events = contractABIDefinition.getEvents().get(eventName);
if (events == null) {
throw new ContractCodecException(
"Invalid event "
+ eventName
+ ", current supported events are: "
+ contractABIDefinition.getEvents().keySet());
}
for (ABIDefinition abiDefinition : events) {
ABIObject inputObject = ABIObjectFactory.createEventInputObject(abiDefinition);
try {
List params = new ArrayList<>();
if (!log.getData().equals("0x")) {
params =
contractCodecJsonWrapper.decode(
inputObject, Hex.decode(log.getData()), isWasm);
}
List topics = decodeIndexedEvent(log, abiDefinition);
return this.mergeEventParamsAndTopicsToString(abiDefinition, params, topics);
} catch (Exception e) {
logger.error(" exception in decodeEventToString : {}", e.getMessage());
}
}
String errorMsg = " cannot decode in decodeEventToString with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public List decodeEventByTopicToString(String abi, String eventTopic, EventLog log)
throws ContractCodecException {
ContractABIDefinition contractABIDefinition = this.abiDefinitionFactory.loadABI(abi);
ABIDefinition abiDefinition =
contractABIDefinition.getABIDefinitionByEventTopic(eventTopic);
ABIObject inputObject = ABIObjectFactory.createEventInputObject(abiDefinition);
try {
List params = new ArrayList<>();
if (!log.getData().equals("0x")) {
params =
contractCodecJsonWrapper.decode(
inputObject, Hex.decode(log.getData()), isWasm);
}
List topics = decodeIndexedEvent(log, abiDefinition);
return this.mergeEventParamsAndTopicsToString(abiDefinition, params, topics);
} catch (Exception e) {
logger.error(" exception in decodeEventByTopicToString : {}", e.getMessage());
}
String errorMsg =
" cannot decode in decodeEventByTopicToString with appropriate interface ABI";
logger.error(errorMsg);
throw new ContractCodecException(errorMsg);
}
public List decodeEventByInterfaceToString(
String abi, String eventSignature, EventLog log) throws ContractCodecException {
byte[] methodId = functionEncoder.buildMethodId(eventSignature);
return this.decodeEventByTopicToString(abi, Numeric.toHexString(methodId), log);
}
private List mergeEventParamsAndTopics(
ABIDefinition abiDefinition, List params, List topics) {
List ret = new ArrayList<>();
int paramIdx = 0;
int topicIdx = 1;
for (ABIDefinition.NamedType namedType : abiDefinition.getInputs()) {
if (namedType.isIndexed()) {
ret.add(topics.get(topicIdx));
topicIdx++;
} else {
ret.add(params.get(paramIdx));
paramIdx++;
}
}
return ret;
}
private List mergeEventParamsAndTopicsToString(
ABIDefinition abiDefinition, List params, List topics) {
List ret = new ArrayList<>();
int paramIdx = 0;
int topicIdx = 1;
for (ABIDefinition.NamedType namedType : abiDefinition.getInputs()) {
if (namedType.isIndexed()) {
ret.add(topics.get(topicIdx));
topicIdx++;
} else {
ret.add(params.get(paramIdx));
paramIdx++;
}
}
return ret;
}
}