aldabra: --bootstrap-from-xprv power-user import path
Adds RootKey::from_root_xsk_bech32() / from_xprv_bytes() / to_root_xsk_bech32() so RootKey can ingest + emit the same bech32 root extended secret key shape that cardano-cli + cardano-address + the IOG node priv/wallet/<name>/root.prv file already use. HRP is strictly root_xsk — refuses acct_xsk/addr_xsk to keep the import scoped to the actual HD root. New CLI flag --bootstrap-from-xprv runs an interactive import: paste root_xsk1... bech32, prompt passphrase, encrypt, persist as root-xprv.age (parallel to mnemonic.age). Refuses to overwrite either existing key file (per Sulkta's no-delete-crypto-keys rule — caller has to move aside, not delete). Startup path now checks for either mnemonic.age OR root-xprv.age; refuses if both exist (ambiguous). Same RootKey downstream — derivation tree, signing, all of it works identically whether the key came in via mnemonic or xprv import. Test root_xprv_round_trip proves the imported xprv derives to the same address as the mnemonic-imported equivalent.
This commit is contained in:
parent
c57316a4fb
commit
2ff007ccaf
3 changed files with 275 additions and 45 deletions
|
|
@ -61,14 +61,19 @@ async fn run() -> Result<()> {
|
|||
// CLI mode flags — all out-of-band, before the MCP transport
|
||||
// takes over stdio.
|
||||
//
|
||||
// `--generate-mnemonic` — print a fresh phrase, exit. No disk write.
|
||||
// `--bootstrap` — paste an existing phrase, encrypt, derive.
|
||||
// `--bootstrap-new` — generate, display, encrypt, derive (one shot).
|
||||
// (none) — load existing, start MCP server.
|
||||
// `--generate-mnemonic` — print a fresh phrase, exit. No disk write.
|
||||
// `--bootstrap` — paste an existing phrase, encrypt, derive.
|
||||
// `--bootstrap-new` — generate, display, encrypt, derive (one shot).
|
||||
// `--bootstrap-from-xprv` — paste a root_xsk1... bech32 (cnode root.prv,
|
||||
// cardano-address output), encrypt, derive.
|
||||
// Power-user import path for keys that came
|
||||
// from outside the BIP-39 mnemonic flow.
|
||||
// (none) — load existing, start MCP server.
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
let generate_only = args.iter().any(|a| a == "--generate-mnemonic");
|
||||
let bootstrap_only = args.iter().any(|a| a == "--bootstrap");
|
||||
let bootstrap_new = args.iter().any(|a| a == "--bootstrap-new");
|
||||
let bootstrap_from_xprv = args.iter().any(|a| a == "--bootstrap-from-xprv");
|
||||
|
||||
if generate_only {
|
||||
bootstrap::print_fresh_mnemonic()?;
|
||||
|
|
@ -76,22 +81,28 @@ async fn run() -> Result<()> {
|
|||
}
|
||||
|
||||
let mnemonic_path = bootstrap::mnemonic_path(&cfg.data_dir);
|
||||
let xprv_path = bootstrap::root_xprv_path(&cfg.data_dir);
|
||||
let any_key_exists = mnemonic_path.exists() || xprv_path.exists();
|
||||
|
||||
// L-2 audit fix: scope `root` to a block so its XPrv drops + wipes
|
||||
// as soon as we've extracted the keys we need.
|
||||
let (payment_key, stake_key, address) = {
|
||||
let root = if bootstrap_new {
|
||||
bootstrap::generate_and_save_root_key(&cfg.data_dir)?
|
||||
} else if mnemonic_path.exists() || bootstrap_only {
|
||||
// Both branches load (or create on the bootstrap path).
|
||||
// `load_or_create_root_key` itself decides which based on
|
||||
// whether `mnemonic.age` exists.
|
||||
} else if bootstrap_from_xprv {
|
||||
bootstrap::import_root_xprv(&cfg.data_dir)?
|
||||
} else if any_key_exists || bootstrap_only {
|
||||
// Loads existing (or runs the mnemonic-paste flow on
|
||||
// first-run with --bootstrap). load_or_create_root_key
|
||||
// itself picks between mnemonic.age and root-xprv.age.
|
||||
bootstrap::load_or_create_root_key(&cfg.data_dir)?
|
||||
} else {
|
||||
anyhow::bail!(
|
||||
"no mnemonic at {}. run `aldabra --bootstrap` (paste existing) \
|
||||
or `aldabra --bootstrap-new` (generate fresh) first.",
|
||||
mnemonic_path.display()
|
||||
"no key at {}. run one of:\n \
|
||||
`aldabra --bootstrap` (paste existing 24-word phrase)\n \
|
||||
`aldabra --bootstrap-new` (generate a fresh wallet)\n \
|
||||
`aldabra --bootstrap-from-xprv` (paste a root_xsk1... bech32)",
|
||||
cfg.data_dir.display()
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue