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.
|
/// 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,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue