Преглед на файлове

Refactor VAA parsing into public view method (#153)

* refactor VAA parsing into public view method
Hendrik Hofstadt преди 4 години
родител
ревизия
f4a7e705c9
променени са 1 файла, в които са добавени 37 реда и са изтрити 23 реда
  1. 37 23
      ethereum/contracts/Wormhole.sol

+ 37 - 23
ethereum/contracts/Wormhole.sol

@@ -49,6 +49,15 @@ contract Wormhole is ReentrancyGuard {
         uint32 nonce
     );
 
+    struct ParsedVAA {
+        uint8 version;
+        bytes32 hash;
+        uint32 guardian_set_index;
+        uint32 timestamp;
+        uint8 action;
+        bytes payload;
+    }
+
     // Mapping of guardian_set_index => guardian set
     mapping(uint32 => GuardianSet) public guardian_sets;
     // Current active guardian set
@@ -80,23 +89,41 @@ contract Wormhole is ReentrancyGuard {
     function submitVAA(
         bytes calldata vaa
     ) public nonReentrant {
-        uint8 version = vaa.toUint8(0);
-        require(version == 1, "VAA version incompatible");
+        ParsedVAA memory parsed_vaa = parseAndVerifyVAA(vaa);
+        // Process VAA
+        if (parsed_vaa.action == 0x01) {
+            require(parsed_vaa.guardian_set_index == guardian_set_index, "only the current guardian set can change the guardian set");
+            vaaUpdateGuardianSet(parsed_vaa.payload);
+        } else if (parsed_vaa.action == 0x10) {
+            vaaTransfer(parsed_vaa.payload);
+        } else {
+            revert("invalid VAA action");
+        }
+
+        // Set the VAA as consumed
+        consumedVAAs[parsed_vaa.hash] = true;
+    }
+
+    // parseAndVerifyVAA parses raw VAA data into a struct and verifies whether it contains sufficient signatures of an
+    // active guardian set i.e. is valid according to Wormhole consensus rules.
+    function parseAndVerifyVAA(bytes calldata vaa) public view returns (ParsedVAA memory parsed_vaa) {
+        parsed_vaa.version = vaa.toUint8(0);
+        require(parsed_vaa.version == 1, "VAA version incompatible");
 
         // Load 4 bytes starting from index 1
-        uint32 vaa_guardian_set_index = vaa.toUint32(1);
+        parsed_vaa.guardian_set_index = vaa.toUint32(1);
 
         uint256 len_signers = vaa.toUint8(5);
         uint offset = 6 + 66 * len_signers;
 
         // Load 4 bytes timestamp
-        //uint32 timestamp = vaa.toUint32(offset);
+        parsed_vaa.timestamp = vaa.toUint32(offset);
 
         // Hash the body
-        bytes32 hash = keccak256(vaa.slice(offset, vaa.length - offset));
-        require(!consumedVAAs[hash], "VAA was already executed");
+        parsed_vaa.hash = keccak256(vaa.slice(offset, vaa.length - offset));
+        require(!consumedVAAs[parsed_vaa.hash], "VAA was already executed");
 
-        GuardianSet memory guardian_set = guardian_sets[vaa_guardian_set_index];
+        GuardianSet memory guardian_set = guardian_sets[parsed_vaa.guardian_set_index];
         require(guardian_set.keys.length > 0, "invalid guardian set");
         require(guardian_set.expiration_time == 0 || guardian_set.expiration_time > block.timestamp, "guardian set has expired");
         // We're using a fixed point number transformation with 1 decimal to deal with rounding.
@@ -112,24 +139,11 @@ contract Wormhole is ReentrancyGuard {
             bytes32 s = vaa.toBytes32(39 + i * 66);
             uint8 v = vaa.toUint8(71 + i * 66);
             v += 27;
-            require(ecrecover(hash, v, r, s) == guardian_set.keys[index], "VAA signature invalid");
-        }
-
-        uint8 action = vaa.toUint8(offset + 4);
-        bytes memory payload = vaa.slice(offset + 5, vaa.length - (offset + 5));
-
-        // Process VAA
-        if (action == 0x01) {
-            require(vaa_guardian_set_index == guardian_set_index, "only the current guardian set can change the guardian set");
-            vaaUpdateGuardianSet(payload);
-        } else if (action == 0x10) {
-            vaaTransfer(payload);
-        } else {
-            revert("invalid VAA action");
+            require(ecrecover(parsed_vaa.hash, v, r, s) == guardian_set.keys[index], "VAA signature invalid");
         }
 
-        // Set the VAA as consumed
-        consumedVAAs[hash] = true;
+        parsed_vaa.action = vaa.toUint8(offset + 4);
+        parsed_vaa.payload = vaa.slice(offset + 5, vaa.length - (offset + 5));
     }
 
     function vaaUpdateGuardianSet(bytes memory data) private {