diff --git a/target_chains/starknet/contracts/src/wormhole.cairo b/target_chains/starknet/contracts/src/wormhole.cairo index 82eb92dd..7ba46368 100644 --- a/target_chains/starknet/contracts/src/wormhole.cairo +++ b/target_chains/starknet/contracts/src/wormhole.cairo @@ -1,12 +1,13 @@ use super::byte_array::ByteArray; use core::starknet::secp256_trait::Signature; +use core::starknet::EthAddress; use pyth::util::UnwrapWithFelt252; mod governance; #[starknet::interface] pub trait IWormhole { - fn submit_new_guardian_set(ref self: T, set_index: u32, guardians: Array); + fn submit_new_guardian_set(ref self: T, set_index: u32, guardians: Array); fn parse_and_verify_vm(self: @T, encoded_vm: ByteArray) -> VerifiedVM; // We don't need to implement other governance actions for now. @@ -133,9 +134,10 @@ mod wormhole { use core::starknet::secp256_trait::{Signature, recover_public_key, Secp256PointTrait}; use core::starknet::secp256k1::Secp256k1Point; use core::starknet::{ - ContractAddress, get_execution_info, get_caller_address, get_block_timestamp + ContractAddress, get_execution_info, get_caller_address, get_block_timestamp, EthAddress, }; use core::keccak::cairo_keccak; + use core::starknet::eth_signature::is_eth_signature_valid; use core::integer::u128_byte_reverse; use core::panic_with_felt252; use pyth::hash::{Hasher, HasherImpl}; @@ -158,14 +160,14 @@ mod wormhole { consumed_governance_actions: LegacyMap, guardian_sets: LegacyMap, // (guardian_set_index, guardian_index) => guardian_address - guardian_keys: LegacyMap<(u32, u8), u256>, + guardian_keys: LegacyMap<(u32, u8), EthAddress>, } #[constructor] fn constructor( ref self: ContractState, owner: ContractAddress, - initial_guardians: Array, + initial_guardians: Array, chain_id: u16, governance_chain_id: u16, governance_contract: u256, @@ -178,7 +180,7 @@ mod wormhole { store_guardian_set(ref self, set_index, @initial_guardians); } - fn store_guardian_set(ref self: ContractState, set_index: u32, guardians: @Array) { + fn store_guardian_set(ref self: ContractState, set_index: u32, guardians: @Array) { if guardians.len() == 0 { panic_with_felt252(SubmitNewGuardianSetError::NoGuardiansSpecified.into()); } @@ -188,7 +190,7 @@ mod wormhole { let mut i = 0; while i < guardians.len() { - if *guardians.at(i) == 0 { + if (*guardians.at(i)).into() == 0 { panic_with_felt252(SubmitNewGuardianSetError::InvalidGuardianKey.into()); } i += 1; @@ -217,7 +219,7 @@ mod wormhole { #[abi(embed_v0)] impl WormholeImpl of IWormhole { fn submit_new_guardian_set( - ref self: ContractState, set_index: u32, guardians: Array + ref self: ContractState, set_index: u32, guardians: Array ) { let execution_info = get_execution_info().unbox(); if self.owner.read() != execution_info.caller_address { @@ -271,9 +273,12 @@ mod wormhole { let guardian_key = self .guardian_keys - .read((vm.guardian_set_index, signature.guardian_index)); + .read((vm.guardian_set_index, signature.guardian_index)) + .try_into() + .expect(UNEXPECTED_OVERFLOW); - verify_signature(vm.hash, signature.signature, guardian_key); + is_eth_signature_valid(vm.hash, signature.signature, guardian_key) + .unwrap_with_felt252(); }; vm } @@ -359,25 +364,6 @@ mod wormhole { } } - fn verify_signature(body_hash: u256, signature: Signature, guardian_key: u256,) { - let point: Secp256k1Point = recover_public_key(body_hash, signature) - .expect(ParseAndVerifyVmError::InvalidSignature.into()); - let address = eth_address(point); - assert(guardian_key != 0, SubmitNewGuardianSetError::InvalidGuardianKey.into()); - if address != guardian_key { - panic_with_felt252(ParseAndVerifyVmError::InvalidSignature.into()); - } - } - - fn eth_address(point: Secp256k1Point) -> u256 { - let (x, y) = point.get_coordinates().expect(ParseAndVerifyVmError::InvalidSignature.into()); - - let mut hasher = HasherImpl::new(); - hasher.push_u256(x); - hasher.push_u256(y); - hasher.finalize() % ONE_SHIFT_160 - } - #[generate_trait] impl PrivateImpl of PrivateImplTrait { fn verify_governance_vm(self: @ContractState, vm: @VerifiedVM) { diff --git a/target_chains/starknet/contracts/src/wormhole/governance.cairo b/target_chains/starknet/contracts/src/wormhole/governance.cairo index e49da043..cf850d36 100644 --- a/target_chains/starknet/contracts/src/wormhole/governance.cairo +++ b/target_chains/starknet/contracts/src/wormhole/governance.cairo @@ -2,6 +2,7 @@ use pyth::reader::{Reader, ReaderImpl}; use pyth::util::UNEXPECTED_OVERFLOW; use super::GovernanceError; use core::panic_with_felt252; +use core::starknet::EthAddress; // "Core" (left padded) const MODULE: u256 = 0x00000000000000000000000000000000000000000000000000000000436f7265; @@ -40,7 +41,7 @@ pub struct Header { #[derive(Drop, Debug, Clone)] pub struct NewGuardianSet { pub set_index: u32, - pub keys: Array, + pub keys: Array, } pub fn parse_header(ref reader: Reader) -> Header { diff --git a/target_chains/starknet/contracts/tests/wormhole.cairo b/target_chains/starknet/contracts/tests/wormhole.cairo index b10b1285..7e9fadd7 100644 --- a/target_chains/starknet/contracts/tests/wormhole.cairo +++ b/target_chains/starknet/contracts/tests/wormhole.cairo @@ -3,7 +3,7 @@ use pyth::wormhole::{IWormholeDispatcher, IWormholeDispatcherTrait, ParseAndVeri use pyth::reader::ReaderImpl; use pyth::byte_array::{ByteArray, ByteArrayImpl}; use pyth::util::{UnwrapWithFelt252, array_try_into}; -use core::starknet::ContractAddress; +use core::starknet::{ContractAddress, EthAddress}; use core::panic_with_felt252; #[test] @@ -118,7 +118,7 @@ fn test_submit_guardian_set_rejects_non_governance(pos: usize, random1: usize, r fn deploy( owner: ContractAddress, - guardians: Array, + guardians: Array, chain_id: u16, governance_chain_id: u16, governance_contract: u256, @@ -211,80 +211,86 @@ fn corrupted_byte(value: u8, random: usize) -> u8 { (v % 256).try_into().unwrap() } -fn guardian_set0() -> Array { - array![0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5] +fn guardian_set0() -> Array { + array_try_into(array![0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5]) } // Below are actual guardian keys from // https://github.com/wormhole-foundation/wormhole-networks/tree/master/mainnetv2/guardianset -fn guardian_set1() -> Array { - array![ - 0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5, - 0xfF6CB952589BDE862c25Ef4392132fb9D4A42157, - 0x114De8460193bdf3A2fCf81f86a09765F4762fD1, - 0x107A0086b32d7A0977926A205131d8731D39cbEB, - 0x8C82B2fd82FaeD2711d59AF0F2499D16e726f6b2, - 0x11b39756C042441BE6D8650b69b54EbE715E2343, - 0x54Ce5B4D348fb74B958e8966e2ec3dBd4958a7cd, - 0xeB5F7389Fa26941519f0863349C223b73a6DDEE7, - 0x74a3bf913953D695260D88BC1aA25A4eeE363ef0, - 0x000aC0076727b35FBea2dAc28fEE5cCB0fEA768e, - 0xAF45Ced136b9D9e24903464AE889F5C8a723FC14, - 0xf93124b7c738843CBB89E864c862c38cddCccF95, - 0xD2CC37A4dc036a8D232b48f62cDD4731412f4890, - 0xDA798F6896A3331F64b48c12D1D57Fd9cbe70811, - 0x71AA1BE1D36CaFE3867910F99C09e347899C19C3, - 0x8192b6E7387CCd768277c17DAb1b7a5027c0b3Cf, - 0x178e21ad2E77AE06711549CFBB1f9c7a9d8096e8, - 0x5E1487F35515d02A92753504a8D75471b9f49EdB, - 0x6FbEBc898F403E4773E95feB15E80C9A99c8348d, - ] +fn guardian_set1() -> Array { + array_try_into( + array![ + 0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5, + 0xfF6CB952589BDE862c25Ef4392132fb9D4A42157, + 0x114De8460193bdf3A2fCf81f86a09765F4762fD1, + 0x107A0086b32d7A0977926A205131d8731D39cbEB, + 0x8C82B2fd82FaeD2711d59AF0F2499D16e726f6b2, + 0x11b39756C042441BE6D8650b69b54EbE715E2343, + 0x54Ce5B4D348fb74B958e8966e2ec3dBd4958a7cd, + 0xeB5F7389Fa26941519f0863349C223b73a6DDEE7, + 0x74a3bf913953D695260D88BC1aA25A4eeE363ef0, + 0x000aC0076727b35FBea2dAc28fEE5cCB0fEA768e, + 0xAF45Ced136b9D9e24903464AE889F5C8a723FC14, + 0xf93124b7c738843CBB89E864c862c38cddCccF95, + 0xD2CC37A4dc036a8D232b48f62cDD4731412f4890, + 0xDA798F6896A3331F64b48c12D1D57Fd9cbe70811, + 0x71AA1BE1D36CaFE3867910F99C09e347899C19C3, + 0x8192b6E7387CCd768277c17DAb1b7a5027c0b3Cf, + 0x178e21ad2E77AE06711549CFBB1f9c7a9d8096e8, + 0x5E1487F35515d02A92753504a8D75471b9f49EdB, + 0x6FbEBc898F403E4773E95feB15E80C9A99c8348d, + ] + ) } -fn guardian_set2() -> Array { - array![ - 0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5, - 0xfF6CB952589BDE862c25Ef4392132fb9D4A42157, - 0x114De8460193bdf3A2fCf81f86a09765F4762fD1, - 0x107A0086b32d7A0977926A205131d8731D39cbEB, - 0x8C82B2fd82FaeD2711d59AF0F2499D16e726f6b2, - 0x11b39756C042441BE6D8650b69b54EbE715E2343, - 0x54Ce5B4D348fb74B958e8966e2ec3dBd4958a7cd, - 0x66B9590e1c41e0B226937bf9217D1d67Fd4E91F5, - 0x74a3bf913953D695260D88BC1aA25A4eeE363ef0, - 0x000aC0076727b35FBea2dAc28fEE5cCB0fEA768e, - 0xAF45Ced136b9D9e24903464AE889F5C8a723FC14, - 0xf93124b7c738843CBB89E864c862c38cddCccF95, - 0xD2CC37A4dc036a8D232b48f62cDD4731412f4890, - 0xDA798F6896A3331F64b48c12D1D57Fd9cbe70811, - 0x71AA1BE1D36CaFE3867910F99C09e347899C19C3, - 0x8192b6E7387CCd768277c17DAb1b7a5027c0b3Cf, - 0x178e21ad2E77AE06711549CFBB1f9c7a9d8096e8, - 0x5E1487F35515d02A92753504a8D75471b9f49EdB, - 0x6FbEBc898F403E4773E95feB15E80C9A99c8348d, - ] +fn guardian_set2() -> Array { + array_try_into( + array![ + 0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5, + 0xfF6CB952589BDE862c25Ef4392132fb9D4A42157, + 0x114De8460193bdf3A2fCf81f86a09765F4762fD1, + 0x107A0086b32d7A0977926A205131d8731D39cbEB, + 0x8C82B2fd82FaeD2711d59AF0F2499D16e726f6b2, + 0x11b39756C042441BE6D8650b69b54EbE715E2343, + 0x54Ce5B4D348fb74B958e8966e2ec3dBd4958a7cd, + 0x66B9590e1c41e0B226937bf9217D1d67Fd4E91F5, + 0x74a3bf913953D695260D88BC1aA25A4eeE363ef0, + 0x000aC0076727b35FBea2dAc28fEE5cCB0fEA768e, + 0xAF45Ced136b9D9e24903464AE889F5C8a723FC14, + 0xf93124b7c738843CBB89E864c862c38cddCccF95, + 0xD2CC37A4dc036a8D232b48f62cDD4731412f4890, + 0xDA798F6896A3331F64b48c12D1D57Fd9cbe70811, + 0x71AA1BE1D36CaFE3867910F99C09e347899C19C3, + 0x8192b6E7387CCd768277c17DAb1b7a5027c0b3Cf, + 0x178e21ad2E77AE06711549CFBB1f9c7a9d8096e8, + 0x5E1487F35515d02A92753504a8D75471b9f49EdB, + 0x6FbEBc898F403E4773E95feB15E80C9A99c8348d, + ] + ) } -fn guardian_set3() -> Array { - array![ - 0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5, - 0xfF6CB952589BDE862c25Ef4392132fb9D4A42157, - 0x114De8460193bdf3A2fCf81f86a09765F4762fD1, - 0x107A0086b32d7A0977926A205131d8731D39cbEB, - 0x8C82B2fd82FaeD2711d59AF0F2499D16e726f6b2, - 0x11b39756C042441BE6D8650b69b54EbE715E2343, - 0x54Ce5B4D348fb74B958e8966e2ec3dBd4958a7cd, - 0x15e7cAF07C4e3DC8e7C469f92C8Cd88FB8005a20, - 0x74a3bf913953D695260D88BC1aA25A4eeE363ef0, - 0x000aC0076727b35FBea2dAc28fEE5cCB0fEA768e, - 0xAF45Ced136b9D9e24903464AE889F5C8a723FC14, - 0xf93124b7c738843CBB89E864c862c38cddCccF95, - 0xD2CC37A4dc036a8D232b48f62cDD4731412f4890, - 0xDA798F6896A3331F64b48c12D1D57Fd9cbe70811, - 0x71AA1BE1D36CaFE3867910F99C09e347899C19C3, - 0x8192b6E7387CCd768277c17DAb1b7a5027c0b3Cf, - 0x178e21ad2E77AE06711549CFBB1f9c7a9d8096e8, - 0x5E1487F35515d02A92753504a8D75471b9f49EdB, - 0x6FbEBc898F403E4773E95feB15E80C9A99c8348d, - ] +fn guardian_set3() -> Array { + array_try_into( + array![ + 0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5, + 0xfF6CB952589BDE862c25Ef4392132fb9D4A42157, + 0x114De8460193bdf3A2fCf81f86a09765F4762fD1, + 0x107A0086b32d7A0977926A205131d8731D39cbEB, + 0x8C82B2fd82FaeD2711d59AF0F2499D16e726f6b2, + 0x11b39756C042441BE6D8650b69b54EbE715E2343, + 0x54Ce5B4D348fb74B958e8966e2ec3dBd4958a7cd, + 0x15e7cAF07C4e3DC8e7C469f92C8Cd88FB8005a20, + 0x74a3bf913953D695260D88BC1aA25A4eeE363ef0, + 0x000aC0076727b35FBea2dAc28fEE5cCB0fEA768e, + 0xAF45Ced136b9D9e24903464AE889F5C8a723FC14, + 0xf93124b7c738843CBB89E864c862c38cddCccF95, + 0xD2CC37A4dc036a8D232b48f62cDD4731412f4890, + 0xDA798F6896A3331F64b48c12D1D57Fd9cbe70811, + 0x71AA1BE1D36CaFE3867910F99C09e347899C19C3, + 0x8192b6E7387CCd768277c17DAb1b7a5027c0b3Cf, + 0x178e21ad2E77AE06711549CFBB1f9c7a9d8096e8, + 0x5E1487F35515d02A92753504a8D75471b9f49EdB, + 0x6FbEBc898F403E4773E95feB15E80C9A99c8348d, + ] + ) } // A random VAA pulled from Hermes.