0

I am trying to create mapping of type mapping(string => string) where you store some text by keyed by its the string representation of its hash, but I've been stymied by the inability to take the calculated hash value and convert it to its string representation.

I tried the below, but it doesn't work. The hashing function appears to work, but the conversion to string doesn't. (Running function hash() returns an error which I don't really understand.

pragma solidity 0.8.4;
contract HashTextMap {
    
    mapping(string=>string) textMap;
    
    
    function set(string memory text) public  {
        bytes32 val;
        val = sha256(abi.encodePacked(text));
        string memory key = string(abi.encodePacked(val));
        textMap[key] = text; 
        
    }
    function get(string memory key) public view returns(string memory) {
        return textMap[key];
    }
    
    function hash(string memory text) public pure returns(string memory) {
        bytes32 val;
        val = sha256(abi.encodePacked(text));
        string memory key = string(abi.encodePacked(val));
        return key;
        
    }
}

Running this in the remix ide, the contract compiles and sets returns normally, but attempting I can't text get because I can't get the hash using hash() which produces this error.

{ "error": "Failed to decode output: null: invalid codepoint at offset 0; unexpected continuation byte (argument=\"bytes\", value={\"0\":153,\"1\":168,\"2\":124,\"3\":145,\"4\":53,\"5\":23,\"6\":70,\"7\":37,\"8\":43,\"9\":238,\"10\":126,\"11\":38,\"12\":250,\"13\":191,\"14\":48,\"15\":2,\"16\":61,\"17\":234,\"18\":227,\"19\":36,\"20\":138,\"21\":6,\"22\":125,\"23\":166,\"24\":226,\"25\":63,\"26\":146,\"27\":129,\"28\":199,\"29\":135,\"30\":194,\"31\":139}, code=INVALID_ARGUMENT, version=strings/5.4.0)" } 
2
  • I've looked up most available answers for converting a bytes32 type into string, and all seem to fail with the latest version of Solidity. I'm sure there is a solution that would work, but I don't possibly see any reason why you would make that conversion in the first place. You could simply key the mapping by the bytes32 representation of the hash. It would be easier to convert a string input into bytes32 type on the user side via Web3JS as in: ethereum.stackexchange.com/questions/23058/…. Commented Aug 10, 2021 at 18:51
  • It may not be necessary to make the conversion internally (could be built with mapping of (bytes32=>string), but I think byte32 is quite a pain for app devs who may want to use my contracts. I was able to achieve something close to what I think will be easier on the user side, with the answer below, although I am not really sure if the conversion of byte32 to unit is totally legit. But it seems to work.
    – GGizmos
    Commented Aug 10, 2021 at 20:19

1 Answer 1

0

In case of interest, I was able to build something like this by converting the hash to a uint and then converting a uint to string. (I'm a little mystified why its so hard to convert a byte32 directly into a string, but there you go.)

contract HashTextMap {
    
    mapping(string=>string) textMap;
    
    
    function set(string memory text) public   {
        bytes32 val;
        val = sha256(abi.encodePacked(text));
        uint256 i = uint(val);
        string memory key = uint2str(i);
        textMap[key] = text;            
    }

    function get(string memory key) public view returns(string memory) {
        return textMap[key];
    }
    
    function hash(string memory text) public pure returns(string memory) {
        bytes32 val;
        val = sha256(abi.encodePacked(text));
        uint ival = uint(val);
        string memory key = uint2str(ival);
        return key;            
    }
    
    function uint2str( uint256 i ) internal pure returns (string memory str) {
        if (i == 0) { return "0";}
        uint256 j = i;
        uint256 length;
        while (j != 0) {
            length++;
            j /= 10;
        }
        bytes memory bstr = new bytes(length);
        uint256 k = length;
        j = i;
        while (j != 0) {
            bstr[--k] = bytes1(uint8(48 + j % 10));
            j /= 10;
        }
        str = string(bstr);
        return str;
    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.