Skip to content

Commit

Permalink
Enterprise adddress generation
Browse files Browse the repository at this point in the history
  • Loading branch information
satran004 committed Apr 16, 2021
1 parent dbd9f33 commit fc738f5
Show file tree
Hide file tree
Showing 9 changed files with 223 additions and 95 deletions.
70 changes: 59 additions & 11 deletions rust/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::os::raw::c_char;
use std::str;

use bip39::{Language, Mnemonic, MnemonicType};
use cardano_serialization_lib::address::{BaseAddress, NetworkInfo, Pointer, PointerAddress, StakeCredential};
use cardano_serialization_lib::address::{BaseAddress, NetworkInfo, Pointer, PointerAddress, StakeCredential, EnterpriseAddress};
use cardano_serialization_lib::chain_core::property::FromStr;
use cardano_serialization_lib::crypto::Bip32PrivateKey;
use rand::prelude::*;
Expand Down Expand Up @@ -56,6 +56,36 @@ pub fn get_baseaddress_from_mnemonic(phrase: &str, index: u32, is_testnet: bool)
get_baseaddress_from_mnemonic_by_networkInfo(phrase, index, network)
}

pub fn get_enterpriseaddress_from_mnemonic_by_networkInfo(phrase: &str, index: u32, network: NetworkInfo) -> String {
let result = Mnemonic::from_phrase(phrase, Language::English).unwrap();

let entropy = result.entropy();

let root_key = get_root_key(&entropy);
let spend = root_key
.derive(harden(1852))
.derive(harden(1815))
.derive(harden(0))
.derive(0)
.derive(index)
.to_public();

let spend_cred = StakeCredential::from_keyhash(&spend.to_raw_key().hash());
let addr_net_0 = EnterpriseAddress::new(network.network_id(), &spend_cred).to_address();

addr_net_0.to_bech32(None).unwrap()
}

pub fn get_enterpriseaddress_from_mnemonic(phrase: &str, index: u32, is_testnet: bool) -> String {
let network = if is_testnet {
NetworkInfo::testnet()
} else {
NetworkInfo::mainnet()
};

get_enterpriseaddress_from_mnemonic_by_networkInfo(phrase, index, network)
}

