[Sui 20/x]- refactor Pyth governance code path (#991)

* - refactor Pyth governance code path to not use wormhole::governance_message module
- use our own custom WormholeVAAVerificationReceipt struct instead of DecreeReceipt

* delete print

* delete print

* contract edits

* add test vaa / test for set_update_fee

* bring back set data sources test

* use correct VAA for test set data sources

* delete commented out code

* write test for set stale price threshold

* update pyth verify_vaa

* simplify pyth::governance::verify_vaa

* use sequence number for replay protection in both governance and contract upgrade code paths

* only use sequence number for replay protection
This commit is contained in:
optke3 2023-08-10 04:58:44 -04:00 committed by GitHub
parent ec63330cf0
commit f79cfd8669
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 104 additions and 216 deletions

View File

@ -11,6 +11,7 @@ module pyth::data_source {
friend pyth::set_data_sources;
friend pyth::pyth;
friend pyth::set_governance_data_source;
friend pyth::governance;
#[test_only]
friend pyth::pyth_tests;
#[test_only]

View File

@ -14,12 +14,11 @@ module pyth::contract_upgrade {
use wormhole::bytes32::{Self, Bytes32};
use wormhole::bytes::{Self};
use wormhole::cursor::{Self};
use wormhole::governance_message::{Self, DecreeTicket, DecreeReceipt};
use pyth::state::{Self, State};
use pyth::governance_witness::{GovernanceWitness, new_governance_witness};
use pyth::governance_instruction::{Self};
use pyth::governance_action::{Self};
use pyth::governance::{Self, WormholeVAAVerificationReceipt};
friend pyth::migrate;
@ -27,6 +26,7 @@ module pyth::contract_upgrade {
const E_DIGEST_ZERO_BYTES: u64 = 0;
const E_GOVERNANCE_ACTION_MUST_BE_CONTRACT_UPGRADE: u64 = 1;
const E_GOVERNANCE_CONTRACT_UPGRADE_CHAIN_ID_ZERO: u64 = 2;
const E_CANNOT_EXECUTE_GOVERNANCE_ACTION_WITH_OBSOLETE_SEQUENCE_NUMBER: u64 = 3;
/// Specific governance payload ID (action) to complete upgrading the
/// contract.
@ -43,35 +43,27 @@ module pyth::contract_upgrade {
digest: Bytes32
}
public fun authorize_governance(
pyth_state: &State
): DecreeTicket<GovernanceWitness> {
governance_message::authorize_verify_local(
new_governance_witness(),
state::governance_chain(pyth_state),
state::governance_contract(pyth_state),
state::governance_module(),
CONTRACT_UPGRADE
)
}
/// Redeem governance VAA to issue an `UpgradeTicket` for the upgrade given
/// a contract upgrade VAA. This governance message is only relevant for Sui
/// because a contract upgrade is only relevant to one particular network
/// (in this case Sui), whose build digest is encoded in this message.
public fun authorize_upgrade(
pyth_state: &mut State,
receipt: DecreeReceipt<GovernanceWitness>
receipt: WormholeVAAVerificationReceipt,
): UpgradeTicket {
// Current package checking when consuming VAA hashes. This is because
// upgrades are protected by the Sui VM, enforcing the latest package
// is the one performing the upgrade.
let consumed =
state::borrow_mut_consumed_vaas_unchecked(pyth_state);
// Get the sequence number of the governance VAA that was used to
// generate the receipt.
let sequence = governance::take_sequence(&receipt);
// And consume.
let payload = governance_message::take_payload(consumed, receipt);
// Require that new sequence number is greater than last executed sequence number.
assert!(sequence > state::get_last_executed_governance_sequence(pyth_state),
E_CANNOT_EXECUTE_GOVERNANCE_ACTION_WITH_OBSOLETE_SEQUENCE_NUMBER);
// Update latest executed sequence number to current one.
state::set_last_executed_governance_sequence_unchecked(pyth_state, sequence);
let payload = governance::take_payload(&receipt);
let instruction = governance_instruction::from_byte_vec(payload);
@ -87,6 +79,8 @@ module pyth::contract_upgrade {
// upgrade_payload contains a 32-byte digest
let upgrade_payload = governance_instruction::destroy(instruction);
governance::destroy(receipt);
// Proceed with processing new implementation version.
handle_upgrade_contract(pyth_state, upgrade_payload)
}

View File

@ -7,26 +7,78 @@ module pyth::governance {
use pyth::set_fee_recipient;
use pyth::state::{Self, State};
use pyth::set_update_fee;
use pyth::governance_witness::{GovernanceWitness};
use wormhole::governance_message::{Self, DecreeReceipt};
use wormhole::vaa::{Self, VAA};
use wormhole::bytes32::Bytes32;
const E_INVALID_GOVERNANCE_ACTION: u64 = 0;
const E_MUST_USE_CONTRACT_UPGRADE_MODULE_TO_DO_UPGRADES: u64 = 1;
const E_CANNOT_EXECUTE_GOVERNANCE_ACTION_WITH_OBSOLETE_SEQUENCE_NUMBER: u64 = 2;
const E_OLD_GUARDIAN_SET_GOVERNANCE: u64 = 3;
const E_INVALID_GOVERNANCE_DATA_SOURCE: u64 = 4;
// this struct does not have the store or key ability so it must be
// used in the same txn chain in which it is created
struct WormholeVAAVerificationReceipt{
payload: vector<u8>,
digest: Bytes32,
sequence: u64, // used for replay protection
}
public fun take_payload(receipt: &WormholeVAAVerificationReceipt): vector<u8> {
receipt.payload
}
public fun take_digest(receipt: &WormholeVAAVerificationReceipt): Bytes32 {
receipt.digest
}
public fun take_sequence(receipt: &WormholeVAAVerificationReceipt): u64 {
receipt.sequence
}
public fun destroy(receipt: WormholeVAAVerificationReceipt) {
let WormholeVAAVerificationReceipt{payload: _, digest: _, sequence: _} = receipt;
}
// We define a custom verify_vaa function instead of using wormhole::governance_message::verify_vaa
// because that function makes extra assumptions about the VAA payload headers. Pyth uses a
// different header format compared to Wormhole, so
public fun verify_vaa(
pyth_state: &State,
verified_vaa: VAA,
): WormholeVAAVerificationReceipt {
state::assert_latest_only(pyth_state);
let vaa_data_source = pyth::data_source::new((vaa::emitter_chain(&verified_vaa) as u64), vaa::emitter_address(&verified_vaa));
// The emitter chain and address must correspond to the Pyth governance emitter chain and contract.
assert!(
pyth::state::is_valid_governance_data_source(pyth_state, vaa_data_source),
E_INVALID_GOVERNANCE_DATA_SOURCE
);
let digest = vaa::digest(&verified_vaa);
let sequence = vaa::sequence(&verified_vaa);
let payload = vaa::take_payload(verified_vaa);
WormholeVAAVerificationReceipt { payload, digest, sequence }
}
/// Execute a governance instruction other than contract upgrade, which is
/// handled separately in the contract_upgrade.move module.
public fun execute_governance_instruction(
pyth_state : &mut State,
receipt: DecreeReceipt<GovernanceWitness>,
receipt: WormholeVAAVerificationReceipt,
) {
// This capability ensures that the current build version is used.
let latest_only = state::assert_latest_only(pyth_state);
// Get the sequence number of the governance VAA that was used to
// generate the receipt.
let sequence = governance_message::sequence(&receipt);
let sequence = receipt.sequence;
// Require that new sequence number is greater than last executed sequence number.
assert!(sequence > state::get_last_executed_governance_sequence(pyth_state),
@ -35,15 +87,9 @@ module pyth::governance {
// Update latest executed sequence number to current one.
state::set_last_executed_governance_sequence(&latest_only, pyth_state, sequence);
// governance_message::take_payload takes care of replay protection.
let payload =
governance_message::take_payload(
state::borrow_mut_consumed_vaas(
&latest_only,
pyth_state
),
receipt
);
let payload = receipt.payload;
destroy(receipt);
let instruction = governance_instruction::from_byte_vec(payload);

View File

@ -39,6 +39,8 @@ module pyth::governance_instruction {
target_chain_id : (target_chain_id as u64),
payload
};
// validate validates that module and target chain are correct
validate(&instruction);
instruction

View File

@ -1,22 +0,0 @@
module pyth::governance_witness {
friend pyth::set_data_sources;
friend pyth::set_stale_price_threshold;
friend pyth::set_update_fee;
friend pyth::set_governance_data_source;
friend pyth::set_fee_recipient;
friend pyth::contract_upgrade;
/// A hot potato that ensures that only DecreeTickets
/// and DecreeReceipts associated with Sui Pyth governance
/// are passed to execute_governance_instruction or
/// execute_contract_upgrade_governance_instruction.
///
/// DecreeTickets and DecreeReceipts are Wormhole structs
/// that are used in the VAA verification process.
struct GovernanceWitness has drop {}
public(friend) fun new_governance_witness(): GovernanceWitness{
GovernanceWitness{}
}
}

View File

@ -4,13 +4,10 @@ module pyth::set_data_sources {
use wormhole::cursor;
use wormhole::external_address::{Self};
use wormhole::bytes32::{Self};
use wormhole::governance_message::{Self, DecreeTicket};
use pyth::deserialize;
use pyth::data_source::{Self, DataSource};
use pyth::state::{Self, State, LatestOnly};
use pyth::governance_action::{Self};
use pyth::governance_witness::{Self, GovernanceWitness};
friend pyth::governance;
@ -18,29 +15,6 @@ module pyth::set_data_sources {
sources: vector<DataSource>,
}
public fun authorize_governance(
pyth_state: &State,
global: bool
): DecreeTicket<GovernanceWitness> {
if (global) {
governance_message::authorize_verify_global(
governance_witness::new_governance_witness(),
state::governance_chain(pyth_state),
state::governance_contract(pyth_state),
state::governance_module(),
governance_action::get_value(governance_action::new_set_data_sources())
)
} else {
governance_message::authorize_verify_local(
governance_witness::new_governance_witness(),
state::governance_chain(pyth_state),
state::governance_contract(pyth_state),
state::governance_module(),
governance_action::get_value(governance_action::new_set_data_sources())
)
}
}
public(friend) fun execute(
latest_only: &LatestOnly,
state: &mut State,
@ -78,16 +52,14 @@ module pyth::set_data_sources_tests {
use sui::test_scenario::{Self};
use sui::coin::Self;
use wormhole::governance_message::verify_vaa;
use wormhole::external_address::{Self};
use wormhole::bytes32::{Self};
use pyth::pyth_tests::{Self, setup_test, take_wormhole_and_pyth_states};
use pyth::set_data_sources::{Self};
use pyth::state::Self;
use pyth::data_source::Self;
const SET_DATA_SOURCES_VAA: vector<u8> = x"01000000000100ac52663a7e50ab23db4f00f0607d930ffd438c5a214b3013418b57117590f76c32d2f790ec62be5f6e69d96273b1a567b8a698a8f5069c1ccd27a6874af2adc00100bc614e00000000000163278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c38500000000000000010100000000000000000000000000000000000000000000000000000000000000010200155054474d01020015030001f346195ac02f37d60d4db8ffa6ef74cb1be3550047543a4a9ee9acf4d78697b0001aa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6001ae101faedac5851e32b9b23b5f9411a8c2bac4aae3ed4dd7b811dd1a72ea4aa71";
const SET_DATA_SOURCES_VAA: vector<u8> = x"01000000000100b29ee59868b9066b04d8d59e1c7cc66f0678eaf4c58b8c87e4405d6de615f64b04da4025719aeed349e03900f37829454d62cc7fc7bca80328c31fe40be7b21b010000000000000000000163278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c3850000000000000001015054474d0102001503001ae101faedac5851e32b9b23b5f9411a8c2bac4aae3ed4dd7b811dd1a72ea4aa71001aa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b60001f346195ac02f37d60d4db8ffa6ef74cb1be3550047543a4a9ee9acf4d78697b0";
// VAA Info:
// module name: 0x1
// action: 2
@ -104,11 +76,9 @@ module pyth::set_data_sources_tests {
test_scenario::next_tx(&mut scenario, DEPLOYER);
let (pyth_state, worm_state) = take_wormhole_and_pyth_states(&scenario);
let ticket = set_data_sources::authorize_governance(&pyth_state, false);
let verified_vaa = wormhole::vaa::parse_and_verify(&mut worm_state, SET_DATA_SOURCES_VAA, &clock);
let receipt = verify_vaa(&worm_state, verified_vaa, ticket);
let receipt = pyth::governance::verify_vaa(&pyth_state, verified_vaa);
test_scenario::next_tx(&mut scenario, DEPLOYER);

View File

@ -3,11 +3,8 @@
module pyth::set_fee_recipient {
use wormhole::cursor;
use wormhole::external_address::{Self};
use wormhole::governance_message::{Self, DecreeTicket};
use pyth::state::{Self, State, LatestOnly};
use pyth::governance_action::{Self};
use pyth::governance_witness::{Self, GovernanceWitness};
friend pyth::governance;
@ -15,18 +12,6 @@ module pyth::set_fee_recipient {
recipient: address
}
public fun authorize_governance(
pyth_state: &State
): DecreeTicket<GovernanceWitness> {
governance_message::authorize_verify_local(
governance_witness::new_governance_witness(),
state::governance_chain(pyth_state),
state::governance_contract(pyth_state),
state::governance_module(),
governance_action::get_value(governance_action::new_set_fee_recipient())
)
}
public(friend) fun execute(latest_only: &LatestOnly, state: &mut State, payload: vector<u8>) {
let PythFeeRecipient { recipient } = from_byte_vec(payload);
state::set_fee_recipient(latest_only, state, recipient);

View File

@ -2,13 +2,10 @@ module pyth::set_governance_data_source {
use pyth::deserialize;
use pyth::data_source;
use pyth::state::{Self, State, LatestOnly};
use pyth::governance_action::{Self};
use pyth::governance_witness::{Self, GovernanceWitness};
use wormhole::cursor;
use wormhole::external_address::{Self, ExternalAddress};
use wormhole::bytes32::{Self};
use wormhole::governance_message::{Self, DecreeTicket};
friend pyth::governance;
@ -18,29 +15,6 @@ module pyth::set_governance_data_source {
initial_sequence: u64,
}
public fun authorize_governance(
pyth_state: &State,
global: bool
): DecreeTicket<GovernanceWitness> {
if (global){
governance_message::authorize_verify_global(
governance_witness::new_governance_witness(),
state::governance_chain(pyth_state),
state::governance_contract(pyth_state),
state::governance_module(),
governance_action::get_value(governance_action::new_set_governance_data_source())
)
} else {
governance_message::authorize_verify_local(
governance_witness::new_governance_witness(),
state::governance_chain(pyth_state),
state::governance_contract(pyth_state),
state::governance_module(),
governance_action::get_value(governance_action::new_set_governance_data_source())
)
}
}
public(friend) fun execute(latest_only: &LatestOnly, pyth_state: &mut State, payload: vector<u8>) {
let GovernanceDataSource { emitter_chain_id, emitter_address, initial_sequence: initial_sequence } = from_byte_vec(payload);
state::set_governance_data_source(latest_only, pyth_state, data_source::new(emitter_chain_id, emitter_address));

View File

@ -1,11 +1,8 @@
module pyth::set_stale_price_threshold {
use wormhole::cursor;
use wormhole::governance_message::{Self, DecreeTicket};
use pyth::deserialize;
use pyth::state::{Self, State, LatestOnly};
use pyth::governance_action::{Self};
use pyth::governance_witness::{Self, GovernanceWitness};
friend pyth::governance;
@ -13,29 +10,6 @@ module pyth::set_stale_price_threshold {
threshold: u64,
}
public fun authorize_governance(
pyth_state: &State,
global: bool
): DecreeTicket<GovernanceWitness> {
if (global){
governance_message::authorize_verify_global(
governance_witness::new_governance_witness(),
state::governance_chain(pyth_state),
state::governance_contract(pyth_state),
state::governance_module(),
governance_action::get_value(governance_action::new_set_stale_price_threshold())
)
} else{
governance_message::authorize_verify_local(
governance_witness::new_governance_witness(),
state::governance_chain(pyth_state),
state::governance_contract(pyth_state),
state::governance_module(),
governance_action::get_value(governance_action::new_set_stale_price_threshold())
)
}
}
public(friend) fun execute(latest_only: &LatestOnly, state: &mut State, payload: vector<u8>) {
let StalePriceThreshold { threshold } = from_byte_vec(payload);
state::set_stale_price_threshold_secs(latest_only, state, threshold);
@ -56,18 +30,15 @@ module pyth::set_stale_price_threshold_test {
use sui::test_scenario::{Self};
use sui::coin::Self;
use wormhole::governance_message::verify_vaa;
use pyth::pyth_tests::{Self, setup_test, take_wormhole_and_pyth_states};
use pyth::set_stale_price_threshold::{Self};
use pyth::state::Self;
const SET_STALE_PRICE_THRESHOLD_VAA: vector<u8> = x"01000000000100196a91724d472b6c160c44ddcc9f9cef531aa95442739300023048bd066b77ca1a02bbfd9ff1799f3d63a4dd10c5348ab3b231e3bb66232e0cb4c07daa3647090100bc614e00000000000163278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c38500000000000000010100000000000000000000000000000000000000000000000000000000000000010400155054474d0104001500000000000aee23";
const SET_STALE_PRICE_THRESHOLD_VAA: vector<u8> = x"010000000001000393eabdb4983e91e0fcfe7e6b2fc5c8fca2847fde52fd2f51a9b26b12298da13af09c271ce7723af8e0b1f52afa02b56f0b64764739b1b05e2f2c5cec80567c000000000000000000000163278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c3850000000000000001015054474d0104001500000000000f4020";
// VAA Info:
// module name: 0x1
// action: 4
// chain: 21
// stale price threshold: 716323
// stale price threshold: 999456
const DEPLOYER: address = @0x1234;
const DEFAULT_BASE_UPDATE_FEE: u64 = 0;
@ -80,11 +51,9 @@ module pyth::set_stale_price_threshold_test {
test_scenario::next_tx(&mut scenario, DEPLOYER);
let (pyth_state, worm_state) = take_wormhole_and_pyth_states(&scenario);
let ticket = set_stale_price_threshold::authorize_governance(&pyth_state, false);
let verified_vaa = wormhole::vaa::parse_and_verify(&mut worm_state, SET_STALE_PRICE_THRESHOLD_VAA, &clock);
let receipt = verify_vaa(&worm_state, verified_vaa, ticket);
let receipt = pyth::governance::verify_vaa(&pyth_state, verified_vaa);
test_scenario::next_tx(&mut scenario, DEPLOYER);
@ -93,7 +62,7 @@ module pyth::set_stale_price_threshold_test {
test_scenario::next_tx(&mut scenario, DEPLOYER);
// assert stale price threshold is set correctly
assert!(state::get_stale_price_threshold_secs(&pyth_state)==716323, 0);
assert!(state::get_stale_price_threshold_secs(&pyth_state)==999456, 0);
// clean up
coin::burn_for_testing(test_coins);

View File

@ -2,12 +2,9 @@ module pyth::set_update_fee {
use sui::math::{Self};
use wormhole::cursor;
use wormhole::governance_message::{Self, DecreeTicket};
use pyth::deserialize;
use pyth::state::{Self, State, LatestOnly};
use pyth::governance_action::{Self};
use pyth::governance_witness::{Self, GovernanceWitness};
friend pyth::governance;
@ -19,30 +16,6 @@ module pyth::set_update_fee {
exponent: u64,
}
public fun authorize_governance(
pyth_state: &State,
global: bool
): DecreeTicket<GovernanceWitness> {
if (global){
governance_message::authorize_verify_global(
governance_witness::new_governance_witness(),
state::governance_chain(pyth_state),
state::governance_contract(pyth_state),
state::governance_module(),
governance_action::get_value(governance_action::new_set_update_fee())
)
} else{
governance_message::authorize_verify_local(
governance_witness::new_governance_witness(),
state::governance_chain(pyth_state),
state::governance_contract(pyth_state),
state::governance_module(),
governance_action::get_value(governance_action::new_set_update_fee())
)
}
}
public(friend) fun execute(latest_only: &LatestOnly, pyth_state: &mut State, payload: vector<u8>) {
let UpdateFee { mantissa, exponent } = from_byte_vec(payload);
assert!(exponent <= 255, E_EXPONENT_DOES_NOT_FIT_IN_U8);
@ -71,35 +44,30 @@ module pyth::set_update_fee_tests {
use sui::test_scenario::{Self};
use sui::coin::Self;
use wormhole::governance_message::verify_vaa;
use pyth::pyth_tests::{Self, setup_test, take_wormhole_and_pyth_states};
use pyth::set_update_fee::{Self};
use pyth::state::Self;
const SET_FEE_VAA: vector<u8> = x"01000000000100e773bfd4a262ecd012333a953aadd243b8c116cc059b970ecb91216675eff89a39438570efb6eedcea15dad71d6ad0a18a7d01617e3cf61d53339df705a36df00100bc614e00000000000163278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c38500000000000000010100000000000000000000000000000000000000000000000000000000000000010300155054474d0103001500000000000000030000000000000002";
const SET_FEE_VAA: vector<u8> = x"01000000000100189d01616814b185b5a26bde6123d48e0d44dd490bbb3bde5d12076247b2180068a8261165777076ae532b7b0739aaee6411c8ba0695d20d4fa548227ce15d8d010000000000000000000163278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c3850000000000000001015054474d0103001500000000000000050000000000000005";
// VAA Info:
// module name: 0x1
// action: 3
// chain: 21
// new fee: 3, new exponent: 2
// new fee: 5, new exponent: 5
const DEPLOYER: address = @0x1234;
const DEFAULT_BASE_UPDATE_FEE: u64 = 0;
const DEFAULT_COIN_TO_MINT: u64 = 0;
#[test]
fun set_update_fee(){
fun test_set_update_fee(){
let (scenario, test_coins, clock) = setup_test(500, 1, x"63278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c385", pyth_tests::data_sources_for_test_vaa(), vector[x"13947bd48b18e53fdaeee77f3473391ac727c638"], DEFAULT_BASE_UPDATE_FEE, DEFAULT_COIN_TO_MINT);
test_scenario::next_tx(&mut scenario, DEPLOYER);
let (pyth_state, worm_state) = take_wormhole_and_pyth_states(&scenario);
let ticket = set_update_fee::authorize_governance(&pyth_state, false);
let verified_vaa = wormhole::vaa::parse_and_verify(&mut worm_state, SET_FEE_VAA, &clock);
let receipt = verify_vaa(&worm_state, verified_vaa, ticket);
let receipt = pyth::governance::verify_vaa(&pyth_state, verified_vaa);
test_scenario::next_tx(&mut scenario, DEPLOYER);
@ -108,7 +76,7 @@ module pyth::set_update_fee_tests {
test_scenario::next_tx(&mut scenario, DEPLOYER);
// assert fee is set correctly
assert!(state::get_base_update_fee(&pyth_state)==300, 0);
assert!(state::get_base_update_fee(&pyth_state)==500000, 0);
// clean up
coin::burn_for_testing(test_coins);

View File

@ -12,11 +12,10 @@
/// their required minimum version.
module pyth::migrate {
use sui::object::{ID};
use wormhole::governance_message::{Self, DecreeReceipt};
use pyth::state::{Self, State};
use pyth::contract_upgrade::{Self};
use pyth::governance_witness::{GovernanceWitness};
use pyth::governance::{Self, WormholeVAAVerificationReceipt};
struct MigrateComplete has drop, copy {
package: ID
@ -24,7 +23,7 @@ module pyth::migrate {
public fun migrate(
pyth_state: &mut State,
receipt: DecreeReceipt<GovernanceWitness>
receipt: WormholeVAAVerificationReceipt,
) {
// Perform standard migrate.
@ -51,7 +50,7 @@ module pyth::migrate {
fun handle_migrate(
pyth_state: &mut State,
receipt: DecreeReceipt<GovernanceWitness>
receipt: WormholeVAAVerificationReceipt,
) {
// See `version_control` module for hard-coded configuration.
state::migrate_version(pyth_state);
@ -62,14 +61,15 @@ module pyth::migrate {
// Check if build digest is the current one.
let digest =
contract_upgrade::take_digest(
governance_message::payload(&receipt)
governance::take_payload(&receipt)
);
state::assert_authorized_digest(
&latest_only,
pyth_state,
digest
);
governance_message::destroy(receipt);
governance::destroy(receipt);
// Finally emit an event reflecting a successful migrate.
let package = state::current_package(&latest_only, pyth_state);

View File

@ -36,12 +36,6 @@ module pyth::pyth {
#[test_only]
friend pyth::pyth_tests;
#[test_only]
friend pyth::set_data_sources_tests;
#[test_only]
friend pyth::set_stale_price_threshold_test;
#[test_only]
friend pyth::set_update_fee_tests;
/// Init state and emit event corresponding to Pyth initialization.
public entry fun init_pyth(
@ -753,9 +747,9 @@ module pyth::pyth_tests{
vector<DataSource>[
data_source::new(
1, external_address::new(bytes32::from_bytes(x"0000000000000000000000000000000000000000000000000000000000000004"))),
data_source::new(
data_source::new(
5, external_address::new(bytes32::new(x"0000000000000000000000000000000000000000000000000000000000007637"))),
data_source::new(
data_source::new(
17, external_address::new(bytes32::new(ACCUMULATOR_TESTS_EMITTER_ADDRESS)))
]
}

View File

@ -254,6 +254,13 @@ module pyth::state {
s.last_executed_governance_sequence = sequence;
}
// We have an unchecked version of set_last_executed_governance_sequence, because in the governance contract
// upgrade code path, no LatestOnly is created (for example, see authorize_upgrade and commit_upgrade in
// governance/contract_upgrade.move)
public(friend) fun set_last_executed_governance_sequence_unchecked(s: &mut State, sequence: u64) {
s.last_executed_governance_sequence = sequence;
}
public(friend) fun set_base_update_fee(_: &LatestOnly, s: &mut State, fee: u64) {
s.base_update_fee = fee;
}