Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ futures-util = "0.3.31"
gasket = { git = "https://github.com/construkts/gasket-rs.git", features = ["derive"] }
hex = "0.4.3"
itertools = "0.14.0"
pallas = { version = "1.0.0-alpha.1", features = ["phase2", "wallet"] }
protoc-wkt = "1.0.0"
serde = { version = "1.0.217", features = ["derive"] }
thiserror = "2.0.11"
Expand All @@ -40,4 +39,10 @@ tokio-stream = "0.1.17"
rand = "0.9.0"
prost = "0.13.5"
vaultrs = "0.7.4"

pallas = { version = "1.0.0-alpha.2", features = ["phase2"] }
# pallas = { git = "https://github.com/txpipe/pallas.git", features = ["phase2"] }

cryptoxide = "0.5.0"
ed25519-bip32 = "0.4.1"
bip39 = "2.1.0"
76 changes: 43 additions & 33 deletions src/signing/key/derive.rs
Original file line number Diff line number Diff line change
@@ -1,50 +1,61 @@
use bip39::Mnemonic;
use cryptoxide::{hmac::Hmac, pbkdf2::pbkdf2, sha2::Sha512};
use ed25519_bip32::{XPrv, XPub, XPRV_SIZE};
use pallas::{
crypto::{hash::Hasher, key::ed25519::PublicKey},
crypto::{
hash::Hasher,
key::ed25519::{self, PublicKey, SecretKey, SecretKeyExtended},
},
ledger::addresses::{
Address, Network, ShelleyAddress, ShelleyDelegationPart, ShelleyPaymentPart,
},
wallet::keystore::{
hd::{Bip32PrivateKey, Bip32PublicKey},
PrivateKey,
},
};

