Update tests to use initial guardian set.

Change-Id: I11cd5d5bc518ce69e12a289211f21b992eef9ffe
This commit is contained in:
Reisen 2021-06-29 13:02:57 +00:00
parent 44384e635f
commit 30e8419f93
4 changed files with 177 additions and 92 deletions

View File

@ -18,7 +18,6 @@ use solitaire::{
pub type FeeCollector<'a> = Derive<Info<'a>, "fee_collector">; pub type FeeCollector<'a> = Derive<Info<'a>, "fee_collector">;
pub type Bridge<'a, const State: AccountState> = Derive<Data<'a, BridgeData, { State }>, "Bridge">; pub type Bridge<'a, const State: AccountState> = Derive<Data<'a, BridgeData, { State }>, "Bridge">;
pub type GuardianSet<'b, const State: AccountState> = Data<'b, types::GuardianSetData, { State }>; pub type GuardianSet<'b, const State: AccountState> = Data<'b, types::GuardianSetData, { State }>;
pub struct GuardianSetDerivationData { pub struct GuardianSetDerivationData {

View File

@ -85,7 +85,7 @@ pub fn post_message(
emitter: Pubkey, emitter: Pubkey,
nonce: u32, nonce: u32,
payload: Vec<u8>, payload: Vec<u8>,
) -> solitaire::Result<Instruction> { ) -> solitaire::Result<(Pubkey, Instruction)> {
let bridge = Bridge::<'_, { AccountState::Uninitialized }>::key(None, &program_id); let bridge = Bridge::<'_, { AccountState::Uninitialized }>::key(None, &program_id);
let fee_collector = FeeCollector::<'_>::key(None, &program_id); let fee_collector = FeeCollector::<'_>::key(None, &program_id);
let sequence = Sequence::<'_>::key( let sequence = Sequence::<'_>::key(
@ -104,7 +104,7 @@ pub fn post_message(
&program_id, &program_id,
); );
Ok(Instruction { Ok((message, Instruction {
program_id, program_id,
accounts: vec![ accounts: vec![
@ -124,7 +124,7 @@ pub fn post_message(
payload: payload.clone(), payload: payload.clone(),
}) })
.try_to_vec()?, .try_to_vec()?,
}) }))
} }
pub fn verify_signatures( pub fn verify_signatures(
@ -255,7 +255,7 @@ pub fn upgrade_guardian_set(
&ClaimDerivationData { &ClaimDerivationData {
emitter_address: emitter.to_bytes(), emitter_address: emitter.to_bytes(),
emitter_chain: 1, emitter_chain: 1,
sequence: 0, sequence: 1,
}, },
&program_id, &program_id,
); );

View File

@ -121,12 +121,24 @@ mod helpers {
); );
} }
pub fn initialize(client: &RpcClient, program: &Pubkey, payer: &Keypair) { pub fn initialize(
client: &RpcClient,
program: &Pubkey,
payer: &Keypair,
initial_guardians: &[[u8; 20]],
) {
execute( execute(
client, client,
payer, payer,
&[payer], &[payer],
&[instructions::initialize(*program, payer.pubkey(), 500, 2_000_000_000).unwrap()], &[instructions::initialize(
*program,
payer.pubkey(),
500,
2_000_000_000,
initial_guardians,
)
.unwrap()],
); );
} }
@ -135,26 +147,24 @@ mod helpers {
program: &Pubkey, program: &Pubkey,
payer: &Keypair, payer: &Keypair,
emitter: &Keypair, emitter: &Keypair,
sequence: u64, nonce: u32,
data: Vec<u8>, data: Vec<u8>,
) { ) -> Pubkey {
// Transfer money into the fee collector as it needs a balance/must exist. // Transfer money into the fee collector as it needs a balance/must exist.
let fee_collector = FeeCollector::<'_>::key(None, program); let fee_collector = FeeCollector::<'_>::key(None, program);
transfer(client, payer, &fee_collector, 1000000); transfer(client, payer, &fee_collector, 100_000_000_000);
let (message_key, instruction) = instructions::post_message(*program, payer.pubkey(), emitter.pubkey(), nonce, data)
.unwrap();
execute( execute(
client, client,
payer, payer,
&[payer, emitter], &[payer, emitter],
&[instructions::post_message( &[instruction],
*program,
payer.pubkey(),
emitter.pubkey(),
0,
data,
)
.unwrap()],
); );
message_key
} }
pub fn verify_signatures( pub fn verify_signatures(
@ -188,6 +198,7 @@ mod helpers {
program: &Pubkey, program: &Pubkey,
payer: &Keypair, payer: &Keypair,
vaa: PostVAAData, vaa: PostVAAData,
guardian_set_index: u32,
) { ) {
execute( execute(
client, client,
@ -196,8 +207,90 @@ mod helpers {
&[instructions::post_vaa( &[instructions::post_vaa(
*program, *program,
payer.pubkey(), payer.pubkey(),
*emitter,
guardian_set_index,
vaa, vaa,
)], )],
); );
} }
pub fn upgrade_contract(
client: &RpcClient,
program: &Pubkey,
payer: &Keypair,
payload_message: Pubkey,
spill: Pubkey,
) {
execute(
client,
payer,
&[payer],
&[instructions::upgrade_contract(
*program,
payer.pubkey(),
payload_message,
spill,
)],
);
}
pub fn upgrade_guardian_set(
client: &RpcClient,
program: &Pubkey,
payer: &Keypair,
payload_message: Pubkey,
emitter: Pubkey,
old_index: u32,
new_index: u32,
) {
execute(
client,
payer,
&[payer],
&[instructions::upgrade_guardian_set(
*program,
payer.pubkey(),
payload_message,
emitter,
old_index,
new_index,
)],
);
}
pub fn set_fees(
client: &RpcClient,
program: &Pubkey,
payer: &Keypair,
fee: u32,
) {
execute(
client,
payer,
&[payer],
&[instructions::set_fees(
*program,
payer.pubkey(),
fee,
)],
);
}
pub fn transfer_fees(
client: &RpcClient,
program: &Pubkey,
payer: &Keypair,
recipient: &Pubkey,
) {
execute(
client,
payer,
&[payer],
&[instructions::transfer_fees(
*program,
payer.pubkey(),
*recipient,
)],
);
}
} }

