Add Sequence tracker and test initialize

Change-Id: I2ecb360f498fe056332690937c0556448bb286f1
This commit is contained in:
Reisen 2021-07-07 08:48:37 +00:00 committed by Hendrik Hofstadt
parent 007098aaec
commit 0d637482d4
2 changed files with 86 additions and 19 deletions

View File

@ -150,17 +150,9 @@ mod helpers {
} }
/// Fetch account data, the loop is there to re-attempt until data is available. /// Fetch account data, the loop is there to re-attempt until data is available.
pub fn get_account_data<T: BorshDeserialize>( pub fn get_account_data<T: BorshDeserialize>(client: &RpcClient, account: &Pubkey) -> T {
client: &RpcClient, let account = client.get_account(account).unwrap();
account: &Pubkey, T::try_from_slice(&account.data).unwrap()
) -> Option<T> {
for _ in 0..5 {
if let Ok(account) = client.get_account(account) {
return Some(T::try_from_slice(&account.data).unwrap());
}
std::thread::sleep(std::time::Duration::from_millis(2000));
}
None
} }
/// Generate `count` secp256k1 private keys, along with their ethereum-styled public key /// Generate `count` secp256k1 private keys, along with their ethereum-styled public key
@ -260,6 +252,8 @@ mod helpers {
program: &Pubkey, program: &Pubkey,
payer: &Keypair, payer: &Keypair,
initial_guardians: &[[u8; 20]], initial_guardians: &[[u8; 20]],
fee: u64,
persistent_fee: u64,
) -> Result<Signature, ClientError> { ) -> Result<Signature, ClientError> {
execute( execute(
client, client,
@ -268,8 +262,8 @@ mod helpers {
&[instructions::initialize( &[instructions::initialize(
*program, *program,
payer.pubkey(), payer.pubkey(),
500, fee,
500, persistent_fee,
2_000_000_000, 2_000_000_000,
initial_guardians, initial_guardians,
) )

View File

@ -1,5 +1,6 @@
#![allow(warnings)] #![allow(warnings)]
use rand::Rng;
use borsh::BorshSerialize; use borsh::BorshSerialize;
use byteorder::{ use byteorder::{
BigEndian, BigEndian,
@ -7,7 +8,7 @@ use byteorder::{
}; };
use hex_literal::hex; use hex_literal::hex;
use secp256k1::{ use secp256k1::{
Message, Message as Secp256k1Message,
PublicKey, PublicKey,
SecretKey, SecretKey,
}; };
@ -48,21 +49,37 @@ use std::{
SystemTime, SystemTime,
}, },
}; };
use solitaire::{
processors::seeded::Seeded,
AccountState,
};
use bridge::{ use bridge::{
accounts::GuardianSetDerivationData, accounts::{
Bridge,
FeeCollector,
GuardianSet,
GuardianSetDerivationData,
Message,
MessageDerivationData,
SignatureSet,
SignatureSetDerivationData,
},
instruction, instruction,
types::{ types::{
BridgeConfig, BridgeConfig,
BridgeData,
GovernancePayloadGuardianSetChange, GovernancePayloadGuardianSetChange,
GovernancePayloadSetMessageFee, GovernancePayloadSetMessageFee,
GovernancePayloadTransferFees, GovernancePayloadTransferFees,
GuardianSetData,
PostedMessage, PostedMessage,
PostedMessageData, PostedMessageData,
SequenceTracker, SequenceTracker,
SignatureSet, SignatureSet as SignatureSetData,
}, },
Initialize, Initialize,
PostVAA,
PostVAAData, PostVAAData,
SerializePayload, SerializePayload,
Signature, Signature,
@ -71,7 +88,7 @@ use primitive_types::U256;
mod common; mod common;
const GOV_KEY: [u8; 64] = [ const GOVERNANCE_KEY: [u8; 64] = [
240, 133, 120, 113, 30, 67, 38, 184, 197, 72, 234, 99, 241, 21, 58, 225, 41, 157, 171, 44, 196, 240, 133, 120, 113, 30, 67, 38, 184, 197, 72, 234, 99, 241, 21, 58, 225, 41, 157, 171, 44, 196,
163, 134, 236, 92, 148, 110, 68, 127, 114, 177, 0, 173, 253, 199, 9, 242, 142, 201, 174, 108, 163, 134, 236, 92, 148, 110, 68, 127, 114, 177, 0, 173, 253, 199, 9, 242, 142, 201, 174, 108,
197, 18, 102, 115, 0, 31, 205, 127, 188, 191, 56, 171, 228, 20, 247, 149, 170, 141, 231, 147, 197, 18, 102, 115, 0, 31, 205, 127, 188, 191, 56, 171, 228, 20, 247, 149, 170, 141, 231, 147,
@ -81,6 +98,25 @@ const GOV_KEY: [u8; 64] = [
struct Context { struct Context {
public: Vec<[u8; 20]>, public: Vec<[u8; 20]>,
secret: Vec<SecretKey>, secret: Vec<SecretKey>,
seq: Sequencer,
}
/// Small helper to track and provide sequences during tests. This is in particular needed for
/// guardian operations that require them for derivations.
struct Sequencer {
sequences: std::collections::HashMap<[u8; 32], u64>,
}
impl Sequencer {
fn next(&mut self, emitter: [u8; 32]) -> u64 {
let entry = self.sequences.entry(emitter).or_insert(0);
*entry += 1;
*entry - 1
}
fn peek(&mut self, emitter: [u8; 32]) -> u64 {
*self.sequences.entry(emitter).or_insert(0)
}
} }
#[test] #[test]
@ -90,9 +126,13 @@ fn run_integration_tests() {
let mut context = Context { let mut context = Context {
public: public_keys, public: public_keys,
secret: secret_keys, secret: secret_keys,
seq: Sequencer {
sequences: std::collections::HashMap::new(),
},
}; };
common::initialize(client, program, payer, &*context.public.clone()); // Initialize the bridge and verify the bridges state.
test_initialize(&mut context);
// Tests are currently unhygienic as It's difficult to wrap `solana-test-validator` within the // Tests are currently unhygienic as It's difficult to wrap `solana-test-validator` within the
// integration tests so for now we work around it by simply chain-calling our tests. // integration tests so for now we work around it by simply chain-calling our tests.
@ -102,6 +142,39 @@ fn run_integration_tests() {
test_guardian_set_change_fails(&mut context); test_guardian_set_change_fails(&mut context);
test_set_fees(&mut context); test_set_fees(&mut context);
test_transfer_fees(&mut context); test_transfer_fees(&mut context);
fn test_initialize(context: &mut Context) {
let (ref payer, ref client, ref program) = common::setup();
// Use a timestamp from a few seconds earlier for testing to simulate thread::sleep();
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs() - 10;
common::initialize(client, program, payer, &*context.public.clone(), 500, 5000);
common::sync(client, payer);
// Verify the initial bridge state is as expected.
let bridge_key = Bridge::<'_, { AccountState::Uninitialized }>::key(None, &program);
let guardian_set_key = GuardianSet::<'_, { AccountState::Uninitialized }>::key(
&GuardianSetDerivationData { index: 0 },
&program,
);
// Fetch account states.
let bridge: BridgeData = common::get_account_data(client, &bridge_key);
let guardian_set: GuardianSetData = common::get_account_data(client, &guardian_set_key);
// Bridge Config should be as expected.
assert_eq!(bridge.guardian_set_index, 0);
assert_eq!(bridge.config.guardian_set_expiration_time, 2_000_000_000);
assert_eq!(bridge.config.fee, 500);
assert_eq!(bridge.config.fee_persistent, 5000);
// Guardian set account must also be as expected.
assert_eq!(guardian_set.index, 0);
assert_eq!(guardian_set.keys, context.public);
assert!(guardian_set.creation_time as u64 > now);
} }
fn test_bridge_messages(context: &mut Context) { fn test_bridge_messages(context: &mut Context) {
@ -180,10 +253,10 @@ fn test_guardian_set_change(context: &mut Context) {
false, false,
) )
.unwrap(); .unwrap();
let (vaa, body, body_hash) = common::generate_vaa(&emitter, message.clone(), nonce, 0, 1); let (vaa, body, body_hash) = common::generate_vaa(&emitter, message.clone(), nonce, 0, 1);
common::verify_signatures(client, program, payer, body, body_hash, &context.secret, 0).unwrap(); common::verify_signatures(client, program, payer, body, body_hash, &context.secret, 0).unwrap();
common::post_vaa(client, program, payer, vaa).unwrap(); common::post_vaa(client, program, payer, vaa).unwrap();
common::upgrade_guardian_set( common::upgrade_guardian_set(
client, client,
program, program,