1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use crate::{
    legacy::utils::{AccountVariant, LegacyAccount},
    types::Timestamp,
};
use anchor_lang::prelude::*;

/// Account used to store a guardian set. The keys encoded in this account are Ethereum pubkeys.
/// Its expiration time is determined at the time a guardian set is updated to a new set, where the
/// current network clock time is used with
/// [guardian_set_ttl](crate::state::Config::guardian_set_ttl).
///
/// NOTE: The account schema is the same as legacy guardian sets, but this account now has a
/// discriminator generated by Anchor's [account] macro. When the Core Bridge program performs a
/// guardian set update with this implementation, guardian sets will now have this Anchor-generated
/// discriminator.
#[account]
#[derive(Debug)]
pub struct GuardianSet {
    /// Index representing an incrementing version number for this guardian set.
    pub index: u32,

    /// Ethereum-style public keys.
    pub keys: Vec<[u8; 20]>,

    /// Timestamp representing the time this guardian became active.
    pub creation_time: Timestamp,

    /// Expiration time when VAAs issued by this set are no longer valid.
    pub expiration_time: Timestamp,
}

impl LegacyAccount for GuardianSet {
    const DISCRIMINATOR: &'static [u8] = &[];

    fn program_id() -> Pubkey {
        crate::ID
    }
}

impl Owner for AccountVariant<GuardianSet> {
    fn owner() -> Pubkey {
        crate::ID
    }
}

impl GuardianSet {
    pub const SEED_PREFIX: &'static [u8] = b"GuardianSet";

    pub(crate) fn compute_size(num_guardians: usize) -> usize {
        8 // discriminator
        + 4 // index
        + 4 + num_guardians * 20 // keys
        + Timestamp::INIT_SPACE // creation_time
        + Timestamp::INIT_SPACE // expiration_time
    }

    pub fn is_active(&self, timestamp: &Timestamp) -> bool {
        // Note: This is a fix for Wormhole on mainnet.  The initial guardian set was never expired
        // so we block it here.
        if self.index == 0 && self.creation_time == 1628099186 {
            false
        } else {
            self.expiration_time == 0 || self.expiration_time >= *timestamp
        }
    }
}