Vergleichen Sie Strukturen und Arrays mit keccak256, um Gas zu sparen

Ich habe gerade letzten Tag an einem Solidity-Code gearbeitet und herausgefunden, dass abgesehen vom Vergleichen von Bytes, Strings usw.

Das Keccak256ist die perfekte Lösung für den Vergleich großer Arrays oder großer Strukturen. Denn wie die Eigenschaften der Hash-Funktionen sagen:

Gegeben x und y mit der Annahme (x != y) => Wir können annehmen, dass H(x) != H(y)

Das Vergleichen der Hashes wird uns also dazu bringen, viel weniger Gas auszugeben, als das Array zu iterieren, und uns zeigen, dass sie gleich oder nicht gleich sind (egal auf welchem ​​​​Index).

Also mit einem Beispiel:

Nehmen wir an, wir haben 2 große Arrays des gleichen Typs. Wird es möglich sein, etwas zu tun als:

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

Das macht man zB um Strings zu vergleichen . (Die, wenn ich mich nicht irre, werden am Ende als Arrays interpretiert).

Um sowas nicht zu machen:

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

Offensichtlich können andere Implementierungen wie das Hinzufügen von Zuordnungen oder ähnliches das Problem recht gut lösen, aber ich bin daran interessiert zu wissen, ob es einen Trick gibt, mit dem Sie diese Art von Strukturen mit derkeccak256() .

Vielen Dank.

Ich denke, das sollte als Frage formuliert werden.

Antworten (1)

Ja da ist!

Da keccak256Solidität einen bytes32Wert ergibt, können Sie die Ergebnisse einfach mit vergleichen ==.

Ein Beispiel:

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)));
    }
}
Eine sehr schöne Erklärung, indem die 2 Anweisungen auf demselben Code demonstriert werden. Vielen Dank und gute Arbeit!
Es ist nicht wahr, dass das Hashing eines Wertes 30 Gas kostet. Es sind 30 Gase + 6*Array-Länge