Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split Secret Manager traits #1756

Closed
wants to merge 37 commits into from
Closed
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
48805bd
close
Dec 5, 2023
8c1f7f9
it lives!!!
Dec 6, 2023
ea20926
remove generics
Dec 7, 2023
8eebdef
overhaul
Dec 7, 2023
2f711dd
Merge branch '2.0' into feat/split-secret-manage
Dec 7, 2023
71d1c8a
Merge branch '2.0' into feat/split-secret-manage
Thoralf-M Dec 11, 2023
e2cb9a8
Add wallet_address_generation_custom_secret_manager test
Thoralf-M Dec 11, 2023
bdc2e7c
Merge branch '2.0' into feat/split-secret-manage
Jan 10, 2024
88ba8f7
Merge secret data with wallet key
Jan 10, 2024
3587c98
fix no_std
Jan 10, 2024
0570cb6
Merge branch '2.0' into feat/split-secret-manage
Jan 10, 2024
7c2814c
docs
Jan 10, 2024
fa21f9f
fix feature sets
Jan 10, 2024
4791224
fix merge
Jan 10, 2024
bf81382
feature gate
Jan 10, 2024
44914cf
more features
Jan 10, 2024
fa04b05
wasm
Jan 10, 2024
e8e9013
fix more gates
Jan 10, 2024
ff8d597
fix address generation
Jan 10, 2024
e67f74a
fix some more tests
Jan 10, 2024
10af7c5
fix address search
Jan 10, 2024
2ff960a
Merge branch '2.0' into feat/split-secret-manage
Jan 22, 2024
9b8a7f6
make tests easier to understand
Jan 22, 2024
490dc20
Update bindings/core/src/method/secret_manager.rs
Jan 22, 2024
a23329e
Merge branch '2.0' into feat/split-secret-manage
Jan 24, 2024
a6e5ec1
Merge branch '2.0' into feat/split-secret-manage
Jan 25, 2024
04ac636
Merge branch '2.0' into feat/split-secret-manage
Jan 25, 2024
a3b1d75
make signing options default to null
Jan 30, 2024
fa4e0a3
Merge branch '2.0' into feat/split-secret-manage
Jan 30, 2024
193300f
comments
Jan 31, 2024
03767ec
Merge branch '2.0' into feat/split-secret-manage
Jan 31, 2024
078c013
Merge branch '2.0' into feat/split-secret-manage
Feb 2, 2024
9dcf11d
remove generate_random
Feb 2, 2024
99bc0dd
make public key opts mutable
Feb 5, 2024
44c3c4d
Merge branch '2.0' into feat/split-secret-manage
Feb 5, 2024
b79e361
cleanup
Feb 9, 2024
a9690a4
Merge branch '2.0' into feat/split-secret-manage
Feb 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions bindings/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,13 @@ mod response;

use std::fmt::{Formatter, Result as FmtResult};

use crypto::keys::bip44::Bip44;
use derivative::Derivative;
use fern_logger::{logger_init, LoggerConfig, LoggerOutputConfigBuilder};
pub use iota_sdk;
use iota_sdk::{
client::secret::{SecretManager, SecretManagerDto},
types::block::address::Bech32Address,
utils::serde::bip44::option_bip44,
wallet::{ClientOptions, Wallet},
wallet::{core::SecretData, ClientOptions, Wallet, WalletBuilder},
};
use serde::Deserialize;

Expand All @@ -46,8 +44,10 @@ pub fn init_logger(config: String) -> std::result::Result<(), fern_logger::Error
pub struct WalletOptions {
pub address: Option<Bech32Address>,
pub alias: Option<String>,
#[serde(with = "option_bip44", default)]
pub bip_path: Option<Bip44>,
#[serde(default)]
pub public_key_options: Option<serde_json::Value>,
#[serde(default)]
pub signing_options: Option<serde_json::Value>,
pub client_options: Option<ClientOptions>,
#[derivative(Debug(format_with = "OmittedDebug::omitted_fmt"))]
pub secret_manager: Option<SecretManagerDto>,
Expand All @@ -65,8 +65,13 @@ impl WalletOptions {
self
}

pub fn with_bip_path(mut self, bip_path: impl Into<Option<Bip44>>) -> Self {
self.bip_path = bip_path.into();
pub fn with_public_key_options(mut self, public_key_options: impl Into<Option<serde_json::Value>>) -> Self {
self.public_key_options = public_key_options.into();
self
}

pub fn with_signing_options(mut self, signing_options: impl Into<Option<serde_json::Value>>) -> Self {
self.signing_options = signing_options.into();
self
}

Expand All @@ -86,12 +91,13 @@ impl WalletOptions {
self
}

pub async fn build(self) -> iota_sdk::wallet::Result<Wallet> {
pub async fn build(self) -> iota_sdk::wallet::Result<Wallet<SecretData<SecretManager>>> {
log::debug!("wallet options: {self:?}");
let mut builder = Wallet::builder()
let mut builder = WalletBuilder::new()
.with_address(self.address)
.with_alias(self.alias)
.with_bip_path(self.bip_path)
.with_public_key_options(self.public_key_options)
.with_signing_options(self.signing_options)
.with_client_options(self.client_options);

#[cfg(feature = "storage")]
Expand Down
87 changes: 48 additions & 39 deletions bindings/core/src/method/secret_manager.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
// Copyright 2023 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use crypto::keys::bip44::Bip44;
use derivative::Derivative;
use iota_sdk::{
client::api::{GetAddressesOptions, PreparedTransactionDataDto},
types::block::{protocol::ProtocolParameters, UnsignedBlockDto},
utils::serde::bip44::Bip44Def,
client::api::PreparedTransactionDataDto,
types::block::{address::Hrp, protocol::ProtocolParameters, UnsignedBlockDto},
};
use serde::{Deserialize, Serialize};

Expand All @@ -20,12 +18,15 @@ use crate::OmittedDebug;
#[non_exhaustive]
pub enum SecretManagerMethod {
/// Generate Ed25519 addresses.
#[serde(rename_all = "camelCase")]
GenerateEd25519Addresses {
DaughterOfMars marked this conversation as resolved.
Show resolved Hide resolved
/// The Bech32 human-readable part
bech32_hrp: Hrp,
/// Addresses generation options
options: GetAddressesOptions,
options: serde_json::Value,
},
/// Generate Evm addresses.
GenerateEvmAddresses { options: GetAddressesOptions },
GenerateEvmAddresses { options: serde_json::Value },
/// Get the ledger status
/// Expected response: [`LedgerNanoStatus`](crate::Response::LedgerNanoStatus)
#[cfg(feature = "ledger_nano")]
Expand All @@ -36,40 +37,45 @@ pub enum SecretManagerMethod {
SignatureUnlock {
/// Transaction signing hash
transaction_signing_hash: String,
/// Chain used to sign the hash
#[serde(with = "Bip44Def")]
chain: Bip44,
/// Options used to sign the hash
#[serde(default)]
signing_options: serde_json::Value,
Thoralf-M marked this conversation as resolved.
Show resolved Hide resolved
},
/// Signs a message with an Ed25519 private key.
#[serde(rename_all = "camelCase")]
SignEd25519 {
/// The message to sign, hex encoded String
message: String,
/// Chain used to sign the message
#[serde(with = "Bip44Def")]
chain: Bip44,
/// Options used to sign the message
#[serde(default)]
signing_options: serde_json::Value,
},
/// Signs a message with an Secp256k1Ecdsa private key.
#[serde(rename_all = "camelCase")]
SignSecp256k1Ecdsa {
/// The message to sign, hex encoded String
message: String,
/// Chain used to sign the message
#[serde(with = "Bip44Def")]
chain: Bip44,
/// Options used to sign the hash
#[serde(default)]
signing_options: serde_json::Value,
},
/// Sign a transaction
#[serde(rename_all = "camelCase")]
SignTransaction {
/// Prepared transaction data
prepared_transaction_data: PreparedTransactionDataDto,
protocol_parameters: Box<ProtocolParameters>,
/// Options used to sign the transaction
#[serde(default)]
signing_options: serde_json::Value,
},
// Sign a block.
#[serde(rename_all = "camelCase")]
SignBlock {
unsigned_block: UnsignedBlockDto,
/// Chain used to sign the block
#[serde(with = "Bip44Def")]
chain: Bip44,
/// Options used to sign the block
#[serde(default)]
signing_options: serde_json::Value,
},
/// Store a mnemonic in the Stronghold vault
#[cfg(feature = "stronghold")]
Expand Down Expand Up @@ -104,68 +110,71 @@ pub enum SecretManagerMethod {

#[cfg(test)]
mod test {
use crypto::keys::bip44::Bip44;
use iota_sdk::client::constants::{ETHER_COIN_TYPE, IOTA_COIN_TYPE};
use pretty_assertions::assert_eq;

#[test]
fn bip44_deserialization() {
let signature_unlock_method: super::SecretManagerMethod = serde_json::from_str(
r#"{"name": "signatureUnlock", "data": {"transactionSigningHash": "txhash", "chain": {"addressIndex": 1}}}"#,
)
.unwrap();
let signature_unlock_method = super::SecretManagerMethod::SignatureUnlock {
transaction_signing_hash: "txhash".to_owned(),
signing_options: serde_json::to_value(Bip44::new(IOTA_COIN_TYPE).with_address_index(1)).unwrap(),
};

assert_eq!(
serde_json::to_value(&signature_unlock_method).unwrap(),
serde_json::json!({
"name": "signatureUnlock",
"data": {
"transactionSigningHash": "txhash",
"chain": {
"coinType": 4218,
"signingOptions": {
"coin_type": 4218,
"account": 0,
"change": 0,
"addressIndex": 1
"address_index": 1
}
}
})
);

let sign_ed25519_method: super::SecretManagerMethod = serde_json::from_str(
r#"{"name": "signEd25519", "data": {"message": "0xFFFFFFFF", "chain": {"coinType": 60, "change": 1}}}"#,
)
.unwrap();
let sign_ed25519_method = super::SecretManagerMethod::SignEd25519 {
message: "0xFFFFFFFF".to_owned(),
signing_options: serde_json::to_value(Bip44::new(ETHER_COIN_TYPE).with_change(1)).unwrap(),
};

assert_eq!(
serde_json::to_value(&sign_ed25519_method).unwrap(),
serde_json::json!({
"name": "signEd25519",
"data": {
"message": "0xFFFFFFFF",
"chain": {
"coinType": 60,
"signingOptions": {
"coin_type": 60,
"account": 0,
"change": 1,
"addressIndex": 0
"address_index": 0
}
}
})
);

let sign_secp256k1_ecdsa_method: super::SecretManagerMethod = serde_json::from_str(
r#"{"name": "signSecp256k1Ecdsa", "data": {"message": "0xFFFFFFFF", "chain": {"account": 2, "addressIndex": 1}}}"#,
)
.unwrap();
let sign_secp256k1_ecdsa_method = super::SecretManagerMethod::SignSecp256k1Ecdsa {
message: "0xFFFFFFFF".to_owned(),
signing_options: serde_json::to_value(Bip44::new(IOTA_COIN_TYPE).with_account(2).with_address_index(1))
.unwrap(),
};

assert_eq!(
serde_json::to_value(&sign_secp256k1_ecdsa_method).unwrap(),
serde_json::json!({
"name": "signSecp256k1Ecdsa",
"data": {
"message": "0xFFFFFFFF",
"chain": {
"coinType": 4218,
"signingOptions": {
"coin_type": 4218,
"account": 2,
"change": 0,
"addressIndex": 1
"address_index": 1
}
}
})
Expand Down
17 changes: 1 addition & 16 deletions bindings/core/src/method/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#[cfg(feature = "stronghold")]
use std::path::PathBuf;

use crypto::keys::bip44::Bip44;
use derivative::Derivative;
#[cfg(feature = "events")]
use iota_sdk::wallet::events::types::{WalletEvent, WalletEventType};
Expand All @@ -18,7 +17,6 @@ use iota_sdk::{
client::{
api::{input_selection::Burn, PreparedTransactionDataDto, SignedTransactionDataDto},
node_manager::node::NodeAuth,
secret::GenerateAddressOptions,
},
types::block::{
address::{Bech32Address, Hrp},
Expand Down Expand Up @@ -200,7 +198,7 @@ pub enum WalletMethod {
#[serde(default)]
public_key: Option<String>,
#[serde(default)]
bip_path: Option<Bip44>,
public_key_options: Option<serde_json::Value>,
},
/// Returns the implicit accounts of the wallet.
/// Expected response: [`OutputsData`](crate::Response::OutputsData)
Expand Down Expand Up @@ -441,19 +439,6 @@ pub enum WalletMethod {
EmitTestEvent { event: WalletEvent },

// TODO: reconsider whether to have the following methods on the wallet
/// Generate an address without storing it
/// Expected response: [`Bech32Address`](crate::Response::Bech32Address)
#[serde(rename_all = "camelCase")]
GenerateEd25519Address {
/// Account index
account_index: u32,
/// Account index
address_index: u32,
/// Options
options: Option<GenerateAddressOptions>,
/// Bech32 HRP
bech32_hrp: Option<Hrp>,
},
/// Get the ledger nano status
/// Expected response: [`LedgerNanoStatus`](crate::Response::LedgerNanoStatus)
#[cfg(feature = "ledger_nano")]
Expand Down
19 changes: 5 additions & 14 deletions bindings/core/src/method_handler/call_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ use std::pin::Pin;

use futures::Future;
use iota_sdk::{
client::{
secret::{DowncastSecretManager, SecretManage},
Client,
},
wallet::Wallet,
client::{secret::SecretManager, Client},
wallet::{core::SecretData, Wallet},
};

use crate::{
Expand Down Expand Up @@ -38,7 +35,7 @@ impl CallMethod for Client {
}
}

impl CallMethod for Wallet {
impl CallMethod for Wallet<SecretData<SecretManager>> {
type Method = WalletMethod;

fn call_method<'a>(&'a self, method: Self::Method) -> Pin<Box<dyn Future<Output = Response> + 'a>> {
Expand All @@ -58,7 +55,7 @@ pub async fn call_client_method(client: &Client, method: ClientMethod) -> Respon
}

/// Call a wallet method.
pub async fn call_wallet_method(wallet: &Wallet, method: WalletMethod) -> Response {
pub async fn call_wallet_method(wallet: &Wallet<SecretData<SecretManager>>, method: WalletMethod) -> Response {
log::debug!("Wallet method: {method:?}");
let result = convert_async_panics(|| async { call_wallet_method_internal(wallet, method).await }).await;

Expand All @@ -80,13 +77,7 @@ pub fn call_utils_method(method: UtilsMethod) -> Response {
}

/// Call a secret manager method.
pub async fn call_secret_manager_method<S: SecretManage + DowncastSecretManager>(
secret_manager: &S,
method: SecretManagerMethod,
) -> Response
where
iota_sdk::client::Error: From<S::Error>,
{
pub async fn call_secret_manager_method(secret_manager: &SecretManager, method: SecretManagerMethod) -> Response {
log::debug!("Secret manager method: {method:?}");
let result =
convert_async_panics(|| async { call_secret_manager_method_internal(secret_manager, method).await }).await;
Expand Down
Loading