Bläddra i källkod

nockchain wallet update

tacryt-socryp 6 månader sedan
förälder
incheckning
8868e31b5b
8 ändrade filer med 254 tillägg och 73 borttagningar
  1. 3 0
      .env_example
  2. 6 4
      Cargo.toml
  3. 19 10
      Makefile
  4. 61 7
      README.md
  5. 33 18
      crates/nockchain-wallet/README.md
  6. 20 6
      crates/nockchain-wallet/src/main.rs
  7. 109 27
      hoon/apps/wallet/wallet.hoon
  8. 3 1
      rust-toolchain.toml

+ 3 - 0
.env_example

@@ -0,0 +1,3 @@
+RUST_LOG=info,nockchain=debug,nockchain_libp2p_io=info,libp2p=info,libp2p_quic=info
+MINIMAL_LOG_FORMAT=true
+MINING_PUBKEY=EHmKL2U3vXfS5GYAY5aVnGdukfDWwvkQPCZXnjvZVShsSQi3UAuA4tQQpVwGJMzc9FfpTY8pLDkqhBGfWutiF4prrCktUH9oAWJxkXQBzAavKDc95NR3DjmYwnnw8GuugnK

+ 6 - 4
Cargo.toml

@@ -22,15 +22,15 @@ resolver = "2"
 version = "0.1.0"
 edition = "2021"
 
-[workspace.dependencies.assert_no_alloc]
-path = "crates/nockvm/rust/assert_no_alloc"
-
 [workspace.dependencies.hoonc]
 path = "crates/hoonc"
 
 [workspace.dependencies.nockapp]
 path = "crates/nockapp"
 
+[workspace.dependencies.assert_no_alloc]
+path = "crates/nockvm/rust/assert_no_alloc"
+
 [workspace.dependencies.ibig]
 path = "crates/nockvm/rust/ibig"
 
@@ -68,6 +68,7 @@ libc = "0.2.171"
 memmap2 = "^0.9.5"
 num-derive = "0.4.2"
 signal-hook = "0.3"
+signal-hook-tokio = "0.3.1"
 static_assertions = "1.1.0"
 
 ## Sword crypto dependencies
@@ -142,7 +143,8 @@ hex-literal = "1.0.0"
 hickory-resolver = { version = "0.25.0-alpha.4", features = ["system-config"] }
 hickory-proto = "0.25.0-alpha.4"
 image = "0.24.7"
-libp2p = "0.55.0"
+# libp2p = "0.55.0"
+libp2p = { git = "ssh://git@github.com/libp2p/rust-libp2p.git", rev = "da0017ee887a868e231ed78c7de892779c17800d" }
 qrcode = "0.13"
 quickcheck = "1.0.3"
 quickcheck_macros = "1.0"

+ 19 - 10
Makefile

@@ -1,9 +1,13 @@
-# Set env variables
-export RUST_BACKTRACE := full
-export RUST_LOG := info,nockchain=debug,nockchain_libp2p_io=info,libp2p=info,libp2p_quic=info
-export MINIMAL_LOG_FORMAT := true
-export MINING_PUBKEY := EHmKL2U3vXfS5GYAY5aVnGdukfDWwvkQPCZXnjvZVShsSQi3UAuA4tQQpVwGJMzc9FfpTY8pLDkqhBGfWutiF4prrCktUH9oAWJxkXQBzAavKDc95NR3DjmYwnnw8GuugnK
+# Load environment variables from .env file
+include .env
 
+# Set default env variables if not set in .env
+export RUST_BACKTRACE ?= full
+export RUST_LOG ?= info,nockchain=debug,nockchain_libp2p_io=info,libp2p=info,libp2p_quic=info
+export MINIMAL_LOG_FORMAT ?= true
+export MINING_PUBKEY ?= EHmKL2U3vXfS5GYAY5aVnGdukfDWwvkQPCZXnjvZVShsSQi3UAuA4tQQpVwGJMzc9FfpTY8pLDkqhBGfWutiF4prrCktUH9oAWJxkXQBzAavKDc95NR3DjmYwnnw8GuugnK
+
+export
 
 .PHONY: build
 build: build-hoon-all build-rust
@@ -81,15 +85,14 @@ build-hoon: ensure-dirs update-hoonc $(HOON_TARGETS)
 	$(call show_env_vars)
 
 .PHONY: run-nockchain-leader
-run-nockchain-leader:  # Run nockchain mode in leader mode
+run-nockchain-leader:  # Run nockchain node in leader mode
 	$(call show_env_vars)
 	mkdir -p test-leader && cd test-leader && rm -f nockchain.sock && RUST_BACKTRACE=1 cargo run --release --bin nockchain -- --fakenet --genesis-leader --npc-socket nockchain.sock --mining-pubkey $(MINING_PUBKEY) --bind /ip4/0.0.0.0/udp/3005/quic-v1 --peer /ip4/127.0.0.1/udp/3006/quic-v1 --new-peer-id --no-default-peers
 
-.PHONY: run-nockchain-follower
-run-nockchain-follower:  # Run nockchain mode in follower mode
+.PHONY: run-nockchain
+run-nockchain:  # Run a nockchain node in follower mode with a mining pubkey
 	$(call show_env_vars)
-	mkdir -p test-follower && cd test-follower && rm -f nockchain.sock && RUST_BACKTRACE=1 cargo run --release --bin nockchain -- --fakenet --genesis-watcher --npc-socket nockchain.sock --mining-pubkey $(MINING_PUBKEY) --bind /ip4/0.0.0.0/udp/3006/quic-v1 --peer /ip4/127.0.0.1/udp/3005/quic-v1 --new-peer-id --no-default-peers
-
+	mkdir -p miner-node && cd miner-node && rm -f nockchain.sock && RUST_BACKTRACE=1 cargo run --release --bin nockchain -- --fakenet --genesis-watcher --npc-socket nockchain.sock --mining-pubkey $(MINING_PUBKEY) --bind /ip4/0.0.0.0/udp/3006/quic-v1 --peer /ip4/127.0.0.1/udp/3005/quic-v1 --new-peer-id --no-default-peers
 
 HOON_SRCS := $(find hoon -type file -name '*.hoon')
 
@@ -104,3 +107,9 @@ assets/wal.jam: update-hoonc hoon/apps/wallet/wallet.hoon $(HOON_SRCS)
 	$(call show_env_vars)
 	RUST_LOG=trace hoonc hoon/apps/wallet/wallet.hoon hoon
 	mv out.jam assets/wal.jam
+
+## Build mining.jam with hoonc
+assets/miner.jam: update-hoonc hoon/apps/dumbnet/miner.hoon $(HOON_SRCS)
+	$(call show_env_vars)
+	RUST_LOG=trace hoonc hoon/apps/dumbnet/miner.hoon hoon
+	mv out.jam assets/miner.jam

+ 61 - 7
README.md

