268 lines
8.8 KiB
Plaintext
268 lines
8.8 KiB
Plaintext
module wormhole::state {
|
|
use std::vector::{Self};
|
|
|
|
use sui::object::{Self, UID};
|
|
use sui::tx_context::{Self, TxContext};
|
|
use sui::transfer::{Self};
|
|
use sui::vec_map::{Self, VecMap};
|
|
use sui::event::{Self};
|
|
|
|
use wormhole::myu16::{Self as u16, U16};
|
|
use wormhole::myu32::{Self as u32, U32};
|
|
use wormhole::set::{Self, Set};
|
|
use wormhole::structs::{Self, create_guardian, Guardian, GuardianSet};
|
|
use wormhole::external_address::{Self, ExternalAddress};
|
|
use wormhole::emitter::{Self};
|
|
|
|
friend wormhole::guardian_set_upgrade;
|
|
//friend wormhole::contract_upgrade;
|
|
friend wormhole::wormhole;
|
|
friend wormhole::myvaa;
|
|
#[test_only]
|
|
friend wormhole::vaa_test;
|
|
|
|
struct DeployerCapability has key, store {id: UID}
|
|
|
|
struct WormholeMessage has store, copy, drop {
|
|
sender: u64,
|
|
sequence: u64,
|
|
nonce: u64,
|
|
payload: vector<u8>,
|
|
consistency_level: u8
|
|
}
|
|
|
|
struct State has key, store {
|
|
id: UID,
|
|
|
|
/// chain id
|
|
chain_id: U16,
|
|
|
|
/// guardian chain ID
|
|
governance_chain_id: U16,
|
|
|
|
/// Address of governance contract on governance chain
|
|
governance_contract: ExternalAddress,
|
|
|
|
/// Current active guardian set index
|
|
guardian_set_index: U32,
|
|
|
|
/// guardian sets
|
|
guardian_sets: VecMap<U32, GuardianSet>,
|
|
|
|
/// Period for which a guardian set stays active after it has been replaced
|
|
guardian_set_expiry: U32,
|
|
|
|
/// Consumed governance actions
|
|
consumed_governance_actions: Set<vector<u8>>,
|
|
|
|
/// Capability for creating new emitters
|
|
emitter_registry: emitter::EmitterRegistry,
|
|
|
|
/// wormhole message fee
|
|
message_fee: u64,
|
|
}
|
|
|
|
/// Called automatically when module is first published. Transfers a deployer cap to sender.
|
|
fun init(ctx: &mut TxContext) {
|
|
transfer::transfer(DeployerCapability{id: object::new(ctx)}, tx_context::sender(ctx));
|
|
}
|
|
|
|
// creates a shared state object, so that anyone can get a reference to &mut State
|
|
// and pass it into various functions
|
|
public entry fun init_and_share_state(
|
|
deployer: DeployerCapability,
|
|
chain_id: u64,
|
|
governance_chain_id: u64,
|
|
governance_contract: vector<u8>,
|
|
initial_guardians: vector<vector<u8>>,
|
|
ctx: &mut TxContext
|
|
) {
|
|
let DeployerCapability{id} = deployer;
|
|
object::delete(id);
|
|
let state = State {
|
|
id: object::new(ctx),
|
|
chain_id: u16::from_u64(chain_id),
|
|
governance_chain_id: u16::from_u64(governance_chain_id),
|
|
governance_contract: external_address::from_bytes(governance_contract),
|
|
guardian_set_index: u32::from_u64(0),
|
|
guardian_sets: vec_map::empty<U32, GuardianSet>(),
|
|
guardian_set_expiry: u32::from_u64(2), // TODO - what is the right #epochs to set this to?
|
|
consumed_governance_actions: set::new(ctx),
|
|
emitter_registry: emitter::init_emitter_registry(),
|
|
message_fee: 0,
|
|
};
|
|
|
|
let guardians = vector::empty<Guardian>();
|
|
vector::reverse(&mut initial_guardians);
|
|
while (!vector::is_empty(&initial_guardians)) {
|
|
vector::push_back(&mut guardians, create_guardian(vector::pop_back(&mut initial_guardians)));
|
|
};
|
|
|
|
// the initial guardian set with index 0
|
|
let initial_index = u32::from_u64(0);
|
|
store_guardian_set(&mut state, initial_index, structs::create_guardian_set(initial_index, guardians));
|
|
|
|
// permanently shares state
|
|
transfer::share_object<State>(state);
|
|
}
|
|
|
|
#[test_only]
|
|
public fun test_init(ctx: &mut TxContext) {
|
|
transfer::transfer(DeployerCapability{id: object::new(ctx)}, tx_context::sender(ctx));
|
|
}
|
|
|
|
public(friend) entry fun publish_event(
|
|
sender: u64,
|
|
sequence: u64,
|
|
nonce: u64,
|
|
payload: vector<u8>
|
|
) {
|
|
event::emit(
|
|
WormholeMessage {
|
|
sender: sender,
|
|
sequence: sequence,
|
|
nonce: nonce,
|
|
payload: payload,
|
|
// Sui is an instant finality chain, so we don't need
|
|
// confirmations
|
|
consistency_level: 0,
|
|
}
|
|
);
|
|
}
|
|
|
|
// setters
|
|
|
|
public(friend) fun set_chain_id(state: &mut State, id: u64){
|
|
state.chain_id = u16::from_u64(id);
|
|
}
|
|
|
|
#[test_only]
|
|
public fun test_set_chain_id(state: &mut State, id: u64) {
|
|
set_chain_id(state, id);
|
|
}
|
|
|
|
public(friend) fun set_governance_chain_id(state: &mut State, id: u64){
|
|
state.governance_chain_id = u16::from_u64(id);
|
|
}
|
|
|
|
#[test_only]
|
|
public fun test_set_governance_chain_id(state: &mut State, id: u64) {
|
|
set_governance_chain_id(state, id);
|
|
}
|
|
|
|
public(friend) fun set_governance_action_consumed(state: &mut State, hash: vector<u8>){
|
|
set::add<vector<u8>>(&mut state.consumed_governance_actions, hash);
|
|
}
|
|
|
|
public(friend) fun set_governance_contract(state: &mut State, contract: vector<u8>) {
|
|
state.governance_contract = external_address::from_bytes(contract);
|
|
}
|
|
|
|
public(friend) fun update_guardian_set_index(state: &mut State, new_index: U32) {
|
|
state.guardian_set_index = new_index;
|
|
}
|
|
|
|
public(friend) fun expire_guardian_set(state: &mut State, index: U32, ctx: &TxContext) {
|
|
let expiry = state.guardian_set_expiry;
|
|
let guardian_set = vec_map::get_mut<U32, GuardianSet>(&mut state.guardian_sets, &index);
|
|
structs::expire_guardian_set(guardian_set, expiry, ctx);
|
|
}
|
|
|
|
public(friend) fun store_guardian_set(state: &mut State, index: U32, set: GuardianSet) {
|
|
vec_map::insert<U32, GuardianSet>(&mut state.guardian_sets, index, set);
|
|
}
|
|
|
|
// getters
|
|
|
|
public fun get_current_guardian_set_index(state: &State): U32 {
|
|
return state.guardian_set_index
|
|
}
|
|
|
|
public fun get_guardian_set(state: &State, index: U32): GuardianSet {
|
|
return *vec_map::get<U32, GuardianSet>(&state.guardian_sets, &index)
|
|
}
|
|
|
|
public fun guardian_set_is_active(state: &State, guardian_set: &GuardianSet, ctx: &TxContext): bool {
|
|
let cur_epoch = tx_context::epoch(ctx);
|
|
let index = structs::get_guardian_set_index(guardian_set);
|
|
let current_index = get_current_guardian_set_index(state);
|
|
index == current_index ||
|
|
u32::to_u64(structs::get_guardian_set_expiry(guardian_set)) > cur_epoch
|
|
}
|
|
|
|
public fun get_governance_chain(state: &State): U16 {
|
|
return state.governance_chain_id
|
|
}
|
|
|
|
public fun get_governance_contract(state: &State): ExternalAddress {
|
|
return state.governance_contract
|
|
}
|
|
|
|
public fun get_chain_id(state: &State): U16 {
|
|
return state.chain_id
|
|
}
|
|
|
|
public fun get_message_fee(state: &State): u64 {
|
|
return state.message_fee
|
|
}
|
|
|
|
public(friend) fun new_emitter(state: &mut State, ctx: &mut TxContext): emitter::EmitterCapability{
|
|
emitter::new_emitter(&mut state.emitter_registry, ctx)
|
|
}
|
|
|
|
}
|
|
|
|
#[test_only]
|
|
module wormhole::test_state{
|
|
use sui::test_scenario::{Self, Scenario, next_tx, ctx, take_from_address, take_shared, return_shared};
|
|
|
|
use wormhole::state::{Self, test_init, State, DeployerCapability};
|
|
use wormhole::myu16::{Self as u16};
|
|
|
|
fun scenario(): Scenario { test_scenario::begin(@0x123233) }
|
|
fun people(): (address, address, address) { (@0x124323, @0xE05, @0xFACE) }
|
|
|
|
public fun init_wormhole_state(test: Scenario, admin: address): Scenario {
|
|
next_tx(&mut test, admin); {
|
|
test_init(ctx(&mut test));
|
|
};
|
|
next_tx(&mut test, admin); {
|
|
let deployer = take_from_address<DeployerCapability>(&test, admin);
|
|
state::init_and_share_state(
|
|
deployer,
|
|
21,
|
|
1, // governance chain
|
|
x"0000000000000000000000000000000000000000000000000000000000000004", // governance_contract
|
|
vector[x"beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe"], // initial_guardian(s)
|
|
ctx(&mut test));
|
|
};
|
|
return test
|
|
}
|
|
|
|
#[test]
|
|
fun test_state_setters() {
|
|
test_state_setters_(scenario())
|
|
}
|
|
|
|
fun test_state_setters_(test: Scenario) {
|
|
let (admin, _, _) = people();
|
|
test = init_wormhole_state(test, admin);
|
|
|
|
// test setters
|
|
next_tx(&mut test, admin); {
|
|
let state = take_shared<State>(&test);
|
|
|
|
// test set chain id
|
|
state::test_set_chain_id(&mut state, 5);
|
|
assert!(state::get_chain_id(&state) == u16::from_u64(5), 0);
|
|
|
|
// test set governance chain id
|
|
state::test_set_governance_chain_id(&mut state, 100);
|
|
assert!(state::get_governance_chain(&state) == u16::from_u64(100), 0);
|
|
|
|
return_shared<State>(state);
|
|
};
|
|
test_scenario::end(test);
|
|
}
|
|
}
|