refactor(target_chains/ethereum): remove legacy batch updates support from updatePriceFeeds
This commit is contained in:
parent
01f878cf5a
commit
8a70ca769b
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
// Populate the contract with the initial prices
|
||||
(
|
||||
cachedPricesWhBatchUpdateData,
|
||||
cachedPricesWhBatchUpdateFee
|
||||
) = generateWhBatchUpdateDataAndFee(cachedPrices);
|
||||
pyth.updatePriceFeeds{value: cachedPricesWhBatchUpdateFee}(
|
||||
cachedPricesWhBatchUpdateData
|
||||
);
|
||||
allCachedPricesWhMerkleUpdateData = cachedPricesWhMerkleUpdateData[
|
||||
NUM_PRICES - 1
|
||||
];
|
||||
allCachedPricesWhMerkleUpdateFee = cachedPricesWhMerkleUpdateFee[
|
||||
NUM_PRICES - 1
|
||||
];
|
||||
allFreshPricesWhMerkleUpdateData = freshPricesWhMerkleUpdateData[
|
||||
NUM_PRICES - 1
|
||||
];
|
||||
allFreshPricesWhMerkleUpdateFee = freshPricesWhMerkleUpdateFee[
|
||||
NUM_PRICES - 1
|
||||
];
|
||||
|
||||
(
|
||||
freshPricesWhBatchUpdateData,
|
||||
freshPricesWhBatchUpdateFee
|
||||
) = generateWhBatchUpdateDataAndFee(freshPrices);
|
||||
// Populate the contract with the initial prices
|
||||
pyth.updatePriceFeeds{value: allCachedPricesWhMerkleUpdateFee}(
|
||||
allCachedPricesWhMerkleUpdateData
|
||||
);
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue