Wiki Home

Wasabi keys state generation

2023-01-02

Create a visual representation from a Wasabi kyes dump.

How to run it

Run Wasabi, open the wallet you are interested in.

Next open a terminal and enter:

dotnet fsi keysgraph.fsx <wallet-name>

The result

The Code

#r "nuget:FSharp.Data"
#r "nuget:Plotly.NET"
#r "nuget:Plotly.NET.ImageExport"

open System
open System.IO
open Plotly.NET 
open Plotly.NET.ImageExport
open System.Net.Http
open FSharp.Data

type Config = JsonProvider<"""{
  "JsonRpcServerEnabled": true,
  "JsonRpcUser": "",
  "JsonRpcPassword": "",
  "JsonRpcServerPrefixes": [
    "http://127.0.0.1:37128/"
  ]
}""">

type RpcResponse = JsonProvider<"""{
  "result": [
     {"fullKeyPath":"xxxx","keyState":0}
  ]
}""">

let config = Config.Load(
  Path.Combine (
    Environment.ExpandEnvironmentVariables ("%HOME%/.walletwasabi/client/"),
    "Config.json"))

let args = Environment.GetCommandLineArgs()
let walletname = args[2]

let http = new HttpClient()
let rpcJsonResponseAsync () = async {
  let content = new StringContent ($"{{\"jsonrpc\":\"2.0\", \"id\":\"id\", \"method\":\"selectwallet\", \"params\":[\"{walletname}\"]}}")
  let! response = http.PostAsync(config.JsonRpcServerPrefixes[0], content) |> Async.AwaitTask

  let content = new StringContent ("{\"jsonrpc\":\"2.0\", \"id\":\"id\", \"method\":\"listkeys\"}")
  let! response = http.PostAsync(config.JsonRpcServerPrefixes[0], content) |> Async.AwaitTask
  let! jsonResult = response.Content.ReadAsStringAsync() |> Async.AwaitTask
  return RpcResponse.Parse(jsonResult)
} 

let rpcJsonResult = rpcJsonResponseAsync () |> Async.RunSynchronously
type KeyInfo = { Path: string; State: int }

let keys = 
    rpcJsonResult.Result 
    |> Array.map (fun x -> { Path=x.FullKeyPath; State=x.KeyState })
    |> List.ofArray

let filterByKeyPath (keys: KeyInfo list) (kp: string) =
    keys
    |> List.filter (fun k -> k.Path.StartsWith kp)
    |> List.sortBy (fun k -> int <| Array.last (k.Path.Split [|'/'|]))

let stateToHeat (key: KeyInfo) =
    key.State

let intSegwit = filterByKeyPath keys "84'/1'/0'/1" |> List.map stateToHeat
let extSegwit = filterByKeyPath keys "84'/1'/0'/0" |> List.map stateToHeat
let intTaproot= filterByKeyPath keys "86'/1'/0'/1" |> List.map stateToHeat
let extTaproot= filterByKeyPath keys "86'/1'/0'/0" |> List.map stateToHeat

let matrix = [ intSegwit; extSegwit; intTaproot; extTaproot ]
 
let rownames = ["segwit Int"; "segwit Ext"; "taproot Int"; "taproot ext"]
let colnames = []

let heat =
    Chart.Heatmap(
        matrix,
        colnames,
        rownames,
        UseDefaults = false
    )

heat |> Chart.show

Dependencies

None