pub fn get_ed25519_keypair(mnemonic: &Mnemonic) -> (PrivateKey, PublicKey) {
fn from_bip39_mnenomic(mnemonic: String, password: String) -> anyhow::Result<ed25519_bip32::XPrv> {
let bip39 = Mnemonic::parse(mnemonic)?;
let entropy = bip39.to_entropy();

let mut pbkdf2_result = [0; XPRV_SIZE];

const ITER: u32 = 4096;

let mut mac = Hmac::new(Sha512::new(), password.as_bytes());
pbkdf2(&mut mac, &entropy, ITER, &mut pbkdf2_result);

Ok(XPrv::normalize_bytes_force3rd(pbkdf2_result))
}

pub fn get_ed25519_keypair(mnemonic: &Mnemonic) -> (SecretKeyExtended, PublicKey) {
let account_key = generate_account_key(mnemonic);
let (private_key, _) = generate_payment_keypair(&account_key);

to_ed25519_keypair(&private_key)
}

pub fn generate_account_key(mnemonic: &Mnemonic) -> Bip32PrivateKey {
let root_key = Bip32PrivateKey::from_bip39_mnenomic(mnemonic.to_string(), "".into()).unwrap();
pub fn generate_account_key(mnemonic: &Mnemonic) -> XPrv {
let root_key = from_bip39_mnenomic(mnemonic.to_string(), "".into()).unwrap();
root_key
.derive(1852 | 0x80000000)
.derive(1815 | 0x80000000)
.derive(0x80000000)
.derive(ed25519_bip32::DerivationScheme::V2, 1852 | 0x80000000)
.derive(ed25519_bip32::DerivationScheme::V2, 1815 | 0x80000000)
.derive(ed25519_bip32::DerivationScheme::V2, 0x80000000)
}

pub fn generate_payment_keypair(
account_key: &Bip32PrivateKey,
) -> (Bip32PrivateKey, Bip32PublicKey) {
let external_key = account_key.derive(0);
let private_key = external_key.derive(0);
let public_key = private_key.to_public();
pub fn generate_payment_keypair(account_key: &XPrv) -> (XPrv, XPub) {
let external_key = account_key.derive(ed25519_bip32::DerivationScheme::V2, 0);
let private_key = external_key.derive(ed25519_bip32::DerivationScheme::V2, 0);
let public_key = private_key.public();
(private_key, public_key)
}

pub fn generate_delegation_keypair(
account_key: &Bip32PrivateKey,
) -> (Bip32PrivateKey, Bip32PublicKey) {
let delegation_key = account_key.derive(2);
let private_key = delegation_key.derive(0);
let public_key = private_key.to_public();
pub fn generate_delegation_keypair(account_key: &XPrv) -> (XPrv, XPub) {
let delegation_key = account_key.derive(ed25519_bip32::DerivationScheme::V2, 2);
let private_key = delegation_key.derive(ed25519_bip32::DerivationScheme::V2, 0);
let public_key = private_key.public();
(private_key, public_key)
}

pub fn generate_address(public_key: &Bip32PublicKey) -> Address {
let payment_hash = Hasher::<224>::hash(&public_key.as_bytes()[..32]);
pub fn generate_address(public_key: &XPub) -> Address {
let payment_hash = Hasher::<224>::hash(&public_key.as_ref().to_vec()[..32]);
let address = ShelleyAddress::new(
Network::Testnet,
ShelleyPaymentPart::key_hash(payment_hash),
Expand All @@ -54,14 +65,11 @@ pub fn generate_address(public_key: &Bip32PublicKey) -> Address {
Address::Shelley(address)
}

pub fn generate_address_with_delegation(
account_key: &Bip32PrivateKey,
public_key: &Bip32PublicKey,
) -> Address {
let payment_hash = Hasher::<224>::hash(public_key.as_bytes().as_slice());
pub fn generate_address_with_delegation(account_key: &XPrv, public_key: &XPub) -> Address {
let payment_hash = Hasher::<224>::hash(public_key.as_ref().to_vec().as_slice());

let (_, public_key) = generate_delegation_keypair(account_key);
let delegation_hash = Hasher::<224>::hash(public_key.as_bytes().as_slice());
let delegation_hash = Hasher::<224>::hash(public_key.as_ref().to_vec().as_slice());

let address = ShelleyAddress::new(
Network::Testnet,
Expand All @@ -72,8 +80,10 @@ pub fn generate_address_with_delegation(
Address::Shelley(address)
}

pub fn to_ed25519_keypair(private_key: &Bip32PrivateKey) -> (PrivateKey, PublicKey) {
let private_key = private_key.to_ed25519_private_key();
pub fn to_ed25519_keypair(private_key: &XPrv) -> (SecretKeyExtended, PublicKey) {
let private_key =
unsafe { SecretKeyExtended::from_bytes_unchecked(private_key.extended_secret_key()) };

let public_key = private_key.public_key();
(private_key, public_key)
}
8 changes: 3 additions & 5 deletions src/signing/key/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use bip39::Mnemonic;
use pallas::{
ledger::traverse::MultiEraTx,
txbuilder::{BuildConway, BuiltTransaction, Bytes, Bytes32, StagingTransaction},
wallet::keystore::PrivateKey,
};

use super::derive::get_ed25519_keypair;
Expand All @@ -23,10 +22,9 @@ pub fn to_built_transaction(tx: &MultiEraTx) -> BuiltTransaction {

pub fn sign_transaction(built_tx: BuiltTransaction, mnemonic: &Mnemonic) -> BuiltTransaction {
let (signing_key, _) = get_ed25519_keypair(mnemonic);
let signed_tx = match signing_key {
PrivateKey::Normal(secret_key) => built_tx.sign(&secret_key),
PrivateKey::Extended(secret_key_extended) => built_tx.sign(&secret_key_extended),
};

let signed_tx = built_tx.sign(&signing_key);

match signed_tx {
Ok(tx) => tx,
_ => panic!("Failed to sign transaction"),
Expand Down