Merge pull request 'feat(dubp): add transparent BIP32 wallet' (#12) from dubp/transparent-bip32 into master
Reviewed-on: #12
This commit is contained in:
commit
2c5237b9bc
|
@ -261,9 +261,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dup-crypto"
|
name = "dup-crypto"
|
||||||
version = "0.40.0"
|
version = "0.41.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ba9cba3d83bf946b9e2d3b444f98df563d6ffefa94579bdfc6f06b158cd872a9"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
|
|
|
@ -7,4 +7,4 @@ codegen-units = 1
|
||||||
debug = true
|
debug = true
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
#dup-crypto = { path = "/home/elois/dev/duniter/libs/dubp-rs-libs/crypto" }
|
dup-crypto = { path = "/home/elois/dev/duniter/libs/dubp-rs-libs/crypto" }
|
||||||
|
|
|
@ -10,7 +10,7 @@ crate-type = ["rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
allo-isolate = "0.1.6"
|
allo-isolate = "0.1.6"
|
||||||
dup-crypto = { version = "0.40.0", features = ["bip32-ed25519", "dewif", "mnemonic", "mnemonic_french", "rand", "scrypt"] }
|
dup-crypto = { version = "0.41.0", features = ["bip32-ed25519", "dewif", "mnemonic", "mnemonic_french", "rand", "scrypt"] }
|
||||||
fast-threadpool = { version = "0.3.0", default-features = false }
|
fast-threadpool = { version = "0.3.0", default-features = false }
|
||||||
once_cell = { version = "1.3.1", default-features = false, features = ["std"] }
|
once_cell = { version = "1.3.1", default-features = false, features = ["std"] }
|
||||||
thiserror = "1.0.23"
|
thiserror = "1.0.23"
|
||||||
|
|
|
@ -13,6 +13,9 @@
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
pub mod bip32;
|
||||||
|
pub mod classic;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
pub(super) fn change_secret_code(
|
pub(super) fn change_secret_code(
|
||||||
|
@ -24,23 +27,16 @@ pub(super) fn change_secret_code(
|
||||||
system_memory: i64,
|
system_memory: i64,
|
||||||
) -> Result<Vec<String>, DubpError> {
|
) -> Result<Vec<String>, DubpError> {
|
||||||
let currency = parse_currency(currency)?;
|
let currency = parse_currency(currency)?;
|
||||||
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
|
let new_log_n = log_n(system_memory);
|
||||||
ExpectedCurrency::Specific(currency),
|
let new_secret_code = gen_secret_code(member_wallet, secret_code_type, new_log_n)?;
|
||||||
dewif,
|
|
||||||
old_secret_code,
|
|
||||||
)
|
|
||||||
.map_err(DubpError::DewifReadError)?;
|
|
||||||
if let Some(KeyPairEnum::Ed25519(keypair)) = keypairs.next() {
|
|
||||||
let log_n = log_n(system_memory);
|
|
||||||
let new_secret_code = gen_secret_code(member_wallet, secret_code_type, log_n)?;
|
|
||||||
|
|
||||||
let dewif =
|
let new_dewif =
|
||||||
dup_crypto::dewif::write_dewif_v3_content(currency, &keypair, log_n, &new_secret_code);
|
dup_crypto::dewif::change_dewif_passphrase(dewif, old_secret_code, &new_secret_code)
|
||||||
let pubkey = keypair.public_key().to_base58();
|
.map_err(DubpError::DewifReadError)?;
|
||||||
Ok(vec![dewif, new_secret_code, pubkey])
|
|
||||||
} else {
|
let pubkey = get_pubkey(currency, &new_dewif, &new_secret_code)?;
|
||||||
Err(DubpError::DewifReadError(DewifReadError::CorruptedContent))
|
|
||||||
}
|
Ok(vec![new_dewif, new_secret_code, pubkey])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn gen_dewif(
|
pub(super) fn gen_dewif(
|
||||||
|
@ -50,17 +46,37 @@ pub(super) fn gen_dewif(
|
||||||
member_wallet: bool,
|
member_wallet: bool,
|
||||||
secret_code_type: SecretCodeType,
|
secret_code_type: SecretCodeType,
|
||||||
system_memory: i64,
|
system_memory: i64,
|
||||||
|
wallet_type: WalletType,
|
||||||
) -> Result<Vec<String>, DubpError> {
|
) -> Result<Vec<String>, DubpError> {
|
||||||
let currency = parse_currency(currency)?;
|
let currency = parse_currency(currency)?;
|
||||||
let mnemonic =
|
let mnemonic =
|
||||||
Mnemonic::from_phrase(mnemonic, language).map_err(|_| DubpError::WrongLanguage)?;
|
Mnemonic::from_phrase(mnemonic, language).map_err(|_| DubpError::WrongLanguage)?;
|
||||||
let seed = dup_crypto::mnemonic::mnemonic_to_seed(&mnemonic);
|
let seed = dup_crypto::mnemonic::mnemonic_to_seed(&mnemonic);
|
||||||
let keypair = KeyPairFromSeed32Generator::generate(seed);
|
|
||||||
|
|
||||||
let log_n = log_n(system_memory);
|
let log_n = log_n(system_memory);
|
||||||
let secret_code = gen_secret_code(member_wallet, secret_code_type, log_n)?;
|
let secret_code = gen_secret_code(member_wallet, secret_code_type, log_n)?;
|
||||||
let dewif = dup_crypto::dewif::write_dewif_v3_content(currency, &keypair, log_n, &secret_code);
|
|
||||||
let pubkey = keypair.public_key().to_base58();
|
let (dewif, pubkey) = match wallet_type {
|
||||||
|
WalletType::Ed25519 => {
|
||||||
|
let keypair = dup_crypto::keys::ed25519::bip32::KeyPair::from_seed(seed.clone());
|
||||||
|
let pubkey = keypair.public_key();
|
||||||
|
let dewif = dup_crypto::dewif::write_dewif_v4_content(
|
||||||
|
currency,
|
||||||
|
log_n,
|
||||||
|
&secret_code,
|
||||||
|
&pubkey,
|
||||||
|
seed,
|
||||||
|
);
|
||||||
|
(dewif, pubkey.to_base58())
|
||||||
|
}
|
||||||
|
WalletType::Bip32Ed25519 => {
|
||||||
|
let keypair = KeyPairFromSeed32Generator::generate(seed);
|
||||||
|
let dewif =
|
||||||
|
dup_crypto::dewif::write_dewif_v3_content(currency, &keypair, log_n, &secret_code);
|
||||||
|
(dewif, keypair.public_key().to_base58())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(vec![dewif, secret_code, pubkey])
|
Ok(vec![dewif, secret_code, pubkey])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,54 +99,19 @@ pub(super) fn get_secret_code_len(
|
||||||
)?)
|
)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn get_pubkey(currency: Currency, dewif: &str, pin: &str) -> Result<String, DubpError> {
|
pub(super) fn get_pubkey(
|
||||||
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
|
currency: Currency,
|
||||||
ExpectedCurrency::Specific(currency),
|
|
||||||
dewif,
|
|
||||||
&pin.to_ascii_uppercase(),
|
|
||||||
)
|
|
||||||
.map_err(DubpError::DewifReadError)?;
|
|
||||||
if let Some(KeyPairEnum::Ed25519(keypair)) = keypairs.next() {
|
|
||||||
Ok(keypair.public_key().to_base58())
|
|
||||||
} else {
|
|
||||||
Err(DubpError::DewifReadError(DewifReadError::CorruptedContent))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn sign(currency: &str, dewif: &str, pin: &str, msg: &str) -> Result<String, DubpError> {
|
|
||||||
let currency = parse_currency(currency)?;
|
|
||||||
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
|
|
||||||
ExpectedCurrency::Specific(currency),
|
|
||||||
dewif,
|
|
||||||
&pin.to_ascii_uppercase(),
|
|
||||||
)
|
|
||||||
.map_err(DubpError::DewifReadError)?;
|
|
||||||
if let Some(KeyPairEnum::Ed25519(keypair)) = keypairs.next() {
|
|
||||||
Ok(keypair.generate_signator().sign(msg.as_bytes()).to_base64())
|
|
||||||
} else {
|
|
||||||
Err(DubpError::DewifReadError(DewifReadError::CorruptedContent))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn sign_several(
|
|
||||||
currency: &str,
|
|
||||||
dewif: &str,
|
dewif: &str,
|
||||||
pin: &str,
|
secret_code: &str,
|
||||||
msgs: &[&str],
|
) -> Result<String, DubpError> {
|
||||||
) -> Result<Vec<String>, DubpError> {
|
|
||||||
let currency = parse_currency(currency)?;
|
|
||||||
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
|
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
|
||||||
ExpectedCurrency::Specific(currency),
|
ExpectedCurrency::Specific(currency),
|
||||||
dewif,
|
dewif,
|
||||||
&pin.to_ascii_uppercase(),
|
&secret_code.to_ascii_uppercase(),
|
||||||
)
|
)
|
||||||
.map_err(DubpError::DewifReadError)?;
|
.map_err(DubpError::DewifReadError)?;
|
||||||
if let Some(KeyPairEnum::Ed25519(keypair)) = keypairs.next() {
|
if let Some(keypair) = keypairs.next() {
|
||||||
let signator = keypair.generate_signator();
|
Ok(keypair.public_key().to_base58())
|
||||||
Ok(msgs
|
|
||||||
.iter()
|
|
||||||
.map(|msg| signator.sign(msg.as_bytes()).to_base64())
|
|
||||||
.collect())
|
|
||||||
} else {
|
} else {
|
||||||
Err(DubpError::DewifReadError(DewifReadError::CorruptedContent))
|
Err(DubpError::DewifReadError(DewifReadError::CorruptedContent))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
// Copyright (C) 2020 Éloïs SANCHEZ.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
pub(crate) fn get_accounts_pubkeys(
|
||||||
|
currency: Currency,
|
||||||
|
dewif: &str,
|
||||||
|
secret_code: &str,
|
||||||
|
accounts_indexs: Vec<DerivationIndex>,
|
||||||
|
) -> Result<Vec<String>, DubpError> {
|
||||||
|
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
|
||||||
|
ExpectedCurrency::Specific(currency),
|
||||||
|
dewif,
|
||||||
|
&secret_code.to_ascii_uppercase(),
|
||||||
|
)
|
||||||
|
.map_err(DubpError::DewifReadError)?;
|
||||||
|
match keypairs.next() {
|
||||||
|
Some(KeyPairEnum::Bip32Ed25519(master_keypair)) => Ok(accounts_indexs
|
||||||
|
.into_iter()
|
||||||
|
.map(|account_index| {
|
||||||
|
master_keypair
|
||||||
|
.derive(account_index)
|
||||||
|
.public_key()
|
||||||
|
.to_base58()
|
||||||
|
})
|
||||||
|
.collect()),
|
||||||
|
Some(_) => Err(DubpError::NotHdWallet),
|
||||||
|
None => Err(DubpError::DewifReadError(DewifReadError::CorruptedContent)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn sign_transparent(
|
||||||
|
account_index: DerivationIndex,
|
||||||
|
currency: &str,
|
||||||
|
dewif: &str,
|
||||||
|
secret_code: &str,
|
||||||
|
msg: &str,
|
||||||
|
) -> Result<String, DubpError> {
|
||||||
|
let currency = parse_currency(currency)?;
|
||||||
|
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
|
||||||
|
ExpectedCurrency::Specific(currency),
|
||||||
|
dewif,
|
||||||
|
&secret_code.to_ascii_uppercase(),
|
||||||
|
)
|
||||||
|
.map_err(DubpError::DewifReadError)?;
|
||||||
|
|
||||||
|
match keypairs.next() {
|
||||||
|
Some(KeyPairEnum::Bip32Ed25519(master_keypair)) => Ok(master_keypair
|
||||||
|
.derive(account_index)
|
||||||
|
.generate_signator()
|
||||||
|
.sign(msg.as_bytes())
|
||||||
|
.to_base64()),
|
||||||
|
Some(_) => Err(DubpError::NotHdWallet),
|
||||||
|
None => Err(DubpError::DewifReadError(DewifReadError::CorruptedContent)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn sign_several_transparent(
|
||||||
|
account_index: DerivationIndex,
|
||||||
|
currency: &str,
|
||||||
|
dewif: &str,
|
||||||
|
secret_code: &str,
|
||||||
|
msgs: &[&str],
|
||||||
|
) -> Result<Vec<String>, DubpError> {
|
||||||
|
let currency = parse_currency(currency)?;
|
||||||
|
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
|
||||||
|
ExpectedCurrency::Specific(currency),
|
||||||
|
dewif,
|
||||||
|
&secret_code.to_ascii_uppercase(),
|
||||||
|
)
|
||||||
|
.map_err(DubpError::DewifReadError)?;
|
||||||
|
|
||||||
|
match keypairs.next() {
|
||||||
|
Some(KeyPairEnum::Bip32Ed25519(master_keypair)) => {
|
||||||
|
let signator = master_keypair.derive(account_index).generate_signator();
|
||||||
|
Ok(msgs
|
||||||
|
.iter()
|
||||||
|
.map(|msg| signator.sign(msg.as_bytes()).to_base64())
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
Some(_) => Err(DubpError::NotHdWallet),
|
||||||
|
None => Err(DubpError::DewifReadError(DewifReadError::CorruptedContent)),
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
// Copyright (C) 2020 Éloïs SANCHEZ.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
pub(crate) fn sign(
|
||||||
|
currency: &str,
|
||||||
|
dewif: &str,
|
||||||
|
secret_code: &str,
|
||||||
|
msg: &str,
|
||||||
|
) -> Result<String, DubpError> {
|
||||||
|
let currency = parse_currency(currency)?;
|
||||||
|
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
|
||||||
|
ExpectedCurrency::Specific(currency),
|
||||||
|
dewif,
|
||||||
|
&secret_code.to_ascii_uppercase(),
|
||||||
|
)
|
||||||
|
.map_err(DubpError::DewifReadError)?;
|
||||||
|
if let Some(KeyPairEnum::Ed25519(keypair)) = keypairs.next() {
|
||||||
|
Ok(keypair.generate_signator().sign(msg.as_bytes()).to_base64())
|
||||||
|
} else {
|
||||||
|
Err(DubpError::DewifReadError(DewifReadError::CorruptedContent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn sign_several(
|
||||||
|
currency: &str,
|
||||||
|
dewif: &str,
|
||||||
|
secret_code: &str,
|
||||||
|
msgs: &[&str],
|
||||||
|
) -> Result<Vec<String>, DubpError> {
|
||||||
|
let currency = parse_currency(currency)?;
|
||||||
|
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
|
||||||
|
ExpectedCurrency::Specific(currency),
|
||||||
|
dewif,
|
||||||
|
&secret_code.to_ascii_uppercase(),
|
||||||
|
)
|
||||||
|
.map_err(DubpError::DewifReadError)?;
|
||||||
|
if let Some(KeyPairEnum::Ed25519(keypair)) = keypairs.next() {
|
||||||
|
let signator = keypair.generate_signator();
|
||||||
|
Ok(msgs
|
||||||
|
.iter()
|
||||||
|
.map(|msg| signator.sign(msg.as_bytes()).to_base64())
|
||||||
|
.collect())
|
||||||
|
} else {
|
||||||
|
Err(DubpError::DewifReadError(DewifReadError::CorruptedContent))
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,8 @@
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use dup_crypto::keys::ed25519::bip32::InvalidDerivationIndex;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
/// Dubp error
|
/// Dubp error
|
||||||
|
@ -22,8 +24,14 @@ pub(crate) enum DubpError {
|
||||||
DewifReadError(DewifReadError),
|
DewifReadError(DewifReadError),
|
||||||
#[error("I/O error: {0}")]
|
#[error("I/O error: {0}")]
|
||||||
IoErr(io::Error),
|
IoErr(io::Error),
|
||||||
|
#[error("{0}")]
|
||||||
|
InvalidDerivationIndex(InvalidDerivationIndex),
|
||||||
#[error("Digits secret code forbid for member wallet")]
|
#[error("Digits secret code forbid for member wallet")]
|
||||||
DigitsCodeForbidForMemberWallet,
|
DigitsCodeForbidForMemberWallet,
|
||||||
|
#[error("this wallet is not an HD wallet")]
|
||||||
|
NotHdWallet,
|
||||||
|
#[error("this account index is not a transparent account index")]
|
||||||
|
NotTransparentAccountIndex,
|
||||||
#[error("A given parameter is null")]
|
#[error("A given parameter is null")]
|
||||||
NullParamErr,
|
NullParamErr,
|
||||||
#[error("fail to generate random bytes")]
|
#[error("fail to generate random bytes")]
|
||||||
|
@ -44,6 +52,12 @@ impl From<io::Error> for DubpError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<InvalidDerivationIndex> for DubpError {
|
||||||
|
fn from(e: InvalidDerivationIndex) -> Self {
|
||||||
|
Self::InvalidDerivationIndex(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct DartRes(allo_isolate::ffi::DartCObject);
|
pub(crate) struct DartRes(allo_isolate::ffi::DartCObject);
|
||||||
impl DartRes {
|
impl DartRes {
|
||||||
pub(crate) fn err<E: ToString>(e: E) -> allo_isolate::ffi::DartCObject {
|
pub(crate) fn err<E: ToString>(e: E) -> allo_isolate::ffi::DartCObject {
|
||||||
|
|
|
@ -29,6 +29,20 @@ impl From<u32> for SecretCodeType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub(crate) enum WalletType {
|
||||||
|
Ed25519,
|
||||||
|
Bip32Ed25519,
|
||||||
|
}
|
||||||
|
impl From<u32> for WalletType {
|
||||||
|
fn from(i: u32) -> Self {
|
||||||
|
if i == 1 {
|
||||||
|
WalletType::Bip32Ed25519
|
||||||
|
} else {
|
||||||
|
WalletType::Ed25519
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn char_ptr_to_str<'a>(c_char_ptr: *const raw::c_char) -> Result<&'a str, DubpError> {
|
pub(crate) fn char_ptr_to_str<'a>(c_char_ptr: *const raw::c_char) -> Result<&'a str, DubpError> {
|
||||||
if c_char_ptr.is_null() {
|
if c_char_ptr.is_null() {
|
||||||
|
@ -38,6 +52,16 @@ pub(crate) fn char_ptr_to_str<'a>(c_char_ptr: *const raw::c_char) -> Result<&'a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn char_ptr_prt_to_vec_hard_derivation_index(
|
||||||
|
u32_ptr: *const u32,
|
||||||
|
len: u32,
|
||||||
|
) -> Result<Vec<DerivationIndex>, DubpError> {
|
||||||
|
u32_ptr_to_vec_u32(u32_ptr, len)?
|
||||||
|
.into_iter()
|
||||||
|
.map(|ai| DerivationIndex::hard(ai).map_err(DubpError::InvalidDerivationIndex))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn char_ptr_prt_to_vec_str<'a>(
|
pub(crate) fn char_ptr_prt_to_vec_str<'a>(
|
||||||
char_ptr_ptr: *const *const raw::c_char,
|
char_ptr_ptr: *const *const raw::c_char,
|
||||||
len: u32,
|
len: u32,
|
||||||
|
@ -61,6 +85,24 @@ pub(crate) fn parse_currency(currency: &str) -> Result<Currency, DubpError> {
|
||||||
Ok(Currency::from(currency_code))
|
Ok(Currency::from(currency_code))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn transparent_account_index(account_index: u32) -> Result<DerivationIndex, DubpError> {
|
||||||
|
if account_index % 3 == 0 {
|
||||||
|
DerivationIndex::hard(account_index).map_err(DubpError::InvalidDerivationIndex)
|
||||||
|
} else {
|
||||||
|
Err(DubpError::NotTransparentAccountIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn u32_ptr_to_vec_u32(u32_ptr: *const u32, len: u32) -> Result<Vec<u32>, DubpError> {
|
||||||
|
let len = len as usize;
|
||||||
|
let u32_slice: &[u32] = unsafe { std::slice::from_raw_parts(u32_ptr, len) };
|
||||||
|
let mut vec = Vec::with_capacity(len);
|
||||||
|
for u32_ in u32_slice {
|
||||||
|
vec.push(*u32_);
|
||||||
|
}
|
||||||
|
Ok(vec)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn u32_to_language(i: u32) -> Result<Language, DubpError> {
|
pub(crate) fn u32_to_language(i: u32) -> Result<Language, DubpError> {
|
||||||
match i {
|
match i {
|
||||||
0 => Ok(Language::English),
|
0 => Ok(Language::English),
|
||||||
|
|
|
@ -32,8 +32,8 @@ use dup_crypto::{
|
||||||
bases::b58::ToBase58,
|
bases::b58::ToBase58,
|
||||||
dewif::{Currency, DewifReadError, ExpectedCurrency, G1_CURRENCY, G1_TEST_CURRENCY},
|
dewif::{Currency, DewifReadError, ExpectedCurrency, G1_CURRENCY, G1_TEST_CURRENCY},
|
||||||
keys::{
|
keys::{
|
||||||
ed25519::KeyPairFromSeed32Generator, KeyPair as _, KeyPairEnum, Signator as _,
|
ed25519::bip32::DerivationIndex, ed25519::KeyPairFromSeed32Generator, KeyPair as _,
|
||||||
Signature as _,
|
KeyPairEnum, Signator as _, Signature as _,
|
||||||
},
|
},
|
||||||
mnemonic::{Language, Mnemonic, MnemonicType},
|
mnemonic::{Language, Mnemonic, MnemonicType},
|
||||||
};
|
};
|
||||||
|
@ -91,6 +91,7 @@ pub extern "C" fn gen_dewif(
|
||||||
member_wallet: u32,
|
member_wallet: u32,
|
||||||
secret_code_type: u32,
|
secret_code_type: u32,
|
||||||
system_memory: i64,
|
system_memory: i64,
|
||||||
|
wallet_type: u32,
|
||||||
) {
|
) {
|
||||||
exec_async(
|
exec_async(
|
||||||
port,
|
port,
|
||||||
|
@ -100,6 +101,7 @@ pub extern "C" fn gen_dewif(
|
||||||
let mnemonic = char_ptr_to_str(mnemonic)?;
|
let mnemonic = char_ptr_to_str(mnemonic)?;
|
||||||
let member_wallet = member_wallet != 0;
|
let member_wallet = member_wallet != 0;
|
||||||
let secret_code_type = SecretCodeType::from(secret_code_type);
|
let secret_code_type = SecretCodeType::from(secret_code_type);
|
||||||
|
let wallet_type = WalletType::from(wallet_type);
|
||||||
Ok((
|
Ok((
|
||||||
currency,
|
currency,
|
||||||
language,
|
language,
|
||||||
|
@ -107,9 +109,18 @@ pub extern "C" fn gen_dewif(
|
||||||
member_wallet,
|
member_wallet,
|
||||||
secret_code_type,
|
secret_code_type,
|
||||||
system_memory,
|
system_memory,
|
||||||
|
wallet_type,
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
|(currency, language, mnemonic, member_wallet, secret_code_type, system_memory)| {
|
|(
|
||||||
|
currency,
|
||||||
|
language,
|
||||||
|
mnemonic,
|
||||||
|
member_wallet,
|
||||||
|
secret_code_type,
|
||||||
|
system_memory,
|
||||||
|
wallet_type,
|
||||||
|
)| {
|
||||||
dewif::gen_dewif(
|
dewif::gen_dewif(
|
||||||
currency,
|
currency,
|
||||||
language,
|
language,
|
||||||
|
@ -117,6 +128,7 @@ pub extern "C" fn gen_dewif(
|
||||||
member_wallet,
|
member_wallet,
|
||||||
secret_code_type,
|
secret_code_type,
|
||||||
system_memory,
|
system_memory,
|
||||||
|
wallet_type,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -200,6 +212,31 @@ pub extern "C" fn get_dewif_pubkey(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn get_bip32_dewif_accounts_pubkeys(
|
||||||
|
port: i64,
|
||||||
|
currency: *const raw::c_char,
|
||||||
|
dewif: *const raw::c_char,
|
||||||
|
secret_code: *const raw::c_char,
|
||||||
|
accounts_indexs_len: u32,
|
||||||
|
accounts_indexs: *const u32,
|
||||||
|
) {
|
||||||
|
exec_async(
|
||||||
|
port,
|
||||||
|
|| {
|
||||||
|
let currency = parse_currency(char_ptr_to_str(currency)?)?;
|
||||||
|
let dewif = char_ptr_to_str(dewif)?;
|
||||||
|
let secret_code = char_ptr_to_str(secret_code)?;
|
||||||
|
let accounts_indexs =
|
||||||
|
char_ptr_prt_to_vec_hard_derivation_index(accounts_indexs, accounts_indexs_len)?;
|
||||||
|
Ok((currency, dewif, secret_code, accounts_indexs))
|
||||||
|
},
|
||||||
|
|(currency, dewif, secret_code, accounts_indexs)| {
|
||||||
|
dewif::bip32::get_accounts_pubkeys(currency, dewif, secret_code, accounts_indexs)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn get_legacy_pubkey(
|
pub extern "C" fn get_legacy_pubkey(
|
||||||
port: i64,
|
port: i64,
|
||||||
|
@ -251,7 +288,32 @@ pub extern "C" fn sign(
|
||||||
let msg = char_ptr_to_str(msg)?;
|
let msg = char_ptr_to_str(msg)?;
|
||||||
Ok((currency, dewif, pin, msg))
|
Ok((currency, dewif, pin, msg))
|
||||||
},
|
},
|
||||||
|(currency, dewif, pin, msg)| dewif::sign(currency, dewif, pin, msg),
|
|(currency, dewif, pin, msg)| dewif::classic::sign(currency, dewif, pin, msg),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn sign_bip32_transparent(
|
||||||
|
port: i64,
|
||||||
|
account_index: u32,
|
||||||
|
currency: *const raw::c_char,
|
||||||
|
dewif: *const raw::c_char,
|
||||||
|
secret_code: *const raw::c_char,
|
||||||
|
msg: *const raw::c_char,
|
||||||
|
) {
|
||||||
|
exec_async(
|
||||||
|
port,
|
||||||
|
|| {
|
||||||
|
let account_index = transparent_account_index(account_index)?;
|
||||||
|
let currency = char_ptr_to_str(currency)?;
|
||||||
|
let dewif = char_ptr_to_str(dewif)?;
|
||||||
|
let pin = char_ptr_to_str(secret_code)?;
|
||||||
|
let msg = char_ptr_to_str(msg)?;
|
||||||
|
Ok((currency, dewif, pin, msg, account_index))
|
||||||
|
},
|
||||||
|
|(currency, dewif, secret_code, msg, account_index)| {
|
||||||
|
dewif::bip32::sign_transparent(account_index, currency, dewif, secret_code, msg)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,6 +354,32 @@ pub extern "C" fn sign_several(
|
||||||
let msgs = char_ptr_prt_to_vec_str(msgs, msgs_len)?;
|
let msgs = char_ptr_prt_to_vec_str(msgs, msgs_len)?;
|
||||||
Ok((currency, dewif, pin, msgs))
|
Ok((currency, dewif, pin, msgs))
|
||||||
},
|
},
|
||||||
|(currency, dewif, pin, msgs)| dewif::sign_several(currency, dewif, pin, &msgs),
|
|(currency, dewif, pin, msgs)| dewif::classic::sign_several(currency, dewif, pin, &msgs),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn sign_several_bip32_transparent(
|
||||||
|
port: i64,
|
||||||
|
account_index: u32,
|
||||||
|
currency: *const raw::c_char,
|
||||||
|
dewif: *const raw::c_char,
|
||||||
|
pin: *const raw::c_char,
|
||||||
|
msgs_len: u32,
|
||||||
|
msgs: *const *const raw::c_char,
|
||||||
|
) {
|
||||||
|
exec_async(
|
||||||
|
port,
|
||||||
|
|| {
|
||||||
|
let account_index = transparent_account_index(account_index)?;
|
||||||
|
let currency = char_ptr_to_str(currency)?;
|
||||||
|
let dewif = char_ptr_to_str(dewif)?;
|
||||||
|
let pin = char_ptr_to_str(pin)?;
|
||||||
|
let msgs = char_ptr_prt_to_vec_str(msgs, msgs_len)?;
|
||||||
|
Ok((currency, dewif, pin, msgs, account_index))
|
||||||
|
},
|
||||||
|
|(currency, dewif, pin, msgs, account_index)| {
|
||||||
|
dewif::bip32::sign_several_transparent(account_index, currency, dewif, pin, &msgs)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,15 @@ enum SecretCodeType {
|
||||||
letters,
|
letters,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wallet type
|
||||||
|
enum WalletType {
|
||||||
|
/// Ed25519
|
||||||
|
ed25519,
|
||||||
|
|
||||||
|
/// BIP32-Ed25519
|
||||||
|
bip32Ed25519,
|
||||||
|
}
|
||||||
|
|
||||||
/// DUBP Rust utilities
|
/// DUBP Rust utilities
|
||||||
///
|
///
|
||||||
/// All the functions of this package are static methods of this
|
/// All the functions of this package are static methods of this
|
||||||
|
@ -128,6 +137,7 @@ class DubpRust {
|
||||||
Language language = Language.english,
|
Language language = Language.english,
|
||||||
String mnemonic,
|
String mnemonic,
|
||||||
SecretCodeType secretCodeType = SecretCodeType.letters,
|
SecretCodeType secretCodeType = SecretCodeType.letters,
|
||||||
|
WalletType walletType = WalletType.ed25519,
|
||||||
}) async {
|
}) async {
|
||||||
int ram = SysInfo.getTotalPhysicalMemory();
|
int ram = SysInfo.getTotalPhysicalMemory();
|
||||||
print('ram=$ram');
|
print('ram=$ram');
|
||||||
|
@ -143,12 +153,34 @@ class DubpRust {
|
||||||
0,
|
0,
|
||||||
secretCodeType.index,
|
secretCodeType.index,
|
||||||
ram,
|
ram,
|
||||||
|
walletType.index,
|
||||||
);
|
);
|
||||||
List<String> newWallet = await completer.future;
|
List<String> newWallet = await completer.future;
|
||||||
|
|
||||||
return Future.value(NewWallet._(newWallet[0], newWallet[1], newWallet[2]));
|
return Future.value(NewWallet._(newWallet[0], newWallet[1], newWallet[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//get_bip32_dewif_accounts_pubkeys
|
||||||
|
|
||||||
|
/// Get BIP32 accounts public keys (in base 58) of `dewif` master keypair.
|
||||||
|
static Future<String> getBip32DewifAccountsPublicKeys(
|
||||||
|
{String currency = "g1",
|
||||||
|
String dewif,
|
||||||
|
String secretCode,
|
||||||
|
List<int> accountsIndex}) async {
|
||||||
|
final completer = Completer<String>();
|
||||||
|
final sendPort =
|
||||||
|
singleCompletePort<String, String>(completer, callback: _handleErr);
|
||||||
|
native.get_bip32_dewif_accounts_pubkeys(
|
||||||
|
sendPort.nativePort,
|
||||||
|
Utf8.toUtf8(currency),
|
||||||
|
Utf8.toUtf8(dewif),
|
||||||
|
Utf8.toUtf8(secretCode),
|
||||||
|
accountsIndex.length,
|
||||||
|
_listIntToPtr(accountsIndex));
|
||||||
|
return completer.future;
|
||||||
|
}
|
||||||
|
|
||||||
/// Get public key (in base 58) of `dewif` keypair.
|
/// Get public key (in base 58) of `dewif` keypair.
|
||||||
static Future<String> getDewifPublicKey(
|
static Future<String> getDewifPublicKey(
|
||||||
{String currency = "g1", String dewif, String pin}) async {
|
{String currency = "g1", String dewif, String pin}) async {
|
||||||
|
@ -215,6 +247,31 @@ class DubpRust {
|
||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sign the message `message` with `dewif` Bip32-Ed25519 keypair encryted
|
||||||
|
/// in DEWIF format.
|
||||||
|
///
|
||||||
|
/// If you have several messages to sign, use `signSeveralBip32Transparent`
|
||||||
|
/// method instead.
|
||||||
|
static Future<String> signBip32Transparent(
|
||||||
|
{int accountIndex,
|
||||||
|
String currency = "g1",
|
||||||
|
String dewif,
|
||||||
|
String secretCode,
|
||||||
|
String message}) {
|
||||||
|
final completer = Completer<String>();
|
||||||
|
final sendPort =
|
||||||
|
singleCompletePort<String, String>(completer, callback: _handleErr);
|
||||||
|
native.sign_bip32_transparent(
|
||||||
|
sendPort.nativePort,
|
||||||
|
accountIndex,
|
||||||
|
Utf8.toUtf8(currency),
|
||||||
|
Utf8.toUtf8(dewif),
|
||||||
|
Utf8.toUtf8(secretCode),
|
||||||
|
Utf8.toUtf8(message),
|
||||||
|
);
|
||||||
|
return completer.future;
|
||||||
|
}
|
||||||
|
|
||||||
/// Sign the message `message` with legacy wallet (password + salt)
|
/// Sign the message `message` with legacy wallet (password + salt)
|
||||||
///
|
///
|
||||||
/// This deprecated method must be used only for compatibility purpose !
|
/// This deprecated method must be used only for compatibility purpose !
|
||||||
|
@ -259,6 +316,44 @@ class DubpRust {
|
||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sign several messages `messages` with `dewif` keypair encryted in DEWIF
|
||||||
|
/// format.
|
||||||
|
///
|
||||||
|
/// This method is optimized to sign several messages at once. If you have
|
||||||
|
/// several messages to sign, avoid calling the `sign` method for each
|
||||||
|
/// message. Use this `signSeveral` method instead.
|
||||||
|
static Future<List<String>> signSeveralBip32Transparent(
|
||||||
|
{int accountIndex,
|
||||||
|
String currency = "g1",
|
||||||
|
String dewif,
|
||||||
|
String pin,
|
||||||
|
List<String> messages}) {
|
||||||
|
final completer = Completer<List<String>>();
|
||||||
|
final sendPort = singleCompletePort<List<String>, List>(completer,
|
||||||
|
callback: _handleErrList);
|
||||||
|
|
||||||
|
native.sign_several_bip32_transparent(
|
||||||
|
sendPort.nativePort,
|
||||||
|
accountIndex,
|
||||||
|
Utf8.toUtf8(currency),
|
||||||
|
Utf8.toUtf8(dewif),
|
||||||
|
Utf8.toUtf8(pin),
|
||||||
|
messages.length,
|
||||||
|
_listStringToPtr(messages),
|
||||||
|
);
|
||||||
|
|
||||||
|
return completer.future;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Pointer<Uint32> _listIntToPtr(List<int> list) {
|
||||||
|
//final listUint32 = list.map(int.toUnsigned).toList();
|
||||||
|
final Pointer<Uint32> ptr = allocate(count: list.length);
|
||||||
|
for (var i = 0; i < list.length; i++) {
|
||||||
|
ptr[i] = list[i];
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
static Pointer<Pointer<Utf8>> _listStringToPtr(List<String> list) {
|
static Pointer<Pointer<Utf8>> _listStringToPtr(List<String> list) {
|
||||||
final listUtf8 = list.map(Utf8.toUtf8).toList();
|
final listUtf8 = list.map(Utf8.toUtf8).toList();
|
||||||
final Pointer<Pointer<Utf8>> ptr = allocate(count: listUtf8.length);
|
final Pointer<Pointer<Utf8>> ptr = allocate(count: listUtf8.length);
|
||||||
|
|
Loading…
Reference in New Issue