From 718061d28441abae06dae60c9806df33876d12fa Mon Sep 17 00:00:00 2001 From: Alekos Filini Date: Wed, 29 Apr 2020 14:42:27 +0200 Subject: [PATCH] Initial commit --- .gitignore | 3 + .gitmodules | 3 + archetypes/default.md | 6 + config.toml | 33 ++ content/_index.md | 28 ++ content/descriptors/_index.md | 36 ++ content/repl/_index.md | 12 + content/repl/compiler.md | 151 +++++++++ content/repl/concept.md | 26 ++ content/repl/installation.md | 63 ++++ content/repl/interface.md | 428 ++++++++++++++++++++++++ content/repl/regtest.md | 34 ++ layouts/partials/custom-footer.html | 2 + layouts/partials/favicon.html | 7 + layouts/partials/logo.html | 3 + layouts/partials/menu-footer.html | 10 + layouts/shortcodes/json.html | 2 + static/css/jsonview.css | 88 +++++ static/css/style.css | 20 ++ static/icons/android-chrome-192x192.png | Bin 0 -> 10952 bytes static/icons/android-chrome-512x512.png | Bin 0 -> 32066 bytes static/icons/apple-touch-icon.png | Bin 0 -> 10778 bytes static/icons/browserconfig.xml | 9 + static/icons/favicon-16x16.png | Bin 0 -> 961 bytes static/icons/favicon-32x32.png | Bin 0 -> 1848 bytes static/icons/favicon.ico | Bin 0 -> 15086 bytes static/icons/mstile-150x150.png | Bin 0 -> 9624 bytes static/icons/safari-pinned-tab.svg | 82 +++++ static/icons/site.webmanifest | 19 ++ static/images/logo.svg | 283 ++++++++++++++++ static/images/wizard.svg | 327 ++++++++++++++++++ static/js/github-buttons.js | 6 + static/js/jsonview.js | 330 ++++++++++++++++++ static/js/main.js | 6 + themes/learn | 1 + 35 files changed, 2018 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 archetypes/default.md create mode 100644 config.toml create mode 100644 content/_index.md create mode 100644 content/descriptors/_index.md create mode 100644 content/repl/_index.md create mode 100644 content/repl/compiler.md create mode 100644 content/repl/concept.md create mode 100644 content/repl/installation.md create mode 100644 content/repl/interface.md create mode 100644 content/repl/regtest.md create mode 100644 layouts/partials/custom-footer.html create mode 100644 layouts/partials/favicon.html create mode 100644 layouts/partials/logo.html create mode 100644 layouts/partials/menu-footer.html create mode 100644 layouts/shortcodes/json.html create mode 100644 static/css/jsonview.css create mode 100644 static/css/style.css create mode 100644 static/icons/android-chrome-192x192.png create mode 100644 static/icons/android-chrome-512x512.png create mode 100644 static/icons/apple-touch-icon.png create mode 100644 static/icons/browserconfig.xml create mode 100644 static/icons/favicon-16x16.png create mode 100644 static/icons/favicon-32x32.png create mode 100644 static/icons/favicon.ico create mode 100644 static/icons/mstile-150x150.png create mode 100644 static/icons/safari-pinned-tab.svg create mode 100644 static/icons/site.webmanifest create mode 100644 static/images/logo.svg create mode 100644 static/images/wizard.svg create mode 100644 static/js/github-buttons.js create mode 100644 static/js/jsonview.js create mode 100644 static/js/main.js create mode 160000 themes/learn diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..69d9321068 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/public + +*.swp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..6433a7d0e7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "themes/learn"] + path = themes/learn + url = https://github.com/matcornic/hugo-theme-learn.git diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 0000000000..00e77bd79b --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,6 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +draft: true +--- + diff --git a/config.toml b/config.toml new file mode 100644 index 0000000000..f9b2445190 --- /dev/null +++ b/config.toml @@ -0,0 +1,33 @@ +baseURL = "https://magicalbitcoin.org/" +languageCode = "en-us" +title = "Magical Bitcoin" +theme = "learn" + +[outputs] +home = [ "HTML", "RSS", "JSON"] + +[params] +# Prefix URL to edit current page. Will display an "Edit this page" button on top right hand corner of every page. +# Useful to give opportunity to people to create merge request for your doc. +# See the config.toml file from this documentation site to have an example. +editURL = "https://github.com/MagicalBitcoin/docs/edit/master/content/" +# Author of the site, will be used in meta information +author = "Alekos Filini - @afilini" +# Description of the site, will be used in meta information +description = "The Magical Bitcoin project aims to build a collection of tools and libraries that are designed to be a solid foundation for Bitcoin wallets." +# A title for shortcuts in menu is set by default. Set this to true to disable it. +# disableShortcutsTitle = false +# Hide breadcrumbs in the header and only show the current page title +disableBreadcrumb = true +# Hide Next and Previous page buttons normally displayed full height beside content +disableNextPrev = false +# Order sections in menu by "weight" or "title". Default to "weight" +ordersectionsby = "weight" +# Change default color scheme with a variant one. Can be "red", "blue", "green". +themeVariant = "blue" +# Provide a list of custom css files to load relative from the `static/` folder in the site root. +custom_css = ["css/style.css", "css/jsonview.css"] + +# render raw html +[markup.goldmark.renderer] +unsafe= true diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000000..a61a1c0021 --- /dev/null +++ b/content/_index.md @@ -0,0 +1,28 @@ +--- +title: "Home" +date: 2020-04-28T09:46:18+02:00 +draft: false +--- + +# 🧙 Magical Bitcoin 🧙 + +The Magical Bitcoin project aims to build a collection of tools and libraries that are designed to be a solid foundation for Bitcoin wallets, along with a fully working *reference implementation* wallet. +All of its components are designed to be lightweight and modular so that they can be adapted for virtually any use-case: from the single-sig mobile wallet to the multi-billion-dollar cold storage vault. + +The main long-term goal is to concentrate the development efforts of multiple people and companies into one open source and very well reviewed project, instead of dispersing them over multiple closed/semi-closed or +poorly designed projects. + +{{% notice info %}} +Keep in mind that this project is still in a very early phase of development. The APIs and the general architecture shouldn't be considered stable yet. At the moment most of the code is concentrated in the +[main repo](https://github.com/MagicalBitcoin/magical-bitcoin-wallet) and is slowly being refactored and taken out into separate, independent modules. +{{% /notice %}} + +## Descriptors + +The name of the project refers to the fact that when its components are built into a wallet, it can "almost magically" support very complex spending policies, without having to individually translate them into code. It may sound disappointing, but there isn't, in fact, +any real magic in this wallet: the generalization is achieved thanks to *descriptors*, that are now slowly starting to see adoption in a few other Bitcoin projects as well. + +The author of this project strongly believes descriptors will be a big part of the future generation of Bitcoin wallets, since they provide a very flexible scripting language that can also be extended as the +technology and tooling on Bitcoin evolve and change (Schnorr signatures, Taproot, etc). + +To learn more, check the specific [Descriptors section](/descriptors). diff --git a/content/descriptors/_index.md b/content/descriptors/_index.md new file mode 100644 index 0000000000..d92f5ef694 --- /dev/null +++ b/content/descriptors/_index.md @@ -0,0 +1,36 @@ +--- +title: "Descriptors" +date: 2020-04-28T14:40:12+02:00 +draft: false +weight: 5 +pre: ' ' +--- + +Magical Bitcoin extends the capabilities of [rust-miniscript](https://github.com/apoelstra/rust-miniscript) by introducing the concept of an *ExtendedDescriptor*: it represents a descriptor that contains one or more "derivable keys" like `xpubs` or `xprvs` +and can be "derived" to a normal Descriptor by deriving every single one of its keys. It is currently called "StringDescriptor" in the code, because it's implemented as a wrapped `miniscript::Descriptor`. + +ExtendedDescriptors are derived using a single index instead of a full derivation path: this is because normally most of the path is fixed and can be represented right after the xpub/xprv itself, and only the +final index changes for each address. This is what's normally called a *DescriptorExtendedKey* in codebase, and it's the represented with a similar syntax to Bitcoin Core's, such as: + +``` +[d34db33f/44'/0'/0']xpub6ERApfZwUNrhL.......rBGRjaDMzQLcgJvLJuZZvRcEL/0/* +``` + +For more details regarding this syntax, see [this document](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md). On top of this, ExtendedDescriptors also support other formats for public and private keys, +like WIF and raw hexadecimal representation. + +Speaking of syntax, the general descriptor operators syntax is a bit different from what Core uses: the `multi()`/`sortedmulti()` are not available, and they are replaced by `thresh_m()`. Also the `combo()` operator is not +available, and doesn't currently have any replacement. For more informations, see [this page](http://bitcoin.sipa.be/miniscript). + +Some examples of valid descriptors are: + +
+ +| Spending Policy | Descriptor | Address 0 | Address 1 | +| --------------- | ---------- | --------- | --------- | +| Static P2PKH | `pkh(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR)` | mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr | mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr | +| Static P2PKH, watch-only | `pkh(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)` | mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr | mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr | +| P2WSH 2-of-2 with one private key | `wsh(thresh_m(2,tprv8ZgxMBicQKsPePmENhT9N9yiSfTtDoC1f39P7nNmgEyCB6Nm4Qiv1muq4CykB9jtnQg2VitBrWh8PJU8LHzoGMHTrS2VKBSgAz7Ssjf9S3P/0/*,tpubDBYDcH8P2PedrEN3HxWYJJJMZEdgnrqMsjeKpPNzwe7jmGwk5M3HRdSf5vudAXwrJPfUsfvUPFooKWmz79Lh111U51RNotagXiGNeJe3i6t/1/*))` | tb1qqsat6c82fvdy73rfzye8f7nwxcz3xny7t56azl73g95mt3tmzvgs9a8vjs | tb1q7sgx6gscgtau57jduend6a8l445ahpk3dt3u5zu58rx5qm27lhkqgfdjdr | +| P2WSH-P2SH one key + 10 days timelock | `sh(wsh(and_v(vc:pk_h(tprv8ZgxMBicQKsPePmENhT9N9yiSfTtDoC1f39P7nNmgEyCB6Nm4Qiv1muq4CykB9jtnQg2VitBrWh8PJU8LHzoGMHTrS2VKBSgAz7Ssjf9S3P/0/*),older(1440))))` | 2Mtk2nyS98MCi2P7TkoBGLaJviBy956XxB1 | 2MuEStKzYhqb5HCFgHz9153tZsL5sVqV5xC | + +
diff --git a/content/repl/_index.md b/content/repl/_index.md new file mode 100644 index 0000000000..07ae230c7d --- /dev/null +++ b/content/repl/_index.md @@ -0,0 +1,12 @@ ++++ +title = "REPL" +date = 2020-04-28T17:03:00+02:00 +weight = 1 +chapter = true +pre = ' ' ++++ + +# REPL + +The [magical-bitcoin-wallet](https://github.com/magicalbitcoin/magical-bitcoin-wallet) repo has a very minimalistic interactive shell that acts both as a reference implementation of a wallet and a tool to +quickly experiment with descriptors and transactions. diff --git a/content/repl/compiler.md b/content/repl/compiler.md new file mode 100644 index 0000000000..2a9633fa39 --- /dev/null +++ b/content/repl/compiler.md @@ -0,0 +1,151 @@ +--- +title: "Compiler" +date: 2020-04-29T12:06:50+02:00 +draft: false +weight: 5 +pre: "5. " +--- + +## Introduction + +If you want to play around with more complicated spending policies, you'll start to find it harder and harder to manually create the descriptors. This is where the miniscript compiler comes in! `magical-bitcoin-wallet` +includes a very simple compiler that can produce a descriptor given a spending policy. The syntax used to encode the spending policiy is very well described [in this page](http://bitcoin.sipa.be/miniscript/), +specifically in the "Policy to Miniscript compiler". The compiler included in Magical Bitcoin does basically the same job, but produces a descriptors for `rust-miniscript` that has some minor differences from +the ones made by the C++ implementation used in that website. + +## Installation + +To install the miniscript compiler run the following command: + +```bash +cargo install --git https://github.com/magicalbitcoin/magical-bitcoin-wallet --features="compiler" --example miniscriptc +``` + +Once the command is done, you should have a `miniscriptc` command available. You can check if that's the case by running `miniscriptc --help`. + +## Usage + +In this case the interface is very simple: it accepts two arguments called "POLICY" and "TYPE", in this order. The first one, as the name implies, sets the spending policy to compile. The latter defines the type +of address that should be used to incapsulate the produced script, like a P2SH, P2WSH, etc. + +Optionally, the `--parsed_policy` flag can be enabled and it will make the compiler print the JSON "human-readable" version of the spending policy, as described in the [`policies subcommand`](/repl/interface/#policies) of the CLI. + +The `--network` flag can be used to change the network encoding of the address shown. + +{{% notice tip %}} +Keep in mind that since the compiler loads and interprets the descriptor, all the public keys specified in the policy must be valid public keys. This differs from the web tool linked above that also accepts +placeholders too. As described in the previous sections of this guide, the keys can be either `xpub`/`xprv` with or without metadata and a derivation path, WIF keys or raw hex public keys. +{{% /notice %}} + +## Example + +Let's take this policy for example: + +```bash +miniscriptc --parsed_policy and(pk(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR),or(50@pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),older(1000)))) sh-wsh +``` + +The compiler should print something like: + +```text +[2020-04-29T10:42:05Z INFO miniscriptc] Compiling policy: and(pk(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR),or(50@pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),older(1000))) +[2020-04-29T10:42:05Z INFO miniscriptc] ... Descriptor: sh(wsh(and_v(or_c(c:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),v:older(1000)),c:pk(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR)))) +[2020-04-29T10:42:05Z INFO miniscriptc] ... First address: 2MsqrJuZewY3o3ADAy1Uhi5vsBqTANjH3Cf +``` + +JSON policy: + +{{% json %}} +{ + "type":"THRESH", + "items":[ + { + "type":"THRESH", + "items":[ + { + "type":"SIGNATURE", + "pubkey":"02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c", + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"NONE" + } + }, + { + "type":"RELATIVETIMELOCK", + "value":1000, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{ + "csv":1000 + } + } + } + ], + "threshold":1, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"PARTIALCOMPLETE", + "n":2, + "m":1, + "items":[ + 1 + ], + "conditions":{ + "[1]":[ + { + "csv":1000 + } + ] + } + } + }, + { + "type":"SIGNATURE", + "pubkey":"02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c", + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{ + + } + } + } + ], + "threshold":2, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"PARTIALCOMPLETE", + "n":2, + "m":2, + "items":[ + 0, + 1 + ], + "conditions":{ + "[0, 1]":[ + { + "csv":1000 + } + ] + } + } +} +{{% /json %}} + +## Troubleshooting + +#### Nothing is printed + +This might mean that you have a `RUST_LOG` variable set to a value that suppresses the compiler's log. You can try adding `miniscriptc=info` to your `RUST_LOG` value and see if that works, or open a new clean +shell. diff --git a/content/repl/concept.md b/content/repl/concept.md new file mode 100644 index 0000000000..d57f541789 --- /dev/null +++ b/content/repl/concept.md @@ -0,0 +1,26 @@ +--- +title: "Concept" +date: 2020-04-28T17:38:20+02:00 +draft: false +weight: 2 +pre: "2. " +--- + +Now, in order to better grasp some of the design choiches made by Magical Bitcoin, it's important to understand the main concept driving the development of this project, and the goal that it's trying to +achieve. + +Magical Bitcoin is aiming first of all to be a **set of libraries and tools**, all meant to be very reusable and adaptable. Developers working on their own wallets or other projects that are trying to integrate +Bitcoin can pick the tools they need and piece them together to prototype and quickly ship a working product. This means that the REPL that we've just installed is designed to be a **very thin layer** over the +APIs exposed by the various components of the library, **not a full, end-user-ready Bitcoin wallet**. + +This concept leads to a few design choices that are arguably very bad for the "UX" of this wallet, but that allow developers to work more directly with the underlying library. For instance: + +* Magical Bitcoin has an internal database that's used to store data about received transactions, spendable UTXOs, etc. This database is stored by default in your home folder, in `~/.magical-bitcoin`. The database + **will never** contain any data that can't be recreated purely by looking at the blockchain. Keys, descriptors, Electrum endpoints **are not stored in there**. This explains why you'll have to specify them every + time in the command line. It can be seen more like a *cache* and can be safely deleted without risking funds. +* Magical Bitcoin doesn't automatically "monitor" the blockchain, instead there's a `sync` command that has to be called by the user. +* When you create a transaction and then sign it, it's not automatically broadcasted to the network. There's a `broadcast` command that does this. Moreover, the command doesn't accept a normal Bitcoin raw transaction, + but instead a *PSBT*. That's because internally transactions are always moved as PSBTs, and again, the `broadcast` command is just a very thin wrapper over the raw library call. + +There are probably more of these examples, but hopefully by this point you'll have more or less understood the gist of it. If you are not a developer, some parts of this are gonna feel weird, inefficient, hard +to understand, and that's absolutely normal. Just try to survive through the pain and you'll be rewarded! diff --git a/content/repl/installation.md b/content/repl/installation.md new file mode 100644 index 0000000000..8ab8e064a1 --- /dev/null +++ b/content/repl/installation.md @@ -0,0 +1,63 @@ +--- +title: "Installation" +date: 2020-04-28T17:11:29+02:00 +draft: false +weight: 1 +pre: "1. " +--- + +## Requirements + +The only requirement is a Linux/macOS system with a fairly recent Rust toolchain installed. Since Linux distros tend to lack behind with updates, the quickest way to install the Rust compiler and Cargo is +[rustup.rs](https://rustup.rs/). You can head there and follow their instructions, after which you can test if everything went fine by running `cargo version`, which should print something like: + +``` +cargo 1.42.0 (86334295e 2020-01-31) +``` + +If you really don't wanna pipe the output of `curl` into `sh`, you can also try using a [Docker image](https://hub.docker.com/_/rust) and working inside of it, but that's meant for more advanced +users and won't be covered in this guide. + +## Installing Magical Bitcoin + +Once Cargo is installed, you can proceed to install the interactive Magical Bitcoin shell directly from the GitHub repository, by running: + +```bash +cargo install --git https://github.com/magicalbitcoin/magical-bitcoin-wallet --example magic +``` + +This command will probably take a while to finish, since it will fetch and compile all the dependencies and the `magical-bitcoin-wallet` itself. Once it's done, you can check if everything went fine +by running `magic --help` which should print something like this: + +```text +Magical Bitcoin Wallet 0.1.0 +Riccardo Casatta :Alekos Filini +A modern, lightweight, descriptor-based wallet + +USAGE: + magic [FLAGS] [OPTIONS] --descriptor [SUBCOMMAND] + +FLAGS: + -h, --help Prints help information + -v Sets the level of verbosity + -V, --version Prints version information + +OPTIONS: + -c, --change_descriptor Sets the descriptor to use for internal addresses + -d, --descriptor Sets the descriptor to use for the external addresses + -n, --network Sets the network [default: testnet] [possible values: testnet, regtest] + -s, --server Sets the Electrum server to use [default: tn.not.fyi:55001] + -w, --wallet Selects the wallet to use [default: main] + +SUBCOMMANDS: + broadcast Extracts the finalized transaction from a PSBT and broadcasts it to the network + create_tx Creates a new unsigned tranasaction + get_balance Returns the current wallet balance + get_new_address Generates a new external address + help Prints this message or the help of the given subcommand(s) + list_unspent Lists the available spendable UTXOs + policies Returns the available spending policies for the descriptor + repl Opens an interactive shell + sign Signs and tries to finalize a PSBT + sync Syncs with the chosen Electrum server +``` diff --git a/content/repl/interface.md b/content/repl/interface.md new file mode 100644 index 0000000000..90acc4f4fa --- /dev/null +++ b/content/repl/interface.md @@ -0,0 +1,428 @@ +--- +title: "Interface" +date: 2020-04-28T18:20:28+02:00 +draft: false +weight: 3 +pre: "3. " +--- + +Remember the `magic --help` command you ran before? Let's analyze its output here to figure out the interface: + +## Flags + +```text +FLAGS: + -h, --help Prints help information + -v Sets the level of verbosity + -V, --version Prints version information +``` + +These are the optional flags that can be set with every command. The `-h` flag prints the help message, the `-V` flag only prints the version and the `-v` is actually ignored at the moment. + +### Verbosity + +If you want to increase the verbosity of the output, you should use the `RUST_LOG` environment variable. You can set it like so to see a lot more of what's going on behind the scenes, before running the `magic` +command. You only have to do this once when you open a new shell, after that you can run the `magic` command multiple times. + +```bash +export RUST_LOG="magical_bitcoin_wallet=debug" +``` + +## Options + +```text +OPTIONS: + -c, --change_descriptor Sets the descriptor to use for internal addresses + -d, --descriptor Sets the descriptor to use for the external addresses + -n, --network Sets the network [default: testnet] [possible values: testnet, regtest] + -s, --server Sets the Electrum server to use [default: tn.not.fyi:55001] + -w, --wallet Selects the wallet to use [default: main] +``` + +These are the global options that can be set. They are pretty much like the flags, but they also take a value. The only **required** one is the `--descriptor` or `-d` flag, since every wallet **must have an +associated descriptor**. + +The `--change-descriptor` flag can be used to set a different descriptor for the change addresses, sometimes called "internal" addresses in Bitcoin Core. Unfortunately there isn't +[really consensus](https://freenode.irclog.whitequark.org/bitcoin-wizards/2020-01-25#26222504;) on a nice way to encode informations about the change derivation inside the standard descriptor, so we are +stuck with having two separate ones. Keep in mind though, that even if you don't specify a change descriptor, you'll still be able to create transactions - the change address will simply be generated from the +standard descriptor. + +The `--network` flag can be used to change the network. Right now only `testnet` and `regtest` are supported since the code is very much not production-ready yet. + +The `--server` flag can be used to select the Electrum server to use. By default it's connecting to a random `testnet` server that has been found online, but sometimes it has proven to be kinda unreliable. +You can also try with `kirsche.emzy.de:50001` or find other servers [here](https://1209k.com/bitcoin-eye/ele.php?chain=tbtc) and see if you have more luck with those. Right now **only tcp, non-Tor** servers are supported. + +The `--wallet` flag can be used to select which wallet to use, if you have more than one of them. If you get a `ChecksumMismatch` error when you make some changes to your descriptor, it's because it doesn't +match anymore the one you've used to initialize the cache. One solution could be to switch to a new wallet name, or delete the cache directory at `~/.magical-bitcoin` and start from scratch. + +## Subcommands + +```text +SUBCOMMANDS: + broadcast Extracts the finalized transaction from a PSBT and broadcasts it to the network + create_tx Creates a new unsigned tranasaction + get_balance Returns the current wallet balance + get_new_address Generates a new external address + list_unspent Lists the available spendable UTXOs + policies Returns the available spending policies for the descriptor + repl Opens an interactive shell + sign Signs and tries to finalize a PSBT + sync Syncs with the chosen Electrum server +``` + +These are the main "functions" of the wallet. Most of them are pretty self explanatory, but we'll go over them quickly anyways. You can get more details about every single command by running `magic --help`. + +### broadcast + +```text +OPTIONS: + --psbt Sets the PSBT to broadcast +``` + +Broadcasts a transaction. The transaction has to be in PSBT format and has to be "finalizable" (i.e. it should contain enough partial signatures to construct a finalized valid signature). + +### create\_tx + +```text +FLAGS: + -a, --send_all Sends all the funds (or all the selected utxos). Requires only one addressees of value 0 + +OPTIONS: + -f, --fee_rate Fee rate to use in sat/vbyte + --policy Selects which policy will be used to satisfy the descriptor + --to ... Adds an addressee to the transaction + --unspendable ... Marks an utxo as unspendable + --utxos ... Selects which utxos *must* be spent +``` + +Creates a new unsigned PSBT. The flags allow to set a custom fee rate (the default is 1.0 sat/vbyte) with `--fee_rate` or `-f`, the list of UTXOs that should be considered unspendable with `--unspendable` (this +option can be specified multiple times) and a list of UTXOs that must be spent with `--utxos` (again, this option can also be specified multiple times). + +The `--to` option sets the receiver address of the transaction, and should contain the address and amount in Satoshi separated by a colon, like: `--to --to 2NErbQPsooXRatRJdrXDm9wKR2fRiZDT9wL:50000`. This option +can also be specified multiple times to send to multiple addresses at once. + +The `--send_all` flag can be used to send the value of all the spendable UTXOs to a single address, without creating a change output. If this flag is set, there must be only one `--to` address, and its value will +be ignored (it can be set to 0). + +The `--policy` option is an advanced flag that can be used to select the spending policy that the sender intends to satisfy in this transaction. It's normally not required if there's no ambiguity, but sometimes +with complex descriptor it has to be specified, or you'll get a `SpendingPolicyRequired` error. This flag should be set to an array of the list of child indexes that should be taken at each step when traversing the spending +policies tree from the root, at least until there are no more ambiguities. This is probably better explained with an example: + +Let's assume our descriptor is: `thresh(2,c:pk(A),sj:and_v(vc:pk(B),n:older(6)),sjn:and_v(vc:pk(C),after(630000)))`. There are three conditions and we need to satisfy two of them to be able to spend. The conditions are: + +1. Sign with the key corresponding to `pk(A)` +2. Sign with the key corresponding to `pk(B)` AND wait 6 blocks +2. Sign with the key corresponding to `pk(C)` AND wait that block 630,000 is reached + +So if we write down all the possible outcomes when we combine them, we get: + +1. Sign with `pk(A)` + `pk(B)` + wait 6 blocks +2. Sign with `pk(A)` + `pk(C)` + wait block 630,000 +3. Sign with `pk(B)` + `pk(C)` + wait 6 blocks + wait block 630,000 + +* If we choose option #1, the final transaction will need to have the `nSequence` of its inputs to a value greather than or equal to 6, but the `nLockTime` can stay at 0. +* If we choose option #2, the final transaction will need to have its `nLockTime` set to a value greater than or equal to 630,000, but the `nSequence` can be set to a final value. +* If we choose option #3, both the `nSequence` and `nLockTime` must be set. + +The wallet can't choose by itself which one of these combination to use, so the user has to provide this information with the `--policy` flag. Now, let's draw the condition tree to understand better how the chosen +policy is represented: + +{{}} +graph TD; + subgraph "" + R["Root"] --> A["pk(A)"] + R["Root"] --> B + B --> B_0["pk(B)"] + B --> B_1["older(6)"] + end + C --> C_0["pk(C)"] + C --> C_1["after(630,000)"] + R["Root"] --> C +{{< /mermaid >}} + +Let's imagine that we are walking down from the root, and we want to use option #1. So we will have to select `pk(A)` + the whole `B` node. Since the order is always mainteined, we can refer to them with their +indexes, in this case they are children #0 and #1 of the root. So our final policy will be: `--policy [[0, 1]]`, which means "at the first step from the root, pick items #0 and #1". + +### get\_balance + +This subcommand has no extra flags, and simply returns the available balance in Satoshis. This command **must be called after [`sync`](#sync)**, since it only looks into the local cache to determine the list of UTXOs. + +### get\_new\_address + +This subcommand has no extra flags and returns a new address. It internally increments the derivation index and saves it in the database. + +### list\_unspent + +This subcommand has no extra flags and returns the list of available UTXOs and their value in Satoshi. Just like [`get_balance`](#get_balance) it **must be called after [`sync`](#sync)**, since it only operates +on the internal cache. + +### policies + +This subcommand has no extra flags and returns the spending policies encoded by the descriptor in a more human-readable format. As an example, running the `policies` command on the descriptor shown earlier for the +in the explanation of the [`create_tx`](#create_tx) command, it will return this: + +{{% json %}} +{ + "type":"THRESH", + "items":[ + { + "type":"SIGNATURE", + "pubkey":"...", + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{ + + } + } + }, + { + "type":"THRESH", + "items":[ + { + "type":"SIGNATURE", + "pubkey":"...", + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{ + + } + } + }, + { + "type":"RELATIVETIMELOCK", + "value":6, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{ + "csv":6 + } + } + } + ], + "threshold":2, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"PARTIALCOMPLETE", + "n":2, + "m":2, + "items":[ + 0, + 1 + ], + "conditions":{ + "[0, 1]":[ + { + "csv":6 + } + ] + } + } + }, + { + "type":"THRESH", + "items":[ + { + "type":"SIGNATURE", + "pubkey":"...", + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{ + + } + } + }, + { + "type":"ABSOLUTETIMELOCK", + "value":630000, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{ + "timelock":630000 + } + } + } + ], + "threshold":2, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"PARTIALCOMPLETE", + "n":2, + "m":2, + "items":[ + 0, + 1 + ], + "conditions":{ + "[0, 1]":[ + { + "timelock":630000 + } + ] + } + } + } + ], + "threshold":2, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"PARTIALCOMPLETE", + "n":3, + "m":2, + "items":[ + 0, + 1, + 2 + ], + "conditions":{ + "[0, 1]":[ + { + "csv":6 + } + ], + "[0, 2]":[ + { + "timelock":630000 + } + ], + "[1, 2]":[ + { + "csv":6, + "timelock":630000 + } + ] + } + } +} +{{% /json %}} + +This is a tree-like recursive structure, so it tends to get huge as more and more pieces are added, but it's in fact fairly simple. Let's analyze a simple node of the tree: + +```json +{ + "type":"SIGNATURE", + "pubkey":"...", + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{} + } +} +``` + +* `type`, as the name implies, represents the type of node. It defines what should be provided to satisfy that particular node. Generally some other data are provided to give meaning to + the type itself (like the `pubkey` field here in the example). There are basically two families of types: some of them can only be used as leaves, while some other can only be used as intermediate nodes. + + Possible leaf nodes are: + - `SIGNATURE`, requires a signature made with the specified key. Has a `pubkey` if it's a single key, a `fingerprint` if the key is an xpub, or a `pubkey_hash` if the full public key is not present in the descriptor. + - `SIGNATUREKEY`, requires a signature plus the raw public key. Again, it can have a `pubkey`, `fingerprint` or `pubkey_hash`. + - `SHA256PREIMAGE`, requires the preimage of a given `hash`. + - `HASH256PREIMAGE`, requires the preimage of a given `hash`. + - `RIPEMD160PREIMAGE`, requires the preimage of a given `hash`. + - `HASH160PREIMAGE`, requires the preimage of a given `hash`. + - `ABSOLUTETIMELOCK`, doesn't technically require anything to be satisfied, just waiting for the timelock to expire. Has a `value` field with the raw value of the timelock (can be both in blocks or time-based). + - `RELATIVETIMELOCK`, again only requires waiting for the timelock to expire. Has a `value` like `ABSOLUTETIMELOCK`. + + Possible non-leaf nodes are: + - `THRESH`, defines a threshold of policies that has to be met to satisfy the node. Has an `items` field, which is a list of policies to satisfy and a `threshold` field that defines the threshold. + - `MULTISIG`, Similar to `THRESH`, has a `keys` field, which is a list of keys represented again as either `pubkey`, `fingerprint` or `pubkey_hash` and a `threshold` field. + +* `satisfaction` is currently not implemented and will be used to provide PSBT introspection, like understanding whether or not a node is already satisfied and to which extent in a PSBT. +* `contribution` represents if so and how much, the provided descriptor can contribute to the node. + + The possible types are: + - `NONE`, which means that the descriptor cannot contribute. + - `COMPLETE`, which means that the descriptor by itself is enough to completely satisfy the node. It also adds a `condition` field which represent any potential extra condition that has to be met to + consider the node complete. An example are the timelock nodes, that are always complete *but* they have an extra `csv` or `timelock` condition. + - `PARTIAL`, which means that the descriptor can partially satisfy the descriptor. This adds a `m`, `n`, `items` that respectively represent the threshold, the number of available items to satisfy and the items + that the provided descriptor can satisfy. Also adds a `conditions` field which is an integer to list of conditions map. The key is the child index and the map are all the possibile extra conditions that + have to be satisfied if that node is used in the threshold. For instance, if you have a threshold of a SIGNATURE and a RELATIVETIMELOCK, in this order, the `conditions` field will be `1 ⇒ csv(x)`, + because the item at index 1 needs the extra csv condition. + - `PARTIALCOMPLETE`, which is basically a `PARTIAL` with the size of `items` >= `m`. It's treated as a separate entity to make the code a bit more clean and easier to implement. Like `PARTIAL`, it also has + a `m`, `n`, `items` fields but the `conditions field` is a bit different: it's a list of integers to list of conditions map. The key represents the combination that can be used to satisfy the threshold, + and the value contains all the possible conditions that also have to be satisfied. For instance, if you have a 2-of-2 threshold of a TIMELOCK and a RELATIVETIMELOCK, the `conditions` field will be `[0, 1] ⇒ + csv(x) + timelock(y)`, because if the combination of items 0 and 1 is picked, both of their conditions will have to be meet too. + +While the structure contains all of the intermediate nodes too, the root node is the most important one because defines how the descriptor can contribute to spend outputs sent to its addresses. + +For instance, looking at the root node of the previous example (with the internal `items` omitted) from a descriptor that has all the three private keys for keys A, B and C, we can clearly see that it can satisfy +the descriptor (type = `PARTIALCOMPLETE`) and the three options are `[0, 1] ⇒ csv(6)` (Option #1), `[0, 2] ⇒ timelock(630,000)` (Option #2) or `[1, 2] ⇒ csv(6) + timelock(630,000)` (Option #3). + +```json +{ + "type":"THRESH", + "items":[], + "threshold":2, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"PARTIALCOMPLETE", + "n":3, + "m":2, + "items":[ + 0, + 1, + 2 + ], + "conditions":{ + "[0, 1]":[ + { + "csv":6 + } + ], + "[0, 2]":[ + { + "timelock":630000 + } + ], + "[1, 2]":[ + { + "csv":6, + "timelock":630000 + } + ] + } + } +} +``` + +### `repl` + +This subcommand has no extra flags and launches an interactive shell session. + +### `sign` + +```text +OPTIONS: + --psbt Sets the PSBT to sign +``` + +Adds to the PSBT all the signatures it can produce with the secrets embedded in the descriptor (xprv or WIF keys). Returns the signed PSBT and, if there are enough item to satisfy the script, also the extracted raw +Bitcoin transaction. + +### `sync` + +This subcommand has no extra flags. It connects to the chosen Electrum server and synchronizes the list of transactions received and available UTXOs. diff --git a/content/repl/regtest.md b/content/repl/regtest.md new file mode 100644 index 0000000000..1fd756ca89 --- /dev/null +++ b/content/repl/regtest.md @@ -0,0 +1,34 @@ +--- +title: "Regtest" +date: 2020-04-29T00:19:34+02:00 +draft: false +weight: 4 +pre: "4. " +--- + +Running the REPL in regtest requires having a local Electrum server set-up. There are two main implementations, [`electrs`](https://github.com/romanz/electrs) in Rust and [`ElectrumX`](https://github.com/kyuupichan/electrumx) in Python. Since the Rust toolchain is already required to +use Magical, this page will focus mostly on the former. + +Electrs can be installed by running: + +```bash +cargo install --git https://github.com/romanz/electrs --bin electrs +``` + +Just like before, this command will probably take a while to finish. + +Once it's done, assuming you have a regtest bitcoind running in background, you can launch a new terminal and run the following command to actually start electrs: + +```bash +electrs -vv --timestamp --db-dir /tmp/electrs-db --electrum-rpc-addr="127.0.0.1:50001" --network=regtest --cookie-file=$HOME/.bitcoin/regtest/.cookie +``` + +on macOS you should change the cookie-file to `$HOME/Library/Application Support/Bitcoin/regtest/.cookie`. + +This will start the Electrum server on port 50001. You can then add the `-n regtest -s localhost:50001` the `magic` commands to switch to the local regtest. + +## Troubleshooting + +#### Stuck with "*wait until bitcoind is synced (i.e. initialblockdownload = false)*" + +Just generate a few blocks with `bitcoin-cli generatetoaddress 1
` diff --git a/layouts/partials/custom-footer.html b/layouts/partials/custom-footer.html new file mode 100644 index 0000000000..15a980ea92 --- /dev/null +++ b/layouts/partials/custom-footer.html @@ -0,0 +1,2 @@ + + diff --git a/layouts/partials/favicon.html b/layouts/partials/favicon.html new file mode 100644 index 0000000000..1eccb39c15 --- /dev/null +++ b/layouts/partials/favicon.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/layouts/partials/logo.html b/layouts/partials/logo.html new file mode 100644 index 0000000000..814ef465fb --- /dev/null +++ b/layouts/partials/logo.html @@ -0,0 +1,3 @@ + diff --git a/layouts/partials/menu-footer.html b/layouts/partials/menu-footer.html new file mode 100644 index 0000000000..d5a655cea3 --- /dev/null +++ b/layouts/partials/menu-footer.html @@ -0,0 +1,10 @@ + + +
+ + Watch + Star + Fork +
+ +
Built with Hugo
diff --git a/layouts/shortcodes/json.html b/layouts/shortcodes/json.html new file mode 100644 index 0000000000..62d3bdb167 --- /dev/null +++ b/layouts/shortcodes/json.html @@ -0,0 +1,2 @@ +{{ $_hugo_config := `{ "version": 1 }` }} +
diff --git a/static/css/jsonview.css b/static/css/jsonview.css new file mode 100644 index 0000000000..72419b32d1 --- /dev/null +++ b/static/css/jsonview.css @@ -0,0 +1,88 @@ +.json { + padding: 16px; + background-color: #272822; + color: #FFF; + font-family: "Consolas", menlo, monospace; +} + +.line { + margin: 4px 0; + display: flex; + justify-content: flex-start; +} + +.caret-icon { + width: 28px; + text-align: center; + cursor: pointer; +} + +.json .caret-icon > i { + border: 0; +} + +.empty-icon { + width: 20px; +} + +.json-type { + margin-right: 4px; + margin-left: 4px; +} + +.json-key { + color: #EEE; + margin-right: 4px; + margin-left: 4px; +} + +.json-index { + margin-right: 4px; + margin-left: 4px; +} + +.json-separator { + +} + +.json-value { + margin-left: 8px; +} + +.json-number { + color: #f9ae58; +} + +.json-boolean { + color: #ec5f66; +} + +.json-string { + color: #86b25c; +} + +.json-size { + margin-right: 4px; + margin-left: 4px; +} + +.hide { + display: none; +} + +.json .fas { + display: inline-block; + width: 0; + height: 0; + border-style: solid; +} + +.json .fa-caret-down { + border-width: 6px 5px 0 5px; + border-color: #808080 transparent +} + +.json .fa-caret-right { + border-width: 5px 0 5px 6px; + border-color: transparent transparent transparent #808080; +} diff --git a/static/css/style.css b/static/css/style.css new file mode 100644 index 0000000000..9f9f18e732 --- /dev/null +++ b/static/css/style.css @@ -0,0 +1,20 @@ +#descriptor-examples-table { +} + +#descriptor-examples-table code, #descriptor-examples-table td:not(:first-child) { + overflow-x: auto; + white-space: pre-wrap; + white-space: -moz-pre-wrap; + white-space: -pre-wrap; + white-space: -o-pre-wrap; + word-wrap: break-word; + overflow-wrap: anywhere; +} + +#descriptor-examples-table > table > thead > tr > th:nth-child(2) { + width: 45%; +} + +#descriptor-examples-table > table > thead > tr > th:nth-child(2) { + width: 45%; +} diff --git a/static/icons/android-chrome-192x192.png b/static/icons/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..a2e4dad8c2766a16e6525d55181361110d7d0fa2 GIT binary patch literal 10952 zcmeAS@N?(olHy`uVBq!ia0y~yU^oE6983%h40rea4q#wlU`coMb!1@J*w6hZk(Ggg zK_S^A$d`ekN{xY`p@o6r7Xt%B!wUw6QUeBtR|yOZRx=nF#0%!^3bbKhU|>t~c6VX; z4}uH!E}zW6z`$PO>Fdh=ghhr+LeRUYVI2d5W~Qf$V@SoVx3!fuu~%!KTb5V3at>&ss-r{RKd71C>x6d#8SxugKrev4OWHBKHMlO|x zgEx+GZ_?F?p7tbm)7Hq-moHzweSi0F%g^mO#qXzzznuH~-sCfXAJy;Jw(gwm_v-rJ z@5>dANknXzpu56J|G=R)ZLSL3E*m&f8ac!obp#G7O<+}uVAuV3!?vfb2#uGw-GDI{c1Jm%9`n}VvQaPlP=78Qg1s?YRZ(A|3#P|a;bk$nOHqB zxh&hH+rdRZu+Df^o$;hc7k#%0#w8!`{dUtk`1?;8>%Z%Yrs;iIoWj}daMStFkEsQ( z%r9;+%H&scW#pKsvznti<#sBj#Rk^Wq9VC%`p1!tUk%i0Az4n`bu zI4Z$(z~Mxo!F5JGo&&Qde(`>|Bu9b8RWZ^p?wwS=rPS-3=k9G&N@gWRtlP1p=JvN$ zb9Y_#O2Tw%SrKHc_movI;oPx5GLT`XPre)@l*JO3Lcys-!77^9l5{q;QQLW z6>r(P5)F)I-M0RFPJeo3q{Zwf7uKjuXedZ`vza1r?qg6$VE(gj1p?=`Z|46clYO^r z{YsNAjaT=1j_ZAx^h}CHf_MM_b4UMwT^w>>m1BkUF+Rfp%lg8%!t>|;zVm+9t7lRs zv*tG4U-2RLqXpOAgO?BJC=0MXP}1Kk>A5}CMbJ0%sR;{jS>EpR8_%goB{IZusmDwE zOV<58@Ou56{}M;Zujj1Hd((b^#4|DuP@NA2vp|9!6)S56L2;b&lA;yV55!2Z2P zU*6>}IQGJkL8c@9k=9A6&s{ei7w{a?Z=1Y(ac1*rW`!0LUWR~4onIW{A0676^4->C)>y1sT4t(GD!?-Rb z!uwZTpylj|%PLnlC5ok_gz((!TJr6faoc*KOIs%SxcSM++itP1TNcdGyNZclv#YRr z&eqb@+3#0Yd=N}8ZDSnI(3wFD+#4g$98HnLNu&pFh`g zZI=oBab@dj0S1K@=au`slim4v_xxKuOWi*D?~BQOU0!R?&k4EMo!nV8EpNl-%TXuy zvD{Zabt~0lt4HgUfIrS0!fkYs$aHl%l}{Z;eg!K^9~Nq4)LGoD6)vKm^fHmto`?=|KG1C+xLlO zW}B|qykN~f89%k<$yr~zPyMTKt7dhw_;W7$;k0LKZZb18G<40km$tsUF81M!HS?aP zw~Nhw$znC-$!^xjYSz_R@Ad2I{=NU_#nG;?AU|*wDd)jyA%R>^l{lyS(_neBJkDy~o7m6_aP{2A@=MX8)dj__9R9wk<2pu(4OV z32Q7`!TxxUUwL3i!Tovb>VM4Vnm=>VX=cW`axX0ZhSy73-(_6s@50LTU~j~;O$JM^ z-&a0y)-$e}RoUdjE$x-wvBBT>CyLaO`zO_9v;c4w+vv;y|X=VIZIiLOF?)_uu=bk+Dtf4{9`d8rn z)A|yV9v+|M^!#njGrK^$X+}HV75!hW|M{Sz@ezIoh805gWlt73c9$-3Ej^~aai;fz zXDas>U(^=}swqf$u{}Rw&eDYA9&i6&)lZuHR(RoJ&J=-rvfiJ!pXrkE`yl9={P#l1 zpEoZbu(Dm1+Ox9`W!%Tc;w)2?y{ z8(-w=nCYRwbAbKhnT8)HkF#rb@%P14KE5s?SUXW5V6pr=S?i*R-}6*@?)Rq}nF~4{ z4|WQ;v{vP2X=2HJxy{n03$)S>xzFDEQH#aFJ!;NF&)%6H3-sddnV&o;SM~htk)OpX zg5nGZTF&43{)xLtX`QIk^U9YlUNioz57x4pC9>trAqoEX|8(W03`6T>^?j13 zylsfWzGQf($mO;ADv6SmBQxK0 zoz-DtP5pW{!|PJIwsNjITm5G%lgmj<7w4{B==@uqTXC(b$+{I*{PIq!Q+et>$SssD z%kGi4S3BDK>g%?>X{<+hlqPf?ynV4`|FJSQfm5AFp3eW@Y$0cKJtI^#@xj(`9;X*E zZkMKI#aubwr0A-uH>Z1U-ud1ij0sNNrR7WYN;7BLDy^J;bmr=#X#$PsK3zK4q8H1c zC{y=+?S+TTN49Mi6u59PSp7Jk{0x;ABVj{D9tU@~`MrlMzFc(F6g>TO0gHxe^5f(E znU8M^9h+<3ZzLjP-0C3Na=&ZImY0Pdfh*^E+y4I*tnyrC(R!~x2VU==^w@B%fYoX5 zx0!+r69O)}#>MXx>~HNiWi~Dn-_F9fT_*67=i621J_IE#yQXnYgh|$$OZL|krb$cZ ziPueg^YYxpQw&Mk1^y{Yk0)Led;4BcU|;T`bpbO3S*&I}C`}a=o?7?+)A^!2UOom!)4E5= z&IwU273DgYCth5x?_zkXPN=!&g&@y`8ynM1CttMt{j$fz(#KRdpn{3l^HiMkMgA7$ z_j_&seGI&u``oi()db0kx2cvBFK{h9*K=j!zbD=86NHW*Uiq&3=S*WZMp64}E87d~ zrfWYjFIw~2Kb?omM}g-+J7-AhP?0#01VZbgVJNOiyZ4b7!uMT62J9my%Zdmvz?1Dn6{eE+l^L`K_3}ZJdf#lGA3>DcO@8_m}J zyTqwj^5w%5yG^TKhg|*9S}gIzcqM1@+_y6iGQOSk%jM~*GnbQERW67IX8OIdGwQi8 z)jZBO{^jZEKV~w7w4OPz+FZ~{K_iDBOYwy%*Q7g@3U{Gjr(wHK-Yf`))bI+6y6Ayb_F6|xs@ST#ek;;X828PCb0O|NU-1t*v@IDLxvtf=yG&-ZU% z&Rj}rt&Co)c`@MAoOkbKHRt@;xr@ia)lcTSsJ7Dz72%chPPaw{F8Qlszj&`3Ew()wc|}{85f?Rb9B++_xoBWXj&(EEw_@*&F6l1pIMX3Gw9Q$qfHSP zu8TQyDj%LGEHACp_10KTf7<;A5)5ZK?Uw3W%h=x&dTW!~^rP`WSQOh?i7UM#g%7Sy zKUxssx%^VC?aw=lq;=R%E4J+G1ZapvUxOH4J zaQf~AFMsU3{BWA`lY9>5kh1rGL#^ivC{H}n`njRPL^x<^-aI zen{8dhS&GHJ{QM)kIvI`w=wDEF#Y_!?U9z1k!HE!pMTatId@n-KGvS~`HHbg`s!OB zS8UH*sOh9p_|E4%x4pB`&vw64X+2jj9Q^BLwRUUEE#pOHX&wtF*fW);9f_;`U{JiY z{>$OLPwtzuttdIY_utdi6O^pAR%h9Nu6(PqX-#8_<=yI;0W%!C7QJ2KF7DuP)Ni}` z*S|^5ldAgk_lTVqZdB=+E!?#3EZ3on%)gDoPc*mBD6Pz%|3fBsJ2L|V+f-}0uX-^l zK|lFcW~BW6*Y%eF{+de}uTBdrew-{Xdu3DP!5ylqA~j5*^Ej?3pGfDqSDjMxWAFBp z&s7r|x~{F!-c|kfNP&ZW;^xZ-8+hqJ5(2fkg}G)vv?w5YhSwvmk0miVq$ zY2|aydN{ZGWk2b3I3CorFtcFKR@J(9JUf5-6n~o)J3sZ#e3{55!*w+U%kw`@`g2X- zp1_U3Sm}s;r}n2phVsK+)$OT_Y4DS zyQfXdxwFQ)nmf6=()Dfn{G}O}ibGF4oELwdm1$}8yVeO6n*`^}-QCZwZ8h=oBq6Tb z?pcA>c-g+cH+=d`^!xjQYiACcPkJb^@Y8R3E}i&D4aFA5ZBwUMX{}~-+Hy8* zTdws^ucIE4H+M&Ss_`-|WSVtpr>X$kgN&dHSLFf<-kf-NCG}Hb@{O>Npq-B|&aOHk zal6a=Sc8 zYqwFzJvH>?FW)2QY^DT%oXB71Z?<%KX+clt3Ef7&)FpwnPiy|%nfYR6SkcGBH|Aco zmftUBv!|_k&$r!M)T5Hl{A4bjUq5e~<)`>bj)80PA1W32hB&lo?*H$2?4jE8fEOPc z&phxkTw3g*!1yqk?Q>*k^Y43;A1%=}l2EumDb;oL_3X9s{Jyqt%55K&7fStRP!8Ev z8vXGW@6Vjlxj)YK9Df~mp zGjQlzmE|7#RbAxx3~rIBcYilMdU8dAc`usGfH^aeK>zuRp&sYDLtY zuif@2sHooV+D*CnDPH0#T649TT-97}hS~|=`7XEfCl7<(?&o#Q-|fyH)7h(55wTIpJSiAN1i;dMUSC?-K{*bu;^g3~;qp!`T zRi^t?Pj7j&e9F@6J4)Z(FjC)sYH6jX#AUwpyPM-5)wos)I7ujk z=g!T3_vfUbUr)ftTfFmFds`;5a;!Mx5Wi#TO@o$IrgPtmy_qAB5fXOJCu=W!3s84SK_m~VTZ zKK;Ia!kx(ut7PtMcR%~WZ>ibU!7Jb+F{B7@3#kwsTv$W$j%Ndz#dNgf#^sn8=aOvW=>XWDM z+VcE4uji|uf7n{is84A6cydby$NwI=TkBIMJ((YSb1(l5Z7supE?p+KcDnuME%MQ6 zvHo-Jb=$=wMm62jLv1%{FW225p-^4fTK}@BAz$Z}L69x4@6qgQlV@K_QjxK$IS{by z#;p4d6MnLAoywYCcWk$W9QSq^!^MTmS3GKL-;$=xlCb#ry9IeQ&(*BAA6zW%#AE#Y z0<-CjwjVo>5-ArLxDY0d_YV$uS z>mm=)pKIP%mM#>D-uXB2*vm^Z&+A1?Ro zkHYektKXlyWvTkwJTtzhx#{)YZ_)R~nKs;gz9ym6>4fR>b?;v4&$#rL$>oNx9r@wx?J%8_tr!#)n`n_F$Tq68!&7u7%J8!1S&DgkGOTMNh zsnqT7-Mrazn@-P(5&iAChH>?(?HgBST+RA)Cu`UC;{iGHp`Vr?^-;SJ8F#5vOHszM z&PR~Ly(IbAJFWZQ8Wex+xt3cV6uj$gZJhgDUuV;vx2aD{&(~b+>DcgW9m7vCecfHv zz0;o7wawaa$xGr^!n%um=|7pRHD+!3>oN7m#(usG?G^)u+|0mJ-D1X*9Wq;Xefj0> zcT72VZOitf3_D*-|Md>fh(Gh>dm;CfO<(x-Uk=C)`*^_Fb@iDwrp+S3TR#`-1uVI` zxmz~o?N){7RsHimN=#pK_rV%P-C!1mKKXn>r^UB~7wuxrw9wx-VJ_qUu(LjP7U+X+pyW&^r$Bv z*Sf;jOVm1$o&r+?CqeYh@P;d;_UVR`O@f@?KvJtwq3nUigJnPW;w;Q1xaj~_ihH{t%y zinng(-kVE^Eq$|PZh^S#+Yi?2qI>Rz@5{A*_nk5von?C#$8t~tVzCi8Amsr1(0 zPR<)nrJl~)AHFNc`wQ#(p3|}aui6(}J$HJRv&0J5)z?GqKUrL>wvFD?chd3P$y4G% zAvdR0pX|OnL8(vHGUY!Jbtc3NY1E>vFzN+&n9R=DPn+ zGw>Z!?~a-JYdd#l)w|;Tn_u+r&)3$PS(L)T%#mGYYx@6m{ME203=Ge1-uS)8e6AN8 z
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 jWR9?(Ztz&(rN{6}T(IPmlj&3j1_lOCS3j3^P6 + + + + + #da532c + + + diff --git a/static/icons/favicon-16x16.png b/static/icons/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..678299afbe3ffd9a247a86ece8da1e91a83dd384 GIT binary patch literal 961 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4rT@h1`S>QUNSs54@ z6p}rHd>I(3)EF2VS{N99F)%PRykKA`HDF+PmB7GYHG_dcykO3*KpO@I#_Rx}5ZC{d zfq(!1|NQs=!pE-31Vm(= zJ=Z*Yo{3GBUDgghXEZ`a{Jxn1PAKvbmdqfl)xum`g^1LsDkinM?i0&aeuL@vCbu zy7MS=@hV16E|ZD|?W9b<)}9al|9|`cKdf)6Now}f-+xcN{iqw4Dr{;!`P|jwbz2$O zIAt7MPrUnh_xmrMh&ToY=9IZh{{H`e`t8TJNE5*@=`!Y zpH)O`+Ubig{`_;QY>;#FIsW#;nYSMeQnHQG^Ul5hwDJBEjqtb&A3p#2|NrXeZ`VG5 z`~Cm_rB7eE>M!dvFffRe1o;KCCf@jaE1B)>yVUEq|J+G=pYiWr`nkj-#S9D#j7i?^ zE({&4vK|Z!4D2PIzOL*~SY)^)1Z+w-STHa!T<~;p43W5;oRE-`B-Y53CKhJK=2j-C za^T>}1FVZ&U0seGQEgblVb07yVak+A(y*~2tXERA6pkt|>gJZp z#@d$FGCOxPESk8nbLGsPt-F?rx;Wgqbu29U?zwvhFLEk9c=PDhvv&*MyIe57EIC;7I88}_sT#uhPa_p$Oikj;36AY|DmoFI~Sa;@3(D`$Mi4RVmJ+0rc zWA_G){WE4Zu3WNZ4U1AhTwv6p(+7?>zOk%hWHa-NbCd`V@R-5Nka$pI#+gvvi3|)3 zswJ)wB`Jv|saDBFsfi`23`Pb<2D%0&x<(cuh6YwfCRT=K+6G2e1_s>Cy&nOiTJTUc4xd$I_#u!2j2$>9`c<;@`qr*B+2apcSqnIr6{8$1?x=`p+# X7cBYYWIC0Bfq}u()z4*}Q$iB}B#NzR literal 0 HcmV?d00001 diff --git a/static/icons/favicon-32x32.png b/static/icons/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..c0a3b561c99b1964038101468e55b3deba26dbd4 GIT binary patch literal 1848 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 QM$B@7kVpd~0|Q7e0Q9jBqW}N^ literal 0 HcmV?d00001 diff --git a/static/icons/mstile-150x150.png b/static/icons/mstile-150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..17106a6aa6e15f9f52679ea8524af4cad2094822 GIT binary patch literal 9624 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 X1xr3TnNDS3U|{fc^>bP0l+XkKap + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + diff --git a/static/icons/site.webmanifest b/static/icons/site.webmanifest new file mode 100644 index 0000000000..ccaa826fe6 --- /dev/null +++ b/static/icons/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "MagicalBitcoin Docs", + "short_name": "MagicalBitcoin Docs", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/static/images/logo.svg b/static/images/logo.svg new file mode 100644 index 0000000000..b284a89c4d --- /dev/null +++ b/static/images/logo.svg @@ -0,0 +1,283 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/images/wizard.svg b/static/images/wizard.svg new file mode 100644 index 0000000000..5fc405bf16 --- /dev/null +++ b/static/images/wizard.svg @@ -0,0 +1,327 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/js/github-buttons.js b/static/js/github-buttons.js new file mode 100644 index 0000000000..7b87efaec1 --- /dev/null +++ b/static/js/github-buttons.js @@ -0,0 +1,6 @@ +/*! + * github-buttons v2.7.0 + * (c) 2020 なつき + * @license BSD-2-Clause + */ +!function(){"use strict";var e=window.document,t=e.location,o=window.Math,r=window.HTMLElement,n=window.XMLHttpRequest,a="https://buttons.github.io/buttons.html",i=n&&n.prototype&&"withCredentials"in n.prototype,l=i&&r&&r.prototype.attachShadow&&!r.prototype.attachShadow.prototype,c=function(e,t,o,r){null==t&&(t="&"),null==o&&(o="="),null==r&&(r=window.decodeURIComponent);for(var n={},a=e.split(t),i=0,l=a.length;i'},heart:{width:12,height:16,path:''},eye:{width:16,height:16,path:''},star:{width:14,height:16,path:''},"repo-forked":{width:10,height:16,path:''},"repo-template":{width:14,height:16,path:''},"issue-opened":{width:14,height:16,path:''},"cloud-download":{width:16,height:16,path:''}},x={},y=function(e,t){var o=x[e]||(x[e]=[]);if(!(o.push(t)>1)){var r=p((function(){for(delete x[e];t=o.shift();)t.apply(null,arguments)}));if(i){var a=new n;d(a,"abort",r),d(a,"error",r),d(a,"load",(function(){var e;try{e=JSON.parse(a.responseText)}catch(e){return void r(e)}r(200!==a.status,e)})),a.open("GET",e),a.send()}else{var l=this||window;l._=function(e){l._=null,r(200!==e.meta.status,e.data)};var c=u(l.document)("script",{async:!0,src:e+(/\?/.test(e)?"&":"?")+"callback=_"}),s=function(){l._&&l._({meta:{}})};d(c,"load",s),d(c,"error",s),c.readyState&&h(c,/de|m/,s),l.document.getElementsByTagName("head")[0].appendChild(c)}}},k=function(e,t,o){var r=u(e.ownerDocument),n=e.appendChild(r("style",{type:"text/css"})),a="body{margin:0}a{text-decoration:none;outline:0}.widget{display:inline-block;overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif;font-size:0;white-space:nowrap}.btn,.social-count{position:relative;display:inline-block;height:14px;padding:2px 5px;font-size:11px;font-weight:600;line-height:14px;vertical-align:bottom;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-repeat:repeat-x;background-position:-1px -1px;background-size:110% 110%;border:1px solid}.btn{border-radius:.25em}.btn:not(:last-child){border-radius:.25em 0 0 .25em}.social-count{border-left:0;border-radius:0 .25em .25em 0}.widget-lg .btn,.widget-lg .social-count{height:20px;padding:3px 10px;font-size:12px;line-height:20px}.octicon{display:inline-block;vertical-align:text-top;fill:currentColor}"+function(e){if(null==e)return v.light;var t=c(e,";",":",(function(e){return e.replace(/^[ \t\n\f\r]+|[ \t\n\f\r]+$/g,"")}));return v[b(v,t["no-preference"])?t["no-preference"]:"light"]+m("light",t.light)+m("dark",t.dark)}(t["data-color-scheme"]);n.styleSheet?n.styleSheet.cssText=a:n.appendChild(e.ownerDocument.createTextNode(a));var i,l,d=r("a",{className:"btn",href:t.href,target:"_blank",rel:"noopener",innerHTML:(i=t["data-icon"],l=/^large$/i.test(t["data-size"])?16:14,i=(""+i).toLowerCase().replace(/^octicon-/,""),b(w,i)||(i="mark-github"),'"),"aria-label":t["aria-label"]||void 0},[" ",r("span",{},[t["data-text"]||""])]),s=e.appendChild(r("div",{className:"widget"+(/^large$/i.test(t["data-size"])?" widget-lg":"")},[d])),f=d.hostname.split(".").reverse();if(""===f[0]&&f.shift(),"com"!==f[0]||"github"!==f[1])return d.href="#",d.target="_self",void o(s);var h=f.length,g=(" /"+d.pathname).split(/\/+/);if(((2===h||3===h&&"gist"===f[2])&&"archive"===g[3]||2===h&&"releases"===g[3]&&"download"===g[4]||3===h&&"codeload"===f[2])&&(d.target="_top"),/^true$/i.test(t["data-show-count"])&&2===h){var p,x;if(!g[2]&&g[1])p=x="followers";else if(!g[3]&&g[2])x="stargazers_count",p="stargazers";else if(g[4]||"subscription"!==g[3])if(g[4]||"fork"!==g[3]){if("issues"!==g[3])return void o(s);x="open_issues_count",p="issues"}else x="forks_count",p="network/members";else x="subscribers_count",p="watchers";var k=g[2]?"/repos/"+g[1]+"/"+g[2]:"/users/"+g[1];y.call(this,"https://api.github.com"+k,(function(e,t){if(!e){var n=t[x];s.appendChild(r("a",{className:"social-count",href:t.html_url+"/"+p,target:"_blank",rel:"noopener","aria-label":n+" "+x.replace(/_count$/,"").replace("_"," ").slice(0,n<2?-1:void 0)+" on GitHub"},[(""+n).replace(/\B(?=(\d{3})+(?!\d))/g,",")]))}o(s)}))}else o(s)},C=window.devicePixelRatio||1,z=function(e){return(C>1?o.ceil(o.round(e*C)/C*2)/2:o.ceil(e))||0},F=function(e,t){e.style.width=t[0]+"px",e.style.height=t[1]+"px"},M=function(t,r){if(null!=t&&null!=r)if(t.getAttribute&&(t=function(e){for(var t={href:e.href,title:e.title,"aria-label":e.getAttribute("aria-label")},o=["icon","color-scheme","text","size","show-count"],r=0,n=o.length;r { + if (el !== null) { + htmlElement.appendChild(el); + } + }); + } + + return htmlElement; +} + + +/** + * @param {Object} node + * @return {HTMLElement} + */ +function createExpandedElement(node) { + const iElem = createElement('i'); + + if (node.expanded) { + iElem.className = 'fas fa-caret-down'; + } else { + iElem.className = 'fas fa-caret-right'; + } + + const caretElem = createElement('div', { + className: 'caret-icon', + children: [iElem], + }); + + const handleClick = node.toggle.bind(node); + caretElem.addEventListener('click', handleClick); + + const indexElem = createElement('div', { + className: 'json-index', + content: node.key, + }); + + const typeElem = createElement('div', { + className: 'json-type', + content: node.type, + }); + + const keyElem = createElement('div', { + className: 'json-key', + content: node.key, + }); + + const sizeElem = createElement('div', { + className: 'json-size' + }); + + if (node.type === 'array') { + sizeElem.innerText = '[' + node.children.length + ']'; + } else if (node.type === 'object') { + sizeElem.innerText = '{' + node.children.length + '}'; + } + + let lineChildren; + if (node.key === null) { + lineChildren = [caretElem, typeElem, sizeElem] + } else if (node.parent.type === 'array') { + lineChildren = [caretElem, indexElem, sizeElem] + } else { + lineChildren = [caretElem, keyElem, sizeElem] + } + + const lineElem = createElement('div', { + className: 'line', + children: lineChildren + }); + + if (node.depth > 0) { + lineElem.style = 'margin-left: ' + node.depth * 24 + 'px;'; + } + + return lineElem; +} + + +/** + * @param {Object} node + * @return {HTMLElement} + */ +function createNotExpandedElement(node) { + const caretElem = createElement('div', { + className: 'empty-icon', + }); + + const keyElem = createElement('div', { + className: 'json-key', + content: node.key + }); + + const separatorElement = createElement('div', { + className: 'json-separator', + content: ':' + }); + + const valueType = ' json-' + typeof node.value; + const valueContent = String(node.value); + const valueElement = createElement('div', { + className: 'json-value' + valueType, + content: valueContent + }); + + const lineElem = createElement('div', { + className: 'line', + children: [caretElem, keyElem, separatorElement, valueElement] + }); + + if (node.depth > 0) { + lineElem.style = 'margin-left: ' + node.depth * 24 + 'px;'; + } + + return lineElem; +} + + +/** + * create tree node + * @return {Object} + */ +function createNode() { + return { + key: null, + parent: null, + value: null, + expanded: false, + type: null, + children: null, + elem: null, + depth: 0, + + setCaretIconRight() { + const icon = this.elem.querySelector('.fas'); + icon.classList.replace('fa-caret-down', 'fa-caret-right'); + }, + + setCaretIconDown() { + const icon = this.elem.querySelector('.fas'); + icon.classList.replace('fa-caret-right', 'fa-caret-down'); + }, + + hideChildren() { + if (this.children !== null) { + this.children.forEach((item) => { + item.elem.classList.add('hide'); + if (item.expanded) { + item.hideChildren(); + } + }); + } + }, + + showChildren() { + if (this.children !== null) { + this.children.forEach((item) => { + item.elem.classList.remove('hide'); + if (item.expanded) { + item.showChildren(); + } + }); + } + }, + + toggle: function() { + if (this.expanded) { + this.expanded = false; + this.hideChildren(); + this.setCaretIconRight(); + } else { + this.expanded = true; + this.showChildren(); + this.setCaretIconDown(); + } + } + } +} + + +/** + * Return object length + * @param {Object} obj + * @return {number} + */ +function getLength(obj) { + let length = 0; + for (let key in obj) { + length += 1; + }; + return length; +} + + +/** + * Return variable type + * @param {*} val + */ +function getType(val) { + let type = typeof val; + if (Array.isArray(val)) { + type = 'array'; + } else if (val === null) { + type = 'null'; + } + return type; +} + + +/** + * Recursively traverse json object + * @param {Object} obj parsed json object + * @param {Object} parent of object tree + */ +function traverseObject(obj, parent) { + for (let key in obj) { + const child = createNode(); + child.parent = parent; + child.key = key; + child.type = getType(obj[key]); + child.depth = parent.depth + 1; + child.expanded = false; + + if (typeof obj[key] === 'object') { + child.children = []; + parent.children.push(child); + traverseObject(obj[key], child); + child.elem = createExpandedElement(child); + } else { + child.value = obj[key]; + child.elem = createNotExpandedElement(child); + parent.children.push(child); + } + } +} + + +/** + * Create root of a tree + * @param {Object} obj Json object + * @return {Object} + */ +function createTree(obj) { + const tree = createNode(); + tree.type = getType(obj); + tree.children = []; + tree.expanded = true; + + traverseObject(obj, tree); + tree.elem = createExpandedElement(tree); + + return tree; +} + + +/** + * Recursively traverse Tree object + * @param {Object} node + * @param {Callback} callback + */ +function traverseTree(node, callback) { + callback(node); + if (node.children !== null) { + node.children.forEach((item) => { + traverseTree(item, callback); + }); + } +} + + +/** + * Render Tree object + * @param {Object} tree + * @param {String} targetElem + */ +function render(tree, rootElem) { + /*if (targetElem) { + rootElem = document.querySelector(targetElem); + } else { + rootElem = document.body; + }*/ + + traverseTree(tree, (node) => { + if (!node.expanded) { + node.hideChildren(); + } + rootElem.appendChild(node.elem); + }); +} + + +/* Export jsonView object */ +window.jsonView = { + /** + * Render JSON into DOM container + * @param {String} jsonData + * @param {String} targetElem + */ + format: function(jsonData, targetElem) { + let parsedData = jsonData; + if (typeof jsonData === 'string' || jsonData instanceof String) parsedData = JSON.parse(jsonData); + const tree = createTree(parsedData); + render(tree, targetElem); + } +} + +})(); diff --git a/static/js/main.js b/static/js/main.js new file mode 100644 index 0000000000..f8c170f557 --- /dev/null +++ b/static/js/main.js @@ -0,0 +1,6 @@ +jQuery(document).ready(function() { + $('div.json[data-json]').each(function(index, element) { + var json = $(element).attr('data-json').replace(/[\u201C\u201D]/g, '"'); + jsonView.format(json, element); + }); +}); diff --git a/themes/learn b/themes/learn new file mode 160000 index 0000000000..d4abb3c9a1 --- /dev/null +++ b/themes/learn @@ -0,0 +1 @@ +Subproject commit d4abb3c9a103bdd14e82184f76463a02755ee070 -- 2.49.0