pub fn generate_mnemonic() -> String {
let mnemonic = Mnemonic::new(MnemonicType::Words24, Language::English);
let phrase = mnemonic.phrase();
Expand All @@ -65,18 +95,10 @@ pub fn generate_mnemonic() -> String {

#[cfg(test)]
mod tests {
use crate::address::{generate_mnemonic, get_baseaddress_from_mnemonic};

// #[test]
// fn it_works() {
// let phrase = "test walk nut penalty hip pave soap entry language right filter choice";
// // let entropy = [0xdf, 0x9e, 0xd2, 0x5e, 0xd1, 0x46, 0xbf, 0x43, 0x33, 0x6a, 0x5d, 0x7c, 0xf7, 0x39, 0x59, 0x94];
// let str = get_baseaddress_from_mnemonic(phrase, 0);
// println!(" Hello: {}", str);
// }
use crate::address::{generate_mnemonic, get_baseaddress_from_mnemonic, get_enterpriseaddress_from_mnemonic};

#[test]
fn get_baseaddress_from_mnemonic_yoroi() {
fn get_baseaddress_from_mnemonic_15words() {
//15 words
let phrase = "stairs same wheel damage taste amused dutch fly end tiger benefit leopard purity work year";
// let entropy = [0xdf, 0x9e, 0xd2, 0x5e, 0xd1, 0x46, 0xbf, 0x43, 0x33, 0x6a, 0x5d, 0x7c, 0xf7, 0x39, 0x59, 0x94];
Expand Down Expand Up @@ -122,6 +144,32 @@ mod tests {
assert_eq!(add2, "addr_test1qrpr30ykyfa3pw6qkkun3dyyxsvftq3xukuyxdt58pxcpxgl5mr3vkp82y2kcwxxtu4zjcxvm80ttmx2hyeyjka4v8pskku650");
}

#[test]
fn get_enterpriseaddress_from_mnemonic_mainnet() {
//24 words
let phrase = "coconut you order found animal inform tent anxiety pepper aisle web horse source indicate eyebrow viable lawsuit speak dragon scheme among animal slogan exchange";
let add0 = get_enterpriseaddress_from_mnemonic(phrase, 0, false);
let add1 = get_enterpriseaddress_from_mnemonic(phrase, 1, false);
let add2 = get_enterpriseaddress_from_mnemonic(phrase, 2, false);

assert_eq!(add0, "addr1vxsaa6czesrzwp45rd5flg86n5hnwhz5setqfyt39natwvstf7k4n");
assert_eq!(add1, "addr1v93jwnn3hvgcuv02tqe08lpdkxxpmvapxgjxwewya47tqsg7davae");
assert_eq!(add2, "addr1v8pr30ykyfa3pw6qkkun3dyyxsvftq3xukuyxdt58pxcpxgvddj89");
}

#[test]
fn get_enterpriseaddress_from_mnemonic_testnet() {
//24 words
let phrase = "coconut you order found animal inform tent anxiety pepper aisle web horse source indicate eyebrow viable lawsuit speak dragon scheme among animal slogan exchange";
let add0 = get_enterpriseaddress_from_mnemonic(phrase, 0, true);
let add1 = get_enterpriseaddress_from_mnemonic(phrase, 1, true);
let add2 = get_enterpriseaddress_from_mnemonic(phrase, 2, true);

assert_eq!(add0, "addr_test1vzsaa6czesrzwp45rd5flg86n5hnwhz5setqfyt39natwvssp226k");
assert_eq!(add1, "addr_test1vp3jwnn3hvgcuv02tqe08lpdkxxpmvapxgjxwewya47tqsg99fsju");
assert_eq!(add2, "addr_test1vrpr30ykyfa3pw6qkkun3dyyxsvftq3xukuyxdt58pxcpxgh9ewgq");
}

#[test]
fn generate_mnemonic_daedalus() {
let mnemonic = generate_mnemonic();
Expand Down
80 changes: 33 additions & 47 deletions rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use jni::objects::{JClass, JString};
// lifetime checker won't let us.
use jni::sys::jstring;

use crate::address::{get_baseaddress_from_mnemonic, get_baseaddress_from_mnemonic_by_networkInfo};
use crate::address::{get_baseaddress_from_mnemonic, get_baseaddress_from_mnemonic_by_networkInfo, get_enterpriseaddress_from_mnemonic_by_networkInfo, get_enterpriseaddress_from_mnemonic};

use std::os::raw::c_char;
use std::ffi::{CStr,CString};
Expand All @@ -22,31 +22,17 @@ use serde_json::Result;

mod address;

// This keeps Rust from "mangling" the name and making it unique for this
// crate.
#[no_mangle]
pub extern "system" fn Java_com_bloxbean_cardano_client_CardanoNative_getBaseAddressFromMnemonic(env: JNIEnv,
// This is the class that owns our static method. It's not going to be used,
// but still must be present to match the expected signature of a static
// native method.
class: JClass,
input: JString, index: u32, is_testnet: bool)
-> jstring {
// First, we have to get the string out of Java. Check out the `strings`
// module for more info on how this works.
let input: String =
env.get_string(input).expect("Couldn't get java string!").into();

let add = get_baseaddress_from_mnemonic(input.as_str(), index, is_testnet);

let output = env.new_string(format!("{}", add))
.expect("Couldn't create java string!");

output.into_inner()
#[repr(C)]
#[allow(missing_copy_implementations)]
pub struct Network {
network_id: u8,
protocol_magic: u64
}

#[no_mangle]
pub fn get_address(phrase: *const c_char, index: u32, is_testnet: bool) -> *const c_char {
#[allow(non_snake_case)]
pub fn getBaseAddress(phrase: *const c_char, index: u32, is_testnet: bool) -> *const c_char {
let s = to_string(phrase);

let add = get_baseaddress_from_mnemonic(s.as_str(), index, is_testnet);
Expand All @@ -55,15 +41,8 @@ pub fn get_address(phrase: *const c_char, index: u32, is_testnet: bool) -> *cons
}

#[no_mangle]
#[repr(C)]
#[allow(missing_copy_implementations)]
pub struct Network {
network_id: u8,
protocol_magic: u64
}

#[no_mangle]
pub fn get_address_by_network(phrase: *const c_char, index: u32, network: &Network) -> *const c_char {
#[allow(non_snake_case)]
pub fn getBaseAddressByNetwork(phrase: *const c_char, index: u32, network: &Network) -> *const c_char {
let s = to_string(phrase);

let netInfo = NetworkInfo::new(network.network_id,
Expand All @@ -73,24 +52,31 @@ pub fn get_address_by_network(phrase: *const c_char, index: u32, network: &Netwo
to_ptr(add)
}

// #[no_mangle]
// pub fn get_address_by_network_json(phrase: *const c_char, index: u32, network: *const c_char) -> *const c_char {
// let s = to_string(phrase);
//
// let netStr = to_string(network);
//
// let nt: NetworkJava = serde_json::from_str(netStr.as_str()).unwrap();
// println!("{}", nt.network_id);
// println!("{}", nt.protocol_magic);
//
// let netInfo = NetworkInfo::new(nt.network_id, nt.protocol_magic);
// let add = get_baseaddress_from_mnemonic_by_networkInfo(s.as_str(), index, netInfo);
//
// to_ptr(add)
// }
#[no_mangle]
#[allow(non_snake_case)]
pub fn getEnterpriseAddress(phrase: *const c_char, index: u32, is_testnet: bool) -> *const c_char {
let s = to_string(phrase);

let add = get_enterpriseaddress_from_mnemonic(s.as_str(), index, is_testnet);

to_ptr(add)
}

#[no_mangle]
#[allow(non_snake_case)]
pub fn getEnterpriseAddressByNetwork(phrase: *const c_char, index: u32, network: &Network) -> *const c_char {
let s = to_string(phrase);

let netInfo = NetworkInfo::new(network.network_id,
network.protocol_magic as u32);
let add = get_enterpriseaddress_from_mnemonic_by_networkInfo(s.as_str(), index, netInfo);

to_ptr(add)
}

#[no_mangle]
pub fn generate_mnemonic() -> *const c_char {
#[allow(non_snake_case)]
pub fn generateMnemonic() -> *const c_char {
let mnemonic = address::generate_mnemonic();

to_ptr(mnemonic)
Expand Down
18 changes: 16 additions & 2 deletions src/main/java/com/bloxbean/cardano/client/account/Account.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
public class Account {
private String mnemonic;
private String baseAddress;
private String enterpriseAddress;
private Network network;

/**
Expand Down Expand Up @@ -66,11 +67,24 @@ public String baseAddress(int index) {
refNetwork.network_id = network.network_id;
refNetwork.protocol_magic = network.protocol_magic;

return CardanoJNA.INSTANCE.get_address_by_network(mnemonic, index, refNetwork);
return CardanoJNA.INSTANCE.getBaseAddressByNetwork(mnemonic, index, refNetwork);
}

/**
*
* @param index
* @return enterpriseAddress at index
*/
public String enterpriseAddress(int index) {
Network.ByReference refNetwork = new Network.ByReference();
refNetwork.network_id = network.network_id;
refNetwork.protocol_magic = network.protocol_magic;

return CardanoJNA.INSTANCE.getEnterpriseAddressByNetwork(mnemonic, index, refNetwork);
}

private void generateNew() {
String mnemonic = CardanoJNA.INSTANCE.generate_mnemonic();
String mnemonic = CardanoJNA.INSTANCE.generateMnemonic();
this.mnemonic = mnemonic;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.bloxbean.cardano.client.cli;

import com.bloxbean.cardano.client.account.Account;
import com.bloxbean.cardano.client.jna.CardanoJNA;
import com.bloxbean.cardano.client.util.Networks;
import picocli.CommandLine;

@CommandLine.Command(
Expand All @@ -15,21 +17,30 @@ public class AccountGeneration implements Runnable {
@CommandLine.Option(names = {"-t", "--total"}, description = "Total number of accounts to generate")
private int total;

@CommandLine.Option(names = {"-ea", "--enterprise-address"}, description = "Generate enterprise address")
private boolean entAddress;

@Override
public void run() {
if (network == null || network.trim().length() == 0)
network = "mainnet";

String mnemonic = CardanoJNA.INSTANCE.generate_mnemonic();
Account account = null;

if("testnet".equals(network)) {
account = new Account(Networks.testnet());
} else {
account = new Account();
}

String mnemonic = account.mnemonic();
System.out.println("Mnemonic : " + mnemonic);

for (int i = 0; i <= total; i++) {
if ("testnet".equals(network)) {
String baseAddress = CardanoJNA.INSTANCE.get_address(mnemonic, i, true);
System.out.println("Address-" + i + ": " + baseAddress);
} else {
String baseAddress = CardanoJNA.INSTANCE.get_address(mnemonic, i, false);
System.out.println("Address-" + i + ": " + baseAddress);
System.out.println(" ");
System.out.println("Base Address-" + i + ": " + account.baseAddress(i));
if(entAddress) {
System.out.println("Ent Address -" + i + ": " + account.enterpriseAddress(i));
}
}
}
Expand Down
22 changes: 16 additions & 6 deletions src/main/java/com/bloxbean/cardano/client/cli/FromMnemonic.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.bloxbean.cardano.client.cli;

import com.bloxbean.cardano.client.account.Account;
import com.bloxbean.cardano.client.jna.CardanoJNA;
import com.bloxbean.cardano.client.util.Networks;
import picocli.CommandLine;

@CommandLine.Command(
Expand All @@ -18,18 +20,26 @@ public class FromMnemonic implements Runnable {
@CommandLine.Option(names = {"-t", "--total"}, description = "Total number of accounts to generate")
private int total;

@CommandLine.Option(names = {"-ea", "--enterprise-address"}, description = "Generate enterprise address")
private boolean entAddress;

@Override
public void run() {
if (network == null || network.trim().length() == 0)
network = "mainnet";

Account account = null;
if("testnet".equals(network)) {
account = new Account(Networks.testnet(), mnemonic);
} else {
account = new Account(mnemonic);
}

for (int i = 0; i <= total; i++) {
if ("testnet".equals(network)) {
String baseAddress = CardanoJNA.INSTANCE.get_address(mnemonic, i, true);
System.out.println("Address-" + i + ": " + baseAddress);
} else {
String baseAddress = CardanoJNA.INSTANCE.get_address(mnemonic, i, false);
System.out.println("Address-" + i + ": " + baseAddress);
System.out.println(" ");
System.out.println("Base Address-" + i + ": " + account.baseAddress(i));
if(entAddress) {
System.out.println("Ent Address -" + i + ": " + account.enterpriseAddress(i));
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/com/bloxbean/cardano/client/jna/CardanoJNA.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ public interface CardanoJNA extends Library {
Native.load(LibraryUtil.getCardanoWrapperLib(),
CardanoJNA.class);

public String get_address(String phrase, int index, boolean isTestnet);
public String get_address_by_network(String phrase, int index, Network.ByReference network);
public String generate_mnemonic();
public String getBaseAddress(String phrase, int index, boolean isTestnet);
public String getBaseAddressByNetwork(String phrase, int index, Network.ByReference network);
public String getEnterpriseAddress(String phrase, int index, boolean isTestnet);
public String getEnterpriseAddressByNetwork(String phrase, int index, Network.ByReference network);
public String generateMnemonic();
}
Loading

0 comments on commit fc738f5

Please sign in to comment.