Skip to content

Commit

Permalink
publish custiodan wallets (#2493)
Browse files Browse the repository at this point in the history
Co-authored-by: Kai <7630809+Kailai-Wang@users.noreply.github.com>
  • Loading branch information
kziemianek and Kailai-Wang committed Feb 15, 2024
1 parent d4426c8 commit 36e5cd6
Show file tree
Hide file tree
Showing 15 changed files with 122 additions and 20 deletions.
2 changes: 2 additions & 0 deletions bitacross-worker/core-primitives/enclave-api/ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,4 +252,6 @@ extern "C" {
until: *const u32,
) -> sgx_status_t;

pub fn publish_wallets(eid: sgx_enclave_id_t, retval: *mut sgx_status_t) -> sgx_status_t;

}
14 changes: 14 additions & 0 deletions bitacross-worker/core-primitives/enclave-api/src/enclave_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ pub trait EnclaveBase: Send + Sync + 'static {

// litentry
fn migrate_shard(&self, old_shard: Vec<u8>, new_shard: Vec<u8>) -> EnclaveResult<()>;

/// Publish generated wallets on parachain
fn publish_wallets(&self) -> EnclaveResult<()>;
}

/// EnclaveApi implementation for Enclave struct
Expand Down Expand Up @@ -379,6 +382,17 @@ mod impl_ffi {

Ok(())
}

fn publish_wallets(&self) -> EnclaveResult<()> {
let mut retval = sgx_status_t::SGX_SUCCESS;

let result = unsafe { ffi::publish_wallets(self.eid, &mut retval) };

ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result));
ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval));

Ok(())
}
}

