diff --git a/cross-chain/solana/programs/tbtc/src/processor/admin/add_guardian.rs b/cross-chain/solana/programs/tbtc/src/processor/admin/add_guardian.rs index 82e3d3380..422bac905 100644 --- a/cross-chain/solana/programs/tbtc/src/processor/admin/add_guardian.rs +++ b/cross-chain/solana/programs/tbtc/src/processor/admin/add_guardian.rs @@ -1,6 +1,6 @@ use crate::{ error::TbtcError, - state::{Config, GuardianIndex, GuardianInfo}, + state::{Config, GuardianInfo}, }; use anchor_lang::prelude::*; @@ -26,15 +26,6 @@ pub struct AddGuardian<'info> { )] guardian_info: Account<'info, GuardianInfo>, - #[account( - init, - payer = authority, - space = 8 + GuardianIndex::INIT_SPACE, - seeds = [GuardianIndex::SEED_PREFIX, &[config.num_guardians]], - bump - )] - guardian_index: Account<'info, GuardianIndex>, - /// CHECK: Required authority to pause contract. This pubkey lives in `GuardianInfo`. guardian: AccountInfo<'info>, @@ -44,15 +35,9 @@ pub struct AddGuardian<'info> { pub fn add_guardian(ctx: Context) -> Result<()> { ctx.accounts.guardian_info.set_inner(GuardianInfo { guardian: ctx.accounts.guardian.key(), - index: ctx.accounts.config.num_guardians, bump: ctx.bumps["guardian_info"], }); - ctx.accounts.guardian_index.set_inner(GuardianIndex { - guardian_info: ctx.accounts.guardian_info.key(), - bump: ctx.bumps["guardian_index"], - }); - ctx.accounts.config.num_guardians += 1; Ok(()) } diff --git a/cross-chain/solana/programs/tbtc/src/processor/admin/remove_guardian.rs b/cross-chain/solana/programs/tbtc/src/processor/admin/remove_guardian.rs index 9fb05b122..777edf865 100644 --- a/cross-chain/solana/programs/tbtc/src/processor/admin/remove_guardian.rs +++ b/cross-chain/solana/programs/tbtc/src/processor/admin/remove_guardian.rs @@ -1,6 +1,6 @@ use crate::{ error::TbtcError, - state::{Config, GuardianIndex, GuardianInfo}, + state::{Config, GuardianInfo}, }; use anchor_lang::prelude::*; @@ -14,7 +14,6 @@ pub struct RemoveGuardian<'info> { authority: Signer<'info>, - // the guardian info to remove #[account( mut, has_one = guardian, @@ -24,43 +23,11 @@ pub struct RemoveGuardian<'info> { )] guardian_info: Account<'info, GuardianInfo>, - // the guardian info at the last index. - // This gets its index swapped to the position of the removed guardian info. - #[account( - mut, - constraint = guardian_info_swap.index == config.num_guardians - 1, - seeds = [GuardianInfo::SEED_PREFIX, guardian_info_swap.guardian.as_ref()], - bump = guardian_info_swap.bump, - )] - guardian_info_swap: Account<'info, GuardianInfo>, - - // The index account of the guardian to remove. - // We replace guardian_info in this with guardian_info_swap. - #[account( - mut, - seeds = [GuardianIndex::SEED_PREFIX, &[guardian_info.index]], - bump = guardian_index_swap.bump, - )] - guardian_index_swap: Account<'info, GuardianIndex>, - - // The last guardian index account. - // This gets removed, and its guardian_info(_swap) gets put into guardian_index_swap instead. - #[account( - mut, - close = authority, - seeds = [GuardianIndex::SEED_PREFIX, &[config.num_guardians - 1]], - bump = guardian_index_tail.bump, - constraint = guardian_index_tail.guardian_info == guardian_info_swap.key(), - )] - guardian_index_tail: Account<'info, GuardianIndex>, - /// CHECK: Required authority to pause contract. This pubkey lives in `GuardianInfo`. guardian: AccountInfo<'info>, } pub fn remove_guardian(ctx: Context) -> Result<()> { - ctx.accounts.guardian_index_swap.guardian_info = ctx.accounts.guardian_index_tail.guardian_info; - ctx.accounts.guardian_info_swap.index = ctx.accounts.guardian_info.index; ctx.accounts.config.num_guardians -= 1; Ok(()) } diff --git a/cross-chain/solana/programs/tbtc/src/state/guardian_index.rs b/cross-chain/solana/programs/tbtc/src/state/guardian_index.rs deleted file mode 100644 index d10bcc196..000000000 --- a/cross-chain/solana/programs/tbtc/src/state/guardian_index.rs +++ /dev/null @@ -1,12 +0,0 @@ -use anchor_lang::prelude::*; - -#[account] -#[derive(Debug, InitSpace)] -pub struct GuardianIndex { - pub guardian_info: Pubkey, - pub bump: u8, -} - -impl GuardianIndex { - pub const SEED_PREFIX: &'static [u8] = b"guardian-index"; -} diff --git a/cross-chain/solana/programs/tbtc/src/state/guardian_info.rs b/cross-chain/solana/programs/tbtc/src/state/guardian_info.rs index 697d5333e..34f1492ba 100644 --- a/cross-chain/solana/programs/tbtc/src/state/guardian_info.rs +++ b/cross-chain/solana/programs/tbtc/src/state/guardian_info.rs @@ -4,7 +4,6 @@ use anchor_lang::prelude::*; #[derive(Debug, InitSpace)] pub struct GuardianInfo { pub guardian: Pubkey, - pub index: u8, pub bump: u8, } diff --git a/cross-chain/solana/programs/tbtc/src/state/mod.rs b/cross-chain/solana/programs/tbtc/src/state/mod.rs index cb61742a2..dffd4099b 100644 --- a/cross-chain/solana/programs/tbtc/src/state/mod.rs +++ b/cross-chain/solana/programs/tbtc/src/state/mod.rs @@ -1,9 +1,6 @@ mod config; pub use config::*; -mod guardian_index; -pub use guardian_index::*; - mod guardian_info; pub use guardian_info::*; diff --git a/cross-chain/solana/tests/01__tbtc.ts b/cross-chain/solana/tests/01__tbtc.ts index f50e193f3..f69c0a820 100644 --- a/cross-chain/solana/tests/01__tbtc.ts +++ b/cross-chain/solana/tests/01__tbtc.ts @@ -224,39 +224,20 @@ function getGuardianPDA( ); } -function getGuardianIndexPDA( - program: Program, - index -): [anchor.web3.PublicKey, number] { - let indexArr = new Uint8Array(1); - indexArr[0] = index; - return web3.PublicKey.findProgramAddressSync( - [ - Buffer.from('guardian-index'), - indexArr, - ], - program.programId - ); -} - async function addGuardian( program: Program, authority, - guardian + guardian, + payer ): Promise { const [config,] = getConfigPDA(program); const [guardianInfoPDA, _] = getGuardianPDA(program, guardian); - - let configState = await program.account.config.fetch(config); - - const [guardianIndexPDA, __] = getGuardianIndexPDA(program, configState.numGuardians); await program.methods .addGuardian() .accounts({ config, authority: authority.publicKey, guardianInfo: guardianInfoPDA, - guardianIndex: guardianIndexPDA, guardian: guardian.publicKey, }) .signers(maybeAuthorityAnd(authority, [])) @@ -266,22 +247,13 @@ async function addGuardian( async function checkGuardian( program: Program, - guardian, - expectedIndex + guardian ) { const [guardianInfoPDA, bump] = getGuardianPDA(program, guardian); let guardianInfo = await program.account.guardianInfo.fetch(guardianInfoPDA); - const [guardianIndexPDA, indexBump] = getGuardianIndexPDA(program, guardianInfo.index); - let guardianIndex = await program.account.guardianIndex.fetch(guardianIndexPDA); - expect(guardianInfo.guardian).to.eql(guardian.publicKey); expect(guardianInfo.bump).to.equal(bump); - - expect(guardianIndex.guardianInfo).to.eql(guardianInfoPDA); - expect(guardianIndex.bump).to.equal(indexBump); - - expect(guardianInfo.index).to.equal(expectedIndex); } async function removeGuardian( @@ -291,24 +263,12 @@ async function removeGuardian( guardianInfo ) { const [config,] = getConfigPDA(program); - const configState = await program.account.config.fetch(config); - const guardianInfoState = await program.account.guardianInfo.fetch(guardianInfo); - - const [lastIndex,] = getGuardianIndexPDA(program, configState.numGuardians - 1); - const [swapIndex,] = getGuardianIndexPDA(program, guardianInfoState.index); - - const lastIndexState = await program.account.guardianIndex.fetch(lastIndex); - const swapInfo = lastIndexState.guardianInfo; - await program.methods .removeGuardian() .accounts({ config, authority: authority.publicKey, guardianInfo: guardianInfo, - guardianInfoSwap: swapInfo, - guardianIndexSwap: swapIndex, - guardianIndexTail: lastIndex, guardian: guardian.publicKey }) .signers(maybeAuthorityAnd(authority, [])) @@ -622,12 +582,12 @@ describe("tbtc", () => { it('add guardian', async () => { await checkState(program, authority, 0, 0, 1500); - await addGuardian(program, authority, guardianKeys); - await checkGuardian(program, guardianKeys, 0); + await addGuardian(program, authority, guardianKeys, authority); + await checkGuardian(program, guardianKeys); await checkState(program, authority, 0, 1, 1500); try { - await addGuardian(program, impostorKeys, guardian2Keys); + await addGuardian(program, impostorKeys, guardian2Keys, authority); chai.assert(false, "should've failed but didn't"); } catch (_err) { expect(_err).to.be.instanceOf(AnchorError); @@ -639,8 +599,8 @@ describe("tbtc", () => { it('remove guardian', async () => { await checkState(program, authority, 0, 1, 1500); - const [guardianInfoPDA,] = getGuardianPDA(program, guardianKeys); - await checkGuardian(program, guardianKeys, 0); + const [guardianInfoPDA, _] = getGuardianPDA(program, guardianKeys); + await checkGuardian(program, guardianKeys); try { await removeGuardian(program, impostorKeys, guardianKeys, guardianInfoPDA); @@ -659,25 +619,16 @@ describe("tbtc", () => { await removeGuardian(program, authority, guardianKeys, guardianInfoPDA); chai.assert(false, "should've failed but didn't"); } catch (_err) { - expect(_err.message).to.include('Account does not exist or has no data'); + expect(_err).to.be.instanceOf(AnchorError); + const err: AnchorError = _err; + expect(err.error.errorCode.code).to.equal('AccountNotInitialized'); + expect(err.program.equals(program.programId)).is.true; } - - await addGuardian(program, authority, guardian2Keys); - await addGuardian(program, authority, guardianKeys); - await checkGuardian(program, guardian2Keys, 0); - await checkGuardian(program, guardianKeys, 1); - - const [guardian2InfoPDA,] = getGuardianPDA(program, guardian2Keys); - await removeGuardian(program, authority, guardian2Keys, guardian2InfoPDA); - - await checkGuardian(program, guardianKeys, 0); - - await removeGuardian(program, authority, guardianKeys, guardianInfoPDA); }); it('pause', async () => { await checkState(program, authority, 0, 0, 1500); - await addGuardian(program, authority, guardianKeys); + await addGuardian(program, authority, guardianKeys, authority); await checkPaused(program, false); await pause(program, guardianKeys); await checkPaused(program, true); @@ -724,9 +675,9 @@ describe("tbtc", () => { it('use two guardians', async () => { await checkState(program, authority, 1, 1, 1500); const [guardianInfoPDA, _] = getGuardianPDA(program, guardianKeys); - await checkGuardian(program, guardianKeys, 0); - await addGuardian(program, authority, guardian2Keys); - await checkGuardian(program, guardian2Keys, 1); + await checkGuardian(program, guardianKeys); + await addGuardian(program, authority, guardian2Keys, authority); + await checkGuardian(program, guardian2Keys); await pause(program, guardianKeys);