solana/token_bridge: Add blacklisted keys

This commit is contained in:
Reisen 2022-02-02 22:01:39 +00:00 committed by Evan Gray
parent b18a6c8c2f
commit 4e13d9d49c
7 changed files with 77 additions and 4 deletions

View File

@ -22,6 +22,7 @@ use crate::{
GuardianSetMismatch, GuardianSetMismatch,
PostVAAConsensusFailed, PostVAAConsensusFailed,
PostVAAGuardianSetExpired, PostVAAGuardianSetExpired,
VAAInvalid,
}, },
}; };
use byteorder::{ use byteorder::{
@ -33,7 +34,10 @@ use serde::{
Serialize, Serialize,
}; };
use sha3::Digest; use sha3::Digest;
use solana_program::program_error::ProgramError; use solana_program::{
program_error::ProgramError,
pubkey::Pubkey,
};
use solitaire::{ use solitaire::{
processors::seeded::Seeded, processors::seeded::Seeded,
CreationLamports::Exempt, CreationLamports::Exempt,
@ -174,6 +178,26 @@ fn check_active<'r>(
Ok(()) Ok(())
} }
// Static list of invalid signature accounts that are not allowed to post VAAs.
static INVALID_SIGNATURES: &'static [&'static str; 16] = &[
"18eK1799CaNMGCUnnCt1Kq2uwKkax6T2WmtrDsZuVFQ",
"2g6NCUUPaD6AxdHPQMVLpjpAvBfKMek6dDiGUe2A6T33",
"3hYV5968hNzbqUfcvnQ6v9D5h32hEwGJn19c47N3unNj",
"76eEyhaEKs4mesjiQiu8bghvwDHNxJW3EfcpbNC78y1z",
"7PdcxSn7xk2UN5VYmKnJ2Q64PdBhbBQFf4RwHqhQCMgv",
"94wXN3z3Pph2vMVaviZSouo7oCDqt4fekvqT3FYJSrWA",
"AXe9VXd9jjXkBxSdvgj4bHSZNeqxY73sSQEsp1tnekY4",
"B2hS49B8n4Ad6cxZLoAjz7Hux7Kf17D5xUX3neDPHpug",
"BTXnYYjnfXByqJprarqzp65Yha2XwQVmg8V8KWBhr6aA",
"Bzb5G4Y8QcaMVMQq3r8q1SuKSxtgnWSFdKCEisJCbcBP",
"CJfRUQxyonG6B5mnztsNUqxknbFT89DJdrdrzV9F96mU",
"CK1j9TxWP1T5w1QzFu4vPDAbUR34mfVqvk5wziE8TzST",
"E8qKJMwzBCiHCHUmBEcL631kN5CjfsHNx24osFLfHg69",
"EtMw1nQ4AQaH53RjYz3pRk12rrqWjcYjPDETphYJzmCX",
"EVNwqfgkUnJoMqBqiHgDfa3TLZPQocX1hpcbAXbpcSLv",
"FixSiDfTxvoy5Zgjp5KdFU8U23ChwCxPWY3WTkmMW2fU",
];
/// The signatures in this instruction must be from the right guardian set. /// The signatures in this instruction must be from the right guardian set.
#[inline(always)] #[inline(always)]
fn check_valid_sigs<'r>( fn check_valid_sigs<'r>(
@ -183,6 +207,12 @@ fn check_valid_sigs<'r>(
if signatures.guardian_set_index != guardian_set.index { if signatures.guardian_set_index != guardian_set.index {
return Err(GuardianSetMismatch.into()); return Err(GuardianSetMismatch.into());
} }
// Reject blacklisted signature accounts.
if INVALID_SIGNATURES.contains(&&*signatures.info().key.to_string()) {
return Err(VAAInvalid.into());
}
Ok(()) Ok(())
} }

View File