fn init_parentchain_components_ffi(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ pub struct NodeMetadataMock {
bitacross_module: u8,
bitacross_add_relayer: u8,
bitacross_remove_relayer: u8,
btc_wallet_generated: u8,
eth_wallet_generated: u8,
}

impl NodeMetadataMock {
Expand Down Expand Up @@ -105,6 +107,8 @@ impl NodeMetadataMock {
bitacross_module: 69u8,
bitacross_add_relayer: 0u8,
bitacross_remove_relayer: 1u8,
btc_wallet_generated: 2u8,
eth_wallet_generated: 3u8,
}
}
}
Expand Down Expand Up @@ -205,4 +209,12 @@ impl BitAcrossCallIndexes for NodeMetadataMock {
fn remove_relayer_call_indexes(&self) -> Result<[u8; 2]> {
Ok([self.bitacross_module, self.bitacross_remove_relayer])
}

fn btc_wallet_generated_indexes(&self) -> Result<[u8; 2]> {
Ok([self.bitacross_module, self.btc_wallet_generated])
}

fn eth_wallet_generated_indexes(&self) -> Result<[u8; 2]> {
Ok([self.bitacross_module, self.eth_wallet_generated])
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const BITACROSS: &str = "Bitacross";
pub trait BitAcrossCallIndexes {
fn add_relayer_call_indexes(&self) -> Result<[u8; 2]>;
fn remove_relayer_call_indexes(&self) -> Result<[u8; 2]>;
fn btc_wallet_generated_indexes(&self) -> Result<[u8; 2]>;
fn eth_wallet_generated_indexes(&self) -> Result<[u8; 2]>;
}

impl BitAcrossCallIndexes for NodeMetadata {
Expand All @@ -32,4 +34,12 @@ impl BitAcrossCallIndexes for NodeMetadata {
fn remove_relayer_call_indexes(&self) -> Result<[u8; 2]> {
self.call_indexes(BITACROSS, "remove_relayer")
}

fn btc_wallet_generated_indexes(&self) -> Result<[u8; 2]> {
self.call_indexes(BITACROSS, "btc_wallet_generated")
}

fn eth_wallet_generated_indexes(&self) -> Result<[u8; 2]> {
self.call_indexes(BITACROSS, "eth_wallet_generated")
}
}
6 changes: 3 additions & 3 deletions bitacross-worker/core-primitives/sgx/crypto/src/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use k256::{
elliptic_curve::group::GroupEncoding,
PublicKey,
};
use std::{string::ToString, vec::Vec};
use std::string::ToString;

/// File name of the sealed seed file.
pub const SEALED_SIGNER_SEED_FILE: &str = "ecdsa_key_sealed.bin";
Expand All @@ -39,8 +39,8 @@ impl Pair {
Self { private, public }
}

pub fn public_bytes(&self) -> Vec<u8> {
self.public.as_affine().to_bytes().as_slice().to_vec()
pub fn public_bytes(&self) -> [u8; 33] {
self.public.as_affine().to_bytes().as_slice().try_into().unwrap()
}

pub fn sign(&self, payload: &[u8]) -> Result<[u8; 64]> {
Expand Down
7 changes: 4 additions & 3 deletions bitacross-worker/core-primitives/sgx/crypto/src/schnorr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use k256::{
schnorr::{signature::Signer, Signature, SigningKey},
PublicKey,
};
use std::{string::ToString, vec::Vec};
use std::string::ToString;

/// File name of the sealed seed file.
pub const SEALED_SIGNER_SEED_FILE: &str = "schnorr_key_sealed.bin";
Expand All @@ -39,8 +39,9 @@ impl Pair {
Self { private, public }
}

pub fn public_bytes(&self) -> Vec<u8> {
self.public.as_affine().to_bytes().as_slice().to_vec()
pub fn public_bytes(&self) -> [u8; 33] {
// safe to unwrap here
self.public.as_affine().to_bytes().as_slice().try_into().unwrap()
}

pub fn sign(&self, payload: &[u8]) -> Result<[u8; 64]> {
Expand Down
2 changes: 2 additions & 0 deletions bitacross-worker/enclave-runtime/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions bitacross-worker/enclave-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ itc-direct-rpc-server = { path = "../core/direct-rpc-server", default-features =
itc-offchain-worker-executor = { path = "../core/offchain-worker-executor", default-features = false, features = ["sgx"] }
itc-parentchain = { path = "../core/parentchain/parentchain-crate", default-features = false, features = ["sgx"] }
itc-parentchain-block-import-dispatcher = { path = "../core/parentchain/block-import-dispatcher", default-features = false, features = ["sgx"] }
itc-parentchain-light-client = { path = "../core/parentchain/light-client", default-features = false }
itc-parentchain-test = { path = "../core/parentchain/test", default-features = false }
itc-peer-top-broadcaster = { path = "../core/peer-top-broadcaster", default-features = false, features = ["sgx"] }
itc-tls-websocket-server = { path = "../core/tls-websocket-server", default-features = false, features = ["sgx"] }
Expand All @@ -109,6 +110,7 @@ itp-extrinsics-factory = { path = "../core-primitives/extrinsics-factory", defau
itp-import-queue = { path = "../core-primitives/import-queue", default-features = false, features = ["sgx"] }
itp-node-api = { path = "../core-primitives/node-api", default-features = false, features = ["sgx"] }
itp-node-api-metadata = { path = "../core-primitives/node-api/metadata", default-features = false }
itp-node-api-metadata-provider = { path = "../core-primitives/node-api/metadata-provider", default-features = false }
itp-nonce-cache = { path = "../core-primitives/nonce-cache", default-features = false, features = ["sgx"] }
itp-ocall-api = { path = "../core-primitives/ocall-api", default-features = false }
itp-primitives-cache = { path = "../core-primitives/primitives-cache", default-features = false, features = ["sgx"] }
Expand Down
4 changes: 3 additions & 1 deletion bitacross-worker/enclave-runtime/Enclave.edl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ enclave {
[in, size=encoded_base_dir_size] uint8_t* encoded_base_dir_str, uint32_t encoded_base_dir_size
);

public sgx_status_t publish_wallets();

public sgx_status_t init_enclave_sidechain_components(
[in, size=fail_mode_size] uint8_t* fail_mode, uint32_t fail_mode_size,
[in, size=fail_at_size] uint8_t* fail_at, uint32_t fail_at_size
Expand Down Expand Up @@ -174,7 +176,7 @@ enclave {
[in, size=shard_size] uint8_t* new_shard,
uint32_t shard_size
);

public sgx_status_t ignore_parentchain_block_import_validation_until(
[in] uint32_t* until
);
Expand Down
42 changes: 41 additions & 1 deletion bitacross-worker/enclave-runtime/src/initialization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,17 @@ use itc_direct_rpc_server::{
create_determine_watch, rpc_connection_registry::ConnectionRegistry,
rpc_ws_handler::RpcWsHandler,
};
use itc_parentchain_light_client::{concurrent_access::ValidatorAccess, ExtrinsicSender};
use itc_peer_top_broadcaster::init;
use itc_tls_websocket_server::{
certificate_generation::ed25519_self_signed_certificate, create_ws_server, ConnectionToken,
WebSocketServer,
};
use itp_attestation_handler::{AttestationHandler, IntelAttestationHandler};
use itp_component_container::{ComponentGetter, ComponentInitializer};
use itp_extrinsics_factory::CreateExtrinsics;
use itp_node_api_metadata::pallet_bitacross::BitAcrossCallIndexes;
use itp_node_api_metadata_provider::AccessNodeMetadata;
use itp_primitives_cache::GLOBAL_PRIMITIVES_CACHE;
use itp_settings::files::{
LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, STATE_SNAPSHOTS_CACHE_SIZE,
Expand All @@ -84,7 +88,7 @@ use itp_stf_state_handler::{
};
use itp_top_pool::pool::Options as PoolOptions;
use itp_top_pool_author::author::{AuthorTopFilter, BroadcastedTopFilter};
use itp_types::{parentchain::ParentchainId, ShardIdentifier};
use itp_types::{parentchain::ParentchainId, OpaqueCall, ShardIdentifier};
use its_sidechain::{
block_composer::BlockComposer,
slots::{FailSlotMode, FailSlotOnDemand},
Expand Down Expand Up @@ -237,6 +241,42 @@ pub(crate) fn init_enclave(
Ok(())
}

pub(crate) fn publish_wallets() -> EnclaveResult<()> {
let metadata_repository = get_node_metadata_repository_from_integritee_solo_or_parachain()?;
let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?;
let validator_accessor = get_validator_accessor_from_integritee_solo_or_parachain()?;

let bitcoin_key_repository = GLOBAL_BITCOIN_KEY_REPOSITORY_COMPONENT.get()?;
let bitcoin_key = bitcoin_key_repository.retrieve_key()?;

let bitcoin_call = metadata_repository
.get_from_metadata(|m| m.btc_wallet_generated_indexes())
.map_err(|e| Error::Other(e.into()))?
.map_err(|e| Error::Other(format!("{:?}", e).into()))?;

let bitcoin_opaque_call = OpaqueCall::from_tuple(&(bitcoin_call, bitcoin_key.public_bytes()));

let ethereum_key_repository = GLOBAL_ETHEREUM_KEY_REPOSITORY_COMPONENT.get()?;
let ethereum_key = ethereum_key_repository.retrieve_key()?;

let ethereum_call = metadata_repository
.get_from_metadata(|m| m.eth_wallet_generated_indexes())
.map_err(|e| Error::Other(e.into()))?
.map_err(|e| Error::Other(format!("{:?}", e).into()))?;

let ethereum_opaque_call =
OpaqueCall::from_tuple(&(ethereum_call, ethereum_key.public_bytes()));

let xts = extrinsics_factory
.create_extrinsics(&[bitcoin_opaque_call, ethereum_opaque_call], None)
.map_err(|e| Error::Other(e.into()))?;
validator_accessor
.execute_mut_on_validator(|v| v.send_extrinsics(xts))
.map_err(|e| Error::Other(e.into()))?;

Ok(())
}

fn initialize_state_observer(
snapshot_repository: &EnclaveStateSnapshotRepository,
) -> EnclaveResult<Arc<EnclaveStateObserver>> {
Expand Down
10 changes: 10 additions & 0 deletions bitacross-worker/enclave-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,16 @@ fn sidechain_rpc_int(request: &str) -> Result<String> {
.unwrap_or_else(|| format!("Empty rpc response for request: {}", request)))
}

#[no_mangle]
pub unsafe extern "C" fn publish_wallets() -> sgx_status_t {
if let Err(e) = initialization::publish_wallets() {
error!("Failed to publish generated wallets: {:?}", e);
return sgx_status_t::SGX_ERROR_UNEXPECTED
}

sgx_status_t::SGX_SUCCESS
}

/// Initialize sidechain enclave components.
///
/// Call this once at startup. Has to be called AFTER the light-client
Expand Down
2 changes: 2 additions & 0 deletions bitacross-worker/service/src/main_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,8 @@ fn start_worker<E, T, D, InitializationHandler, WorkerModeProvider>(
is_development_mode,
)
}
// Publish generated custiodian wallets
enclave.publish_wallets();

// ------------------------------------------------------------------------
// Subscribe to events and print them.
Expand Down
4 changes: 4 additions & 0 deletions bitacross-worker/service/src/tests/mocks/enclave_api_mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ impl EnclaveBase for EnclaveMock {
fn migrate_shard(&self, _old_shard: Vec<u8>, _new_shard: Vec<u8>) -> EnclaveResult<()> {
unimplemented!()
}

fn publish_wallets(&self) -> EnclaveResult<()> {
unimplemented!()
}
}

impl Sidechain for EnclaveMock {
Expand Down
7 changes: 4 additions & 3 deletions pallets/bitacross/src/custodial_wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
// along with Litentry. If not, see <https://www.gnu.org/licenses/>.

use codec::{Decode, Encode};
use core_primitives::{Address20, Address33};
use scale_info::TypeInfo;

pub type PubKey = [u8; 33];

/// custodial wallet that each tee worker generates and holds
#[derive(Encode, Decode, Clone, Default, Debug, PartialEq, Eq, TypeInfo)]
pub struct CustodialWallet {
pub btc: Option<Address33>,
pub eth: Option<Address20>,
pub btc: Option<PubKey>,
pub eth: Option<PubKey>,
}

impl CustodialWallet {
Expand Down
18 changes: 9 additions & 9 deletions pallets/bitacross/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

#![cfg_attr(not(feature = "std"), no_std)]

use core_primitives::{Address20, Address33, Identity};
use core_primitives::Identity;
use frame_support::{
dispatch::{DispatchResult, DispatchResultWithPostInfo},
ensure,
Expand Down Expand Up @@ -70,8 +70,8 @@ pub mod pallet {
AdminSet { new_admin: Option<T::AccountId> },
RelayerAdded { who: Identity },
RelayerRemoved { who: Identity },
BtcWalletGenerated { address: Address33 },
EthWalletGenerated { address: Address20 },
BtcWalletGenerated { pub_key: PubKey },
EthWalletGenerated { pub_key: PubKey },
}

#[pallet::error]
Expand Down Expand Up @@ -149,13 +149,13 @@ pub mod pallet {
#[pallet::weight(({195_000_000}, DispatchClass::Normal, Pays::No))]
pub fn btc_wallet_generated(
origin: OriginFor<T>,
address: Address33,
pub_key: PubKey,
) -> DispatchResultWithPostInfo {
let tee_account = T::TEECallOrigin::ensure_origin(origin)?;
Vault::<T>::try_mutate(tee_account, |v| {
ensure!(!v.has_btc(), Error::<T>::BtcWalletAlreadyExist);
v.btc = Some(address);
Self::deposit_event(Event::BtcWalletGenerated { address });
v.btc = Some(pub_key);
Self::deposit_event(Event::BtcWalletGenerated { pub_key });
Ok(Pays::No.into())
})
}
Expand All @@ -164,13 +164,13 @@ pub mod pallet {
#[pallet::weight(({195_000_000}, DispatchClass::Normal, Pays::No))]
pub fn eth_wallet_generated(
origin: OriginFor<T>,
address: Address20,
pub_key: PubKey,
) -> DispatchResultWithPostInfo {
let tee_account = T::TEECallOrigin::ensure_origin(origin)?;
Vault::<T>::try_mutate(tee_account, |v| {
ensure!(!v.has_eth(), Error::<T>::EthWalletAlreadyExist);
v.eth = Some(address);
Self::deposit_event(Event::EthWalletGenerated { address });
v.eth = Some(pub_key);
Self::deposit_event(Event::EthWalletGenerated { pub_key });
Ok(Pays::No.into())
})
}
Expand Down

0 comments on commit 36e5cd6

Please sign in to comment.