web3j中字符串如何转换Bytes32?

简介: web3j中字符串如何转换Bytes32?我想用web3j发送bytes32类型的参数到SmartContract函数,它总是抛出异常。

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应用开发,适合入门。
相关文章
|
Java 应用服务中间件
org.apache.tomcat.util.descriptor.web.WebXml.setVersion 未知版本字符串 [4.0]。将使用默认版本。
org.apache.tomcat.util.descriptor.web.WebXml.setVersion 未知版本字符串 [4.0]。将使用默认版本。
420 0
|
算法 PHP C语言
【web开发基础】PHP快速入门(5)-PHP运算符之算术运算符和字符串运算符详解
运算符用于执行程序代码运算,会针对一个以上操作数项目来进行运算。例如:2+3,其操作数是2和3,而运算符则是"+"。如在vb2005中运算符大致可以分为5种类型:算术运算符、连接运算符、关系运算符、赋值运算符和逻辑运算符;PHP也同样包含这些运算符。 运算符和变量是所有计算机编程语言中的不可或缺的一部分,是一个命令解释器对一个或多个操作数(变量或数值)执行某种运算的符号,也称为操作符
226 1
|
前端开发 JavaScript
web前端面试宝典-JavaScript生成随机字符串
web前端面试宝典-JavaScript生成随机字符串
148 0
|
JavaScript
web:翻转字符串中的单词
第一种方法:直接暴力分割,再单个求翻转后的单词,最后再添加到一个最新的字符串中。 /** @param N Number @return Boolean
104 0
web作业:字符串生成
/** @param S String @return String
84 0
web作业:字符串逆序输出
**有需要自取,必须标明出处 @param w String @return String
78 0
|
前端开发 JavaScript
web前端面试宝典-JavaScript生成随机字符串
思路: 先随机生成一个0-1之间的小数。再将该小数转换为字符串,并以36进制的形式展示,截取小数点后的部分即可。 三十六进制:由数字0-9,字母A-Z组成,字母不区分大小写。与10进制的对应关系是:0-9对应0-9;A-F对应10-35。
|
存储 JavaScript 前端开发
web前端学习(三十五)——JavaScript事件、字符串及运算符的相关设置
web前端学习(三十五)——JavaScript事件、字符串及运算符的相关设置
web前端学习(三十五)——JavaScript事件、字符串及运算符的相关设置