public String solFunction(String str) {
byte[] byteValue = DatatypeConverter.parseHexBinary(str);
Bytes32 strInBytes = new Bytes32(byteValue);
try {
Uint256 value = contract.showPoint(strInBytes).get();
return value.getValue().toString();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return null;
}
// web3j generated java code for solidity program
public Future<Uint256> showPoint(Bytes32 byteValue) {
Function function = new Function("showPoint",
Arrays.<Type>asList(rewardType),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
return executeCallSingleValueReturnAsync(function);
}
Estoy tratando de enviar el argumento de tipo Bytes32 a la función SmartContract usando web3j. Siempre lanza una excepción
Input byte array must be in range 0 < M <= 32 and length must match type
Ya he comprobado el convertidor de tipos de datos numéricos de web3j y estas soluciones. problema informado en git web3j
Este es mi programa de solidez.
contract MyContract {
address public owner; // Store owner address
mapping (address => mapping (bytes32 => uint)) value;
function MyContract (uint initValue, bytes32 chkByte) {
owner = msg.sender;
reward[msg.sender][chkByte] = initValue;
}
function showAvailReward(bytes32 chkByte) constant returns(uint) {
return value[msg.sender][chkByte];
}
}
SOLUCIONADO!!! MÉTODO LARGO/Detallado!!! ( Versión más corta en la parte inferior )
El problema principal era que Bytes32(byte[])
solo admite 32 de longitud byte[]
. También tenga en cuenta Numeric.hexStringToByteArray(strValueInHex)
que convierte cualquier HexString a byte[]
.
Este es el proceso:
String => Hex => 32 length Hex (ie. 64 length HexString) => byte[] => Bytes32
Nota: "00"
= 1 longitud hexadecimal y 2 longitudes de cadena
Así es como logré String to Bytes:
Cadena a 64 HexString de longitud:
// String to 64 length HexString (equivalent to 32 Hex lenght)
public static String asciiToHex(String asciiValue)
{
char[] chars = asciiValue.toCharArray();
StringBuffer hex = new StringBuffer();
for (int i = 0; i < chars.length; i++)
{
hex.append(Integer.toHexString((int) chars[i]));
}
return hex.toString() + "".join("", Collections.nCopies(32 - (hex.length()/2), "00"));
}
HexString de 64 longitudes a 32 bytes de longitud[]:
byte[] myStringInByte = Numeric.hexStringToByteArray(asciiToHex("myString"));
32 bytes de longitud [] a Bytes32:
Bytes32 myStringInBytes32 = new Bytes32(myStringInByte);
Ahora myStringInBytes32 es aceptado por la función de contrato de web3j. En mi caso corregido solFunction(String str)
es:
public String solFunction(String str) {
String strInHex = asciiToHex(str);
Bytes32 strInBytes32 = new Bytes32(Numeric.hexStringToByteArray(strInHex));
try {
Uint256 value = contract.showPoint(strInBytes32).get();
return value.getValue().toString();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return null;
}
Si su función de solidez devuelve datos en Bytes32, aquí se explica cómo obtener valor de los datos de Bytes32 devueltos.
String dataInString = hexToASCII(Numeric.toHexStringNoPrefix(dataInBytes32);
FunciónhexToASCII
public static String hexToASCII(String hexValue)
{
StringBuilder output = new StringBuilder("");
for (int i = 0; i < hexValue.length(); i += 2)
{
String str = hexValue.substring(i, i + 2);
output.append((char) Integer.parseInt(str, 16));
}
return output.toString();
}
Ayuda de cadena a hexadecimal y hexadecimal a cadena desde aquí
Método CORTO/SIMPLIFICADO:
Cadena a Bytes32:
public static Bytes32 stringToBytes32(String string) {
byte[] byteValue = string.getBytes();
byte[] byteValueLen32 = new byte[32];
System.arraycopy(byteValue, 0, byteValueLen32, 0, byteValue.length);
return new Bytes32(byteValueLen32);
}
Bytes32 a cadena:
StringUtils.newStringUsAscii(varTypeBytes32.getValue());