add key derivation
This commit is contained in:
parent
40467ce13d
commit
10cda7824c
|
@ -1046,7 +1046,9 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"icepick-module",
|
"icepick-module",
|
||||||
|
"keyfork-derive-util",
|
||||||
"keyforkd-client",
|
"keyforkd-client",
|
||||||
|
"keyforkd-models",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror 2.0.3",
|
"thiserror 2.0.3",
|
||||||
|
|
|
@ -167,7 +167,7 @@ impl Module for Solana {
|
||||||
match (&fee_payer, &fee_payer_address) {
|
match (&fee_payer, &fee_payer_address) {
|
||||||
(Some(payer), Some(address)) => {
|
(Some(payer), Some(address)) => {
|
||||||
// Use the provided account
|
// Use the provided account
|
||||||
Some((payer.clone(), Pubkey::from_str_const(address)))
|
Some((u32::from_str(payer).unwrap(), Pubkey::from_str(address).unwrap()))
|
||||||
}
|
}
|
||||||
(None, None) => {
|
(None, None) => {
|
||||||
// Use the transaction account
|
// Use the transaction account
|
||||||
|
@ -185,19 +185,23 @@ impl Module for Solana {
|
||||||
&hash,
|
&hash,
|
||||||
);
|
);
|
||||||
let transaction = solana_sdk::transaction::Transaction::new_unsigned(message);
|
let transaction = solana_sdk::transaction::Transaction::new_unsigned(message);
|
||||||
let mut required_derivation_indices = vec![];
|
|
||||||
// TODO: error handling from_str
|
// TODO: error handling from_str
|
||||||
let from_account = from_account.and_then(|a| u32::from_str(&a).ok()).unwrap_or(0);
|
let from_account = from_account.and_then(|a| u32::from_str(&a).ok()).unwrap_or(0);
|
||||||
required_derivation_indices.push(from_account);
|
let mut requested_accounts = vec![];
|
||||||
|
requested_accounts.push(from_account | 1 << 31);
|
||||||
|
if let Some((account, _)) = &payer_account_and_pk {
|
||||||
|
requested_accounts.push(*account | 1 << 31);
|
||||||
|
}
|
||||||
Ok(serde_json::json!({
|
Ok(serde_json::json!({
|
||||||
"blob": transaction,
|
"blob": transaction,
|
||||||
|
"derivation-accounts": requested_accounts,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Operation::Sign(Sign {}) => {
|
Operation::Sign(Sign {}) => {
|
||||||
let blob = request.blob.expect("passed in instruction blob");
|
let blob = request.blob.expect("passed in instruction blob");
|
||||||
let transaction: solana_sdk::transaction::Transaction =
|
let transaction: solana_sdk::transaction::Transaction =
|
||||||
serde_json::from_value(blob).expect("valid message blob");
|
serde_json::from_value(blob).expect("valid message blob");
|
||||||
dbg!(transaction);
|
let keys = request.derived_keys.unwrap_or_default();
|
||||||
Ok(serde_json::json!({
|
Ok(serde_json::json!({
|
||||||
"blob": []
|
"blob": []
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -6,7 +6,9 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.5.20", features = ["cargo", "derive", "string"] }
|
clap = { version = "4.5.20", features = ["cargo", "derive", "string"] }
|
||||||
icepick-module = { version = "0.1.0", path = "../icepick-module" }
|
icepick-module = { version = "0.1.0", path = "../icepick-module" }
|
||||||
|
keyfork-derive-util = { version = "0.2.1", registry = "distrust" }
|
||||||
keyforkd-client = { version = "0.2.1", registry = "distrust" }
|
keyforkd-client = { version = "0.2.1", registry = "distrust" }
|
||||||
|
keyforkd-models = { version = "0.2.0", registry = "distrust" }
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
thiserror = "2.0.3"
|
thiserror = "2.0.3"
|
||||||
|
|
|
@ -18,7 +18,33 @@ pub fn get_command(bin_name: &str) -> (&str, Vec<&str>) {
|
||||||
struct ModuleConfig {
|
struct ModuleConfig {
|
||||||
name: String,
|
name: String,
|
||||||
command_name: Option<String>,
|
command_name: Option<String>,
|
||||||
derivation_prefix: String,
|
algorithm: keyfork_derive_util::request::DerivationAlgorithm,
|
||||||
|
#[serde(with = "serde_derivation")]
|
||||||
|
derivation_prefix: keyfork_derive_util::DerivationPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
mod serde_derivation {
|
||||||
|
use keyfork_derive_util::DerivationPath;
|
||||||
|
use serde::{Deserialize, Deserializer, Serializer};
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
pub fn serialize<S>(p: &DerivationPath, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
let path = p.to_string();
|
||||||
|
serializer.serialize_str(&path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize<'de, D>(deserializer: D) -> Result<DerivationPath, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
use serde::de::Error;
|
||||||
|
String::deserialize(deserializer).and_then(|string| {
|
||||||
|
DerivationPath::from_str(&string).map_err(|e| Error::custom(e.to_string()))
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Default)]
|
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||||
|
@ -45,7 +71,10 @@ pub fn do_cli_thing() {
|
||||||
// and coin_bin otherwise wouldn't live long enough
|
// and coin_bin otherwise wouldn't live long enough
|
||||||
for module in &config.modules {
|
for module in &config.modules {
|
||||||
let module_name = &module.name;
|
let module_name = &module.name;
|
||||||
let bin = module.command_name.clone().unwrap_or_else(|| format!("icepick-{module_name}"));
|
let bin = module
|
||||||
|
.command_name
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| format!("icepick-{module_name}"));
|
||||||
let (command, args) = get_command(&bin);
|
let (command, args) = get_command(&bin);
|
||||||
let mut child = Command::new(command)
|
let mut child = Command::new(command)
|
||||||
.args(args)
|
.args(args)
|
||||||
|
@ -93,6 +122,10 @@ pub fn do_cli_thing() {
|
||||||
}
|
}
|
||||||
let blob = cli_input.as_ref().and_then(|json| json.get("blob"));
|
let blob = cli_input.as_ref().and_then(|json| json.get("blob"));
|
||||||
|
|
||||||
|
let derivation_accounts = cli_input
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|json| json.get("derivation-accounts"));
|
||||||
|
|
||||||
let matches = icepick_command.get_matches();
|
let matches = icepick_command.get_matches();
|
||||||
if let Some((module, matches)) = matches.subcommand() {
|
if let Some((module, matches)) = matches.subcommand() {
|
||||||
if let Some((subcommand, matches)) = matches.subcommand() {
|
if let Some((subcommand, matches)) = matches.subcommand() {
|
||||||
|
@ -107,19 +140,50 @@ pub fn do_cli_thing() {
|
||||||
for arg in &operation.arguments {
|
for arg in &operation.arguments {
|
||||||
args.insert(&arg.name, matches.get_one::<String>(&arg.name));
|
args.insert(&arg.name, matches.get_one::<String>(&arg.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (algo, path) = config.modules.iter().find_map(|fmodule| {
|
||||||
|
if fmodule.name == module {
|
||||||
|
return Some((fmodule.algorithm.clone(), fmodule.derivation_prefix.clone()))
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
let mut derived_keys: Vec<Vec<u8>> = vec![];
|
||||||
|
if let Some(accounts) = derivation_accounts {
|
||||||
|
let accounts: Vec<keyfork_derive_util::DerivationIndex> =
|
||||||
|
serde_json::from_value(accounts.clone())
|
||||||
|
.expect("valid derivation-accounts");
|
||||||
|
let mut client =
|
||||||
|
keyforkd_client::Client::discover_socket().expect("keyforkd started");
|
||||||
|
for account in accounts {
|
||||||
|
let request = keyfork_derive_util::request::DerivationRequest::new(algo.clone(), &path.clone().chain_push(account));
|
||||||
|
let request = keyforkd_models::Request::Derivation(request);
|
||||||
|
let response = client.request(&request).expect("valid derivation");
|
||||||
|
match response {
|
||||||
|
keyforkd_models::Response::Derivation(keyfork_derive_util::request::DerivationResponse { data, .. }) => {
|
||||||
|
derived_keys.push(data.to_vec());
|
||||||
|
},
|
||||||
|
_ => panic!("Unexpected response"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let json = serde_json::json!({
|
let json = serde_json::json!({
|
||||||
"operation": subcommand,
|
"operation": subcommand,
|
||||||
"values": args,
|
"values": args,
|
||||||
"derived-keys": [],
|
"derived-keys": derived_keys,
|
||||||
"blob": blob,
|
"blob": blob,
|
||||||
});
|
});
|
||||||
let bin = commands.iter().find_map(|(fmodule, fcommand, _)| {
|
let bin = commands
|
||||||
if fmodule == module {
|
.iter()
|
||||||
Some(fcommand)
|
.find_map(|(fmodule, fcommand, _)| {
|
||||||
} else {
|
if fmodule == module {
|
||||||
None
|
Some(fcommand)
|
||||||
}
|
} else {
|
||||||
}).expect("previously found module should exist in new search");
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.expect("previously found module should exist in new search");
|
||||||
let (command, args) = get_command(bin);
|
let (command, args) = get_command(bin);
|
||||||
let mut child = Command::new(command)
|
let mut child = Command::new(command)
|
||||||
.args(args)
|
.args(args)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
[[module]]
|
[[module]]
|
||||||
name = "sol"
|
name = "sol"
|
||||||
derivation_prefix = "m/44'/501'"
|
derivation_prefix = "m/44'/501'"
|
||||||
|
algorithm = "Ed25519"
|
||||||
|
|
Loading…
Reference in New Issue