Skip to content

Commit

Permalink
refactor: use second Stronghold for IOTA wallet
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-mader committed Apr 22, 2024
1 parent 4f10dab commit 2865e66
Show file tree
Hide file tree
Showing 16 changed files with 370 additions and 295 deletions.
98 changes: 33 additions & 65 deletions did_iota/src/producer/produce.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::sync::Arc;
use token_wallet::{iota::IotaWallet, TokenWallet};
use tokio::sync::RwLock;

use identity_iota::{
Expand Down Expand Up @@ -37,7 +38,7 @@ static TESTNET_URL: &str = "https://api.testnet.shimmer.network";

/// Note: Producing a DID document on an IOTA network involves publishing it to the network.
pub async fn produce_did_iota(
storage: JwkStorageWrapper,
storage: &JwkStorageWrapper,
key_id: &KeyId,
iota_method: IotaMethod,
) -> Result<CoreDocument, ProducerError> {
Expand All @@ -48,8 +49,6 @@ pub async fn produce_did_iota(
JwkStorageWrapper::PKCS11 => todo!(),
};

// let secret_manager = SecretManager::Stronghold(stronghold_adapter);

let network = match iota_method {
IotaMethod::Testnet => {
info!(
Expand All @@ -76,21 +75,35 @@ pub async fn produce_did_iota(
// Placeholder until document is published to network
let controller = IotaDID::placeholder(&network);

// let client = stronghold_adapter.inner().await.load_client("0")?;
// let secret_manager = SecretManager::Stronghold(stronghold_secret_manager);

// let stronghold_storage = StrongholdStorage::new(stronghold_secret_manager);

// let x = StrongholdStorage::get_public_key(&self, key_id).await.unwrap(); //stronghold_adapter
// Create new Stronghold instance
// let secret_manager = SecretManager::Stronghold(
// StrongholdSecretManager::builder()
// .password(Password::from("password"))
// .build(random_stronghold_path())?,
// );

// let secret_manager = SecretManager::Stronghold(stronghold_adapter);
// let x = secret_manager.clone();

// let stronghold_storage = StrongholdStorage::new(stronghold_adapter);
let wallet = IotaWallet::new().await;

// TODO: create helper function: "get_stronghold_secret_manager()"?
let secret_manager: SecretManager = SecretManager::Stronghold(
StrongholdSecretManager::builder()
.password(Password::from("secure_password".to_owned()))
.build(random_stronghold_path())
.unwrap(),
);
// let client_options = ClientOptions::new().with_node(TESTNET_URL).unwrap();
// let coin_type = SHIMMER_COIN_TYPE; // TODO: hardcoded for now
// let wallet = Wallet::builder()
// .with_secret_manager_arc(Some(Arc::new(RwLock::new(secret_manager))))
// .with_client_options(client_options)
// .with_coin_type(coin_type)
// .finish()
// .await
// .unwrap();

// let ssm: StrongholdSecretManager = match wallet.get_secret_manager().as_ref() {
// SecretManager::Stronghold(ssm) => ssm.clone(),
// _ => panic!("Expected StrongholdSecretManager"),
// };

let public_key_jwk = stronghold_storage.get_public_key(key_id).await.unwrap();

Expand All @@ -101,25 +114,7 @@ pub async fn produce_did_iota(
.insert_method(verification_method, MethodScope::VerificationMethod)
.ok();

let governor_address = get_governor_address(&secret_manager).await;

// let secret_manager = match storage {
// JwkStorageWrapper::Stronghold(_) => todo!(),
// JwkStorageWrapper::SecretManager(stronghold_adapter) => SecretManager::Stronghold(stronghold_adapter),
// JwkStorageWrapper::PKCS11 => todo!(),
// };

// let stronghold_storage = StrongholdStorage::new(StrongholdAdapter::builder().);

let client_options = ClientOptions::new().with_node(TESTNET_URL).unwrap();
let coin_type = SHIMMER_COIN_TYPE; // TODO: hardcoded for now
let wallet = Wallet::builder()
.with_secret_manager_arc(Some(Arc::new(RwLock::new(secret_manager))))
.with_client_options(client_options)
.with_coin_type(coin_type)
.finish()
.await
.unwrap();
let governor_address = wallet.get_governor_address().await;

let published_document = publish_iota_document(iota_document, governor_address, wallet).await?;

Expand All @@ -128,38 +123,11 @@ pub async fn produce_did_iota(
Ok(published_document)
}

/// First address: funding address, second address: governor address
async fn get_governor_address(secret_manager: &SecretManager) -> Bech32Address {
// let secret_manager = match storage {
// JwkStorageWrapper::Stronghold(_) => todo!(),
// JwkStorageWrapper::SecretManager(stronghold_adapter) => SecretManager::Stronghold(stronghold_adapter),
// JwkStorageWrapper::PKCS11 => todo!(),
// };

let addresses = secret_manager
.generate_ed25519_addresses(
GetAddressesOptions::default()
.with_range(0..2)
.with_bech32_hrp(SHIMMER_TESTNET_BECH32_HRP),
)
.await
.unwrap();

// TODO: governor address should use a different different key
let governor = addresses[1];
info!("Governor address: {}", governor);
governor
}

#[cfg(test)]
mod tests {
use super::*;

use identity_iota::storage;
use iota_sdk::client::{
secret::{stronghold::StrongholdSecretManager, SecretManager},
Password,
};
use iota_sdk::client::{secret::stronghold::StrongholdSecretManager, Password};
use test_log::test;

const SNAPSHOT_PATH: &str = "tests/res/test.stronghold";
Expand All @@ -178,10 +146,10 @@ mod tests {
.build(SNAPSHOT_PATH.to_owned())
.unwrap();

// let storage = JwkStorageWrapper::SecretManager(stronghold_adapter);
let storage = JwkStorageWrapper::Stronghold(StrongholdStorage::new(stronghold_adapter));
// let storage = JwkStorageWrapper::Stronghold(stronghold_adapter);

let document = produce_did_iota(storage, &KeyId::new(KEY_ID), IotaMethod::Testnet)
let document = produce_did_iota(&storage, &KeyId::new(KEY_ID), IotaMethod::Testnet)
.await
.unwrap();

Expand Down Expand Up @@ -216,7 +184,7 @@ mod tests {

let storage = JwkStorageWrapper::Stronghold(StrongholdStorage::new(stronghold_adapter));

let document = produce_did_iota(storage, &KeyId::new(KEY_ID), IotaMethod::Shimmer)
let document = produce_did_iota(&storage, &KeyId::new(KEY_ID), IotaMethod::Shimmer)
.await
.unwrap();

Expand All @@ -233,7 +201,7 @@ mod tests {

let storage = JwkStorageWrapper::Stronghold(StrongholdStorage::new(stronghold_adapter));

let document = produce_did_iota(storage, &KeyId::new(KEY_ID), IotaMethod::Mainnet)
let document = produce_did_iota(&storage, &KeyId::new(KEY_ID), IotaMethod::Mainnet)
.await
.unwrap();

Expand Down
84 changes: 44 additions & 40 deletions did_iota/src/producer/publish.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
// use consumer::resolver::Resolver;
use identity_iota::core::ToJson;
use identity_iota::did::DID;
use identity_iota::document::CoreDocument;
use identity_iota::iota::{IotaClientExt, IotaDID, IotaDocument, IotaIdentityClientExt};
use identity_iota::iota::{IotaDID, IotaDocument, IotaIdentityClientExt};
use iota_sdk::client::{node_api::indexer::query_parameters::QueryParameter, Client};
use iota_sdk::types::block::address::Bech32Address;
use iota_sdk::types::block::output::{AliasId, MinimumStorageDepositBasicOutput};
use iota_sdk::Wallet;
use log::{debug, info, warn};
use shared::error::{ProducerError, WalletError};
use token_wallet::{fund_storage_deposit, get_address_balance};
use token_wallet::iota::IotaWallet;
use token_wallet::TokenWallet;

use crate::producer::resolve::resolve;

Expand All @@ -23,8 +22,9 @@ pub async fn publish_iota_document(
document: IotaDocument,
governor_address: Bech32Address,
// secret_manager: &ExternSecretManager,
wallet: Wallet,
wallet: IotaWallet,
) -> Result<CoreDocument, ProducerError> {
// TODO: use `wallet.client()`
let client = match document.id().network_str() {
"rms" => Client::builder().with_primary_node(TESTNET_URL, None)?.finish().await?,
"smr" => Client::builder().with_primary_node(SHIMMER_URL, None)?.finish().await?,
Expand All @@ -44,24 +44,24 @@ pub async fn publish_iota_document(
info!("No AliasOutput found for the given Governor address.");

// Create account with alias: "0" (default)
let account = wallet
.create_account()
.finish()
.await
.map_err(|e| ProducerError::WalletError(e.into()))?;

let funding_address = &account
.addresses()
.await
.unwrap()
.first()
.unwrap()
.clone()
.into_bech32();
// let account = wallet
// .create_account()
// .finish()
// .await
// .map_err(|e| ProducerError::WalletError(e.into()))?;

let funding_address = &wallet.get_funding_address().await;
// .addresses()
// .await
// .unwrap()
// .first()
// .unwrap()
// .clone()
// .into_bech32();
// let funding_address: Bech32Address = wallet.generate_ed25519_address(0, 0, None).await.unwrap();

// Check available funds for storage deposit
let balance = get_address_balance(&funding_address).await?;
let balance = wallet.get_balance(&funding_address.to_string()).await?;

// calculate_storage_deposit(&client).await?;
// TODO: temporary hardcoded: check if balance is enough for storage deposit
Expand All @@ -73,7 +73,8 @@ pub async fn publish_iota_document(
}

// TODO: send exact amount of funds from funding_address to governor_address
fund_storage_deposit(&account, governor_address).await?;
// fund_storage_deposit(&account, governor_address).await?;
wallet.fund_storage_deposit().await?;

// Create new Alias
let alias_output = client
Expand All @@ -91,9 +92,9 @@ pub async fn publish_iota_document(
// TODO: handle different types of errors:
// - no funding at all: "publish failed: no input with matching ed25519 address provided"
// - too little funding: "publish failed: insufficient amount: found 42601, required 89300"
let document: IotaDocument = client
.publish_did_output(&wallet.get_secret_manager().blocking_read(), alias_output)
.await?;
// let document: IotaDocument = client
// .publish_did_output(&wallet.get_secret_manager().blocking_read(), alias_output)
// .await?;

info!("Successfully published AliasOutput.");
document.core_document().to_owned()
Expand Down Expand Up @@ -161,6 +162,7 @@ mod tests {
Password,
},
wallet::ClientOptions,
Wallet,
};
use test_log::test;

Expand All @@ -184,22 +186,24 @@ mod tests {
let governor_address =
Bech32Address::try_from_str("rms1qzs0e5qrmljhmgcas9z3xs0v9ejjvfpcwhztfjcdq5slmfr48amwk7vl0xr").unwrap();

let secret_manager: ExternSecretManager = ExternSecretManager::Stronghold(
StrongholdSecretManager::builder()
.password(Password::from(PASSWORD.to_owned()))
.build(SNAPSHOT_PATH.to_owned())
.unwrap(),
);

let client_options = ClientOptions::new().with_node(TESTNET_URL).unwrap();
let coin_type = SHIMMER_COIN_TYPE;
let wallet = Wallet::builder()
.with_secret_manager(secret_manager)
.with_client_options(client_options)
.with_coin_type(coin_type)
.finish()
.await
.unwrap();
// let secret_manager: ExternSecretManager = ExternSecretManager::Stronghold(
// StrongholdSecretManager::builder()
// .password(Password::from(PASSWORD.to_owned()))
// .build(SNAPSHOT_PATH.to_owned())
// .unwrap(),
// );

// let client_options = ClientOptions::new().with_node(TESTNET_URL).unwrap();
// let coin_type = SHIMMER_COIN_TYPE;
// let wallet = Wallet::builder()
// .with_secret_manager(secret_manager)
// .with_client_options(client_options)
// .with_coin_type(coin_type)
// .finish()
// .await
// .unwrap();

let wallet = IotaWallet::new().await;

publish_iota_document(iota_document, governor_address, wallet)
.await
Expand Down
11 changes: 3 additions & 8 deletions did_jwk/src/producer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@ use identity_iota::core::Object;
use identity_iota::verification::VerificationMethod;
use identity_iota::{core::ToJson, did::CoreDID, document::CoreDocument, storage::KeyId};
use identity_stronghold::StrongholdStorage;
use iota_sdk::client::secret::stronghold::StrongholdSecretManager;
use iota_sdk::client::secret::SecretManager;
use iota_sdk::client::stronghold::StrongholdAdapter;
use iota_sdk::client::Password;
use log::info;
use serde_json::json;
use shared::test_utils::random_stronghold_path;
use shared::JwkStorageWrapper;
use ssi_dids::{DIDMethod, Source};
use std::io::Error;
Expand Down Expand Up @@ -76,14 +71,14 @@ mod tests {
use super::*;

use serde_json::json;
use shared::test_utils::new_stronghold_storage;
use shared::test_utils::new_stronghold;
use test_log::test;

#[test(tokio::test)]
async fn produces_did_jwk() {
let (stronghold_storage, key_id) = new_stronghold_storage().await;
let (stronghold_storage, key_id) = new_stronghold().await;

let storage = JwkStorageWrapper::Stronghold(stronghold_storage);
let storage = JwkStorageWrapper::Stronghold(StrongholdStorage::new(stronghold_storage));
let document = produce_did_jwk(storage, key_id.as_str()).await.unwrap();

assert_eq!(
Expand Down
7 changes: 4 additions & 3 deletions did_key/src/producer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use identity_iota::{
storage::KeyId,
verification::VerificationMethod,
};
use identity_stronghold::StrongholdStorage;
use log::info;
use serde_json::json;
use shared::JwkStorageWrapper;
Expand Down Expand Up @@ -66,14 +67,14 @@ mod tests {

use identity_iota::core::ToJson;
use serde_json::json;
use shared::test_utils::new_stronghold_storage;
use shared::test_utils::new_stronghold;
use test_log::test;

#[test(tokio::test)]
async fn produces_did_key() {
let (stronghold_storage, key_id) = new_stronghold_storage().await;
let (stronghold_storage, key_id) = new_stronghold().await;

let storage = JwkStorageWrapper::Stronghold(stronghold_storage);
let storage = JwkStorageWrapper::Stronghold(StrongholdStorage::new(stronghold_storage));
let document = produce_did_key(storage, &key_id).await.unwrap();

assert_eq!(
Expand Down
Loading

0 comments on commit 2865e66

Please sign in to comment.