¿Convertir String a Bytes32 en web3j?

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];
        }
}

Respuestas (1)

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());