|
| 1 | +#![deny(warnings)] |
1 | 2 | pub mod cli;
|
2 | 3 |
|
3 | 4 | use {
|
|
45 | 46 | },
|
46 | 47 | wormhole_solana::{
|
47 | 48 | instructions::{
|
| 49 | + initialize, |
48 | 50 | post_vaa,
|
| 51 | + upgrade_guardian_set, |
49 | 52 | verify_signatures_txs,
|
50 | 53 | PostVAAData,
|
51 | 54 | },
|
|
55 | 58 | VAA as WormholeSolanaVAA,
|
56 | 59 | },
|
57 | 60 | };
|
| 61 | + |
| 62 | +const INITIAL_GUARDIAN: &str = "58cc3ae5c097b213ce3c81979e1b9f9570746aa5"; // Mainnet intial guardian set so we can use stable price feeds |
| 63 | +const UPGRADE_GUARDIAN_SET_VAA_1 : &str = "010000000001007ac31b282c2aeeeb37f3385ee0de5f8e421d30b9e5ae8ba3d4375c1c77a86e77159bb697d9c456d6f8c02d22a94b1279b65b0d6a9957e7d3857423845ac758e300610ac1d2000000030001000000000000000000000000000000000000000000000000000000000000000400000000000005390000000000000000000000000000000000000000000000000000000000436f7265020000000000011358cc3ae5c097b213ce3c81979e1b9f9570746aa5ff6cb952589bde862c25ef4392132fb9d4a42157114de8460193bdf3a2fcf81f86a09765f4762fd1107a0086b32d7a0977926a205131d8731d39cbeb8c82b2fd82faed2711d59af0f2499d16e726f6b211b39756c042441be6d8650b69b54ebe715e234354ce5b4d348fb74b958e8966e2ec3dbd4958a7cdeb5f7389fa26941519f0863349c223b73a6ddee774a3bf913953d695260d88bc1aa25a4eee363ef0000ac0076727b35fbea2dac28fee5ccb0fea768eaf45ced136b9d9e24903464ae889f5c8a723fc14f93124b7c738843cbb89e864c862c38cddcccf95d2cc37a4dc036a8d232b48f62cdd4731412f4890da798f6896a3331f64b48c12d1d57fd9cbe7081171aa1be1d36cafe3867910f99c09e347899c19c38192b6e7387ccd768277c17dab1b7a5027c0b3cf178e21ad2e77ae06711549cfbb1f9c7a9d8096e85e1487f35515d02a92753504a8d75471b9f49edb6fbebc898f403e4773e95feb15e80c9a99c8348d"; |
| 64 | +const UPGRADE_GUARDIAN_SET_VAA_2 : &str = "01000000010d0012e6b39c6da90c5dfd3c228edbb78c7a4c97c488ff8a346d161a91db067e51d638c17216f368aa9bdf4836b8645a98018ca67d2fec87d769cabfdf2406bf790a0002ef42b288091a670ef3556596f4f47323717882881eaf38e03345078d07a156f312b785b64dae6e9a87e3d32872f59cb1931f728cecf511762981baf48303668f0103cef2616b84c4e511ff03329e0853f1bd7ee9ac5ba71d70a4d76108bddf94f69c2a8a84e4ee94065e8003c334e899184943634e12043d0dda78d93996da073d190104e76d166b9dac98f602107cc4b44ac82868faf00b63df7d24f177aa391e050902413b71046434e67c770b19aecdf7fce1d1435ea0be7262e3e4c18f50ddc8175c0105d9450e8216d741e0206a50f93b750a47e0a258b80eb8fed1314cc300b3d905092de25cd36d366097b7103ae2d184121329ba3aa2d7c6cc53273f11af14798110010687477c8deec89d36a23e7948feb074df95362fc8dcbd8ae910ac556a1dee1e755c56b9db5d710c940938ed79bc1895a3646523a58bc55f475a23435a373ecfdd0107fb06734864f79def4e192497362513171530daea81f07fbb9f698afe7e66c6d44db21323144f2657d4a5386a954bb94eef9f64148c33aef6e477eafa2c5c984c01088769e82216310d1827d9bd48645ec23e90de4ef8a8de99e2d351d1df318608566248d80cdc83bdcac382b3c30c670352be87f9069aab5037d0b747208eae9c650109e9796497ff9106d0d1c62e184d83716282870cef61a1ee13d6fc485b521adcce255c96f7d1bca8d8e7e7d454b65783a830bddc9d94092091a268d311ecd84c26010c468c9fb6d41026841ff9f8d7368fa309d4dbea3ea4bbd2feccf94a92cc8a20a226338a8e2126cd16f70eaf15b4fc9be2c3fa19def14e071956a605e9d1ac4162010e23fcb6bd445b7c25afb722250c1acbc061ed964ba9de1326609ae012acdfb96942b2a102a2de99ab96327859a34a2b49a767dbdb62e0a1fb26af60fe44fd496a00106bb0bac77ac68b347645f2fb1ad789ea9bd76fb9b2324f25ae06f97e65246f142df717f662e73948317182c62ce87d79c73def0dba12e5242dfc038382812cfe00126da03c5e56cb15aeeceadc1e17a45753ab4dc0ec7bf6a75ca03143ed4a294f6f61bc3f478a457833e43084ecd7c985bf2f55a55f168aac0e030fc49e845e497101626e9d9a5d9e343f00010000000000000000000000000000000000000000000000000000000000000004c1759167c43f501c2000000000000000000000000000000000000000000000000000000000436f7265020000000000021358cc3ae5c097b213ce3c81979e1b9f9570746aa5ff6cb952589bde862c25ef4392132fb9d4a42157114de8460193bdf3a2fcf81f86a09765f4762fd1107a0086b32d7a0977926a205131d8731d39cbeb8c82b2fd82faed2711d59af0f2499d16e726f6b211b39756c042441be6d8650b69b54ebe715e234354ce5b4d348fb74b958e8966e2ec3dbd4958a7cd66b9590e1c41e0b226937bf9217d1d67fd4e91f574a3bf913953d695260d88bc1aa25a4eee363ef0000ac0076727b35fbea2dac28fee5ccb0fea768eaf45ced136b9d9e24903464ae889f5c8a723fc14f93124b7c738843cbb89e864c862c38cddcccf95d2cc37a4dc036a8d232b48f62cdd4731412f4890da798f6896a3331f64b48c12d1d57fd9cbe7081171aa1be1d36cafe3867910f99c09e347899c19c38192b6e7387ccd768277c17dab1b7a5027c0b3cf178e21ad2e77ae06711549cfbb1f9c7a9d8096e85e1487f35515d02a92753504a8d75471b9f49edb6fbebc898f403e4773e95feb15e80c9a99c8348d"; |
| 65 | +const UPGRADE_GUARDIAN_SET_VAA_3 : &str = "01000000020d00ce45474d9e1b1e7790a2d210871e195db53a70ffd6f237cfe70e2686a32859ac43c84a332267a8ef66f59719cf91cc8df0101fd7c36aa1878d5139241660edc0010375cc906156ae530786661c0cd9aef444747bc3d8d5aa84cac6a6d2933d4e1a031cffa30383d4af8131e929d9f203f460b07309a647d6cd32ab1cc7724089392c000452305156cfc90343128f97e499311b5cae174f488ff22fbc09591991a0a73d8e6af3afb8a5968441d3ab8437836407481739e9850ad5c95e6acfcc871e951bc30105a7956eefc23e7c945a1966d5ddbe9e4be376c2f54e45e3d5da88c2f8692510c7429b1ea860ae94d929bd97e84923a18187e777aa3db419813a80deb84cc8d22b00061b2a4f3d2666608e0aa96737689e3ba5793810ff3a52ff28ad57d8efb20967735dc5537a2e43ef10f583d144c12a1606542c207f5b79af08c38656d3ac40713301086b62c8e130af3411b3c0d91b5b50dcb01ed5f293963f901fc36e7b0e50114dce203373b32eb45971cef8288e5d928d0ed51cd86e2a3006b0af6a65c396c009080009e93ab4d2c8228901a5f4525934000b2c26d1dc679a05e47fdf0ff3231d98fbc207103159ff4116df2832eea69b38275283434e6cd4a4af04d25fa7a82990b707010aa643f4cf615dfff06ffd65830f7f6cf6512dabc3690d5d9e210fdc712842dc2708b8b2c22e224c99280cd25e5e8bfb40e3d1c55b8c41774e287c1e2c352aecfc010b89c1e85faa20a30601964ccc6a79c0ae53cfd26fb10863db37783428cd91390a163346558239db3cd9d420cfe423a0df84c84399790e2e308011b4b63e6b8015010ca31dcb564ac81a053a268d8090e72097f94f366711d0c5d13815af1ec7d47e662e2d1bde22678113d15963da100b668ba26c0c325970d07114b83c5698f46097010dc9fda39c0d592d9ed92cd22b5425cc6b37430e236f02d0d1f8a2ef45a00bde26223c0a6eb363c8b25fd3bf57234a1d9364976cefb8360e755a267cbbb674b39501108db01e444ab1003dd8b6c96f8eb77958b40ba7a85fefecf32ad00b7a47c0ae7524216262495977e09c0989dd50f280c21453d3756843608eacd17f4fdfe47600001261025228ef5af837cb060bcd986fcfa84ccef75b3fa100468cfd24e7fadf99163938f3b841a33496c2706d0208faab088bd155b2e20fd74c625bb1cc8c43677a0163c53c409e0c5dfa000100000000000000000000000000000000000000000000000000000000000000046c5a054d7833d1e42000000000000000000000000000000000000000000000000000000000436f7265020000000000031358cc3ae5c097b213ce3c81979e1b9f9570746aa5ff6cb952589bde862c25ef4392132fb9d4a42157114de8460193bdf3a2fcf81f86a09765f4762fd1107a0086b32d7a0977926a205131d8731d39cbeb8c82b2fd82faed2711d59af0f2499d16e726f6b211b39756c042441be6d8650b69b54ebe715e234354ce5b4d348fb74b958e8966e2ec3dbd4958a7cd15e7caf07c4e3dc8e7c469f92c8cd88fb8005a2074a3bf913953d695260d88bc1aa25a4eee363ef0000ac0076727b35fbea2dac28fee5ccb0fea768eaf45ced136b9d9e24903464ae889f5c8a723fc14f93124b7c738843cbb89e864c862c38cddcccf95d2cc37a4dc036a8d232b48f62cdd4731412f4890da798f6896a3331f64b48c12d1d57fd9cbe7081171aa1be1d36cafe3867910f99c09e347899c19c38192b6e7387ccd768277c17dab1b7a5027c0b3cf178e21ad2e77ae06711549cfbb1f9c7a9d8096e85e1487f35515d02a92753504a8d75471b9f49edb6fbebc898f403e4773e95feb15e80c9a99c8348d"; |
| 66 | + |
| 67 | + |
58 | 68 | // Note: this is a reimplementation of the GuardianSet from wormhole_solana
|
59 | 69 | // because the wormhole_solana crate does uses an older versions of the dependencies.
|
60 | 70 | // This can be removed once the GuardianSet is added to the wormhole_anchor_sdk
|
@@ -89,12 +99,16 @@ impl Owner for GuardianSet {
|
89 | 99 |
|
90 | 100 | fn main() -> Result<()> {
|
91 | 101 | let cli = Cli::parse();
|
| 102 | + let Cli { |
| 103 | + action, |
| 104 | + keypair, |
| 105 | + url, |
| 106 | + wormhole, |
| 107 | + } = cli; |
92 | 108 |
|
93 |
| - match cli.action { |
| 109 | + match action { |
94 | 110 | Action::PostAndReceiveVAA {
|
95 | 111 | vaa: accumulator_update_data_str,
|
96 |
| - keypair, |
97 |
| - url, |
98 | 112 | } => {
|
99 | 113 | let wormhole = wormhole_anchor_sdk::wormhole::program::id();
|
100 | 114 | let rpc_client = RpcClient::new(url);
|
@@ -233,11 +247,169 @@ fn main() -> Result<()> {
|
233 | 247 | }
|
234 | 248 | }
|
235 | 249 | }
|
| 250 | + Action::InitializeWormholeReceiver {} => { |
| 251 | + let rpc_client = RpcClient::new(url); |
| 252 | + let payer = |
| 253 | + read_keypair_file(&*shellexpand::tilde(&keypair)).expect("Keypair not found"); |
| 254 | + |
| 255 | + let initialize_instruction = initialize( |
| 256 | + wormhole, |
| 257 | + payer.pubkey(), |
| 258 | + 0, |
| 259 | + 0, |
| 260 | + &[hex::decode(INITIAL_GUARDIAN).unwrap().try_into().unwrap()], |
| 261 | + ) |
| 262 | + .unwrap(); |
| 263 | + process_transaction(&rpc_client, vec![initialize_instruction], &vec![&payer])?; |
| 264 | + |
| 265 | + process_upgrade_guardian_set( |
| 266 | + &rpc_client, |
| 267 | + &hex::decode(UPGRADE_GUARDIAN_SET_VAA_1).unwrap(), |
| 268 | + wormhole, |
| 269 | + &payer, |
| 270 | + true, |
| 271 | + )?; |
| 272 | + process_upgrade_guardian_set( |
| 273 | + &rpc_client, |
| 274 | + &hex::decode(UPGRADE_GUARDIAN_SET_VAA_2).unwrap(), |
| 275 | + wormhole, |
| 276 | + &payer, |
| 277 | + false, |
| 278 | + )?; |
| 279 | + process_upgrade_guardian_set( |
| 280 | + &rpc_client, |
| 281 | + &hex::decode(UPGRADE_GUARDIAN_SET_VAA_3).unwrap(), |
| 282 | + wormhole, |
| 283 | + &payer, |
| 284 | + false, |
| 285 | + )?; |
| 286 | + } |
236 | 287 | }
|
237 | 288 |
|
238 | 289 | Ok(())
|
239 | 290 | }
|
240 | 291 |
|
| 292 | +pub fn process_upgrade_guardian_set( |
| 293 | + rpc_client: &RpcClient, |
| 294 | + vaa: &[u8], |
| 295 | + wormhole: Pubkey, |
| 296 | + payer: &Keypair, |
| 297 | + legacy_guardian_set: bool, |
| 298 | +) -> Result<()> { |
| 299 | + let posted_vaa = |
| 300 | + process_post_vaa(rpc_client, vaa, wormhole, payer, legacy_guardian_set).unwrap(); |
| 301 | + let parsed_vaa: Vaa<&RawMessage> = serde_wormhole::from_slice(vaa).unwrap(); |
| 302 | + let (header, body): (Header, Body<&RawMessage>) = parsed_vaa.into(); |
| 303 | + let guardian_set_index_old = header.guardian_set_index; |
| 304 | + let emitter = Pubkey::from(body.emitter_address.0); |
| 305 | + let sequence = body.sequence; |
| 306 | + |
| 307 | + let update_guardian_set_instruction = upgrade_guardian_set( |
| 308 | + wormhole, |
| 309 | + payer.pubkey(), |
| 310 | + posted_vaa, |
| 311 | + guardian_set_index_old, |
| 312 | + emitter, |
| 313 | + sequence, |
| 314 | + ) |
| 315 | + .unwrap(); |
| 316 | + |
| 317 | + process_transaction( |
| 318 | + rpc_client, |
| 319 | + vec![update_guardian_set_instruction], |
| 320 | + &vec![payer], |
| 321 | + )?; |
| 322 | + Ok(()) |
| 323 | +} |
| 324 | + |
| 325 | +fn deserialize_guardian_set(buf: &mut &[u8], legacy_guardian_set: bool) -> Result<GuardianSet> { |
| 326 | + if !legacy_guardian_set { |
| 327 | + // Skip anchor discriminator |
| 328 | + *buf = &buf[8..]; |
| 329 | + } |
| 330 | + let guardian_set = GuardianSet::deserialize(buf)?; |
| 331 | + Ok(guardian_set) |
| 332 | +} |
| 333 | + |
| 334 | +pub fn process_post_vaa( |
| 335 | + rpc_client: &RpcClient, |
| 336 | + vaa: &[u8], |
| 337 | + wormhole: Pubkey, |
| 338 | + payer: &Keypair, |
| 339 | + legacy_guardian_set: bool, |
| 340 | +) -> Result<Pubkey> { |
| 341 | + let parsed_vaa: Vaa<&RawMessage> = serde_wormhole::from_slice(vaa).unwrap(); |
| 342 | + let (header, body): (Header, Body<&RawMessage>) = parsed_vaa.into(); |
| 343 | + |
| 344 | + let wormhole_config = WormholeConfig::key(&wormhole, ()); |
| 345 | + |
| 346 | + let wormhole_config_data = |
| 347 | + BridgeData::try_from_slice(&rpc_client.get_account_data(&wormhole_config)?)?; |
| 348 | + |
| 349 | + let guardian_set = Pubkey::find_program_address( |
| 350 | + &[ |
| 351 | + b"GuardianSet", |
| 352 | + &wormhole_config_data.guardian_set_index.to_be_bytes(), |
| 353 | + ], |
| 354 | + &wormhole, |
| 355 | + ) |
| 356 | + .0; |
| 357 | + |
| 358 | + let guardian_set_data = deserialize_guardian_set( |
| 359 | + &mut &rpc_client.get_account_data(&guardian_set)?[..], |
| 360 | + legacy_guardian_set, |
| 361 | + )?; |
| 362 | + |
| 363 | + let vaa_hash = body.digest().unwrap().hash; |
| 364 | + let vaa_pubkey = WormholeSolanaVAA::key(&wormhole, vaa_hash); |
| 365 | + |
| 366 | + let signature_set_keypair = Keypair::new(); |
| 367 | + |
| 368 | + let verify_txs = verify_signatures_txs( |
| 369 | + vaa, |
| 370 | + WormholeSolanaGuardianSet { |
| 371 | + index: guardian_set_data.index, |
| 372 | + keys: guardian_set_data.keys, |
| 373 | + creation_time: guardian_set_data.creation_time, |
| 374 | + expiration_time: guardian_set_data.expiration_time, |
| 375 | + }, |
| 376 | + wormhole, |
| 377 | + payer.pubkey(), |
| 378 | + wormhole_config_data.guardian_set_index, |
| 379 | + signature_set_keypair.pubkey(), |
| 380 | + )?; |
| 381 | + |
| 382 | + for tx in verify_txs { |
| 383 | + process_transaction(rpc_client, tx, &vec![payer, &signature_set_keypair])?; |
| 384 | + } |
| 385 | + let post_vaa_data = PostVAAData { |
| 386 | + version: header.version, |
| 387 | + guardian_set_index: header.guardian_set_index, |
| 388 | + timestamp: body.timestamp, |
| 389 | + nonce: body.nonce, |
| 390 | + emitter_chain: body.emitter_chain.into(), |
| 391 | + emitter_address: body.emitter_address.0, |
| 392 | + sequence: body.sequence, |
| 393 | + consistency_level: body.consistency_level, |
| 394 | + payload: body.payload.to_vec(), |
| 395 | + }; |
| 396 | + |
| 397 | + process_transaction( |
| 398 | + rpc_client, |
| 399 | + vec![post_vaa( |
| 400 | + wormhole, |
| 401 | + payer.pubkey(), |
| 402 | + signature_set_keypair.pubkey(), |
| 403 | + post_vaa_data, |
| 404 | + )?], |
| 405 | + &vec![payer], |
| 406 | + )?; |
| 407 | + |
| 408 | + rpc_client.get_account_data(&vaa_pubkey).ok(); |
| 409 | + |
| 410 | + Ok(vaa_pubkey) |
| 411 | +} |
| 412 | + |
241 | 413 | pub fn process_transaction(
|
242 | 414 | rpc_client: &RpcClient,
|
243 | 415 | instructions: Vec<Instruction>,
|
|
0 commit comments