Преобразование структуры в байты в Solidity

Есть ли удобный способ конвертировать (например, приводить) structтип в bytes?

Я пытаюсь вызвать метод, подобный приведенному ниже (взято отсюда ), где вы можете передать некоторую (произвольную) контекстную информацию, которая будет возвращена вам позже в методе «обратного вызова».

function approveAndCall(address _spender, uint256 _value, bytes _extraData)
    returns (bool success) {    
    tokenRecipient spender = tokenRecipient(_spender);
    if (approve(_spender, _value)) {
        spender.receiveApproval(msg.sender, _value, this, _extraData);
        return true;
    }
}

Предположим, я хочу вызвать этот метод, передав Userструктуру в качестве _extraDataаргумента, что было бы правильным использованием?

Заранее спасибо,

Solidity не имеет формата сериализации для структур. Вам нужно вынимать параметры один за другим и объединять их в массив байтов один за другим. (Хотя я не знаю подробностей, как добавить массив байтов). Вот еще некоторые подробности ethereum.stackexchange.com/questions/11016/…

Ответы (2)

Вы можете сделать что-то вроде этого. Обратите внимание: для каждой пользовательской структуры вам придется писать собственные методы сериализации и десериализации.

pragma solidity ^0.4.0;

contract StructSerialization
{
    function StructSerialization()
    {
    }

    event exactUserStructEvent(uint32 id, string name);

    //Use only fixed size simple (uint,int) types!
    struct ExactUserStruct
    {
        uint32 id;
        string name;
    }

    function showStruct(ExactUserStruct u) private
    {
        exactUserStructEvent(u.id, u.name);
    }


    function exactUserStructToBytes(ExactUserStruct u) private
    returns (bytes data)
    {
        // _size = "sizeof" u.id + "sizeof" u.name
        uint _size = 4 + bytes(u.name).length;
        bytes memory _data = new bytes(_size);

        uint counter=0;
        for (uint i=0;i<4;i++)
        {
            _data[counter]=byte(u.id>>(8*i)&uint32(255));
            counter++;
        }

        for (i=0;i<bytes(u.name).length;i++)
        {
            _data[counter]=bytes(u.name)[i];
            counter++;
        }

        return (_data);
    }


    function exactUserStructFromBytes(bytes data) private
    returns (ExactUserStruct u)
    {
        for (uint i=0;i<4;i++)
        {
            uint32 temp = uint32(data[i]);
            temp<<=8*i;
            u.id^=temp;
        }

        bytes memory str = new bytes(data.length-4);

        for (i=0;i<data.length-4;i++)
        {
            str[i]=data[i+4];
        }

        u.name=string(str);
     }

    function test()
    {
        //Create and  show struct
        ExactUserStruct memory struct_1=ExactUserStruct(1234567,"abcdef");
        showStruct(struct_1);

        //Serializing struct
        bytes memory serialized_struct_1 = exactUserStructToBytes(struct_1);

        //Deserializing struct
        ExactUserStruct memory struct_2 = exactUserStructFromBytes(serialized_struct_1);

        //Show deserealized struct
        showStruct(struct_2);
    }
}

Вы можете использовать библиотеку Seriality .

1- С помощью Seriality вы можете легко сериализовать и десериализовать свои переменные, структуры, массивы, кортежи... и передавать их через контракты и библиотеки.

2- Вы можете отделить свой контракт от библиотек, сериализовав параметры в массив байтов.

3- Его также можно использовать в качестве альтернативы протоколу RLP в Solidity.

Вот пример:

pragma solidity ^0.4.16;

import "./Seriality.sol";

contract SerialitySample is Seriality {

   function testSample1() public returns(int n1, int8 n2, uint24 n3,  string n4,string n5) {

    bytes memory buffer = new  bytes(200);
    string memory out4  = new string(32);        
    string memory out5  = new string(32);
    n4 = new string(32);
    n5 = new string(32);
    int     out1 = 34444445;
    int8    out2 = 87;
    uint24  out3 = 76545;
    out4 = "Copy kon lashi";
    out5 = "Bia inja dahan service";

    // Serializing
    uint offset = 200;

    intToBytes(offset, out2, buffer);
    offset -= sizeOfInt(8);

    uintToBytes(offset, out3, buffer);
    offset -= sizeOfUint(24);

    stringToBytes(offset, bytes(out5), buffer);
    offset -= sizeOfString(out5);

    stringToBytes(offset, bytes(out4), buffer);
    offset -= sizeOfString(out4);       

    intToBytes(offset, out1, buffer);
    offset -= sizeOfInt(256);

    // Deserializing
    offset = 200; 

    n2 = bytesToInt8(offset, buffer);
    offset -= sizeOfInt(8);

    n3 = bytesToUint24(offset, buffer);
    offset -= sizeOfUint(24);

    bytesToString(offset, buffer, bytes(n5));
    offset -= sizeOfString(out5);

    bytesToString(offset, buffer, bytes(n4));
    offset -= sizeOfString(out4);

    n1 = bytesToInt256(offset, buffer);
}

}

выходной буфер:

00000000000000000000000000000000000000000000000000000000020d949d 436f7079206b6f6e206c61736869000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000e 42696120696e6a6120646168616e207365727669636500000000000000000000 0000000000000000000000000000000000000000000000000000000000000016 012b0157

"1": int256: n1 34444445

"2": int8: n2 87

"3": uint24: n3 76545

"4": строка: n4 Копировать кон лаши

"5": строка: n5 Служба Bia inja dahan