common.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. #![allow(warnings)]
  2. use borsh::{
  3. BorshDeserialize,
  4. BorshSerialize,
  5. };
  6. use byteorder::{
  7. BigEndian,
  8. WriteBytesExt,
  9. };
  10. use hex_literal::hex;
  11. use secp256k1::{
  12. Message as Secp256k1Message,
  13. PublicKey,
  14. SecretKey,
  15. };
  16. use sha3::Digest;
  17. use solana_client::{
  18. client_error::ClientError,
  19. rpc_client::RpcClient,
  20. rpc_config::RpcSendTransactionConfig,
  21. };
  22. use solana_program::{
  23. borsh::try_from_slice_unchecked,
  24. hash,
  25. instruction::{
  26. AccountMeta,
  27. Instruction,
  28. },
  29. program_pack::Pack,
  30. pubkey::Pubkey,
  31. system_instruction::{
  32. self,
  33. create_account,
  34. },
  35. system_program,
  36. sysvar,
  37. };
  38. use solana_sdk::{
  39. commitment_config::CommitmentConfig,
  40. secp256k1_instruction::new_secp256k1_instruction,
  41. signature::{
  42. read_keypair_file,
  43. Keypair,
  44. Signature,
  45. Signer,
  46. },
  47. transaction::Transaction,
  48. };
  49. use std::{
  50. convert::TryInto,
  51. env,
  52. io::{
  53. Cursor,
  54. Write,
  55. },
  56. time::{
  57. Duration,
  58. SystemTime,
  59. },
  60. };
  61. use bridge::{
  62. accounts::{
  63. BridgeConfig,
  64. FeeCollector,
  65. GuardianSet,
  66. GuardianSetDerivationData,
  67. PostedVAAData,
  68. PostedVAADerivationData,
  69. Sequence,
  70. SequenceDerivationData,
  71. SequenceTracker,
  72. SignatureSet,
  73. },
  74. instruction,
  75. instructions,
  76. types::ConsistencyLevel,
  77. Initialize,
  78. InitializeData,
  79. PostMessageData,
  80. PostVAAData,
  81. UninitializedMessage,
  82. VerifySignaturesData,
  83. };
  84. use solitaire::{
  85. processors::seeded::Seeded,
  86. AccountState,
  87. };
  88. pub use helpers::*;
  89. /// Simple API wrapper for quickly preparing and sending transactions.
  90. pub fn execute(
  91. client: &RpcClient,
  92. payer: &Keypair,
  93. signers: &[&Keypair],
  94. instructions: &[Instruction],
  95. commitment_level: CommitmentConfig,
  96. ) -> Result<Signature, ClientError> {
  97. let mut transaction = Transaction::new_with_payer(instructions, Some(&payer.pubkey()));
  98. let recent_blockhash = client.get_recent_blockhash().unwrap().0;
  99. transaction.sign(&signers.to_vec(), recent_blockhash);
  100. client.send_and_confirm_transaction_with_spinner_and_config(
  101. &transaction,
  102. commitment_level,
  103. RpcSendTransactionConfig {
  104. skip_preflight: true,
  105. preflight_commitment: None,
  106. encoding: None,
  107. },
  108. )
  109. }
  110. mod helpers {
  111. use super::*;
  112. /// Initialize the test environment, spins up a solana-test-validator in the background so that
  113. /// each test has a fresh environment to work within.
  114. pub fn setup() -> (Keypair, RpcClient, Pubkey) {
  115. let payer = env::var("BRIDGE_PAYER").unwrap_or("./payer.json".to_string());
  116. let rpc_address = env::var("BRIDGE_RPC").unwrap_or("http://127.0.0.1:8899".to_string());
  117. let payer = read_keypair_file(payer).unwrap();
  118. let rpc = RpcClient::new(rpc_address);
  119. let program = env::var("BRIDGE_PROGRAM")
  120. .unwrap_or("Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o".to_string())
  121. .parse::<Pubkey>()
  122. .unwrap();
  123. (payer, rpc, program)
  124. }
  125. /// Wait for a single transaction to fully finalize, guaranteeing chain state has been
  126. /// confirmed. Useful for consistently fetching data during state checks.
  127. pub fn sync(client: &RpcClient, payer: &Keypair) {
  128. execute(
  129. client,
  130. payer,
  131. &[payer],
  132. &[system_instruction::transfer(
  133. &payer.pubkey(),
  134. &payer.pubkey(),
  135. 1,
  136. )],
  137. CommitmentConfig::finalized(),
  138. )
  139. .unwrap();
  140. }
  141. /// Fetch account data, the loop is there to re-attempt until data is available.
  142. pub fn get_account_data<T: BorshDeserialize>(client: &RpcClient, account: &Pubkey) -> T {
  143. let account = client.get_account(account).unwrap();
  144. T::try_from_slice(&account.data).unwrap()
  145. }
  146. /// Generate `count` secp256k1 private keys, along with their ethereum-styled public key
  147. /// encoding: 0x0123456789ABCDEF01234
  148. pub fn generate_keys(count: u8) -> (Vec<[u8; 20]>, Vec<SecretKey>) {
  149. use rand::Rng;
  150. use sha3::Digest;
  151. let mut rng = rand::thread_rng();
  152. // Generate Guardian Keys
  153. let secret_keys: Vec<SecretKey> = std::iter::repeat_with(|| SecretKey::random(&mut rng))
  154. .take(count as usize)
  155. .collect();
  156. (
  157. secret_keys
  158. .iter()
  159. .map(|key| {
  160. let public_key = PublicKey::from_secret_key(&key);
  161. let mut h = sha3::Keccak256::default();
  162. h.write(&public_key.serialize()[1..]).unwrap();
  163. let key: [u8; 32] = h.finalize().into();
  164. let mut address = [0u8; 20];
  165. address.copy_from_slice(&key[12..]);
  166. address
  167. })
  168. .collect(),
  169. secret_keys,
  170. )
  171. }
  172. /// Utility function for generating VAA's from message data.
  173. pub fn generate_vaa(
  174. emitter: &Keypair,
  175. data: Vec<u8>,
  176. nonce: u32,
  177. guardian_set_index: u32,
  178. emitter_chain: u16,
  179. ) -> (PostVAAData, [u8; 32], [u8; 32]) {
  180. let mut vaa = PostVAAData {
  181. version: 0,
  182. guardian_set_index,
  183. // Body part
  184. emitter_chain,
  185. emitter_address: emitter.pubkey().to_bytes(),
  186. sequence: 0,
  187. payload: data,
  188. timestamp: SystemTime::now()
  189. .duration_since(SystemTime::UNIX_EPOCH)
  190. .unwrap()
  191. .as_secs() as u32,
  192. nonce,
  193. consistency_level: ConsistencyLevel::Confirmed as u8,
  194. };
  195. // Hash data, the thing we wish to actually sign.
  196. let body = {
  197. let mut v = Cursor::new(Vec::new());
  198. v.write_u32::<BigEndian>(vaa.timestamp).unwrap();
  199. v.write_u32::<BigEndian>(vaa.nonce).unwrap();
  200. v.write_u16::<BigEndian>(vaa.emitter_chain).unwrap();
  201. v.write(&vaa.emitter_address).unwrap();
  202. v.write_u64::<BigEndian>(vaa.sequence).unwrap();
  203. v.write_u8(vaa.consistency_level).unwrap();
  204. v.write(&vaa.payload).unwrap();
  205. v.into_inner()
  206. };
  207. // Hash this body, which is expected to be the same as the hash currently stored in the
  208. // signature account, binding that set of signatures to this VAA.
  209. let body: [u8; 32] = {
  210. let mut h = sha3::Keccak256::default();
  211. h.write(body.as_slice()).unwrap();
  212. h.finalize().into()
  213. };
  214. let body_hash: [u8; 32] = {
  215. let mut h = sha3::Keccak256::default();
  216. h.write(&body).unwrap();
  217. h.finalize().into()
  218. };
  219. (vaa, body, body_hash)
  220. }
  221. pub fn transfer(
  222. client: &RpcClient,
  223. from: &Keypair,
  224. to: &Pubkey,
  225. lamports: u64,
  226. ) -> Result<Signature, ClientError> {
  227. execute(
  228. client,
  229. from,
  230. &[from],
  231. &[system_instruction::transfer(&from.pubkey(), to, lamports)],
  232. CommitmentConfig::processed(),
  233. )
  234. }
  235. pub fn initialize(
  236. client: &RpcClient,
  237. program: &Pubkey,
  238. payer: &Keypair,
  239. initial_guardians: &[[u8; 20]],
  240. fee: u64,
  241. ) -> Result<Signature, ClientError> {
  242. execute(
  243. client,
  244. payer,
  245. &[payer],
  246. &[instructions::initialize(
  247. *program,
  248. payer.pubkey(),
  249. fee,
  250. 2_000_000_000,
  251. initial_guardians,
  252. )
  253. .unwrap()],
  254. CommitmentConfig::processed(),
  255. )
  256. }
  257. pub fn post_message(
  258. client: &RpcClient,
  259. program: &Pubkey,
  260. payer: &Keypair,
  261. emitter: &Keypair,
  262. nonce: u32,
  263. data: Vec<u8>,
  264. fee: u64,
  265. ) -> Result<Pubkey, ClientError> {
  266. // Transfer money into the fee collector as it needs a balance/must exist.
  267. let fee_collector = FeeCollector::<'_>::key(None, program);
  268. let message = Keypair::new();
  269. // Capture the resulting message, later functions will need this.
  270. let instruction = instructions::post_message(
  271. *program,
  272. payer.pubkey(),
  273. emitter.pubkey(),
  274. message.pubkey(),
  275. nonce,
  276. data,
  277. ConsistencyLevel::Confirmed,
  278. )
  279. .unwrap();
  280. execute(
  281. client,
  282. payer,
  283. &[payer, emitter, &message],
  284. &[
  285. system_instruction::transfer(&payer.pubkey(), &fee_collector, fee),
  286. instruction,
  287. ],
  288. CommitmentConfig::processed(),
  289. )?;
  290. Ok(message.pubkey())
  291. }
  292. pub fn verify_signatures(
  293. client: &RpcClient,
  294. program: &Pubkey,
  295. payer: &Keypair,
  296. body: [u8; 32],
  297. secret_keys: &[SecretKey],
  298. guardian_set_version: u32,
  299. ) -> Result<Pubkey, ClientError> {
  300. let signature_set = Keypair::new();
  301. let tx_signers = &[payer, &signature_set];
  302. // Push Secp256k1 instructions for each signature we want to verify.
  303. for (i, key) in secret_keys.iter().enumerate() {
  304. // Set this signers signature position as present at 0.
  305. let mut signers = [-1; 19];
  306. signers[i] = 0;
  307. execute(
  308. client,
  309. payer,
  310. tx_signers,
  311. &vec![
  312. new_secp256k1_instruction(&key, &body),
  313. instructions::verify_signatures(
  314. *program,
  315. payer.pubkey(),
  316. guardian_set_version,
  317. signature_set.pubkey(),
  318. VerifySignaturesData { signers },
  319. )
  320. .unwrap(),
  321. ],
  322. CommitmentConfig::processed(),
  323. )?;
  324. }
  325. Ok(signature_set.pubkey())
  326. }
  327. pub fn post_vaa(
  328. client: &RpcClient,
  329. program: &Pubkey,
  330. payer: &Keypair,
  331. signature_set: Pubkey,
  332. vaa: PostVAAData,
  333. ) -> Result<Signature, ClientError> {
  334. execute(
  335. client,
  336. payer,
  337. &[payer],
  338. &[instructions::post_vaa(
  339. *program,
  340. payer.pubkey(),
  341. signature_set,
  342. vaa,
  343. )],
  344. CommitmentConfig::processed(),
  345. )
  346. }
  347. pub fn upgrade_guardian_set(
  348. client: &RpcClient,
  349. program: &Pubkey,
  350. payer: &Keypair,
  351. payload_message: Pubkey,
  352. emitter: Pubkey,
  353. old_index: u32,
  354. new_index: u32,
  355. sequence: u64,
  356. ) -> Result<Signature, ClientError> {
  357. execute(
  358. client,
  359. payer,
  360. &[payer],
  361. &[instructions::upgrade_guardian_set(
  362. *program,
  363. payer.pubkey(),
  364. payload_message,
  365. emitter,
  366. old_index,
  367. new_index,
  368. sequence,
  369. )],
  370. CommitmentConfig::processed(),
  371. )
  372. }
  373. pub fn upgrade_contract(
  374. client: &RpcClient,
  375. program: &Pubkey,
  376. payer: &Keypair,
  377. payload_message: Pubkey,
  378. emitter: Pubkey,
  379. new_contract: Pubkey,
  380. spill: Pubkey,
  381. sequence: u64,
  382. ) -> Result<Signature, ClientError> {
  383. execute(
  384. client,
  385. payer,
  386. &[payer],
  387. &[instructions::upgrade_contract(
  388. *program,
  389. payer.pubkey(),
  390. payload_message,
  391. emitter,
  392. new_contract,
  393. spill,
  394. sequence,
  395. )],
  396. CommitmentConfig::processed(),
  397. )
  398. }
  399. pub fn set_fees(
  400. client: &RpcClient,
  401. program: &Pubkey,
  402. payer: &Keypair,
  403. message: Pubkey,
  404. emitter: Pubkey,
  405. sequence: u64,
  406. ) -> Result<Signature, ClientError> {
  407. execute(
  408. client,
  409. payer,
  410. &[payer],
  411. &[instructions::set_fees(
  412. *program,
  413. payer.pubkey(),
  414. message,
  415. emitter,
  416. sequence,
  417. )],
  418. CommitmentConfig::processed(),
  419. )
  420. }
  421. pub fn transfer_fees(
  422. client: &RpcClient,
  423. program: &Pubkey,
  424. payer: &Keypair,
  425. message: Pubkey,
  426. emitter: Pubkey,
  427. recipient: Pubkey,
  428. sequence: u64,
  429. ) -> Result<Signature, ClientError> {
  430. execute(
  431. client,
  432. payer,
  433. &[payer],
  434. &[instructions::transfer_fees(
  435. *program,
  436. payer.pubkey(),
  437. message,
  438. emitter,
  439. sequence,
  440. recipient,
  441. )],
  442. CommitmentConfig::processed(),
  443. )
  444. }
  445. }