@ -23,6 +23,7 @@ pub enum Error {
PostVAAGuardianSetExpired, PostVAAGuardianSetExpired,
TooManyGuardians, TooManyGuardians,
VAAAlreadyExecuted, VAAAlreadyExecuted,
VAAInvalid,
} }
/// Errors thrown by the program will bubble up to the solitaire wrapper, which needs a way to /// Errors thrown by the program will bubble up to the solitaire wrapper, which needs a way to

View File

@ -8,6 +8,7 @@ use crate::{
InvalidGovernanceChain, InvalidGovernanceChain,
InvalidGovernanceModule, InvalidGovernanceModule,
VAAAlreadyExecuted, VAAAlreadyExecuted,
VAAInvalid,
}, },
Claim, Claim,
ClaimDerivationData, ClaimDerivationData,
@ -23,7 +24,10 @@ use serde::{
Deserialize, Deserialize,
Serialize, Serialize,
}; };
use solana_program::pubkey::Pubkey; use solana_program::{
account_info::AccountInfo,
pubkey::Pubkey,
};
use solitaire::{ use solitaire::{
processors::seeded::Seeded, processors::seeded::Seeded,
trace, trace,
@ -143,6 +147,10 @@ impl<'b, T: DeserializePayload> PayloadMessage<'b, T> {
pub fn meta(&self) -> &PostedVAAData { pub fn meta(&self) -> &PostedVAAData {
&self.0 &self.0
} }
pub fn info(&self) -> AccountInfo<'b> {
self.0.info().clone()
}
} }
#[derive(FromAccounts)] #[derive(FromAccounts)]

View File

