org.fisco.bcos.sdk.abi.FunctionEncoder Maven / Gradle / Ivy
The newest version!
package org.fisco.bcos.sdk.abi;
import java.math.BigInteger;
import java.util.List;
import java.util.stream.Collectors;
import org.fisco.bcos.sdk.abi.datatypes.Function;
import org.fisco.bcos.sdk.abi.datatypes.Type;
import org.fisco.bcos.sdk.abi.datatypes.Uint;
import org.fisco.bcos.sdk.crypto.CryptoSuite;
import org.fisco.bcos.sdk.utils.Numeric;
/**
* Ethereum Contract Application Binary Interface (ABI) encoding for functions. Further details are
* available here.
*/
public class FunctionEncoder {
private CryptoSuite cryptoSuite;
public FunctionEncoder(CryptoSuite cryptoSuite) {
this.cryptoSuite = cryptoSuite;
}
public String encode(Function function) {
List parameters = function.getInputParameters();
String methodSignature = buildMethodSignature(function.getName(), parameters);
String methodId = buildMethodId(methodSignature);
StringBuilder result = new StringBuilder();
result.append(methodId);
return encodeParameters(parameters, result);
}
public static String encodeConstructor(List parameters) {
return encodeParameters(parameters, new StringBuilder());
}
public static String encodeParameters(List parameters, StringBuilder result) {
int dynamicDataOffset = Utils.getLength(parameters) * Type.MAX_BYTE_LENGTH;
StringBuilder dynamicData = new StringBuilder();
for (Type parameter : parameters) {
String encodedValue = TypeEncoder.encode(parameter);
if (parameter.dynamicType()) {
String encodedDataOffset =
TypeEncoder.encodeNumeric(new Uint(BigInteger.valueOf(dynamicDataOffset)));
result.append(encodedDataOffset);
dynamicData.append(encodedValue);
dynamicDataOffset += (encodedValue.length() >> 1);
} else {
result.append(encodedValue);
}
}
result.append(dynamicData);
return result.toString();
}
public static String buildMethodSignature(String methodName, List parameters) {
StringBuilder result = new StringBuilder();
result.append(methodName);
result.append("(");
String params =
parameters.stream().map(Type::getTypeAsString).collect(Collectors.joining(","));
result.append(params);
result.append(")");
return result.toString();
}
public String buildMethodId(String methodSignature) {
byte[] input = methodSignature.getBytes();
byte[] hash = cryptoSuite.hash(input);
return Numeric.toHexString(hash).substring(0, 10);
}
/** @return the cryptoSuite */
public CryptoSuite getCryptoSuite() {
return cryptoSuite;
}
/** @param cryptoSuite the cryptoSuite to set */
public void setCryptoSuite(CryptoSuite cryptoSuite) {
this.cryptoSuite = cryptoSuite;
}
}