浏览代码

refactor(target_chains/ethereum): remove legacy batch updates support from updatePriceFeeds

Pavel Strakhov 1 年之前
父节点
当前提交
8a70ca769b

+ 3 - 55
target_chains/ethereum/contracts/contracts/pyth/Pyth.sol

@@ -62,29 +62,14 @@ abstract contract Pyth is
         PythSetters.setSingleUpdateFeeInWei(singleUpdateFeeInWei);
     }
 
-    function updatePriceBatchFromVm(bytes calldata encodedVm) private {
-        parseAndProcessBatchPriceAttestation(
-            parseAndVerifyBatchAttestationVM(encodedVm)
-        );
-    }
-
     function updatePriceFeeds(
         bytes[] calldata updateData
     ) public payable override {
         uint totalNumUpdates = 0;
         for (uint i = 0; i < updateData.length; ) {
-            if (
-                updateData[i].length > 4 &&
-                UnsafeCalldataBytesLib.toUint32(updateData[i], 0) ==
-                ACCUMULATOR_MAGIC
-            ) {
-                totalNumUpdates += updatePriceInfosFromAccumulatorUpdate(
-                    updateData[i]
-                );
-            } else {
-                updatePriceBatchFromVm(updateData[i]);
-                totalNumUpdates += 1;
-            }
+            totalNumUpdates += updatePriceInfosFromAccumulatorUpdate(
+                updateData[i]
+            );
 
             unchecked {
                 i++;
@@ -138,43 +123,6 @@ abstract contract Pyth is
         return isValidDataSource(vm.emitterChainId, vm.emitterAddress);
     }
 
-    function parseAndProcessBatchPriceAttestation(
-        IWormhole.VM memory vm
-    ) internal {
-        // Most of the math operations below are simple additions.
-        // In the places that there is more complex operation there is
-        // a comment explaining why it is safe. Also, byteslib
-        // operations have proper require.
-        unchecked {
-            bytes memory encoded = vm.payload;
-            (
-                uint index,
-                uint nAttestations,
-                uint attestationSize
-            ) = parseBatchAttestationHeader(encoded);
-
-            // Deserialize each attestation
-            for (uint j = 0; j < nAttestations; j++) {
-                (
-                    PythInternalStructs.PriceInfo memory info,
-                    bytes32 priceId
-                ) = parseSingleAttestationFromBatch(
-                        encoded,
-                        index,
-                        attestationSize
-                    );
-
-                // Respect specified attestation size for forward-compat
-                index += attestationSize;
-
-                // Store the attestation
-                updateLatestPriceIfNecessary(priceId, info);
-            }
-
-            emit BatchPriceFeedUpdate(vm.emitterChainId, vm.sequence);
-        }
-    }
-
     function parseSingleAttestationFromBatch(
         bytes memory encoded,
         uint index,

+ 34 - 67
target_chains/ethereum/contracts/forge-test/GasBenchmark.t.sol

@@ -32,21 +32,21 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils {
 
     // Cached prices are populated in the setUp
     PythStructs.Price[] cachedPrices;
-    bytes[] cachedPricesWhBatchUpdateData;
-    uint cachedPricesWhBatchUpdateFee;
     uint64[] cachedPricesPublishTimes;
 
     bytes[][] cachedPricesWhMerkleUpdateData; // i th element contains the update data for the first i prices
+    bytes[] allCachedPricesWhMerkleUpdateData; // the update data for all prices
     uint[] cachedPricesWhMerkleUpdateFee; // i th element contains the update fee for the first i prices
+    uint allCachedPricesWhMerkleUpdateFee; // the update fee for all prices
 
     // Fresh prices are different prices that can be used
     // as a fresh price to update the prices
     PythStructs.Price[] freshPrices;
-    bytes[] freshPricesWhBatchUpdateData;
-    uint freshPricesWhBatchUpdateFee;
     uint64[] freshPricesPublishTimes;
     bytes[][] freshPricesWhMerkleUpdateData; // i th element contains the update data for the first i prices
+    bytes[] allFreshPricesWhMerkleUpdateData; // the update data for all prices
     uint[] freshPricesWhMerkleUpdateFee; // i th element contains the update fee for the first i prices
+    uint allFreshPricesWhMerkleUpdateFee; // the update fee for all prices
 
     uint64 sequence;
     uint randomSeed;
@@ -104,19 +104,23 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils {
             freshPricesWhMerkleUpdateData.push(updateData);
             freshPricesWhMerkleUpdateFee.push(updateFee);
         }
+        allCachedPricesWhMerkleUpdateData = cachedPricesWhMerkleUpdateData[
+            NUM_PRICES - 1
+        ];
+        allCachedPricesWhMerkleUpdateFee = cachedPricesWhMerkleUpdateFee[
+            NUM_PRICES - 1
+        ];
+        allFreshPricesWhMerkleUpdateData = freshPricesWhMerkleUpdateData[
+            NUM_PRICES - 1
+        ];
+        allFreshPricesWhMerkleUpdateFee = freshPricesWhMerkleUpdateFee[
+            NUM_PRICES - 1
+        ];
+
         // Populate the contract with the initial prices
-        (
-            cachedPricesWhBatchUpdateData,
-            cachedPricesWhBatchUpdateFee
-        ) = generateWhBatchUpdateDataAndFee(cachedPrices);
-        pyth.updatePriceFeeds{value: cachedPricesWhBatchUpdateFee}(
-            cachedPricesWhBatchUpdateData
+        pyth.updatePriceFeeds{value: allCachedPricesWhMerkleUpdateFee}(
+            allCachedPricesWhMerkleUpdateData
         );
-
-        (
-            freshPricesWhBatchUpdateData,
-            freshPricesWhBatchUpdateFee
-        ) = generateWhBatchUpdateDataAndFee(freshPrices);
     }
 
     function getRand() internal returns (uint val) {
@@ -124,23 +128,6 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils {
         val = uint(keccak256(abi.encode(randomSeed)));
     }
 
-    function generateWhBatchUpdateDataAndFee(
-        PythStructs.Price[] memory prices
-    ) internal returns (bytes[] memory updateData, uint updateFee) {
-        bytes memory vaa = generateWhBatchUpdate(
-            pricesToPriceAttestations(priceIds, prices),
-            sequence,
-            NUM_GUARDIAN_SIGNERS
-        );
-
-        ++sequence;
-
-        updateData = new bytes[](1);
-        updateData[0] = vaa;
-
-        updateFee = pyth.getUpdateFee(updateData);
-    }
-
     function generateWhMerkleUpdateDataAndFee(
         PythStructs.Price[] memory prices
     ) internal returns (bytes[] memory updateData, uint updateFee) {
@@ -155,18 +142,6 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils {
         updateFee = pyth.getUpdateFee(updateData);
     }
 
-    function testBenchmarkUpdatePriceFeedsWhBatchFresh() public {
-        pyth.updatePriceFeeds{value: freshPricesWhBatchUpdateFee}(
-            freshPricesWhBatchUpdateData
-        );
-    }
-
-    function testBenchmarkUpdatePriceFeedsWhBatchNotFresh() public {
-        pyth.updatePriceFeeds{value: cachedPricesWhBatchUpdateFee}(
-            cachedPricesWhBatchUpdateData
-        );
-    }
-
     function testBenchmarkUpdatePriceFeedsWhMerkle1FeedFresh() public {
         pyth.updatePriceFeeds{value: freshPricesWhMerkleUpdateFee[0]}(
             freshPricesWhMerkleUpdateData[0]
@@ -227,23 +202,23 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils {
         );
     }
 
-    function testBenchmarkUpdatePriceFeedsIfNecessaryWhBatchFresh() public {
+    function testBenchmarkUpdatePriceFeedsIfNecessaryWhMerkleFresh() public {
         // Since the prices have advanced, the publishTimes are newer than one in
         // the contract and hence, the call should succeed.
-        pyth.updatePriceFeedsIfNecessary{value: freshPricesWhBatchUpdateFee}(
-            freshPricesWhBatchUpdateData,
-            priceIds,
-            freshPricesPublishTimes
-        );
+        pyth.updatePriceFeedsIfNecessary{
+            value: allFreshPricesWhMerkleUpdateFee
+        }(allFreshPricesWhMerkleUpdateData, priceIds, freshPricesPublishTimes);
     }
 
-    function testBenchmarkUpdatePriceFeedsIfNecessaryWhBatchNotFresh() public {
+    function testBenchmarkUpdatePriceFeedsIfNecessaryWhMerkleNotFresh() public {
         // Since the price is not advanced, the publishTimes are the same as the
         // ones in the contract.
         vm.expectRevert(PythErrors.NoFreshUpdate.selector);
 
-        pyth.updatePriceFeedsIfNecessary{value: cachedPricesWhBatchUpdateFee}(
-            cachedPricesWhBatchUpdateData,
+        pyth.updatePriceFeedsIfNecessary{
+            value: allCachedPricesWhMerkleUpdateFee
+        }(
+            allCachedPricesWhMerkleUpdateData,
             priceIds,
             cachedPricesPublishTimes
         );
@@ -253,8 +228,8 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils {
         bytes32[] memory ids = new bytes32[](1);
         ids[0] = priceIds[0];
 
-        pyth.parsePriceFeedUpdates{value: freshPricesWhBatchUpdateFee}(
-            freshPricesWhBatchUpdateData,
+        pyth.parsePriceFeedUpdates{value: allFreshPricesWhMerkleUpdateFee}(
+            allFreshPricesWhMerkleUpdateData,
             ids,
             0,
             50
@@ -266,8 +241,8 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils {
         ids[0] = priceIds[0];
         ids[1] = priceIds[1];
 
-        pyth.parsePriceFeedUpdates{value: freshPricesWhBatchUpdateFee}(
-            freshPricesWhBatchUpdateData,
+        pyth.parsePriceFeedUpdates{value: allFreshPricesWhMerkleUpdateFee}(
+            allFreshPricesWhMerkleUpdateData,
             ids,
             0,
             50
@@ -403,8 +378,8 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils {
         ids[0] = priceIds[0];
 
         vm.expectRevert(PythErrors.PriceFeedNotFoundWithinRange.selector);
-        pyth.parsePriceFeedUpdates{value: freshPricesWhBatchUpdateFee}(
-            freshPricesWhBatchUpdateData,
+        pyth.parsePriceFeedUpdates{value: allFreshPricesWhMerkleUpdateFee}(
+            allFreshPricesWhMerkleUpdateData,
             ids,
             50,
             100
@@ -427,10 +402,6 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils {
         pyth.getEmaPrice(priceIds[0]);
     }
 
-    function testBenchmarkGetUpdateFeeWhBatch() public view {
-        pyth.getUpdateFee(freshPricesWhBatchUpdateData);
-    }
-
     function testBenchmarkGetUpdateFeeWhMerkle1() public view {
         pyth.getUpdateFee(freshPricesWhMerkleUpdateData[0]);
     }
@@ -450,8 +421,4 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils {
     function testBenchmarkGetUpdateFeeWhMerkle5() public view {
         pyth.getUpdateFee(freshPricesWhMerkleUpdateData[4]);
     }
-
-    function testBenchmarkWormholeParseAndVerifyVMBatchAttestation() public {
-        wormhole.parseAndVerifyVM(freshPricesWhBatchUpdateData[0]);
-    }
 }

+ 11 - 8
target_chains/ethereum/contracts/forge-test/VerificationExperiments.t.sol

@@ -35,6 +35,9 @@ contract VerificationExperiments is
     // Private key for the threshold signature
     uint256 THRESHOLD_KEY = 1234;
 
+    // We will have less than 512 price for a foreseeable future.
+    uint8 constant MERKLE_TREE_DEPTH = 9;
+
     PythExperimental public pyth;
 
     bytes32[] priceIds;
@@ -106,7 +109,7 @@ contract VerificationExperiments is
 
         setRandSeed(12345);
         for (uint i = 0; i < NUM_PRICES; ++i) {
-            uint64 publishTime = uint64(getRandUint() % 10);
+            uint64 publishTime = uint64(getRandUint() % 10) + 1; // to make sure prevPublishTime is >= 0
 
             cachedPrices.push(
                 PythStructs.Price(
@@ -147,17 +150,17 @@ contract VerificationExperiments is
 
         // Generate the update payloads for the various verification systems
 
-        whMerkleUpdateDepth0 = generateWhMerkleUpdate(
+        whMerkleUpdateDepth0 = generateSingleWhMerkleUpdate(
             priceIds[0],
             freshPrices[0],
             0
         );
-        whMerkleUpdateDepth1 = generateWhMerkleUpdate(
+        whMerkleUpdateDepth1 = generateSingleWhMerkleUpdate(
             priceIds[0],
             freshPrices[0],
             1
         );
-        whMerkleUpdateDepth8 = generateWhMerkleUpdate(
+        whMerkleUpdateDepth8 = generateSingleWhMerkleUpdate(
             priceIds[0],
             freshPrices[0],
             8
@@ -188,9 +191,9 @@ contract VerificationExperiments is
     function generateWormholeUpdateDataAndFee(
         PythStructs.Price[] memory prices
     ) internal returns (bytes[] memory updateData, uint updateFee) {
-        bytes memory vaa = generateWhBatchUpdate(
-            pricesToPriceAttestations(priceIds, prices),
-            sequence,
+        bytes memory vaa = generateWhMerkleUpdate(
+            pricesToPriceFeedMessages(priceIds, prices),
+            MERKLE_TREE_DEPTH,
             NUM_GUARDIAN_SIGNERS
         );
 
@@ -252,7 +255,7 @@ contract VerificationExperiments is
     }
 
     // Generate a wormhole-attested merkle proof with the given depth.
-    function generateWhMerkleUpdate(
+    function generateSingleWhMerkleUpdate(
         bytes32 priceId,
         PythStructs.Price memory price,
         uint depth

+ 0 - 46
target_chains/ethereum/contracts/forge-test/utils/PythTestUtils.t.sol

@@ -362,49 +362,3 @@ abstract contract PythTestUtils is Test, WormholeTestUtils {
         }
     }
 }
-
-contract PythTestUtilsTest is
-    Test,
-    WormholeTestUtils,
-    PythTestUtils,
-    IPythEvents
-{
-    function testGenerateWhBatchUpdateWorks() public {
-        IPyth pyth = IPyth(
-            setUpPyth(
-                setUpWormholeReceiver(
-                    1 // Number of guardians
-                )
-            )
-        );
-
-        bytes32[] memory priceIds = new bytes32[](1);
-        priceIds[
-            0
-        ] = 0x0000000000000000000000000000000000000000000000000000000000000222;
-
-        PythStructs.Price[] memory prices = new PythStructs.Price[](1);
-        prices[0] = PythStructs.Price(
-            100, // Price
-            10, // Confidence
-            -5, // Exponent
-            1 // Publish time
-        );
-
-        bytes memory vaa = generateWhBatchUpdate(
-            pricesToPriceAttestations(priceIds, prices),
-            1, // Sequence
-            1 // No. Signers
-        );
-
-        bytes[] memory updateData = new bytes[](1);
-        updateData[0] = vaa;
-
-        uint updateFee = pyth.getUpdateFee(updateData);
-
-        vm.expectEmit(true, false, false, true);
-        emit PriceFeedUpdate(priceIds[0], 1, 100, 10);
-
-        pyth.updatePriceFeeds{value: updateFee}(updateData);
-    }
-}