Сравните структуры и массивы с keccak256, чтобы сэкономить газ

Просто работая над кодом надежности в последний день, я понял, что помимо сравнения байтов, строк и т. д.

Будет Keccak256идеальным решением для сравнения больших массивов или больших структур. Потому что, как говорят свойства хеш-функции:

Учитывая x и y с предположением (x != y) => Мы можем предположить, что H(x) != H(y)

Таким образом , сравнение его хэшей заставит нас потратить намного меньше газа, чем повторение массива, и продемонстрирует нам, что они равны или не равны (не имеет значения, по какому индексу).

Итак, на примере:

Предположим, что у нас есть 2 больших массива одного типа. Можно ли будет сделать что-то вроде:

Assert.equal(keccak256(array1)), keccak256(array2));

Это то, что вы делаете, например, для сравнения строк . (Это, если я не ошибаюсь, интерпретируются как массивы в конце).

Чтобы не делать что-то вроде:

Assert.equal(array1[i], array2[i]); 
//Implemented on a for loop from i=0 to i=minlength(arr1,arr2)

Очевидно, что другие реализации, такие как добавление сопоставлений или тому подобное, могут довольно хорошо решить проблему, но мне интересно узнать, есть ли какой-нибудь трюк, который позволяет вам сравнивать эти типы структур сkeccak256() .

Спасибо.

Я думаю, что это должно быть сформулировано как вопрос.

Ответы (1)

Да, есть!

Так как keccak256Solidity дает bytes32значение, вы можете просто сравнить результаты, используя ==.

Пример:

pragma solidity 0.4.24;

contract KeccakCompare {
    struct Example {
        uint256 age;
        bytes32 name;
    }

    Example[] public examples;

    function pushExample(uint256 _age, bytes32 _name) external {
        examples.push(Example({
            age: _age,
            name: _name
        }));
    }

    function equals(uint256 _firstIndex, uint256 _secondIndex) external view returns (bool) {
        return equals(examples[_firstIndex], examples[_secondIndex]);
    }

    function equals(Example storage _first, Example storage _second) internal view returns (bool) {
        // Just compare the output of hashing all fields packed
        return(keccak256(abi.encodePacked(_first.age, _first.name)) == keccak256(abi.encodePacked(_second.age, _second.name)));
    }
}
Очень хорошее объяснение, демонстрирующее 2 утверждения в одном и том же коде. Большое спасибо и хорошей работы!
Это неправда, что хеширование любого значения стоит 30 газа. Это 30 газов + 6 * длина массива.