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

Remove ed25519 address generation from wallet #1586

Merged
Show file tree
Hide file tree
Changes from 69 commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
8fd2992
rm ed25519 address generation from wallet
Alex6323 Nov 7, 2023
a3826bf
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Dec 6, 2023
008c863
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Dec 6, 2023
565a28b
rename fn
Alex6323 Dec 7, 2023
e8e05fc
rm with_address
Alex6323 Dec 7, 2023
456c5e5
update bindings
Alex6323 Dec 7, 2023
4b683d2
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Dec 7, 2023
9900a5d
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Thoralf-M Dec 11, 2023
5aee8e9
handle builder address cases
Alex6323 Dec 11, 2023
f84767d
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Dec 11, 2023
847785f
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Jan 23, 2024
b528ed8
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Jan 31, 2024
2f1dd63
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Feb 1, 2024
e5fd7d9
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Feb 12, 2024
a3cc197
unused import
Alex6323 Feb 12, 2024
f1182d8
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Feb 16, 2024
6f2b916
re-add address to wallet options
Alex6323 Feb 16, 2024
31e04ff
fix tests
Alex6323 Feb 18, 2024
1d23230
re-enable placeholder test
Alex6323 Feb 18, 2024
f707397
move tests
Alex6323 Feb 18, 2024
35da3bb
nodejs: address to wallet options
Alex6323 Feb 19, 2024
e0e8ba2
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Feb 19, 2024
dc5533a
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Feb 19, 2024
2532bbd
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Feb 20, 2024
916306a
revert going through json file for address
Alex6323 Feb 20, 2024
37308ae
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Feb 20, 2024
61324e6
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Feb 21, 2024
0d9d0f0
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Feb 21, 2024
137edeb
revert unrelated change
Alex6323 Feb 21, 2024
f9e3f68
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Feb 23, 2024
b98ba06
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Feb 23, 2024
cbae7f8
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Feb 23, 2024
2a61956
Update sdk/tests/client/secret_manager/address_generation.rs
thibault-martinez Feb 27, 2024
fad9849
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Feb 29, 2024
9cdfe39
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Feb 29, 2024
79ff6ae
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Mar 1, 2024
1f0da78
recipient
Alex6323 Mar 1, 2024
40dc8c3
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Mar 4, 2024
1c02b2a
bad wildcards
Alex6323 Mar 4, 2024
ad69324
PR suggestion
Alex6323 Mar 4, 2024
ec1915f
import
Alex6323 Mar 4, 2024
0d957c1
example doc
Alex6323 Mar 4, 2024
f80d2ce
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Mar 5, 2024
e8e450b
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
thibault-martinez Mar 5, 2024
0ae1791
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Mar 5, 2024
077f4aa
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Mar 5, 2024
623cd8b
fix example
Alex6323 Mar 5, 2024
2fb4b53
rename generate methods
Alex6323 Mar 6, 2024
beb50b4
Core: add SecretManager:GenerateEd25519AddressAsBech32 method
Alex6323 Mar 6, 2024
f056d0a
update examples and tests
Alex6323 Mar 6, 2024
d015eac
Core: simplify SecretManager:GenerateEd25519AddressAsBech32 method
Alex6323 Mar 6, 2024
89e6ac3
Python: update binding
Alex6323 Mar 6, 2024
c20b755
nit
Alex6323 Mar 6, 2024
d586235
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Mar 6, 2024
da0a295
core: undo rename; update docs
Alex6323 Mar 7, 2024
80dd4f4
add todo
Alex6323 Mar 7, 2024
0348aa6
Python: nits
Alex6323 Mar 7, 2024
eb70061
NodeJs: add binding method
Alex6323 Mar 7, 2024
602457a
nit
Alex6323 Mar 7, 2024
82078b7
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Mar 7, 2024
0804101
sdk: undo rename; format
Alex6323 Mar 7, 2024
b53e401
core: import
Alex6323 Mar 7, 2024
cce3be4
NodeJs: method suffix
Alex6323 Mar 7, 2024
4170fa6
fix test
Alex6323 Mar 7, 2024
20fb18f
nit
Alex6323 Mar 7, 2024
fbad591
remove single address generation binding
Alex6323 Mar 7, 2024
853bcb0
Python: small fix
Alex6323 Mar 7, 2024
1a02e15
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Mar 7, 2024
73b576f
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
thibault-martinez Mar 7, 2024
aca3007
Merge branch '2.0' into refactor/wallet/remove-ed25519-address-genera…
Alex6323 Mar 7, 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
2 changes: 1 addition & 1 deletion bindings/core/src/method/secret_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::OmittedDebug;
#[serde(tag = "name", content = "data", rename_all = "camelCase")]
#[non_exhaustive]
pub enum SecretManagerMethod {
/// Generate Ed25519 addresses.
/// Generate multiple Ed25519 addresses at once.
GenerateEd25519Addresses {
/// Addresses generation options
options: GetAddressesOptions,
Expand Down
21 changes: 2 additions & 19 deletions bindings/core/src/method/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use std::path::PathBuf;

use crypto::keys::bip44::Bip44;
use derivative::Derivative;
use iota_sdk::client::api::options::TransactionOptions;
#[cfg(feature = "events")]
use iota_sdk::wallet::events::types::{WalletEvent, WalletEventType};
use iota_sdk::{client::api::options::TransactionOptions, utils::serde::string};
// #[cfg(feature = "participation")]
// use iota_sdk::{
// client::node_manager::node::Node,
Expand All @@ -19,10 +19,9 @@ use iota_sdk::{
client::{
api::{transaction_builder::Burn, PreparedTransactionDataDto, SignedTransactionDataDto},
node_manager::node::NodeAuth,
secret::GenerateAddressOptions,
},
types::block::{
address::{Bech32Address, Hrp},
address::Hrp,
output::{AccountId, DelegationId, Output, OutputId, TokenId},
payload::signed_transaction::TransactionId,
},
Expand Down Expand Up @@ -456,27 +455,11 @@ pub enum WalletMethod {
/// Expected response: [`OutputsData`](crate::Response::OutputsData)
#[serde(rename_all = "camelCase")]
UnspentOutputs { filter_options: Option<FilterOptions> },

/// Emits an event for testing if the event system is working
/// Expected response: [`Ok`](crate::Response::Ok)
#[cfg(feature = "events")]
#[cfg_attr(docsrs, doc(cfg(feature = "events")))]
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
22 changes: 1 addition & 21 deletions bindings/core/src/method_handler/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ use std::time::Duration;
use crypto::signatures::ed25519::PublicKey;
use iota_sdk::{
client::api::{PreparedTransactionData, SignedTransactionData, SignedTransactionDataDto},
types::{
block::{address::ToBech32Ext, output::feature::BlockIssuerKeySource},
TryFromDto,
},
types::{block::output::feature::BlockIssuerKeySource, TryFromDto},
wallet::{types::TransactionWithMetadataDto, Wallet},
};

Expand Down Expand Up @@ -73,23 +70,6 @@ pub(crate) async fn call_wallet_method_internal(
let ledger_nano_status = wallet.get_ledger_nano_status().await?;
Response::LedgerNanoStatus(ledger_nano_status)
}
WalletMethod::GenerateEd25519Address {
account_index,
address_index,
options,
bech32_hrp,
} => {
let address = wallet
.generate_ed25519_address(account_index, address_index, options)
.await?;

let bech32_hrp = match bech32_hrp {
Some(bech32_hrp) => bech32_hrp,
None => *wallet.address().await.hrp(),
};

Response::Bech32Address(address.to_bech32(bech32_hrp))
}
#[cfg(feature = "stronghold")]
WalletMethod::SetStrongholdPassword { password } => {
wallet.set_stronghold_password(password).await?;
Expand Down
11 changes: 0 additions & 11 deletions bindings/nodejs/examples/how_tos/wallet/create-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,7 @@ async function run() {
// The mnemonic can't be retrieved from the Stronghold file, so make a backup in a secure place!
await secretManager.storeMnemonic(process.env.MNEMONIC as string);

const walletAddress = await secretManager.generateEd25519Addresses({
Alex6323 marked this conversation as resolved.
Show resolved Hide resolved
coinType: CoinType.IOTA,
accountIndex: 0,
range: {
start: 0,
end: 1,
},
bech32Hrp: 'tst',
});

const walletOptions: WalletOptions = {
address: walletAddress[0],
storagePath: process.env.WALLET_DB_PATH,
clientOptions: {
nodes: [process.env.NODE_URL as string],
Expand Down
11 changes: 0 additions & 11 deletions bindings/nodejs/examples/wallet/getting-started.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,7 @@ async function run() {
// The mnemonic can't be retrieved from the Stronghold file, so make a backup in a secure place!
await secretManager.storeMnemonic(mnemonic);

const wallet_address = await secretManager.generateEd25519Addresses({
coinType: CoinType.IOTA,
accountIndex: 0,
range: {
start: 0,
end: 1,
},
bech32Hrp: 'tst',
});

const walletOptions: WalletOptions = {
address: wallet_address[0],
storagePath: WALLET_DB_PATH,
clientOptions: {
nodes: [NODE_URL as string],
Expand Down
5 changes: 3 additions & 2 deletions bindings/nodejs/lib/secret_manager/secret-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
UnsignedBlock,
Block,
parseBlock,
Bech32Address,
} from '../types';

import { plainToInstance } from 'class-transformer';
Expand All @@ -44,14 +45,14 @@ export class SecretManager {
}

/**
* Generate Ed25519 addresses.
* Generate multiple Ed25519 addresses at once.
*
* @param generateAddressesOptions Options to generate addresses.
* @returns An array of generated addresses.
*/
async generateEd25519Addresses(
generateAddressesOptions: GenerateAddressesOptions,
): Promise<string[]> {
): Promise<Bech32Address[]> {
const response = await this.methodHandler.callMethod({
name: 'generateEd25519Addresses',
data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import type { CoinType } from './constants';
import type { Range } from './range';

// TODO: Rename (to GetAddressOptions) and refactor (move out range field),
// so we can use it for the single address generation method as well?
/**
* Input options for GenerateAddresses
*/
Expand Down
2 changes: 1 addition & 1 deletion bindings/nodejs/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ pub async fn get_client(wallet: External<WalletMethodHandler>) -> Result<Externa
#[napi(js_name = "getSecretManager")]
pub async fn get_secret_manager(wallet: External<WalletMethodHandler>) -> Result<External<SecretManagerMethodHandler>> {
if let Some(wallet) = &**wallet.as_ref().read().await {
Ok(External::new(wallet.get_secret_manager().clone()))
Ok(External::new(wallet.secret_manager().clone()))
} else {
Err(destroyed_err("Wallet"))
}
Expand Down
48 changes: 48 additions & 0 deletions bindings/nodejs/tests/secret_manager/secret_manager.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2023 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import 'reflect-metadata';

import { describe, it, expect } from '@jest/globals';
import {
CoinType,
SecretManager,
Utils,
} from '../../lib/';

describe('SecretManager', () => {
it('generate IOTA Ed25519 address', async () => {
const mnemonicSecretManager = {
mnemonic: "acoustic trophy damage hint search taste love bicycle foster cradle brown govern endless depend situate athlete pudding blame question genius transfer van random vast"
};

let bech32_hrp = Utils.iotaMainnetProtocolParameters().bech32Hrp;

const secretManager = SecretManager.create(mnemonicSecretManager);
const addresses = await secretManager.generateEd25519Addresses({
DaughterOfMars marked this conversation as resolved.
Show resolved Hide resolved
coinType: CoinType.IOTA,
bech32Hrp: bech32_hrp,
});

expect(addresses[0]).toEqual('iota1qpg2xkj66wwgn8p2ggnp7p582gj8g6p79us5hve2tsudzpsr2ap4skprwjg');

}, 20000);

it('generate Shimmer Ed25519 address', async () => {
const mnemonicSecretManager = {
mnemonic: "acoustic trophy damage hint search taste love bicycle foster cradle brown govern endless depend situate athlete pudding blame question genius transfer van random vast"
};

let bech32_hrp = Utils.shimmerMainnetProtocolParameters().bech32Hrp;

const secretManager = SecretManager.create(mnemonicSecretManager);
const addresses = await secretManager.generateEd25519Addresses({
coinType: CoinType.Shimmer,
bech32Hrp: bech32_hrp,
range: { start: 0, end: 1 },
});

expect(addresses[0]).toEqual('smr1qzev36lk0gzld0k28fd2fauz26qqzh4hd4cwymlqlv96x7phjxcw6ckj80y');

}, 20000);
});
55 changes: 50 additions & 5 deletions bindings/python/iota_sdk/secret_manager/secret_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,24 +125,69 @@ def _call_method(self, name, data=None):
return json_response['payload']
return response

# TODO: Should we include `bech32` in the method name?
def generate_ed25519_address(self,
coin_type: int,
bech32_hrp: str,
account_index: Optional[int] = None,
address_index: Optional[int] = None,
internal: Optional[bool] = None,
legder_nano_prompt: Optional[bool] = None):
"""Generate a single Ed25519 address.

Args:
coin_type: The coin type to generate the address for.
bech32_hrp: The bech32 HRP (human readable part) to use.
account_index: An account index.
address_index: An address index.
internal: Whether the generated address should be internal.
ledger_nano_prompt: Whether to display the address on Ledger Nano devices.

Returns:
The generated Ed25519 address.
"""

options = {}
options['coinType'] = coin_type
options['bech32Hrp'] = bech32_hrp
if address_index is not None:
options['range'] = {}
options['range']['start'] = address_index
options['range']['end'] = address_index + 1
if account_index is not None:
options['accountIndex'] = account_index
if internal is not None or legder_nano_prompt is not None:
options['options'] = {}
if internal is not None:
options['options']['internal'] = internal
if legder_nano_prompt is not None:
options['options']['ledgerNanoPrompot'] = legder_nano_prompt

return self._call_method('generateEd25519Addresses', {
'options': options
})[0]

# pylint: disable=unused-argument

# TODO: Should `coin_type` and `bech32_hrp` be mandatory to provide?
# TODO: Should we include `bech32` in the method name?
def generate_ed25519_addresses(self,
coin_type: Optional[int] = None,
bech32_hrp: Optional[str] = None,
account_index: Optional[int] = None,
start: Optional[int] = None,
end: Optional[int] = None,
internal: Optional[bool] = None,
coin_type: Optional[int] = None,
bech32_hrp: Optional[str] = None,
ledger_nano_prompt: Optional[bool] = None):
"""Generate Ed25519 addresses.
"""Generate multiple Ed25519 addresses at once.

Args:
coin_type: The coin type to generate addresses for.
bech32_hrp: The bech32 HRP (human readable part) to use.
account_index: An account index.
start: The start index of the addresses to generate.
end: The end index of the addresses to generate.
internal: Whether the generated addresses should be internal.
coin_type: The coin type to generate addresses for.
bech32_hrp: The bech32 HRP (human readable part) to use.
ledger_nano_prompt: Whether to display the address on Ledger Nano devices.

Returns:
Expand Down
2 changes: 1 addition & 1 deletion bindings/python/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ pub fn get_secret_manager_from_wallet(wallet: &Wallet) -> Result<SecretManager,
.read()
.await
.as_ref()
.map(|w| w.get_secret_manager().clone())
.map(|w| w.secret_manager().clone())
.ok_or_else(|| {
Error::from(
serde_json::to_string(&Response::Panic("wallet was destroyed".into()))
Expand Down
24 changes: 24 additions & 0 deletions bindings/python/tests/test_secret_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2023 IOTA Stiftung
# SPDX-License-Identifier: Apache-2.0

from iota_sdk import MnemonicSecretManager, SecretManager, CoinType, Utils


def test_secret_manager_address_generation_iota():
secret_manager = SecretManager(MnemonicSecretManager(
"acoustic trophy damage hint search taste love bicycle foster cradle brown govern endless depend situate athlete pudding blame question genius transfer van random vast"))

bech32_hrp = Utils.iota_mainnet_protocol_parameters().bech32_hrp
address = secret_manager.generate_ed25519_address(CoinType.IOTA, bech32_hrp)

assert 'iota1qpg2xkj66wwgn8p2ggnp7p582gj8g6p79us5hve2tsudzpsr2ap4skprwjg' == address


def test_secret_manager_address_generation_shimmer():
secret_manager = SecretManager(MnemonicSecretManager(
"acoustic trophy damage hint search taste love bicycle foster cradle brown govern endless depend situate athlete pudding blame question genius transfer van random vast"))

bech32_hrp = Utils.shimmer_mainnet_protocol_parameters().bech32_hrp
address = secret_manager.generate_ed25519_address(CoinType.SHIMMER, bech32_hrp)

assert 'smr1qzev36lk0gzld0k28fd2fauz26qqzh4hd4cwymlqlv96x7phjxcw6ckj80y' == address
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from iota_sdk import Wallet, MnemonicSecretManager, CoinType, ClientOptions, WalletOptions, Bip44, Utils


def test_address_generation_iota():
db_path = './test_address_generation_iota'
def test_wallet_address_iota():
db_path = './test_wallet_address_iota'
shutil.rmtree(db_path, ignore_errors=True)

client_options = ClientOptions(
Expand All @@ -33,8 +33,8 @@ def test_address_generation_iota():
shutil.rmtree(db_path, ignore_errors=True)


def test_address_generation_shimmer():
db_path = './test_address_generation_shimmer'
def test_wallet_address_shimmer():
db_path = './test_wallet_address_shimmer'
shutil.rmtree(db_path, ignore_errors=True)

client_options = ClientOptions(
Expand Down
2 changes: 1 addition & 1 deletion bindings/wasm/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub async fn get_client(method_handler: &WalletMethodHandler) -> Result<ClientMe
#[wasm_bindgen(js_name = getSecretManager)]
pub async fn get_secret_manager(method_handler: &WalletMethodHandler) -> Result<SecretManagerMethodHandler, JsError> {
if let Some(wallet) = &*method_handler.0.read().await {
Ok(SecretManagerMethodHandler::new(wallet.get_secret_manager().clone()))
Ok(SecretManagerMethodHandler::new(wallet.secret_manager().clone()))
} else {
// Notify that the wallet was destroyed
Err(destroyed_err("Wallet"))
Expand Down
2 changes: 1 addition & 1 deletion cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ pub async fn new_wallet(cli: Cli) -> Result<Option<Wallet>, Error> {
if storage_path.is_dir() {
match Wallet::builder().with_storage_path(storage_path).finish().await {
Ok(wallet) => {
let linked_secret_manager = match &mut *wallet.get_secret_manager().write().await {
let linked_secret_manager = match &mut *wallet.secret_manager().write().await {
SecretManager::Stronghold(stronghold) => {
let snapshot_path = stronghold.snapshot_path().to_path_buf();
let snapshot_exists = snapshot_path.exists();
Expand Down
2 changes: 1 addition & 1 deletion cli/src/wallet_cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1377,7 +1377,7 @@ pub enum PromptResponse {
}

async fn ensure_password(wallet: &Wallet) -> Result<(), Error> {
if matches!(*wallet.get_secret_manager().read().await, SecretManager::Stronghold(_))
if matches!(*wallet.secret_manager().read().await, SecretManager::Stronghold(_))
&& !wallet.is_stronghold_password_available().await?
{
let password = get_password("Stronghold password", false)?;
Expand Down
Loading
Loading