@ -15,6 +15,7 @@ use crate::{
messages::PayloadTransfer, messages::PayloadTransfer,
types::*, types::*,
TokenBridgeError::*, TokenBridgeError::*,
INVALID_VAAS,
}; };
use bridge::{ use bridge::{
vaa::ClaimableVAA, vaa::ClaimableVAA,
@ -124,6 +125,9 @@ pub fn complete_native(
if accs.vaa.to != accs.to.info().key.to_bytes() { if accs.vaa.to != accs.to.info().key.to_bytes() {
return Err(InvalidRecipient.into()); return Err(InvalidRecipient.into());
} }
if INVALID_VAAS.contains(&&*accs.vaa.message.info().key.to_string()) {
return Err(InvalidVAA.into());
}
// Prevent vaa double signing // Prevent vaa double signing
accs.vaa.verify(ctx.program_id)?; accs.vaa.verify(ctx.program_id)?;
@ -243,6 +247,9 @@ pub fn complete_wrapped(
if accs.vaa.to != accs.to.info().key.to_bytes() { if accs.vaa.to != accs.to.info().key.to_bytes() {
return Err(InvalidRecipient.into()); return Err(InvalidRecipient.into());
} }
if INVALID_VAAS.contains(&&*accs.vaa.message.info().key.to_string()) {
return Err(InvalidVAA.into());
}
accs.vaa.verify(ctx.program_id)?; accs.vaa.verify(ctx.program_id)?;
accs.vaa.claim(ctx, accs.payer.key)?; accs.vaa.claim(ctx, accs.payer.key)?;

View File

@ -16,7 +16,9 @@ use crate::{
TokenBridgeError::{ TokenBridgeError::{
InvalidChain, InvalidChain,
InvalidMetadata, InvalidMetadata,
InvalidVAA,
}, },
INVALID_VAAS,
}; };
use bridge::{ use bridge::{
vaa::ClaimableVAA, vaa::ClaimableVAA,
@ -127,6 +129,10 @@ pub fn create_wrapped(
accs.chain_registration accs.chain_registration
.verify_derivation(ctx.program_id, &derivation_data)?; .verify_derivation(ctx.program_id, &derivation_data)?;
if INVALID_VAAS.contains(&&*accs.vaa.message.info().key.to_string()) {
return Err(InvalidVAA.into());
}
accs.vaa.verify(ctx.program_id)?; accs.vaa.verify(ctx.program_id)?;
accs.vaa.claim(ctx, accs.payer.key)?; accs.vaa.claim(ctx, accs.payer.key)?;

View File

@ -12,7 +12,9 @@ use crate::{
TokenBridgeError::{ TokenBridgeError::{
InvalidChain, InvalidChain,
InvalidGovernanceKey, InvalidGovernanceKey,
InvalidVAA,
}, },
INVALID_VAAS,
}; };
use bridge::{ use bridge::{
vaa::{ vaa::{
@ -101,9 +103,12 @@ pub fn upgrade_contract(
accs: &mut UpgradeContract, accs: &mut UpgradeContract,
_data: UpgradeContractData, _data: UpgradeContractData,
) -> Result<()> { ) -> Result<()> {
if INVALID_VAAS.contains(&&*accs.vaa.message.info().key.to_string()) {
return Err(InvalidVAA.into());
}
verify_governance(&accs.vaa)?; verify_governance(&accs.vaa)?;
accs.vaa.verify(ctx.program_id)?; accs.vaa.verify(ctx.program_id)?;
accs.vaa.claim(ctx, accs.payer.key)?; accs.vaa.claim(ctx, accs.payer.key)?;
let upgrade_ix = solana_program::bpf_loader_upgradeable::upgrade( let upgrade_ix = solana_program::bpf_loader_upgradeable::upgrade(
@ -151,12 +156,16 @@ pub struct RegisterChainData {}
pub fn register_chain( pub fn register_chain(
ctx: &ExecutionContext, ctx: &ExecutionContext,
accs: &mut RegisterChain, accs: &mut RegisterChain,
data: RegisterChainData, _data: RegisterChainData,
) -> Result<()> { ) -> Result<()> {
let derivation_data: EndpointDerivationData = (&*accs).into(); let derivation_data: EndpointDerivationData = (&*accs).into();
accs.endpoint accs.endpoint
.verify_derivation(ctx.program_id, &derivation_data)?; .verify_derivation(ctx.program_id, &derivation_data)?;
if INVALID_VAAS.contains(&&*accs.vaa.message.info().key.to_string()) {
return Err(InvalidVAA.into());
}
// Claim VAA // Claim VAA
verify_governance(&accs.vaa)?; verify_governance(&accs.vaa)?;
accs.vaa.verify(ctx.program_id)?; accs.vaa.verify(ctx.program_id)?;

View File

@ -53,6 +53,17 @@ pub use api::{
use solitaire::*; use solitaire::*;
use std::error::Error; use std::error::Error;
// Static list of invalid VAA Message accounts.
pub(crate) static INVALID_VAAS: &'static [&'static str; 7] = &[
"28Tx7c3W8rggVNyUQEAL9Uq6pUng4xJLAeLA6V8nLH1Z",
"32YEuzLCvSyHoV6NFpaTXfiAB8sHiAnYcvP2BBeLeGWq",
"427N2RrDHYooLvyWCiEiNR4KtGsGFTMuXiGwtuChWRSd",
"56Vf4Y2SCxJBf4TSR24fPF8qLHhC8ZuTJvHS6mLGWieD",
"7SzK4pmh9fM9SWLTCKmbjQC8EvDgPmtwdaBeTRztkM98",
"G2VJNjmQsz6wfVZkTUzYAB8ZzRS2hZbpUd5Cr4DTpz6t",
"GvAarWUV8khMLrTRouzBh3xSr8AeLDXxoKNJ6FgxGyg5",
];
pub enum TokenBridgeError { pub enum TokenBridgeError {
AlreadyExecuted, AlreadyExecuted,
InvalidChain, InvalidChain,
@ -66,6 +77,7 @@ pub enum TokenBridgeError {
WrongAccountOwner, WrongAccountOwner,
InvalidFee, InvalidFee,
InvalidRecipient, InvalidRecipient,
InvalidVAA,
} }
impl From<TokenBridgeError> for SolitaireError { impl From<TokenBridgeError> for SolitaireError {