Add Sequence tracker and test initialize
Change-Id: I2ecb360f498fe056332690937c0556448bb286f1
This commit is contained in:
parent
007098aaec
commit
0d637482d4
|
@ -150,17 +150,9 @@ mod helpers {
|
|||
}
|
||||
|
||||
/// Fetch account data, the loop is there to re-attempt until data is available.
|
||||
pub fn get_account_data<T: BorshDeserialize>(
|
||||
client: &RpcClient,
|
||||
account: &Pubkey,
|
||||
) -> 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
|
||||
pub fn get_account_data<T: BorshDeserialize>(client: &RpcClient, account: &Pubkey) -> T {
|
||||
let account = client.get_account(account).unwrap();
|
||||
T::try_from_slice(&account.data).unwrap()
|
||||
}
|
||||
|
||||
/// Generate `count` secp256k1 private keys, along with their ethereum-styled public key
|
||||
|
@ -260,6 +252,8 @@ mod helpers {
|
|||
program: &Pubkey,
|
||||
payer: &Keypair,
|
||||
initial_guardians: &[[u8; 20]],
|
||||
fee: u64,
|
||||
persistent_fee: u64,
|
||||
) -> Result<Signature, ClientError> {
|
||||
execute(
|
||||
client,
|
||||
|
@ -268,8 +262,8 @@ mod helpers {
|
|||
&[instructions::initialize(
|
||||
*program,
|
||||
payer.pubkey(),
|
||||
500,
|
||||
500,
|
||||
fee,
|
||||
persistent_fee,
|
||||
2_000_000_000,
|
||||
initial_guardians,
|
||||
)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![allow(warnings)]
|
||||
|
||||
use rand::Rng;
|
||||
use borsh::BorshSerialize;
|
||||
use byteorder::{
|
||||
BigEndian,
|
||||
|
@ -7,7 +8,7 @@ use byteorder::{
|
|||
};
|
||||
use hex_literal::hex;
|
||||
use secp256k1::{
|
||||
Message,
|
||||
Message as Secp256k1Message,
|
||||
PublicKey,
|
||||
SecretKey,
|
||||
};
|
||||
|
@ -48,21 +49,37 @@ use std::{
|
|||
SystemTime,
|
||||
},
|
||||
};
|
||||
use solitaire::{
|
||||
processors::seeded::Seeded,
|
||||
AccountState,
|
||||
};
|
||||
|
||||
use bridge::{
|
||||
accounts::GuardianSetDerivationData,
|
||||
accounts::{
|
||||
Bridge,
|
||||
FeeCollector,
|
||||
GuardianSet,
|
||||
GuardianSetDerivationData,
|
||||
Message,
|
||||
MessageDerivationData,
|
||||
SignatureSet,
|
||||
SignatureSetDerivationData,
|
||||
},
|
||||
instruction,
|
||||
types::{
|
||||
BridgeConfig,
|
||||
BridgeData,
|
||||
GovernancePayloadGuardianSetChange,
|
||||
GovernancePayloadSetMessageFee,
|
||||
GovernancePayloadTransferFees,
|
||||
GuardianSetData,
|
||||
PostedMessage,
|
||||
PostedMessageData,
|
||||
SequenceTracker,
|
||||
SignatureSet,
|
||||
SignatureSet as SignatureSetData,
|
||||
},
|
||||
Initialize,
|
||||
PostVAA,
|
||||
PostVAAData,
|
||||
SerializePayload,
|
||||
Signature,
|
||||
|
@ -71,7 +88,7 @@ use primitive_types::U256;
|
|||
|
||||
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,
|
||||
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,
|
||||
|
@ -81,6 +98,25 @@ const GOV_KEY: [u8; 64] = [
|
|||
struct Context {
|
||||
public: Vec<[u8; 20]>,
|
||||
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]
|
||||
|
@ -90,9 +126,13 @@ fn run_integration_tests() {
|
|||
let mut context = Context {
|
||||
public: public_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
|
||||
// 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_set_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) {
|
||||
|
@ -180,10 +253,10 @@ fn test_guardian_set_change(context: &mut Context) {
|
|||
false,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
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::post_vaa(client, program, payer, vaa).unwrap();
|
||||
|
||||
common::upgrade_guardian_set(
|
||||
client,
|
||||
program,
|
||||
|
|
Loading…
Reference in New Issue