bridge: check quorum

This commit is contained in:
Hendrik Hofstadt 2020-08-21 12:43:31 +02:00
parent d317164345
commit 1d960405d1
6 changed files with 32 additions and 6 deletions

View File

@ -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

View File

@ -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()?;

View File

@ -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]);

View File

@ -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

View File

@ -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())

View File

@ -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