common.rs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  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. rent::Rent,
  41. secp256k1_instruction::new_secp256k1_instruction,
  42. signature::{
  43. read_keypair_file,
  44. Keypair,
  45. Signature,
  46. Signer,
  47. },
  48. transaction::Transaction,
  49. };
  50. use spl_token::state::Mint;
  51. use std::{
  52. convert::TryInto,
  53. env,
  54. io::{
  55. Cursor,
  56. Write,
  57. },
  58. time::{
  59. Duration,
  60. SystemTime,
  61. },
  62. };
  63. use token_bridge::{
  64. accounts::*,
  65. instruction,
  66. instructions,
  67. types::*,
  68. Initialize,
  69. };
  70. use solitaire::{
  71. processors::seeded::Seeded,
  72. AccountState,
  73. };
  74. pub use helpers::*;
  75. /// Simple API wrapper for quickly preparing and sending transactions.
  76. pub fn execute(
  77. client: &RpcClient,
  78. payer: &Keypair,
  79. signers: &[&Keypair],
  80. instructions: &[Instruction],
  81. commitment_level: CommitmentConfig,
  82. ) -> Result<Signature, ClientError> {
  83. let mut transaction = Transaction::new_with_payer(instructions, Some(&payer.pubkey()));
  84. let recent_blockhash = client.get_recent_blockhash().unwrap().0;
  85. transaction.sign(&signers.to_vec(), recent_blockhash);
  86. client.send_and_confirm_transaction_with_spinner_and_config(
  87. &transaction,
  88. commitment_level,
  89. RpcSendTransactionConfig {
  90. skip_preflight: true,
  91. preflight_commitment: None,
  92. encoding: None,
  93. },
  94. )
  95. }
  96. mod helpers {
  97. use bridge::types::{
  98. ConsistencyLevel,
  99. PostedVAAData,
  100. };
  101. use token_bridge::{
  102. CompleteNativeData,
  103. CompleteWrappedData,
  104. CreateWrappedData,
  105. RegisterChainData,
  106. TransferNativeData,
  107. TransferWrappedData,
  108. };
  109. use super::*;
  110. use bridge::{
  111. accounts::{
  112. FeeCollector,
  113. PostedVAADerivationData,
  114. },
  115. PostVAAData,
  116. };
  117. use std::ops::Add;
  118. use token_bridge::messages::{
  119. PayloadAssetMeta,
  120. PayloadGovernanceRegisterChain,
  121. PayloadTransfer,
  122. };
  123. /// Initialize the test environment, spins up a solana-test-validator in the background so that
  124. /// each test has a fresh environment to work within.
  125. pub fn setup() -> (Keypair, RpcClient, Pubkey, Pubkey) {
  126. let payer = env::var("BRIDGE_PAYER").unwrap_or("./payer.json".to_string());
  127. let rpc_address = env::var("BRIDGE_RPC").unwrap_or("http://127.0.0.1:8899".to_string());
  128. let payer = read_keypair_file(payer).unwrap();
  129. let rpc = RpcClient::new(rpc_address);
  130. let (program, token_program) = (
  131. env::var("BRIDGE_PROGRAM")
  132. .unwrap_or("Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o".to_string())
  133. .parse::<Pubkey>()
  134. .unwrap(),
  135. env::var("TOKEN_BRIDGE_PROGRAM")
  136. .unwrap_or("B6RHG3mfcckmrYN1UhmJzyS1XX3fZKbkeUcpJe9Sy3FE".to_string())
  137. .parse::<Pubkey>()
  138. .unwrap(),
  139. );
  140. (payer, rpc, program, token_program)
  141. }
  142. /// Wait for a single transaction to fully finalize, guaranteeing chain state has been
  143. /// confirmed. Useful for consistently fetching data during state checks.
  144. pub fn sync(client: &RpcClient, payer: &Keypair) {
  145. execute(
  146. client,
  147. payer,
  148. &[payer],
  149. &[system_instruction::transfer(
  150. &payer.pubkey(),
  151. &payer.pubkey(),
  152. 1,
  153. )],
  154. CommitmentConfig::finalized(),
  155. )
  156. .unwrap();
  157. }
  158. /// Fetch account data, the loop is there to re-attempt until data is available.
  159. pub fn get_account_data<T: BorshDeserialize>(
  160. client: &RpcClient,
  161. account: &Pubkey,
  162. ) -> Option<T> {
  163. let account = client
  164. .get_account_with_commitment(account, CommitmentConfig::processed())
  165. .unwrap();
  166. T::try_from_slice(&account.value.unwrap().data).ok()
  167. }
  168. pub fn initialize_bridge(
  169. client: &RpcClient,
  170. program: &Pubkey,
  171. payer: &Keypair,
  172. ) -> Result<Signature, ClientError> {
  173. let initial_guardians = &[[1u8; 20]];
  174. execute(
  175. client,
  176. payer,
  177. &[payer],
  178. &[bridge::instructions::initialize(
  179. *program,
  180. payer.pubkey(),
  181. 50,
  182. 2_000_000_000,
  183. initial_guardians,
  184. )
  185. .unwrap()],
  186. CommitmentConfig::processed(),
  187. )
  188. }
  189. pub fn transfer(
  190. client: &RpcClient,
  191. from: &Keypair,
  192. to: &Pubkey,
  193. lamports: u64,
  194. ) -> Result<Signature, ClientError> {
  195. execute(
  196. client,
  197. from,
  198. &[from],
  199. &[system_instruction::transfer(&from.pubkey(), to, lamports)],
  200. CommitmentConfig::processed(),
  201. )
  202. }
  203. pub fn initialize(
  204. client: &RpcClient,
  205. program: &Pubkey,
  206. payer: &Keypair,
  207. bridge: &Pubkey,
  208. ) -> Result<Signature, ClientError> {
  209. let instruction = instructions::initialize(*program, payer.pubkey(), *bridge)
  210. .expect("Could not create Initialize instruction");
  211. for account in instruction.accounts.iter().enumerate() {
  212. println!("{}: {}", account.0, account.1.pubkey);
  213. }
  214. execute(
  215. client,
  216. payer,
  217. &[payer],
  218. &[instruction],
  219. CommitmentConfig::processed(),
  220. )
  221. }
  222. pub fn attest(
  223. client: &RpcClient,
  224. program: &Pubkey,
  225. bridge: &Pubkey,
  226. payer: &Keypair,
  227. message: &Keypair,
  228. mint: Pubkey,
  229. nonce: u32,
  230. ) -> Result<Signature, ClientError> {
  231. let mint_data = Mint::unpack(
  232. &client
  233. .get_account_with_commitment(&mint, CommitmentConfig::processed())?
  234. .value
  235. .unwrap()
  236. .data,
  237. )
  238. .expect("Could not unpack Mint");
  239. let instruction = instructions::attest(
  240. *program,
  241. *bridge,
  242. payer.pubkey(),
  243. message.pubkey(),
  244. mint,
  245. nonce,
  246. )
  247. .expect("Could not create Attest instruction");
  248. for account in instruction.accounts.iter().enumerate() {
  249. println!("{}: {}", account.0, account.1.pubkey);
  250. }
  251. execute(
  252. client,
  253. payer,
  254. &[payer, message],
  255. &[instruction],
  256. CommitmentConfig::processed(),
  257. )
  258. }
  259. pub fn transfer_native(
  260. client: &RpcClient,
  261. program: &Pubkey,
  262. bridge: &Pubkey,
  263. payer: &Keypair,
  264. message: &Keypair,
  265. from: &Keypair,
  266. from_owner: &Keypair,
  267. mint: Pubkey,
  268. amount: u64,
  269. ) -> Result<Signature, ClientError> {
  270. let instruction = instructions::transfer_native(
  271. *program,
  272. *bridge,
  273. payer.pubkey(),
  274. message.pubkey(),
  275. from.pubkey(),
  276. mint,
  277. TransferNativeData {
  278. nonce: 0,
  279. amount,
  280. fee: 0,
  281. target_address: [0u8; 32],
  282. target_chain: 2,
  283. },
  284. )
  285. .expect("Could not create Transfer Native");
  286. for account in instruction.accounts.iter().enumerate() {
  287. println!("{}: {}", account.0, account.1.pubkey);
  288. }
  289. execute(
  290. client,
  291. payer,
  292. &[payer, from_owner, message],
  293. &[
  294. spl_token::instruction::approve(
  295. &spl_token::id(),
  296. &from.pubkey(),
  297. &token_bridge::accounts::AuthoritySigner::key(None, program),
  298. &from_owner.pubkey(),
  299. &[],
  300. amount,
  301. )
  302. .unwrap(),
  303. instruction,
  304. ],
  305. CommitmentConfig::processed(),
  306. )
  307. }
  308. pub fn transfer_wrapped(
  309. client: &RpcClient,
  310. program: &Pubkey,
  311. bridge: &Pubkey,
  312. payer: &Keypair,
  313. message: &Keypair,
  314. from: Pubkey,
  315. from_owner: &Keypair,
  316. token_chain: u16,
  317. token_address: Address,
  318. amount: u64,
  319. ) -> Result<Signature, ClientError> {
  320. let instruction = instructions::transfer_wrapped(
  321. *program,
  322. *bridge,
  323. payer.pubkey(),
  324. message.pubkey(),
  325. from,
  326. from_owner.pubkey(),
  327. token_chain,
  328. token_address,
  329. TransferWrappedData {
  330. nonce: 0,
  331. amount,
  332. fee: 0,
  333. target_address: [5u8; 32],
  334. target_chain: 2,
  335. },
  336. )
  337. .expect("Could not create Transfer Native");
  338. for account in instruction.accounts.iter().enumerate() {
  339. println!("{}: {}", account.0, account.1.pubkey);
  340. }
  341. execute(
  342. client,
  343. payer,
  344. &[payer, from_owner, message],
  345. &[
  346. spl_token::instruction::approve(
  347. &spl_token::id(),
  348. &from,
  349. &token_bridge::accounts::AuthoritySigner::key(None, program),
  350. &from_owner.pubkey(),
  351. &[],
  352. amount,
  353. )
  354. .unwrap(),
  355. instruction,
  356. ],
  357. CommitmentConfig::processed(),
  358. )
  359. }
  360. pub fn register_chain(
  361. client: &RpcClient,
  362. program: &Pubkey,
  363. bridge: &Pubkey,
  364. message_acc: &Pubkey,
  365. vaa: PostVAAData,
  366. payload: PayloadGovernanceRegisterChain,
  367. payer: &Keypair,
  368. ) -> Result<Signature, ClientError> {
  369. let instruction = instructions::register_chain(
  370. *program,
  371. *bridge,
  372. payer.pubkey(),
  373. *message_acc,
  374. vaa,
  375. payload,
  376. RegisterChainData {},
  377. )
  378. .expect("Could not create Transfer Native");
  379. for account in instruction.accounts.iter().enumerate() {
  380. println!("{}: {}", account.0, account.1.pubkey);
  381. }
  382. execute(
  383. client,
  384. payer,
  385. &[payer],
  386. &[instruction],
  387. CommitmentConfig::processed(),
  388. )
  389. }
  390. pub fn complete_native(
  391. client: &RpcClient,
  392. program: &Pubkey,
  393. bridge: &Pubkey,
  394. message_acc: &Pubkey,
  395. vaa: PostVAAData,
  396. payload: PayloadTransfer,
  397. payer: &Keypair,
  398. ) -> Result<Signature, ClientError> {
  399. let instruction = instructions::complete_native(
  400. *program,
  401. *bridge,
  402. payer.pubkey(),
  403. *message_acc,
  404. vaa,
  405. Pubkey::new(&payload.to[..]),
  406. None,
  407. Pubkey::new(&payload.token_address[..]),
  408. CompleteNativeData {},
  409. )
  410. .expect("Could not create Complete Native instruction");
  411. for account in instruction.accounts.iter().enumerate() {
  412. println!("{}: {}", account.0, account.1.pubkey);
  413. }
  414. execute(
  415. client,
  416. payer,
  417. &[payer],
  418. &[instruction],
  419. CommitmentConfig::processed(),
  420. )
  421. }
  422. pub fn complete_transfer_wrapped(
  423. client: &RpcClient,
  424. program: &Pubkey,
  425. bridge: &Pubkey,
  426. message_acc: &Pubkey,
  427. vaa: PostVAAData,
  428. payload: PayloadTransfer,
  429. payer: &Keypair,
  430. ) -> Result<Signature, ClientError> {
  431. let to = Pubkey::new(&payload.to[..]);
  432. let instruction = instructions::complete_wrapped(
  433. *program,
  434. *bridge,
  435. payer.pubkey(),
  436. *message_acc,
  437. vaa,
  438. payload,
  439. to,
  440. None,
  441. CompleteWrappedData {},
  442. )
  443. .expect("Could not create Complete Wrapped instruction");
  444. for account in instruction.accounts.iter().enumerate() {
  445. println!("{}: {}", account.0, account.1.pubkey);
  446. }
  447. execute(
  448. client,
  449. payer,
  450. &[payer],
  451. &[instruction],
  452. CommitmentConfig::processed(),
  453. )
  454. }
  455. pub fn create_wrapped(
  456. client: &RpcClient,
  457. program: &Pubkey,
  458. bridge: &Pubkey,
  459. message_acc: &Pubkey,
  460. vaa: PostVAAData,
  461. payload: PayloadAssetMeta,
  462. payer: &Keypair,
  463. ) -> Result<Signature, ClientError> {
  464. let instruction = instructions::create_wrapped(
  465. *program,
  466. *bridge,
  467. payer.pubkey(),
  468. *message_acc,
  469. vaa,
  470. payload,
  471. CreateWrappedData {},
  472. )
  473. .expect("Could not create Create Wrapped instruction");
  474. for account in instruction.accounts.iter().enumerate() {
  475. println!("{}: {}", account.0, account.1.pubkey);
  476. }
  477. execute(
  478. client,
  479. payer,
  480. &[payer],
  481. &[instruction],
  482. CommitmentConfig::processed(),
  483. )
  484. }
  485. pub fn create_mint(
  486. client: &RpcClient,
  487. payer: &Keypair,
  488. mint_authority: &Pubkey,
  489. mint: &Keypair,
  490. ) -> Result<Signature, ClientError> {
  491. execute(
  492. client,
  493. payer,
  494. &[payer, mint],
  495. &[
  496. solana_sdk::system_instruction::create_account(
  497. &payer.pubkey(),
  498. &mint.pubkey(),
  499. Rent::default().minimum_balance(spl_token::state::Mint::LEN),
  500. spl_token::state::Mint::LEN as u64,
  501. &spl_token::id(),
  502. ),
  503. spl_token::instruction::initialize_mint(
  504. &spl_token::id(),
  505. &mint.pubkey(),
  506. mint_authority,
  507. None,
  508. 0,
  509. )
  510. .unwrap(),
  511. ],
  512. CommitmentConfig::processed(),
  513. )
  514. }
  515. pub fn create_spl_metadata(
  516. client: &RpcClient,
  517. payer: &Keypair,
  518. metadata_account: &Pubkey,
  519. mint_authority: &Keypair,
  520. mint: &Keypair,
  521. update_authority: &Pubkey,
  522. name: String,
  523. symbol: String,
  524. ) -> Result<Signature, ClientError> {
  525. execute(
  526. client,
  527. payer,
  528. &[payer, mint_authority],
  529. &[spl_token_metadata::instruction::create_metadata_accounts(
  530. spl_token_metadata::id(),
  531. *metadata_account,
  532. mint.pubkey(),
  533. mint_authority.pubkey(),
  534. payer.pubkey(),
  535. *update_authority,
  536. name,
  537. symbol,
  538. "https://token.org".to_string(),
  539. None,
  540. 0,
  541. false,
  542. false,
  543. )],
  544. CommitmentConfig::processed(),
  545. )
  546. }
  547. pub fn create_token_account(
  548. client: &RpcClient,
  549. payer: &Keypair,
  550. token_acc: &Keypair,
  551. token_authority: Pubkey,
  552. mint: Pubkey,
  553. ) -> Result<Signature, ClientError> {
  554. execute(
  555. client,
  556. payer,
  557. &[payer, token_acc],
  558. &[
  559. solana_sdk::system_instruction::create_account(
  560. &payer.pubkey(),
  561. &token_acc.pubkey(),
  562. Rent::default().minimum_balance(spl_token::state::Account::LEN),
  563. spl_token::state::Account::LEN as u64,
  564. &spl_token::id(),
  565. ),
  566. spl_token::instruction::initialize_account(
  567. &spl_token::id(),
  568. &token_acc.pubkey(),
  569. &mint,
  570. &token_authority,
  571. )
  572. .unwrap(),
  573. ],
  574. CommitmentConfig::processed(),
  575. )
  576. }
  577. pub fn mint_tokens(
  578. client: &RpcClient,
  579. payer: &Keypair,
  580. mint_authority: &Keypair,
  581. mint: &Keypair,
  582. token_account: &Pubkey,
  583. amount: u64,
  584. ) -> Result<Signature, ClientError> {
  585. execute(
  586. client,
  587. payer,
  588. &[payer, &mint_authority],
  589. &[spl_token::instruction::mint_to(
  590. &spl_token::id(),
  591. &mint.pubkey(),
  592. token_account,
  593. &mint_authority.pubkey(),
  594. &[],
  595. amount,
  596. )
  597. .unwrap()],
  598. CommitmentConfig::processed(),
  599. )
  600. }
  601. /// Utility function for generating VAA's from message data.
  602. pub fn generate_vaa(
  603. emitter: Address,
  604. emitter_chain: u16,
  605. data: Vec<u8>,
  606. nonce: u32,
  607. sequence: u64,
  608. ) -> (PostVAAData, [u8; 32], [u8; 32]) {
  609. let mut vaa = PostVAAData {
  610. version: 0,
  611. guardian_set_index: 0,
  612. // Body part
  613. emitter_chain,
  614. emitter_address: emitter,
  615. sequence,
  616. payload: data,
  617. timestamp: SystemTime::now()
  618. .duration_since(SystemTime::UNIX_EPOCH)
  619. .unwrap()
  620. .as_secs() as u32,
  621. nonce,
  622. consistency_level: ConsistencyLevel::Confirmed as u8,
  623. };
  624. // Hash data, the thing we wish to actually sign.
  625. let body = {
  626. let mut v = Cursor::new(Vec::new());
  627. v.write_u32::<BigEndian>(vaa.timestamp).unwrap();
  628. v.write_u32::<BigEndian>(vaa.nonce).unwrap();
  629. v.write_u16::<BigEndian>(vaa.emitter_chain).unwrap();
  630. v.write(&vaa.emitter_address).unwrap();
  631. v.write_u64::<BigEndian>(vaa.sequence).unwrap();
  632. v.write_u8(vaa.consistency_level).unwrap();
  633. v.write(&vaa.payload).unwrap();
  634. v.into_inner()
  635. };
  636. // Hash this body, which is expected to be the same as the hash currently stored in the
  637. // signature account, binding that set of signatures to this VAA.
  638. let body: [u8; 32] = {
  639. let mut h = sha3::Keccak256::default();
  640. h.write(body.as_slice()).unwrap();
  641. h.finalize().into()
  642. };
  643. let body_hash: [u8; 32] = {
  644. let mut h = sha3::Keccak256::default();
  645. h.write(&body).unwrap();
  646. h.finalize().into()
  647. };
  648. (vaa, body, body_hash)
  649. }
  650. pub fn post_vaa(
  651. client: &RpcClient,
  652. program: &Pubkey,
  653. payer: &Keypair,
  654. vaa: PostVAAData,
  655. ) -> Result<(), ClientError> {
  656. let instruction =
  657. bridge::instructions::post_vaa(*program, payer.pubkey(), Pubkey::new_unique(), vaa);
  658. for account in instruction.accounts.iter().enumerate() {
  659. println!("{}: {}", account.0, account.1.pubkey);
  660. }
  661. execute(
  662. client,
  663. payer,
  664. &[payer],
  665. &[instruction],
  666. CommitmentConfig::processed(),
  667. )?;
  668. Ok(())
  669. }
  670. pub fn post_message(
  671. client: &RpcClient,
  672. program: &Pubkey,
  673. payer: &Keypair,
  674. emitter: &Keypair,
  675. message: &Keypair,
  676. nonce: u32,
  677. data: Vec<u8>,
  678. fee: u64,
  679. ) -> Result<(), ClientError> {
  680. // Transfer money into the fee collector as it needs a balance/must exist.
  681. let fee_collector = FeeCollector::<'_>::key(None, program);
  682. // Capture the resulting message, later functions will need this.
  683. let instruction = bridge::instructions::post_message(
  684. *program,
  685. payer.pubkey(),
  686. emitter.pubkey(),
  687. message.pubkey(),
  688. nonce,
  689. data,
  690. ConsistencyLevel::Confirmed,
  691. )
  692. .unwrap();
  693. for account in instruction.accounts.iter().enumerate() {
  694. println!("{}: {}", account.0, account.1.pubkey);
  695. }
  696. execute(
  697. client,
  698. payer,
  699. &[payer, emitter, message],
  700. &[
  701. system_instruction::transfer(&payer.pubkey(), &fee_collector, fee),
  702. instruction,
  703. ],
  704. CommitmentConfig::processed(),
  705. )?;
  706. Ok(())
  707. }
  708. }