web3j中字符串如何转换Bytes32?

web3j中字符串如何转换Bytes32?我想用web3j发送bytes32类型的参数到SmartContract函数,它总是抛出异常。
先来看一段代码:

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

我已经检查了web3j的Numeric datatype转换,并给出了解决方案。

Input byte array must be in range 0 < M <= 32 and length must match type

我的以太坊智能合约代码:

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

问题的解决

主要问题是Bytes32(byte[])只支持32位长度的byte[]。同样记住Numeric.hexStringToByteArray(strValueInHex)将任何HexString转换为byte[]

处理过程:

String => Hex => 32 length Hex (ie. 64 length HexString) => byte[] => Bytes32

注意:00 等于1个Hex长度或者2个String长度。

字符串到64位长的HexString:

// 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"));
}

64位长的HexString到32位长的byte[]:

byte[] myStringInByte = Numeric.hexStringToByteArray(asciiToHex("myString"));

32位长的byte[]Bytes32:

Bytes32 myStringInBytes32 = new Bytes32(myStringInByte);

现在myStringInBytes32被接受为web3j的以太坊智能合约功能。在我的案例中solFunction(String str)修改代码如下:

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

如果你的solidity函数在Bytes32中返回数据,那么下面是如何从返回的Bytes32数据中获取值:

String dataInString = hexToASCII(Numeric.toHexStringNoPrefix(dataInBytes32);

函数hexToASCII

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

Convert Hex to ASCII and ASCII to Hex
June 5, 2014 by Lokesh Gupta

更简单的方法

string 到32位长的byte32:

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

32位长的byte32到string:

StringUtils.newStringUsAscii(varTypeBytes32.getValue());

原文《以太坊常见问题和错误》中的:
http://cw.hubwiz.com/card/c/ethereum-FAQ/1/1/11/

另外推荐几个很受欢迎全网稀缺的互动教程:

  • web3j,主要是针对java和android程序员围绕web3j库进行区块链以太坊开发的讲解。
  • python以太坊,主要是针对python围绕web3.py进行区块链以太坊应用开发的讲解。
  • php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和事件等内容。
  • 以太坊开发,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
  • 以太坊教程,主要介绍智能合约与dapp应用开发,适合入门。

版权声明:本文为mongo_node原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。