Ethereumj

在 web3j 中將字元串轉換為 Bytes32?

  • August 3, 2017
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 將 Bytes32 類型的參數發送到 SmartContract 函式。它總是拋出異常

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

我已經檢查了 web3j 的數值數據類型轉換器和這個解決方案。 git web3j 中報告的問題

這是我的穩固計劃

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 十六進制長度 & 2 字元串長度

這是我如何實現字元串到字節:

字元串到 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[] myStringInByte = Numeric.hexStringToByteArray(asciiToHex("myString"));

32個長度字節

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

字元串到十六進制和十六進製到字元串的幫助從這裡


簡短/簡化方法:

字元串到 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 轉字元串:

StringUtils.newStringUsAscii(varTypeBytes32.getValue());

引用自:https://ethereum.stackexchange.com/questions/23549