Есть ли способ вернуть несколько структур (или полей из них) в Solidity, когда одно из полей структуры имеет тип «байты»?

Я хотел бы вернуть ключи структур из моего контракта для отображения во внешнем интерфейсе, в идеале по 10 за раз. Я понимаю, что если я сделаю keyByOwnerобщедоступным, я могу вернуть один ключ за раз с помощью созданного геттера, но мне нужно 10 ключей, и я не хочу вызывать функцию геттера 10 раз.

Я попытался использовать описанный здесь подход для возврата кортежа массивов: https://medium.com/coinmonks/solidity-tutorial-returning-structs-from-public-functions-e78e48efb378 продолжайте, за исключением того, что он, похоже, не работает с dataполем ключа типа bytes(он отлично работает, если я меняю type byesна type bytes32), что дает мне эту ошибку:

TypeError: This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature.
    returns (uint[], bytes[])
                     ^-----^

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

Вот моя функция:

struct Key {
  uint expirationTimestamp;
  bytes data;
 }

 mapping (address => Key) internal keyByOwner;

 address[] public owners;

  function getKeysByPage(uint _startIndex)
    external
    view
    returns (uint[], bytes[])
  {
    require(outstandingKeys() > 0, "No keys to retrieve");
    require(_startIndex >= 0 && _startIndex < outstandingKeys(), "Index must be in-bounds");
    uint endOfPageIndex;

    if (_startIndex + 9 > owners.length) {
      endOfPageIndex = owners.length - 1;
    } else {
      endOfPageIndex = _startIndex + 9;
    }

    address[] memory ownersByPage = new address[](10);
    uint[] memory timestampsArray = new uint[](10);
    bytes[] memory keyDataArray = new bytes[](10);
    Key memory tempKey;
    uint pageIndex = 0;

    // Build the specified set of owners into a new temporary array
    for (uint256 i = _startIndex; i <= endOfPageIndex; i++) {
      ownersByPage[pageIndex] = owners[i];
      pageIndex++;
    }

    // Loop through ownersByPage & build the requested keys into 2 new temporary arrays
    for (uint256 n = 0; n < ownersByPage.length; n++) {
      tempKey = keyByOwner[ownersByPage[n]];
      timestampsArray[n] = tempKey.expirationTimestamp;
      keyDataArray[n] = tempKey.data;
    }

    return(timestampsArray, keyDataArray);
  }

Ответы (1)

Возврат структур и кортежей структур невозможен с текущим ABI. Если вы добавите pragma experimental ABIEncoderV2сразу после своей pragma solidityстроки, она будет скомпилирована просто отлично. К сожалению, не рекомендуется переходить в производство с экспериментальной функцией, поэтому единственная жизнеспособная альтернатива сейчас — возвращать примитивные типы каждой структуры в строке.

Конкретно для вашего сценария вам нужно временно использовать совместимый тип. Например, вы можете преобразовать свой динамический массив байтов в bytes32.

Спасибо, Пол. Я знал, что он работает с pragma experimental ABIEncoderV2заголовком, но, как вы сказали, недостаточно хорош для производства. Я могу возвращать кортежи массивов, но, похоже, это не работает, если один из массивов в кортеже имеет тип bytesили тип string, вероятно, потому, что они оба являются динамическими массивами. Можете ли вы уточнить, что «единственная жизнеспособная альтернатива сейчас — это возвращать примитивные типы каждой структуры в строке»?
О, извините, я вообще имел в виду структуры. Я обновил ответ.
Так что да, к сожалению, это единственное, что вы можете сделать на данный момент.
Не беспокойтесь, это был мой первоначальный вопрос. В моем примере я взял поля из 10 структур и перекомпоновал их в 2 новых массива, по одному для каждого поля. Я надеялся, что, возможно, Solidity 0.5 решит эту проблему, но сейчас я посмотрю ссылку, которую вы опубликовали, о преобразовании динамических массивов байтов в bytes32.