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/
另外推荐几个很受欢迎全网稀缺的互动教程: