Repository: cryptoadvance/specter-desktop
Issue: Can't create nested segwit multisig wallet

I created a mainnet nested segwit 2of3 wallet with a variety of usb wallets. But it immediately crashes the system:

```
File "/Users/kdmukai/dev/bitcoin/specter-desktop/src/specter/specter.py", line 597, in sort_descriptor
pubkeys = self.cli.getaddressinfo(address)["pubkeys"]
KeyError: 'pubkeys'
```

Inspecting the `self.cli.getaddressinfo(address)` I see that there is no 'pubkeys' attr, but there is one in the 'embedded' section. So I added a check for that:
```
        # get pubkeys involved
        address_info = self.cli.getaddressinfo(address)
        if 'pubkeys' in address_info:
            pubkeys = address_info["pubkeys"]
        elif 'embedded' in address_info and 'pubkeys' in address_info['embedded']:
            pubkeys = address_info["embedded"]["pubkeys"]
        else:
            raise Exception("Could not find 'pubkeys' in address info:\\n%s" % json.dumps(address_info, indent=2))
```

That gets me through that part. But then the next hurdle is at:
```
File "/Users/kdmukai/dev/bitcoin/specter-desktop/src/specter/specter.py", line 543, in get_address
return self.cli.deriveaddresses(sorted_desc)[0]
File "/Users/kdmukai/dev/bitcoin/specter-desktop/src/specter/rpc.py", line 175, in fn
raise Exception("Server responded with error code %d: %s" % (r.status_code, r.text))
Exception: Server responded with error code 500: {"result":null,"error":{"code":-5,"message":"Cannot have sh in non-top level"},"id":0}
```

The descriptor it's working on begins:
`wsh(sh(multi(2,...`

But when I look at the specter wallet json it lists:
```
    "recv_descriptor": "sh(wsh(multi(2,...
    "change_descriptor": "sh(wsh(multi(2,
```

So the while the wallet's descriptor nesting is correct, it's getting transposed when loaded into Specter. Pull request on the way.

Running:
Bitcoin Core version v0.19.0.1-a284bbbee

Changed files:
src/specter/specter.py

diff --git a/src/specter/specter.py b/src/specter/specter.py
index 43e25149..8509b11a 100644
--- a/src/specter/specter.py
+++ b/src/specter/specter.py
@@ -590,23 +590,38 @@ class Wallet(dict):
             descriptor = descriptor.replace("*", f"{index}")
         # remove checksum
         descriptor = descriptor.split("#")[0]
+
         # get address (should be already imported to the wallet)
         address = self.cli.deriveaddresses(AddChecksum(descriptor))[0]
+
         # get pubkeys involved
-        pubkeys = self.cli.getaddressinfo(address)["pubkeys"]
+        address_info = self.cli.getaddressinfo(address)
+        if 'pubkeys' in address_info:
+            pubkeys = address_info["pubkeys"]
+        elif 'embedded' in address_info and 'pubkeys' in address_info['embedded']:
+            pubkeys = address_info["embedded"]["pubkeys"]
+        else:
+            raise Exception("Could not find 'pubkeys' in address info:\\n%s" % json.dumps(address_info, indent=2))
+
         # get xpubs from the descriptor
         arr = descriptor.split("(multi(")[1].split(")")[0].split(",")
+
         # getting [wsh] or [sh, wsh]
         prefix = descriptor.split("(multi(")[0].split("(")
         sigs_required = arr[0]
         keys = arr[1:]
+
         # sort them according to sortedmulti
         z = sorted(zip(pubkeys,keys), key=lambda x: x[0])
         keys = [zz[1] for zz in z]
         inner = f"{sigs_required},"+",".join(keys)
         desc = f"multi({inner})"
+
+        # Write from the inside out
+        prefix.reverse()
         for p in prefix:
             desc = f"{p}({desc})"
+
         return AddChecksum(desc)
 
     def keypoolrefill(self, start, end=None, change=False):