From ae220ce9083e6e94aa9cfc729a01a333e08485f8 Mon Sep 17 00:00:00 2001 From: armaniferrante Date: Wed, 10 Mar 2021 14:17:03 -0800 Subject: [PATCH] Invalidate transactions when owner set changes --- programs/multisig/src/lib.rs | 9 +++++++++ tests/multisig.js | 4 +++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/programs/multisig/src/lib.rs b/programs/multisig/src/lib.rs index 2740001..de85e6c 100644 --- a/programs/multisig/src/lib.rs +++ b/programs/multisig/src/lib.rs @@ -39,6 +39,7 @@ pub mod multisig { multisig.owners = owners; multisig.threshold = threshold; multisig.nonce = nonce; + multisig.owner_set_seqno = 0; Ok(()) } @@ -69,6 +70,7 @@ pub mod multisig { tx.signers = signers; tx.multisig = *ctx.accounts.multisig.to_account_info().key; tx.did_execute = false; + tx.owner_set_seqno = ctx.accounts.multisig.owner_set_seqno; Ok(()) } @@ -98,6 +100,8 @@ pub mod multisig { } multisig.owners = owners; + multisig.owner_set_seqno += 1; + Ok(()) } @@ -184,6 +188,7 @@ pub struct CreateTransaction<'info> { #[derive(Accounts)] pub struct Approve<'info> { + #[account("multisig.owner_set_seqno == transaction.owner_set_seqno")] multisig: ProgramAccount<'info, Multisig>, #[account(mut, belongs_to = multisig)] transaction: ProgramAccount<'info, Transaction>, @@ -205,6 +210,7 @@ pub struct Auth<'info> { #[derive(Accounts)] pub struct ExecuteTransaction<'info> { + #[account("multisig.owner_set_seqno == transaction.owner_set_seqno")] multisig: ProgramAccount<'info, Multisig>, #[account(seeds = [ multisig.to_account_info().key.as_ref(), @@ -220,6 +226,7 @@ pub struct Multisig { owners: Vec, threshold: u64, nonce: u8, + owner_set_seqno: u32, } #[account] @@ -236,6 +243,8 @@ pub struct Transaction { signers: Vec, // Boolean ensuring one time execution. did_execute: bool, + // Owner set sequence number. + owner_set_seqno: u32, } impl From<&Transaction> for Instruction { diff --git a/tests/multisig.js b/tests/multisig.js index 4001f8d..2b9bb85 100644 --- a/tests/multisig.js +++ b/tests/multisig.js @@ -40,10 +40,10 @@ describe("multisig", () => { }); let multisigAccount = await program.account.multisig(multisig.publicKey); - assert.equal(multisigAccount.nonce, nonce); assert.ok(multisigAccount.threshold.eq(new anchor.BN(2))); assert.deepEqual(multisigAccount.owners, owners); + assert.ok(multisigAccount.ownerSetSeqno === 0); const pid = program.programId; const accounts = [ @@ -88,6 +88,7 @@ describe("multisig", () => { assert.deepEqual(txAccount.data, data); assert.ok(txAccount.multisig.equals(multisig.publicKey)); assert.equal(txAccount.didExecute, false); + assert.ok(txAccount.ownerSetSeqno === 0); // Other owner approves transactoin. await program.rpc.approve({ @@ -129,5 +130,6 @@ describe("multisig", () => { assert.equal(multisigAccount.nonce, nonce); assert.ok(multisigAccount.threshold.eq(new anchor.BN(2))); assert.deepEqual(multisigAccount.owners, newOwners); + assert.ok(multisigAccount.ownerSetSeqno === 1); }); });