bridge: check quorum
This commit is contained in:
parent
d317164345
commit
1d960405d1
|
@ -20,6 +20,7 @@ COPY Cargo.lock .
|
|||
RUN --mount=type=cache,target=/usr/local/cargo,from=rust,source=/usr/local/cargo \
|
||||
--mount=type=cache,target=/root/.cache \
|
||||
--mount=type=cache,target=bridge/target \
|
||||
--mount=type=cache,target=target \
|
||||
./do.sh build bridge && \
|
||||
mkdir -p /opt/solana/deps && \
|
||||
cp target/bpfel-unknown-unknown/release/spl_bridge.so /opt/solana/deps
|
||||
|
|
|
@ -34,6 +34,8 @@ pub type ForeignAddress = [u8; FOREIGN_ADDRESS_SIZE];
|
|||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct InitializePayload {
|
||||
/// number of initial guardians
|
||||
pub len_guardians: u8,
|
||||
/// guardians that are allowed to sign mints
|
||||
pub initial_guardian: [[u8; 20]; 20],
|
||||
/// config for the bridge
|
||||
|
@ -232,6 +234,7 @@ pub fn initialize(
|
|||
}
|
||||
let data = BridgeInstruction::Initialize(InitializePayload {
|
||||
config: *config,
|
||||
len_guardians: initial_guardian.len() as u8,
|
||||
initial_guardian: initial_g,
|
||||
})
|
||||
.serialize()?;
|
||||
|
|
|
@ -36,6 +36,7 @@ impl Bridge {
|
|||
Self::process_initialize(
|
||||
program_id,
|
||||
accounts,
|
||||
payload.len_guardians,
|
||||
payload.initial_guardian,
|
||||
payload.config,
|
||||
)
|
||||
|
@ -69,6 +70,7 @@ impl Bridge {
|
|||
pub fn process_initialize(
|
||||
program_id: &Pubkey,
|
||||
accounts: &[AccountInfo],
|
||||
len_guardians: u8,
|
||||
initial_guardian_key: [[u8; 20]; 20],
|
||||
config: BridgeConfig,
|
||||
) -> ProgramResult {
|
||||
|
@ -115,6 +117,10 @@ impl Bridge {
|
|||
return Err(Error::AlreadyExists.into());
|
||||
}
|
||||
|
||||
if len_guardians > 20 {
|
||||
return Err(ProgramError::InvalidInstructionData);
|
||||
}
|
||||
|
||||
// Initialize bridge params
|
||||
bridge.is_initialized = true;
|
||||
bridge.guardian_set_index = 0;
|
||||
|
@ -125,6 +131,7 @@ impl Bridge {
|
|||
guardian_info.index = 0;
|
||||
guardian_info.creation_time = clock.unix_timestamp.as_();
|
||||
guardian_info.keys = initial_guardian_key;
|
||||
guardian_info.len_keys = len_guardians;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -432,7 +439,7 @@ impl Bridge {
|
|||
}
|
||||
|
||||
// Verify VAA signature
|
||||
if !vaa.verify(&guardian_set.keys) {
|
||||
if !vaa.verify(&guardian_set.keys[..guardian_set.len_keys as usize]) {
|
||||
return Err(Error::InvalidVAASignature.into());
|
||||
}
|
||||
|
||||
|
@ -538,12 +545,19 @@ impl Bridge {
|
|||
return Err(Error::AlreadyExists.into());
|
||||
}
|
||||
|
||||
if b.new_keys.len() > 20 {
|
||||
return Err(Error::InvalidVAAFormat.into());
|
||||
}
|
||||
|
||||
// Set values on the new guardian set
|
||||
guardian_set_new.is_initialized = true;
|
||||
guardian_set_new.index = b.new_index;
|
||||
let mut new_guardians = [[0u8; 20]; 20];
|
||||
new_guardians.copy_from_slice(b.new_keys.as_slice());
|
||||
for (i, guardian) in b.new_keys.iter().enumerate() {
|
||||
new_guardians[i] = *guardian
|
||||
}
|
||||
guardian_set_new.keys = new_guardians;
|
||||
guardian_set_new.len_keys = b.new_keys.len() as u8;
|
||||
guardian_set_new.creation_time = clock.unix_timestamp as u32;
|
||||
|
||||
// Update the bridge guardian set id
|
||||
|
@ -829,7 +843,7 @@ impl Bridge {
|
|||
None,
|
||||
Some(&Self::derive_bridge_id(program_id)?),
|
||||
0,
|
||||
8,
|
||||
18,
|
||||
)?;
|
||||
invoke_signed(&ix, accounts, &[])
|
||||
}
|
||||
|
@ -906,6 +920,8 @@ impl Bridge {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
|
||||
use solana_sdk::{
|
||||
account::Account, account_info::create_is_signer_account_infos, instruction::Instruction,
|
||||
};
|
||||
|
@ -918,7 +934,6 @@ mod tests {
|
|||
use crate::instruction::{initialize, TransferOutPayloadRaw};
|
||||
|
||||
use super::*;
|
||||
use std::str::FromStr;
|
||||
|
||||
const TOKEN_PROGRAM_ID: Pubkey = Pubkey::new_from_array([1u8; 32]);
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@ pub struct Fee {
|
|||
pub struct GuardianSet {
|
||||
/// index of the set
|
||||
pub index: u32,
|
||||
/// number of keys stored
|
||||
pub len_keys: u8,
|
||||
/// public key of the threshold schnorr set
|
||||
pub keys: [[u8; 20]; 20],
|
||||
/// creation time
|
||||
|
@ -79,6 +81,7 @@ impl IsInitialized for TransferOutProposal {
|
|||
}
|
||||
|
||||
pub const TRANSFER_OUT_PROPOSAL_SIZE: usize = 1139;
|
||||
|
||||
impl TransferOutProposal {
|
||||
pub fn matches_vaa(&self, b: &BodyTransfer) -> bool {
|
||||
return b.amount == self.amount
|
||||
|
|
|
@ -56,6 +56,11 @@ impl VAA {
|
|||
};
|
||||
let hash = h.finalize().into();
|
||||
|
||||
// Check quorum
|
||||
if self.signatures.len() < ((guardian_keys.len() as f32 / 4f32 * 3f32).ceil() as usize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for sig in self.signatures.iter() {
|
||||
let ecrecover_input = EcrecoverInput::new(sig.r, sig.s, sig.v, hash);
|
||||
let res = match sol_syscall_ecrecover(&ecrecover_input) {
|
||||
|
@ -122,7 +127,6 @@ impl VAA {
|
|||
v.write_u8(payload.action_id())?;
|
||||
|
||||
let payload_data = payload.serialize()?;
|
||||
v.write_u8(payload_data.len() as u8)?;
|
||||
v.write(payload_data.as_slice())?;
|
||||
|
||||
Ok(v.into_inner())
|
||||
|
|
|
@ -28,7 +28,7 @@ profile=bpfel-unknown-unknown/release
|
|||
perform_action() {
|
||||
set -e
|
||||
projectDir="$PWD"/$2
|
||||
targetDir="$projectDir"/target
|
||||
targetDir=target
|
||||
case "$1" in
|
||||
build)
|
||||
if [[ -f "$projectDir"/Xargo.toml ]]; then
|
||||
|
|
Loading…
Reference in New Issue