@@ -12,6 +12,17 @@ We believe the future of blockchains is lightweight trustless settlement of heav
 
 Install `rustup` by following their instructions at: [https://rustup.rs/](https://rustup.rs/)
 
+Ensure you have these dependencies installed if running on Debian/Ubuntu:
+```
+sudo apt update
+sudo apt install clang llvm-dev libclang-dev
+```
+
+Copy the example environment file and rename it to `.env`:
+```
+cp .env_example .env
+```
+
 Install `hoonc`, the Hoon compiler:
 
 ```
@@ -32,30 +43,73 @@ After you've run the setup and build commands, install the wallet:
 make install-nockchain-wallet
 ```
 
-To run the wallet, see the nockchain-wallet [README](./crates/nockchain-wallet/README.md).
+See the nockchain-wallet [README](./crates/nockchain-wallet/README.md) for more information.
 
 
 ## Install Nockchain
 
-After you've run the setup and build commands, install the wallet:
+After you've run the setup and build commands, install Nockchain:
 
 ```
 make install-nockchain
 ```
 
+## Setup Keys
+
+To generate a new key pair:
+
+```
+nockchain-wallet keygen
+```
+
+This will print a new public/private key pair + chain code to the console, as well as the seed phrase for the private key.
+
+Now, copy the public key to the `.env` file:
+
+```
+MINING_PUBKEY=<public-key>
+```
 
-## Testing Nodes
+## Backup Keys
 
-To run a test Nockchain node that publishes the genesis block:
+To backup your keys, run:
 
 ```
-make run-nockchain-leader
+nockchain-wallet export-keys
 ```
 
+This will save your keys to a file called `keys.export` in the current directory.
+
+They can be imported later with:
+
+```
+nockchain-wallet import-keys --input keys.export
+```
+
+## Running Nodes
+
+To run a Nockchain miner:
+
+```
+make run-nockchain
+```
+
+## FAQ
+
+### Can I use same pubkey if running multiple miners?
+
+Yes, you can use the same pubkey if running multiple miners.
+
+### How do I change the mining pubkey?
+
+Run `nockchain-wallet keygen` to generate a new key pair and copy the new public key to the `.env` file.
+
+### How do I import an existing key that I generated with a different tool?
 
-To run a test Nockchain node that waits for the genesis block:
+If you have a **base58 encoded** public key *AND* a **base58 encoded** chain code, you can import it with:
 
 ```
-make run-nockchain-follower
+nockchain-wallet import-master-pubkey --key <base58-encoded-public-key> --chain-code <base58-encoded-chain-code>
 ```
 
+But you really should use the `nockchain-wallet keygen` command to generate a new key pair and use that instead.

+ 33 - 18
crates/nockchain-wallet/README.md

@@ -1,6 +1,6 @@
 # Nockchain Wallet
 
-## Key Management
+## Setup
 
 ### Generate New Key Pair
 
@@ -9,16 +9,44 @@
 nockchain-wallet keygen
 ```
 
-### Import Private Key
+### Importing and Exporting Keys
+
+The wallet supports importing and exporting keys:
 
 ```bash
-# Import keys from a jammed file
-nockchain-wallet import-keys --input path/to/keys.jam
+# Export all wallet keys to a file (default: keys.export)
+nockchain-wallet export-keys
+
+# Import keys from the exported file
+nockchain-wallet import-keys --input keys.export
 
 # Import a master public key and chain code
-nockchain-wallet import-master-pubkey --key <base58-key> --knot <base58-chain-code>
+nockchain-wallet import-master-pubkey --key <base58-key> --chain-code <base58-chain-code>
 ```
 
+The exported keys file contains all wallet keys as a `jam` file that can be imported on another instance.
+
+Can be used for:
+- Backing up your wallet
+- Migrating to a new device
+- Sharing public keys with other users
+
+### Connecting to Nockchain
+
+The wallet needs to connect to a running nockchain instance to perform operations like checking balances, broadcasting transactions, etc.
+
+```bash
+# Connect to nockchain using a Unix domain socket
+nockchain-wallet --nockchain-socket ./nockchain.sock <command>
+```
+
+Note: Make sure nockchain is running and the socket path matches your nockchain configuration.
+
+
+
+# Advanced Options
+
+
 ### Generate Master Private Key from Seed Phrase
 
 ```bash
@@ -44,19 +72,6 @@ nockchain-wallet derive-child --key-type <pub|priv> --index <0-255>
 Derives a child public or private key at the given index from the current master key.
 
 
-## Connecting to Nockchain
-
-The wallet needs to connect to a running nockchain instance to perform operations like checking balances, broadcasting transactions, etc.
-
-```bash
-# Connect to nockchain using a Unix domain socket
-nockchain-wallet --nockchain-socket ./test-leader/nockchain.sock <command>
-
-# Example: broadcasting a transaction
-nockchain-wallet --nockchain-socket ./test-leader/nockchain.sock make-tx --draft my_draft
-```
-
-Note: Make sure nockchain is running and the socket path matches your nockchain configuration.
 
 
 ## Listing Notes

+ 20 - 6
crates/nockchain-wallet/src/main.rs

@@ -90,6 +90,9 @@ pub enum Commands {
         input: String,
     },
 
+    /// Export keys to a file
+    ExportKeys,
+
     /// Signs a transaction
     SignTx {
         /// Path to input bundle file
@@ -174,7 +177,7 @@ pub enum Commands {
         key: String,
         /// Base58-encoded chain code
         #[arg(short, long)]
-        knot: String,
+        chain_code: String,
     },
 
     /// Lists all public keys in the wallet
@@ -196,6 +199,7 @@ impl Commands {
             Commands::Keygen => "keygen",
             Commands::DeriveChild { .. } => "derive-child",
             Commands::ImportKeys { .. } => "import-keys",
+            Commands::ExportKeys => "export-keys",
             Commands::SignTx { .. } => "sign-tx",
             Commands::GenMasterPrivkey { .. } => "gen-master-privkey",
             Commands::GenMasterPubkey { .. } => "gen-master-pubkey",
@@ -434,6 +438,12 @@ impl Wallet {
         Self::wallet("import-keys", &[pubkey_noun], Operation::Poke, &mut slab)
     }
 
+    /// Exports keys to a file.
+    fn export_keys() -> CommandNoun<NounSlab> {
+        let mut slab = NounSlab::new();
+        Self::wallet("export-keys", &[], Operation::Poke, &mut slab)
+    }
+
     /// Performs a simple scan of the blockchain.
     ///
     /// # Arguments
@@ -642,15 +652,15 @@ impl Wallet {
     /// # Arguments
     ///
     /// * `key` - Base58-encoded public key
-    /// * `knot` - Base58-encoded chain code
-    fn import_master_pubkey(key: &str, knot: &str) -> CommandNoun<NounSlab> {
+    /// * `chain_code` - Base58-encoded chain code
+    fn import_master_pubkey(key: &str, chain_code: &str) -> CommandNoun<NounSlab> {
         let mut slab = NounSlab::new();
         let key_noun = make_tas(&mut slab, key).as_noun();
-        let knot_noun = make_tas(&mut slab, knot).as_noun();
+        let chain_code_noun = make_tas(&mut slab, chain_code).as_noun();
 
         Self::wallet(
             "import-master-pubkey",
-            &[key_noun, knot_noun],
+            &[key_noun, chain_code_noun],
             Operation::Poke,
             &mut slab,
         )
@@ -749,6 +759,7 @@ async fn main() -> Result<(), NockAppError> {
         Commands::Keygen
         | Commands::DeriveChild { .. }
         | Commands::ImportKeys { .. }
+        | Commands::ExportKeys
         | Commands::SignTx { .. }
         | Commands::MakeTx { .. }
         | Commands::GenMasterPrivkey { .. }
@@ -797,6 +808,7 @@ async fn main() -> Result<(), NockAppError> {
         }
         Commands::SignTx { draft, index } => Wallet::sign_tx(draft, *index),
         Commands::ImportKeys { input } => Wallet::import_keys(input),
+        Commands::ExportKeys => Wallet::export_keys(),
         Commands::GenMasterPrivkey { seedphrase } => Wallet::gen_master_privkey(seedphrase),
         Commands::GenMasterPubkey { master_privkey } => Wallet::gen_master_pubkey(master_privkey),
         Commands::Scan {
@@ -823,7 +835,9 @@ async fn main() -> Result<(), NockAppError> {
         } => Wallet::simple_spend(names.clone(), recipients.clone(), gifts.clone(), *fee),
         Commands::MakeTx { draft } => Wallet::make_tx(draft),
         Commands::UpdateBalance => Wallet::update_balance(),
-        Commands::ImportMasterPubkey { key, knot } => Wallet::import_master_pubkey(key, knot),
+        Commands::ImportMasterPubkey { key, chain_code } => {
+            Wallet::import_master_pubkey(key, chain_code)
+        }
         Commands::ListPubkeys => Wallet::list_pubkeys(),
         Commands::ShowSeedphrase => Wallet::show_seedphrase(),
         Commands::ShowMasterPubkey => Wallet::show_master_pubkey(),

+ 109 - 27
hoon/apps/wallet/wallet.hoon

@@ -158,7 +158,8 @@
 +$  cause
   $%  [%keygen entropy=byts salt=byts]
       [%derive-child key-type=?(%pub %prv) i=@ label=(unit @t)]
-      [%import-keys keys=(list (pair trek coil))]
+      [%import-keys keys=(list (pair trek meta))]
+      [%export-keys ~]
       [%import-master-pubkey key=@t cc=@t]           ::  base58-encoded pubkey + chain code
       [%make-tx dat=draft]
       [%list-notes-by-pubkey pubkey=@t]                ::  base58-encoded pubkey
@@ -361,14 +362,14 @@
   |*  meg=tape
   |*  *
   ?.  bug  +<
-  ~>  %slog.[1 (crip "WARN: !! {meg} !!")]
+  ~>  %slog.[1 (cat 3 'wallet: warning: ' (crip meg))]
   +<
 ::
 ++  debug
   |*  meg=tape
   |*  *
   ?.  bug  +<
-  ~>  %slog.[2 (crip "wallet: {meg}")]
+  ~>  %slog.[2 (cat 3 'wallet: debug: ' (crip meg))]
   +<
 ::
 ++  moat  (keep state)
@@ -1024,6 +1025,7 @@
       %update-balance        (do-update-balance cause)
       %update-block          (do-update-block cause)
       %import-keys           (do-import-keys cause)
+      %export-keys           (do-export-keys cause)
       %import-master-pubkey  (do-import-master-pubkey cause)
       %gen-master-privkey    (do-gen-master-privkey cause)
       %gen-master-pubkey     (do-gen-master-pubkey cause)
@@ -1068,19 +1070,23 @@
           (~(del by peek-requests.state) pid)
         ?~  softed
           %-  (debug "handle-npc: %balance: could not soft result")
-          `state
+          [[%exit 0]~ state]
         =/  balance-result=(unit (unit _balance.state))  u.softed
         ?~  balance-result
           %-  (warn "%update-balance did not return a result: bad path")
-          `state
+          [[%exit 0]~ state]
         ?~  u.balance-result
           %-  (warn "%update-balance did not return a result: nothing")
-          `state
+          [[%exit 0]~ state]
         ?~  u.u.balance-result
           %-  (warn "%update-balance did not return a result: empty result")
-          `state
+          [[%exit 0]~ state]
         =.  balance.state  u.u.balance-result
         %-  (debug "balance state updated!")
+        ::  count the number of notes in the balance
+        =/  note-count=@ud
+          (lent ~(tap z-by:zo balance.state))
+        %-  (debug "note count: {<note-count>}")
         =.  name-to-hash.state
           %-  ~(run z-by:zo balance.state)
           |=  not=nnote:transact
@@ -1116,19 +1122,19 @@
           (~(del by peek-requests.state) pid)
         ?~  softed
           %-  (warn "handle-npc: %block: could not soft result")
-          `state
+          [[%exit 0]~ state]
         =/  block-result  u.softed
         %-  (debug "handle-npc: %block: {<block-result>}")
         %-  (debug "handle-npc: %block: {<peek-requests.state>}")
         ?~  block-result
           %-  (warn "handle-npc: %block: bad path")
-          `state
+          [[%exit 0]~ state]
         ?~  u.block-result
           %-  (warn "handle-npc: %block: nothing")
-          `state
+          [[%exit 0]~ state]
         ?~  u.u.block-result
           %-  (warn "handle-npc: %block: empty result")
-          `state
+          [[%exit 0]~ state]
         %-  (debug "handle-npc: %block: found block")
         %-  (debug "handle-npc: {<(to-b58:block-id:transact (need u.u.block-result))>}")
         %-  (debug "handle-npc: hash: {<(to-b58:hash:transact (need u.u.block-result))>}")
@@ -1252,11 +1258,58 @@
     ?>  ?=(%import-keys -.cause)
     =/  new-keys=_keys.state
       %+  roll  keys.cause
-      |=  [[=trek =coil] acc=_keys.state]
-      (~(put of acc) trek coil)
-    `state(keys new-keys)
+      |=  [[=trek =meta] acc=_keys.state]
+      (~(put of acc) trek meta)
+    =/  master-key=coil
+      %-  head
+      %+  murn  ~(tap of new-keys)
+      |=  [t=trek m=meta]
+      ^-  (unit coil)
+      ?:  ?&
+            ?=(%coil -.m)
+            =((slag 2 t) /pub/m)
+          ==
+        `m
+      ~
+    =/  key-list=(list tape)
+      %+  murn  ~(tap of new-keys)
+      |=  [t=trek m=meta]
+      ^-  (unit tape)
+      ?:  ?=(%coil -.m)
+        `(en:base58:wrap p.key.m)
+      ~
+    =.  master.state  `master-key
+    :_  state(keys new-keys)
+    :~  :-  %markdown
+        %-  crip
+        """
+        ## imported keys
+
+        {<key-list>}
+        """
+        [%exit 0]
+    ==
+  ::
+  ++  do-export-keys
+    |=  =cause
+    ?>  ?=(%export-keys -.cause)
+    =/  keys-list=(list [trek meta])
+      ~(tap of keys.state)
+    =/  dat-jam  (jam keys-list)
+    =/  path=@t  'keys.export'
+    =/  =effect  [%file %write path dat-jam]
+    :_  state
+    :~  effect
+        :-  %markdown
+        %-  crip
+        """
+        ## exported keys
+
+        - path: {<path>}
+        """
+        [%exit 0]
+    ==
   ::
-  ::>)  TODO: update state.master as well
   ++  do-import-master-pubkey
     |=  =cause
     ?>  ?=(%import-master-pubkey -.cause)
@@ -1268,7 +1321,16 @@
     =/  label  `(crip "master-public-{<(end [3 4] public-key:cor)>}")
     %-  (debug "Imported master public key: {<public-key:cor>}")
     =.  keys.state  (key:put:v master-pubkey-coil ~ label)
-    `state
+    :_  state
+    :~  :-  %markdown
+        %-  crip
+        """
+        ## master public key
+
+        {<public-key:cor>}
+        """
+        [%exit 0]
+    ==
   ::
   ++  do-gen-master-privkey
     |=  =cause
@@ -1301,18 +1363,27 @@
     =.  keys.state  (key:put:v master-privkey-coil ~ private-label)
     =.  keys.state  (key:put:v master-pubkey-coil ~ public-label)
     %-  (debug "master.state: {<master.state>}")
-    `state
+    :_  state
+    :~  :-  %markdown
+        %-  crip
+        """
+        ## master public key
+
+        {<public-key:cor>}
+        """
+        [%exit 0]
+    ==
   ::
   ++  do-make-tx
     |=  =cause
     ?>  ?=(%make-tx -.cause)
-    %-  (debug "make-tx: {<dat.cause>}")
+    %-  (debug "make-tx: creating raw-tx")
     ::  note that new:raw-tx calls +validate already
     =/  raw=raw-tx:transact  (new:raw-tx:transact p.dat.cause)
     =/  tx-id  id.raw
     =/  nock-cause=$>(%fact cause:dumb)
       [%fact %0 %heard-tx raw]
-    %-  (debug "make-tx: new-tx {<tx-id>}")
+    %-  (debug "make-tx: made raw-tx, poking over npc")
     :_  state
     :~
       [%npc 0 %poke nock-cause]
@@ -1329,9 +1400,16 @@
       =/  pubkey=schnorr-pubkey:transact  pub:(from-public:s10 [p.key cc]:coil)
       %-  trip
       (to-b58:schnorr-pubkey:transact pubkey)
-    %-  (debug "base58-keys: {<base58-keys>}")
-    :-  [%exit 0]~
-    state
+    :_  state
+    :~  :-  %markdown
+        %-  crip
+        """
+        ## pubkeys
+
+        {<base58-keys>}
+        """
+        [%exit 0]
+    ==
   ::
   ++  do-show-seedphrase
     |=  =cause
@@ -1469,7 +1547,7 @@
           ==
       ==
     :_  state
-    ~[(make-markdown-effect nodes)]
+    ~[(make-markdown-effect nodes) [%exit 0]]
   ::
   ++  do-list-notes
     |=  =cause
@@ -1645,10 +1723,8 @@
     =/  master-public-coil  [%coil [%pub public-key] chain-code]:cor
     =/  master-private-coil  [%coil [%prv private-key] chain-code]:cor
     =.  master.state  (some master-public-coil)
-    %-  (debug "keygen: new public key {<public-key:cor>}")
-    %-  (debug "keygen: public key: base58 {<(en:base58:wrap public-key:cor)>}")
-    %-  (debug "keygen: new private key {<private-key:cor>}")
-    %-  (debug "keygen: private key: base58 {<(en:base58:wrap private-key:cor)>}")
+    %-  (debug "keygen: public key: {<(en:base58:wrap public-key:cor)>}")
+    %-  (debug "keygen: private key: {<(en:base58:wrap private-key:cor)>}")
     =/  pub-label  `(crip "master-public-{<(end [3 4] public-key:cor)>}")
     =/  prv-label  `(crip "master-public-{<(end [3 4] public-key:cor)>}")
     =.  keys.state  (key:put:v master-public-coil ~ pub-label)
@@ -1665,6 +1741,12 @@
 
         ### New Private Key
         {<(en:base58:wrap private-key:cor)>}
+
+        ### Chain Code
+        {<(en:base58:wrap chain-code:cor)>}
+
+        ### Seed Phrase
+        {<seed-phrase>}
         """
         [%exit 0]
     ==

+ 3 - 1
rust-toolchain.toml

@@ -1,2 +1,4 @@
 [toolchain]
-channel = "1.86.0"
+channel = "nightly-2025-02-14"
+components = ["miri"]
+