View File

@ -1,7 +1,7 @@
#![allow(warnings)] #![allow(warnings)]
use borsh::BorshSerialize; use borsh::BorshSerialize;
use secp256k1::{Message}; use secp256k1::Message;
use solana_client::rpc_client::RpcClient; use solana_client::rpc_client::RpcClient;
use solana_program::{ use solana_program::{
@ -34,10 +34,12 @@ use byteorder::{
WriteBytesExt, WriteBytesExt,
}; };
use std::convert::TryInto; use std::{
use std::io::{ convert::TryInto,
io::{
Cursor, Cursor,
Write, Write,
},
}; };
use std::time::{ use std::time::{
@ -52,6 +54,7 @@ use bridge::{
instruction, instruction,
types::{ types::{
BridgeConfig, BridgeConfig,
GovernancePayloadGuardianSetChange,
PostedMessage, PostedMessage,
PostedMessageData, PostedMessageData,
SequenceTracker, SequenceTracker,
@ -60,62 +63,76 @@ use bridge::{
Initialize, Initialize,
PostVAAData, PostVAAData,
Signature, Signature,
SerializePayload,
}; };
mod common; mod common;
/// Test messages coming from another chain other than Solana.
#[test]
fn test_alien_chain_messages() {
}
/// Ethereum Address (Keccak hashed Public Key)
const INITIAL_PUBLIC: [u8; 20] = [
0x1d, 0x72, 0x87, 0x7e, 0xb2, 0xd8, 0x98, 0x73, 0x8a, 0xfe, 0x94, 0xc6, 0x10, 0x11, 0x52, 0xed,
0xe0, 0x43, 0x5d, 0xe9,
];
/// Secp256k1 Secret Key, used as the single initial guardian for testing.
const INITIAL_SECRET: [u8; 32] = [
0x99, 0x70, 0x1c, 0x80, 0x5e, 0xf9, 0x38, 0xe1, 0x3f, 0x0e, 0x48, 0xf0, 0x9e, 0x2c, 0x32, 0x78,
0x91, 0xc1, 0xd8, 0x47, 0x29, 0xd1, 0x52, 0xf3, 0x01, 0xe7, 0xe6, 0x2c, 0xbf, 0x1f, 0x91, 0xc9,
];
#[test] #[test]
fn test_bridge_messages() { fn test_bridge_messages() {
// Data we want to verify exists, wrapped in a message the guardians can process.
let nonce = 12397;
let data = b"Prove Me".to_vec();
// Initialize a wormhole bridge on Solana to test with.
let (ref payer, ref client, ref program) = common::setup(); let (ref payer, ref client, ref program) = common::setup();
// Emitting Entity needs a keypair for signing. // Keypair representing the emitting entity for our messages.
let emitter = Keypair::new(); let emitter = Keypair::new();
// Data we want to verify exists. // Initialize the Bridge.
let data = vec![]; common::initialize(client, program, payer, &[INITIAL_PUBLIC]);
let message = create_message(data.clone());
// Initialize the Bridge // Post the message, publishing the data for guardian consumption.
common::initialize( common::post_message(client, program, payer, &emitter, nonce, data.clone());
// Emulate Guardian behaviour, verifying the data and publishing signatures/VAA.
let (vaa, body, body_hash, secret_key) = guardian_sign_round(&emitter, data.clone(), nonce);
common::verify_signatures(client, program, payer, body, body_hash, secret_key);
common::post_vaa(client, program, payer, &emitter.pubkey(), vaa, 0);
// Upgrade the guardian set with a new set of guardians.
let nonce = 12398;
let data = update_guardian_set(1, &[INITIAL_PUBLIC]);
let message_key = common::post_message(client, program, payer, &emitter, nonce, data.clone());
common::upgrade_guardian_set(
client, client,
program, program,
payer, payer,
message_key,
emitter.pubkey(),
0,
1,
); );
}
// Post a Message fn update_guardian_set(
common::post_message( index: u32,
client, keys: &[[u8; 20]],
program, ) -> Vec<u8> {
payer, let mut v = Cursor::new(Vec::new());
&emitter, v.write_u32::<BigEndian>(index).unwrap();
message.0.sequence, v.write_u8(keys.len() as u8).unwrap();
message.0.payload, keys.iter().map(|key| v.write(key));
); v.into_inner()
// Guardians sign, verify, and we produce VAA data here.
let (vaa, body, body_hash, secret_key) = guardian_sign_round(
&emitter,
data.clone(),
);
common::verify_signatures(
client,
program,
payer,
body,
body_hash,
secret_key,
);
// Post VAA
common::post_vaa(
client,
program,
payer,
vaa,
);
// Did it actually work?
} }
/// A utility function for emulating what the guardians should be doing, I.E, detecting a message /// A utility function for emulating what the guardians should be doing, I.E, detecting a message
@ -123,13 +140,13 @@ fn test_bridge_messages() {
fn guardian_sign_round( fn guardian_sign_round(
emitter: &Keypair, emitter: &Keypair,
data: Vec<u8>, data: Vec<u8>,
nonce: u32,
) -> (PostVAAData, Vec<u8>, [u8; 32], secp256k1::SecretKey) { ) -> (PostVAAData, Vec<u8>, [u8; 32], secp256k1::SecretKey) {
let mut vaa = PostVAAData { let mut vaa = PostVAAData {
version: 0, version: 0,
guardian_set_index: 0, guardian_set_index: 0,
// Body part // Body part
nonce: 0,
emitter_chain: 1, emitter_chain: 1,
emitter_address: emitter.pubkey().to_bytes(), emitter_address: emitter.pubkey().to_bytes(),
sequence: 0, sequence: 0,
@ -138,6 +155,7 @@ fn guardian_sign_round(
.duration_since(SystemTime::UNIX_EPOCH) .duration_since(SystemTime::UNIX_EPOCH)
.unwrap() .unwrap()
.as_secs() as u32, .as_secs() as u32,
nonce,
}; };
// Hash data, the thing we wish to actually sign. // Hash data, the thing we wish to actually sign.
@ -147,17 +165,13 @@ fn guardian_sign_round(
v.write_u32::<BigEndian>(vaa.nonce).unwrap(); v.write_u32::<BigEndian>(vaa.nonce).unwrap();
v.write_u16::<BigEndian>(vaa.emitter_chain).unwrap(); v.write_u16::<BigEndian>(vaa.emitter_chain).unwrap();
v.write(&vaa.emitter_address).unwrap(); v.write(&vaa.emitter_address).unwrap();
v.write_u64::<BigEndian>(vaa.sequence).unwrap();
v.write(&vaa.payload).unwrap(); v.write(&vaa.payload).unwrap();
v.into_inner() v.into_inner()
}; };
// Public Key: 0x1d72877eb2d898738afe94c6101152ede0435de9 // Public Key: 0x1d72877eb2d898738afe94c6101152ede0435de9
let secret_key = secp256k1::SecretKey::parse(&[ let secret_key = secp256k1::SecretKey::parse(&INITIAL_SECRET).unwrap();
0x99, 0x70, 0x1c, 0x80, 0x5e, 0xf9, 0x38, 0xe1, 0x3f, 0x0e, 0x48, 0xf0, 0x9e, 0x2c, 0x32,
0x78, 0x91, 0xc1, 0xd8, 0x47, 0x29, 0xd1, 0x52, 0xf3, 0x01, 0xe7, 0xe6, 0x2c, 0xbf, 0x1f,
0x91, 0xc9
]).unwrap();
let public_key = secp256k1::PublicKey::from_secret_key(&secret_key); let public_key = secp256k1::PublicKey::from_secret_key(&secret_key);
println!("{}", hex::encode(&public_key.serialize())); println!("{}", hex::encode(&public_key.serialize()));
@ -170,10 +184,7 @@ fn guardian_sign_round(
}; };
// Sign the body hash of the VAA. // Sign the body hash of the VAA.
let sig = secp256k1::sign( let sig = secp256k1::sign(&Message::parse(&body_hash), &secret_key);
&Message::parse(&body_hash),
&secret_key,
);
// Insert signature into VAA. // Insert signature into VAA.
let signature = sig.0.serialize(); let signature = sig.0.serialize();
@ -186,21 +197,3 @@ fn guardian_sign_round(
(vaa, body, body_hash, secret_key) (vaa, body, body_hash, secret_key)
} }
fn create_message(data: Vec<u8>) -> PostedMessage {
PostedMessage(PostedMessageData {
vaa_version: 0,
vaa_time: 0,
vaa_signature_account: Pubkey::new_unique(),
nonce: 0,
sequence: 0,
emitter_chain: 1,
emitter_address: [0u8; 32],
payload: data,
submission_time: SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs() as u32,
})
}