From: Steve Myers Date: Mon, 14 Sep 2020 21:01:54 +0000 (-0700) Subject: update docs-rs for new `bdk` crate name X-Git-Url: http://internal-gitweb-vhost/script/%22https:/struct.SegwitCodeLengthError.html?a=commitdiff_plain;h=cc7de8f38437069aeb50bdda1fb53107cedf835f;p=bitcoindevkit.org update docs-rs for new `bdk` crate name --- diff --git a/README.md b/README.md index e1f8f8327b..b9f1348768 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,13 @@ If you are editing this website, you can run ``` to start a local webserver at [`http://localhost:1313`](http://localhost:1313). + +# generating docs-rs + +To create or re-create the contents of `static/docs-rs/bdk/`, copy the contents of +the `bdk/target/doc` directory after running the below commands from the `bdk` project directory: + + ``` + cargo clean + cargo doc --no-deps + ``` diff --git a/config.toml b/config.toml index 69b5f5c9a3..b1db154070 100644 --- a/config.toml +++ b/config.toml @@ -34,7 +34,7 @@ unsafe= true [[Languages.en.menu.shortcuts]] name = " Rust Docs" -url = "/docs-rs/magical/" +url = "/docs-rs/bdk/" weight = 5 [[Languages.en.menu.shortcuts]] diff --git a/content/repl/concept.md b/content/repl/concept.md index 8f9147d120..9c9989f961 100644 --- a/content/repl/concept.md +++ b/content/repl/concept.md @@ -15,7 +15,7 @@ APIs exposed by the various components of the library, **not a full, end-user-re 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: -* BDK 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 `~/.bdk`. The database +* BDK 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 `~/.bdk-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. * BDK doesn't automatically "monitor" the blockchain, instead there's a `sync` command that has to be called by the user. diff --git a/content/repl/installation.md b/content/repl/installation.md index 6b005d6dbb..edf610e9f5 100644 --- a/content/repl/installation.md +++ b/content/repl/installation.md @@ -32,7 +32,7 @@ This command will probably take a while to finish, since it will fetch and compi by running `repl --help` which should print something like this: ```text -BDK repl 0.1.0 +Magical Bitcoin Wallet 0.1.0 Riccardo Casatta :Alekos Filini A modern, lightweight, descriptor-based wallet @@ -63,3 +63,9 @@ SUBCOMMANDS: sign Signs and tries to finalize a PSBT sync Syncs with the chosen Electrum server ``` + +An example command to sync a testnet wallet looks like this: + +``` +repl --descriptor "wpkh(tprv8ZgxMBicQKsPexGYyaFwnAsCXCjmz2FaTm6LtesyyihjbQE3gRMfXqQBXKM43DvC1UgRVv1qom1qFxNMSqVAs88qx9PhgFnfGVUdiiDf6j4/0/*)" --network testnet --server tcp://testnet.aranguren.org:51001 sync +``` \ No newline at end of file diff --git a/content/repl/interface.md b/content/repl/interface.md index 41915154bc..ed616827da 100644 --- a/content/repl/interface.md +++ b/content/repl/interface.md @@ -25,7 +25,7 @@ If you want to increase the verbosity of the output, you should use the `RUST_LO command. You only have to do this once when you open a new shell, after that you can run the `repl` command multiple times. ```bash -export RUST_LOG="bdk_repl=debug" +export RUST_LOG="bdk=debug" ``` ## Options diff --git a/content/repl/regtest.md b/content/repl/regtest.md index 103fa10e71..b626c9d043 100644 --- a/content/repl/regtest.md +++ b/content/repl/regtest.md @@ -25,7 +25,7 @@ electrs -vv --timestamp --db-dir /tmp/electrs-db --electrum-rpc-addr="127.0.0.1: 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 `bdk` commands to switch to the local regtest. +This will start the Electrum server on port 50001. You can then add the `-n regtest -s localhost:50001` the `repl` commands to switch to the local regtest. ## Troubleshooting diff --git a/static/CNAME b/static/CNAME index 9982129f13..cddb241d5e 100644 --- a/static/CNAME +++ b/static/CNAME @@ -1 +1 @@ -test.bitcoindevkit.org \ No newline at end of file +bitcoindevkit.org \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/COPYRIGHT.txt b/static/docs-rs/bdk/0.1.0-beta.1/COPYRIGHT.txt new file mode 100644 index 0000000000..af77776cca --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/COPYRIGHT.txt @@ -0,0 +1,45 @@ +These documentation pages include resources by third parties. This copyright +file applies only to those resources. The following third party resources are +included, and carry their own copyright notices and license terms: + +* Fira Sans (FiraSans-Regular.woff, FiraSans-Medium.woff): + + Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ + with Reserved Font Name Fira Sans. + + Copyright (c) 2014, Telefonica S.A. + + Licensed under the SIL Open Font License, Version 1.1. + See FiraSans-LICENSE.txt. + +* rustdoc.css, main.js, and playpen.js: + + Copyright 2015 The Rust Developers. + Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or + the MIT license (LICENSE-MIT.txt) at your option. + +* normalize.css: + + Copyright (c) Nicolas Gallagher and Jonathan Neal. + Licensed under the MIT license (see LICENSE-MIT.txt). + +* Source Code Pro (SourceCodePro-Regular.woff, SourceCodePro-Semibold.woff): + + Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), + with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark + of Adobe Systems Incorporated in the United States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceCodePro-LICENSE.txt. + +* Source Serif Pro (SourceSerifPro-Regular.ttf.woff, + SourceSerifPro-Bold.ttf.woff, SourceSerifPro-It.ttf.woff): + + Copyright 2014 Adobe Systems Incorporated (http://www.adobe.com/), with + Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of + Adobe Systems Incorporated in the United States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceSerifPro-LICENSE.txt. + +This copyright file is intended to be distributed with rustdoc output. diff --git a/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-LICENSE.txt b/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-LICENSE.txt new file mode 100644 index 0000000000..d444ea92b6 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-LICENSE.txt @@ -0,0 +1,94 @@ +Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. +with Reserved Font Name < Fira >, + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-Medium.woff b/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-Medium.woff new file mode 100644 index 0000000000..7d742c5fb7 Binary files /dev/null and b/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-Medium.woff differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-Regular.woff b/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-Regular.woff new file mode 100644 index 0000000000..d8e0363f4e Binary files /dev/null and b/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-Regular.woff differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/LICENSE-APACHE.txt b/static/docs-rs/bdk/0.1.0-beta.1/LICENSE-APACHE.txt new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/LICENSE-APACHE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/static/docs-rs/bdk/0.1.0-beta.1/LICENSE-MIT.txt b/static/docs-rs/bdk/0.1.0-beta.1/LICENSE-MIT.txt new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/LICENSE-MIT.txt @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-LICENSE.txt b/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-LICENSE.txt new file mode 100644 index 0000000000..07542572e3 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-LICENSE.txt @@ -0,0 +1,93 @@ +Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Regular.woff b/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Regular.woff new file mode 100644 index 0000000000..5576670903 Binary files /dev/null and b/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Regular.woff differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Semibold.woff b/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Semibold.woff new file mode 100644 index 0000000000..ca972a11dc Binary files /dev/null and b/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Semibold.woff differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Bold.ttf.woff b/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Bold.ttf.woff new file mode 100644 index 0000000000..ca254318fe Binary files /dev/null and b/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Bold.ttf.woff differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-It.ttf.woff b/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-It.ttf.woff new file mode 100644 index 0000000000..a287bbe6ed Binary files /dev/null and b/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-It.ttf.woff differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-LICENSE.md b/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-LICENSE.md new file mode 100644 index 0000000000..22cb755f2f --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-LICENSE.md @@ -0,0 +1,93 @@ +Copyright 2014-2018 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Regular.ttf.woff b/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Regular.ttf.woff new file mode 100644 index 0000000000..a3d55cfdf2 Binary files /dev/null and b/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Regular.ttf.woff differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/all.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/all.html new file mode 100644 index 0000000000..3a505a083c --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/all.html @@ -0,0 +1,3 @@ +List of all items in this crate

[] + + List of all items

Structs

Enums

Traits

Functions

Typedefs

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/enum.CompactFiltersError.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/enum.CompactFiltersError.html new file mode 100644 index 0000000000..e4c41ded0b --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/enum.CompactFiltersError.html @@ -0,0 +1,56 @@ +bdk::blockchain::compact_filters::CompactFiltersError - Rust

[][src]Enum bdk::blockchain::compact_filters::CompactFiltersError

pub enum CompactFiltersError {
+    InvalidResponse,
+    InvalidHeaders,
+    InvalidFilterHeader,
+    InvalidFilter,
+    MissingBlock,
+    DataCorruption,
+    NotConnected,
+    Timeout,
+    NoPeers,
+    DB(Error),
+    IO(Error),
+    BIP158(Error),
+    Time(SystemTimeError),
+    Global(Box<Error>),
+}

An error that can occur during sync with a [CompactFiltersBlockchain]

+

+ Variants

+
InvalidResponse

A peer sent an invalid or unexpected response

+
InvalidHeaders

The headers returned are invalid

+
InvalidFilterHeader

The compact filter headers returned are invalid

+
InvalidFilter

The compact filter returned is invalid

+
MissingBlock

The peer is missing a block in the valid chain

+
DataCorruption

The data stored in the block filters storage are corrupted

+
NotConnected

A peer is not connected

+
Timeout

A peer took too long to reply to one of our messages

+
NoPeers

No peers have been specified

+
DB(Error)

Internal database error

+
IO(Error)

Internal I/O error

+
BIP158(Error)

Invalid BIP158 filter

+

Internal system time error

+
Global(Box<Error>)

Wrapper for [crate::error::Error]

+

Trait Implementations

impl Debug for CompactFiltersError[src]

impl Display for CompactFiltersError[src]

impl Error for CompactFiltersError[src]

impl From<CompactFiltersError> for Error[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for CompactFiltersError[src]

impl From<SystemTimeError> for CompactFiltersError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/index.html new file mode 100644 index 0000000000..26e359d8ec --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/index.html @@ -0,0 +1,31 @@ +bdk::blockchain::compact_filters - Rust

[][src]Module bdk::blockchain::compact_filters

Compact Filters

+

This module contains a multithreaded implementation of an [Blockchain] backend that +uses BIP157 (aka "Neutrino") to populate the wallet's database +by downloading compact filters from the P2P network.

+

Since there are currently very few peers "in the wild" that advertise the required service +flag, this implementation requires that one or more known peers are provided by the user. +No dns or other kinds of peer discovery are done internally.

+

Moreover, this module doesn't currently support detecting and resolving conflicts between +messages received by different peers. Thus, it's recommended to use this module by only +connecting to a single peer at a time, optionally by opening multiple connections if it's +desirable to use multiple threads at once to sync in parallel.

+

Example

+
+let num_threads = 4;
+
+let mempool = Arc::new(Mempool::default());
+let peers = (0..num_threads)
+    .map(|_| Peer::connect(
+        "btcd-mainnet.lightning.computer:8333",
+        Arc::clone(&mempool),
+        Network::Bitcoin,
+    ))
+    .collect::<Result<_, _>>()?;
+let blockchain = CompactFiltersBlockchain::new(peers, "./wallet-filters", Some(500_000))?;
+

Structs

+
CompactFiltersBlockchain

Structure implementing the required blockchain traits

+
Mempool

Container for unconfirmed, but valid Bitcoin transactions

+
Peer

A Bitcoin peer

+

Enums

+
CompactFiltersError

An error that can occur during sync with a [CompactFiltersBlockchain]

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Mempool.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Mempool.html new file mode 100644 index 0000000000..cd04378cbe --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Mempool.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../../../bdk/blockchain/compact_filters/struct.Mempool.html...

+ + + \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Peer.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Peer.html new file mode 100644 index 0000000000..11332c3bdb --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Peer.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../../../bdk/blockchain/compact_filters/struct.Peer.html...

+ + + \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/sidebar-items.js new file mode 100644 index 0000000000..22c61151d6 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["CompactFiltersError","An error that can occur during sync with a [`CompactFiltersBlockchain`]"]],"struct":[["CompactFiltersBlockchain","Structure implementing the required blockchain traits"],["Mempool","Container for unconfirmed, but valid Bitcoin transactions"],["Peer","A Bitcoin peer"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html new file mode 100644 index 0000000000..26a60c6fc9 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html @@ -0,0 +1,28 @@ +bdk::blockchain::compact_filters::CompactFiltersBlockchain - Rust

[][src]Struct bdk::blockchain::compact_filters::CompactFiltersBlockchain

pub struct CompactFiltersBlockchain { /* fields omitted */ }

Structure implementing the required blockchain traits

+

Example

+

See the blockchain::compact_filters module for a usage example.

+

Implementations

impl CompactFiltersBlockchain[src]

pub fn new<P: AsRef<Path>>(
    peers: Vec<Peer>,
    storage_dir: P,
    skip_blocks: Option<usize>
) -> Result<Self, CompactFiltersError>
[src]

Construct a new instance given a list of peers, a path to store headers and block +filters downloaded during the sync and optionally a number of blocks to ignore starting +from the genesis while scanning for the wallet's outputs.

+

For each [Peer] specified a new thread will be spawned to download and verify the filters +in parallel. It's currently recommended to only connect to a single peer to avoid +inconsistencies in the data returned, optionally with multiple connections in parallel to +speed-up the sync process.

+

Trait Implementations

impl Blockchain for CompactFiltersBlockchain[src]

impl Debug for CompactFiltersBlockchain[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BlockchainMarker for T where
    T: Blockchain
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Mempool.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Mempool.html new file mode 100644 index 0000000000..40b0b89143 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Mempool.html @@ -0,0 +1,21 @@ +bdk::blockchain::compact_filters::Mempool - Rust

[][src]Struct bdk::blockchain::compact_filters::Mempool

pub struct Mempool { /* fields omitted */ }

Container for unconfirmed, but valid Bitcoin transactions

+

It is normally shared between [Peer]s with the use of [Arc], so that transactions are not +duplicated in memory.

+

Implementations

impl Mempool[src]

pub fn add_tx(&self, tx: Transaction)[src]

Add a transaction to the mempool

+

Note that this doesn't propagate the transaction to other +peers. To do that, broadcast should be used.

+

pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction>[src]

Look-up a transaction in the mempool given an [Inventory] request

+

pub fn has_tx(&self, txid: &Txid) -> bool[src]

Return whether or not the mempool contains a transaction with a given txid

+

pub fn iter_txs(&self) -> Vec<Transaction>[src]

Return the list of transactions contained in the mempool

+

Trait Implementations

impl Debug for Mempool[src]

impl Default for Mempool[src]

Auto Trait Implementations

impl RefUnwindSafe for Mempool

impl Send for Mempool

impl Sync for Mempool

impl Unpin for Mempool

impl UnwindSafe for Mempool

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Peer.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Peer.html new file mode 100644 index 0000000000..b0ac7bbd7b --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Peer.html @@ -0,0 +1,25 @@ +bdk::blockchain::compact_filters::Peer - Rust

[][src]Struct bdk::blockchain::compact_filters::Peer

pub struct Peer { /* fields omitted */ }

A Bitcoin peer

+

Implementations

impl Peer[src]

pub fn connect<A: ToSocketAddrs>(
    address: A,
    mempool: Arc<Mempool>,
    network: Network
) -> Result<Self, CompactFiltersError>
[src]

Connect to a peer over a plaintext TCP connection

+

This function internally spawns a new thread that will monitor incoming messages from the +peer, and optionally reply to some of them transparently, like pings

+

pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
    target: T,
    proxy: P,
    credentials: Option<(&str, &str)>,
    mempool: Arc<Mempool>,
    network: Network
) -> Result<Self, CompactFiltersError>
[src]

Connect to a peer through a SOCKS5 proxy, optionally by using some credentials, specified +as a tuple of (username, password)

+

This function internally spawns a new thread that will monitor incoming messages from the +peer, and optionally reply to some of them transparently, like pings

+

pub fn get_version(&self) -> &VersionMessage[src]

Return the [VersionMessage] sent by the peer

+

pub fn get_network(&self) -> Network[src]

Return the Bitcoin [Network] in use

+

pub fn get_mempool(&self) -> Arc<Mempool>[src]

Return the mempool used by this peer

+

pub fn is_connected(&self) -> bool[src]

Return whether or not the peer is still connected

+

pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError>[src]

Send a raw Bitcoin message to the peer

+

pub fn recv(
    &self,
    wait_for: &'static str,
    timeout: Option<Duration>
) -> Result<Option<NetworkMessage>, CompactFiltersError>
[src]

Waits for a specific incoming Bitcoin message, optionally with a timeout

+

Trait Implementations

impl Debug for Peer[src]

Auto Trait Implementations

impl !RefUnwindSafe for Peer

impl Send for Peer

impl Sync for Peer

impl Unpin for Peer

impl !UnwindSafe for Peer

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/index.html new file mode 100644 index 0000000000..6124b78e35 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/index.html @@ -0,0 +1,11 @@ +bdk::blockchain::electrum - Rust

[][src]Module bdk::blockchain::electrum

Electrum

+

This module defines a [Blockchain] struct that wraps an [electrum_client::Client] +and implements the logic required to populate the wallet's database by +querying the inner client.

+

Example

+
+let client = electrum_client::Client::new("ssl://electrum.blockstream.info:50002", None)?;
+let blockchain = ElectrumBlockchain::from(client);
+

Structs

+
ElectrumBlockchain

Wrapper over an Electrum Client that implements the required blockchain traits

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/sidebar-items.js new file mode 100644 index 0000000000..ca94a34fb0 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["ElectrumBlockchain","Wrapper over an Electrum Client that implements the required blockchain traits"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/struct.ElectrumBlockchain.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/struct.ElectrumBlockchain.html new file mode 100644 index 0000000000..c9382cd9ab --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/struct.ElectrumBlockchain.html @@ -0,0 +1,21 @@ +bdk::blockchain::electrum::ElectrumBlockchain - Rust

[][src]Struct bdk::blockchain::electrum::ElectrumBlockchain

pub struct ElectrumBlockchain(_);

Wrapper over an Electrum Client that implements the required blockchain traits

+

Example

+

See the blockchain::electrum module for a usage example.

+

Trait Implementations

impl Blockchain for ElectrumBlockchain[src]

impl From<Client> for ElectrumBlockchain[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BlockchainMarker for T where
    T: Blockchain
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/enum.Capability.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/enum.Capability.html new file mode 100644 index 0000000000..0e3b82edfa --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/enum.Capability.html @@ -0,0 +1,32 @@ +bdk::blockchain::Capability - Rust

[][src]Enum bdk::blockchain::Capability

pub enum Capability {
+    FullHistory,
+    GetAnyTx,
+    AccurateFees,
+}

Capabilities that can be supported by a [Blockchain] backend

+

+ Variants

+
FullHistory

Can recover the full history of a wallet and not only the set of currently spendable UTXOs

+
GetAnyTx

Can fetch any historical transaction given its txid

+
AccurateFees

Can compute accurate fees for the transactions found during sync

+

Trait Implementations

impl Clone for Capability[src]

impl Copy for Capability[src]

impl Debug for Capability[src]

impl Eq for Capability[src]

impl Hash for Capability[src]

impl PartialEq<Capability> for Capability[src]

impl StructuralEq for Capability[src]

impl StructuralPartialEq for Capability[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/enum.EsploraError.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/enum.EsploraError.html new file mode 100644 index 0000000000..ac8df66950 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/enum.EsploraError.html @@ -0,0 +1,34 @@ +bdk::blockchain::esplora::EsploraError - Rust

[][src]Enum bdk::blockchain::esplora::EsploraError

pub enum EsploraError {
+    Reqwest(Error),
+    Parsing(ParseIntError),
+    BitcoinEncoding(Error),
+    TransactionNotFound(Txid),
+}

Errors that can happen during a sync with [EsploraBlockchain]

+

+ Variants

+
Reqwest(Error)

Error with the HTTP call

+
Parsing(ParseIntError)

Invalid number returned

+
BitcoinEncoding(Error)

Invalid Bitcoin data returned

+
TransactionNotFound(Txid)

Transaction not found

+

Trait Implementations

impl Debug for EsploraError[src]

impl Display for EsploraError[src]

impl Error for EsploraError[src]

impl From<Error> for EsploraError[src]

impl From<Error> for EsploraError[src]

impl From<EsploraError> for Error[src]

impl From<ParseIntError> for EsploraError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/index.html new file mode 100644 index 0000000000..87c6703711 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/index.html @@ -0,0 +1,11 @@ +bdk::blockchain::esplora - Rust

[][src]Module bdk::blockchain::esplora

Esplora

+

This module defines a [Blockchain] struct that can query an Esplora backend +populate the wallet's database by

+

Example

+
+let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api");
+

Structs

+
EsploraBlockchain

Structure that implements the logic to sync with Esplora

+

Enums

+
EsploraError

Errors that can happen during a sync with [EsploraBlockchain]

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/sidebar-items.js new file mode 100644 index 0000000000..fc6ecf6be6 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["EsploraError","Errors that can happen during a sync with [`EsploraBlockchain`]"]],"struct":[["EsploraBlockchain","Structure that implements the logic to sync with Esplora"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/struct.EsploraBlockchain.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/struct.EsploraBlockchain.html new file mode 100644 index 0000000000..1e46bd99b8 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/struct.EsploraBlockchain.html @@ -0,0 +1,22 @@ +bdk::blockchain::esplora::EsploraBlockchain - Rust

[][src]Struct bdk::blockchain::esplora::EsploraBlockchain

pub struct EsploraBlockchain(_);

Structure that implements the logic to sync with Esplora

+

Example

+

See the blockchain::esplora module for a usage example.

+

Implementations

impl EsploraBlockchain[src]

pub fn new(base_url: &str) -> Self[src]

Create a new instance of the client from a base URL

+

Trait Implementations

impl Blockchain for EsploraBlockchain[src]

impl Debug for EsploraBlockchain[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BlockchainMarker for T where
    T: Blockchain
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.log_progress.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.log_progress.html new file mode 100644 index 0000000000..7b9070a659 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.log_progress.html @@ -0,0 +1,2 @@ +bdk::blockchain::log_progress - Rust

[][src]Function bdk::blockchain::log_progress

pub fn log_progress() -> LogProgress

Create a nwe instance of [LogProgress]

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.noop_progress.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.noop_progress.html new file mode 100644 index 0000000000..d537afe53d --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.noop_progress.html @@ -0,0 +1,2 @@ +bdk::blockchain::noop_progress - Rust

[][src]Function bdk::blockchain::noop_progress

pub fn noop_progress() -> NoopProgress

Create a new instance of [NoopProgress]

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.progress.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.progress.html new file mode 100644 index 0000000000..8e6c0b5573 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.progress.html @@ -0,0 +1,2 @@ +bdk::blockchain::progress - Rust

[][src]Function bdk::blockchain::progress

pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>)

Shortcut to create a [channel] (pair of [Sender] and [Receiver]) that can transport [ProgressData]

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/index.html new file mode 100644 index 0000000000..c9e114ee05 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/index.html @@ -0,0 +1,28 @@ +bdk::blockchain - Rust

[][src]Module bdk::blockchain

Blockchain backends

+

This module provides the implementation of a few commonly-used backends like +Electrum, Esplora and +Compact Filters/Neutrino, along with a generalized trait +[Blockchain] that can be implemented to build customized backends.

+

Re-exports

+
pub use self::electrum::ElectrumBlockchain;
pub use self::esplora::EsploraBlockchain;
pub use self::compact_filters::CompactFiltersBlockchain;

Modules

+
compact_filters

Compact Filters

+
electrum

Electrum

+
esplora

Esplora

+

Structs

+
LogProgress

Type that implements [Progress] and logs at level INFO every update received

+
NoopProgress

Type that implements [Progress] and drops every update received

+
OfflineBlockchain

Type that only implements [Blockchain] and is always "offline"

+

Enums

+
Capability

Capabilities that can be supported by a [Blockchain] backend

+

Traits

+
Blockchain

Trait that defines the actions that must be supported by a blockchain backend

+
BlockchainMarker

Marker trait for a blockchain backend

+
Progress

Trait for types that can receive and process progress updates during [Blockchain::sync] and +[Blockchain::setup]

+

Functions

+
log_progress

Create a nwe instance of [LogProgress]

+
noop_progress

Create a new instance of [NoopProgress]

+
progress

Shortcut to create a [channel] (pair of [Sender] and [Receiver]) that can transport [ProgressData]

+

Type Definitions

+
ProgressData

Data sent with a progress update over a [channel]

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/sidebar-items.js new file mode 100644 index 0000000000..caf2b0fe29 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Capability","Capabilities that can be supported by a [`Blockchain`] backend"]],"fn":[["log_progress","Create a nwe instance of [`LogProgress`]"],["noop_progress","Create a new instance of [`NoopProgress`]"],["progress","Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]"]],"mod":[["compact_filters","Compact Filters"],["electrum","Electrum"],["esplora","Esplora"]],"struct":[["LogProgress","Type that implements [`Progress`] and logs at level `INFO` every update received"],["NoopProgress","Type that implements [`Progress`] and drops every update received"],["OfflineBlockchain","Type that only implements [`Blockchain`] and is always \"offline\""]],"trait":[["Blockchain","Trait that defines the actions that must be supported by a blockchain backend"],["BlockchainMarker","Marker trait for a blockchain backend"],["Progress","Trait for types that can receive and process progress updates during [`Blockchain::sync`] and [`Blockchain::setup`]"]],"type":[["ProgressData","Data sent with a progress update over a [`channel`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.LogProgress.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.LogProgress.html new file mode 100644 index 0000000000..551e5af3cf --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.LogProgress.html @@ -0,0 +1,18 @@ +bdk::blockchain::LogProgress - Rust

[][src]Struct bdk::blockchain::LogProgress

pub struct LogProgress;

Type that implements [Progress] and logs at level INFO every update received

+

Trait Implementations

impl Clone for LogProgress[src]

impl Progress for LogProgress[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.NoopProgress.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.NoopProgress.html new file mode 100644 index 0000000000..258ebd5f60 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.NoopProgress.html @@ -0,0 +1,18 @@ +bdk::blockchain::NoopProgress - Rust

[][src]Struct bdk::blockchain::NoopProgress

pub struct NoopProgress;

Type that implements [Progress] and drops every update received

+

Trait Implementations

impl Clone for NoopProgress[src]

impl Progress for NoopProgress[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.OfflineBlockchain.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.OfflineBlockchain.html new file mode 100644 index 0000000000..ba777d9cbf --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.OfflineBlockchain.html @@ -0,0 +1,11 @@ +bdk::blockchain::OfflineBlockchain - Rust

[][src]Struct bdk::blockchain::OfflineBlockchain

pub struct OfflineBlockchain;

Type that only implements [Blockchain] and is always "offline"

+

Trait Implementations

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BlockchainMarker for T where
    T: Blockchain
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Blockchain.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Blockchain.html new file mode 100644 index 0000000000..77f53cc7bb --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Blockchain.html @@ -0,0 +1,37 @@ +bdk::blockchain::Blockchain - Rust

[][src]Trait bdk::blockchain::Blockchain

pub trait Blockchain: BlockchainMarker {
+    fn get_capabilities(&self) -> HashSet<Capability>;
+
fn setup<D: BatchDatabase, P: 'static + Progress>(
        &self,
        stop_gap: Option<usize>,
        database: &mut D,
        progress_update: P
    ) -> Result<(), Error>; +
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>; +
fn broadcast(&self, tx: &Transaction) -> Result<(), Error>; +
fn get_height(&self) -> Result<u32, Error>; +
fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>; + + fn sync<D: BatchDatabase, P: 'static + Progress>(
        &self,
        stop_gap: Option<usize>,
        database: &mut D,
        progress_update: P
    ) -> Result<(), Error> { ... } +}

Trait that defines the actions that must be supported by a blockchain backend

+
+

Required methods

fn get_capabilities(&self) -> HashSet<Capability>

Return the set of [Capability] supported by this backend

+

fn setup<D: BatchDatabase, P: 'static + Progress>(
    &self,
    stop_gap: Option<usize>,
    database: &mut D,
    progress_update: P
) -> Result<(), Error>

Setup the backend and populate the internal database for the first time

+

This method is the equivalent of [Blockchain::sync], but it's guaranteed to only be +called once, at the first Wallet::sync.

+

The rationale behind the distinction between sync and setup is that some custom backends +might need to perform specific actions only the first time they are synced.

+

For types that do not have that distinction, only this method can be implemented, since +[Blockchain::sync] defaults to calling this internally if not overridden.

+

fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>

Fetch a transaction from the blockchain given its txid

+

fn broadcast(&self, tx: &Transaction) -> Result<(), Error>

Broadcast a transaction

+

fn get_height(&self) -> Result<u32, Error>

Return the current height

+

fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>

Estimate the fee rate required to confirm a transaction in a given target of blocks

+
Loading content... +

Provided methods

fn sync<D: BatchDatabase, P: 'static + Progress>(
    &self,
    stop_gap: Option<usize>,
    database: &mut D,
    progress_update: P
) -> Result<(), Error>

Populate the internal database with transactions and UTXOs

+

If not overridden, it defaults to calling [Blockchain::setup] internally.

+

This method should implement the logic required to iterate over the list of the wallet's +script_pubkeys using Database::iter_script_pubkeys and look for relevant transactions +in the blockchain to populate the database with BatchOperations::set_tx and +BatchOperations::set_utxo.

+

This method should also take care of removing UTXOs that are seen as spent in the +blockchain, using BatchOperations::del_utxo.

+

The progress_update object can be used to give the caller updates about the progress by using +[Progress::update].

+
Loading content... +

Implementations on Foreign Types

impl<T: Blockchain> Blockchain for Arc<T>[src]

Loading content... +

Implementors

impl Blockchain for CompactFiltersBlockchain[src]

impl Blockchain for ElectrumBlockchain[src]

impl Blockchain for EsploraBlockchain[src]

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.BlockchainMarker.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.BlockchainMarker.html new file mode 100644 index 0000000000..86eea223b1 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.BlockchainMarker.html @@ -0,0 +1,12 @@ +bdk::blockchain::BlockchainMarker - Rust

[][src]Trait bdk::blockchain::BlockchainMarker

pub trait BlockchainMarker { }

Marker trait for a blockchain backend

+

This is a marker trait for blockchain types. It is automatically implemented for types that +implement [Blockchain], so as a user of the library you won't have to implement this +manually.

+

Users of the library will probably never have to implement this trait manually, but they +could still need to import it to define types and structs with generics; +Implementing only the marker trait is pointless, since [OfflineBlockchain] +already does that, and whenever [Blockchain] is implemented, the marker trait is also +automatically implemented by the library.

+
+

Implementors

impl BlockchainMarker for OfflineBlockchain[src]

impl<T: Blockchain> BlockchainMarker for T[src]

The [BlockchainMarker] marker trait is automatically implemented for [Blockchain] types

+
Loading content...
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Progress.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Progress.html new file mode 100644 index 0000000000..29ffb95073 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Progress.html @@ -0,0 +1,11 @@ +bdk::blockchain::Progress - Rust

[][src]Trait bdk::blockchain::Progress

pub trait Progress: Send {
+    fn update(
        &self,
        progress: f32,
        message: Option<String>
    ) -> Result<(), Error>; +}

Trait for types that can receive and process progress updates during [Blockchain::sync] and +[Blockchain::setup]

+
+

Required methods

fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error>

Send a new progress update

+

The progress value should be in the range 0.0 - 100.0, and the message value is an +optional text message that can be displayed to the user.

+
Loading content... +

Implementations on Foreign Types

impl Progress for Sender<ProgressData>[src]

Loading content... +

Implementors

impl Progress for LogProgress[src]

impl Progress for NoopProgress[src]

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/type.ProgressData.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/type.ProgressData.html new file mode 100644 index 0000000000..9bdf253623 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/type.ProgressData.html @@ -0,0 +1,2 @@ +bdk::blockchain::ProgressData - Rust

[][src]Type Definition bdk::blockchain::ProgressData

type ProgressData = (f32, Option<String>);

Data sent with a progress update over a [channel]

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/index.html new file mode 100644 index 0000000000..b82eb576f9 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/index.html @@ -0,0 +1,17 @@ +bdk::database - Rust

[][src]Module bdk::database

Database types

+

This module provides the implementation of some defaults database types, along with traits that +can be implemented externally to let Wallets use customized databases.

+

It's important to note that the databases defined here only contains "blockchain-related" data. +They can be seen more as a cache than a critical piece of storage that contains secrets and +keys.

+

The currently recommended database is [sled], which is a pretty simple key-value embedded +database written in Rust. If the key-value-db feature is enabled (which by default is), +this library automatically implements all the required traits for [sled::Tree].

+

Re-exports

+
pub use memory::MemoryDatabase;

Modules

+
memory

In-memory ephemeral database

+

Traits

+
BatchDatabase

Trait for a database that supports batch operations

+
BatchOperations

Trait for operations that can be batched

+
Database

Trait for reading data from a database

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/index.html new file mode 100644 index 0000000000..71dd168af7 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/index.html @@ -0,0 +1,6 @@ +bdk::database::memory - Rust

[][src]Module bdk::database::memory

In-memory ephemeral database

+

This module defines an in-memory database type called [MemoryDatabase] that is based on a +[BTreeMap].

+

Structs

+
MemoryDatabase

In-memory ephemeral database

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/sidebar-items.js new file mode 100644 index 0000000000..665f6718d0 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["MemoryDatabase","In-memory ephemeral database"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/struct.MemoryDatabase.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/struct.MemoryDatabase.html new file mode 100644 index 0000000000..54af7606e0 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/struct.MemoryDatabase.html @@ -0,0 +1,45 @@ +bdk::database::memory::MemoryDatabase - Rust

[][src]Struct bdk::database::memory::MemoryDatabase

pub struct MemoryDatabase { /* fields omitted */ }

In-memory ephemeral database

+

This database can be used as a temporary storage for wallets that are not kept permanently on +a device, or on platforms that don't provide a filesystem, like wasm32.

+

Once it's dropped its content will be lost.

+

If you are looking for a permanent storage solution, you can try with the default key-value +database called [sled]. See the database module documentation for more defailts.

+

Implementations

impl MemoryDatabase[src]

pub fn new() -> Self[src]

Create a new empty database

+

Trait Implementations

impl BatchDatabase for MemoryDatabase[src]

type Batch = Self

Container for the operations

+

impl BatchOperations for MemoryDatabase[src]

impl Database for MemoryDatabase[src]

impl Debug for MemoryDatabase[src]

impl Default for MemoryDatabase[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/sidebar-items.js new file mode 100644 index 0000000000..1d5816196c --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"mod":[["memory","In-memory ephemeral database"]],"trait":[["BatchDatabase","Trait for a database that supports batch operations"],["BatchOperations","Trait for operations that can be batched"],["Database","Trait for reading data from a database"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchDatabase.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchDatabase.html new file mode 100644 index 0000000000..5af2c0e52b --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchDatabase.html @@ -0,0 +1,14 @@ +bdk::database::BatchDatabase - Rust

[][src]Trait bdk::database::BatchDatabase

pub trait BatchDatabase: Database {
+    type Batch: BatchOperations;
+    fn begin_batch(&self) -> Self::Batch;
+
fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>; +}

Trait for a database that supports batch operations

+

This trait defines the methods to start and apply a batch of operations.

+
+

Associated Types

type Batch: BatchOperations

Container for the operations

+
Loading content... +

Required methods

fn begin_batch(&self) -> Self::Batch

Create a new batch container

+

fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>

Consume and apply a batch of operations

+
Loading content... +

Implementations on Foreign Types

impl BatchDatabase for Tree[src]

type Batch = Batch

Loading content... +

Implementors

impl BatchDatabase for MemoryDatabase[src]

type Batch = Self

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchOperations.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchOperations.html new file mode 100644 index 0000000000..ced1c71908 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchOperations.html @@ -0,0 +1,31 @@ +bdk::database::BatchOperations - Rust

[][src]Trait bdk::database::BatchOperations

pub trait BatchOperations {
+    fn set_script_pubkey(
        &mut self,
        script: &Script,
        script_type: ScriptType,
        child: u32
    ) -> Result<(), Error>; +
fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>; +
fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>; +
fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>; +
fn set_last_index(
        &mut self,
        script_type: ScriptType,
        value: u32
    ) -> Result<(), Error>; +
fn del_script_pubkey_from_path(
        &mut self,
        script_type: ScriptType,
        child: u32
    ) -> Result<Option<Script>, Error>; +
fn del_path_from_script_pubkey(
        &mut self,
        script: &Script
    ) -> Result<Option<(ScriptType, u32)>, Error>; +
fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>; +
fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>; +
fn del_tx(
        &mut self,
        txid: &Txid,
        include_raw: bool
    ) -> Result<Option<TransactionDetails>, Error>; +
fn del_last_index(
        &mut self,
        script_type: ScriptType
    ) -> Result<Option<u32>, Error>; +}

Trait for operations that can be batched

+

This trait defines the list of operations that must be implemented on the [Database] type and +the [BatchDatabase::Batch] type.

+
+

Required methods

fn set_script_pubkey(
    &mut self,
    script: &Script,
    script_type: ScriptType,
    child: u32
) -> Result<(), Error>

Store a script_pubkey along with its script type and child number

+

fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>

Store a [UTXO]

+

fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>

Store a raw transaction

+

fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>

Store the metadata of a transaction

+

fn set_last_index(
    &mut self,
    script_type: ScriptType,
    value: u32
) -> Result<(), Error>

Store the last derivation index for a given script type

+

fn del_script_pubkey_from_path(
    &mut self,
    script_type: ScriptType,
    child: u32
) -> Result<Option<Script>, Error>

Delete a script_pubkey given the script type and its child number

+

fn del_path_from_script_pubkey(
    &mut self,
    script: &Script
) -> Result<Option<(ScriptType, u32)>, Error>

Delete the data related to a specific script_pubkey, meaning the script type and the child +number

+

fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>

Delete a [UTXO] given its [OutPoint]

+

fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>

Delete a raw transaction given its [Txid]

+

fn del_tx(
    &mut self,
    txid: &Txid,
    include_raw: bool
) -> Result<Option<TransactionDetails>, Error>

Delete the metadata of a transaction and optionally the raw transaction itself

+

fn del_last_index(
    &mut self,
    script_type: ScriptType
) -> Result<Option<u32>, Error>

Delete the last derivation index for a script type

+
Loading content... +

Implementations on Foreign Types

impl BatchOperations for Tree[src]

impl BatchOperations for Batch[src]

Loading content... +

Implementors

impl BatchOperations for MemoryDatabase[src]

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.Database.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.Database.html new file mode 100644 index 0000000000..132165ada4 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.Database.html @@ -0,0 +1,35 @@ +bdk::database::Database - Rust

[][src]Trait bdk::database::Database

pub trait Database: BatchOperations {
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
        &mut self,
        script_type: ScriptType,
        bytes: B
    ) -> Result<(), Error>; +
fn iter_script_pubkeys(
        &self,
        script_type: Option<ScriptType>
    ) -> Result<Vec<Script>, Error>; +
fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>; +
fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>; +
fn iter_txs(
        &self,
        include_raw: bool
    ) -> Result<Vec<TransactionDetails>, Error>; +
fn get_script_pubkey_from_path(
        &self,
        script_type: ScriptType,
        child: u32
    ) -> Result<Option<Script>, Error>; +
fn get_path_from_script_pubkey(
        &self,
        script: &Script
    ) -> Result<Option<(ScriptType, u32)>, Error>; +
fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>; +
fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>; +
fn get_tx(
        &self,
        txid: &Txid,
        include_raw: bool
    ) -> Result<Option<TransactionDetails>, Error>; +
fn get_last_index(
        &self,
        script_type: ScriptType
    ) -> Result<Option<u32>, Error>; +
fn increment_last_index(
        &mut self,
        script_type: ScriptType
    ) -> Result<u32, Error>; +}

Trait for reading data from a database

+

This traits defines the operations that can be used to read data out of a database

+
+

Required methods

fn check_descriptor_checksum<B: AsRef<[u8]>>(
    &mut self,
    script_type: ScriptType,
    bytes: B
) -> Result<(), Error>

Read and checks the descriptor checksum for a given script type

+

Should return Error::ChecksumMismatch if the +checksum doesn't match. If there's no checksum in the database, simply store it for the +next time.

+

fn iter_script_pubkeys(
    &self,
    script_type: Option<ScriptType>
) -> Result<Vec<Script>, Error>

Return the list of script_pubkeys

+

fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>

Return the list of [UTXO]s

+

fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>

Return the list of raw transactions

+

fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error>

Return the list of transactions metadata

+

fn get_script_pubkey_from_path(
    &self,
    script_type: ScriptType,
    child: u32
) -> Result<Option<Script>, Error>

Fetch a script_pubkey given the script type and child number

+

fn get_path_from_script_pubkey(
    &self,
    script: &Script
) -> Result<Option<(ScriptType, u32)>, Error>

Fetch the script type and child number of a given script_pubkey

+

fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>

Fetch a [UTXO] given its [OutPoint]

+

fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>

Fetch a raw transaction given its [Txid]

+

fn get_tx(
    &self,
    txid: &Txid,
    include_raw: bool
) -> Result<Option<TransactionDetails>, Error>

Fetch the transaction metadata and optionally also the raw transaction

+

fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error>

Return the last defivation index for a script type

+

fn increment_last_index(
    &mut self,
    script_type: ScriptType
) -> Result<u32, Error>

Increment the last derivation index for a script type and returns it

+

It should insert and return 0 if not present in the database

+
Loading content... +

Implementations on Foreign Types

impl Database for Tree[src]

Loading content... +

Implementors

impl Database for MemoryDatabase[src]

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/fn.get_checksum.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/fn.get_checksum.html new file mode 100644 index 0000000000..43647729e3 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/fn.get_checksum.html @@ -0,0 +1,2 @@ +bdk::descriptor::checksum::get_checksum - Rust

[][src]Function bdk::descriptor::checksum::get_checksum

pub fn get_checksum(desc: &str) -> Result<String, Error>

Compute the checksum of a descriptor

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/index.html new file mode 100644 index 0000000000..b6b7a26f33 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/index.html @@ -0,0 +1,6 @@ +bdk::descriptor::checksum - Rust

[][src]Module bdk::descriptor::checksum

Descriptor checksum

+

This module contains a re-implementation of the function used by Bitcoin Core to calculate the +checksum of a descriptor

+

Functions

+
get_checksum

Compute the checksum of a descriptor

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/sidebar-items.js new file mode 100644 index 0000000000..e1add094a5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"fn":[["get_checksum","Compute the checksum of a descriptor"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Descriptor.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Descriptor.html new file mode 100644 index 0000000000..fae819031a --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Descriptor.html @@ -0,0 +1,80 @@ +bdk::descriptor::Descriptor - Rust

[]Enum bdk::descriptor::Descriptor

pub enum Descriptor<Pk> where
    Pk: MiniscriptKey
{ + Bare(Miniscript<Pk, Legacy>), + Pk(Pk), + Pkh(Pk), + Wpkh(Pk), + ShWpkh(Pk), + Sh(Miniscript<Pk, Legacy>), + Wsh(Miniscript<Pk, Segwitv0>), + ShWsh(Miniscript<Pk, Segwitv0>), +}

Script descriptor

+

+ Variants

+
Bare(Miniscript<Pk, Legacy>)

A raw scriptpubkey (including pay-to-pubkey) under Legacy context

+
Pk(Pk)

Pay-to-Pubkey

+
Pkh(Pk)

Pay-to-PubKey-Hash

+
Wpkh(Pk)

Pay-to-Witness-PubKey-Hash

+
ShWpkh(Pk)

Pay-to-Witness-PubKey-Hash inside P2SH

+

Pay-to-ScriptHash with Legacy context

+

Pay-to-Witness-ScriptHash with Segwitv0 context

+
ShWsh(Miniscript<Pk, Segwitv0>)

P2SH-P2WSH with Segwitv0 context

+

Implementations

impl<Pk> Descriptor<Pk> where
    Pk: MiniscriptKey

pub fn translate_pk<Fpk, Fpkh, Q, E>(
    &self,
    translatefpk: Fpk,
    translatefpkh: Fpkh
) -> Result<Descriptor<Q>, E> where
    Fpk: FnMut(&Pk) -> Result<Q, E>,
    Fpkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, E>,
    Q: MiniscriptKey

Convert a descriptor using abstract keys to one using specific keys +This will panic if translatefpk returns an uncompressed key when +converting to a Segwit descriptor. To prevent this panic, ensure +translatefpk returns an error in this case instead.

+

impl<Pk> Descriptor<Pk> where
    Pk: MiniscriptKey + ToPublicKey

pub fn address(&self, network: Network) -> Option<Address>

Computes the Bitcoin address of the descriptor, if one exists

+

pub fn script_pubkey(&self) -> Script

Computes the scriptpubkey of the descriptor

+

pub fn unsigned_script_sig(&self) -> Script

Computes the scriptSig that will be in place for an unsigned +input spending an output with this descriptor. For pre-segwit +descriptors, which use the scriptSig for signatures, this +returns the empty script.

+

This is used in Segwit transactions to produce an unsigned +transaction whose txid will not change during signing (since +only the witness data will change).

+

pub fn witness_script(&self) -> Script

Computes the "witness script" of the descriptor, i.e. the underlying +script before any hashing is done. For Bare, Pkh and Wpkh this +is the scriptPubkey; for ShWpkh and Sh this is the redeemScript; +for the others it is the witness script.

+

pub fn satisfy<S>(&self, txin: &mut TxIn, satisfier: S) -> Result<(), Error> where
    S: Satisfier<Pk>, 

Attempts to produce a satisfying witness and scriptSig to spend an +output controlled by the given descriptor; add the data to a given +TxIn output.

+

pub fn max_satisfaction_weight(&self) -> usize

Computes an upper bound on the weight of a satisfying witness to the +transaction. Assumes all signatures are 73 bytes, including push opcode +and sighash suffix. Includes the weight of the VarInts encoding the +scriptSig and witness stack length.

+

impl Descriptor<DescriptorPublicKey>

pub fn derive(&self, path: &[ChildNumber]) -> Descriptor<DescriptorPublicKey>

Derives all wildcard keys in the descriptor using the supplied path

+

pub fn parse_secret(
    s: &str
) -> Result<(Descriptor<DescriptorPublicKey>, HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>), Error>

pub fn to_string_with_secret(
    &self,
    key_map: &HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>
) -> String

Trait Implementations

impl<Pk> Clone for Descriptor<Pk> where
    Pk: MiniscriptKey + Clone

impl<Pk> Debug for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> Display for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> Eq for Descriptor<Pk> where
    Pk: MiniscriptKey + Eq

impl ExtractPolicy for Descriptor<DescriptorPublicKey>[src]

impl<Pk> FromStr for Descriptor<Pk> where
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

type Err = Error

The associated error which can be returned from parsing.

+

impl<Pk> FromTree for Descriptor<Pk> where
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

fn from_tree(top: &Tree) -> Result<Descriptor<Pk>, Error>

Parse an expression tree into a descriptor

+

impl<Pk> Liftable<Pk> for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> Ord for Descriptor<Pk> where
    Pk: MiniscriptKey + Ord

impl<Pk> PartialEq<Descriptor<Pk>> for Descriptor<Pk> where
    Pk: MiniscriptKey + PartialEq<Pk>, 

impl<Pk> PartialOrd<Descriptor<Pk>> for Descriptor<Pk> where
    Pk: MiniscriptKey + PartialOrd<Pk>, 

impl<Pk> StructuralEq for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> StructuralPartialEq for Descriptor<Pk> where
    Pk: MiniscriptKey

Auto Trait Implementations

impl<Pk> RefUnwindSafe for Descriptor<Pk> where
    Pk: RefUnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe

impl<Pk> Send for Descriptor<Pk> where
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk> Sync for Descriptor<Pk> where
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk> Unpin for Descriptor<Pk> where
    Pk: Unpin,
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk> UnwindSafe for Descriptor<Pk> where
    Pk: RefUnwindSafe + UnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Legacy.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Legacy.html new file mode 100644 index 0000000000..498794d39a --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Legacy.html @@ -0,0 +1,32 @@ +bdk::descriptor::Legacy - Rust

[]Enum bdk::descriptor::Legacy

pub enum Legacy {}

Legacy ScriptContext

+

Trait Implementations

impl Clone for Legacy

impl Debug for Legacy

impl Eq for Legacy

impl Ord for Legacy

impl PartialEq<Legacy> for Legacy

impl PartialOrd<Legacy> for Legacy

impl ScriptContext for Legacy

impl StructuralEq for Legacy

impl StructuralPartialEq for Legacy

Auto Trait Implementations

impl RefUnwindSafe for Legacy

impl Send for Legacy

impl Sync for Legacy

impl Unpin for Legacy

impl UnwindSafe for Legacy

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Segwitv0.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Segwitv0.html new file mode 100644 index 0000000000..49880c3bef --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Segwitv0.html @@ -0,0 +1,32 @@ +bdk::descriptor::Segwitv0 - Rust

[]Enum bdk::descriptor::Segwitv0

pub enum Segwitv0 {}

Segwitv0 ScriptContext

+

Trait Implementations

impl Clone for Segwitv0

impl Debug for Segwitv0

impl Eq for Segwitv0

impl Ord for Segwitv0

impl PartialEq<Segwitv0> for Segwitv0

impl PartialOrd<Segwitv0> for Segwitv0

impl ScriptContext for Segwitv0

impl StructuralEq for Segwitv0

impl StructuralPartialEq for Segwitv0

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Terminal.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Terminal.html new file mode 100644 index 0000000000..7a18f3a4eb --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Terminal.html @@ -0,0 +1,128 @@ +bdk::descriptor::Terminal - Rust

[]Enum bdk::descriptor::Terminal

pub enum Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey
{ + True, + False, + PkK(Pk), + PkH(<Pk as MiniscriptKey>::Hash), + After(u32), + Older(u32), + Sha256(Hash), + Hash256(Hash), + Ripemd160(Hash), + Hash160(Hash), + Alt(Arc<Miniscript<Pk, Ctx>>), + Swap(Arc<Miniscript<Pk, Ctx>>), + Check(Arc<Miniscript<Pk, Ctx>>), + DupIf(Arc<Miniscript<Pk, Ctx>>), + Verify(Arc<Miniscript<Pk, Ctx>>), + NonZero(Arc<Miniscript<Pk, Ctx>>), + ZeroNotEqual(Arc<Miniscript<Pk, Ctx>>), + AndV(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + AndB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + AndOr(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + OrB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + OrD(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + OrC(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + OrI(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + Thresh(usizeVec<Arc<Miniscript<Pk, Ctx>>>), + Multi(usizeVec<Pk>), +}

All AST elements

+

+ Variants

+
True

1

+
False

0

+
PkK(Pk)

<key>

+
PkH(<Pk as MiniscriptKey>::Hash)

DUP HASH160 <keyhash> EQUALVERIFY

+
After(u32)

n CHECKLOCKTIMEVERIFY

+
Older(u32)

n CHECKSEQUENCEVERIFY

+
Sha256(Hash)

SIZE 32 EQUALVERIFY SHA256 <hash> EQUAL

+
Hash256(Hash)

SIZE 32 EQUALVERIFY HASH256 <hash> EQUAL

+
Ripemd160(Hash)

SIZE 32 EQUALVERIFY RIPEMD160 <hash> EQUAL

+
Hash160(Hash)

SIZE 32 EQUALVERIFY HASH160 <hash> EQUAL

+
Alt(Arc<Miniscript<Pk, Ctx>>)

TOALTSTACK [E] FROMALTSTACK

+
Swap(Arc<Miniscript<Pk, Ctx>>)

SWAP [E1]

+
Check(Arc<Miniscript<Pk, Ctx>>)

[Kt]/[Ke] CHECKSIG

+
DupIf(Arc<Miniscript<Pk, Ctx>>)

DUP IF [V] ENDIF

+
Verify(Arc<Miniscript<Pk, Ctx>>)

[T] VERIFY

+
NonZero(Arc<Miniscript<Pk, Ctx>>)

SIZE 0NOTEQUAL IF [Fn] ENDIF

+
ZeroNotEqual(Arc<Miniscript<Pk, Ctx>>)

[X] 0NOTEQUAL

+
AndV(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[V] [T]/[V]/[F]/[Kt]

+
AndB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] [W] BOOLAND

+
AndOr(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[various] NOTIF [various] ELSE [various] ENDIF

+
OrB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] [W] BOOLOR

+
OrD(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] IFDUP NOTIF [T]/[E] ENDIF

+
OrC(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] NOTIF [V] ENDIF

+
OrI(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

IF [various] ELSE [various] ENDIF

+
Thresh(usizeVec<Arc<Miniscript<Pk, Ctx>>>)

[E] ([W] ADD)* k EQUAL

+
Multi(usizeVec<Pk>)

k ()* n CHECKMULTISIG

+

Implementations

impl<Pk, Ctx> Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn translate_pk<FPk, FPkh, Q, Error>(
    &self,
    translatefpk: &mut FPk,
    translatefpkh: &mut FPkh
) -> Result<Terminal<Q, Ctx>, Error> where
    FPk: FnMut(&Pk) -> Result<Q, Error>,
    FPkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, Error>,
    Q: MiniscriptKey

Convert an AST element with one public key type to one of another +public key type .This will panic while converting to +Segwit Miniscript using uncompressed public keys

+

impl<Pk, Ctx> Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey + ToPublicKey

pub fn encode(&self, builder: Builder) -> Builder

Encode the element as a fragment of Bitcoin Script. The inverse +function, from Script to an AST element, is implemented in the +parse module.

+

pub fn script_size(&self) -> usize

Size, in bytes of the script-pubkey. If this Miniscript is used outside +of segwit (e.g. in a bare or P2SH descriptor), this quantity should be +multiplied by 4 to compute the weight.

+

In general, it is not recommended to use this function directly, but +to instead call the corresponding function on a Descriptor, which +will handle the segwit/non-segwit technicalities for you.

+

pub fn max_dissatisfaction_witness_elements(&self) -> Option<usize>

Maximum number of witness elements used to dissatisfy the Miniscript +fragment. Used to estimate the weight of the VarInt that specifies +this number in a serialized transaction.

+

Will panic if the fragment is not an E, W or Ke.

+

pub fn max_dissatisfaction_size(&self, one_cost: usize) -> Option<usize>

Maximum dissatisfaction cost, in bytes, of a Miniscript fragment, +if it is possible to compute this. This function should probably +not ever be used directly. It is called from max_satisfaction_size.

+

Will panic if the fragment is not E, W or Ke

+

pub fn max_satisfaction_witness_elements(&self) -> usize

Maximum number of witness elements used to satisfy the Miniscript +fragment. Used to estimate the weight of the VarInt that specifies +this number in a serialized transaction.

+

This number does not include the witness script itself, so 1 needs +to be added to the final result.

+

pub fn max_satisfaction_size(&self, one_cost: usize) -> usize

Maximum size, in bytes, of a satisfying witness. For Segwit outputs +one_cost should be set to 2, since the number 1 requires two +bytes to encode. For non-segwit outputs one_cost should be set to +1, since OP_1 is available in scriptSigs.

+

In general, it is not recommended to use this function directly, but +to instead call the corresponding function on a Descriptor, which +will handle the segwit/non-segwit technicalities for you.

+

All signatures are assumed to be 73 bytes in size, including the +length prefix (segwit) or push opcode (pre-segwit) and sighash +postfix.

+

This function may panic on misformed Miniscript objects which do not +correspond to semantically sane Scripts. (Such scripts should be rejected +at parse time. Any exceptions are bugs.)

+

Trait Implementations

impl<Pk, Ctx> Clone for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Clone,
    Pk: MiniscriptKey + Clone,
    <Pk as MiniscriptKey>::Hash: Clone

impl<Pk, Ctx> Debug for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Display for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Eq for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Eq,
    Pk: MiniscriptKey + Eq,
    <Pk as MiniscriptKey>::Hash: Eq

impl<Pk, Ctx> FromTree for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

impl<Pk, Ctx> Hash for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Hash,
    Pk: MiniscriptKey + Hash,
    <Pk as MiniscriptKey>::Hash: Hash

impl<Pk, Ctx> Liftable<Pk> for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Ord for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Ord,
    Pk: MiniscriptKey + Ord,
    <Pk as MiniscriptKey>::Hash: Ord

impl<Pk, Ctx> PartialEq<Terminal<Pk, Ctx>> for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + PartialEq<Ctx>,
    Pk: MiniscriptKey + PartialEq<Pk>,
    <Pk as MiniscriptKey>::Hash: PartialEq<<Pk as MiniscriptKey>::Hash>, 

impl<Pk, Ctx> PartialOrd<Terminal<Pk, Ctx>> for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + PartialOrd<Ctx>,
    Pk: MiniscriptKey + PartialOrd<Pk>,
    <Pk as MiniscriptKey>::Hash: PartialOrd<<Pk as MiniscriptKey>::Hash>, 

impl<Pk, Ctx> StructuralEq for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> StructuralPartialEq for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Auto Trait Implementations

impl<Pk, Ctx> RefUnwindSafe for Terminal<Pk, Ctx> where
    Ctx: RefUnwindSafe,
    Pk: RefUnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe

impl<Pk, Ctx> Send for Terminal<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk, Ctx> Sync for Terminal<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk, Ctx> Unpin for Terminal<Pk, Ctx> where
    Pk: Unpin,
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk, Ctx> UnwindSafe for Terminal<Pk, Ctx> where
    Ctx: RefUnwindSafe,
    Pk: RefUnwindSafe + UnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/enum.Error.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/enum.Error.html new file mode 100644 index 0000000000..72553ca2c8 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/enum.Error.html @@ -0,0 +1,45 @@ +bdk::descriptor::error::Error - Rust

[][src]Enum bdk::descriptor::error::Error

pub enum Error {
+    InternalError,
+    InvalidPrefix(Vec<u8>),
+    HardenedDerivationOnXpub,
+    MalformedInput,
+    KeyParsingError(String),
+    Policy(PolicyError),
+    InputIndexDoesntExist,
+    MissingPublicKey,
+    MissingDetails,
+    InvalidDescriptorCharacter(char),
+    CantDeriveWithMiniscript,
+    BIP32(Error),
+    Base58(Error),
+    PK(Error),
+    Miniscript(Error),
+    Hex(Error),
+}

Errors related to the parsing and usage of descriptors

+

+ Variants

+
InternalError
InvalidPrefix(Vec<u8>)
HardenedDerivationOnXpub
MalformedInput
KeyParsingError(String)
Policy(PolicyError)
InputIndexDoesntExist
MissingPublicKey
MissingDetails
InvalidDescriptorCharacter(char)
CantDeriveWithMiniscript
BIP32(Error)
Base58(Error)
PK(Error)
Miniscript(Error)
Hex(Error)

Trait Implementations

impl Debug for Error[src]

impl Display for Error[src]

impl Error for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<PolicyError> for Error[src]

Auto Trait Implementations

impl RefUnwindSafe for Error

impl Send for Error

impl Sync for Error

impl Unpin for Error

impl UnwindSafe for Error

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/index.html new file mode 100644 index 0000000000..3c3a9a8451 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/index.html @@ -0,0 +1,4 @@ +bdk::descriptor::error - Rust

[][src]Module bdk::descriptor::error

Descriptor errors

+

Enums

+
Error

Errors related to the parsing and usage of descriptors

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/sidebar-items.js new file mode 100644 index 0000000000..1ad99d4faf --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Error","Errors related to the parsing and usage of descriptors"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/index.html new file mode 100644 index 0000000000..2bdbcbdb44 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/index.html @@ -0,0 +1,24 @@ +bdk::descriptor - Rust

[][src]Module bdk::descriptor

Descriptors

+

This module contains generic utilities to work with descriptors, plus some re-exported types +from [miniscript].

+

Re-exports

+
pub use self::checksum::get_checksum;
pub use self::policy::Policy;

Modules

+
checksum

Descriptor checksum

+
error

Descriptor errors

+
policy

Descriptor policy

+

Structs

+
Miniscript

Top-level script AST type

+

Enums

+
Descriptor

Script descriptor

+
Legacy

Legacy ScriptContext

+
Segwitv0

Segwitv0 ScriptContext

+
Terminal

All AST elements

+

Traits

+
ExtractPolicy

Trait implemented on [Descriptor]s to add a method to extract the spending [policy]

+
MiniscriptKey

Public key trait which can be converted to Hash type

+
ScriptContext
ToPublicKey

Trait describing public key types which can be converted to bitcoin pubkeys

+

Type Definitions

+
ExtendedDescriptor

Alias for a [Descriptor] that can contain extended keys using [DescriptorPublicKey]

+
HDKeyPaths

Alias for the type of maps that represent derivation paths in a psbt::Input or +psbt::Output

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.PolicyError.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.PolicyError.html new file mode 100644 index 0000000000..0246f20cce --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.PolicyError.html @@ -0,0 +1,31 @@ +bdk::descriptor::policy::PolicyError - Rust

[][src]Enum bdk::descriptor::policy::PolicyError

pub enum PolicyError {
+    NotEnoughItemsSelected(String),
+    TooManyItemsSelected(String),
+    IndexOutOfRange(usize),
+    AddOnLeaf,
+    AddOnPartialComplete,
+    MixedTimelockUnits,
+    IncompatibleConditions,
+}

Errors that can happen while extracting and manipulating policies

+

+ Variants

+
NotEnoughItemsSelected(String)
TooManyItemsSelected(String)
IndexOutOfRange(usize)
AddOnLeaf
AddOnPartialComplete
MixedTimelockUnits
IncompatibleConditions

Trait Implementations

impl Debug for PolicyError[src]

impl Display for PolicyError[src]

impl Error for PolicyError[src]

impl From<PolicyError> for Error[src]

impl From<PolicyError> for Error[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.Satisfaction.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.Satisfaction.html new file mode 100644 index 0000000000..e62db9d51f --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.Satisfaction.html @@ -0,0 +1,52 @@ +bdk::descriptor::policy::Satisfaction - Rust

[][src]Enum bdk::descriptor::policy::Satisfaction

pub enum Satisfaction {
+    Partial {
+        n: usize,
+        m: usize,
+        items: Vec<usize>,
+        conditions: ConditionMap,
+    },
+    PartialComplete {
+        n: usize,
+        m: usize,
+        items: Vec<usize>,
+        conditions: FoldedConditionMap,
+    },
+    Complete {
+        condition: Condition,
+    },
+    None,
+}

Represent if and how much a policy item is satisfied by the wallet's descriptor

+

+ Variants

+
Partial

Only a partial satisfaction of some kind of threshold policy

+

Fields of Partial

n: usize

Total number of items

+
m: usize

Threshold

+
items: Vec<usize>

The items that can be satisfied by the descriptor

+
conditions: ConditionMap

Extra conditions that also need to be satisfied

+
PartialComplete

Can reach the threshold of some kind of threshold policy

+

Fields of PartialComplete

n: usize

Total number of items

+
m: usize

Threshold

+
items: Vec<usize>

The items that can be satisfied by the descriptor

+
conditions: FoldedConditionMap

Extra conditions that also need to be satisfied

+
Complete

Can satisfy the policy item

+

Fields of Complete

condition: Condition

Extra conditions that also need to be satisfied

+
None

Cannot satisfy or contribute to the policy item

+

Implementations

impl Satisfaction[src]

pub fn is_leaf(&self) -> bool[src]

Trait Implementations

impl Clone for Satisfaction[src]

impl Debug for Satisfaction[src]

impl From<bool> for Satisfaction[src]

impl Serialize for Satisfaction[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.SatisfiableItem.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.SatisfiableItem.html new file mode 100644 index 0000000000..7e27c014ca --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.SatisfiableItem.html @@ -0,0 +1,51 @@ +bdk::descriptor::policy::SatisfiableItem - Rust

[][src]Enum bdk::descriptor::policy::SatisfiableItem

pub enum SatisfiableItem {
+    Signature(PKOrF),
+    SignatureKey(PKOrF),
+    SHA256Preimage {
+        hash: Hash,
+    },
+    HASH256Preimage {
+        hash: Hash,
+    },
+    RIPEMD160Preimage {
+        hash: Hash,
+    },
+    HASH160Preimage {
+        hash: Hash,
+    },
+    AbsoluteTimelock {
+        value: u32,
+    },
+    RelativeTimelock {
+        value: u32,
+    },
+    Thresh {
+        items: Vec<Policy>,
+        threshold: usize,
+    },
+    Multisig {
+        keys: Vec<PKOrF>,
+        threshold: usize,
+    },
+}

An item that need to be satisfied

+

+ Variants

+
Signature(PKOrF)
SignatureKey(PKOrF)
SHA256Preimage

Fields of SHA256Preimage

hash: Hash
HASH256Preimage

Fields of HASH256Preimage

hash: Hash
RIPEMD160Preimage

Fields of RIPEMD160Preimage

hash: Hash
HASH160Preimage

Fields of HASH160Preimage

hash: Hash
AbsoluteTimelock

Fields of AbsoluteTimelock

value: u32
RelativeTimelock

Fields of RelativeTimelock

value: u32
Thresh

Fields of Thresh

items: Vec<Policy>threshold: usize
Multisig

Fields of Multisig

keys: Vec<PKOrF>threshold: usize

Implementations

impl SatisfiableItem[src]

pub fn is_leaf(&self) -> bool[src]

pub fn id(&self) -> String[src]

Trait Implementations

impl Clone for SatisfiableItem[src]

impl Debug for SatisfiableItem[src]

impl From<SatisfiableItem> for Policy[src]

impl Serialize for SatisfiableItem[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/index.html new file mode 100644 index 0000000000..f494586dc6 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/index.html @@ -0,0 +1,23 @@ +bdk::descriptor::policy - Rust

[][src]Module bdk::descriptor::policy

Descriptor policy

+

This module implements the logic to extract and represent the spending policies of a descriptor +in a more human-readable format.

+

Example

+
+let desc = "wsh(and_v(v:pk(cV3oCth6zxZ1UVsHLnGothsWNsaoxRhC6aeNi5VbSdFpwUkgkEci),or_d(pk(cVMTy7uebJgvFaSBwcgvwk8qn8xSLc97dKow4MBetjrrahZoimm2),older(12960))))";
+
+let (extended_desc, key_map) = ExtendedDescriptor::parse_secret(desc)?;
+println!("{:?}", extended_desc);
+
+let signers = Arc::new(key_map.into());
+let policy = extended_desc.extract_policy(signers)?;
+println!("policy: {}", serde_json::to_string(&policy)?);
+

Structs

+
Condition

An extra condition that must be satisfied but that is out of control of the user

+
PKOrF

Raw public key or extended key fingerprint

+
Policy

Descriptor spending policy

+

Enums

+
PolicyError

Errors that can happen while extracting and manipulating policies

+
Satisfaction

Represent if and how much a policy item is satisfied by the wallet's descriptor

+
SatisfiableItem

An item that need to be satisfied

+

Type Definitions

+
ConditionMap
FoldedConditionMap
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/sidebar-items.js new file mode 100644 index 0000000000..6928dca21e --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["PolicyError","Errors that can happen while extracting and manipulating policies"],["Satisfaction","Represent if and how much a policy item is satisfied by the wallet's descriptor"],["SatisfiableItem","An item that need to be satisfied"]],"struct":[["Condition","An extra condition that must be satisfied but that is out of control of the user"],["PKOrF","Raw public key or extended key fingerprint"],["Policy","Descriptor spending policy"]],"type":[["ConditionMap",""],["FoldedConditionMap",""]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Condition.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Condition.html new file mode 100644 index 0000000000..4aa736ab3b --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Condition.html @@ -0,0 +1,38 @@ +bdk::descriptor::policy::Condition - Rust

[][src]Struct bdk::descriptor::policy::Condition

pub struct Condition {
+    pub csv: Option<u32>,
+    pub timelock: Option<u32>,
+}

An extra condition that must be satisfied but that is out of control of the user

+

+ Fields

csv: Option<u32>timelock: Option<u32>

Implementations

impl Condition[src]

pub fn is_null(&self) -> bool[src]

Trait Implementations

impl Clone for Condition[src]

impl Copy for Condition[src]

impl Debug for Condition[src]

impl Default for Condition[src]

impl Eq for Condition[src]

impl Hash for Condition[src]

impl Ord for Condition[src]

impl PartialEq<Condition> for Condition[src]

impl PartialOrd<Condition> for Condition[src]

impl Serialize for Condition[src]

impl StructuralEq for Condition[src]

impl StructuralPartialEq for Condition[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.PKOrF.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.PKOrF.html new file mode 100644 index 0000000000..af271a9b11 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.PKOrF.html @@ -0,0 +1,20 @@ +bdk::descriptor::policy::PKOrF - Rust

[][src]Struct bdk::descriptor::policy::PKOrF

pub struct PKOrF { /* fields omitted */ }

Raw public key or extended key fingerprint

+

Trait Implementations

impl Clone for PKOrF[src]

impl Debug for PKOrF[src]

impl Default for PKOrF[src]

impl Serialize for PKOrF[src]

Auto Trait Implementations

impl RefUnwindSafe for PKOrF

impl Send for PKOrF

impl Sync for PKOrF

impl Unpin for PKOrF

impl UnwindSafe for PKOrF

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Policy.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Policy.html new file mode 100644 index 0000000000..1151e37bf5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Policy.html @@ -0,0 +1,37 @@ +bdk::descriptor::policy::Policy - Rust

[][src]Struct bdk::descriptor::policy::Policy

pub struct Policy {
+    pub id: String,
+    pub item: SatisfiableItem,
+    pub satisfaction: Satisfaction,
+    pub contribution: Satisfaction,
+}

Descriptor spending policy

+

+ Fields

id: String

Identifier for this policy node

+
item: SatisfiableItem

Type of this policy node

+
satisfaction: Satisfaction

How a much given PSBT already satisfies this polcy node (currently unused)

+
contribution: Satisfaction

How the wallet's descriptor can satisfy this policy node

+

Implementations

impl Policy[src]

pub fn requires_path(&self) -> bool[src]

Return whether or not a specific path in the policy tree is required to unambiguously +create a transaction

+

What this means is that for some spending policies the user should select which paths in +the tree it intends to satisfy while signing, because the transaction must be created differently based +on that.

+

pub fn get_condition(
    &self,
    path: &BTreeMap<String, Vec<usize>>
) -> Result<Condition, PolicyError>
[src]

Return the conditions that are set by the spending policy for a given path in the +policy tree

+

Trait Implementations

impl Clone for Policy[src]

impl Debug for Policy[src]

impl From<SatisfiableItem> for Policy[src]

impl Serialize for Policy[src]

Auto Trait Implementations

impl RefUnwindSafe for Policy

impl Send for Policy

impl Sync for Policy

impl Unpin for Policy

impl UnwindSafe for Policy

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.ConditionMap.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.ConditionMap.html new file mode 100644 index 0000000000..33b5632c7b --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.ConditionMap.html @@ -0,0 +1 @@ +bdk::descriptor::policy::ConditionMap - Rust

[][src]Type Definition bdk::descriptor::policy::ConditionMap

type ConditionMap = BTreeMap<usize, HashSet<Condition>>;
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.FoldedConditionMap.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.FoldedConditionMap.html new file mode 100644 index 0000000000..ac1cee86e6 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.FoldedConditionMap.html @@ -0,0 +1 @@ +bdk::descriptor::policy::FoldedConditionMap - Rust

[][src]Type Definition bdk::descriptor::policy::FoldedConditionMap

type FoldedConditionMap = BTreeMap<Vec<usize>, HashSet<Condition>>;
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/sidebar-items.js new file mode 100644 index 0000000000..8460b2d5c8 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Descriptor","Script descriptor"],["Legacy","Legacy ScriptContext"],["Segwitv0","Segwitv0 ScriptContext"],["Terminal","All AST elements"]],"mod":[["checksum","Descriptor checksum"],["error","Descriptor errors"],["policy","Descriptor policy"]],"struct":[["Miniscript","Top-level script AST type"]],"trait":[["ExtractPolicy","Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]"],["MiniscriptKey","Public key trait which can be converted to Hash type"],["ScriptContext",""],["ToPublicKey","Trait describing public key types which can be converted to bitcoin pubkeys"]],"type":[["ExtendedDescriptor","Alias for a [`Descriptor`] that can contain extended keys using [`DescriptorPublicKey`]"],["HDKeyPaths","Alias for the type of maps that represent derivation paths in a [`psbt::Input`] or [`psbt::Output`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/struct.Miniscript.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/struct.Miniscript.html new file mode 100644 index 0000000000..a1b8820683 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/struct.Miniscript.html @@ -0,0 +1,97 @@ +bdk::descriptor::Miniscript - Rust

[]Struct bdk::descriptor::Miniscript

pub struct Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey
{ + pub node: Terminal<Pk, Ctx>, + pub ty: Type, + pub ext: ExtData, + // some fields omitted +}

Top-level script AST type

+

+ Fields

node: Terminal<Pk, Ctx>

A node in the Abstract Syntax Tree(

+
ty: Type

The correctness and malleability type information for the AST node

+
ext: ExtData

Additional information helpful for extra analysis.

+

Implementations

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn from_ast(t: Terminal<Pk, Ctx>) -> Result<Miniscript<Pk, Ctx>, Error>

Add type information(Type and Extdata) to Miniscript based on +AstElem fragment. Dependent on display and clone because of Error +Display code of type_check.

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn into_inner(self) -> Terminal<Pk, Ctx>

Extracts the AstElem representing the root of the miniscript

+

pub fn as_inner(&self) -> &Terminal<Pk, Ctx>

impl<Ctx> Miniscript<PublicKey, Ctx> where
    Ctx: ScriptContext

pub fn parse(script: &Script) -> Result<Miniscript<PublicKey, Ctx>, Error>

Attempt to parse a script into a Miniscript representation

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey + ToPublicKey

pub fn encode(&self) -> Script

Encode as a Bitcoin script

+

pub fn script_size(&self) -> usize

Size, in bytes of the script-pubkey. If this Miniscript is used outside +of segwit (e.g. in a bare or P2SH descriptor), this quantity should be +multiplied by 4 to compute the weight.

+

In general, it is not recommended to use this function directly, but +to instead call the corresponding function on a Descriptor, which +will handle the segwit/non-segwit technicalities for you.

+

pub fn max_satisfaction_witness_elements(&self) -> usize

Maximum number of witness elements used to satisfy the Miniscript +fragment, including the witness script itself. Used to estimate +the weight of the VarInt that specifies this number in a serialized +transaction.

+

This function may panic on misformed Miniscript objects which do +not correspond to semantically sane Scripts. (Such scripts should be +rejected at parse time. Any exceptions are bugs.)

+

pub fn max_satisfaction_size(&self, one_cost: usize) -> usize

Maximum size, in bytes, of a satisfying witness. For Segwit outputs +one_cost should be set to 2, since the number 1 requires two +bytes to encode. For non-segwit outputs one_cost should be set to +1, since OP_1 is available in scriptSigs.

+

In general, it is not recommended to use this function directly, but +to instead call the corresponding function on a Descriptor, which +will handle the segwit/non-segwit technicalities for you.

+

All signatures are assumed to be 73 bytes in size, including the +length prefix (segwit) or push opcode (pre-segwit) and sighash +postfix.

+

This function may panic on misformed Miniscript objects which do not +correspond to semantically sane Scripts. (Such scripts should be +rejected at parse time. Any exceptions are bugs.)

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn translate_pk<FPk, FPkh, Q, FuncError>(
    &self,
    translatefpk: &mut FPk,
    translatefpkh: &mut FPkh
) -> Result<Miniscript<Q, Ctx>, FuncError> where
    FPk: FnMut(&Pk) -> Result<Q, FuncError>,
    FPkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, FuncError>,
    Q: MiniscriptKey

This will panic if translatefpk returns an uncompressed key when +converting to a Segwit descriptor. To prevent this panic, ensure +translatefpk returns an error in this case instead.

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey + ToPublicKey

pub fn satisfy<S>(&self, satisfier: S) -> Option<Vec<Vec<u8>>> where
    S: Satisfier<Pk>, 

Attempt to produce a satisfying witness for the +witness script represented by the parse tree

+

Trait Implementations

impl<Pk, Ctx> Clone for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext + Clone,
    Pk: MiniscriptKey + Clone

impl<Pk, Ctx> Debug for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Display for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Eq for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Eq of Miniscript must depend only on node and not the type information. +The type information and extra_properties can be deterministically determined +by the ast.

+

impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>[src]

impl<Pk, Ctx> FromStr for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

type Err = Error

The associated error which can be returned from parsing.

+

impl<Pk, Ctx> FromTree for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

fn from_tree(top: &Tree) -> Result<Miniscript<Pk, Ctx>, Error>

Parse an expression tree into a Miniscript. As a general rule, this +should not be called directly; rather go through the descriptor API.

+

impl<Pk, Ctx> Hash for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext + Hash,
    Pk: MiniscriptKey + Hash

impl<Pk, Ctx> Liftable<Pk> for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Ord for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Ord of Miniscript must depend only on node and not the type information. +The type information and extra_properties can be deterministically determined +by the ast.

+

impl<Pk, Ctx> PartialEq<Miniscript<Pk, Ctx>> for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

PartialEq of Miniscript must depend only on node and not the type information. +The type information and extra_properties can be deterministically determined +by the ast.

+

impl<Pk, Ctx> PartialOrd<Miniscript<Pk, Ctx>> for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

PartialOrd of Miniscript must depend only on node and not the type information. +The type information and extra_properties can be deterministically determined +by the ast.

+

Auto Trait Implementations

impl<Pk, Ctx> RefUnwindSafe for Miniscript<Pk, Ctx> where
    Ctx: RefUnwindSafe,
    Pk: RefUnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe

impl<Pk, Ctx> Send for Miniscript<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk, Ctx> Sync for Miniscript<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk, Ctx> Unpin for Miniscript<Pk, Ctx> where
    Ctx: Unpin,
    Pk: Unpin,
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk, Ctx> UnwindSafe for Miniscript<Pk, Ctx> where
    Ctx: RefUnwindSafe + UnwindSafe,
    Pk: RefUnwindSafe + UnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ExtractPolicy.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ExtractPolicy.html new file mode 100644 index 0000000000..74215f7434 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ExtractPolicy.html @@ -0,0 +1,6 @@ +bdk::descriptor::ExtractPolicy - Rust

[][src]Trait bdk::descriptor::ExtractPolicy

pub trait ExtractPolicy {
+    fn extract_policy(
        &self,
        signers: Arc<SignersContainer<DescriptorPublicKey>>
    ) -> Result<Option<Policy>, Error>; +}

Trait implemented on [Descriptor]s to add a method to extract the spending [policy]

+
+

Required methods

fn extract_policy(
    &self,
    signers: Arc<SignersContainer<DescriptorPublicKey>>
) -> Result<Option<Policy>, Error>

Loading content... +

Implementors

impl ExtractPolicy for Descriptor<DescriptorPublicKey>[src]

impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>[src]

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.MiniscriptKey.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.MiniscriptKey.html new file mode 100644 index 0000000000..19a9329fdc --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.MiniscriptKey.html @@ -0,0 +1,18 @@ +bdk::descriptor::MiniscriptKey - Rust

[]Trait bdk::descriptor::MiniscriptKey

pub trait MiniscriptKey: Clone + Eq + Ord + Debug + Display + Hash + FromStr {
+    type Hash: Clone + Eq + Ord + Debug + Display + Hash + FromStr;
+    fn to_pubkeyhash(&self) -> Self::Hash;
+
+    fn is_uncompressed(&self) -> bool { ... }
+}

Public key trait which can be converted to Hash type

+
+

Associated Types

type Hash: Clone + Eq + Ord + Debug + Display + Hash + FromStr

The associated Hash type with the publicKey

+
Loading content... +

Required methods

fn to_pubkeyhash(&self) -> Self::Hash

Converts an object to PublicHash

+
Loading content... +

Provided methods

fn is_uncompressed(&self) -> bool

Check if the publicKey is uncompressed. The default +implementation returns false

+
Loading content... +

Implementations on Foreign Types

impl MiniscriptKey for DummyKey

type Hash = DummyKeyHash

impl MiniscriptKey for String

impl MiniscriptKey for PublicKey

fn is_uncompressed(&self) -> bool

is_uncompressed returns true only for +bitcoin::Publickey type if the underlying key is uncompressed.

+

type Hash = Hash

impl MiniscriptKey for DescriptorPublicKey

type Hash = Hash

Loading content... +

Implementors

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ScriptContext.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ScriptContext.html new file mode 100644 index 0000000000..512fe4af1b --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ScriptContext.html @@ -0,0 +1,19 @@ +bdk::descriptor::ScriptContext - Rust

[]Trait bdk::descriptor::ScriptContext

pub trait ScriptContext: Sealed + Clone + PartialEq<Self> + Eq + Ord + PartialOrd<Self> + Debug {
+    fn check_frag_non_malleable<Pk, Ctx>(
        _frag: &Terminal<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
; +
fn check_frag_validity<Pk, Ctx>(
        _frag: &Terminal<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
; +}
+

Required methods

fn check_frag_non_malleable<Pk, Ctx>(
    _frag: &Terminal<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Depending on ScriptContext, fragments can be malleable. For Example, +under Legacy context, PkH is malleable because it is possible to +estimate the cost of satisfaction because of compressed keys +This is currently only used in compiler code for removing malleable +compilations. +This does NOT recursively check if the children of the fragment are +valid or not. Since the compilation proceeds in a leaf to root fashion, +a recursive check is unnecessary.

+

fn check_frag_validity<Pk, Ctx>(
    _frag: &Terminal<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Depending on script Context, some of the Terminals might not be valid. +For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey +uncompressed public keys are non-standard and thus invalid. +Post Tapscript upgrade, this would have to consider other nodes. +This does not recursively check

+
Loading content... +

Implementors

impl ScriptContext for Legacy

impl ScriptContext for Segwitv0

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ToPublicKey.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ToPublicKey.html new file mode 100644 index 0000000000..c799b12de8 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ToPublicKey.html @@ -0,0 +1,19 @@ +bdk::descriptor::ToPublicKey - Rust

[]Trait bdk::descriptor::ToPublicKey

pub trait ToPublicKey: MiniscriptKey {
+    fn to_public_key(&self) -> PublicKey;
+
fn hash_to_hash160(hash: &Self::Hash) -> Hash; + + fn serialized_len(&self) -> usize { ... } +}

Trait describing public key types which can be converted to bitcoin pubkeys

+
+

Required methods

fn to_public_key(&self) -> PublicKey

Converts an object to a public key

+

fn hash_to_hash160(hash: &Self::Hash) -> Hash

Converts a hashed version of the public key to a hash160 hash.

+

This method must be consistent with to_public_key, in the sense +that calling MiniscriptKey::to_pubkeyhash followed by this function +should give the same result as calling to_public_key and hashing +the result directly.

+
Loading content... +

Provided methods

fn serialized_len(&self) -> usize

Computes the size of a public key when serialized in a script, +including the length bytes

+
Loading content... +

Implementations on Foreign Types

impl ToPublicKey for PublicKey

impl ToPublicKey for DescriptorPublicKey

impl ToPublicKey for DummyKey

Loading content... +

Implementors

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.ExtendedDescriptor.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.ExtendedDescriptor.html new file mode 100644 index 0000000000..1f60bc989e --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.ExtendedDescriptor.html @@ -0,0 +1,2 @@ +bdk::descriptor::ExtendedDescriptor - Rust

[][src]Type Definition bdk::descriptor::ExtendedDescriptor

type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;

Alias for a [Descriptor] that can contain extended keys using [DescriptorPublicKey]

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.HDKeyPaths.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.HDKeyPaths.html new file mode 100644 index 0000000000..93e0240143 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.HDKeyPaths.html @@ -0,0 +1,3 @@ +bdk::descriptor::HDKeyPaths - Rust

[][src]Type Definition bdk::descriptor::HDKeyPaths

type HDKeyPaths = BTreeMap<PublicKey, (Fingerprint, DerivationPath)>;

Alias for the type of maps that represent derivation paths in a psbt::Input or +psbt::Output

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/enum.Error.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/enum.Error.html new file mode 100644 index 0000000000..cdd9814f75 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/enum.Error.html @@ -0,0 +1,80 @@ +bdk::Error - Rust

[][src]Enum bdk::Error

pub enum Error {
+    KeyMismatch(PublicKey, PublicKey),
+    MissingInputUTXO(usize),
+    InvalidU32Bytes(Vec<u8>),
+    Generic(String),
+    ScriptDoesntHaveAddressForm,
+    SendAllMultipleOutputs,
+    NoAddressees,
+    OutputBelowDustLimit(usize),
+    InsufficientFunds,
+    InvalidAddressNetwork(Address),
+    UnknownUTXO,
+    DifferentTransactions,
+    TransactionNotFound,
+    TransactionConfirmed,
+    IrreplaceableTransaction,
+    FeeRateTooLow {
+        required: FeeRate,
+    },
+    ChecksumMismatch,
+    DifferentDescriptorStructure,
+    SpendingPolicyRequired,
+    InvalidPolicyPathError(PolicyError),
+    Signer(SignerError),
+    Uncapable(Capability),
+    OfflineClient,
+    InvalidProgressValue(f32),
+    ProgressUpdateError,
+    MissingCachedAddresses,
+    InvalidOutpoint(OutPoint),
+    Descriptor(Error),
+    AddressValidator(AddressValidatorError),
+    Encode(Error),
+    Miniscript(Error),
+    BIP32(Error),
+    Secp256k1(Error),
+    JSON(Error),
+    Hex(Error),
+    PSBT(Error),
+    Electrum(Error),
+    Esplora(EsploraError),
+    CompactFilters(CompactFiltersError),
+    Sled(Error),
+}

Errors that can be thrown by the Wallet

+

+ Variants

+
KeyMismatch(PublicKey, PublicKey)
MissingInputUTXO(usize)
InvalidU32Bytes(Vec<u8>)
Generic(String)
ScriptDoesntHaveAddressForm
SendAllMultipleOutputs
NoAddressees
OutputBelowDustLimit(usize)
InsufficientFunds
InvalidAddressNetwork(Address)
UnknownUTXO
DifferentTransactions
TransactionNotFound
TransactionConfirmed
IrreplaceableTransaction
FeeRateTooLow

Fields of FeeRateTooLow

required: FeeRate
ChecksumMismatch
DifferentDescriptorStructure
SpendingPolicyRequired
InvalidPolicyPathError(PolicyError)
Signer(SignerError)
Uncapable(Capability)
OfflineClient
InvalidProgressValue(f32)
ProgressUpdateError
MissingCachedAddresses
InvalidOutpoint(OutPoint)
Descriptor(Error)
AddressValidator(AddressValidatorError)
Encode(Error)
Miniscript(Error)
BIP32(Error)
Secp256k1(Error)
JSON(Error)
Hex(Error)
PSBT(Error)
Electrum(Error)
Esplora(EsploraError)
CompactFilters(CompactFiltersError)
Sled(Error)

Trait Implementations

impl Debug for Error[src]

impl Display for Error[src]

impl Error for Error[src]

impl From<AddressValidatorError> for Error[src]

impl From<CompactFiltersError> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<EsploraError> for Error[src]

impl From<PolicyError> for Error[src]

impl From<SignerError> for Error[src]

Auto Trait Implementations

impl !RefUnwindSafe for Error

impl Send for Error

impl Sync for Error

impl Unpin for Error

impl !UnwindSafe for Error

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/enum.ScriptType.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/enum.ScriptType.html new file mode 100644 index 0000000000..2765268c94 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/enum.ScriptType.html @@ -0,0 +1,36 @@ +bdk::ScriptType - Rust

[][src]Enum bdk::ScriptType

pub enum ScriptType {
+    External,
+    Internal,
+}

Types of script

+

+ Variants

+
External
Internal

Implementations

impl ScriptType[src]

pub fn as_byte(&self) -> u8[src]

pub fn is_internal(&self) -> bool[src]

Trait Implementations

impl AsRef<[u8]> for ScriptType[src]

impl Clone for ScriptType[src]

impl Copy for ScriptType[src]

impl Debug for ScriptType[src]

impl<'de> Deserialize<'de> for ScriptType[src]

impl Eq for ScriptType[src]

impl Hash for ScriptType[src]

impl PartialEq<ScriptType> for ScriptType[src]

impl Serialize for ScriptType[src]

impl StructuralEq for ScriptType[src]

impl StructuralPartialEq for ScriptType[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Base32Len for T where
    T: AsRef<[u8]>, 

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<'f, T> CheckBase32<Vec<u5>> for T where
    T: AsRef<[u8]>, 

type Err = Error

Error type if conversion fails

+

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToBase32 for T where
    T: AsRef<[u8]>, 

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/error/enum.Error.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/error/enum.Error.html new file mode 100644 index 0000000000..113a951037 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/error/enum.Error.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/enum.Error.html...

+ + + \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/index.html new file mode 100644 index 0000000000..750a8ef4a8 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/index.html @@ -0,0 +1,14 @@ +bdk - Rust

[][src]Crate bdk

Re-exports

+
pub extern crate bitcoin;
pub extern crate miniscript;
pub extern crate electrum_client;
pub extern crate reqwest;
pub extern crate sled;
pub use descriptor::HDKeyPaths;
pub use wallet::address_validator;
pub use wallet::signer;
pub use wallet::tx_builder::TxBuilder;
pub use wallet::OfflineWallet;
pub use wallet::Wallet;

Modules

+
blockchain

Blockchain backends

+
database

Database types

+
descriptor

Descriptors

+
wallet

Wallet

+

Structs

+
FeeRate

Fee rate

+
TransactionDetails

A wallet transaction

+
UTXO

A wallet unspent output

+

Enums

+
Error

Errors that can be thrown by the Wallet

+
ScriptType

Types of script

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/sidebar-items.js new file mode 100644 index 0000000000..9e94a707e4 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Error","Errors that can be thrown by the `Wallet`"],["ScriptType","Types of script"]],"mod":[["blockchain","Blockchain backends"],["database","Database types"],["descriptor","Descriptors"],["wallet","Wallet"]],"struct":[["FeeRate","Fee rate"],["TransactionDetails","A wallet transaction"],["UTXO","A wallet unspent output"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.FeeRate.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.FeeRate.html new file mode 100644 index 0000000000..44ddc154fe --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.FeeRate.html @@ -0,0 +1,30 @@ +bdk::FeeRate - Rust

[][src]Struct bdk::FeeRate

pub struct FeeRate(_);

Fee rate

+

Implementations

impl FeeRate[src]

pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self[src]

Create a new instance of [FeeRate] given a float fee rate in btc/kvbytes

+

pub fn from_sat_per_vb(sat_per_vb: f32) -> Self[src]

Create a new instance of [FeeRate] given a float fee rate in satoshi/vbyte

+

pub fn default_min_relay_fee() -> Self[src]

Create a new [FeeRate] with the default min relay fee value

+

pub fn as_sat_vb(&self) -> f32[src]

Return the value as satoshi/vbyte

+

Trait Implementations

impl Clone for FeeRate[src]

impl Copy for FeeRate[src]

impl Debug for FeeRate[src]

impl Default for FeeRate[src]

impl PartialEq<FeeRate> for FeeRate[src]

impl PartialOrd<FeeRate> for FeeRate[src]

impl StructuralPartialEq for FeeRate[src]

Auto Trait Implementations

impl RefUnwindSafe for FeeRate

impl Send for FeeRate

impl Sync for FeeRate

impl Unpin for FeeRate

impl UnwindSafe for FeeRate

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.TransactionDetails.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.TransactionDetails.html new file mode 100644 index 0000000000..805445ce1f --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.TransactionDetails.html @@ -0,0 +1,33 @@ +bdk::TransactionDetails - Rust

[][src]Struct bdk::TransactionDetails

pub struct TransactionDetails {
+    pub transaction: Option<Transaction>,
+    pub txid: Txid,
+    pub timestamp: u64,
+    pub received: u64,
+    pub sent: u64,
+    pub fees: u64,
+    pub height: Option<u32>,
+}

A wallet transaction

+

+ Fields

transaction: Option<Transaction>txid: Txidtimestamp: u64received: u64sent: u64fees: u64height: Option<u32>

Trait Implementations

impl Clone for TransactionDetails[src]

impl Debug for TransactionDetails[src]

impl Default for TransactionDetails[src]

impl<'de> Deserialize<'de> for TransactionDetails[src]

impl Eq for TransactionDetails[src]

impl PartialEq<TransactionDetails> for TransactionDetails[src]

impl Serialize for TransactionDetails[src]

impl StructuralEq for TransactionDetails[src]

impl StructuralPartialEq for TransactionDetails[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.UTXO.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.UTXO.html new file mode 100644 index 0000000000..6c7b7583ec --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.UTXO.html @@ -0,0 +1,28 @@ +bdk::UTXO - Rust

[][src]Struct bdk::UTXO

pub struct UTXO {
+    pub outpoint: OutPoint,
+    pub txout: TxOut,
+    pub is_internal: bool,
+}

A wallet unspent output

+

+ Fields

outpoint: OutPointtxout: TxOutis_internal: bool

Trait Implementations

impl Clone for UTXO[src]

impl Debug for UTXO[src]

impl<'de> Deserialize<'de> for UTXO[src]

impl Eq for UTXO[src]

impl PartialEq<UTXO> for UTXO[src]

impl Serialize for UTXO[src]

impl StructuralEq for UTXO[src]

impl StructuralPartialEq for UTXO[src]

Auto Trait Implementations

impl RefUnwindSafe for UTXO

impl Send for UTXO

impl Sync for UTXO

impl Unpin for UTXO

impl UnwindSafe for UTXO

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/enum.ScriptType.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/enum.ScriptType.html new file mode 100644 index 0000000000..b10e9a3fe6 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/enum.ScriptType.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/enum.ScriptType.html...

+ + + \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.FeeRate.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.FeeRate.html new file mode 100644 index 0000000000..c8b0ec4f98 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.FeeRate.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/struct.FeeRate.html...

+ + + \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.TransactionDetails.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.TransactionDetails.html new file mode 100644 index 0000000000..5db5e06868 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.TransactionDetails.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/struct.TransactionDetails.html...

+ + + \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.UTXO.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.UTXO.html new file mode 100644 index 0000000000..1517bb40f5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.UTXO.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/struct.UTXO.html...

+ + + \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/enum.AddressValidatorError.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/enum.AddressValidatorError.html new file mode 100644 index 0000000000..1214d2bcdc --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/enum.AddressValidatorError.html @@ -0,0 +1,37 @@ +bdk::wallet::address_validator::AddressValidatorError - Rust

[][src]Enum bdk::wallet::address_validator::AddressValidatorError

pub enum AddressValidatorError {
+    UserRejected,
+    ConnectionError,
+    TimeoutError,
+    InvalidScript,
+    Message(String),
+}

Errors that can be returned to fail the validation of an address

+

+ Variants

+
UserRejected
ConnectionError
TimeoutError
InvalidScript
Message(String)

Trait Implementations

impl Clone for AddressValidatorError[src]

impl Debug for AddressValidatorError[src]

impl Display for AddressValidatorError[src]

impl Eq for AddressValidatorError[src]

impl Error for AddressValidatorError[src]

impl From<AddressValidatorError> for Error[src]

impl PartialEq<AddressValidatorError> for AddressValidatorError[src]

impl StructuralEq for AddressValidatorError[src]

impl StructuralPartialEq for AddressValidatorError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/index.html new file mode 100644 index 0000000000..9393f2927f --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/index.html @@ -0,0 +1,44 @@ +bdk::wallet::address_validator - Rust

[][src]Module bdk::wallet::address_validator

Address validation callbacks

+

The typical usage of those callbacks is for displaying the newly-generated address on a +hardware wallet, so that the user can cross-check its correctness.

+

More generally speaking though, these callbacks can also be used to "do something" every time +an address is generated, without necessarily checking or validating it.

+

An address validator can be attached to a Wallet by using the +Wallet::add_address_validator method, and +whenever a new address is generated (either explicitly by the user with +Wallet::get_new_address or internally to create a change +address) all the attached validators will be polled, in sequence. All of them must complete +successfully to continue.

+

Example

+
+struct PrintAddressAndContinue;
+
+impl AddressValidator for PrintAddressAndContinue {
+    fn validate(
+        &self,
+        script_type: ScriptType,
+        hd_keypaths: &HDKeyPaths,
+        script: &Script
+    ) -> Result<(), AddressValidatorError> {
+        let address = Address::from_script(script, Network::Testnet)
+            .as_ref()
+            .map(Address::to_string)
+            .unwrap_or(script.to_string());
+        println!("New address of type {:?}: {}", script_type, address);
+        println!("HD keypaths: {:#?}", hd_keypaths);
+
+        Ok(())
+    }
+}
+
+let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+wallet.add_address_validator(Arc::new(Box::new(PrintAddressAndContinue)));
+
+let address = wallet.get_new_address()?;
+println!("Address: {}", address);
+

Enums

+
AddressValidatorError

Errors that can be returned to fail the validation of an address

+

Traits

+
AddressValidator

Trait to build address validators

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/sidebar-items.js new file mode 100644 index 0000000000..58959ba340 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["AddressValidatorError","Errors that can be returned to fail the validation of an address"]],"trait":[["AddressValidator","Trait to build address validators"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/trait.AddressValidator.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/trait.AddressValidator.html new file mode 100644 index 0000000000..8e76d6be2a --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/trait.AddressValidator.html @@ -0,0 +1,11 @@ +bdk::wallet::address_validator::AddressValidator - Rust

[][src]Trait bdk::wallet::address_validator::AddressValidator

pub trait AddressValidator {
+    fn validate(
        &self,
        script_type: ScriptType,
        hd_keypaths: &HDKeyPaths,
        script: &Script
    ) -> Result<(), AddressValidatorError>; +}

Trait to build address validators

+

All the address validators attached to a wallet with Wallet::add_address_validator will be polled +every time an address (external or internal) is generated by the wallet. Errors returned in the +validator will be propagated up to the original caller that triggered the address generation.

+

For a usage example see this module's documentation.

+
+

Required methods

fn validate(
    &self,
    script_type: ScriptType,
    hd_keypaths: &HDKeyPaths,
    script: &Script
) -> Result<(), AddressValidatorError>

Validate or inspect an address

+
Loading content... +

Implementors

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/index.html new file mode 100644 index 0000000000..7f859804f5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/index.html @@ -0,0 +1,73 @@ +bdk::wallet::coin_selection - Rust

[][src]Module bdk::wallet::coin_selection

Coin selection

+

This module provides the trait [CoinSelectionAlgorithm] that can be implemented to +define custom coin selection algorithms.

+

The coin selection algorithm is not globally part of a Wallet, instead it +is selected whenever a Wallet::create_tx call is made, through +the use of the TxBuilder structure, specifically with +TxBuilder::coin_selection method.

+

The [DefaultCoinSelectionAlgorithm] selects the default coin selection algorithm that +TxBuilder uses, if it's not explicitly overridden.

+

Example

+
+#[derive(Debug)]
+struct AlwaysSpendEverything;
+
+impl CoinSelectionAlgorithm for AlwaysSpendEverything {
+    fn coin_select(
+        &self,
+        utxos: Vec<UTXO>,
+        _use_all_utxos: bool,
+        fee_rate: FeeRate,
+        amount_needed: u64,
+        input_witness_weight: usize,
+        fee_amount: f32,
+    ) -> Result<CoinSelectionResult, bdk::Error> {
+        let selected_amount = utxos.iter().fold(0, |acc, utxo| acc + utxo.txout.value);
+        let all_utxos_selected = utxos
+            .into_iter()
+            .map(|utxo| {
+                (
+                    TxIn {
+                        previous_output: utxo.outpoint,
+                        ..Default::default()
+                    },
+                    utxo.txout.script_pubkey,
+                )
+            })
+            .collect::<Vec<_>>();
+        let additional_weight = all_utxos_selected.iter().fold(0, |acc, (txin, _)| {
+            acc + serialize(txin).len() * 4 + input_witness_weight
+        });
+        let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
+
+        if (fee_amount + additional_fees).ceil() as u64 + amount_needed > selected_amount {
+            return Err(bdk::Error::InsufficientFunds);
+        }
+
+        Ok(CoinSelectionResult {
+            txin: all_utxos_selected,
+            selected_amount,
+            fee_amount: fee_amount + additional_fees,
+        })
+    }
+}
+
+// create wallet, sync, ...
+
+let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+let (psbt, details) = wallet.create_tx(
+    TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+        .coin_selection(AlwaysSpendEverything),
+)?;
+
+// inspect, sign, broadcast, ...
+
+

Structs

+
CoinSelectionResult

Result of a successful coin selection

+
DumbCoinSelection

Simple and dumb coin selection

+

Traits

+
CoinSelectionAlgorithm

Trait for generalized coin selection algorithms

+

Type Definitions

+
DefaultCoinSelectionAlgorithm

Default coin selection algorithm used by TxBuilder if not +overridden

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/sidebar-items.js new file mode 100644 index 0000000000..d124fee721 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["CoinSelectionResult","Result of a successful coin selection"],["DumbCoinSelection","Simple and dumb coin selection"]],"trait":[["CoinSelectionAlgorithm","Trait for generalized coin selection algorithms"]],"type":[["DefaultCoinSelectionAlgorithm","Default coin selection algorithm used by `TxBuilder` if not overridden"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.CoinSelectionResult.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.CoinSelectionResult.html new file mode 100644 index 0000000000..1081c3afdd --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.CoinSelectionResult.html @@ -0,0 +1,20 @@ +bdk::wallet::coin_selection::CoinSelectionResult - Rust

[][src]Struct bdk::wallet::coin_selection::CoinSelectionResult

pub struct CoinSelectionResult {
+    pub txin: Vec<(TxIn, Script)>,
+    pub selected_amount: u64,
+    pub fee_amount: f32,
+}

Result of a successful coin selection

+

+ Fields

txin: Vec<(TxIn, Script)>

List of inputs to use, with the respective previous script_pubkey

+
selected_amount: u64

Sum of the selected inputs' value

+
fee_amount: f32

Total fee amount in satoshi

+

Trait Implementations

impl Debug for CoinSelectionResult[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.DumbCoinSelection.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.DumbCoinSelection.html new file mode 100644 index 0000000000..d2e5130177 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.DumbCoinSelection.html @@ -0,0 +1,16 @@ +bdk::wallet::coin_selection::DumbCoinSelection - Rust

[][src]Struct bdk::wallet::coin_selection::DumbCoinSelection

pub struct DumbCoinSelection;

Simple and dumb coin selection

+

This coin selection algorithm sorts the available UTXOs by value and then picks them starting +from the largest ones until the required amount is reached.

+

Trait Implementations

impl CoinSelectionAlgorithm for DumbCoinSelection[src]

impl Debug for DumbCoinSelection[src]

impl Default for DumbCoinSelection[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html new file mode 100644 index 0000000000..f911a82add --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html @@ -0,0 +1,18 @@ +bdk::wallet::coin_selection::CoinSelectionAlgorithm - Rust

[][src]Trait bdk::wallet::coin_selection::CoinSelectionAlgorithm

pub trait CoinSelectionAlgorithm: Debug {
+    fn coin_select(
        &self,
        utxos: Vec<UTXO>,
        use_all_utxos: bool,
        fee_rate: FeeRate,
        amount_needed: u64,
        input_witness_weight: usize,
        fee_amount: f32
    ) -> Result<CoinSelectionResult, Error>; +}

Trait for generalized coin selection algorithms

+

This trait can be implemented to make the Wallet use a customized coin +selection algorithm when it creates transactions.

+

For an example see this module's documentation.

+
+

Required methods

fn coin_select(
    &self,
    utxos: Vec<UTXO>,
    use_all_utxos: bool,
    fee_rate: FeeRate,
    amount_needed: u64,
    input_witness_weight: usize,
    fee_amount: f32
) -> Result<CoinSelectionResult, Error>

Perform the coin selection

+
    +
  • utxos: the list of spendable UTXOs
  • +
  • use_all_utxos: if true all utxos should be spent unconditionally
  • +
  • fee_rate: fee rate to use
  • +
  • amount_needed: the amount in satoshi to select
  • +
  • input_witness_weight: the weight of an input's witness to keep into account for the fees
  • +
  • fee_amount: the amount of fees in satoshi already accumulated from adding outputs
  • +
+
Loading content... +

Implementors

impl CoinSelectionAlgorithm for DumbCoinSelection[src]

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html new file mode 100644 index 0000000000..39e9b5a231 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html @@ -0,0 +1,3 @@ +bdk::wallet::coin_selection::DefaultCoinSelectionAlgorithm - Rust

[][src]Type Definition bdk::wallet::coin_selection::DefaultCoinSelectionAlgorithm

type DefaultCoinSelectionAlgorithm = DumbCoinSelection;

Default coin selection algorithm used by TxBuilder if not +overridden

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/index.html new file mode 100644 index 0000000000..7bd0bc5222 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/index.html @@ -0,0 +1,28 @@ +bdk::wallet::export - Rust

[][src]Module bdk::wallet::export

Wallet export

+

This modules implements the wallet export format used by FullyNoded.

+

Examples

Import from JSON

+
+let import = r#"{
+    "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
+    "blockheight":1782088,
+    "label":"testnet"
+}"#;
+
+let import = WalletExport::from_str(import)?;
+let wallet: OfflineWallet<_> = Wallet::new_offline(&import.descriptor(), import.change_descriptor().as_deref(), Network::Testnet, MemoryDatabase::default())?;
+

Export a Wallet

+
+let wallet: OfflineWallet<_> = Wallet::new_offline(
+    "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
+    Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
+    .map_err(ToString::to_string)
+    .map_err(bdk::Error::Generic)?;
+
+println!("Exported: {}", export.to_string());
+

Structs

+
WalletExport

Structure that contains the export of a wallet

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/sidebar-items.js new file mode 100644 index 0000000000..06abb3c4ee --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["WalletExport","Structure that contains the export of a wallet"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/struct.WalletExport.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/struct.WalletExport.html new file mode 100644 index 0000000000..25efee899e --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/struct.WalletExport.html @@ -0,0 +1,36 @@ +bdk::wallet::export::WalletExport - Rust

[][src]Struct bdk::wallet::export::WalletExport

pub struct WalletExport {
+    pub blockheight: u32,
+    pub label: String,
+    // some fields omitted
+}

Structure that contains the export of a wallet

+

For a usage example see this module's documentation.

+

+ Fields

blockheight: u32

Earliest block to rescan when looking for the wallet's transactions

+
label: String

Arbitrary label for the wallet

+

Implementations

impl WalletExport[src]

pub fn export_wallet<B: BlockchainMarker, D: BatchDatabase>(
    wallet: &Wallet<B, D>,
    label: &str,
    include_blockheight: bool
) -> Result<Self, &'static str>
[src]

Export a wallet

+

This function returns an error if it determines that the wallet's descriptor(s) are not +supported by Bitcoin Core or don't follow the standard derivation paths defined by BIP44 +and others.

+

If include_blockheight is true, this function will look into the wallet's database +for the oldest transaction it knows and use that as the earliest block to rescan.

+

If the database is empty or include_blockheight is false, the blockheight field +returned will be 0.

+

pub fn descriptor(&self) -> String[src]

Return the external descriptor

+

pub fn change_descriptor(&self) -> Option<String>[src]

Return the internal descriptor, if present

+

Trait Implementations

impl Debug for WalletExport[src]

impl<'de> Deserialize<'de> for WalletExport[src]

impl FromStr for WalletExport[src]

type Err = Error

The associated error which can be returned from parsing.

+

impl Serialize for WalletExport[src]

impl ToString for WalletExport[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/index.html new file mode 100644 index 0000000000..8109a88f81 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/index.html @@ -0,0 +1,16 @@ +bdk::wallet - Rust

[][src]Module bdk::wallet

Wallet

+

This module defines the [Wallet] structure.

+

Modules

+
address_validator

Address validation callbacks

+
coin_selection

Coin selection

+
export

Wallet export

+
signer

Generalized signers

+
time

Cross-platform time

+
tx_builder

Transaction builder

+

Structs

+
Wallet

A Bitcoin wallet

+

Traits

+
IsDust

Trait to check if a value is below the dust limit

+

Type Definitions

+
OfflineWallet

Type alias for a [Wallet] that uses [OfflineBlockchain]

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/sidebar-items.js new file mode 100644 index 0000000000..811ec3c2b5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"mod":[["address_validator","Address validation callbacks"],["coin_selection","Coin selection"],["export","Wallet export"],["signer","Generalized signers"],["time","Cross-platform time"],["tx_builder","Transaction builder"]],"struct":[["Wallet","A Bitcoin wallet"]],"trait":[["IsDust","Trait to check if a value is below the dust limit"]],"type":[["OfflineWallet","Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerError.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerError.html new file mode 100644 index 0000000000..b7ee45eccf --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerError.html @@ -0,0 +1,50 @@ +bdk::wallet::signer::SignerError - Rust

[][src]Enum bdk::wallet::signer::SignerError

pub enum SignerError {
+    MissingKey,
+    UserCanceled,
+    MissingSighash,
+    InputIndexOutOfRange,
+    MissingNonWitnessUtxo,
+    InvalidNonWitnessUtxo,
+    MissingWitnessUtxo,
+    MissingWitnessScript,
+    MissingHDKeypath,
+}

Signing error

+

+ Variants

+
MissingKey

The private key is missing for the required public key

+
UserCanceled

The user canceled the operation

+
MissingSighash

The sighash is missing in the PSBT input

+
InputIndexOutOfRange

Input index is out of range

+
MissingNonWitnessUtxo

The non_witness_utxo field of the transaction is required to sign this input

+
InvalidNonWitnessUtxo

The non_witness_utxo specified is invalid

+
MissingWitnessUtxo

The witness_utxo field of the transaction is required to sign this input

+
MissingWitnessScript

The witness_script field of the transaction is requied to sign this input

+
MissingHDKeypath

The fingerprint and derivation path are missing from the psbt input

+

Trait Implementations

impl Clone for SignerError[src]

impl Debug for SignerError[src]

impl Display for SignerError[src]

impl Eq for SignerError[src]

impl Error for SignerError[src]

impl From<SignerError> for Error[src]

impl PartialEq<SignerError> for SignerError[src]

impl StructuralEq for SignerError[src]

impl StructuralPartialEq for SignerError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerId.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerId.html new file mode 100644 index 0000000000..326c2242d2 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerId.html @@ -0,0 +1,31 @@ +bdk::wallet::signer::SignerId - Rust

[][src]Enum bdk::wallet::signer::SignerId

pub enum SignerId<Pk: MiniscriptKey> {
+    PkHash(<Pk as MiniscriptKey>::Hash),
+    Fingerprint(Fingerprint),
+}

Identifier of a signer in the SignersContainers. Used as a key to find the right signer among +multiple of them

+

+ Variants

+
PkHash(<Pk as MiniscriptKey>::Hash)
Fingerprint(Fingerprint)

Trait Implementations

impl<Pk: Clone + MiniscriptKey> Clone for SignerId<Pk>[src]

impl<Pk: Debug + MiniscriptKey> Debug for SignerId<Pk>[src]

impl<Pk: Eq + MiniscriptKey> Eq for SignerId<Pk>[src]

impl From<Fingerprint> for SignerId<DescriptorPublicKey>[src]

impl From<Hash> for SignerId<DescriptorPublicKey>[src]

impl<Pk: Hash + MiniscriptKey> Hash for SignerId<Pk>[src]

impl<Pk: PartialEq + MiniscriptKey> PartialEq<SignerId<Pk>> for SignerId<Pk>[src]

impl<Pk: MiniscriptKey> StructuralEq for SignerId<Pk>[src]

impl<Pk: MiniscriptKey> StructuralPartialEq for SignerId<Pk>[src]

Auto Trait Implementations

impl<Pk> RefUnwindSafe for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe

impl<Pk> Send for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Send

impl<Pk> Sync for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Sync

impl<Pk> Unpin for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk> UnwindSafe for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/index.html new file mode 100644 index 0000000000..34dc35196d --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/index.html @@ -0,0 +1,54 @@ +bdk::wallet::signer - Rust

[][src]Module bdk::wallet::signer

Generalized signers

+

This module provides the ability to add customized signers to a Wallet +through the Wallet::add_signer function.

+ +
+#[derive(Debug)]
+struct CustomSigner {
+    device: CustomHSM,
+}
+
+impl CustomSigner {
+    fn connect() -> Self {
+        CustomSigner { device: CustomHSM::connect() }
+    }
+}
+
+impl Signer for CustomSigner {
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+    ) -> Result<(), SignerError> {
+        let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
+        self.device.sign_input(psbt, input_index)?;
+
+        Ok(())
+    }
+
+    fn sign_whole_tx(&self) -> bool {
+        false
+    }
+}
+
+let custom_signer = CustomSigner::connect();
+
+let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+wallet.add_signer(
+    ScriptType::External,
+    Fingerprint::from_str("e30f11b8").unwrap().into(),
+    SignerOrdering(200),
+    Arc::new(Box::new(custom_signer))
+);
+
+

Structs

+
SignerOrdering

Defines the order in which signers are called

+
SignersContainer

Container for multiple signers

+

Enums

+
SignerError

Signing error

+
SignerId

Identifier of a signer in the SignersContainers. Used as a key to find the right signer among +multiple of them

+

Traits

+
Signer

Trait for signers

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/sidebar-items.js new file mode 100644 index 0000000000..8f3e3d79b6 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["SignerError","Signing error"],["SignerId","Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among multiple of them"]],"struct":[["SignerOrdering","Defines the order in which signers are called"],["SignersContainer","Container for multiple signers"]],"trait":[["Signer","Trait for signers"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignerOrdering.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignerOrdering.html new file mode 100644 index 0000000000..366a6f003a --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignerOrdering.html @@ -0,0 +1,34 @@ +bdk::wallet::signer::SignerOrdering - Rust

[][src]Struct bdk::wallet::signer::SignerOrdering

pub struct SignerOrdering(pub usize);

Defines the order in which signers are called

+

The default value is 100. Signers with an ordering above that will be called later, +and they will thus see the partial signatures added to the transaction once they get to sign +themselves.

+

Trait Implementations

impl Clone for SignerOrdering[src]

impl Debug for SignerOrdering[src]

impl Default for SignerOrdering[src]

impl Eq for SignerOrdering[src]

impl Ord for SignerOrdering[src]

impl PartialEq<SignerOrdering> for SignerOrdering[src]

impl PartialOrd<SignerOrdering> for SignerOrdering[src]

impl StructuralEq for SignerOrdering[src]

impl StructuralPartialEq for SignerOrdering[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignersContainer.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignersContainer.html new file mode 100644 index 0000000000..96e0d58dd9 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignersContainer.html @@ -0,0 +1,27 @@ +bdk::wallet::signer::SignersContainer - Rust

[][src]Struct bdk::wallet::signer::SignersContainer

pub struct SignersContainer<Pk: MiniscriptKey>(_);

Container for multiple signers

+

Implementations

impl SignersContainer<DescriptorPublicKey>[src]

pub fn as_key_map(&self) -> KeyMap[src]

impl<Pk: MiniscriptKey> SignersContainer<Pk>[src]

pub fn new() -> Self[src]

Default constructor

+

pub fn add_external(
    &mut self,
    id: SignerId<Pk>,
    ordering: SignerOrdering,
    signer: Arc<Box<dyn Signer>>
) -> Option<Arc<Box<dyn Signer>>>
[src]

Adds an external signer to the container for the specified id. Optionally returns the +signer that was previosuly in the container, if any

+

pub fn remove(
    &mut self,
    id: SignerId<Pk>,
    ordering: SignerOrdering
) -> Option<Arc<Box<dyn Signer>>>
[src]

Removes a signer from the container and returns it

+

pub fn ids(&self) -> Vec<&SignerId<Pk>>[src]

Returns the list of identifiers of all the signers in the container

+

pub fn signers(&self) -> Vec<&Arc<Box<dyn Signer>>>[src]

Returns the list of signers in the container, sorted by lowest to highest ordering

+

pub fn find(&self, id: SignerId<Pk>) -> Option<&Arc<Box<dyn Signer>>>[src]

Finds the signer with lowest ordering for a given id in the container.

+

Trait Implementations

impl<Pk: Clone + MiniscriptKey> Clone for SignersContainer<Pk>[src]

impl<Pk: Debug + MiniscriptKey> Debug for SignersContainer<Pk>[src]

impl<Pk: Default + MiniscriptKey> Default for SignersContainer<Pk>[src]

impl From<HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>> for SignersContainer<DescriptorPublicKey>[src]

Auto Trait Implementations

impl<Pk> !RefUnwindSafe for SignersContainer<Pk>

impl<Pk> !Send for SignersContainer<Pk>

impl<Pk> !Sync for SignersContainer<Pk>

impl<Pk> Unpin for SignersContainer<Pk> where
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk> !UnwindSafe for SignersContainer<Pk>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/trait.Signer.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/trait.Signer.html new file mode 100644 index 0000000000..43c457c266 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/trait.Signer.html @@ -0,0 +1,23 @@ +bdk::wallet::signer::Signer - Rust

[][src]Trait bdk::wallet::signer::Signer

pub trait Signer: Debug {
+    fn sign(
        &self,
        psbt: &mut PartiallySignedTransaction,
        input_index: Option<usize>
    ) -> Result<(), SignerError>; +
fn sign_whole_tx(&self) -> bool; + + fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> { ... } +}

Trait for signers

+

This trait can be implemented to provide customized signers to the wallet. For an example see +this module's documentation.

+
+

Required methods

fn sign(
    &self,
    psbt: &mut PartiallySignedTransaction,
    input_index: Option<usize>
) -> Result<(), SignerError>

Sign a PSBT

+

The input_index argument is only provided if the wallet doesn't declare to sign the whole +transaction in one go (see [Signer::sign_whole_tx]). Otherwise its value is None and +can be ignored.

+

fn sign_whole_tx(&self) -> bool

Return whether or not the signer signs the whole transaction in one go instead of every +input individually

+
Loading content... +

Provided methods

fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey>

Return the secret key for the signer

+

This is used internally to reconstruct the original descriptor that may contain secrets. +External signers that are meant to keep key isolated should just return None here (which +is the default for this method, if not overridden).

+
Loading content... +

Implementations on Foreign Types

impl Signer for DescriptorXKey<ExtendedPrivKey>[src]

impl Signer for PrivateKey[src]

Loading content... +

Implementors

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/struct.Wallet.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/struct.Wallet.html new file mode 100644 index 0000000000..baccff0341 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/struct.Wallet.html @@ -0,0 +1,70 @@ +bdk::wallet::Wallet - Rust

[][src]Struct bdk::wallet::Wallet

pub struct Wallet<B: BlockchainMarker, D: BatchDatabase> { /* fields omitted */ }

A Bitcoin wallet

+

A wallet takes descriptors, a database and a +blockchain and implements the basic functions that a Bitcoin wallets +needs to operate, like generating addresses, returning the balance, +creating transactions, etc.

+

A wallet can be either "online" if the blockchain type provided +implements [Blockchain], or "offline" [OfflineBlockchain] is used. Offline wallets only expose +methods that don't need any interaction with the blockchain to work.

+

Implementations

impl<B, D> Wallet<B, D> where
    B: BlockchainMarker,
    D: BatchDatabase
[src]

pub fn new_offline(
    descriptor: &str,
    change_descriptor: Option<&str>,
    network: Network,
    database: D
) -> Result<Self, Error>
[src]

Create a new "offline" wallet

+

pub fn get_new_address(&self) -> Result<Address, Error>[src]

Return a newly generated address using the external descriptor

+

pub fn is_mine(&self, script: &Script) -> Result<bool, Error>[src]

Return whether or not a script is part of this wallet (either internal or external)

+

pub fn list_unspent(&self) -> Result<Vec<UTXO>, Error>[src]

Return the list of unspent outputs of this wallet

+

Note that this methods only operate on the internal database, which first needs to be +[Wallet::sync] manually.

+

pub fn list_transactions(
    &self,
    include_raw: bool
) -> Result<Vec<TransactionDetails>, Error>
[src]

Return the list of transactions made and received by the wallet

+

Optionally fill the [TransactionDetails::transaction] field with the raw transaction if +include_raw is true.

+

Note that this methods only operate on the internal database, which first needs to be +[Wallet::sync] manually.

+

pub fn get_balance(&self) -> Result<u64, Error>[src]

Return the balance, meaning the sum of this wallet's unspent outputs' values

+

Note that this methods only operate on the internal database, which first needs to be +[Wallet::sync] manually.

+

pub fn add_signer(
    &mut self,
    script_type: ScriptType,
    id: SignerId<DescriptorPublicKey>,
    ordering: SignerOrdering,
    signer: Arc<Box<dyn Signer>>
)
[src]

Add an external signer

+

See the signer module for an example.

+

pub fn add_address_validator(
    &mut self,
    validator: Arc<Box<dyn AddressValidator>>
)
[src]

Add an address validator

+

See the address_validator module for an example.

+

pub fn create_tx<Cs: CoinSelectionAlgorithm>(
    &self,
    builder: TxBuilder<Cs>
) -> Result<(PSBT, TransactionDetails), Error>
[src]

Create a new transaction following the options specified in the builder

+

Example

+
+let (psbt, details) = wallet.create_tx(
+    TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+)?;
+// sign and broadcast ...
+

pub fn bump_fee<Cs: CoinSelectionAlgorithm>(
    &self,
    txid: &Txid,
    builder: TxBuilder<Cs>
) -> Result<(PSBT, TransactionDetails), Error>
[src]

Bump the fee of a transaction following the options specified in the builder

+

Return an error if the transaction is already confirmed or doesn't explicitly signal RBF.

+

NOTE: if the original transaction was made with [TxBuilder::send_all], the same +option must be enabled when bumping its fees to correctly reduce the only output's value to +increase the fees.

+

Example

+
+let txid = Txid::from_str("faff0a466b70f5d5f92bd757a92c1371d4838bdd5bc53a06764e2488e51ce8f8").unwrap();
+let (psbt, details) = wallet.bump_fee(
+    &txid,
+    TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(5.0)),
+)?;
+// sign and broadcast ...
+

pub fn sign(
    &self,
    psbt: PSBT,
    assume_height: Option<u32>
) -> Result<(PSBT, bool), Error>
[src]

Sign a transaction with all the wallet's signers, in the order specified by every signer's +[SignerOrdering]

+

Example

+
+let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
+

pub fn policies(&self, script_type: ScriptType) -> Result<Option<Policy>, Error>[src]

Return the spending policies for the wallet's descriptor

+

pub fn public_descriptor(
    &self,
    script_type: ScriptType
) -> Result<Option<ExtendedDescriptor>, Error>
[src]

Return the "public" version of the wallet's descriptor, meaning a new descriptor that has +the same structure but with every secret key removed

+

This can be used to build a watch-only version of a wallet

+

pub fn finalize_psbt(
    &self,
    psbt: PSBT,
    assume_height: Option<u32>
) -> Result<(PSBT, bool), Error>
[src]

Try to finalize a PSBT

+

impl<B, D> Wallet<B, D> where
    B: Blockchain,
    D: BatchDatabase
[src]

pub fn new(
    descriptor: &str,
    change_descriptor: Option<&str>,
    network: Network,
    database: D,
    client: B
) -> Result<Self, Error>
[src]

Create a new "online" wallet

+

pub fn sync<P: 'static + Progress>(
    &self,
    progress_update: P,
    max_address_param: Option<u32>
) -> Result<(), Error>
[src]

Sync the internal database with the blockchain

+

pub fn client(&self) -> Option<&B>[src]

Return a reference to the internal blockchain client

+

pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error>[src]

Broadcast a transaction to the network

+

Auto Trait Implementations

impl<B, D> !RefUnwindSafe for Wallet<B, D>

impl<B, D> !Send for Wallet<B, D>

impl<B, D> !Sync for Wallet<B, D>

impl<B, D> Unpin for Wallet<B, D> where
    B: Unpin,
    D: Unpin

impl<B, D> !UnwindSafe for Wallet<B, D>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/fn.get_timestamp.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/fn.get_timestamp.html new file mode 100644 index 0000000000..201c354c30 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/fn.get_timestamp.html @@ -0,0 +1,2 @@ +bdk::wallet::time::get_timestamp - Rust

[][src]Function bdk::wallet::time::get_timestamp

pub fn get_timestamp() -> u64

Return the current timestamp in seconds

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/index.html new file mode 100644 index 0000000000..17c3d7ce66 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/index.html @@ -0,0 +1,8 @@ +bdk::wallet::time - Rust

[][src]Module bdk::wallet::time

Cross-platform time

+

This module provides a function to get the current timestamp that works on all the platforms +supported by the library.

+

It can be useful to compare it with the timestamps found in +TransactionDetails.

+

Functions

+
get_timestamp

Return the current timestamp in seconds

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/sidebar-items.js new file mode 100644 index 0000000000..22164ef49f --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"fn":[["get_timestamp","Return the current timestamp in seconds"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/trait.IsDust.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/trait.IsDust.html new file mode 100644 index 0000000000..411b351028 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/trait.IsDust.html @@ -0,0 +1,8 @@ +bdk::wallet::IsDust - Rust

[][src]Trait bdk::wallet::IsDust

pub trait IsDust {
+    fn is_dust(&self) -> bool;
+}

Trait to check if a value is below the dust limit

+
+

Required methods

fn is_dust(&self) -> bool

Check whether or not a value is below dust limit

+
Loading content... +

Implementations on Foreign Types

impl IsDust for u64[src]

Loading content... +

Implementors

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html new file mode 100644 index 0000000000..41575bbd0e --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html @@ -0,0 +1,42 @@ +bdk::wallet::tx_builder::ChangeSpendPolicy - Rust

[][src]Enum bdk::wallet::tx_builder::ChangeSpendPolicy

pub enum ChangeSpendPolicy {
+    ChangeAllowed,
+    OnlyChange,
+    ChangeForbidden,
+}

Policy regarding the use of change outputs when creating a transaction

+

+ Variants

+
ChangeAllowed

Use both change and non-change outputs (default)

+
OnlyChange

Only use change outputs (see [TxBuilder::only_spend_change])

+
ChangeForbidden

Only use non-change outputs (see [TxBuilder::do_not_spend_change])

+

Trait Implementations

impl Clone for ChangeSpendPolicy[src]

impl Copy for ChangeSpendPolicy[src]

impl Debug for ChangeSpendPolicy[src]

impl Default for ChangeSpendPolicy[src]

impl Eq for ChangeSpendPolicy[src]

impl Hash for ChangeSpendPolicy[src]

impl Ord for ChangeSpendPolicy[src]

impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy[src]

impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy[src]

impl StructuralEq for ChangeSpendPolicy[src]

impl StructuralPartialEq for ChangeSpendPolicy[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.TxOrdering.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.TxOrdering.html new file mode 100644 index 0000000000..18fcd110c2 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.TxOrdering.html @@ -0,0 +1,42 @@ +bdk::wallet::tx_builder::TxOrdering - Rust

[][src]Enum bdk::wallet::tx_builder::TxOrdering

pub enum TxOrdering {
+    Shuffle,
+    Untouched,
+    BIP69Lexicographic,
+}

Ordering of the transaction's inputs and outputs

+

+ Variants

+
Shuffle

Randomized (default)

+
Untouched

Unchanged

+
BIP69Lexicographic

BIP69 / Lexicographic

+

Implementations

impl TxOrdering[src]

pub fn sort_tx(&self, tx: &mut Transaction)[src]

Trait Implementations

impl Clone for TxOrdering[src]

impl Copy for TxOrdering[src]

impl Debug for TxOrdering[src]

impl Default for TxOrdering[src]

impl Eq for TxOrdering[src]

impl Hash for TxOrdering[src]

impl Ord for TxOrdering[src]

impl PartialEq<TxOrdering> for TxOrdering[src]

impl PartialOrd<TxOrdering> for TxOrdering[src]

impl StructuralEq for TxOrdering[src]

impl StructuralPartialEq for TxOrdering[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/index.html new file mode 100644 index 0000000000..90c59e1cb8 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/index.html @@ -0,0 +1,16 @@ +bdk::wallet::tx_builder - Rust

[][src]Module bdk::wallet::tx_builder

Transaction builder

+

Example

+
+// Create a transaction with one output to `to_address` of 50_000 satoshi, with a custom fee rate
+// of 5.0 satoshi/vbyte, only spending non-change outputs and with RBF signaling
+// enabled
+let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+    .fee_rate(FeeRate::from_sat_per_vb(5.0))
+    .do_not_spend_change()
+    .enable_rbf();
+

Structs

+
TxBuilder

A transaction builder

+

Enums

+
ChangeSpendPolicy

Policy regarding the use of change outputs when creating a transaction

+
TxOrdering

Ordering of the transaction's inputs and outputs

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/sidebar-items.js new file mode 100644 index 0000000000..e51db729e0 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["ChangeSpendPolicy","Policy regarding the use of change outputs when creating a transaction"],["TxOrdering","Ordering of the transaction's inputs and outputs"]],"struct":[["TxBuilder","A transaction builder"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/struct.TxBuilder.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/struct.TxBuilder.html new file mode 100644 index 0000000000..d12f019472 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/struct.TxBuilder.html @@ -0,0 +1,70 @@ +bdk::wallet::tx_builder::TxBuilder - Rust

[][src]Struct bdk::wallet::tx_builder::TxBuilder

pub struct TxBuilder<Cs: CoinSelectionAlgorithm> { /* fields omitted */ }

A transaction builder

+

This structure contains the configuration that the wallet must follow to build a transaction.

+

For an example see this module's documentation;

+

Implementations

impl TxBuilder<DefaultCoinSelectionAlgorithm>[src]

pub fn new() -> Self[src]

Create an empty builder

+

pub fn with_recipients(recipients: Vec<(Script, u64)>) -> Self[src]

Create a builder starting from a list of recipients

+

impl<Cs: CoinSelectionAlgorithm> TxBuilder<Cs>[src]

pub fn set_recipients(self, recipients: Vec<(Script, u64)>) -> Self[src]

Replace the recipients already added with a new list

+

pub fn add_recipient(self, script_pubkey: Script, amount: u64) -> Self[src]

Add a recipient to the internal list

+

pub fn send_all(self) -> Self[src]

Send all the selected utxos to a single output

+

Adding more than one recipients with this option enabled will result in an error.

+

The value associated with the only recipient is irrelevant and will be replaced by the wallet.

+

pub fn fee_rate(self, fee_rate: FeeRate) -> Self[src]

Set a custom fee rate

+

pub fn policy_path(self, policy_path: BTreeMap<String, Vec<usize>>) -> Self[src]

Set the policy path to use while creating the transaction

+

This method accepts a map where the key is the policy node id (see +Policy::id) and the value is the list of the indexes of +the items that are intended to be satisfied from the policy node (see +SatisfiableItem::Thresh::items).

+

pub fn utxos(self, utxos: Vec<OutPoint>) -> Self[src]

Replace the internal list of utxos that must be spent with a new list

+

These have priority over the "unspendable" utxos, meaning that if a utxo is present both in +the "utxos" and the "unspendable" list, it will be spent.

+

pub fn add_utxo(self, utxo: OutPoint) -> Self[src]

Add a utxo to the internal list of utxos that must be spent

+

These have priority over the "unspendable" utxos, meaning that if a utxo is present both in +the "utxos" and the "unspendable" list, it will be spent.

+

pub fn unspendable(self, unspendable: Vec<OutPoint>) -> Self[src]

Replace the internal list of unspendable utxos with a new list

+

It's important to note that the "must-be-spent" utxos added with [TxBuilder::utxos] and +[TxBuilder::add_utxo] have priority over these. See the docs of the two linked methods +for more details.

+

pub fn add_unspendable(self, unspendable: OutPoint) -> Self[src]

Add a utxo to the internal list of unspendable utxos

+

It's important to note that the "must-be-spent" utxos added with [TxBuilder::utxos] and +[TxBuilder::add_utxo] have priority over this. See the docs of the two linked methods +for more details.

+

pub fn sighash(self, sighash: SigHashType) -> Self[src]

Sign with a specific sig hash

+

Use this option very carefully

+

pub fn ordering(self, ordering: TxOrdering) -> Self[src]

Choose the ordering for inputs and outputs of the transaction

+

pub fn nlocktime(self, locktime: u32) -> Self[src]

Use a specific nLockTime while creating the transaction

+

This can cause conflicts if the wallet's descriptors contain an "after" (OP_CLTV) operator.

+

pub fn enable_rbf(self) -> Self[src]

Enable signaling RBF

+

This will use the default nSequence value of 0xFFFFFFFD.

+

pub fn enable_rbf_with_sequence(self, nsequence: u32) -> Self[src]

Enable signaling RBF with a specific nSequence value

+

This can cause conflicts if the wallet's descriptors contain an "older" (OP_CSV) operator +and the given nsequence is lower than the CSV value.

+

If the nsequence is higher than 0xFFFFFFFD an error will be thrown, since it would not +be a valid nSequence to signal RBF.

+

pub fn version(self, version: u32) -> Self[src]

Build a transaction with a specific version

+

The version should always be greater than 0 and greater than 1 if the wallet's +descriptors contain an "older" (OP_CSV) operator.

+

pub fn do_not_spend_change(self) -> Self[src]

Do not spend change outputs

+

This effectively adds all the change outputs to the "unspendable" list. See +[TxBuilder::unspendable].

+

pub fn only_spend_change(self) -> Self[src]

Only spend change outputs

+

This effectively adds all the non-change outputs to the "unspendable" list. See +[TxBuilder::unspendable].

+

pub fn change_policy(self, change_policy: ChangeSpendPolicy) -> Self[src]

Set a specific [ChangeSpendPolicy]. See [TxBuilder::do_not_spend_change] and +[TxBuilder::only_spend_change] for some shortcuts.

+

pub fn force_non_witness_utxo(self) -> Self[src]

Fill-in the psbt::Input::non_witness_utxo field even if the wallet only has SegWit +descriptors.

+

This is useful for signers which always require it, like Trezor hardware wallets.

+

pub fn coin_selection<P: CoinSelectionAlgorithm>(
    self,
    coin_selection: P
) -> TxBuilder<P>
[src]

Choose the coin selection algorithm

+

Overrides the DefaultCoinSelectionAlgorithm.

+

Trait Implementations

impl<Cs: Debug + CoinSelectionAlgorithm> Debug for TxBuilder<Cs>[src]

impl<Cs: Default + CoinSelectionAlgorithm> Default for TxBuilder<Cs>[src]

Auto Trait Implementations

impl<Cs> RefUnwindSafe for TxBuilder<Cs> where
    Cs: RefUnwindSafe

impl<Cs> Send for TxBuilder<Cs> where
    Cs: Send

impl<Cs> Sync for TxBuilder<Cs> where
    Cs: Sync

impl<Cs> Unpin for TxBuilder<Cs> where
    Cs: Unpin

impl<Cs> UnwindSafe for TxBuilder<Cs> where
    Cs: UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/type.OfflineWallet.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/type.OfflineWallet.html new file mode 100644 index 0000000000..7e279e53e2 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/type.OfflineWallet.html @@ -0,0 +1,2 @@ +bdk::wallet::OfflineWallet - Rust

[][src]Type Definition bdk::wallet::OfflineWallet

type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;

Type alias for a [Wallet] that uses [OfflineBlockchain]

+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/utils/trait.IsDust.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/utils/trait.IsDust.html new file mode 100644 index 0000000000..71ab5675d6 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/utils/trait.IsDust.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../../bdk/wallet/trait.IsDust.html...

+ + + \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/brush.svg b/static/docs-rs/bdk/0.1.0-beta.1/brush.svg new file mode 100644 index 0000000000..ea266e856a --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/brush.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/dark.css b/static/docs-rs/bdk/0.1.0-beta.1/dark.css new file mode 100644 index 0000000000..7f71607767 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/dark.css @@ -0,0 +1 @@ +body{background-color:#353535;color:#ddd;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:#ddd;}h1.fqn{border-bottom-color:#d2d2d2;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){border-bottom-color:#d2d2d2;}.in-band{background-color:#353535;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#2A2A2A;}pre{background-color:#2A2A2A;}.sidebar{background-color:#505050;}*{scrollbar-color:rgb(64,65,67) #717171;}.sidebar{scrollbar-color:rgba(32,34,37,.6) transparent;}::-webkit-scrollbar-track{background-color:#717171;}::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar::-webkit-scrollbar-track{background-color:#717171;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar .current{background-color:#333;}.source .sidebar{background-color:#353535;}.sidebar .location{border-color:#fff;background:#575757;color:#DDD;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#444;}.line-numbers span{color:#3B91E2;}.line-numbers .line-highlighted{background-color:#0a042f !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#DDD;}.docblock table,.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#ddd;}.content .highlighted{color:#eee !important;background-color:#616161;}.content .highlighted a,.content .highlighted span{color:#eee !important;}.content .highlighted.trait{background-color:#013191;}.content .highlighted.traitalias{background-color:#013191;}.content .highlighted.mod,.content .highlighted.externcrate{background-color:#afc6e4;}.content .highlighted.mod{background-color:#803a1b;}.content .highlighted.externcrate{background-color:#396bac;}.content .highlighted.enum{background-color:#5b4e68;}.content .highlighted.struct{background-color:#194e9f;}.content .highlighted.union{background-color:#b7bd49;}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{background-color:#4950ed;}.content .highlighted.type{background-color:#38902c;}.content .highlighted.foreigntype{background-color:#b200d6;}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{background-color:#217d1c;}.content .highlighted.constant,.content .highlighted.static{background-color:#0063cc;}.content .highlighted.primitive{background-color:#00708a;}.content .highlighted.keyword{background-color:#884719;}.content .stability::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#82b089;}.content span.struct,.content a.struct,.block a.current.struct{color:#2dbfb8;}.content span.type,.content a.type,.block a.current.type{color:#ff7f00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#dd7de8;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#09bd00;}.content span.union,.content a.union,.block a.current.union{color:#a6ae37;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#82a5c9;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#43aec7;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#bda000;}.content span.trait,.content a.trait,.block a.current.trait{color:#b78cf2;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#b397da;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#2BAB63;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8d8d8b;}pre.rust .doccomment{color:#8ca375;}nav:not(.sidebar){border-bottom-color:#4e4e4e;}nav.main .current{border-top-color:#eee;border-bottom-color:#eee;}nav.main .separator{border-color:#eee;}a{color:#ddd;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.stability a{color:#D2991D;}.stab.internal a{color:#304FFE;}a.test-arrow{color:#dedede;}.collapse-toggle{color:#999;}#crate-search{color:#111;background-color:#f0f0f0;border-color:#000;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input{color:#111;background-color:#f0f0f0;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input:focus{border-color:#008dfd;}.search-focus:disabled{background-color:#c5c4c4;}#crate-search+.search-input:focus{box-shadow:0 0 8px 4px #078dd8;}.module-item .stab{color:#ddd;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;color:#2f2f2f;}.stab.internal{background:#FFB9B3;border-color:#B71C1C;color:#2f2f2f;}.stab.deprecated{background:#F3DFFF;border-color:#7F0087;color:#2f2f2f;}.stab.portability{background:#C4ECFF;border-color:#7BA5DB;color:#2f2f2f;}.stab.portability>code{color:#ddd;}#help>div{background:#4d4d4d;border-color:#bfbfbf;}#help dt{border-color:#bfbfbf;background:rgba(0,0,0,0);color:black;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:#ddd;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#ab8ac1;}pre.rust .kw-2,pre.rust .prelude-ty{color:#769acb;}pre.rust .number,pre.rust .string{color:#83a300;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#ee6868;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#d97f26;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#4a4949;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label{color:#999;}:target>code,:target>.in-band{background-color:#494a3d;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.8);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.8);}.information>.compile_fail:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip .tooltiptext{background-color:#000;color:#fff;border-color:#000;}.tooltip .tooltiptext::after{border-color:transparent black transparent transparent;}#titles>div:not(.selected){background-color:#252525;border-top-color:#252525;}#titles>div:hover,#titles>div.selected{border-top-color:#0089ff;}#titles>div>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#505050;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#505050;border-right-color:#000;}#sidebar-filler{background-color:#505050;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu{border-color:#e0e0e0;background:#f0f0f0;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus{border-color:#ffb900;}#theme-choices{border-color:#e0e0e0;background-color:#353535;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#4e4e4e;}@media (max-width:700px){#theme-picker{background:#f0f0f0;}}#all-types{background-color:#505050;}#all-types:hover{background-color:#606060;}.search-results td span.alias{color:#fff;}.search-results td span.grey{color:#ccc;}#sidebar-toggle{background-color:#565656;}#sidebar-toggle:hover{background-color:#676767;}#source-sidebar{background-color:#565656;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#444;}div.files>.selected{background-color:#333;}.setting-line>.title{border-bottom-color:#ddd;} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/down-arrow.svg b/static/docs-rs/bdk/0.1.0-beta.1/down-arrow.svg new file mode 100644 index 0000000000..35437e77a7 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/down-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/favicon.ico b/static/docs-rs/bdk/0.1.0-beta.1/favicon.ico new file mode 100644 index 0000000000..b8ad23769a Binary files /dev/null and b/static/docs-rs/bdk/0.1.0-beta.1/favicon.ico differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/alloc/string/trait.ToString.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/alloc/string/trait.ToString.js new file mode 100644 index 0000000000..f3e935dbe1 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/alloc/string/trait.ToString.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl ToString for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Blockchain.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Blockchain.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Blockchain.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.BlockchainMarker.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.BlockchainMarker.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.BlockchainMarker.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Progress.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Progress.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Progress.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchDatabase.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchDatabase.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchDatabase.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchOperations.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchOperations.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchOperations.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.Database.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.Database.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.Database.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ExtractPolicy.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ExtractPolicy.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ExtractPolicy.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.MiniscriptKey.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.MiniscriptKey.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.MiniscriptKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ScriptContext.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ScriptContext.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ScriptContext.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ToPublicKey.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ToPublicKey.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ToPublicKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/signer/trait.Signer.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/signer/trait.Signer.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/signer/trait.Signer.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/trait.IsDust.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/trait.IsDust.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/trait.IsDust.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/clone/trait.Clone.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/clone/trait.Clone.js new file mode 100644 index 0000000000..795f3aa5e4 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/clone/trait.Clone.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Clone for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Clone for NoopProgress","synthetic":false,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Clone for LogProgress","synthetic":false,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Clone for PKOrF","synthetic":false,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Clone for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Clone for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Clone for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Clone for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Clone for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Clone for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Clone for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl Clone for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Clone for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: Clone + MiniscriptKey> Clone for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Clone for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Clone for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk: Clone + MiniscriptKey> Clone for SignersContainer<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Clone for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Clone for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Eq.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Eq.js new file mode 100644 index 0000000000..7d046cd5c6 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Eq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Eq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Eq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Eq for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Eq for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl Eq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Eq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: Eq + MiniscriptKey> Eq for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Eq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Eq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Eq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Eq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Ord.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Ord.js new file mode 100644 index 0000000000..def6b4a7cf --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Ord.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Ord for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Ord for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Ord for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Ord for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialEq.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialEq.js new file mode 100644 index 0000000000..317284f165 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl PartialEq<Capability> for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl PartialEq<Condition> for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl PartialEq<ScriptType> for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl PartialEq<FeeRate> for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl PartialEq<UTXO> for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl PartialEq<TransactionDetails> for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl PartialEq<AddressValidatorError> for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: PartialEq + MiniscriptKey> PartialEq<SignerId<Pk>> for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl PartialEq<SignerError> for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl PartialEq<SignerOrdering> for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl PartialEq<TxOrdering> for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialOrd.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialOrd.js new file mode 100644 index 0000000000..a07fbbf60f --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialOrd.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl PartialOrd<Condition> for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl PartialOrd<FeeRate> for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl PartialOrd<SignerOrdering> for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl PartialOrd<TxOrdering> for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.AsRef.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.AsRef.js new file mode 100644 index 0000000000..cf12c34f1d --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.AsRef.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl AsRef<[u8]> for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.From.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.From.js new file mode 100644 index 0000000000..54b9db1def --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.From.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<AddressValidatorError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<SignerError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<EsploraError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<CompactFiltersError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Client> for ElectrumBlockchain","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<ParseIntError> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<SystemTimeError> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<bool> for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl From<SatisfiableItem> for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl From<Hash> for SignerId<DescriptorPublicKey>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl From<Fingerprint> for SignerId<DescriptorPublicKey>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl From<HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>> for SignersContainer<DescriptorPublicKey>","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/default/trait.Default.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/default/trait.Default.js new file mode 100644 index 0000000000..521ae3ac3c --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/default/trait.Default.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Default for Mempool","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Default for MemoryDatabase","synthetic":false,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Default for PKOrF","synthetic":false,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Default for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Default for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Default for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Default for DumbCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Default for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk: Default + MiniscriptKey> Default for SignersContainer<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Cs: Default + CoinSelectionAlgorithm> Default for TxBuilder<Cs>","synthetic":false,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Default for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Default for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Debug.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Debug.js new file mode 100644 index 0000000000..74c7308e86 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Debug.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Debug for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Debug for EsploraBlockchain","synthetic":false,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Debug for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Debug for Mempool","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Debug for Peer","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Debug for CompactFiltersBlockchain","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Debug for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Debug for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Debug for MemoryDatabase","synthetic":false,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Debug for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Debug for PKOrF","synthetic":false,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Debug for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Debug for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Debug for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Debug for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Debug for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Debug for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Debug for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Debug for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl Debug for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Debug for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Debug for CoinSelectionResult","synthetic":false,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Debug for DumbCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Debug for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl<Pk: Debug + MiniscriptKey> Debug for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Debug for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Debug for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk: Debug + MiniscriptKey> Debug for SignersContainer<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Cs: Debug + CoinSelectionAlgorithm> Debug for TxBuilder<Cs>","synthetic":false,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Debug for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Debug for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Display.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Display.js new file mode 100644 index 0000000000..e2ed5553a9 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Display.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Display for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Display for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Display for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Display for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Display for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Display for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Display for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/hash/trait.Hash.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/hash/trait.Hash.js new file mode 100644 index 0000000000..a5da8ca7bd --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/hash/trait.Hash.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Hash for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Hash for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Hash for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl<Pk: Hash + MiniscriptKey> Hash for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Hash for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Hash for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Copy.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Copy.js new file mode 100644 index 0000000000..5f551c2945 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Copy.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Copy for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Copy for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Copy for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Copy for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Copy for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Copy for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Freeze.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Freeze.js new file mode 100644 index 0000000000..23dc06ecd5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Freeze.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Freeze for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Freeze for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl Freeze for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Freeze for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Freeze for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl Freeze for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl Freeze for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Freeze for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Freeze for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl !Freeze for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Freeze for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Freeze for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl !Freeze for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Freeze for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Freeze for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Freeze for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Freeze for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Freeze for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Freeze for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Freeze for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Freeze for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Freeze for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Freeze for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Freeze for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !Freeze for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Freeze for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Freeze for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Freeze for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Freeze for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Freeze for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> Freeze for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Freeze for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Freeze, 
","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Freeze for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> Freeze for TxBuilder<Cs> where
    Cs: Freeze, 
","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Freeze for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Freeze for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Send.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Send.js new file mode 100644 index 0000000000..764c51c5e0 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Send.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Send for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Send for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl Send for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Send for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Send for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl Send for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl Send for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Send for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Send for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Send for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Send for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Send for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Send for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Send for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Send for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Send for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !Send for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Send for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Send for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Send for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Send for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Send for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Send for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Send for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !Send for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Send for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Send for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Send for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Send for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Send for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !Send for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Send for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Send
","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Send for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> Send for TxBuilder<Cs> where
    Cs: Send
","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Send for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Send for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralEq.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralEq.js new file mode 100644 index 0000000000..9aa523c03e --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl StructuralEq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl StructuralEq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl StructuralEq for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl StructuralEq for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl StructuralEq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl StructuralEq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: MiniscriptKey> StructuralEq for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl StructuralEq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl StructuralEq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl StructuralEq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl StructuralEq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralPartialEq.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralPartialEq.js new file mode 100644 index 0000000000..f0eb276a1d --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralPartialEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl StructuralPartialEq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl StructuralPartialEq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl StructuralPartialEq for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl StructuralPartialEq for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl StructuralPartialEq for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl StructuralPartialEq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl StructuralPartialEq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: MiniscriptKey> StructuralPartialEq for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl StructuralPartialEq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl StructuralPartialEq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl StructuralPartialEq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl StructuralPartialEq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Sync.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Sync.js new file mode 100644 index 0000000000..1fd8f87484 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Sync.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Sync for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Sync for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl Sync for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Sync for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Sync for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl Sync for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl Sync for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Sync for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Sync for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Sync for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Sync for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Sync for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Sync for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Sync for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Sync for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Sync for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !Sync for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Sync for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Sync for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Sync for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Sync for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Sync for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Sync for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Sync for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !Sync for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Sync for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Sync for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Sync for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Sync for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Sync for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !Sync for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Sync for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Sync
","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Sync for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> Sync for TxBuilder<Cs> where
    Cs: Sync
","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Sync for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Sync for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Unpin.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Unpin.js new file mode 100644 index 0000000000..8cc0048d2d --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Unpin.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Unpin for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Unpin for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl Unpin for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Unpin for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Unpin for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl Unpin for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl Unpin for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Unpin for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Unpin for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Unpin for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Unpin for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Unpin for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Unpin for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Unpin for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Unpin for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Unpin for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Unpin for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Unpin for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Unpin for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Unpin for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Unpin for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Unpin for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Unpin for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Unpin for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> Unpin for Wallet<B, D> where
    B: Unpin,
    D: Unpin
","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Unpin for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Unpin for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Unpin for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Unpin for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Unpin for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> Unpin for SignersContainer<Pk> where
    <Pk as MiniscriptKey>::Hash: Unpin
","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Unpin for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Unpin
","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Unpin for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> Unpin for TxBuilder<Cs> where
    Cs: Unpin
","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Unpin for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Unpin for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/str/trait.FromStr.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/str/trait.FromStr.js new file mode 100644 index 0000000000..fd4b285a22 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/str/trait.FromStr.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl FromStr for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/serde/de/trait.Deserialize.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/serde/de/trait.Deserialize.js new file mode 100644 index 0000000000..8053d7effa --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/serde/de/trait.Deserialize.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl<'de> Deserialize<'de> for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl<'de> Deserialize<'de> for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl<'de> Deserialize<'de> for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl<'de> Deserialize<'de> for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/serde/ser/trait.Serialize.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/serde/ser/trait.Serialize.js new file mode 100644 index 0000000000..f6b22d25bf --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/serde/ser/trait.Serialize.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Serialize for PKOrF","synthetic":false,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Serialize for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Serialize for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Serialize for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Serialize for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Serialize for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Serialize for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl Serialize for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Serialize for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/error/trait.Error.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/error/trait.Error.js new file mode 100644 index 0000000000..7326983fef --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/error/trait.Error.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Error for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Error for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Error for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Error for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Error for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Error for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Error for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.RefUnwindSafe.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.RefUnwindSafe.js new file mode 100644 index 0000000000..29deba8e41 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.RefUnwindSafe.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl RefUnwindSafe for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl RefUnwindSafe for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl RefUnwindSafe for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl !RefUnwindSafe for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl RefUnwindSafe for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl RefUnwindSafe for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl RefUnwindSafe for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl RefUnwindSafe for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl RefUnwindSafe for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl RefUnwindSafe for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl !RefUnwindSafe for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl !RefUnwindSafe for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl RefUnwindSafe for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl !RefUnwindSafe for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl !RefUnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl !RefUnwindSafe for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !RefUnwindSafe for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl RefUnwindSafe for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl RefUnwindSafe for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl RefUnwindSafe for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl RefUnwindSafe for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl RefUnwindSafe for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl RefUnwindSafe for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl RefUnwindSafe for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !RefUnwindSafe for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl RefUnwindSafe for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl RefUnwindSafe for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl RefUnwindSafe for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl RefUnwindSafe for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl RefUnwindSafe for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !RefUnwindSafe for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> RefUnwindSafe for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe
","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl RefUnwindSafe for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> RefUnwindSafe for TxBuilder<Cs> where
    Cs: RefUnwindSafe
","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl RefUnwindSafe for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl RefUnwindSafe for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.UnwindSafe.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.UnwindSafe.js new file mode 100644 index 0000000000..1aa1c54fb5 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.UnwindSafe.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl UnwindSafe for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl UnwindSafe for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl UnwindSafe for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl !UnwindSafe for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl UnwindSafe for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl UnwindSafe for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl UnwindSafe for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl UnwindSafe for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl UnwindSafe for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl UnwindSafe for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl !UnwindSafe for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl !UnwindSafe for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl UnwindSafe for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl !UnwindSafe for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl !UnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl !UnwindSafe for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !UnwindSafe for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl UnwindSafe for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl UnwindSafe for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl UnwindSafe for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl UnwindSafe for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl UnwindSafe for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl UnwindSafe for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl UnwindSafe for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !UnwindSafe for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl UnwindSafe for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl UnwindSafe for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl UnwindSafe for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl UnwindSafe for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl UnwindSafe for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !UnwindSafe for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> UnwindSafe for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: UnwindSafe
","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl UnwindSafe for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> UnwindSafe for TxBuilder<Cs> where
    Cs: UnwindSafe
","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl UnwindSafe for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl UnwindSafe for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/light.css b/static/docs-rs/bdk/0.1.0-beta.1/light.css new file mode 100644 index 0000000000..d74d60dcf8 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/light.css @@ -0,0 +1 @@ + body{background-color:white;color:black;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:black;}h1.fqn{border-bottom-color:#D5D5D5;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){border-bottom-color:#DDDDDD;}.in-band{background-color:white;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#F5F5F5;}pre{background-color:#F5F5F5;}.sidebar{background-color:#F1F1F1;}*{scrollbar-color:rgba(36,37,39,0.6) #e6e6e6;}.sidebar{scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;}::-webkit-scrollbar-track{background-color:#ecebeb;}::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar::-webkit-scrollbar-track{background-color:#dcdcdc;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar .current{background-color:#fff;}.source .sidebar{background-color:#fff;}.sidebar .location{border-color:#000;background-color:#fff;color:#333;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#F5F5F5;}.line-numbers span{color:#c67e2d;}.line-numbers .line-highlighted{background-color:#f6fdb0 !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#ddd;}.docblock table,.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#4E4C4C;}.content .highlighted{color:#000 !important;background-color:#ccc;}.content .highlighted a,.content .highlighted span{color:#000 !important;}.content .highlighted.trait{background-color:#c7b6ff;}.content .highlighted.traitalias{background-color:#c7b6ff;}.content .highlighted.mod,.content .highlighted.externcrate{background-color:#afc6e4;}.content .highlighted.enum{background-color:#b4d1b9;}.content .highlighted.struct{background-color:#e7b1a0;}.content .highlighted.union{background-color:#b7bd49;}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{background-color:#c6afb3;}.content .highlighted.type{background-color:#ffc891;}.content .highlighted.foreigntype{background-color:#f5c4ff;}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{background-color:#8ce488;}.content .highlighted.constant,.content .highlighted.static{background-color:#c3e0ff;}.content .highlighted.primitive{background-color:#9aecff;}.content .highlighted.keyword{background-color:#f99650;}.content .stability::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#508157;}.content span.struct,.content a.struct,.block a.current.struct{color:#ad448e;}.content span.type,.content a.type,.block a.current.type{color:#ba5d00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#cd00e2;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#068000;}.content span.union,.content a.union,.block a.current.union{color:#767b27;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#546e8a;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#2c8093;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#4d76ae;}.content span.trait,.content a.trait,.block a.current.trait{color:#7c5af3;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#6841f1;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#9a6e31;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8E908C;}pre.rust .doccomment{color:#4D4D4C;}nav:not(.sidebar){border-bottom-color:#e0e0e0;}nav.main .current{border-top-color:#000;border-bottom-color:#000;}nav.main .separator{border:1px solid #000;}a{color:#000;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.stability a{color:#3873AD;}.stab.internal a{color:#304FFE;}a.test-arrow{color:#f5f5f5;}.collapse-toggle{color:#999;}#crate-search{color:#555;background-color:white;border-color:#e0e0e0;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input{color:#555;background-color:white;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input:focus{border-color:#66afe9;}.search-focus:disabled{background-color:#e6e6e6;}#crate-search+.search-input:focus{box-shadow:0 0 8px #078dd8;}.module-item .stab{color:#000;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;}.stab.internal{background:#FFB9B3;border-color:#B71C1C;}.stab.deprecated{background:#F3DFFF;border-color:#7F0087;}.stab.portability{background:#C4ECFF;border-color:#7BA5DB;}.stab.portability>code{color:#000;}#help>div{background:#e9e9e9;border-color:#bfbfbf;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:black;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#8959A8;}pre.rust .kw-2,pre.rust .prelude-ty{color:#4271AE;}pre.rust .number,pre.rust .string{color:#718C00;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#C82829;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#B76514;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#c7c7c7;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label{color:#999;}:target>code,:target>.in-band{background:#FDFFD3;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.5);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip .tooltiptext{background-color:#000;color:#fff;}.tooltip .tooltiptext::after{border-color:transparent black transparent transparent;}#titles>div:not(.selected){background-color:#e6e6e6;border-top-color:#e6e6e6;}#titles>div:hover,#titles>div.selected{border-top-color:#0089ff;}#titles>div>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#F1F1F1;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#F1F1F1;border-right-color:#000;}#sidebar-filler{background-color:#F1F1F1;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu{border-color:#e0e0e0;background-color:#fff;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus{border-color:#717171;}#theme-choices{border-color:#ccc;background-color:#fff;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#eee;}@media (max-width:700px){#theme-picker{background:#fff;}}#all-types{background-color:#fff;}#all-types:hover{background-color:#f9f9f9;}.search-results td span.alias{color:#000;}.search-results td span.grey{color:#999;}#sidebar-toggle{background-color:#F1F1F1;}#sidebar-toggle:hover{background-color:#E0E0E0;}#source-sidebar{background-color:#F1F1F1;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#E0E0E0;}div.files>.selected{background-color:#fff;}.setting-line>.title{border-bottom-color:#D5D5D5;} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/main.js b/static/docs-rs/bdk/0.1.0-beta.1/main.js new file mode 100644 index 0000000000..6618d8e508 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/main.js @@ -0,0 +1,7 @@ +if(!String.prototype.startsWith){String.prototype.startsWith=function(searchString,position){position=position||0;return this.indexOf(searchString,position)===position}}if(!String.prototype.endsWith){String.prototype.endsWith=function(suffix,length){var l=length||this.length;return this.indexOf(suffix,l-suffix.length)!==-1}}if(!DOMTokenList.prototype.add){DOMTokenList.prototype.add=function(className){if(className&&!hasClass(this,className)){if(this.className&&this.className.length>0){this.className+=" "+className}else{this.className=className}}}}if(!DOMTokenList.prototype.remove){DOMTokenList.prototype.remove=function(className){if(className&&this.className){this.className=(" "+this.className+" ").replace(" "+className+" "," ").trim()}}}function getSearchInput(){return document.getElementsByClassName("search-input")[0]}function getSearchElement(){return document.getElementById("search")}function focusSearchBar(){getSearchInput().focus()}function defocusSearchBar(){getSearchInput().blur()}(function(){"use strict";var itemTypes=["mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","primitive","associatedtype","constant","associatedconstant","union","foreigntype","keyword","existential","attr","derive","traitalias"];var disableShortcuts=getCurrentValue("rustdoc-disable-shortcuts")==="true";var search_input=getSearchInput();var searchTimeout=null;var currentTab=0;var titleBeforeSearch=document.title;function clearInputTimeout(){if(searchTimeout!==null){clearTimeout(searchTimeout);searchTimeout=null}}function getPageId(){var id=document.location.href.split("#")[1];if(id){return id.split("?")[0].split("&")[0]}return null}function showSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){addClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];if(sidebar){addClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(!filler){var div=document.createElement("div");div.id="sidebar-filler";sidebar.appendChild(div)}}var themePickers=document.getElementsByClassName("theme-picker");if(themePickers&&themePickers.length>0){themePickers[0].style.display="none"}}function hideSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){removeClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(filler){filler.remove()}document.getElementsByTagName("body")[0].style.marginTop="";var themePickers=document.getElementsByClassName("theme-picker");if(themePickers&&themePickers.length>0){themePickers[0].style.display=null}}function showSearchResults(search){if(search===null||typeof search==='undefined'){search=getSearchElement()}addClass(main,"hidden");removeClass(search,"hidden")}function hideSearchResults(search){if(search===null||typeof search==='undefined'){search=getSearchElement()}addClass(search,"hidden");removeClass(main,"hidden")}var TY_PRIMITIVE=itemTypes.indexOf("primitive");var TY_KEYWORD=itemTypes.indexOf("keyword");function getQueryStringParams(){var params={};window.location.search.substring(1).split("&").map(function(s){var pair=s.split("=");params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function isHidden(elem){return elem.offsetHeight===0}var main=document.getElementById("main");var savedHash="";function handleHashes(ev){var elem;var search=getSearchElement();if(ev!==null&&search&&!hasClass(search,"hidden")&&ev.newURL){hideSearchResults(search);var hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(hash,"","?search=#"+hash)}elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}if(savedHash!==window.location.hash){savedHash=window.location.hash;if(savedHash.length===0){return}elem=document.getElementById(savedHash.slice(1));if(!elem||!isHidden(elem)){return}var parent=elem.parentNode;if(parent&&hasClass(parent,"impl-items")){onEachLazy(parent.getElementsByClassName("collapsed"),function(e){if(e.parentNode===parent){e.click();return true}});if(isHidden(elem)){if(hasClass(parent.lastElementChild,"collapse-toggle")){parent.lastElementChild.click()}}}}}function highlightSourceLines(match,ev){if(typeof match==="undefined"){hideSidebar();match=window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/)}if(!match){return}var from=parseInt(match[1],10);var to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to0){collapseDocs(collapses[0],"show")}}}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!="undefined"){return ev.key}var c=ev.charCode||ev.keyCode;if(c==27){return"Escape"}return String.fromCharCode(c)}function getHelpElement(){return document.getElementById("help")}function displayHelp(display,ev,help){help=help?help:getHelpElement();if(display===true){if(hasClass(help,"hidden")){ev.preventDefault();removeClass(help,"hidden");addClass(document.body,"blur")}}else if(hasClass(help,"hidden")===false){ev.preventDefault();addClass(help,"hidden");removeClass(document.body,"blur")}}function handleEscape(ev){var help=getHelpElement();var search=getSearchElement();if(hasClass(help,"hidden")===false){displayHelp(false,ev,help)}else if(hasClass(search,"hidden")===false){clearInputTimeout();ev.preventDefault();hideSearchResults(search);document.title=titleBeforeSearch}defocusSearchBar()}function handleShortcut(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts===true){return}if(document.activeElement.tagName==="INPUT"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":displayHelp(false,ev);ev.preventDefault();focusSearchBar();break;case"+":case"-":ev.preventDefault();toggleAllDocs();break;case"?":if(ev.shiftKey){displayHelp(true,ev)}break}}}function findParentElement(elem,tagName){do{if(elem&&elem.tagName===tagName){return elem}elem=elem.parentNode}while(elem);return null}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);var handleSourceHighlight=(function(){var prev_line_id=0;var set_fragment=function(name){var x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSourceLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return function(ev){var cur_line_id=parseInt(ev.target.id,10);ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){var tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());document.addEventListener("click",function(ev){if(hasClass(ev.target,"collapse-toggle")){collapseDocs(ev.target,"toggle")}else if(hasClass(ev.target.parentNode,"collapse-toggle")){collapseDocs(ev.target.parentNode,"toggle")}else if(ev.target.tagName==="SPAN"&&hasClass(ev.target.parentNode,"line-numbers")){handleSourceHighlight(ev)}else if(hasClass(getHelpElement(),"hidden")===false){var help=getHelpElement();var is_inside_help_popup=ev.target!==help&&help.contains(ev.target);if(is_inside_help_popup===false){addClass(help,"hidden");removeClass(document.body,"blur")}}else{var a=findParentElement(ev.target,"A");if(a&&a.hash){expandSection(a.hash.replace(/^#/,""))}}});(function(){var x=document.getElementsByClassName("version-selector");if(x.length>0){x[0].onchange=function(){var i,match,url=document.location.href,stripped="",len=rootPath.match(/\.\.\//g).length+1;for(i=0;i-1){var obj=searchIndex[results[i].id];obj.lev=results[i].lev;if(isType!==true||obj.type){var res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=obj.displayPath+obj.name;obj.fullPath+="|"+obj.ty;obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}}return out}function sortResults(results,isType){var ar=[];for(var entry in results){if(hasOwnProperty(results,entry)){ar.push(results[entry])}}results=ar;var i;var nresults=results.length;for(i=0;ib?+1:-1)}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}if((aaa.item.ty===TY_PRIMITIVE&&bbb.item.ty!==TY_KEYWORD)||(aaa.item.ty===TY_KEYWORD&&bbb.item.ty!==TY_PRIMITIVE)){return-1}if((bbb.item.ty===TY_PRIMITIVE&&aaa.item.ty!==TY_PRIMITIVE)||(bbb.item.ty===TY_KEYWORD&&aaa.item.ty!==TY_KEYWORD)){return 1}a=(aaa.item.desc==="");b=(bbb.item.desc==="");if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});var length=results.length;for(i=0;i"));return{name:val.substring(0,val.indexOf("<")),generics:values.split(/\s*,\s*/),}}return{name:val,generics:[],}}function getObjectFromId(id){if(typeof id==="number"){return searchIndex[id]}return{'name':id}}function checkGenerics(obj,val){var lev_distance=MAX_LEV_DISTANCE+1;if(val.generics.length>0){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=obj[GENERICS_DATA].slice(0);var total=0;var done=0;var vlength=val.generics.length;for(var y=0;yGENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=obj[GENERICS_DATA].slice(0);var allFound=true;for(var y=0;allFound===true&&yGENERICS_DATA&&obj[GENERICS_DATA].length!==0){var tmp_lev=checkGenerics(obj,val);if(tmp_lev<=MAX_LEV_DISTANCE){return tmp_lev}}else{return 0}}if(literalSearch===true){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>0){var length=obj[GENERICS_DATA].length;for(x=0;xGENERICS_DATA&&obj[GENERICS_DATA].length>0){var olength=obj[GENERICS_DATA].length;for(x=0;x0){var length=obj.type[INPUTS_DATA].length;for(var i=0;iOUTPUT_DATA){var ret=obj.type[OUTPUT_DATA];if(typeof ret[0]==="string"){ret=[ret]}for(var x=0;xlength){return MAX_LEV_DISTANCE+1}for(var i=0;ilength){break}var lev_total=0;var aborted=false;for(var x=0;xMAX_LEV_DISTANCE){aborted=true;break}lev_total+=lev}if(aborted===false){ret_lev=Math.min(ret_lev,Math.round(lev_total/clength))}}return ret_lev}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER)return true;if(filter===type)return true;var name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function generateId(ty){if(ty.parent&&ty.parent.name){return itemTypes[ty.ty]+ty.path+ty.parent.name+ty.name}return itemTypes[ty.ty]+ty.path+ty.name}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,desc:item.desc,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,}}function handleAliases(ret,query,filterCrates){var aliases=[];var crateAliases=[];var i;if(filterCrates!==undefined){if(ALIASES[filterCrates]&&ALIASES[filterCrates][query.search]){for(i=0;iMAX_RESULTS){ret.others.pop()}};onEach(aliases,pushFunc);onEach(crateAliases,pushFunc)}var nSearchWords=searchWords.length;var i;var ty;var fullId;var returned;var in_args;if((val.charAt(0)==="\""||val.charAt(0)==="'")&&val.charAt(val.length-1)===val.charAt(0)){val=extractGenerics(val.substr(1,val.length-2));for(i=0;i")>-1){var trimmer=function(s){return s.trim()};var parts=val.split("->").map(trimmer);var input=parts[0];var inputs=input.split(",").map(trimmer).sort();for(i=0;i1?paths.length-1:1);var lev;for(j=0;j1){lev=checkPath(contains,paths[paths.length-1],ty);if(lev>MAX_LEV_DISTANCE){continue}else if(lev>0){lev_add=lev/10}}returned=MAX_LEV_DISTANCE+1;in_args=MAX_LEV_DISTANCE+1;var index=-1;lev=MAX_LEV_DISTANCE+1;fullId=generateId(ty);if(searchWords[j].indexOf(split[i])>-1||searchWords[j].indexOf(val)>-1||searchWords[j].replace(/_/g,"").indexOf(val)>-1){if(typePassesFilter(typeFilter,ty.ty)&&results[fullId]===undefined){index=searchWords[j].replace(/_/g,"").indexOf(val)}}if((lev=levenshtein(searchWords[j],val))<=MAX_LEV_DISTANCE){if(typePassesFilter(typeFilter,ty.ty)===false){lev=MAX_LEV_DISTANCE+1}else{lev+=1}}in_args=findArg(ty,valGenerics,false,typeFilter);returned=checkReturned(ty,valGenerics,false,typeFilter);lev+=lev_add;if(lev>0&&val.length>3&&searchWords[j].indexOf(val)>-1){if(val.length<6){lev-=1}else{lev=0}}if(in_args<=MAX_LEV_DISTANCE){if(results_in_args[fullId]===undefined){results_in_args[fullId]={id:j,index:index,lev:in_args,}}results_in_args[fullId].lev=Math.min(results_in_args[fullId].lev,in_args)}if(returned<=MAX_LEV_DISTANCE){if(results_returned[fullId]===undefined){results_returned[fullId]={id:j,index:index,lev:returned,}}results_returned[fullId].lev=Math.min(results_returned[fullId].lev,returned)}if(index!==-1||lev<=MAX_LEV_DISTANCE){if(index!==-1&&paths.length<2){lev=0}if(results[fullId]===undefined){results[fullId]={id:j,index:index,lev:lev,}}results[fullId].lev=Math.min(results[fullId].lev,lev)}}}var ret={"in_args":sortResults(results_in_args,true),"returned":sortResults(results_returned,true),"others":sortResults(results),};handleAliases(ret,query,filterCrates);return ret}function validateResult(name,path,keys,parent){for(var i=0;i-1||path.indexOf(keys[i])>-1||(parent!==undefined&&parent.name!==undefined&&parent.name.toLowerCase().indexOf(keys[i])>-1)||levenshtein(name,keys[i])<=MAX_LEV_DISTANCE)){return false}}return true}function getQuery(raw){var matches,type,query;query=raw;matches=query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);if(matches){type=matches[1].replace(/^const$/,"constant");query=query.substring(matches[0].length)}return{raw:raw,query:query,type:type,id:query+type}}function initSearchNav(){var hoverTimeout;var click_func=function(e){var el=e.target;while(el.tagName!=="TR"){el=el.parentNode}var dst=e.target.getElementsByTagName("a");if(dst.length<1){return}dst=dst[0];if(window.location.pathname===dst.pathname){hideSearchResults();document.location.href=dst.href}};var mouseover_func=function(e){var el=e.target;while(el.tagName!=="TR"){el=el.parentNode}clearTimeout(hoverTimeout);hoverTimeout=setTimeout(function(){onEachLazy(document.getElementsByClassName("search-results"),function(e){onEachLazy(e.getElementsByClassName("result"),function(i_e){removeClass(i_e,"highlighted")})});addClass(el,"highlighted")},20)};onEachLazy(document.getElementsByClassName("search-results"),function(e){onEachLazy(e.getElementsByClassName("result"),function(i_e){i_e.onclick=click_func;i_e.onmouseover=mouseover_func})});search_input.onkeydown=function(e){var actives=[[],[],[]];var current=0;onEachLazy(document.getElementById("results").childNodes,function(e){onEachLazy(e.getElementsByClassName("highlighted"),function(e){actives[current].push(e)});current+=1});if(e.which===38){if(!actives[currentTab].length||!actives[currentTab][0].previousElementSibling){return}addClass(actives[currentTab][0].previousElementSibling,"highlighted");removeClass(actives[currentTab][0],"highlighted")}else if(e.which===40){if(!actives[currentTab].length){var results=document.getElementById("results").childNodes;if(results.length>0){var res=results[currentTab].getElementsByClassName("result");if(res.length>0){addClass(res[0],"highlighted")}}}else if(actives[currentTab][0].nextElementSibling){addClass(actives[currentTab][0].nextElementSibling,"highlighted");removeClass(actives[currentTab][0],"highlighted")}}else if(e.which===13){if(actives[currentTab].length){document.location.href=actives[currentTab][0].getElementsByTagName("a")[0].href}}else if(e.which===9){if(e.shiftKey){printTab(currentTab>0?currentTab-1:2)}else{printTab(currentTab>1?0:currentTab+1)}e.preventDefault()}else if(e.which===16){}else if(actives[currentTab].length>0){removeClass(actives[currentTab][0],"highlighted")}}}function buildHrefAndPath(item){var displayPath;var href;var type=itemTypes[item.ty];var name=item.name;var path=item.path;if(type==="mod"){displayPath=path+"::";href=rootPath+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="primitive"||type==="keyword"){displayPath="";href=rootPath+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=rootPath+name+"/index.html"}else if(item.parent!==undefined){var myparent=item.parent;var anchor="#"+type+"."+name;var parentType=itemTypes[myparent.ty];var pageType=parentType;var pageName=myparent.name;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){var splitPath=item.path.split("::");var enumName=splitPath.pop();path=splitPath.join("::");displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="#variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}href=rootPath+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html"+anchor}else{displayPath=item.path+"::";href=rootPath+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href]}function escape(content){var h1=document.createElement("h1");h1.textContent=content;return h1.innerHTML}function pathSplitter(path){var tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}function addTab(array,query,display){var extraStyle="";if(display===false){extraStyle=" style=\"display: none;\""}var output="";var duplicates={};var length=0;if(array.length>0){output="";array.forEach(function(item){var name,type;name=item.name;type=itemTypes[item.ty];if(item.is_alias!==true){if(duplicates[item.fullPath]){return}duplicates[item.fullPath]=true}length+=1;output+=""});output+="
"+""+(item.is_alias===true?(""+item.alias+"  - see "):"")+item.displayPath+""+name+""+""+""+escape(item.desc)+" 
"}else{output="
No results :(
"+"Try on DuckDuckGo?

"+"Or try looking in one of these:
"}return[output,length]}function makeTabHeader(tabNb,text,nbElems){if(currentTab===tabNb){return"
"+text+"
("+nbElems+")
"}return"
"+text+"
("+nbElems+")
"}function showResults(results){if(results.others.length===1&&getCurrentValue("rustdoc-go-to-only-result")==="true"){var elem=document.createElement("a");elem.href=results.others[0].href;elem.style.display="none";document.body.appendChild(elem);elem.click()}var query=getQuery(search_input.value);currentResults=query.id;var ret_others=addTab(results.others,query);var ret_in_args=addTab(results.in_args,query,false);var ret_returned=addTab(results.returned,query,false);var output="

Results for "+escape(query.query)+(query.type?" (type: "+escape(query.type)+")":"")+"

"+"
"+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
"+ret_others[0]+ret_in_args[0]+ret_returned[0]+"
";var search=getSearchElement();search.innerHTML=output;showSearchResults(search);var tds=search.getElementsByTagName("td");var td_width=0;if(tds.length>0){td_width=tds[0].offsetWidth}var width=search.offsetWidth-40-td_width;onEachLazy(search.getElementsByClassName("desc"),function(e){e.style.width=width+"px"});initSearchNav();var elems=document.getElementById("titles").childNodes;elems[0].onclick=function(){printTab(0)};elems[1].onclick=function(){printTab(1)};elems[2].onclick=function(){printTab(2)};printTab(currentTab)}function execSearch(query,searchWords,filterCrates){function getSmallest(arrays,positions,notDuplicates){var start=null;for(var it=0;itpositions[it]&&(start===null||start>arrays[it][positions[it]].lev)&&!notDuplicates[arrays[it][positions[it]].fullPath]){start=arrays[it][positions[it]].lev}}return start}function mergeArrays(arrays){var ret=[];var positions=[];var notDuplicates={};for(var x=0;xpositions[x]&&arrays[x][positions[x]].lev===smallest&&!notDuplicates[arrays[x][positions[x]].fullPath]){ret.push(arrays[x][positions[x]]);notDuplicates[arrays[x][positions[x]].fullPath]=true;positions[x]+=1}}}return ret}var queries=query.raw.split(",");var results={"in_args":[],"returned":[],"others":[],};for(var i=0;i1){return{"in_args":mergeArrays(results.in_args),"returned":mergeArrays(results.returned),"others":mergeArrays(results.others),}}return{"in_args":results.in_args[0],"returned":results.returned[0],"others":results.others[0],}}function getFilterCrates(){var elem=document.getElementById("crate-search");if(elem&&elem.value!=="All crates"&&hasOwnProperty(rawSearchIndex,elem.value)){return elem.value}return undefined}function search(e,forced){var params=getQueryStringParams();var query=getQuery(search_input.value.trim());if(e){e.preventDefault()}if(query.query.length===0){return}if(forced!==true&&query.id===currentResults){if(query.query.length>0){putBackSearch(search_input)}return}document.title="Results for "+query.query+" - Rust";if(browserSupportsHistoryApi()){if(!history.state&&!params.search){history.pushState(query,"","?search="+encodeURIComponent(query.raw))}else{history.replaceState(query,"","?search="+encodeURIComponent(query.raw))}}var filterCrates=getFilterCrates();showResults(execSearch(query,index,filterCrates))}function buildIndex(rawSearchIndex){searchIndex=[];var searchWords=[];var i;var currentIndex=0;for(var crate in rawSearchIndex){if(!hasOwnProperty(rawSearchIndex,crate)){continue}var crateSize=0;searchWords.push(crate);searchIndex.push({crate:crate,ty:1,name:crate,path:"",desc:rawSearchIndex[crate].doc,type:null,});currentIndex+=1;var items=rawSearchIndex[crate].i;var paths=rawSearchIndex[crate].p;var aliases=rawSearchIndex[crate].a;var len=paths.length;for(i=0;i0){search_input.value=params.search;search(e)}else{search_input.value="";hideSearchResults()}})}search()}index=buildIndex(rawSearchIndex);startSearch();if(rootPath==="../"||rootPath==="./"){var sidebar=document.getElementsByClassName("sidebar-elems")[0];if(sidebar){var div=document.createElement("div");div.className="block crate";div.innerHTML="

Crates

";var ul=document.createElement("ul");div.appendChild(ul);var crates=[];for(var crate in rawSearchIndex){if(!hasOwnProperty(rawSearchIndex,crate)){continue}crates.push(crate)}crates.sort();for(var i=0;i"+""+"
"+code.outerHTML+"
";list.appendChild(display)}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}function labelForToggleButton(sectionIsCollapsed){if(sectionIsCollapsed){return"+"}return"\u2212"}function onEveryMatchingChild(elem,className,func){if(elem&&className&&func){var length=elem.childNodes.length;var nodes=elem.childNodes;for(var i=0;i"+labelForToggleButton(sectionIsCollapsed)+"
]";return toggle}function createToggle(toggle,otherMessage,fontSize,extraClass,show){var span=document.createElement("span");span.className="toggle-label";if(show){span.style.display="none"}if(!otherMessage){span.innerHTML=" Expand description"}else{span.innerHTML=otherMessage}if(fontSize){span.style.fontSize=fontSize}var mainToggle=toggle.cloneNode(true);mainToggle.appendChild(span);var wrapper=document.createElement("div");wrapper.className="toggle-wrapper";if(!show){addClass(wrapper,"collapsed");var inner=mainToggle.getElementsByClassName("inner");if(inner&&inner.length>0){inner[0].innerHTML="+"}}if(extraClass){addClass(wrapper,extraClass)}wrapper.appendChild(mainToggle);return wrapper}(function(){var toggle=createSimpleToggle(false);var hideMethodDocs=getCurrentValue("rustdoc-auto-hide-method-docs")==="true";var pageId=getPageId();var func=function(e){var next=e.nextElementSibling;if(!next){return}if(hasClass(next,"docblock")===true||(hasClass(next,"stability")===true&&hasClass(next.nextElementSibling,"docblock")===true)){var newToggle=toggle.cloneNode(true);insertAfter(newToggle,e.childNodes[e.childNodes.length-1]);if(hideMethodDocs===true&&hasClass(e,"method")===true){collapseDocs(newToggle,"hide",pageId)}}};var funcImpl=function(e){var next=e.nextElementSibling;if(next&&hasClass(next,"docblock")){next=next.nextElementSibling}if(!next){return}if(next.getElementsByClassName("method").length>0&&hasClass(e,"impl")){insertAfter(toggle.cloneNode(true),e.childNodes[e.childNodes.length-1])}};onEachLazy(document.getElementsByClassName("method"),func);onEachLazy(document.getElementsByClassName("associatedconstant"),func);onEachLazy(document.getElementsByClassName("impl"),funcImpl);var impl_call=function(){};if(hideMethodDocs===true){impl_call=function(e,newToggle){if(e.id.match(/^impl(?:-\d+)?$/)===null){if(hasClass(e,"impl")===true){collapseDocs(newToggle,"hide",pageId)}}}}var newToggle=document.createElement("a");newToggle.href="javascript:void(0)";newToggle.className="collapse-toggle hidden-default collapsed";newToggle.innerHTML="["+labelForToggleButton(true)+"] Show hidden undocumented items";function toggleClicked(){if(hasClass(this,"collapsed")){removeClass(this,"collapsed");onEachLazy(this.parentNode.getElementsByClassName("hidden"),function(x){if(hasClass(x,"content")===false){removeClass(x,"hidden");addClass(x,"x")}},true);this.innerHTML="["+labelForToggleButton(false)+"] Hide undocumented items"}else{addClass(this,"collapsed");onEachLazy(this.parentNode.getElementsByClassName("x"),function(x){if(hasClass(x,"content")===false){addClass(x,"hidden");removeClass(x,"x")}},true);this.innerHTML="["+labelForToggleButton(true)+"] Show hidden undocumented items"}}onEachLazy(document.getElementsByClassName("impl-items"),function(e){onEachLazy(e.getElementsByClassName("associatedconstant"),func);var hiddenElems=e.getElementsByClassName("hidden");var needToggle=false;var hlength=hiddenElems.length;for(var i=0;iLoading search results...";showSearchResults(search)}var sidebar_menu=document.getElementsByClassName("sidebar-menu")[0];if(sidebar_menu){sidebar_menu.onclick=function(){var sidebar=document.getElementsByClassName("sidebar")[0];if(hasClass(sidebar,"mobile")===true){hideSidebar()}else{showSidebar()}}}window.onresize=function(){hideSidebar()};autoCollapse(getPageId(),getCurrentValue("rustdoc-collapse")==="true");if(window.location.hash&&window.location.hash.length>0){expandSection(window.location.hash.replace(/^#/,""))}if(main){onEachLazy(main.getElementsByClassName("loading-content"),function(e){e.remove()});onEachLazy(main.childNodes,function(e){if(e.tagName==="H2"||e.tagName==="H3"){var nextTagName=e.nextElementSibling.tagName;if(nextTagName=="H2"||nextTagName=="H3"){e.nextElementSibling.style.display="flex"}else{e.nextElementSibling.style.display="block"}}})}window.addSearchOptions=function(crates){var elem=document.getElementById("crate-search");if(!elem){return}var crates_text=[];if(Object.keys(crates).length>1){for(var crate in crates){if(hasOwnProperty(crates,crate)){crates_text.push(crate)}}}crates_text.sort(function(a,b){var lower_a=a.toLowerCase();var lower_b=b.toLowerCase();if(lower_alower_b){return 1}return 0});var savedCrate=getCurrentValue("rustdoc-saved-filter-crate");for(var i=0;i"
"+x[0]+"
"+x[1]+"
").join("");var div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

Keyboard Shortcuts

"+shortcuts+"
";var infos=["Prefix searches with a type followed by a colon (e.g., fn:) to \ + restrict the search to a given type.","Accepted types are: fn, mod, struct, \ + enum, trait, type, macro, \ + and const.","Search functions by type signature (e.g., vec -> usize or \ + * -> vec)","Search multiple things at once by splitting your query with comma (e.g., \ + str,u8 or String,struct:Vec,test)","You can look for items with an exact name by putting double quotes around \ + your request: \"string\"","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

"+x+"

").join("");var div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

Search Tricks

"+infos;container.appendChild(div_shortcuts);container.appendChild(div_infos);popup.appendChild(container);insertAfter(popup,getSearchElement())}onHashChange(null);window.onhashchange=onHashChange;buildHelperPopup()}());window.onunload=function(){} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/normalize.css b/static/docs-rs/bdk/0.1.0-beta.1/normalize.css new file mode 100644 index 0000000000..45b6cb2638 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/normalize.css @@ -0,0 +1,2 @@ +/*! normalize.css v3.0.0 | MIT License | git.io/normalize */ +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/noscript.css b/static/docs-rs/bdk/0.1.0-beta.1/noscript.css new file mode 100644 index 0000000000..351b41cf8e --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/noscript.css @@ -0,0 +1 @@ +#main>h2+div,#main>h2+h3,#main>h3+div{display:block;}.loading-content{display:none;}#main>h2+div,#main>h3+div{display:block;}#main>h2+h3{display:flex;} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/rust-logo.png b/static/docs-rs/bdk/0.1.0-beta.1/rust-logo.png new file mode 100644 index 0000000000..74b4bd6950 Binary files /dev/null and b/static/docs-rs/bdk/0.1.0-beta.1/rust-logo.png differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/rustdoc.css b/static/docs-rs/bdk/0.1.0-beta.1/rustdoc.css new file mode 100644 index 0000000000..1d4cec165b --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/rustdoc.css @@ -0,0 +1 @@ + @font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular.woff") format('woff');}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:normal;font-weight:400;src:local('Source Serif Pro'),url("SourceSerifPro-Regular.ttf.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:italic;font-weight:400;src:local('Source Serif Pro Italic'),url("SourceSerifPro-It.ttf.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:normal;font-weight:700;src:local('Source Serif Pro Bold'),url("SourceSerifPro-Bold.ttf.woff") format('woff');}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular.woff") format('woff');}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold.woff") format('woff');}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}html{content:"";}@media (prefers-color-scheme:light){html{content:"light";}}@media (prefers-color-scheme:dark){html{content:"dark";}}body{font:16px/1.4 "Source Serif Pro",serif;margin:0;position:relative;padding:10px 15px 20px 15px;-webkit-font-feature-settings:"kern","liga";-moz-font-feature-settings:"kern","liga";font-feature-settings:"kern","liga";}h1{font-size:1.5em;}h2{font-size:1.4em;}h3{font-size:1.3em;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.important),h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){font-weight:500;margin:20px 0 15px 0;padding-bottom:6px;}h1.fqn{border-bottom:1px dashed;margin-top:0;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){border-bottom:1px solid;}h3.impl,h3.method,h4.method,h3.type,h4.type,h4.associatedconstant{flex-basis:100%;font-weight:600;margin-top:16px;margin-bottom:10px;position:relative;}h3.impl,h3.method,h3.type{padding-left:15px;}h1,h2,h3,h4,.sidebar,a.source,.search-input,.content table :not(code)>a,.collapse-toggle,div.item-list .out-of-band,#source-sidebar,#sidebar-toggle{font-family:"Fira Sans",sans-serif;}ol,ul{padding-left:25px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.6em;}p{margin:0 0 .6em 0;}summary{outline:none;}code,pre,a.test-arrow{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.1em;}.docblock pre code,.docblock-short pre code{padding:0;}pre{padding:14px;}.source .content pre{padding:20px;}img{max-width:100%;}li{position:relative;}.source .content{margin-top:50px;max-width:none;overflow:visible;margin-left:0px;min-width:70em;}nav.sub{font-size:16px;text-transform:uppercase;}.sidebar{width:200px;position:fixed;left:0;top:0;bottom:0;overflow:auto;}*{scrollbar-width:initial;}.sidebar{scrollbar-width:thin;}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;}.sidebar .block>ul>li{margin-right:-10px;}.content,nav{max-width:960px;}.hidden{display:none !important;}.logo-container{height:100px;width:100px;position:relative;margin:20px auto;display:block;margin-top:10px;}.logo-container>img{max-width:100px;max-height:100px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:block;}.sidebar .location{border:1px solid;font-size:17px;margin:30px 10px 20px 10px;text-align:center;word-wrap:break-word;}.sidebar .version{font-size:15px;text-align:center;border-bottom:1px solid;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;}.location:empty{border:none;}.location a:first-child{font-weight:500;}.block{padding:0;margin-bottom:14px;}.block h2,.block h3{margin-top:0;margin-bottom:8px;text-align:center;}.block ul,.block li{margin:0 10px;padding:0;list-style:none;}.block a{display:block;text-overflow:ellipsis;overflow:hidden;line-height:15px;padding:7px 5px;font-size:14px;font-weight:300;transition:border 500ms ease-out;}.sidebar-title{border-top:1px solid;border-bottom:1px solid;text-align:center;font-size:17px;margin-bottom:5px;}.sidebar-links{margin-bottom:15px;}.sidebar-links>a{padding-left:10px;width:100%;}.sidebar-menu{display:none;}.content{padding:15px 0;}.source .content pre.rust{white-space:pre;overflow:auto;padding-left:0;}.rustdoc:not(.source) .example-wrap{display:inline-flex;margin-bottom:10px;position:relative;}.example-wrap{width:100%;}.example-wrap>pre.line-number{overflow:initial;border:1px solid;border-top-left-radius:5px;border-bottom-left-radius:5px;padding:13px 8px;text-align:right;}.rustdoc:not(.source) .example-wrap>pre.rust{width:100%;overflow-x:auto;}.rustdoc:not(.source) .example-wrap>pre{margin:0;}#search{margin-left:230px;position:relative;}#results{position:absolute;right:0;left:0;overflow:auto;}#results>table{width:100%;table-layout:fixed;}.content pre.line-numbers{float:left;border:none;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}.line-numbers span{cursor:pointer;}.docblock-short p{display:inline;}.docblock-short.nowrap{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.docblock-short p{overflow:hidden;text-overflow:ellipsis;margin:0;}.docblock code,.docblock-short code{white-space:pre-wrap;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom:1px solid;}#main>.docblock h1{font-size:1.3em;}#main>.docblock h2{font-size:1.15em;}#main>.docblock h3,#main>.docblock h4,#main>.docblock h5{font-size:1em;}#main>h2+div,#main>h2+h3,#main>h3+div{display:none;flex-wrap:wrap;}.docblock h1{font-size:1em;}.docblock h2{font-size:0.95em;}.docblock h3,.docblock h4,.docblock h5{font-size:0.9em;}.docblock{margin-left:24px;position:relative;}.content .out-of-band{float:right;font-size:23px;margin:0px;padding:0px;font-weight:normal;}h3.impl>.out-of-band{font-size:21px;}h4.method>.out-of-band{font-size:19px;}h4>code,h3>code,.invisible>code{max-width:calc(100% - 41px);display:block;}.invisible{width:100%;display:inline-block;}.content .in-band{margin:0px;padding:0px;}.in-band>code{display:inline-block;}#main{position:relative;}#main>.since{top:inherit;font-family:"Fira Sans",sans-serif;}.content table:not(.table-display){border-spacing:0 5px;}.content td{vertical-align:top;}.content td:first-child{padding-right:20px;}.content td p:first-child{margin-top:0;}.content td h1,.content td h2{margin-left:0;font-size:1.1em;}.content tr:first-child td{border-top:0;}.docblock table{margin:.5em 0;width:calc(100% - 2px);border:1px dashed;}.docblock table td{padding:.5em;border:1px dashed;}.docblock table th{padding:.5em;text-align:left;border:1px solid;}.fields+table{margin-bottom:1em;}.content .item-list{list-style-type:none;padding:0;}.content .multi-column{-moz-column-count:5;-moz-column-gap:2.5em;-webkit-column-count:5;-webkit-column-gap:2.5em;column-count:5;column-gap:2.5em;}.content .multi-column li{width:100%;display:inline-block;}.content .method{font-size:1em;position:relative;}.content .method .where,.content .fn .where,.content .where.fmt-newline{display:block;font-size:0.8em;}.content .methods>div{margin-left:40px;margin-bottom:15px;}.content .docblock>.impl-items{margin-left:20px;margin-top:-34px;}.content .docblock>.impl-items>h4{border-bottom:0;}.content .docblock>.impl-items .table-display{margin:0;}.content .docblock>.impl-items table td{padding:0;}.toggle-wrapper.marg-left>.collapse-toggle{left:-24px;}.content .docblock>.impl-items .table-display,.impl-items table td{border:none;}.content .stability code{font-size:90%;}.content .stability{position:relative;margin-left:33px;margin-top:-13px;}.sub-variant>div>.stability{margin-top:initial;}.content .stability::before{content:'⬑';font-size:25px;position:absolute;top:-6px;left:-19px;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant{margin-left:20px;}.content .impl-items .docblock,.content .impl-items .stability{margin-bottom:.6em;}.content .impl-items>.stability{margin-left:40px;}.methods>.stability,.content .impl-items>.stability{margin-top:-8px;}.impl-items{flex-basis:100%;}#main>.stability{margin-top:0;}nav:not(.sidebar){border-bottom:1px solid;padding-bottom:10px;margin-bottom:10px;}nav.main{padding:20px 0;text-align:center;}nav.main .current{border-top:1px solid;border-bottom:1px solid;}nav.main .separator{border:1px solid;display:inline-block;height:23px;margin:0 20px;}nav.sum{text-align:right;}nav.sub form{display:inline;}nav.sub,.content{margin-left:230px;}a{text-decoration:none;background:transparent;}.small-section-header:hover>.anchor{display:initial;}.in-band:hover>.anchor,.impl:hover>.anchor{display:inline-block;position:absolute;}.anchor{display:none;position:absolute;left:-7px;}.anchor.field{left:-5px;}.small-section-header>.anchor{left:-28px;padding-right:10px;}.anchor:before{content:'\2002\00a7\2002';}.docblock a:not(.srclink):not(.test-arrow):hover,.docblock-short a:not(.srclink):not(.test-arrow):hover,.stability a{text-decoration:underline;}.invisible>.srclink,h4>code+.srclink{position:absolute;top:0;right:0;font-size:17px;font-weight:normal;}.block a.current.crate{font-weight:500;}.search-container{position:relative;}.search-container>div{display:inline-flex;width:calc(100% - 34px);}#crate-search{margin-top:5px;padding:6px;padding-right:19px;flex:none;border:0;border-right:0;border-radius:4px 0 0 4px;outline:none;cursor:pointer;border-right:1px solid;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;text-overflow:"";background-repeat:no-repeat;background-color:transparent;background-size:20px;background-position:calc(100% - 1px) 56%;}.search-container>.top-button{position:absolute;right:0;top:10px;}.search-input{-moz-box-sizing:border-box !important;box-sizing:border-box !important;outline:none;border:none;border-radius:1px;margin-top:5px;padding:10px 16px;font-size:17px;transition:border-color 300ms ease;transition:border-radius 300ms ease-in-out;transition:box-shadow 300ms ease-in-out;width:100%;}#crate-search+.search-input{border-radius:0 1px 1px 0;width:calc(100% - 32px);}.search-input:focus{border-radius:2px;border:0;outline:0;}.search-results .desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;display:block;}.search-results a{display:block;}.content .search-results td:first-child{padding-right:0;width:50%;}.content .search-results td:first-child a{padding-right:10px;}.content .search-results td:first-child a:after{clear:both;content:"";display:block;}.content .search-results td:first-child a span{float:left;}tr.result span.primitive::after{content:' (primitive type)';font-style:italic;}tr.result span.keyword::after{content:' (keyword)';font-style:italic;}body.blur>:not(#help){filter:blur(8px);-webkit-filter:blur(8px);opacity:.7;}#help{width:100%;height:100vh;position:fixed;top:0;left:0;display:flex;justify-content:center;align-items:center;}#help>div{flex:0 0 auto;box-shadow:0 0 6px rgba(0,0,0,.2);width:550px;height:auto;border:1px solid;}#help dt{float:left;clear:left;display:block;}#help dd{margin:5px 35px;}#help .infos{padding-left:0;}#help h1,#help h2{margin-top:0;}#help>div div{width:50%;float:left;padding:20px;padding-left:17px;}.stab{display:table;border-width:1px;border-style:solid;padding:3px;margin-bottom:5px;font-size:90%;}.stab p{display:inline;}.stab summary{display:list-item;}.stab .emoji{font-size:1.5em;}.module-item .stab{border-radius:3px;display:inline-block;font-size:80%;line-height:1.2;margin-bottom:0;margin-right:.3em;padding:2px;vertical-align:text-bottom;}.module-item.unstable{opacity:0.65;}.since{font-weight:normal;font-size:initial;position:absolute;right:0;top:0;}.impl-items .since,.impl .since{flex-grow:0;padding-left:12px;padding-right:2px;position:initial;}.impl-items .srclink,.impl .srclink{flex-grow:0;font-size:17px;font-weight:normal;}.impl-items code,.impl code{flex-grow:1;}.impl-items h4,h4.impl,h3.impl{display:flex;flex-basis:100%;font-size:16px;margin-bottom:12px;justify-content:space-between;}.variants_table{width:100%;}.variants_table tbody tr td:first-child{width:1%;}td.summary-column{width:100%;}.summary{padding-right:0px;}pre.rust .question-mark{font-weight:bold;}a.test-arrow{display:inline-block;position:absolute;padding:5px 10px 5px 10px;border-radius:5px;font-size:130%;top:5px;right:5px;z-index:1;}a.test-arrow:hover{text-decoration:none;}.section-header:hover a:before{position:absolute;left:-25px;padding-right:10px;content:'\2002\00a7\2002';}.section-header:hover a{text-decoration:none;}.section-header a{color:inherit;}.collapse-toggle{font-weight:300;position:absolute;left:-23px;top:0;}h3>.collapse-toggle,h4>.collapse-toggle{font-size:0.8em;top:5px;}.toggle-wrapper>.collapse-toggle{left:-24px;margin-top:0px;}.toggle-wrapper{position:relative;margin-top:0;}.toggle-wrapper.collapsed{height:25px;transition:height .2s;margin-bottom:.6em;}.collapse-toggle>.inner{display:inline-block;width:1.2ch;text-align:center;}.collapse-toggle.hidden-default{position:relative;margin-left:20px;}.since+.srclink{display:table-cell;padding-left:10px;}.item-spacer{width:100%;height:12px;}.out-of-band>span.since{position:initial;font-size:20px;margin-right:5px;}.toggle-wrapper>.collapse-toggle{left:0;}.variant+.toggle-wrapper+.docblock>p{margin-top:5px;}.sub-variant,.sub-variant>h3{margin-top:1px !important;}#main>.sub-variant>h3{font-size:15px;margin-left:25px;margin-bottom:5px;}.sub-variant>div{margin-left:20px;margin-bottom:10px;}.sub-variant>div>span{display:block;position:relative;}.toggle-label{display:inline-block;margin-left:4px;margin-top:3px;}.enum>.toggle-wrapper+.docblock,.struct>.toggle-wrapper+.docblock{margin-left:30px;margin-bottom:20px;margin-top:5px;}.docblock>.section-header:first-child{margin-left:15px;margin-top:0;}.docblock>.section-header:first-child:hover>a:before{left:-10px;}.enum>.collapsed,.struct>.collapsed{margin-bottom:25px;}#main>.variant,#main>.structfield{display:block;}.attributes{display:block;margin-top:0px !important;margin-right:0px;margin-bottom:0px !important;margin-left:30px;}.toggle-attributes.collapsed{margin-bottom:0;}.impl-items>.toggle-attributes{margin-left:20px;}.impl-items .attributes{font-weight:500;}:target>code{opacity:1;}.information{position:absolute;left:-25px;margin-top:7px;z-index:1;}.tooltip{position:relative;display:inline-block;cursor:pointer;}.tooltip .tooltiptext{width:120px;display:none;text-align:center;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;top:-5px;left:105%;z-index:10;font-size:16px;}.tooltip:hover .tooltiptext{display:inline;}.tooltip .tooltiptext::after{content:" ";position:absolute;top:50%;left:16px;margin-top:-5px;border-width:5px;border-style:solid;}.tooltip.compile_fail,.tooltip.ignore{font-weight:bold;font-size:20px;}.tooltip .tooltiptext{border:1px solid;font-weight:normal;}pre.rust{position:relative;tab-size:4;-moz-tab-size:4;}.search-failed{text-align:center;margin-top:20px;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#titles{height:35px;}#titles>div{float:left;width:33.3%;text-align:center;font-size:18px;cursor:pointer;border-top:2px solid;}#titles>div:not(:last-child){margin-right:1px;width:calc(33.3% - 1px);}#titles>div>div.count{display:inline-block;font-size:16px;}#all-types{text-align:center;border:1px solid;margin:0 10px;margin-bottom:10px;display:block;border-radius:7px;}#all-types>p{margin:5px 0;}#sidebar-toggle{position:fixed;top:30px;left:300px;z-index:10;padding:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;cursor:pointer;font-weight:bold;transition:left .5s;font-size:1.2em;border:1px solid;border-left:0;}#source-sidebar{position:fixed;top:0;bottom:0;left:0;width:300px;z-index:1;overflow:auto;transition:left .5s;border-right:1px solid;}#source-sidebar>.title{font-size:1.5em;text-align:center;border-bottom:1px solid;margin-bottom:6px;}.theme-picker{position:absolute;left:211px;top:19px;}.theme-picker button{outline:none;}#settings-menu{position:absolute;right:0;top:10px;outline:none;}#theme-picker,#settings-menu{padding:4px;width:27px;height:29px;border:1px solid;border-radius:3px;cursor:pointer;}#theme-choices{display:none;position:absolute;left:0;top:28px;border:1px solid;border-radius:3px;z-index:1;cursor:pointer;}#theme-choices>button{border:none;width:100%;padding:4px;text-align:center;background:rgba(0,0,0,0);}#theme-choices>button:not(:first-child){border-top:1px solid;}@media (max-width:700px){body{padding-top:0px;}.rustdoc>.sidebar{height:45px;min-height:40px;margin:0;margin-left:-15px;padding:0 15px;position:static;z-index:11;}.sidebar>.location{float:right;margin:0px;margin-top:2px;padding:3px 10px 1px 10px;min-height:39px;background:inherit;text-align:left;font-size:24px;}.sidebar .location:empty{padding:0;}.sidebar .logo-container{width:35px;height:35px;margin-top:5px;margin-bottom:5px;float:left;margin-left:50px;}.sidebar .logo-container>img{max-width:35px;max-height:35px;}.sidebar-menu{position:fixed;z-index:10;font-size:2rem;cursor:pointer;width:45px;left:0;text-align:center;display:block;border-bottom:1px solid;border-right:1px solid;height:45px;}.rustdoc.source>.sidebar>.sidebar-menu{display:none;}.sidebar-elems{position:fixed;z-index:1;left:0;top:45px;bottom:0;overflow-y:auto;border-right:1px solid;display:none;}.sidebar>.block.version{border-bottom:none;margin-top:12px;}nav.sub{width:calc(100% - 32px);float:right;}.content{margin-left:0px;}#main{margin-top:45px;padding:0;}.content .in-band{width:100%;}.content h4>.out-of-band{position:inherit;}.toggle-wrapper>.collapse-toggle{left:0px;}.toggle-wrapper{height:1.5em;}#search{margin-left:0;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant{display:flex;}.anchor{display:none !important;}h1.fqn{overflow:initial;}.theme-picker{left:10px;top:54px;z-index:1;}#titles>div>div.count{float:left;width:100%;}#titles{height:50px;}.sidebar.mobile{position:fixed;width:100%;margin-left:0;background-color:rgba(0,0,0,0);height:100%;}.sidebar{width:calc(100% + 30px);}.show-it{display:block;width:246px;}.show-it>.block.items{margin:8px 0;}.show-it>.block.items>ul{margin:0;}.show-it>.block.items>ul>li{text-align:center;margin:2px 0;}.show-it>.block.items>ul>li>a{font-size:21px;}#sidebar-filler{position:fixed;left:45px;width:calc(100% - 45px);top:0;height:45px;z-index:-1;border-bottom:1px solid;}.collapse-toggle{left:-20px;}.impl>.collapse-toggle{left:-10px;}#all-types{margin:10px;}#sidebar-toggle{top:100px;width:30px;font-size:1.5rem;text-align:center;padding:0;}#source-sidebar{z-index:11;}#main>.line-numbers{margin-top:0;}}@media print{nav.sub,.content .out-of-band,.collapse-toggle{display:none;}}@media (max-width:416px){#titles{height:73px;}#titles>div{height:73px;}}h3.important{margin:0;margin-bottom:13px;font-size:19px;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px;border-radius:3px;box-shadow:inset 0 -1px 0;cursor:default;}.hidden-by-impl-hider,.hidden-by-usual-hider{display:none !important;}#implementations-list>h3>span.in-band{width:100%;}.table-display{width:100%;border:0;border-collapse:collapse;border-spacing:0;font-size:16px;}.table-display tr td:first-child{padding-right:0;}.table-display tr td:last-child{float:right;}.table-display .out-of-band{position:relative;font-size:19px;display:block;}#implementors-list>.impl-items .table-display .out-of-band{font-size:17px;}.table-display td:hover .anchor{display:block;top:2px;left:-5px;}#main>ul{padding-left:10px;}#main>ul>li{list-style:none;}.non-exhaustive{margin-bottom:1em;}div.children{padding-left:27px;display:none;}div.name{cursor:pointer;position:relative;margin-left:16px;}div.files>a{display:block;padding:0 3px;}div.files>a:hover,div.name:hover{background-color:#a14b4b;}div.name.expand+.children{display:block;}div.name::before{content:"\25B6";padding-left:4px;font-size:0.7em;position:absolute;left:-16px;top:4px;}div.name.expand::before{transform:rotate(90deg);left:-15px;top:2px;}.type-decl>pre>.toggle-wrapper.toggle-attributes.top-attr{margin-left:0 !important;}.type-decl>pre>.docblock.attributes.top-attr{margin-left:1.8em !important;}.type-decl>pre>.toggle-attributes{margin-left:2.2em;}.type-decl>pre>.docblock.attributes{margin-left:4em;} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/search-index.js b/static/docs-rs/bdk/0.1.0-beta.1/search-index.js new file mode 100644 index 0000000000..178789e6a9 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/search-index.js @@ -0,0 +1,4 @@ +var searchIndex = JSON.parse('{\ +"bdk":{"doc":"","i":[[3,"FeeRate","bdk","Fee rate",null,null],[3,"UTXO","","A wallet unspent output",null,null],[12,"outpoint","","",0,null],[12,"txout","","",0,null],[12,"is_internal","","",0,null],[3,"TransactionDetails","","A wallet transaction",null,null],[12,"transaction","","",1,null],[12,"txid","","",1,null],[12,"timestamp","","",1,null],[12,"received","","",1,null],[12,"sent","","",1,null],[12,"fees","","",1,null],[12,"height","","",1,null],[4,"Error","","Errors that can be thrown by the `Wallet`",null,null],[13,"KeyMismatch","","",2,null],[13,"MissingInputUTXO","","",2,null],[13,"InvalidU32Bytes","","",2,null],[13,"Generic","","",2,null],[13,"ScriptDoesntHaveAddressForm","","",2,null],[13,"SendAllMultipleOutputs","","",2,null],[13,"NoAddressees","","",2,null],[13,"OutputBelowDustLimit","","",2,null],[13,"InsufficientFunds","","",2,null],[13,"InvalidAddressNetwork","","",2,null],[13,"UnknownUTXO","","",2,null],[13,"DifferentTransactions","","",2,null],[13,"TransactionNotFound","","",2,null],[13,"TransactionConfirmed","","",2,null],[13,"IrreplaceableTransaction","","",2,null],[13,"FeeRateTooLow","","",2,null],[12,"required","bdk::Error","",3,null],[13,"ChecksumMismatch","bdk","",2,null],[13,"DifferentDescriptorStructure","","",2,null],[13,"SpendingPolicyRequired","","",2,null],[13,"InvalidPolicyPathError","","",2,null],[13,"Signer","","",2,null],[13,"Uncapable","","",2,null],[13,"OfflineClient","","",2,null],[13,"InvalidProgressValue","","",2,null],[13,"ProgressUpdateError","","",2,null],[13,"MissingCachedAddresses","","",2,null],[13,"InvalidOutpoint","","",2,null],[13,"Descriptor","","",2,null],[13,"AddressValidator","","",2,null],[13,"Encode","","",2,null],[13,"Miniscript","","",2,null],[13,"BIP32","","",2,null],[13,"Secp256k1","","",2,null],[13,"JSON","","",2,null],[13,"Hex","","",2,null],[13,"PSBT","","",2,null],[13,"Electrum","","",2,null],[13,"Esplora","","",2,null],[13,"CompactFilters","","",2,null],[13,"Sled","","",2,null],[4,"ScriptType","","Types of script",null,null],[13,"External","","",4,null],[13,"Internal","","",4,null],[0,"blockchain","","Blockchain backends",null,null],[3,"OfflineBlockchain","bdk::blockchain","Type that only implements [`Blockchain`] and is always…",null,null],[3,"NoopProgress","","Type that implements [`Progress`] and drops every update…",null,null],[3,"LogProgress","","Type that implements [`Progress`] and logs at level `INFO`…",null,null],[4,"Capability","","Capabilities that can be supported by a [`Blockchain`]…",null,null],[13,"FullHistory","","Can recover the full history of a wallet and not only the…",5,null],[13,"GetAnyTx","","Can fetch any historical transaction given its txid",5,null],[13,"AccurateFees","","Can compute accurate fees for the transactions found…",5,null],[5,"progress","","Shortcut to create a [`channel`] (pair of [`Sender`] and…",null,[[]]],[5,"noop_progress","","Create a new instance of [`NoopProgress`]",null,[[],["noopprogress",3]]],[5,"log_progress","","Create a nwe instance of [`LogProgress`]",null,[[],["logprogress",3]]],[0,"electrum","","Electrum",null,null],[3,"ElectrumBlockchain","bdk::blockchain::electrum","Wrapper over an Electrum Client that implements the…",null,null],[0,"esplora","bdk::blockchain","Esplora",null,null],[3,"EsploraBlockchain","bdk::blockchain::esplora","Structure that implements the logic to sync with Esplora",null,null],[4,"EsploraError","","Errors that can happen during a sync with…",null,null],[13,"Reqwest","","Error with the HTTP call",6,null],[13,"Parsing","","Invalid number returned",6,null],[13,"BitcoinEncoding","","Invalid Bitcoin data returned",6,null],[13,"TransactionNotFound","","Transaction not found",6,null],[11,"new","","Create a new instance of the client from a base URL",7,[[]]],[0,"compact_filters","bdk::blockchain","Compact Filters",null,null],[3,"Mempool","bdk::blockchain::compact_filters","Container for unconfirmed, but valid Bitcoin transactions",null,null],[3,"Peer","","A Bitcoin peer",null,null],[3,"CompactFiltersBlockchain","","Structure implementing the required blockchain traits",null,null],[4,"CompactFiltersError","","An error that can occur during sync with a…",null,null],[13,"InvalidResponse","","A peer sent an invalid or unexpected response",8,null],[13,"InvalidHeaders","","The headers returned are invalid",8,null],[13,"InvalidFilterHeader","","The compact filter headers returned are invalid",8,null],[13,"InvalidFilter","","The compact filter returned is invalid",8,null],[13,"MissingBlock","","The peer is missing a block in the valid chain",8,null],[13,"DataCorruption","","The data stored in the block filters storage are corrupted",8,null],[13,"NotConnected","","A peer is not connected",8,null],[13,"Timeout","","A peer took too long to reply to one of our messages",8,null],[13,"NoPeers","","No peers have been specified",8,null],[13,"DB","","Internal database error",8,null],[13,"IO","","Internal I/O error",8,null],[13,"BIP158","","Invalid BIP158 filter",8,null],[13,"Time","","Internal system time error",8,null],[13,"Global","","Wrapper for [`crate::error::Error`]",8,null],[11,"add_tx","","Add a transaction to the mempool",9,[[["transaction",3]]]],[11,"get_tx","","Look-up a transaction in the mempool given an…",9,[[["inventory",4]],[["transaction",3],["option",4]]]],[11,"has_tx","","Return whether or not the mempool contains a transaction…",9,[[["txid",3]]]],[11,"iter_txs","","Return the list of transactions contained in the mempool",9,[[],[["vec",3],["transaction",3]]]],[11,"connect","","Connect to a peer over a plaintext TCP connection",10,[[["tosocketaddrs",8],["arc",3],["network",4],["mempool",3]],[["compactfilterserror",4],["result",4]]]],[11,"connect_proxy","","Connect to a peer through a SOCKS5 proxy, optionally by…",10,[[["tosocketaddrs",8],["option",4],["arc",3],["network",4],["mempool",3],["totargetaddr",8]],[["compactfilterserror",4],["result",4]]]],[11,"get_version","","Return the [`VersionMessage`] sent by the peer",10,[[],["versionmessage",3]]],[11,"get_network","","Return the Bitcoin [`Network`] in use",10,[[],["network",4]]],[11,"get_mempool","","Return the mempool used by this peer",10,[[],[["mempool",3],["arc",3]]]],[11,"is_connected","","Return whether or not the peer is still connected",10,[[]]],[11,"send","","Send a raw Bitcoin message to the peer",10,[[["networkmessage",4]],[["result",4],["compactfilterserror",4]]]],[11,"recv","","Waits for a specific incoming Bitcoin message, optionally…",10,[[["duration",3],["option",4]],[["compactfilterserror",4],["result",4],["option",4]]]],[11,"new","","Construct a new instance given a list of peers, a path to…",11,[[["peer",3],["asref",8],["path",3],["option",4],["vec",3]],[["compactfilterserror",4],["result",4]]]],[6,"ProgressData","bdk::blockchain","Data sent with a progress update over a [`channel`]",null,null],[8,"BlockchainMarker","","Marker trait for a blockchain backend",null,null],[8,"Blockchain","","Trait that defines the actions that must be supported by a…",null,null],[10,"get_capabilities","","Return the set of [`Capability`] supported by this backend",12,[[],[["hashset",3],["capability",4]]]],[10,"setup","","Setup the backend and populate the internal database for…",12,[[["progress",8],["option",4]],[["result",4],["error",4]]]],[11,"sync","","Populate the internal database with transactions and UTXOs",12,[[["progress",8],["option",4]],[["result",4],["error",4]]]],[10,"get_tx","","Fetch a transaction from the blockchain given its txid",12,[[["txid",3]],[["error",4],["result",4],["option",4]]]],[10,"broadcast","","Broadcast a transaction",12,[[["transaction",3]],[["result",4],["error",4]]]],[10,"get_height","","Return the current height",12,[[],[["error",4],["result",4]]]],[10,"estimate_fee","","Estimate the fee rate required to confirm a transaction in…",12,[[],[["feerate",3],["result",4],["error",4]]]],[8,"Progress","","Trait for types that can receive and process progress…",null,null],[10,"update","","Send a new progress update",13,[[["string",3],["option",4]],[["result",4],["error",4]]]],[0,"database","bdk","Database types",null,null],[0,"memory","bdk::database","In-memory ephemeral database",null,null],[3,"MemoryDatabase","bdk::database::memory","In-memory ephemeral database",null,null],[11,"new","","Create a new empty database",14,[[]]],[8,"BatchOperations","bdk::database","Trait for operations that can be batched",null,null],[10,"set_script_pubkey","","Store a script_pubkey along with its script type and child…",15,[[["scripttype",4],["script",3]],[["result",4],["error",4]]]],[10,"set_utxo","","Store a [`UTXO`]",15,[[["utxo",3]],[["result",4],["error",4]]]],[10,"set_raw_tx","","Store a raw transaction",15,[[["transaction",3]],[["result",4],["error",4]]]],[10,"set_tx","","Store the metadata of a transaction",15,[[["transactiondetails",3]],[["result",4],["error",4]]]],[10,"set_last_index","","Store the last derivation index for a given script type",15,[[["scripttype",4]],[["result",4],["error",4]]]],[10,"del_script_pubkey_from_path","","Delete a script_pubkey given the script type and its child…",15,[[["scripttype",4]],[["option",4],["error",4],["result",4]]]],[10,"del_path_from_script_pubkey","","Delete the data related to a specific script_pubkey,…",15,[[["script",3]],[["error",4],["result",4],["option",4]]]],[10,"del_utxo","","Delete a [`UTXO`] given its [`OutPoint`]",15,[[["outpoint",3]],[["result",4],["error",4],["option",4]]]],[10,"del_raw_tx","","Delete a raw transaction given its [`Txid`]",15,[[["txid",3]],[["error",4],["result",4],["option",4]]]],[10,"del_tx","","Delete the metadata of a transaction and optionally the…",15,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[10,"del_last_index","","Delete the last derivation index for a script type",15,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[8,"Database","","Trait for reading data from a database",null,null],[10,"check_descriptor_checksum","","Read and checks the descriptor checksum for a given script…",16,[[["scripttype",4],["asref",8]],[["result",4],["error",4]]]],[10,"iter_script_pubkeys","","Return the list of script_pubkeys",16,[[["scripttype",4],["option",4]],[["error",4],["vec",3],["result",4]]]],[10,"iter_utxos","","Return the list of [`UTXO`]s",16,[[],[["vec",3],["result",4],["error",4]]]],[10,"iter_raw_txs","","Return the list of raw transactions",16,[[],[["result",4],["vec",3],["error",4]]]],[10,"iter_txs","","Return the list of transactions metadata",16,[[],[["result",4],["vec",3],["error",4]]]],[10,"get_script_pubkey_from_path","","Fetch a script_pubkey given the script type and child number",16,[[["scripttype",4]],[["option",4],["error",4],["result",4]]]],[10,"get_path_from_script_pubkey","","Fetch the script type and child number of a given…",16,[[["script",3]],[["error",4],["result",4],["option",4]]]],[10,"get_utxo","","Fetch a [`UTXO`] given its [`OutPoint`]",16,[[["outpoint",3]],[["result",4],["error",4],["option",4]]]],[10,"get_raw_tx","","Fetch a raw transaction given its [`Txid`]",16,[[["txid",3]],[["error",4],["result",4],["option",4]]]],[10,"get_tx","","Fetch the transaction metadata and optionally also the raw…",16,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[10,"get_last_index","","Return the last defivation index for a script type",16,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[10,"increment_last_index","","Increment the last derivation index for a script type and…",16,[[["scripttype",4]],[["error",4],["result",4]]]],[8,"BatchDatabase","","Trait for a database that supports batch operations",null,null],[16,"Batch","","Container for the operations",17,null],[10,"begin_batch","","Create a new batch container",17,[[]]],[10,"commit_batch","","Consume and apply a batch of operations",17,[[],[["result",4],["error",4]]]],[0,"descriptor","bdk","Descriptors",null,null],[4,"Descriptor","bdk::descriptor","Script descriptor",null,null],[13,"Bare","","A raw scriptpubkey (including pay-to-pubkey) under Legacy…",18,null],[13,"Pk","","Pay-to-Pubkey",18,null],[13,"Pkh","","Pay-to-PubKey-Hash",18,null],[13,"Wpkh","","Pay-to-Witness-PubKey-Hash",18,null],[13,"ShWpkh","","Pay-to-Witness-PubKey-Hash inside P2SH",18,null],[13,"Sh","","Pay-to-ScriptHash with Legacy context",18,null],[13,"Wsh","","Pay-to-Witness-ScriptHash with Segwitv0 context",18,null],[13,"ShWsh","","P2SH-P2WSH with Segwitv0 context",18,null],[4,"Legacy","","Legacy ScriptContext",null,null],[3,"Miniscript","","Top-level script AST type",null,null],[12,"node","","A node in the Abstract Syntax Tree(",19,null],[12,"ty","","The correctness and malleability type information for the…",19,null],[12,"ext","","Additional information helpful for extra analysis.",19,null],[8,"MiniscriptKey","","Public key trait which can be converted to Hash type",null,null],[11,"is_uncompressed","","Check if the publicKey is uncompressed. The default…",20,[[]]],[16,"Hash","","The associated Hash type with the publicKey",20,null],[10,"to_pubkeyhash","","Converts an object to PublicHash",20,[[]]],[8,"ScriptContext","","",null,null],[10,"check_frag_non_malleable","","Depending on ScriptContext, fragments can be malleable.…",21,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[10,"check_frag_validity","","Depending on script Context, some of the Terminals might…",21,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[4,"Segwitv0","","Segwitv0 ScriptContext",null,null],[4,"Terminal","","All AST elements",null,null],[13,"True","","`1`",22,null],[13,"False","","`0`",22,null],[13,"PkK","","``",22,null],[13,"PkH","","`DUP HASH160 EQUALVERIFY`",22,null],[13,"After","","`n CHECKLOCKTIMEVERIFY`",22,null],[13,"Older","","`n CHECKSEQUENCEVERIFY`",22,null],[13,"Sha256","","`SIZE 32 EQUALVERIFY SHA256 EQUAL`",22,null],[13,"Hash256","","`SIZE 32 EQUALVERIFY HASH256 EQUAL`",22,null],[13,"Ripemd160","","`SIZE 32 EQUALVERIFY RIPEMD160 EQUAL`",22,null],[13,"Hash160","","`SIZE 32 EQUALVERIFY HASH160 EQUAL`",22,null],[13,"Alt","","`TOALTSTACK [E] FROMALTSTACK`",22,null],[13,"Swap","","`SWAP [E1]`",22,null],[13,"Check","","`[Kt]/[Ke] CHECKSIG`",22,null],[13,"DupIf","","`DUP IF [V] ENDIF`",22,null],[13,"Verify","","[T] VERIFY",22,null],[13,"NonZero","","SIZE 0NOTEQUAL IF [Fn] ENDIF",22,null],[13,"ZeroNotEqual","","[X] 0NOTEQUAL",22,null],[13,"AndV","","[V] [T]/[V]/[F]/[Kt]",22,null],[13,"AndB","","[E] [W] BOOLAND",22,null],[13,"AndOr","","[various] NOTIF [various] ELSE [various] ENDIF",22,null],[13,"OrB","","[E] [W] BOOLOR",22,null],[13,"OrD","","[E] IFDUP NOTIF [T]/[E] ENDIF",22,null],[13,"OrC","","[E] NOTIF [V] ENDIF",22,null],[13,"OrI","","IF [various] ELSE [various] ENDIF",22,null],[13,"Thresh","","[E] ([W] ADD)* k EQUAL",22,null],[13,"Multi","","k ()* n CHECKMULTISIG",22,null],[8,"ToPublicKey","","Trait describing public key types which can be converted…",null,null],[10,"to_public_key","","Converts an object to a public key",23,[[],["publickey",3]]],[11,"serialized_len","","Computes the size of a public key when serialized in a…",23,[[]]],[10,"hash_to_hash160","","Converts a hashed version of the public key to a `hash160`…",23,[[],["hash",3]]],[0,"checksum","","Descriptor checksum",null,null],[5,"get_checksum","bdk::descriptor::checksum","Compute the checksum of a descriptor",null,[[],[["error",4],["string",3],["result",4]]]],[0,"error","bdk::descriptor","Descriptor errors",null,null],[4,"Error","bdk::descriptor::error","Errors related to the parsing and usage of descriptors",null,null],[13,"InternalError","","",24,null],[13,"InvalidPrefix","","",24,null],[13,"HardenedDerivationOnXpub","","",24,null],[13,"MalformedInput","","",24,null],[13,"KeyParsingError","","",24,null],[13,"Policy","","",24,null],[13,"InputIndexDoesntExist","","",24,null],[13,"MissingPublicKey","","",24,null],[13,"MissingDetails","","",24,null],[13,"InvalidDescriptorCharacter","","",24,null],[13,"CantDeriveWithMiniscript","","",24,null],[13,"BIP32","","",24,null],[13,"Base58","","",24,null],[13,"PK","","",24,null],[13,"Miniscript","","",24,null],[13,"Hex","","",24,null],[0,"policy","bdk::descriptor","Descriptor policy",null,null],[3,"PKOrF","bdk::descriptor::policy","Raw public key or extended key fingerprint",null,null],[3,"Policy","","Descriptor spending policy",null,null],[12,"id","","Identifier for this policy node",25,null],[12,"item","","Type of this policy node",25,null],[12,"satisfaction","","How a much given PSBT already satisfies this polcy node…",25,null],[12,"contribution","","How the wallet\'s descriptor can satisfy this policy node",25,null],[3,"Condition","","An extra condition that must be satisfied but that is out…",null,null],[12,"csv","","",26,null],[12,"timelock","","",26,null],[4,"SatisfiableItem","","An item that need to be satisfied",null,null],[13,"Signature","","",27,null],[13,"SignatureKey","","",27,null],[13,"SHA256Preimage","","",27,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","",28,null],[13,"HASH256Preimage","bdk::descriptor::policy","",27,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","",29,null],[13,"RIPEMD160Preimage","bdk::descriptor::policy","",27,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","",30,null],[13,"HASH160Preimage","bdk::descriptor::policy","",27,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","",31,null],[13,"AbsoluteTimelock","bdk::descriptor::policy","",27,null],[12,"value","bdk::descriptor::policy::SatisfiableItem","",32,null],[13,"RelativeTimelock","bdk::descriptor::policy","",27,null],[12,"value","bdk::descriptor::policy::SatisfiableItem","",33,null],[13,"Thresh","bdk::descriptor::policy","",27,null],[12,"items","bdk::descriptor::policy::SatisfiableItem","",34,null],[12,"threshold","","",34,null],[13,"Multisig","bdk::descriptor::policy","",27,null],[12,"keys","bdk::descriptor::policy::SatisfiableItem","",35,null],[12,"threshold","","",35,null],[4,"Satisfaction","bdk::descriptor::policy","Represent if and how much a policy item is satisfied by…",null,null],[13,"Partial","","Only a partial satisfaction of some kind of threshold policy",36,null],[12,"n","bdk::descriptor::policy::Satisfaction","Total number of items",37,null],[12,"m","","Threshold",37,null],[12,"items","","The items that can be satisfied by the descriptor",37,null],[12,"conditions","","Extra conditions that also need to be satisfied",37,null],[13,"PartialComplete","bdk::descriptor::policy","Can reach the threshold of some kind of threshold policy",36,null],[12,"n","bdk::descriptor::policy::Satisfaction","Total number of items",38,null],[12,"m","","Threshold",38,null],[12,"items","","The items that can be satisfied by the descriptor",38,null],[12,"conditions","","Extra conditions that also need to be satisfied",38,null],[13,"Complete","bdk::descriptor::policy","Can satisfy the policy item",36,null],[12,"condition","bdk::descriptor::policy::Satisfaction","Extra conditions that also need to be satisfied",39,null],[13,"None","bdk::descriptor::policy","Cannot satisfy or contribute to the policy item",36,null],[4,"PolicyError","","Errors that can happen while extracting and manipulating…",null,null],[13,"NotEnoughItemsSelected","","",40,null],[13,"TooManyItemsSelected","","",40,null],[13,"IndexOutOfRange","","",40,null],[13,"AddOnLeaf","","",40,null],[13,"AddOnPartialComplete","","",40,null],[13,"MixedTimelockUnits","","",40,null],[13,"IncompatibleConditions","","",40,null],[6,"ConditionMap","","",null,null],[6,"FoldedConditionMap","","",null,null],[11,"is_leaf","","",27,[[]]],[11,"id","","",27,[[],["string",3]]],[11,"is_leaf","","",36,[[]]],[11,"is_null","","",26,[[]]],[11,"requires_path","","Return whether or not a specific path in the policy tree…",25,[[]]],[11,"get_condition","","Return the conditions that are set by the spending policy…",25,[[["btreemap",3]],[["policyerror",4],["result",4],["condition",3]]]],[6,"ExtendedDescriptor","bdk::descriptor","Alias for a [`Descriptor`] that can contain extended keys…",null,null],[6,"HDKeyPaths","","Alias for the type of maps that represent derivation paths…",null,null],[8,"ExtractPolicy","","Trait implemented on [`Descriptor`]s to add a method to…",null,null],[10,"extract_policy","","",41,[[["signerscontainer",3],["arc",3]],[["error",4],["option",4],["result",4]]]],[11,"as_byte","bdk","",4,[[]]],[11,"is_internal","","",4,[[]]],[11,"from_btc_per_kvb","","Create a new instance of [`FeeRate`] given a float fee…",42,[[]]],[11,"from_sat_per_vb","","Create a new instance of [`FeeRate`] given a float fee…",42,[[]]],[11,"default_min_relay_fee","","Create a new [`FeeRate`] with the default min relay fee…",42,[[]]],[11,"as_sat_vb","","Return the value as satoshi/vbyte",42,[[]]],[0,"wallet","","Wallet",null,null],[3,"Wallet","bdk::wallet","A Bitcoin wallet",null,null],[0,"address_validator","","Address validation callbacks",null,null],[4,"AddressValidatorError","bdk::wallet::address_validator","Errors that can be returned to fail the validation of an…",null,null],[13,"UserRejected","","",43,null],[13,"ConnectionError","","",43,null],[13,"TimeoutError","","",43,null],[13,"InvalidScript","","",43,null],[13,"Message","","",43,null],[8,"AddressValidator","","Trait to build address validators",null,null],[10,"validate","","Validate or inspect an address",44,[[["scripttype",4],["script",3],["hdkeypaths",6]],[["result",4],["addressvalidatorerror",4]]]],[0,"coin_selection","bdk::wallet","Coin selection",null,null],[3,"CoinSelectionResult","bdk::wallet::coin_selection","Result of a successful coin selection",null,null],[12,"txin","","List of inputs to use, with the respective previous…",45,null],[12,"selected_amount","","Sum of the selected inputs\' value",45,null],[12,"fee_amount","","Total fee amount in satoshi",45,null],[3,"DumbCoinSelection","","Simple and dumb coin selection",null,null],[6,"DefaultCoinSelectionAlgorithm","","Default coin selection algorithm used by `TxBuilder` if…",null,null],[8,"CoinSelectionAlgorithm","","Trait for generalized coin selection algorithms",null,null],[10,"coin_select","","Perform the coin selection",46,[[["vec",3],["feerate",3],["utxo",3]],[["error",4],["result",4],["coinselectionresult",3]]]],[0,"export","bdk::wallet","Wallet export",null,null],[3,"WalletExport","bdk::wallet::export","Structure that contains the export of a wallet",null,null],[12,"blockheight","","Earliest block to rescan when looking for the wallet\'s…",47,null],[12,"label","","Arbitrary label for the wallet",47,null],[11,"export_wallet","","Export a wallet",47,[[["wallet",3]],["result",4]]],[11,"descriptor","","Return the external descriptor",47,[[],["string",3]]],[11,"change_descriptor","","Return the internal descriptor, if present",47,[[],[["string",3],["option",4]]]],[0,"signer","bdk::wallet","Generalized signers",null,null],[3,"SignerOrdering","bdk::wallet::signer","Defines the order in which signers are called",null,null],[12,"0","","",48,null],[3,"SignersContainer","","Container for multiple signers",null,null],[4,"SignerId","","Identifier of a signer in the `SignersContainers`. Used as…",null,null],[13,"PkHash","","",49,null],[13,"Fingerprint","","",49,null],[4,"SignerError","","Signing error",null,null],[13,"MissingKey","","The private key is missing for the required public key",50,null],[13,"UserCanceled","","The user canceled the operation",50,null],[13,"MissingSighash","","The sighash is missing in the PSBT input",50,null],[13,"InputIndexOutOfRange","","Input index is out of range",50,null],[13,"MissingNonWitnessUtxo","","The `non_witness_utxo` field of the transaction is…",50,null],[13,"InvalidNonWitnessUtxo","","The `non_witness_utxo` specified is invalid",50,null],[13,"MissingWitnessUtxo","","The `witness_utxo` field of the transaction is required to…",50,null],[13,"MissingWitnessScript","","The `witness_script` field of the transaction is requied…",50,null],[13,"MissingHDKeypath","","The fingerprint and derivation path are missing from the…",50,null],[8,"Signer","","Trait for signers",null,null],[10,"sign","","Sign a PSBT",51,[[["partiallysignedtransaction",3],["option",4]],[["result",4],["signererror",4]]]],[10,"sign_whole_tx","","Return whether or not the signer signs the whole…",51,[[]]],[11,"descriptor_secret_key","","Return the secret key for the signer",51,[[],[["option",4],["descriptorsecretkey",4]]]],[11,"as_key_map","","",52,[[],["keymap",6]]],[11,"new","","Default constructor",52,[[]]],[11,"add_external","","Adds an external signer to the container for the specified…",52,[[["signerid",4],["signerordering",3],["arc",3],["box",3]],[["arc",3],["option",4]]]],[11,"remove","","Removes a signer from the container and returns it",52,[[["signerid",4],["signerordering",3]],[["arc",3],["option",4]]]],[11,"ids","","Returns the list of identifiers of all the signers in the…",52,[[],[["vec",3],["signerid",4]]]],[11,"signers","","Returns the list of signers in the container, sorted by…",52,[[],[["arc",3],["vec",3]]]],[11,"find","","Finds the signer with lowest ordering for a given id in…",52,[[["signerid",4]],[["arc",3],["option",4]]]],[0,"time","bdk::wallet","Cross-platform time",null,null],[5,"get_timestamp","bdk::wallet::time","Return the current timestamp in seconds",null,[[]]],[0,"tx_builder","bdk::wallet","Transaction builder",null,null],[3,"TxBuilder","bdk::wallet::tx_builder","A transaction builder",null,null],[4,"TxOrdering","","Ordering of the transaction\'s inputs and outputs",null,null],[13,"Shuffle","","Randomized (default)",53,null],[13,"Untouched","","Unchanged",53,null],[13,"BIP69Lexicographic","","BIP69 / Lexicographic",53,null],[4,"ChangeSpendPolicy","","Policy regarding the use of change outputs when creating a…",null,null],[13,"ChangeAllowed","","Use both change and non-change outputs (default)",54,null],[13,"OnlyChange","","Only use change outputs (see…",54,null],[13,"ChangeForbidden","","Only use non-change outputs (see…",54,null],[11,"new","","Create an empty builder",55,[[]]],[11,"with_recipients","","Create a builder starting from a list of recipients",55,[[["vec",3]]]],[11,"set_recipients","","Replace the recipients already added with a new list",55,[[["vec",3]]]],[11,"add_recipient","","Add a recipient to the internal list",55,[[["script",3]]]],[11,"send_all","","Send all the selected utxos to a single output",55,[[]]],[11,"fee_rate","","Set a custom fee rate",55,[[["feerate",3]]]],[11,"policy_path","","Set the policy path to use while creating the transaction",55,[[["btreemap",3],["vec",3],["string",3]]]],[11,"utxos","","Replace the internal list of utxos that must be spent with…",55,[[["outpoint",3],["vec",3]]]],[11,"add_utxo","","Add a utxo to the internal list of utxos that must be spent",55,[[["outpoint",3]]]],[11,"unspendable","","Replace the internal list of unspendable utxos with a new…",55,[[["outpoint",3],["vec",3]]]],[11,"add_unspendable","","Add a utxo to the internal list of unspendable utxos",55,[[["outpoint",3]]]],[11,"sighash","","Sign with a specific sig hash",55,[[["sighashtype",4]]]],[11,"ordering","","Choose the ordering for inputs and outputs of the…",55,[[["txordering",4]]]],[11,"nlocktime","","Use a specific nLockTime while creating the transaction",55,[[]]],[11,"enable_rbf","","Enable signaling RBF",55,[[]]],[11,"enable_rbf_with_sequence","","Enable signaling RBF with a specific nSequence value",55,[[]]],[11,"version","","Build a transaction with a specific version",55,[[]]],[11,"do_not_spend_change","","Do not spend change outputs",55,[[]]],[11,"only_spend_change","","Only spend change outputs",55,[[]]],[11,"change_policy","","Set a specific [`ChangeSpendPolicy`]. See…",55,[[["changespendpolicy",4]]]],[11,"force_non_witness_utxo","","Fill-in the `psbt::Input::non_witness_utxo` field even if…",55,[[]]],[11,"coin_selection","","Choose the coin selection algorithm",55,[[["coinselectionalgorithm",8]],[["txbuilder",3],["coinselectionalgorithm",8]]]],[11,"sort_tx","","",53,[[["transaction",3]]]],[6,"OfflineWallet","bdk::wallet","Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]",null,null],[8,"IsDust","","Trait to check if a value is below the dust limit",null,null],[10,"is_dust","","Check whether or not a value is below dust limit",56,[[]]],[11,"new_offline","","Create a new \\\"offline\\\" wallet",57,[[["option",4],["network",4]],[["result",4],["error",4]]]],[11,"get_new_address","","Return a newly generated address using the external…",57,[[],[["address",3],["result",4],["error",4]]]],[11,"is_mine","","Return whether or not a `script` is part of this wallet…",57,[[["script",3]],[["error",4],["result",4]]]],[11,"list_unspent","","Return the list of unspent outputs of this wallet",57,[[],[["vec",3],["result",4],["error",4]]]],[11,"list_transactions","","Return the list of transactions made and received by the…",57,[[],[["result",4],["vec",3],["error",4]]]],[11,"get_balance","","Return the balance, meaning the sum of this wallet\'s…",57,[[],[["error",4],["result",4]]]],[11,"add_signer","","Add an external signer",57,[[["scripttype",4],["signerid",4],["signerordering",3],["descriptorpublickey",4],["arc",3],["box",3]]]],[11,"add_address_validator","","Add an address validator",57,[[["arc",3],["box",3]]]],[11,"create_tx","","Create a new transaction following the options specified…",57,[[["txbuilder",3],["coinselectionalgorithm",8]],[["result",4],["error",4]]]],[11,"bump_fee","","Bump the fee of a transaction following the options…",57,[[["txid",3],["txbuilder",3],["coinselectionalgorithm",8]],[["result",4],["error",4]]]],[11,"sign","","Sign a transaction with all the wallet\'s signers, in the…",57,[[["psbt",3],["option",4]],[["error",4],["result",4]]]],[11,"policies","","Return the spending policies for the wallet\'s descriptor",57,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[11,"public_descriptor","","Return the \\\"public\\\" version of the wallet\'s descriptor,…",57,[[["scripttype",4]],[["error",4],["option",4],["result",4]]]],[11,"finalize_psbt","","Try to finalize a PSBT",57,[[["psbt",3],["option",4]],[["error",4],["result",4]]]],[11,"new","","Create a new \\\"online\\\" wallet",57,[[["option",4],["network",4]],[["result",4],["error",4]]]],[11,"sync","","Sync the internal database with the blockchain",57,[[["progress",8],["option",4]],[["result",4],["error",4]]]],[11,"client","","Return a reference to the internal blockchain client",57,[[],["option",4]]],[11,"broadcast","","Broadcast a transaction to the network",57,[[["transaction",3]],[["result",4],["txid",3],["error",4]]]],[11,"from","bdk","",42,[[]]],[11,"into","","",42,[[]]],[11,"to_owned","","",42,[[]]],[11,"clone_into","","",42,[[]]],[11,"try_from","","",42,[[],["result",4]]],[11,"try_into","","",42,[[],["result",4]]],[11,"borrow","","",42,[[]]],[11,"borrow_mut","","",42,[[]]],[11,"type_id","","",42,[[],["typeid",3]]],[11,"vzip","","",42,[[]]],[11,"from","","",0,[[]]],[11,"into","","",0,[[]]],[11,"to_owned","","",0,[[]]],[11,"clone_into","","",0,[[]]],[11,"try_from","","",0,[[],["result",4]]],[11,"try_into","","",0,[[],["result",4]]],[11,"borrow","","",0,[[]]],[11,"borrow_mut","","",0,[[]]],[11,"type_id","","",0,[[],["typeid",3]]],[11,"equivalent","","",0,[[]]],[11,"vzip","","",0,[[]]],[11,"from","","",1,[[]]],[11,"into","","",1,[[]]],[11,"to_owned","","",1,[[]]],[11,"clone_into","","",1,[[]]],[11,"try_from","","",1,[[],["result",4]]],[11,"try_into","","",1,[[],["result",4]]],[11,"borrow","","",1,[[]]],[11,"borrow_mut","","",1,[[]]],[11,"type_id","","",1,[[],["typeid",3]]],[11,"equivalent","","",1,[[]]],[11,"vzip","","",1,[[]]],[11,"from","","",2,[[]]],[11,"into","","",2,[[]]],[11,"to_string","","",2,[[],["string",3]]],[11,"try_from","","",2,[[],["result",4]]],[11,"try_into","","",2,[[],["result",4]]],[11,"borrow","","",2,[[]]],[11,"borrow_mut","","",2,[[]]],[11,"type_id","","",2,[[],["typeid",3]]],[11,"vzip","","",2,[[]]],[11,"from","","",4,[[]]],[11,"into","","",4,[[]]],[11,"to_owned","","",4,[[]]],[11,"clone_into","","",4,[[]]],[11,"try_from","","",4,[[],["result",4]]],[11,"try_into","","",4,[[],["result",4]]],[11,"borrow","","",4,[[]]],[11,"borrow_mut","","",4,[[]]],[11,"type_id","","",4,[[],["typeid",3]]],[11,"write_base32","","",4,[[],["result",4]]],[11,"base32_len","","",4,[[]]],[11,"check_base32","","",4,[[],[["result",4],["vec",3]]]],[11,"equivalent","","",4,[[]]],[11,"vzip","","",4,[[]]],[11,"from","bdk::blockchain","",58,[[]]],[11,"into","","",58,[[]]],[11,"try_from","","",58,[[],["result",4]]],[11,"try_into","","",58,[[],["result",4]]],[11,"borrow","","",58,[[]]],[11,"borrow_mut","","",58,[[]]],[11,"type_id","","",58,[[],["typeid",3]]],[11,"vzip","","",58,[[]]],[11,"from","","",59,[[]]],[11,"into","","",59,[[]]],[11,"to_owned","","",59,[[]]],[11,"clone_into","","",59,[[]]],[11,"try_from","","",59,[[],["result",4]]],[11,"try_into","","",59,[[],["result",4]]],[11,"borrow","","",59,[[]]],[11,"borrow_mut","","",59,[[]]],[11,"type_id","","",59,[[],["typeid",3]]],[11,"vzip","","",59,[[]]],[11,"from","","",60,[[]]],[11,"into","","",60,[[]]],[11,"to_owned","","",60,[[]]],[11,"clone_into","","",60,[[]]],[11,"try_from","","",60,[[],["result",4]]],[11,"try_into","","",60,[[],["result",4]]],[11,"borrow","","",60,[[]]],[11,"borrow_mut","","",60,[[]]],[11,"type_id","","",60,[[],["typeid",3]]],[11,"vzip","","",60,[[]]],[11,"from","","",5,[[]]],[11,"into","","",5,[[]]],[11,"to_owned","","",5,[[]]],[11,"clone_into","","",5,[[]]],[11,"try_from","","",5,[[],["result",4]]],[11,"try_into","","",5,[[],["result",4]]],[11,"borrow","","",5,[[]]],[11,"borrow_mut","","",5,[[]]],[11,"type_id","","",5,[[],["typeid",3]]],[11,"equivalent","","",5,[[]]],[11,"vzip","","",5,[[]]],[11,"from","bdk::blockchain::electrum","",61,[[]]],[11,"into","","",61,[[]]],[11,"try_from","","",61,[[],["result",4]]],[11,"try_into","","",61,[[],["result",4]]],[11,"borrow","","",61,[[]]],[11,"borrow_mut","","",61,[[]]],[11,"type_id","","",61,[[],["typeid",3]]],[11,"vzip","","",61,[[]]],[11,"from","bdk::blockchain::esplora","",7,[[]]],[11,"into","","",7,[[]]],[11,"try_from","","",7,[[],["result",4]]],[11,"try_into","","",7,[[],["result",4]]],[11,"borrow","","",7,[[]]],[11,"borrow_mut","","",7,[[]]],[11,"type_id","","",7,[[],["typeid",3]]],[11,"vzip","","",7,[[]]],[11,"from","","",6,[[]]],[11,"into","","",6,[[]]],[11,"to_string","","",6,[[],["string",3]]],[11,"try_from","","",6,[[],["result",4]]],[11,"try_into","","",6,[[],["result",4]]],[11,"borrow","","",6,[[]]],[11,"borrow_mut","","",6,[[]]],[11,"type_id","","",6,[[],["typeid",3]]],[11,"vzip","","",6,[[]]],[11,"from","bdk::blockchain::compact_filters","",9,[[]]],[11,"into","","",9,[[]]],[11,"try_from","","",9,[[],["result",4]]],[11,"try_into","","",9,[[],["result",4]]],[11,"borrow","","",9,[[]]],[11,"borrow_mut","","",9,[[]]],[11,"type_id","","",9,[[],["typeid",3]]],[11,"vzip","","",9,[[]]],[11,"from","","",10,[[]]],[11,"into","","",10,[[]]],[11,"try_from","","",10,[[],["result",4]]],[11,"try_into","","",10,[[],["result",4]]],[11,"borrow","","",10,[[]]],[11,"borrow_mut","","",10,[[]]],[11,"type_id","","",10,[[],["typeid",3]]],[11,"vzip","","",10,[[]]],[11,"from","","",11,[[]]],[11,"into","","",11,[[]]],[11,"try_from","","",11,[[],["result",4]]],[11,"try_into","","",11,[[],["result",4]]],[11,"borrow","","",11,[[]]],[11,"borrow_mut","","",11,[[]]],[11,"type_id","","",11,[[],["typeid",3]]],[11,"vzip","","",11,[[]]],[11,"from","","",8,[[]]],[11,"into","","",8,[[]]],[11,"to_string","","",8,[[],["string",3]]],[11,"try_from","","",8,[[],["result",4]]],[11,"try_into","","",8,[[],["result",4]]],[11,"borrow","","",8,[[]]],[11,"borrow_mut","","",8,[[]]],[11,"type_id","","",8,[[],["typeid",3]]],[11,"vzip","","",8,[[]]],[11,"from","bdk::database::memory","",14,[[]]],[11,"into","","",14,[[]]],[11,"try_from","","",14,[[],["result",4]]],[11,"try_into","","",14,[[],["result",4]]],[11,"borrow","","",14,[[]]],[11,"borrow_mut","","",14,[[]]],[11,"type_id","","",14,[[],["typeid",3]]],[11,"vzip","","",14,[[]]],[11,"from","bdk::descriptor","",18,[[]]],[11,"into","","",18,[[]]],[11,"to_owned","","",18,[[]]],[11,"clone_into","","",18,[[]]],[11,"to_string","","",18,[[],["string",3]]],[11,"try_from","","",18,[[],["result",4]]],[11,"try_into","","",18,[[],["result",4]]],[11,"borrow","","",18,[[]]],[11,"borrow_mut","","",18,[[]]],[11,"type_id","","",18,[[],["typeid",3]]],[11,"equivalent","","",18,[[]]],[11,"vzip","","",18,[[]]],[11,"from","","",62,[[]]],[11,"into","","",62,[[]]],[11,"to_owned","","",62,[[]]],[11,"clone_into","","",62,[[]]],[11,"try_from","","",62,[[],["result",4]]],[11,"try_into","","",62,[[],["result",4]]],[11,"borrow","","",62,[[]]],[11,"borrow_mut","","",62,[[]]],[11,"type_id","","",62,[[],["typeid",3]]],[11,"equivalent","","",62,[[]]],[11,"vzip","","",62,[[]]],[11,"from","","",19,[[]]],[11,"into","","",19,[[]]],[11,"to_owned","","",19,[[]]],[11,"clone_into","","",19,[[]]],[11,"to_string","","",19,[[],["string",3]]],[11,"try_from","","",19,[[],["result",4]]],[11,"try_into","","",19,[[],["result",4]]],[11,"borrow","","",19,[[]]],[11,"borrow_mut","","",19,[[]]],[11,"type_id","","",19,[[],["typeid",3]]],[11,"equivalent","","",19,[[]]],[11,"vzip","","",19,[[]]],[11,"from","","",63,[[]]],[11,"into","","",63,[[]]],[11,"to_owned","","",63,[[]]],[11,"clone_into","","",63,[[]]],[11,"try_from","","",63,[[],["result",4]]],[11,"try_into","","",63,[[],["result",4]]],[11,"borrow","","",63,[[]]],[11,"borrow_mut","","",63,[[]]],[11,"type_id","","",63,[[],["typeid",3]]],[11,"equivalent","","",63,[[]]],[11,"vzip","","",63,[[]]],[11,"from","","",22,[[]]],[11,"into","","",22,[[]]],[11,"to_owned","","",22,[[]]],[11,"clone_into","","",22,[[]]],[11,"to_string","","",22,[[],["string",3]]],[11,"try_from","","",22,[[],["result",4]]],[11,"try_into","","",22,[[],["result",4]]],[11,"borrow","","",22,[[]]],[11,"borrow_mut","","",22,[[]]],[11,"type_id","","",22,[[],["typeid",3]]],[11,"equivalent","","",22,[[]]],[11,"vzip","","",22,[[]]],[11,"from","bdk::descriptor::error","",24,[[]]],[11,"into","","",24,[[]]],[11,"to_string","","",24,[[],["string",3]]],[11,"try_from","","",24,[[],["result",4]]],[11,"try_into","","",24,[[],["result",4]]],[11,"borrow","","",24,[[]]],[11,"borrow_mut","","",24,[[]]],[11,"type_id","","",24,[[],["typeid",3]]],[11,"vzip","","",24,[[]]],[11,"from","bdk::descriptor::policy","",64,[[]]],[11,"into","","",64,[[]]],[11,"to_owned","","",64,[[]]],[11,"clone_into","","",64,[[]]],[11,"try_from","","",64,[[],["result",4]]],[11,"try_into","","",64,[[],["result",4]]],[11,"borrow","","",64,[[]]],[11,"borrow_mut","","",64,[[]]],[11,"type_id","","",64,[[],["typeid",3]]],[11,"vzip","","",64,[[]]],[11,"from","","",25,[[]]],[11,"into","","",25,[[]]],[11,"to_owned","","",25,[[]]],[11,"clone_into","","",25,[[]]],[11,"try_from","","",25,[[],["result",4]]],[11,"try_into","","",25,[[],["result",4]]],[11,"borrow","","",25,[[]]],[11,"borrow_mut","","",25,[[]]],[11,"type_id","","",25,[[],["typeid",3]]],[11,"vzip","","",25,[[]]],[11,"from","","",26,[[]]],[11,"into","","",26,[[]]],[11,"to_owned","","",26,[[]]],[11,"clone_into","","",26,[[]]],[11,"try_from","","",26,[[],["result",4]]],[11,"try_into","","",26,[[],["result",4]]],[11,"borrow","","",26,[[]]],[11,"borrow_mut","","",26,[[]]],[11,"type_id","","",26,[[],["typeid",3]]],[11,"equivalent","","",26,[[]]],[11,"vzip","","",26,[[]]],[11,"from","","",27,[[]]],[11,"into","","",27,[[]]],[11,"to_owned","","",27,[[]]],[11,"clone_into","","",27,[[]]],[11,"try_from","","",27,[[],["result",4]]],[11,"try_into","","",27,[[],["result",4]]],[11,"borrow","","",27,[[]]],[11,"borrow_mut","","",27,[[]]],[11,"type_id","","",27,[[],["typeid",3]]],[11,"vzip","","",27,[[]]],[11,"from","","",36,[[]]],[11,"into","","",36,[[]]],[11,"to_owned","","",36,[[]]],[11,"clone_into","","",36,[[]]],[11,"try_from","","",36,[[],["result",4]]],[11,"try_into","","",36,[[],["result",4]]],[11,"borrow","","",36,[[]]],[11,"borrow_mut","","",36,[[]]],[11,"type_id","","",36,[[],["typeid",3]]],[11,"vzip","","",36,[[]]],[11,"from","","",40,[[]]],[11,"into","","",40,[[]]],[11,"to_string","","",40,[[],["string",3]]],[11,"try_from","","",40,[[],["result",4]]],[11,"try_into","","",40,[[],["result",4]]],[11,"borrow","","",40,[[]]],[11,"borrow_mut","","",40,[[]]],[11,"type_id","","",40,[[],["typeid",3]]],[11,"vzip","","",40,[[]]],[11,"from","bdk::wallet","",57,[[]]],[11,"into","","",57,[[]]],[11,"try_from","","",57,[[],["result",4]]],[11,"try_into","","",57,[[],["result",4]]],[11,"borrow","","",57,[[]]],[11,"borrow_mut","","",57,[[]]],[11,"type_id","","",57,[[],["typeid",3]]],[11,"vzip","","",57,[[]]],[11,"from","bdk::wallet::address_validator","",43,[[]]],[11,"into","","",43,[[]]],[11,"to_owned","","",43,[[]]],[11,"clone_into","","",43,[[]]],[11,"to_string","","",43,[[],["string",3]]],[11,"try_from","","",43,[[],["result",4]]],[11,"try_into","","",43,[[],["result",4]]],[11,"borrow","","",43,[[]]],[11,"borrow_mut","","",43,[[]]],[11,"type_id","","",43,[[],["typeid",3]]],[11,"equivalent","","",43,[[]]],[11,"vzip","","",43,[[]]],[11,"from","bdk::wallet::coin_selection","",45,[[]]],[11,"into","","",45,[[]]],[11,"try_from","","",45,[[],["result",4]]],[11,"try_into","","",45,[[],["result",4]]],[11,"borrow","","",45,[[]]],[11,"borrow_mut","","",45,[[]]],[11,"type_id","","",45,[[],["typeid",3]]],[11,"vzip","","",45,[[]]],[11,"from","","",65,[[]]],[11,"into","","",65,[[]]],[11,"try_from","","",65,[[],["result",4]]],[11,"try_into","","",65,[[],["result",4]]],[11,"borrow","","",65,[[]]],[11,"borrow_mut","","",65,[[]]],[11,"type_id","","",65,[[],["typeid",3]]],[11,"vzip","","",65,[[]]],[11,"from","bdk::wallet::export","",47,[[]]],[11,"into","","",47,[[]]],[11,"to_string","","",47,[[],["string",3]]],[11,"try_from","","",47,[[],["result",4]]],[11,"try_into","","",47,[[],["result",4]]],[11,"borrow","","",47,[[]]],[11,"borrow_mut","","",47,[[]]],[11,"type_id","","",47,[[],["typeid",3]]],[11,"vzip","","",47,[[]]],[11,"from","bdk::wallet::signer","",48,[[]]],[11,"into","","",48,[[]]],[11,"to_owned","","",48,[[]]],[11,"clone_into","","",48,[[]]],[11,"try_from","","",48,[[],["result",4]]],[11,"try_into","","",48,[[],["result",4]]],[11,"borrow","","",48,[[]]],[11,"borrow_mut","","",48,[[]]],[11,"type_id","","",48,[[],["typeid",3]]],[11,"equivalent","","",48,[[]]],[11,"vzip","","",48,[[]]],[11,"from","","",52,[[]]],[11,"into","","",52,[[]]],[11,"to_owned","","",52,[[]]],[11,"clone_into","","",52,[[]]],[11,"try_from","","",52,[[],["result",4]]],[11,"try_into","","",52,[[],["result",4]]],[11,"borrow","","",52,[[]]],[11,"borrow_mut","","",52,[[]]],[11,"type_id","","",52,[[],["typeid",3]]],[11,"vzip","","",52,[[]]],[11,"from","","",49,[[]]],[11,"into","","",49,[[]]],[11,"to_owned","","",49,[[]]],[11,"clone_into","","",49,[[]]],[11,"try_from","","",49,[[],["result",4]]],[11,"try_into","","",49,[[],["result",4]]],[11,"borrow","","",49,[[]]],[11,"borrow_mut","","",49,[[]]],[11,"type_id","","",49,[[],["typeid",3]]],[11,"equivalent","","",49,[[]]],[11,"vzip","","",49,[[]]],[11,"from","","",50,[[]]],[11,"into","","",50,[[]]],[11,"to_owned","","",50,[[]]],[11,"clone_into","","",50,[[]]],[11,"to_string","","",50,[[],["string",3]]],[11,"try_from","","",50,[[],["result",4]]],[11,"try_into","","",50,[[],["result",4]]],[11,"borrow","","",50,[[]]],[11,"borrow_mut","","",50,[[]]],[11,"type_id","","",50,[[],["typeid",3]]],[11,"equivalent","","",50,[[]]],[11,"vzip","","",50,[[]]],[11,"from","bdk::wallet::tx_builder","",55,[[]]],[11,"into","","",55,[[]]],[11,"try_from","","",55,[[],["result",4]]],[11,"try_into","","",55,[[],["result",4]]],[11,"borrow","","",55,[[]]],[11,"borrow_mut","","",55,[[]]],[11,"type_id","","",55,[[],["typeid",3]]],[11,"vzip","","",55,[[]]],[11,"from","","",53,[[]]],[11,"into","","",53,[[]]],[11,"to_owned","","",53,[[]]],[11,"clone_into","","",53,[[]]],[11,"try_from","","",53,[[],["result",4]]],[11,"try_into","","",53,[[],["result",4]]],[11,"borrow","","",53,[[]]],[11,"borrow_mut","","",53,[[]]],[11,"type_id","","",53,[[],["typeid",3]]],[11,"equivalent","","",53,[[]]],[11,"vzip","","",53,[[]]],[11,"from","","",54,[[]]],[11,"into","","",54,[[]]],[11,"to_owned","","",54,[[]]],[11,"clone_into","","",54,[[]]],[11,"try_from","","",54,[[],["result",4]]],[11,"try_into","","",54,[[],["result",4]]],[11,"borrow","","",54,[[]]],[11,"borrow_mut","","",54,[[]]],[11,"type_id","","",54,[[],["typeid",3]]],[11,"equivalent","","",54,[[]]],[11,"vzip","","",54,[[]]],[11,"partial_cmp","bdk::descriptor","",22,[[["terminal",4]],[["option",4],["ordering",4]]]],[11,"lt","","",22,[[["terminal",4]]]],[11,"le","","",22,[[["terminal",4]]]],[11,"gt","","",22,[[["terminal",4]]]],[11,"ge","","",22,[[["terminal",4]]]],[11,"partial_cmp","","",62,[[["legacy",4]],[["option",4],["ordering",4]]]],[11,"partial_cmp","","",18,[[["descriptor",4]],[["option",4],["ordering",4]]]],[11,"lt","","",18,[[["descriptor",4]]]],[11,"le","","",18,[[["descriptor",4]]]],[11,"gt","","",18,[[["descriptor",4]]]],[11,"ge","","",18,[[["descriptor",4]]]],[11,"partial_cmp","","",63,[[["segwitv0",4]],[["option",4],["ordering",4]]]],[11,"partial_cmp","","",19,[[["miniscript",3]],[["option",4],["ordering",4]]]],[11,"fmt","","",63,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",22,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",19,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",18,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",62,[[["formatter",3]],[["result",4],["error",3]]]],[11,"hash","","",19,[[]]],[11,"hash","","",22,[[]]],[11,"cmp","","",62,[[["legacy",4]],["ordering",4]]],[11,"cmp","","",63,[[["segwitv0",4]],["ordering",4]]],[11,"cmp","","",22,[[["terminal",4]],["ordering",4]]],[11,"cmp","","",19,[[["miniscript",3]],["ordering",4]]],[11,"cmp","","",18,[[["descriptor",4]],["ordering",4]]],[11,"fmt","","",22,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",19,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",18,[[["formatter",3]],[["result",4],["error",3]]]],[11,"check_frag_non_malleable","","",63,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_frag_validity","","",63,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_frag_non_malleable","","",62,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_frag_validity","","",62,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"clone","","",19,[[],["miniscript",3]]],[11,"clone","","",22,[[],["terminal",4]]],[11,"clone","","",63,[[],["segwitv0",4]]],[11,"clone","","",18,[[],["descriptor",4]]],[11,"clone","","",62,[[],["legacy",4]]],[11,"eq","","",62,[[["legacy",4]]]],[11,"eq","","",22,[[["terminal",4]]]],[11,"ne","","",22,[[["terminal",4]]]],[11,"eq","","",63,[[["segwitv0",4]]]],[11,"eq","","",19,[[["miniscript",3]]]],[11,"eq","","",18,[[["descriptor",4]]]],[11,"ne","","",18,[[["descriptor",4]]]],[11,"from_str","","",19,[[],[["result",4],["error",4],["miniscript",3]]]],[11,"from_str","","",18,[[],[["error",4],["descriptor",4],["result",4]]]],[11,"from_tree","","Parse an expression tree into a Miniscript. As a general…",19,[[["tree",3]],[["result",4],["error",4],["miniscript",3]]]],[11,"from_tree","","",22,[[["tree",3]],[["error",4],["result",4],["terminal",4]]]],[11,"from_tree","","Parse an expression tree into a descriptor",18,[[["tree",3]],[["error",4],["descriptor",4],["result",4]]]],[11,"lift","","",18,[[],["policy",4]]],[11,"lift","","",19,[[],["policy",4]]],[11,"lift","","",22,[[],["policy",4]]],[11,"update","bdk::blockchain","",59,[[["string",3],["option",4]],[["result",4],["error",4]]]],[11,"update","","",60,[[["string",3],["option",4]],[["result",4],["error",4]]]],[11,"set_script_pubkey","bdk::database::memory","",14,[[["scripttype",4],["script",3]],[["result",4],["error",4]]]],[11,"set_utxo","","",14,[[["utxo",3]],[["result",4],["error",4]]]],[11,"set_raw_tx","","",14,[[["transaction",3]],[["result",4],["error",4]]]],[11,"set_tx","","",14,[[["transactiondetails",3]],[["result",4],["error",4]]]],[11,"set_last_index","","",14,[[["scripttype",4]],[["result",4],["error",4]]]],[11,"del_script_pubkey_from_path","","",14,[[["scripttype",4]],[["option",4],["error",4],["result",4]]]],[11,"del_path_from_script_pubkey","","",14,[[["script",3]],[["error",4],["result",4],["option",4]]]],[11,"del_utxo","","",14,[[["outpoint",3]],[["result",4],["error",4],["option",4]]]],[11,"del_raw_tx","","",14,[[["txid",3]],[["error",4],["result",4],["option",4]]]],[11,"del_tx","","",14,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"del_last_index","","",14,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[11,"check_descriptor_checksum","","",14,[[["scripttype",4],["asref",8]],[["result",4],["error",4]]]],[11,"iter_script_pubkeys","","",14,[[["scripttype",4],["option",4]],[["error",4],["vec",3],["result",4]]]],[11,"iter_utxos","","",14,[[],[["vec",3],["result",4],["error",4]]]],[11,"iter_raw_txs","","",14,[[],[["result",4],["vec",3],["error",4]]]],[11,"iter_txs","","",14,[[],[["result",4],["vec",3],["error",4]]]],[11,"get_script_pubkey_from_path","","",14,[[["scripttype",4]],[["option",4],["error",4],["result",4]]]],[11,"get_path_from_script_pubkey","","",14,[[["script",3]],[["error",4],["result",4],["option",4]]]],[11,"get_utxo","","",14,[[["outpoint",3]],[["result",4],["error",4],["option",4]]]],[11,"get_raw_tx","","",14,[[["txid",3]],[["error",4],["result",4],["option",4]]]],[11,"get_tx","","",14,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"get_last_index","","",14,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[11,"increment_last_index","","",14,[[["scripttype",4]],[["error",4],["result",4]]]],[11,"begin_batch","","",14,[[]]],[11,"commit_batch","","",14,[[],[["result",4],["error",4]]]],[11,"extract_policy","bdk::descriptor","",19,[[["signerscontainer",3],["arc",3]],[["error",4],["option",4],["result",4]]]],[11,"extract_policy","","",18,[[["signerscontainer",3],["arc",3]],[["error",4],["option",4],["result",4]]]],[11,"coin_select","bdk::wallet::coin_selection","",65,[[["vec",3],["feerate",3],["utxo",3]],[["error",4],["result",4],["coinselectionresult",3]]]],[11,"get_capabilities","bdk::blockchain::electrum","",61,[[],[["hashset",3],["capability",4]]]],[11,"setup","","",61,[[["progress",8],["option",4]],[["result",4],["error",4]]]],[11,"get_tx","","",61,[[["txid",3]],[["error",4],["result",4],["option",4]]]],[11,"broadcast","","",61,[[["transaction",3]],[["result",4],["error",4]]]],[11,"get_height","","",61,[[],[["error",4],["result",4]]]],[11,"estimate_fee","","",61,[[],[["feerate",3],["result",4],["error",4]]]],[11,"get_capabilities","bdk::blockchain::esplora","",7,[[],[["hashset",3],["capability",4]]]],[11,"setup","","",7,[[["progress",8],["option",4]],[["result",4],["error",4]]]],[11,"get_tx","","",7,[[["txid",3]],[["error",4],["result",4],["option",4]]]],[11,"broadcast","","",7,[[["transaction",3]],[["result",4],["error",4]]]],[11,"get_height","","",7,[[],[["error",4],["result",4]]]],[11,"estimate_fee","","",7,[[],[["feerate",3],["result",4],["error",4]]]],[11,"get_capabilities","bdk::blockchain::compact_filters","",11,[[],[["hashset",3],["capability",4]]]],[11,"setup","","",11,[[["progress",8],["option",4]],[["result",4],["error",4]]]],[11,"get_tx","","",11,[[["txid",3]],[["error",4],["result",4],["option",4]]]],[11,"broadcast","","",11,[[["transaction",3]],[["result",4],["error",4]]]],[11,"get_height","","",11,[[],[["error",4],["result",4]]]],[11,"estimate_fee","","",11,[[],[["feerate",3],["result",4],["error",4]]]],[11,"as_ref","bdk","",4,[[]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["addressvalidatorerror",4]]]],[11,"from","","",2,[[["policyerror",4]]]],[11,"from","","",2,[[["signererror",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",3]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["esploraerror",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["compactfilterserror",4]]]],[11,"from","bdk::blockchain::electrum","",61,[[["client",4]]]],[11,"from","bdk::blockchain::esplora","",6,[[["error",3]]]],[11,"from","","",6,[[["parseinterror",3]]]],[11,"from","","",6,[[["error",4]]]],[11,"from","bdk::blockchain::compact_filters","",8,[[["error",3]]]],[11,"from","","",8,[[["error",3]]]],[11,"from","","",8,[[["error",4]]]],[11,"from","","",8,[[["systemtimeerror",3]]]],[11,"from","","",8,[[["error",4]]]],[11,"from","bdk::descriptor::error","",24,[[["error",4]]]],[11,"from","","",24,[[["error",4]]]],[11,"from","","",24,[[["error",4]]]],[11,"from","","",24,[[["error",4]]]],[11,"from","","",24,[[["error",4]]]],[11,"from","","",24,[[["policyerror",4]]]],[11,"from","bdk::descriptor::policy","",36,[[]]],[11,"from","","",25,[[["satisfiableitem",4]]]],[11,"from","bdk::wallet::signer","",49,[[["hash",3]],[["signerid",4],["descriptorpublickey",4]]]],[11,"from","","",49,[[["fingerprint",3]],[["signerid",4],["descriptorpublickey",4]]]],[11,"from","","",52,[[["keymap",6]],[["signerscontainer",3],["descriptorpublickey",4]]]],[11,"clone","bdk::blockchain","",5,[[],["capability",4]]],[11,"clone","","",59,[[],["noopprogress",3]]],[11,"clone","","",60,[[],["logprogress",3]]],[11,"clone","bdk::descriptor::policy","",64,[[],["pkorf",3]]],[11,"clone","","",27,[[],["satisfiableitem",4]]],[11,"clone","","",36,[[],["satisfaction",4]]],[11,"clone","","",25,[[],["policy",3]]],[11,"clone","","",26,[[],["condition",3]]],[11,"clone","bdk","",4,[[],["scripttype",4]]],[11,"clone","","",42,[[],["feerate",3]]],[11,"clone","","",0,[[],["utxo",3]]],[11,"clone","","",1,[[],["transactiondetails",3]]],[11,"clone","bdk::wallet::address_validator","",43,[[],["addressvalidatorerror",4]]],[11,"clone","bdk::wallet::signer","",49,[[],["signerid",4]]],[11,"clone","","",50,[[],["signererror",4]]],[11,"clone","","",48,[[],["signerordering",3]]],[11,"clone","","",52,[[],["signerscontainer",3]]],[11,"clone","bdk::wallet::tx_builder","",53,[[],["txordering",4]]],[11,"clone","","",54,[[],["changespendpolicy",4]]],[11,"default","bdk::blockchain::compact_filters","",9,[[],["mempool",3]]],[11,"default","bdk::database::memory","",14,[[],["memorydatabase",3]]],[11,"default","bdk::descriptor::policy","",64,[[],["pkorf",3]]],[11,"default","","",26,[[],["condition",3]]],[11,"default","bdk","",42,[[]]],[11,"default","","",1,[[],["transactiondetails",3]]],[11,"default","bdk::wallet::coin_selection","",65,[[],["dumbcoinselection",3]]],[11,"default","bdk::wallet::signer","",48,[[]]],[11,"default","","",52,[[],["signerscontainer",3]]],[11,"default","bdk::wallet::tx_builder","",55,[[],["txbuilder",3]]],[11,"default","","",53,[[]]],[11,"default","","",54,[[]]],[11,"cmp","bdk::descriptor::policy","",26,[[["condition",3]],["ordering",4]]],[11,"cmp","bdk::wallet::signer","",48,[[["signerordering",3]],["ordering",4]]],[11,"cmp","bdk::wallet::tx_builder","",53,[[["txordering",4]],["ordering",4]]],[11,"cmp","","",54,[[["changespendpolicy",4]],["ordering",4]]],[11,"eq","bdk::blockchain","",5,[[["capability",4]]]],[11,"eq","bdk::descriptor::policy","",26,[[["condition",3]]]],[11,"ne","","",26,[[["condition",3]]]],[11,"eq","bdk","",4,[[["scripttype",4]]]],[11,"eq","","",42,[[["feerate",3]]]],[11,"ne","","",42,[[["feerate",3]]]],[11,"eq","","",0,[[["utxo",3]]]],[11,"ne","","",0,[[["utxo",3]]]],[11,"eq","","",1,[[["transactiondetails",3]]]],[11,"ne","","",1,[[["transactiondetails",3]]]],[11,"eq","bdk::wallet::address_validator","",43,[[["addressvalidatorerror",4]]]],[11,"ne","","",43,[[["addressvalidatorerror",4]]]],[11,"eq","bdk::wallet::signer","",49,[[["signerid",4]]]],[11,"ne","","",49,[[["signerid",4]]]],[11,"eq","","",50,[[["signererror",4]]]],[11,"eq","","",48,[[["signerordering",3]]]],[11,"ne","","",48,[[["signerordering",3]]]],[11,"eq","bdk::wallet::tx_builder","",53,[[["txordering",4]]]],[11,"eq","","",54,[[["changespendpolicy",4]]]],[11,"partial_cmp","bdk::descriptor::policy","",26,[[["condition",3]],[["option",4],["ordering",4]]]],[11,"lt","","",26,[[["condition",3]]]],[11,"le","","",26,[[["condition",3]]]],[11,"gt","","",26,[[["condition",3]]]],[11,"ge","","",26,[[["condition",3]]]],[11,"partial_cmp","bdk","",42,[[["feerate",3]],[["option",4],["ordering",4]]]],[11,"lt","","",42,[[["feerate",3]]]],[11,"le","","",42,[[["feerate",3]]]],[11,"gt","","",42,[[["feerate",3]]]],[11,"ge","","",42,[[["feerate",3]]]],[11,"partial_cmp","bdk::wallet::signer","",48,[[["signerordering",3]],[["option",4],["ordering",4]]]],[11,"lt","","",48,[[["signerordering",3]]]],[11,"le","","",48,[[["signerordering",3]]]],[11,"gt","","",48,[[["signerordering",3]]]],[11,"ge","","",48,[[["signerordering",3]]]],[11,"partial_cmp","bdk::wallet::tx_builder","",53,[[["txordering",4]],[["option",4],["ordering",4]]]],[11,"partial_cmp","","",54,[[["changespendpolicy",4]],[["option",4],["ordering",4]]]],[11,"to_string","bdk::wallet::export","",47,[[],["string",3]]],[11,"fmt","bdk","",2,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::esplora","",7,[[["formatter",3]],["result",6]]],[11,"fmt","","",6,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::compact_filters","",9,[[["formatter",3]],["result",6]]],[11,"fmt","","",10,[[["formatter",3]],["result",6]]],[11,"fmt","","",11,[[["formatter",3]],["result",6]]],[11,"fmt","","",8,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain","",5,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::database::memory","",14,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::error","",24,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::policy","",64,[[["formatter",3]],["result",6]]],[11,"fmt","","",27,[[["formatter",3]],["result",6]]],[11,"fmt","","",36,[[["formatter",3]],["result",6]]],[11,"fmt","","",25,[[["formatter",3]],["result",6]]],[11,"fmt","","",26,[[["formatter",3]],["result",6]]],[11,"fmt","","",40,[[["formatter",3]],["result",6]]],[11,"fmt","bdk","",4,[[["formatter",3]],["result",6]]],[11,"fmt","","",42,[[["formatter",3]],["result",6]]],[11,"fmt","","",0,[[["formatter",3]],["result",6]]],[11,"fmt","","",1,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::address_validator","",43,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::coin_selection","",45,[[["formatter",3]],["result",6]]],[11,"fmt","","",65,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::export","",47,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::signer","",49,[[["formatter",3]],["result",6]]],[11,"fmt","","",50,[[["formatter",3]],["result",6]]],[11,"fmt","","",48,[[["formatter",3]],["result",6]]],[11,"fmt","","",52,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::tx_builder","",55,[[["formatter",3]],["result",6]]],[11,"fmt","","",53,[[["formatter",3]],["result",6]]],[11,"fmt","","",54,[[["formatter",3]],["result",6]]],[11,"fmt","bdk","",2,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::esplora","",6,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::compact_filters","",8,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::error","",24,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::policy","",40,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::address_validator","",43,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::signer","",50,[[["formatter",3]],["result",6]]],[11,"hash","bdk::blockchain","",5,[[]]],[11,"hash","bdk::descriptor::policy","",26,[[]]],[11,"hash","bdk","",4,[[]]],[11,"hash","bdk::wallet::signer","",49,[[]]],[11,"hash","bdk::wallet::tx_builder","",53,[[]]],[11,"hash","","",54,[[]]],[11,"from_str","bdk::wallet::export","",47,[[],["result",4]]],[11,"serialize","bdk::descriptor::policy","",64,[[],["result",4]]],[11,"serialize","","",27,[[],["result",4]]],[11,"serialize","","",36,[[],["result",4]]],[11,"serialize","","",25,[[],["result",4]]],[11,"serialize","","",26,[[],["result",4]]],[11,"serialize","bdk","",4,[[],["result",4]]],[11,"serialize","","",0,[[],["result",4]]],[11,"serialize","","",1,[[],["result",4]]],[11,"serialize","bdk::wallet::export","",47,[[],["result",4]]],[11,"deserialize","bdk","",4,[[],["result",4]]],[11,"deserialize","","",0,[[],["result",4]]],[11,"deserialize","","",1,[[],["result",4]]],[11,"deserialize","bdk::wallet::export","",47,[[],["result",4]]],[11,"translate_pk","bdk::descriptor","Convert a descriptor using abstract keys to one using…",18,[[],[["result",4],["descriptor",4]]]],[11,"address","","Computes the Bitcoin address of the descriptor, if one…",18,[[["network",4]],[["option",4],["address",3]]]],[11,"script_pubkey","","Computes the scriptpubkey of the descriptor",18,[[],["script",3]]],[11,"unsigned_script_sig","","Computes the scriptSig that will be in place for an…",18,[[],["script",3]]],[11,"witness_script","","Computes the \\\"witness script\\\" of the descriptor, i.e. the…",18,[[],["script",3]]],[11,"satisfy","","Attempts to produce a satisfying witness and scriptSig to…",18,[[["txin",3]],[["error",4],["result",4]]]],[11,"max_satisfaction_weight","","Computes an upper bound on the weight of a satisfying…",18,[[]]],[11,"derive","","Derives all wildcard keys in the descriptor using the…",18,[[],[["descriptor",4],["descriptorpublickey",4]]]],[11,"parse_secret","","",18,[[],[["result",4],["error",4]]]],[11,"to_string_with_secret","","",18,[[["hashmap",3]],["string",3]]],[11,"from_ast","","Add type information(Type and Extdata) to Miniscript based…",19,[[["terminal",4]],[["result",4],["error",4],["miniscript",3]]]],[11,"into_inner","","Extracts the `AstElem` representing the root of the…",19,[[],["terminal",4]]],[11,"as_inner","","",19,[[],["terminal",4]]],[11,"parse","","Attempt to parse a script into a Miniscript representation",19,[[["script",3]],[["error",4],["miniscript",3],["result",4]]]],[11,"encode","","Encode as a Bitcoin script",19,[[],["script",3]]],[11,"script_size","","Size, in bytes of the script-pubkey. If this Miniscript is…",19,[[]]],[11,"max_satisfaction_witness_elements","","Maximum number of witness elements used to satisfy the…",19,[[]]],[11,"max_satisfaction_size","","Maximum size, in bytes, of a satisfying witness. For…",19,[[]]],[11,"translate_pk","","This will panic if translatefpk returns an uncompressed…",19,[[],[["result",4],["miniscript",3]]]],[11,"satisfy","","Attempt to produce a satisfying witness for the witness…",19,[[],[["option",4],["vec",3]]]],[11,"translate_pk","","Convert an AST element with one public key type to one of…",22,[[],[["result",4],["terminal",4]]]],[11,"encode","","Encode the element as a fragment of Bitcoin Script. The…",22,[[["builder",3]],["builder",3]]],[11,"script_size","","Size, in bytes of the script-pubkey. If this Miniscript is…",22,[[]]],[11,"max_dissatisfaction_witness_elements","","Maximum number of witness elements used to dissatisfy the…",22,[[],["option",4]]],[11,"max_dissatisfaction_size","","Maximum dissatisfaction cost, in bytes, of a Miniscript…",22,[[],["option",4]]],[11,"max_satisfaction_witness_elements","","Maximum number of witness elements used to satisfy the…",22,[[]]],[11,"max_satisfaction_size","","Maximum size, in bytes, of a satisfying witness. For…",22,[[]]]],"p":[[3,"UTXO"],[3,"TransactionDetails"],[4,"Error"],[13,"FeeRateTooLow"],[4,"ScriptType"],[4,"Capability"],[4,"EsploraError"],[3,"EsploraBlockchain"],[4,"CompactFiltersError"],[3,"Mempool"],[3,"Peer"],[3,"CompactFiltersBlockchain"],[8,"Blockchain"],[8,"Progress"],[3,"MemoryDatabase"],[8,"BatchOperations"],[8,"Database"],[8,"BatchDatabase"],[4,"Descriptor"],[3,"Miniscript"],[8,"MiniscriptKey"],[8,"ScriptContext"],[4,"Terminal"],[8,"ToPublicKey"],[4,"Error"],[3,"Policy"],[3,"Condition"],[4,"SatisfiableItem"],[13,"SHA256Preimage"],[13,"HASH256Preimage"],[13,"RIPEMD160Preimage"],[13,"HASH160Preimage"],[13,"AbsoluteTimelock"],[13,"RelativeTimelock"],[13,"Thresh"],[13,"Multisig"],[4,"Satisfaction"],[13,"Partial"],[13,"PartialComplete"],[13,"Complete"],[4,"PolicyError"],[8,"ExtractPolicy"],[3,"FeeRate"],[4,"AddressValidatorError"],[8,"AddressValidator"],[3,"CoinSelectionResult"],[8,"CoinSelectionAlgorithm"],[3,"WalletExport"],[3,"SignerOrdering"],[4,"SignerId"],[4,"SignerError"],[8,"Signer"],[3,"SignersContainer"],[4,"TxOrdering"],[4,"ChangeSpendPolicy"],[3,"TxBuilder"],[8,"IsDust"],[3,"Wallet"],[3,"OfflineBlockchain"],[3,"NoopProgress"],[3,"LogProgress"],[3,"ElectrumBlockchain"],[4,"Legacy"],[4,"Segwitv0"],[3,"PKOrF"],[3,"DumbCoinSelection"]]}\ +}'); +addSearchOptions(searchIndex);initSearch(searchIndex); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/settings.css b/static/docs-rs/bdk/0.1.0-beta.1/settings.css new file mode 100644 index 0000000000..6ce7665866 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/settings.css @@ -0,0 +1 @@ +.setting-line{padding:5px;position:relative;}.setting-line>div{max-width:calc(100% - 74px);display:inline-block;vertical-align:top;font-size:17px;padding-top:2px;}.setting-line>.title{font-size:19px;width:100%;max-width:none;border-bottom:1px solid;}.toggle{position:relative;display:inline-block;width:45px;height:27px;margin-right:20px;}.toggle input{display:none;}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.3s;transition:.3s;}.slider:before{position:absolute;content:"";height:19px;width:19px;left:4px;bottom:4px;background-color:white;-webkit-transition:.3s;transition:.3s;}input:checked+.slider{background-color:#2196F3;}input:focus+.slider{box-shadow:0 0 1px #2196F3;}input:checked+.slider:before{-webkit-transform:translateX(19px);-ms-transform:translateX(19px);transform:translateX(19px);}.setting-line>.sub-settings{padding-left:42px;width:100%;display:block;} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/settings.html b/static/docs-rs/bdk/0.1.0-beta.1/settings.html new file mode 100644 index 0000000000..12a71ee2cf --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/settings.html @@ -0,0 +1,2 @@ +Rustdoc settings

Rustdoc settings

Auto-hide item declarations
Auto-hide structs declaration
Auto-hide enums declaration
Auto-hide unions declaration
Auto-hide traits declaration
Auto-hide macros declaration
+
Auto-hide item attributes.
Auto-hide item methods' documentation
Auto-hide trait implementations documentation
Directly go to item in search if there is only one result
Show line numbers on code examples
Disable keyboard shortcuts
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/settings.js b/static/docs-rs/bdk/0.1.0-beta.1/settings.js new file mode 100644 index 0000000000..9930309054 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/settings.js @@ -0,0 +1 @@ +(function(){function changeSetting(settingName,isEnabled){updateLocalStorage('rustdoc-'+settingName,isEnabled)}function getSettingValue(settingName){return getCurrentValue('rustdoc-'+settingName)}function setEvents(){var elems=document.getElementsByClassName("slider");if(!elems||elems.length===0){return}for(var i=0;i"){sidebar.style.left="";this.style.left="";child.innerText="<";updateLocalStorage("rustdoc-source-sidebar-show","true")}else{sidebar.style.left="-300px";this.style.left="0";child.innerText=">";updateLocalStorage("rustdoc-source-sidebar-show","false")}}function createSidebarToggle(){var sidebarToggle=document.createElement("div");sidebarToggle.id="sidebar-toggle";sidebarToggle.onclick=toggleSidebar;var inner1=document.createElement("div");inner1.style.position="relative";var inner2=document.createElement("div");inner2.style.paddingTop="3px";if(getCurrentValue("rustdoc-source-sidebar-show")==="true"){inner2.innerText="<"}else{inner2.innerText=">";sidebarToggle.style.left="0"}inner1.appendChild(inner2);sidebarToggle.appendChild(inner1);return sidebarToggle}function createSourceSidebar(){if(window.rootPath.endsWith("/")===false){window.rootPath+="/"}var main=document.getElementById("main");var sidebarToggle=createSidebarToggle();main.insertBefore(sidebarToggle,main.firstChild);var sidebar=document.createElement("div");sidebar.id="source-sidebar";if(getCurrentValue("rustdoc-source-sidebar-show")!=="true"){sidebar.style.left="-300px"}var currentFile=getCurrentFilePath();var hasFoundFile=false;var title=document.createElement("div");title.className="title";title.innerText="Files";sidebar.appendChild(title);Object.keys(sourcesIndex).forEach(function(key){sourcesIndex[key].name=key;hasFoundFile=createDirEntry(sourcesIndex[key],sidebar,"",currentFile,hasFoundFile)});main.insertBefore(sidebar,main.firstChild)} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/mod.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/mod.rs.html new file mode 100644 index 0000000000..6fad4c357b --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/mod.rs.html @@ -0,0 +1,1057 @@ +mod.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Compact Filters
+//!
+//! This module contains a multithreaded implementation of an [`Blockchain`] backend that
+//! uses BIP157 (aka "Neutrino") to populate the wallet's [database](crate::database::Database)
+//! by downloading compact filters from the P2P network.
+//!
+//! Since there are currently very few peers "in the wild" that advertise the required service
+//! flag, this implementation requires that one or more known peers are provided by the user.
+//! No dns or other kinds of peer discovery are done internally.
+//!
+//! Moreover, this module doesn't currently support detecting and resolving conflicts between
+//! messages received by different peers. Thus, it's recommended to use this module by only
+//! connecting to a single peer at a time, optionally by opening multiple connections if it's
+//! desirable to use multiple threads at once to sync in parallel.
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use std::sync::Arc;
+//! # use bitcoin::*;
+//! # use bdk::*;
+//! # use bdk::blockchain::compact_filters::*;
+//! let num_threads = 4;
+//!
+//! let mempool = Arc::new(Mempool::default());
+//! let peers = (0..num_threads)
+//!     .map(|_| Peer::connect(
+//!         "btcd-mainnet.lightning.computer:8333",
+//!         Arc::clone(&mempool),
+//!         Network::Bitcoin,
+//!     ))
+//!     .collect::<Result<_, _>>()?;
+//! let blockchain = CompactFiltersBlockchain::new(peers, "./wallet-filters", Some(500_000))?;
+//! # Ok::<(), bdk::error::Error>(())
+//! ```
+
+use std::collections::HashSet;
+use std::fmt;
+use std::path::Path;
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::{Arc, Mutex};
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use bitcoin::network::message_blockdata::Inventory;
+use bitcoin::{OutPoint, Transaction, Txid};
+
+use rocksdb::{Options, SliceTransform, DB};
+
+mod peer;
+mod store;
+mod sync;
+
+use super::{Blockchain, Capability, Progress};
+use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
+use crate::error::Error;
+use crate::types::{ScriptType, TransactionDetails, UTXO};
+use crate::FeeRate;
+
+use peer::*;
+use store::*;
+use sync::*;
+
+pub use peer::{Mempool, Peer};
+
+const SYNC_HEADERS_COST: f32 = 1.0;
+const SYNC_FILTERS_COST: f32 = 11.6 * 1_000.0;
+const PROCESS_BLOCKS_COST: f32 = 20_000.0;
+
+/// Structure implementing the required blockchain traits
+///
+/// ## Example
+/// See the [`blockchain::compact_filters`](crate::blockchain::compact_filters) module for a usage example.
+#[derive(Debug)]
+pub struct CompactFiltersBlockchain {
+    peers: Vec<Arc<Peer>>,
+    headers: Arc<ChainStore<Full>>,
+    skip_blocks: Option<usize>,
+}
+
+impl CompactFiltersBlockchain {
+    /// Construct a new instance given a list of peers, a path to store headers and block
+    /// filters downloaded during the sync and optionally a number of blocks to ignore starting
+    /// from the genesis while scanning for the wallet's outputs.
+    ///
+    /// For each [`Peer`] specified a new thread will be spawned to download and verify the filters
+    /// in parallel. It's currently recommended to only connect to a single peer to avoid
+    /// inconsistencies in the data returned, optionally with multiple connections in parallel to
+    /// speed-up the sync process.
+    pub fn new<P: AsRef<Path>>(
+        peers: Vec<Peer>,
+        storage_dir: P,
+        skip_blocks: Option<usize>,
+    ) -> Result<Self, CompactFiltersError> {
+        if peers.is_empty() {
+            return Err(CompactFiltersError::NoPeers);
+        }
+
+        let mut opts = Options::default();
+        opts.create_if_missing(true);
+        opts.set_prefix_extractor(SliceTransform::create_fixed_prefix(16));
+
+        let network = peers[0].get_network();
+
+        let cfs = DB::list_cf(&opts, &storage_dir).unwrap_or(vec!["default".to_string()]);
+        let db = DB::open_cf(&opts, &storage_dir, &cfs)?;
+        let headers = Arc::new(ChainStore::new(db, network)?);
+
+        // try to recover partial snapshots
+        for cf_name in &cfs {
+            if !cf_name.starts_with("_headers:") {
+                continue;
+            }
+
+            info!("Trying to recover: {:?}", cf_name);
+            headers.recover_snapshot(cf_name)?;
+        }
+
+        Ok(CompactFiltersBlockchain {
+            peers: peers.into_iter().map(Arc::new).collect(),
+            headers,
+            skip_blocks,
+        })
+    }
+
+    /// Process a transaction by looking for inputs that spend from a UTXO in the database or
+    /// outputs that send funds to a know script_pubkey.
+    fn process_tx<D: BatchDatabase>(
+        &self,
+        database: &mut D,
+        tx: &Transaction,
+        height: Option<u32>,
+        timestamp: u64,
+        internal_max_deriv: &mut Option<u32>,
+        external_max_deriv: &mut Option<u32>,
+    ) -> Result<(), Error> {
+        let mut updates = database.begin_batch();
+
+        let mut incoming: u64 = 0;
+        let mut outgoing: u64 = 0;
+
+        let mut inputs_sum: u64 = 0;
+        let mut outputs_sum: u64 = 0;
+
+        // look for our own inputs
+        for (i, input) in tx.input.iter().enumerate() {
+            if let Some(previous_output) = database.get_previous_output(&input.previous_output)? {
+                inputs_sum += previous_output.value;
+
+                if database.is_mine(&previous_output.script_pubkey)? {
+                    outgoing += previous_output.value;
+
+                    debug!("{} input #{} is mine, removing from utxo", tx.txid(), i);
+                    updates.del_utxo(&input.previous_output)?;
+                }
+            }
+        }
+
+        for (i, output) in tx.output.iter().enumerate() {
+            // to compute the fees later
+            outputs_sum += output.value;
+
+            // this output is ours, we have a path to derive it
+            if let Some((script_type, child)) =
+                database.get_path_from_script_pubkey(&output.script_pubkey)?
+            {
+                debug!("{} output #{} is mine, adding utxo", tx.txid(), i);
+                updates.set_utxo(&UTXO {
+                    outpoint: OutPoint::new(tx.txid(), i as u32),
+                    txout: output.clone(),
+                    is_internal: script_type.is_internal(),
+                })?;
+                incoming += output.value;
+
+                if script_type == ScriptType::Internal
+                    && (internal_max_deriv.is_none() || child > internal_max_deriv.unwrap_or(0))
+                {
+                    *internal_max_deriv = Some(child);
+                } else if script_type == ScriptType::External
+                    && (external_max_deriv.is_none() || child > external_max_deriv.unwrap_or(0))
+                {
+                    *external_max_deriv = Some(child);
+                }
+            }
+        }
+
+        if incoming > 0 || outgoing > 0 {
+            let tx = TransactionDetails {
+                txid: tx.txid(),
+                transaction: Some(tx.clone()),
+                received: incoming,
+                sent: outgoing,
+                height,
+                timestamp,
+                fees: inputs_sum.checked_sub(outputs_sum).unwrap_or(0),
+            };
+
+            info!("Saving tx {}", tx.txid);
+            updates.set_tx(&tx)?;
+        }
+
+        database.commit_batch(updates)?;
+
+        Ok(())
+    }
+}
+
+impl Blockchain for CompactFiltersBlockchain {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        vec![Capability::FullHistory].into_iter().collect()
+    }
+
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        _stop_gap: Option<usize>, // TODO: move to electrum and esplora only
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        let first_peer = &self.peers[0];
+
+        let skip_blocks = self.skip_blocks.unwrap_or(0);
+
+        let cf_sync = Arc::new(CFSync::new(Arc::clone(&self.headers), skip_blocks, 0x00)?);
+
+        let initial_height = self.headers.get_height()?;
+        let total_bundles = (first_peer.get_version().start_height as usize)
+            .checked_sub(skip_blocks)
+            .map(|x| x / 1000)
+            .unwrap_or(0)
+            + 1;
+        let expected_bundles_to_sync = total_bundles
+            .checked_sub(cf_sync.pruned_bundles()?)
+            .unwrap_or(0);
+
+        let headers_cost = (first_peer.get_version().start_height as usize)
+            .checked_sub(initial_height)
+            .unwrap_or(0) as f32
+            * SYNC_HEADERS_COST;
+        let filters_cost = expected_bundles_to_sync as f32 * SYNC_FILTERS_COST;
+
+        let total_cost = headers_cost + filters_cost + PROCESS_BLOCKS_COST;
+
+        if let Some(snapshot) = sync::sync_headers(
+            Arc::clone(&first_peer),
+            Arc::clone(&self.headers),
+            |new_height| {
+                let local_headers_cost =
+                    new_height.checked_sub(initial_height).unwrap_or(0) as f32 * SYNC_HEADERS_COST;
+                progress_update.update(
+                    local_headers_cost / total_cost * 100.0,
+                    Some(format!("Synced headers to {}", new_height)),
+                )
+            },
+        )? {
+            if snapshot.work()? > self.headers.work()? {
+                info!("Applying snapshot with work: {}", snapshot.work()?);
+                self.headers.apply_snapshot(snapshot)?;
+            }
+        }
+
+        let synced_height = self.headers.get_height()?;
+        let buried_height = synced_height
+            .checked_sub(sync::BURIED_CONFIRMATIONS)
+            .unwrap_or(0);
+        info!("Synced headers to height: {}", synced_height);
+
+        cf_sync.prepare_sync(Arc::clone(&first_peer))?;
+
+        let all_scripts = Arc::new(
+            database
+                .iter_script_pubkeys(None)?
+                .into_iter()
+                .map(|s| s.to_bytes())
+                .collect::<Vec<_>>(),
+        );
+
+        let last_synced_block = Arc::new(Mutex::new(synced_height));
+        let synced_bundles = Arc::new(AtomicUsize::new(0));
+        let progress_update = Arc::new(Mutex::new(progress_update));
+
+        let mut threads = Vec::with_capacity(self.peers.len());
+        for peer in &self.peers {
+            let cf_sync = Arc::clone(&cf_sync);
+            let peer = Arc::clone(&peer);
+            let headers = Arc::clone(&self.headers);
+            let all_scripts = Arc::clone(&all_scripts);
+            let last_synced_block = Arc::clone(&last_synced_block);
+            let progress_update = Arc::clone(&progress_update);
+            let synced_bundles = Arc::clone(&synced_bundles);
+
+            let thread = std::thread::spawn(move || {
+                cf_sync.capture_thread_for_sync(
+                    peer,
+                    |block_hash, filter| {
+                        if !filter
+                            .match_any(block_hash, &mut all_scripts.iter().map(AsRef::as_ref))?
+                        {
+                            return Ok(false);
+                        }
+
+                        let block_height = headers.get_height_for(block_hash)?.unwrap_or(0);
+                        let saved_correct_block = match headers.get_full_block(block_height)? {
+                            Some(block) if &block.block_hash() == block_hash => true,
+                            _ => false,
+                        };
+
+                        if saved_correct_block {
+                            Ok(false)
+                        } else {
+                            let mut last_synced_block = last_synced_block.lock().unwrap();
+
+                            // If we download a block older than `last_synced_block`, we update it so that
+                            // we know to delete and re-process all txs starting from that height
+                            if block_height < *last_synced_block {
+                                *last_synced_block = block_height;
+                            }
+
+                            Ok(true)
+                        }
+                    },
+                    |index| {
+                        let synced_bundles = synced_bundles.fetch_add(1, Ordering::SeqCst);
+                        let local_filters_cost = synced_bundles as f32 * SYNC_FILTERS_COST;
+                        progress_update.lock().unwrap().update(
+                            (headers_cost + local_filters_cost) / total_cost * 100.0,
+                            Some(format!(
+                                "Synced filters {} - {}",
+                                index * 1000 + 1,
+                                (index + 1) * 1000
+                            )),
+                        )
+                    },
+                )
+            });
+
+            threads.push(thread);
+        }
+
+        for t in threads {
+            t.join().unwrap()?;
+        }
+
+        progress_update.lock().unwrap().update(
+            (headers_cost + filters_cost) / total_cost * 100.0,
+            Some("Processing downloaded blocks and mempool".into()),
+        )?;
+
+        // delete all txs newer than last_synced_block
+        let last_synced_block = *last_synced_block.lock().unwrap();
+        log::debug!(
+            "Dropping transactions newer than `last_synced_block` = {}",
+            last_synced_block
+        );
+        let mut updates = database.begin_batch();
+        for details in database.iter_txs(false)? {
+            match details.height {
+                Some(height) if (height as usize) < last_synced_block => continue,
+                _ => updates.del_tx(&details.txid, false)?,
+            };
+        }
+        database.commit_batch(updates)?;
+
+        first_peer.ask_for_mempool()?;
+
+        let mut internal_max_deriv = None;
+        let mut external_max_deriv = None;
+
+        for (height, block) in self.headers.iter_full_blocks()? {
+            for tx in &block.txdata {
+                self.process_tx(
+                    database,
+                    tx,
+                    Some(height as u32),
+                    0,
+                    &mut internal_max_deriv,
+                    &mut external_max_deriv,
+                )?;
+            }
+        }
+        for tx in first_peer.get_mempool().iter_txs().iter() {
+            self.process_tx(
+                database,
+                tx,
+                None,
+                0,
+                &mut internal_max_deriv,
+                &mut external_max_deriv,
+            )?;
+        }
+
+        let current_ext = database.get_last_index(ScriptType::External)?.unwrap_or(0);
+        let first_ext_new = external_max_deriv.map(|x| x + 1).unwrap_or(0);
+        if first_ext_new > current_ext {
+            info!("Setting external index to {}", first_ext_new);
+            database.set_last_index(ScriptType::External, first_ext_new)?;
+        }
+
+        let current_int = database.get_last_index(ScriptType::Internal)?.unwrap_or(0);
+        let first_int_new = internal_max_deriv.map(|x| x + 1).unwrap_or(0);
+        if first_int_new > current_int {
+            info!("Setting internal index to {}", first_int_new);
+            database.set_last_index(ScriptType::Internal, first_int_new)?;
+        }
+
+        info!("Dropping blocks until {}", buried_height);
+        self.headers.delete_blocks_until(buried_height)?;
+
+        progress_update
+            .lock()
+            .unwrap()
+            .update(100.0, Some("Done".into()))?;
+
+        Ok(())
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        Ok(self.peers[0]
+            .get_mempool()
+            .get_tx(&Inventory::Transaction(*txid)))
+    }
+
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        self.peers[0].broadcast_tx(tx.clone())?;
+
+        Ok(())
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        Ok(self.headers.get_height()? as u32)
+    }
+
+    fn estimate_fee(&self, _target: usize) -> Result<FeeRate, Error> {
+        // TODO
+        Ok(FeeRate::default())
+    }
+}
+
+/// An error that can occur during sync with a [`CompactFiltersBlockchain`]
+#[derive(Debug)]
+pub enum CompactFiltersError {
+    /// A peer sent an invalid or unexpected response
+    InvalidResponse,
+    /// The headers returned are invalid
+    InvalidHeaders,
+    /// The compact filter headers returned are invalid
+    InvalidFilterHeader,
+    /// The compact filter returned is invalid
+    InvalidFilter,
+    /// The peer is missing a block in the valid chain
+    MissingBlock,
+    /// The data stored in the block filters storage are corrupted
+    DataCorruption,
+
+    /// A peer is not connected
+    NotConnected,
+    /// A peer took too long to reply to one of our messages
+    Timeout,
+
+    /// No peers have been specified
+    NoPeers,
+
+    /// Internal database error
+    DB(rocksdb::Error),
+    /// Internal I/O error
+    IO(std::io::Error),
+    /// Invalid BIP158 filter
+    BIP158(bitcoin::util::bip158::Error),
+    /// Internal system time error
+    Time(std::time::SystemTimeError),
+
+    /// Wrapper for [`crate::error::Error`]
+    Global(Box<crate::error::Error>),
+}
+
+impl fmt::Display for CompactFiltersError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for CompactFiltersError {}
+
+macro_rules! impl_error {
+    ( $from:ty, $to:ident ) => {
+        impl std::convert::From<$from> for CompactFiltersError {
+            fn from(err: $from) -> Self {
+                CompactFiltersError::$to(err)
+            }
+        }
+    };
+}
+
+impl_error!(rocksdb::Error, DB);
+impl_error!(std::io::Error, IO);
+impl_error!(bitcoin::util::bip158::Error, BIP158);
+impl_error!(std::time::SystemTimeError, Time);
+
+impl From<crate::error::Error> for CompactFiltersError {
+    fn from(err: crate::error::Error) -> Self {
+        CompactFiltersError::Global(Box::new(err))
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/peer.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/peer.rs.html new file mode 100644 index 0000000000..cdec7c7773 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/peer.rs.html @@ -0,0 +1,1103 @@ +peer.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::collections::HashMap;
+use std::net::{TcpStream, ToSocketAddrs};
+use std::sync::{Arc, Condvar, Mutex, RwLock};
+use std::thread;
+use std::time::{Duration, SystemTime, UNIX_EPOCH};
+
+use socks::{Socks5Stream, ToTargetAddr};
+
+use rand::{thread_rng, Rng};
+
+use bitcoin::consensus::Encodable;
+use bitcoin::hash_types::BlockHash;
+use bitcoin::hashes::Hash;
+use bitcoin::network::constants::ServiceFlags;
+use bitcoin::network::message::{NetworkMessage, RawNetworkMessage};
+use bitcoin::network::message_blockdata::*;
+use bitcoin::network::message_filter::*;
+use bitcoin::network::message_network::VersionMessage;
+use bitcoin::network::stream_reader::StreamReader;
+use bitcoin::network::Address;
+use bitcoin::{Block, Network, Transaction, Txid};
+
+use super::CompactFiltersError;
+
+type ResponsesMap = HashMap<&'static str, Arc<(Mutex<Vec<NetworkMessage>>, Condvar)>>;
+
+pub(crate) const TIMEOUT_SECS: u64 = 30;
+
+/// Container for unconfirmed, but valid Bitcoin transactions
+///
+/// It is normally shared between [`Peer`]s with the use of [`Arc`], so that transactions are not
+/// duplicated in memory.
+#[derive(Debug, Default)]
+pub struct Mempool {
+    txs: RwLock<HashMap<Txid, Transaction>>,
+}
+
+impl Mempool {
+    /// Add a transaction to the mempool
+    ///
+    /// Note that this doesn't propagate the transaction to other
+    /// peers. To do that, [`broadcast`](crate::blockchain::Blockchain::broadcast) should be used.
+    pub fn add_tx(&self, tx: Transaction) {
+        self.txs.write().unwrap().insert(tx.txid(), tx);
+    }
+
+    /// Look-up a transaction in the mempool given an [`Inventory`] request
+    pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction> {
+        let txid = match inventory {
+            Inventory::Error | Inventory::Block(_) | Inventory::WitnessBlock(_) => return None,
+            Inventory::Transaction(txid) => *txid,
+            Inventory::WitnessTransaction(wtxid) => Txid::from_inner(wtxid.into_inner()),
+        };
+        self.txs.read().unwrap().get(&txid).cloned()
+    }
+
+    /// Return whether or not the mempool contains a transaction with a given txid
+    pub fn has_tx(&self, txid: &Txid) -> bool {
+        self.txs.read().unwrap().contains_key(txid)
+    }
+
+    /// Return the list of transactions contained in the mempool
+    pub fn iter_txs(&self) -> Vec<Transaction> {
+        self.txs.read().unwrap().values().cloned().collect()
+    }
+}
+
+/// A Bitcoin peer
+#[derive(Debug)]
+pub struct Peer {
+    writer: Arc<Mutex<TcpStream>>,
+    responses: Arc<RwLock<ResponsesMap>>,
+
+    reader_thread: thread::JoinHandle<()>,
+    connected: Arc<RwLock<bool>>,
+
+    mempool: Arc<Mempool>,
+
+    version: VersionMessage,
+    network: Network,
+}
+
+impl Peer {
+    /// Connect to a peer over a plaintext TCP connection
+    ///
+    /// This function internally spawns a new thread that will monitor incoming messages from the
+    /// peer, and optionally reply to some of them transparently, like [pings](NetworkMessage::Ping)
+    pub fn connect<A: ToSocketAddrs>(
+        address: A,
+        mempool: Arc<Mempool>,
+        network: Network,
+    ) -> Result<Self, CompactFiltersError> {
+        let stream = TcpStream::connect(address)?;
+
+        Peer::from_stream(stream, mempool, network)
+    }
+
+    /// Connect to a peer through a SOCKS5 proxy, optionally by using some credentials, specified
+    /// as a tuple of `(username, password)`
+    ///
+    /// This function internally spawns a new thread that will monitor incoming messages from the
+    /// peer, and optionally reply to some of them transparently, like [pings](NetworkMessage::Ping)
+    pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
+        target: T,
+        proxy: P,
+        credentials: Option<(&str, &str)>,
+        mempool: Arc<Mempool>,
+        network: Network,
+    ) -> Result<Self, CompactFiltersError> {
+        let socks_stream = if let Some((username, password)) = credentials {
+            Socks5Stream::connect_with_password(proxy, target, username, password)?
+        } else {
+            Socks5Stream::connect(proxy, target)?
+        };
+
+        Peer::from_stream(socks_stream.into_inner(), mempool, network)
+    }
+
+    /// Create a [`Peer`] from an already connected TcpStream
+    fn from_stream(
+        stream: TcpStream,
+        mempool: Arc<Mempool>,
+        network: Network,
+    ) -> Result<Self, CompactFiltersError> {
+        let writer = Arc::new(Mutex::new(stream.try_clone()?));
+        let responses: Arc<RwLock<ResponsesMap>> = Arc::new(RwLock::new(HashMap::new()));
+        let connected = Arc::new(RwLock::new(true));
+
+        let mut locked_writer = writer.lock().unwrap();
+
+        let reader_thread_responses = Arc::clone(&responses);
+        let reader_thread_writer = Arc::clone(&writer);
+        let reader_thread_mempool = Arc::clone(&mempool);
+        let reader_thread_connected = Arc::clone(&connected);
+        let reader_thread = thread::spawn(move || {
+            Self::reader_thread(
+                network,
+                stream,
+                reader_thread_responses,
+                reader_thread_writer,
+                reader_thread_mempool,
+                reader_thread_connected,
+            )
+        });
+
+        let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i64;
+        let nonce = thread_rng().gen();
+        let receiver = Address::new(&locked_writer.peer_addr()?, ServiceFlags::NONE);
+        let sender = Address {
+            services: ServiceFlags::NONE,
+            address: [0u16; 8],
+            port: 0,
+        };
+
+        Self::_send(
+            &mut locked_writer,
+            network.magic(),
+            NetworkMessage::Version(VersionMessage::new(
+                ServiceFlags::WITNESS,
+                timestamp,
+                receiver,
+                sender,
+                nonce,
+                "MagicalBitcoinWallet".into(),
+                0,
+            )),
+        )?;
+        let version = if let NetworkMessage::Version(version) =
+            Self::_recv(&responses, "version", None)?.unwrap()
+        {
+            version
+        } else {
+            return Err(CompactFiltersError::InvalidResponse);
+        };
+
+        if let NetworkMessage::Verack = Self::_recv(&responses, "verack", None)?.unwrap() {
+            Self::_send(&mut locked_writer, network.magic(), NetworkMessage::Verack)?;
+        } else {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+
+        std::mem::drop(locked_writer);
+
+        Ok(Peer {
+            writer,
+            reader_thread,
+            responses,
+            connected,
+            mempool,
+            network,
+            version,
+        })
+    }
+
+    /// Send a Bitcoin network message
+    fn _send(
+        writer: &mut TcpStream,
+        magic: u32,
+        payload: NetworkMessage,
+    ) -> Result<(), CompactFiltersError> {
+        log::trace!("==> {:?}", payload);
+
+        let raw_message = RawNetworkMessage { magic, payload };
+
+        raw_message
+            .consensus_encode(writer)
+            .map_err(|_| CompactFiltersError::DataCorruption)?;
+
+        Ok(())
+    }
+
+    /// Wait for a specific incoming Bitcoin message, optionally with a timeout
+    fn _recv(
+        responses: &Arc<RwLock<ResponsesMap>>,
+        wait_for: &'static str,
+        timeout: Option<Duration>,
+    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
+        let message_resp = {
+            let mut lock = responses.write().unwrap();
+            let message_resp = lock.entry(wait_for).or_default();
+            Arc::clone(&message_resp)
+        };
+
+        let (lock, cvar) = &*message_resp;
+
+        let mut messages = lock.lock().unwrap();
+        while messages.is_empty() {
+            match timeout {
+                None => messages = cvar.wait(messages).unwrap(),
+                Some(t) => {
+                    let result = cvar.wait_timeout(messages, t).unwrap();
+                    if result.1.timed_out() {
+                        return Ok(None);
+                    }
+
+                    messages = result.0;
+                }
+            }
+        }
+
+        Ok(messages.pop())
+    }
+
+    /// Return the [`VersionMessage`] sent by the peer
+    pub fn get_version(&self) -> &VersionMessage {
+        &self.version
+    }
+
+    /// Return the Bitcoin [`Network`] in use
+    pub fn get_network(&self) -> Network {
+        self.network
+    }
+
+    /// Return the mempool used by this peer
+    pub fn get_mempool(&self) -> Arc<Mempool> {
+        Arc::clone(&self.mempool)
+    }
+
+    /// Return whether or not the peer is still connected
+    pub fn is_connected(&self) -> bool {
+        *self.connected.read().unwrap()
+    }
+
+    /// Internal function called once the `reader_thread` is spawned
+    fn reader_thread(
+        network: Network,
+        connection: TcpStream,
+        reader_thread_responses: Arc<RwLock<ResponsesMap>>,
+        reader_thread_writer: Arc<Mutex<TcpStream>>,
+        reader_thread_mempool: Arc<Mempool>,
+        reader_thread_connected: Arc<RwLock<bool>>,
+    ) {
+        macro_rules! check_disconnect {
+            ($call:expr) => {
+                match $call {
+                    Ok(good) => good,
+                    Err(e) => {
+                        log::debug!("Error {:?}", e);
+                        *reader_thread_connected.write().unwrap() = false;
+
+                        break;
+                    }
+                }
+            };
+        }
+
+        let mut reader = StreamReader::new(connection, None);
+        loop {
+            let raw_message: RawNetworkMessage = check_disconnect!(reader.read_next());
+
+            let in_message = if raw_message.magic != network.magic() {
+                continue;
+            } else {
+                raw_message.payload
+            };
+
+            log::trace!("<== {:?}", in_message);
+
+            match in_message {
+                NetworkMessage::Ping(nonce) => {
+                    check_disconnect!(Self::_send(
+                        &mut reader_thread_writer.lock().unwrap(),
+                        network.magic(),
+                        NetworkMessage::Pong(nonce),
+                    ));
+
+                    continue;
+                }
+                NetworkMessage::Alert(_) => continue,
+                NetworkMessage::GetData(ref inv) => {
+                    let (found, not_found): (Vec<_>, Vec<_>) = inv
+                        .into_iter()
+                        .map(|item| (*item, reader_thread_mempool.get_tx(item)))
+                        .partition(|(_, d)| d.is_some());
+                    for (_, found_tx) in found {
+                        check_disconnect!(Self::_send(
+                            &mut reader_thread_writer.lock().unwrap(),
+                            network.magic(),
+                            NetworkMessage::Tx(found_tx.unwrap()),
+                        ));
+                    }
+
+                    if !not_found.is_empty() {
+                        check_disconnect!(Self::_send(
+                            &mut reader_thread_writer.lock().unwrap(),
+                            network.magic(),
+                            NetworkMessage::NotFound(
+                                not_found.into_iter().map(|(i, _)| i).collect(),
+                            ),
+                        ));
+                    }
+                }
+                _ => {}
+            }
+
+            let message_resp = {
+                let mut lock = reader_thread_responses.write().unwrap();
+                let message_resp = lock.entry(in_message.cmd()).or_default();
+                Arc::clone(&message_resp)
+            };
+
+            let (lock, cvar) = &*message_resp;
+            let mut messages = lock.lock().unwrap();
+            messages.push(in_message);
+            cvar.notify_all();
+        }
+    }
+
+    /// Send a raw Bitcoin message to the peer
+    pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError> {
+        let mut writer = self.writer.lock().unwrap();
+        Self::_send(&mut writer, self.network.magic(), payload)
+    }
+
+    /// Waits for a specific incoming Bitcoin message, optionally with a timeout
+    pub fn recv(
+        &self,
+        wait_for: &'static str,
+        timeout: Option<Duration>,
+    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
+        Self::_recv(&self.responses, wait_for, timeout)
+    }
+}
+
+pub trait CompactFiltersPeer {
+    fn get_cf_checkpt(
+        &self,
+        filter_type: u8,
+        stop_hash: BlockHash,
+    ) -> Result<CFCheckpt, CompactFiltersError>;
+    fn get_cf_headers(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<CFHeaders, CompactFiltersError>;
+    fn get_cf_filters(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<(), CompactFiltersError>;
+    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError>;
+}
+
+impl CompactFiltersPeer for Peer {
+    fn get_cf_checkpt(
+        &self,
+        filter_type: u8,
+        stop_hash: BlockHash,
+    ) -> Result<CFCheckpt, CompactFiltersError> {
+        self.send(NetworkMessage::GetCFCheckpt(GetCFCheckpt {
+            filter_type,
+            stop_hash,
+        }))?;
+
+        let response = self
+            .recv("cfcheckpt", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?;
+        let response = match response {
+            NetworkMessage::CFCheckpt(response) => response,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        if response.filter_type != filter_type {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+
+        Ok(response)
+    }
+
+    fn get_cf_headers(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<CFHeaders, CompactFiltersError> {
+        self.send(NetworkMessage::GetCFHeaders(GetCFHeaders {
+            filter_type,
+            start_height,
+            stop_hash,
+        }))?;
+
+        let response = self
+            .recv("cfheaders", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?;
+        let response = match response {
+            NetworkMessage::CFHeaders(response) => response,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        if response.filter_type != filter_type {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+
+        Ok(response)
+    }
+
+    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError> {
+        let response = self
+            .recv("cfilter", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?;
+        let response = match response {
+            NetworkMessage::CFilter(response) => response,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        Ok(response)
+    }
+
+    fn get_cf_filters(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<(), CompactFiltersError> {
+        self.send(NetworkMessage::GetCFilters(GetCFilters {
+            filter_type,
+            start_height,
+            stop_hash,
+        }))?;
+
+        Ok(())
+    }
+}
+
+pub trait InvPeer {
+    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError>;
+    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError>;
+    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError>;
+}
+
+impl InvPeer for Peer {
+    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError> {
+        self.send(NetworkMessage::GetData(vec![Inventory::WitnessBlock(
+            block_hash,
+        )]))?;
+
+        match self.recv("block", Some(Duration::from_secs(TIMEOUT_SECS)))? {
+            None => Ok(None),
+            Some(NetworkMessage::Block(response)) => Ok(Some(response)),
+            _ => Err(CompactFiltersError::InvalidResponse),
+        }
+    }
+
+    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError> {
+        self.send(NetworkMessage::MemPool)?;
+        let inv = match self.recv("inv", Some(Duration::from_secs(5)))? {
+            None => return Ok(()), // empty mempool
+            Some(NetworkMessage::Inv(inv)) => inv,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        let getdata = inv
+            .iter()
+            .cloned()
+            .filter(|item| match item {
+                Inventory::Transaction(txid) if !self.mempool.has_tx(txid) => true,
+                _ => false,
+            })
+            .collect::<Vec<_>>();
+        let num_txs = getdata.len();
+        self.send(NetworkMessage::GetData(getdata))?;
+
+        for _ in 0..num_txs {
+            let tx = self
+                .recv("tx", Some(Duration::from_secs(TIMEOUT_SECS)))?
+                .ok_or(CompactFiltersError::Timeout)?;
+            let tx = match tx {
+                NetworkMessage::Tx(tx) => tx,
+                _ => return Err(CompactFiltersError::InvalidResponse),
+            };
+
+            self.mempool.add_tx(tx);
+        }
+
+        Ok(())
+    }
+
+    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError> {
+        self.mempool.add_tx(tx.clone());
+        self.send(NetworkMessage::Tx(tx))?;
+
+        Ok(())
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/store.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/store.rs.html new file mode 100644 index 0000000000..64172790be --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/store.rs.html @@ -0,0 +1,1811 @@ +store.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::convert::TryInto;
+use std::fmt;
+use std::io::{Read, Write};
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::sync::Arc;
+use std::sync::RwLock;
+
+use rand::distributions::Alphanumeric;
+use rand::{thread_rng, Rng};
+
+use rocksdb::{Direction, IteratorMode, ReadOptions, WriteBatch, DB};
+
+use bitcoin::consensus::{deserialize, encode::VarInt, serialize, Decodable, Encodable};
+use bitcoin::hash_types::FilterHash;
+use bitcoin::hashes::hex::FromHex;
+use bitcoin::hashes::{sha256d, Hash};
+use bitcoin::util::bip158::BlockFilter;
+use bitcoin::util::uint::Uint256;
+use bitcoin::Block;
+use bitcoin::BlockHash;
+use bitcoin::BlockHeader;
+use bitcoin::Network;
+
+use super::CompactFiltersError;
+
+lazy_static! {
+    static ref MAINNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A29AB5F49FFFF001D1DAC2B7C0101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
+    static ref TESTNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF001D1AA4AE180101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
+    static ref REGTEST_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF7F20020000000101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
+}
+
+pub trait StoreType: Default + fmt::Debug {}
+
+#[derive(Default, Debug)]
+pub struct Full;
+impl StoreType for Full {}
+#[derive(Default, Debug)]
+pub struct Snapshot;
+impl StoreType for Snapshot {}
+
+pub enum StoreEntry {
+    BlockHeader(Option<usize>),
+    Block(Option<usize>),
+    BlockHeaderIndex(Option<BlockHash>),
+    CFilterTable((u8, Option<usize>)),
+}
+
+impl StoreEntry {
+    pub fn get_prefix(&self) -> Vec<u8> {
+        match self {
+            StoreEntry::BlockHeader(_) => b"z",
+            StoreEntry::Block(_) => b"x",
+            StoreEntry::BlockHeaderIndex(_) => b"i",
+            StoreEntry::CFilterTable(_) => b"t",
+        }
+        .to_vec()
+    }
+
+    pub fn get_key(&self) -> Vec<u8> {
+        let mut prefix = self.get_prefix();
+        match self {
+            StoreEntry::BlockHeader(Some(height)) => {
+                prefix.extend_from_slice(&height.to_be_bytes())
+            }
+            StoreEntry::Block(Some(height)) => prefix.extend_from_slice(&height.to_be_bytes()),
+            StoreEntry::BlockHeaderIndex(Some(hash)) => {
+                prefix.extend_from_slice(&hash.into_inner())
+            }
+            StoreEntry::CFilterTable((filter_type, bundle_index)) => {
+                prefix.push(*filter_type);
+                if let Some(bundle_index) = bundle_index {
+                    prefix.extend_from_slice(&bundle_index.to_be_bytes());
+                }
+            }
+            _ => {}
+        }
+
+        prefix
+    }
+}
+
+pub trait SerializeDb: Sized {
+    fn serialize(&self) -> Vec<u8>;
+    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError>;
+}
+
+impl<T> SerializeDb for T
+where
+    T: Encodable + Decodable,
+{
+    fn serialize(&self) -> Vec<u8> {
+        serialize(self)
+    }
+
+    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError> {
+        Ok(deserialize(data).map_err(|_| CompactFiltersError::DataCorruption)?)
+    }
+}
+
+impl Encodable for FilterHeader {
+    fn consensus_encode<W: Write>(
+        &self,
+        mut e: W,
+    ) -> Result<usize, bitcoin::consensus::encode::Error> {
+        let mut written = self.prev_header_hash.consensus_encode(&mut e)?;
+        written += self.filter_hash.consensus_encode(&mut e)?;
+        Ok(written)
+    }
+}
+
+impl Decodable for FilterHeader {
+    fn consensus_decode<D: Read>(mut d: D) -> Result<Self, bitcoin::consensus::encode::Error> {
+        let prev_header_hash = FilterHeaderHash::consensus_decode(&mut d)?;
+        let filter_hash = FilterHash::consensus_decode(&mut d)?;
+
+        Ok(FilterHeader {
+            prev_header_hash,
+            filter_hash,
+        })
+    }
+}
+
+impl Encodable for BundleStatus {
+    fn consensus_encode<W: Write>(
+        &self,
+        mut e: W,
+    ) -> Result<usize, bitcoin::consensus::encode::Error> {
+        let mut written = 0;
+
+        match self {
+            BundleStatus::Init => {
+                written += 0x00u8.consensus_encode(&mut e)?;
+            }
+            BundleStatus::CFHeaders { cf_headers } => {
+                written += 0x01u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_headers.len() as u64).consensus_encode(&mut e)?;
+                for header in cf_headers {
+                    written += header.consensus_encode(&mut e)?;
+                }
+            }
+            BundleStatus::CFilters { cf_filters } => {
+                written += 0x02u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
+                for filter in cf_filters {
+                    written += filter.consensus_encode(&mut e)?;
+                }
+            }
+            BundleStatus::Processed { cf_filters } => {
+                written += 0x03u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
+                for filter in cf_filters {
+                    written += filter.consensus_encode(&mut e)?;
+                }
+            }
+            BundleStatus::Pruned => {
+                written += 0x04u8.consensus_encode(&mut e)?;
+            }
+            BundleStatus::Tip { cf_filters } => {
+                written += 0x05u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
+                for filter in cf_filters {
+                    written += filter.consensus_encode(&mut e)?;
+                }
+            }
+        }
+
+        Ok(written)
+    }
+}
+
+impl Decodable for BundleStatus {
+    fn consensus_decode<D: Read>(mut d: D) -> Result<Self, bitcoin::consensus::encode::Error> {
+        let byte_type = u8::consensus_decode(&mut d)?;
+        match byte_type {
+            0x00 => Ok(BundleStatus::Init),
+            0x01 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_headers = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_headers.push(FilterHeader::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::CFHeaders { cf_headers })
+            }
+            0x02 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_filters = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::CFilters { cf_filters })
+            }
+            0x03 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_filters = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::Processed { cf_filters })
+            }
+            0x04 => Ok(BundleStatus::Pruned),
+            0x05 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_filters = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::Tip { cf_filters })
+            }
+            _ => Err(bitcoin::consensus::encode::Error::ParseFailed(
+                "Invalid byte type",
+            )),
+        }
+    }
+}
+
+pub struct ChainStore<T: StoreType> {
+    store: Arc<RwLock<DB>>,
+    cf_name: String,
+    min_height: usize,
+    network: Network,
+    phantom: PhantomData<T>,
+}
+
+impl ChainStore<Full> {
+    pub fn new(store: DB, network: Network) -> Result<Self, CompactFiltersError> {
+        let genesis = match network {
+            Network::Bitcoin => MAINNET_GENESIS.deref(),
+            Network::Testnet => TESTNET_GENESIS.deref(),
+            Network::Regtest => REGTEST_GENESIS.deref(),
+        };
+
+        let cf_name = "default".to_string();
+        let cf_handle = store.cf_handle(&cf_name).unwrap();
+
+        let genesis_key = StoreEntry::BlockHeader(Some(0)).get_key();
+
+        if store.get_pinned_cf(cf_handle, &genesis_key)?.is_none() {
+            let mut batch = WriteBatch::default();
+            batch.put_cf(
+                cf_handle,
+                genesis_key,
+                (genesis.header, genesis.header.work()).serialize(),
+            );
+            batch.put_cf(
+                cf_handle,
+                StoreEntry::BlockHeaderIndex(Some(genesis.block_hash())).get_key(),
+                &0usize.to_be_bytes(),
+            );
+            store.write(batch)?;
+        }
+
+        Ok(ChainStore {
+            store: Arc::new(RwLock::new(store)),
+            cf_name,
+            min_height: 0,
+            network,
+            phantom: PhantomData,
+        })
+    }
+
+    pub fn get_locators(&self) -> Result<Vec<(BlockHash, usize)>, CompactFiltersError> {
+        let mut step = 1;
+        let mut index = self.get_height()?;
+        let mut answer = Vec::new();
+
+        let store_read = self.store.read().unwrap();
+        let cf_handle = store_read.cf_handle(&self.cf_name).unwrap();
+
+        loop {
+            if answer.len() > 10 {
+                step *= 2;
+            }
+
+            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(
+                &store_read
+                    .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(index)).get_key())?
+                    .unwrap(),
+            )?;
+            answer.push((header.block_hash(), index));
+
+            if let Some(new_index) = index.checked_sub(step) {
+                index = new_index;
+            } else {
+                break;
+            }
+        }
+
+        Ok(answer)
+    }
+
+    pub fn start_snapshot(&self, from: usize) -> Result<ChainStore<Snapshot>, CompactFiltersError> {
+        let new_cf_name: String = thread_rng().sample_iter(&Alphanumeric).take(16).collect();
+        let new_cf_name = format!("_headers:{}", new_cf_name);
+
+        let mut write_store = self.store.write().unwrap();
+
+        write_store.create_cf(&new_cf_name, &Default::default())?;
+
+        let cf_handle = write_store.cf_handle(&self.cf_name).unwrap();
+        let new_cf_handle = write_store.cf_handle(&new_cf_name).unwrap();
+
+        let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(
+            &write_store
+                .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
+                .ok_or(CompactFiltersError::DataCorruption)?,
+        )?;
+
+        let mut batch = WriteBatch::default();
+        batch.put_cf(
+            new_cf_handle,
+            StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
+            &from.to_be_bytes(),
+        );
+        batch.put_cf(
+            new_cf_handle,
+            StoreEntry::BlockHeader(Some(from)).get_key(),
+            (header, work).serialize(),
+        );
+        write_store.write(batch)?;
+
+        let store = Arc::clone(&self.store);
+        Ok(ChainStore {
+            store,
+            cf_name: new_cf_name,
+            min_height: from,
+            network: self.network,
+            phantom: PhantomData,
+        })
+    }
+
+    pub fn recover_snapshot(&self, cf_name: &str) -> Result<(), CompactFiltersError> {
+        let mut write_store = self.store.write().unwrap();
+        let snapshot_cf_handle = write_store.cf_handle(cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let mut iterator = write_store.prefix_iterator_cf(snapshot_cf_handle, prefix);
+
+        let min_height = match iterator
+            .next()
+            .and_then(|(k, _)| k[1..].try_into().ok())
+            .map(|bytes| usize::from_be_bytes(bytes))
+        {
+            None => {
+                std::mem::drop(iterator);
+                write_store.drop_cf(cf_name).ok();
+
+                return Ok(());
+            }
+            Some(x) => x,
+        };
+        std::mem::drop(iterator);
+        std::mem::drop(write_store);
+
+        let snapshot = ChainStore {
+            store: Arc::clone(&self.store),
+            cf_name: cf_name.into(),
+            min_height,
+            network: self.network,
+            phantom: PhantomData,
+        };
+        if snapshot.work()? > self.work()? {
+            self.apply_snapshot(snapshot)?;
+        }
+
+        Ok(())
+    }
+
+    pub fn apply_snapshot(
+        &self,
+        snaphost: ChainStore<Snapshot>,
+    ) -> Result<(), CompactFiltersError> {
+        let mut batch = WriteBatch::default();
+
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+        let snapshot_cf_handle = read_store.cf_handle(&snaphost.cf_name).unwrap();
+
+        let from_key = StoreEntry::BlockHeader(Some(snaphost.min_height)).get_key();
+        let to_key = StoreEntry::BlockHeader(Some(usize::MAX)).get_key();
+
+        let mut opts = ReadOptions::default();
+        opts.set_iterate_upper_bound(to_key.clone());
+
+        log::debug!("Removing items");
+        batch.delete_range_cf(cf_handle, &from_key, &to_key);
+        for (_, v) in read_store.iterator_cf_opt(
+            cf_handle,
+            opts,
+            IteratorMode::From(&from_key, Direction::Forward),
+        ) {
+            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
+
+            batch.delete_cf(
+                cf_handle,
+                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
+            );
+        }
+
+        // Delete full blocks overriden by snapshot
+        let from_key = StoreEntry::Block(Some(snaphost.min_height)).get_key();
+        let to_key = StoreEntry::Block(Some(usize::MAX)).get_key();
+        batch.delete_range(&from_key, &to_key);
+
+        log::debug!("Copying over new items");
+        for (k, v) in read_store.iterator_cf(snapshot_cf_handle, IteratorMode::Start) {
+            batch.put_cf(cf_handle, k, v);
+        }
+
+        read_store.write(batch)?;
+
+        std::mem::drop(snapshot_cf_handle);
+        std::mem::drop(cf_handle);
+        std::mem::drop(read_store);
+
+        self.store.write().unwrap().drop_cf(&snaphost.cf_name)?;
+
+        Ok(())
+    }
+
+    pub fn get_height_for(
+        &self,
+        block_hash: &BlockHash,
+    ) -> Result<Option<usize>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let key = StoreEntry::BlockHeaderIndex(Some(block_hash.clone())).get_key();
+        let data = read_store.get_pinned_cf(cf_handle, key)?;
+        Ok(data
+            .map(|data| {
+                Ok::<_, CompactFiltersError>(usize::from_be_bytes(
+                    data.as_ref()
+                        .try_into()
+                        .map_err(|_| CompactFiltersError::DataCorruption)?,
+                ))
+            })
+            .transpose()?)
+    }
+
+    pub fn get_block_hash(&self, height: usize) -> Result<Option<BlockHash>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let key = StoreEntry::BlockHeader(Some(height)).get_key();
+        let data = read_store.get_pinned_cf(cf_handle, key)?;
+        Ok(data
+            .map(|data| {
+                let (header, _): (BlockHeader, Uint256) =
+                    deserialize(&data).map_err(|_| CompactFiltersError::DataCorruption)?;
+                Ok::<_, CompactFiltersError>(header.block_hash())
+            })
+            .transpose()?)
+    }
+
+    pub fn save_full_block(&self, block: &Block, height: usize) -> Result<(), CompactFiltersError> {
+        let key = StoreEntry::Block(Some(height)).get_key();
+        self.store.read().unwrap().put(key, block.serialize())?;
+
+        Ok(())
+    }
+
+    pub fn get_full_block(&self, height: usize) -> Result<Option<Block>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let key = StoreEntry::Block(Some(height)).get_key();
+        let opt_block = read_store.get_pinned(key)?;
+
+        Ok(opt_block
+            .map(|data| deserialize(&data))
+            .transpose()
+            .map_err(|_| CompactFiltersError::DataCorruption)?)
+    }
+
+    pub fn delete_blocks_until(&self, height: usize) -> Result<(), CompactFiltersError> {
+        let from_key = StoreEntry::Block(Some(0)).get_key();
+        let to_key = StoreEntry::Block(Some(height)).get_key();
+
+        let mut batch = WriteBatch::default();
+        batch.delete_range(&from_key, &to_key);
+
+        self.store.read().unwrap().write(batch)?;
+
+        Ok(())
+    }
+
+    pub fn iter_full_blocks(&self) -> Result<Vec<(usize, Block)>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let prefix = StoreEntry::Block(None).get_key();
+
+        let iterator = read_store.prefix_iterator(&prefix);
+        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
+        // have the right prefix
+        iterator
+            .filter(|(k, _)| k.starts_with(&prefix))
+            .map(|(k, v)| {
+                let height: usize = usize::from_be_bytes(
+                    k[1..]
+                        .try_into()
+                        .map_err(|_| CompactFiltersError::DataCorruption)?,
+                );
+                let block = SerializeDb::deserialize(&v)?;
+
+                Ok((height, block))
+            })
+            .collect::<Result<_, _>>()
+    }
+}
+
+impl<T: StoreType> ChainStore<T> {
+    pub fn work(&self) -> Result<Uint256, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
+
+        Ok(iterator
+            .last()
+            .map(|(_, v)| -> Result<_, CompactFiltersError> {
+                let (_, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
+
+                Ok(work)
+            })
+            .transpose()?
+            .unwrap_or_default())
+    }
+
+    pub fn get_height(&self) -> Result<usize, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
+
+        Ok(iterator
+            .last()
+            .map(|(k, _)| -> Result<_, CompactFiltersError> {
+                let height = usize::from_be_bytes(
+                    k[1..]
+                        .try_into()
+                        .map_err(|_| CompactFiltersError::DataCorruption)?,
+                );
+
+                Ok(height)
+            })
+            .transpose()?
+            .unwrap_or_default())
+    }
+
+    pub fn get_tip_hash(&self) -> Result<Option<BlockHash>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
+
+        Ok(iterator
+            .last()
+            .map(|(_, v)| -> Result<_, CompactFiltersError> {
+                let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
+
+                Ok(header.block_hash())
+            })
+            .transpose()?)
+    }
+
+    pub fn apply(
+        &mut self,
+        from: usize,
+        headers: Vec<BlockHeader>,
+    ) -> Result<BlockHash, CompactFiltersError> {
+        let mut batch = WriteBatch::default();
+
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let (mut last_hash, mut accumulated_work) = read_store
+            .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
+            .map(|result| {
+                let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&result)?;
+                Ok::<_, CompactFiltersError>((header.block_hash(), work))
+            })
+            .transpose()?
+            .ok_or(CompactFiltersError::DataCorruption)?;
+
+        for (index, header) in headers.into_iter().enumerate() {
+            if header.prev_blockhash != last_hash {
+                return Err(CompactFiltersError::InvalidHeaders);
+            }
+
+            last_hash = header.block_hash();
+            accumulated_work = accumulated_work + header.work();
+
+            let height = from + index + 1;
+            batch.put_cf(
+                cf_handle,
+                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
+                &(height).to_be_bytes(),
+            );
+            batch.put_cf(
+                cf_handle,
+                StoreEntry::BlockHeader(Some(height)).get_key(),
+                (header, accumulated_work).serialize(),
+            );
+        }
+
+        std::mem::drop(cf_handle);
+        std::mem::drop(read_store);
+
+        self.store.write().unwrap().write(batch)?;
+        Ok(last_hash)
+    }
+}
+
+impl<T: StoreType> fmt::Debug for ChainStore<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct(&format!("ChainStore<{:?}>", T::default()))
+            .field("cf_name", &self.cf_name)
+            .field("min_height", &self.min_height)
+            .field("network", &self.network)
+            .field("headers_height", &self.get_height())
+            .field("tip_hash", &self.get_tip_hash())
+            .finish()
+    }
+}
+
+pub type FilterHeaderHash = FilterHash;
+
+#[derive(Debug, Clone)]
+pub struct FilterHeader {
+    prev_header_hash: FilterHeaderHash,
+    filter_hash: FilterHash,
+}
+
+impl FilterHeader {
+    fn header_hash(&self) -> FilterHeaderHash {
+        let mut hash_data = self.filter_hash.into_inner().to_vec();
+        hash_data.extend_from_slice(&self.prev_header_hash);
+        sha256d::Hash::hash(&hash_data).into()
+    }
+}
+
+pub enum BundleStatus {
+    Init,
+    CFHeaders { cf_headers: Vec<FilterHeader> },
+    CFilters { cf_filters: Vec<Vec<u8>> },
+    Processed { cf_filters: Vec<Vec<u8>> },
+    Tip { cf_filters: Vec<Vec<u8>> },
+    Pruned,
+}
+
+pub struct CFStore {
+    store: Arc<RwLock<DB>>,
+    filter_type: u8,
+}
+
+type BundleEntry = (BundleStatus, FilterHeaderHash);
+
+impl CFStore {
+    pub fn new(
+        headers_store: &ChainStore<Full>,
+        filter_type: u8,
+    ) -> Result<Self, CompactFiltersError> {
+        let cf_store = CFStore {
+            store: Arc::clone(&headers_store.store),
+            filter_type,
+        };
+
+        let genesis = match headers_store.network {
+            Network::Bitcoin => MAINNET_GENESIS.deref(),
+            Network::Testnet => TESTNET_GENESIS.deref(),
+            Network::Regtest => REGTEST_GENESIS.deref(),
+        };
+
+        let filter = BlockFilter::new_script_filter(genesis, |utxo| {
+            Err(bitcoin::util::bip158::Error::UtxoMissing(*utxo))
+        })?;
+        let first_key = StoreEntry::CFilterTable((filter_type, Some(0))).get_key();
+
+        // Add the genesis' filter
+        {
+            let read_store = cf_store.store.read().unwrap();
+            if read_store.get_pinned(&first_key)?.is_none() {
+                read_store.put(
+                    &first_key,
+                    (BundleStatus::Init, filter.filter_id(&FilterHash::default())).serialize(),
+                )?;
+            }
+        }
+
+        Ok(cf_store)
+    }
+
+    pub fn get_filter_type(&self) -> u8 {
+        self.filter_type
+    }
+
+    pub fn get_bundles(&self) -> Result<Vec<BundleEntry>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
+        let iterator = read_store.prefix_iterator(&prefix);
+
+        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
+        // have the right prefix
+        iterator
+            .filter(|(k, _)| k.starts_with(&prefix))
+            .map(|(_, data)| BundleEntry::deserialize(&data))
+            .collect::<Result<_, _>>()
+    }
+
+    pub fn get_checkpoints(&self) -> Result<Vec<FilterHash>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
+        let iterator = read_store.prefix_iterator(&prefix);
+
+        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
+        // have the right prefix
+        Ok(iterator
+            .filter(|(k, _)| k.starts_with(&prefix))
+            .skip(1)
+            .map(|(_, data)| Ok::<_, CompactFiltersError>(BundleEntry::deserialize(&data)?.1))
+            .collect::<Result<_, _>>()?)
+    }
+
+    pub fn replace_checkpoints(
+        &self,
+        checkpoints: Vec<FilterHash>,
+    ) -> Result<(), CompactFiltersError> {
+        let current_checkpoints = self.get_checkpoints()?;
+
+        let mut equal_bundles = 0;
+        for (index, (our, their)) in current_checkpoints
+            .iter()
+            .zip(checkpoints.iter())
+            .enumerate()
+        {
+            equal_bundles = index;
+
+            if our != their {
+                break;
+            }
+        }
+
+        let read_store = self.store.read().unwrap();
+        let mut batch = WriteBatch::default();
+
+        for (index, filter_hash) in checkpoints.iter().enumerate().skip(equal_bundles) {
+            let key = StoreEntry::CFilterTable((self.filter_type, Some(index + 1))).get_key(); // +1 to skip the genesis' filter
+
+            if let Some((BundleStatus::Tip { .. }, _)) = read_store
+                .get_pinned(&key)?
+                .map(|data| BundleEntry::deserialize(&data))
+                .transpose()?
+            {
+                println!("Keeping bundle #{} as Tip", index);
+            } else {
+                batch.put(&key, (BundleStatus::Init, *filter_hash).serialize());
+            }
+        }
+
+        read_store.write(batch)?;
+
+        Ok(())
+    }
+
+    pub fn advance_to_cf_headers(
+        &self,
+        bundle: usize,
+        checkpoint_hash: FilterHeaderHash,
+        filter_headers: Vec<FilterHash>,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let mut last_hash = checkpoint_hash;
+        let cf_headers = filter_headers
+            .into_iter()
+            .map(|filter_hash| {
+                let filter_header = FilterHeader {
+                    prev_header_hash: last_hash,
+                    filter_hash,
+                };
+                last_hash = filter_header.header_hash();
+
+                filter_header
+            })
+            .collect();
+
+        let read_store = self.store.read().unwrap();
+
+        let next_key = StoreEntry::CFilterTable((self.filter_type, Some(bundle + 1))).get_key(); // +1 to skip the genesis' filter
+        if let Some((_, next_checkpoint)) = read_store
+            .get_pinned(&next_key)?
+            .map(|data| BundleEntry::deserialize(&data))
+            .transpose()?
+        {
+            // check connection with the next bundle if present
+            if last_hash != next_checkpoint {
+                return Err(CompactFiltersError::InvalidFilterHeader);
+            }
+        }
+
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::CFHeaders { cf_headers }, checkpoint_hash);
+
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+
+    pub fn advance_to_cf_filters(
+        &self,
+        bundle: usize,
+        checkpoint_hash: FilterHeaderHash,
+        headers: Vec<FilterHeader>,
+        filters: Vec<(usize, Vec<u8>)>,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let cf_filters = filters
+            .into_iter()
+            .zip(headers.iter())
+            .map(|((_, filter_content), header)| {
+                if header.filter_hash != sha256d::Hash::hash(&filter_content).into() {
+                    return Err(CompactFiltersError::InvalidFilter);
+                }
+
+                Ok::<_, CompactFiltersError>(filter_content)
+            })
+            .collect::<Result<_, _>>()?;
+
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::CFilters { cf_filters }, checkpoint_hash);
+
+        let read_store = self.store.read().unwrap();
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+
+    pub fn prune_filters(
+        &self,
+        bundle: usize,
+        checkpoint_hash: FilterHeaderHash,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::Pruned, checkpoint_hash);
+
+        let read_store = self.store.read().unwrap();
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+
+    pub fn mark_as_tip(
+        &self,
+        bundle: usize,
+        cf_filters: Vec<Vec<u8>>,
+        checkpoint_hash: FilterHeaderHash,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::Tip { cf_filters }, checkpoint_hash);
+
+        let read_store = self.store.read().unwrap();
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/sync.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/sync.rs.html new file mode 100644 index 0000000000..29d89bdd81 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/sync.rs.html @@ -0,0 +1,629 @@ +sync.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::collections::{BTreeMap, HashMap, VecDeque};
+use std::sync::{Arc, Mutex};
+use std::time::Duration;
+
+use bitcoin::hash_types::{BlockHash, FilterHash};
+use bitcoin::network::message::NetworkMessage;
+use bitcoin::network::message_blockdata::GetHeadersMessage;
+use bitcoin::util::bip158::BlockFilter;
+
+use super::peer::*;
+use super::store::*;
+use super::CompactFiltersError;
+use crate::error::Error;
+
+pub(crate) const BURIED_CONFIRMATIONS: usize = 100;
+
+pub struct CFSync {
+    headers_store: Arc<ChainStore<Full>>,
+    cf_store: Arc<CFStore>,
+    skip_blocks: usize,
+    bundles: Mutex<VecDeque<(BundleStatus, FilterHash, usize)>>,
+}
+
+impl CFSync {
+    pub fn new(
+        headers_store: Arc<ChainStore<Full>>,
+        skip_blocks: usize,
+        filter_type: u8,
+    ) -> Result<Self, CompactFiltersError> {
+        let cf_store = Arc::new(CFStore::new(&headers_store, filter_type)?);
+
+        Ok(CFSync {
+            headers_store,
+            cf_store,
+            skip_blocks,
+            bundles: Mutex::new(VecDeque::new()),
+        })
+    }
+
+    pub fn pruned_bundles(&self) -> Result<usize, CompactFiltersError> {
+        Ok(self
+            .cf_store
+            .get_bundles()?
+            .into_iter()
+            .skip(self.skip_blocks / 1000)
+            .fold(0, |acc, (status, _)| match status {
+                BundleStatus::Pruned => acc + 1,
+                _ => acc,
+            }))
+    }
+
+    pub fn prepare_sync(&self, peer: Arc<Peer>) -> Result<(), CompactFiltersError> {
+        let mut bundles_lock = self.bundles.lock().unwrap();
+
+        let resp = peer.get_cf_checkpt(
+            self.cf_store.get_filter_type(),
+            self.headers_store.get_tip_hash()?.unwrap(),
+        )?;
+        self.cf_store.replace_checkpoints(resp.filter_headers)?;
+
+        bundles_lock.clear();
+        for (index, (status, checkpoint)) in self.cf_store.get_bundles()?.into_iter().enumerate() {
+            bundles_lock.push_back((status, checkpoint, index));
+        }
+
+        Ok(())
+    }
+
+    pub fn capture_thread_for_sync<F, Q>(
+        &self,
+        peer: Arc<Peer>,
+        process: F,
+        completed_bundle: Q,
+    ) -> Result<(), CompactFiltersError>
+    where
+        F: Fn(&BlockHash, &BlockFilter) -> Result<bool, CompactFiltersError>,
+        Q: Fn(usize) -> Result<(), Error>,
+    {
+        let current_height = self.headers_store.get_height()?; // TODO: we should update it in case headers_store is also updated
+
+        loop {
+            let (mut status, checkpoint, index) = match self.bundles.lock().unwrap().pop_front() {
+                None => break,
+                Some(x) => x,
+            };
+
+            log::debug!(
+                "Processing bundle #{} - height {} to {}",
+                index,
+                index * 1000 + 1,
+                (index + 1) * 1000
+            );
+
+            let process_received_filters =
+                |expected_filters| -> Result<BTreeMap<usize, Vec<u8>>, CompactFiltersError> {
+                    let mut filters_map = BTreeMap::new();
+                    for _ in 0..expected_filters {
+                        let filter = peer.pop_cf_filter_resp()?;
+                        if filter.filter_type != self.cf_store.get_filter_type() {
+                            return Err(CompactFiltersError::InvalidResponse);
+                        }
+
+                        match self.headers_store.get_height_for(&filter.block_hash)? {
+                            Some(height) => filters_map.insert(height, filter.filter),
+                            None => return Err(CompactFiltersError::InvalidFilter),
+                        };
+                    }
+
+                    Ok(filters_map)
+                };
+
+            let start_height = index * 1000 + 1;
+            let mut already_processed = 0;
+
+            if start_height < self.skip_blocks {
+                status = self.cf_store.prune_filters(index, checkpoint)?;
+            }
+
+            let stop_height = std::cmp::min(current_height, start_height + 999);
+            let stop_hash = self.headers_store.get_block_hash(stop_height)?.unwrap();
+
+            if let BundleStatus::Init = status {
+                log::trace!("status: Init");
+
+                let resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
+
+                assert!(resp.previous_filter == checkpoint);
+                status =
+                    self.cf_store
+                        .advance_to_cf_headers(index, checkpoint, resp.filter_hashes)?;
+            }
+            if let BundleStatus::Tip { cf_filters } = status {
+                log::trace!("status: Tip (beginning) ");
+
+                already_processed = cf_filters.len();
+                let headers_resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
+
+                let cf_headers = match self.cf_store.advance_to_cf_headers(
+                    index,
+                    checkpoint,
+                    headers_resp.filter_hashes,
+                )? {
+                    BundleStatus::CFHeaders { cf_headers } => cf_headers,
+                    _ => return Err(CompactFiltersError::InvalidResponse),
+                };
+
+                peer.get_cf_filters(
+                    self.cf_store.get_filter_type(),
+                    (start_height + cf_filters.len()) as u32,
+                    stop_hash,
+                )?;
+                let expected_filters = stop_height - start_height + 1 - cf_filters.len();
+                let filters_map = process_received_filters(expected_filters)?;
+                let filters = cf_filters
+                    .into_iter()
+                    .enumerate()
+                    .chain(filters_map.into_iter())
+                    .collect();
+                status = self
+                    .cf_store
+                    .advance_to_cf_filters(index, checkpoint, cf_headers, filters)?;
+            }
+            if let BundleStatus::CFHeaders { cf_headers } = status {
+                log::trace!("status: CFHeaders");
+
+                peer.get_cf_filters(
+                    self.cf_store.get_filter_type(),
+                    start_height as u32,
+                    stop_hash,
+                )?;
+                let expected_filters = stop_height - start_height + 1;
+                let filters_map = process_received_filters(expected_filters)?;
+                status = self.cf_store.advance_to_cf_filters(
+                    index,
+                    checkpoint,
+                    cf_headers,
+                    filters_map.into_iter().collect(),
+                )?;
+            }
+            if let BundleStatus::CFilters { cf_filters } = status {
+                log::trace!("status: CFilters");
+
+                let last_sync_buried_height = (start_height + already_processed)
+                    .checked_sub(BURIED_CONFIRMATIONS)
+                    .unwrap_or(0);
+
+                for (filter_index, filter) in cf_filters.iter().enumerate() {
+                    let height = filter_index + start_height;
+
+                    // do not download blocks that were already "buried" since the last sync
+                    if height < last_sync_buried_height {
+                        continue;
+                    }
+
+                    let block_hash = self.headers_store.get_block_hash(height)?.unwrap();
+
+                    // TODO: also download random blocks?
+                    if process(&block_hash, &BlockFilter::new(&filter))? {
+                        log::debug!("Downloading block {}", block_hash);
+
+                        let block = peer
+                            .get_block(block_hash)?
+                            .ok_or(CompactFiltersError::MissingBlock)?;
+                        self.headers_store.save_full_block(&block, height)?;
+                    }
+                }
+
+                status = BundleStatus::Processed { cf_filters };
+            }
+            if let BundleStatus::Processed { cf_filters } = status {
+                log::trace!("status: Processed");
+
+                if current_height - stop_height > 1000 {
+                    status = self.cf_store.prune_filters(index, checkpoint)?;
+                } else {
+                    status = self.cf_store.mark_as_tip(index, cf_filters, checkpoint)?;
+                }
+
+                completed_bundle(index)?;
+            }
+            if let BundleStatus::Pruned = status {
+                log::trace!("status: Pruned");
+            }
+            if let BundleStatus::Tip { .. } = status {
+                log::trace!("status: Tip");
+            }
+        }
+
+        Ok(())
+    }
+}
+
+pub fn sync_headers<F>(
+    peer: Arc<Peer>,
+    store: Arc<ChainStore<Full>>,
+    sync_fn: F,
+) -> Result<Option<ChainStore<Snapshot>>, CompactFiltersError>
+where
+    F: Fn(usize) -> Result<(), Error>,
+{
+    let locators = store.get_locators()?;
+    let locators_vec = locators.iter().map(|(hash, _)| hash).cloned().collect();
+    let locators_map: HashMap<_, _> = locators.into_iter().collect();
+
+    peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
+        locators_vec,
+        Default::default(),
+    )))?;
+    let (mut snapshot, mut last_hash) = if let NetworkMessage::Headers(headers) = peer
+        .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
+        .ok_or(CompactFiltersError::Timeout)?
+    {
+        if headers.is_empty() {
+            return Ok(None);
+        }
+
+        match locators_map.get(&headers[0].prev_blockhash) {
+            None => return Err(CompactFiltersError::InvalidHeaders),
+            Some(from) => (
+                store.start_snapshot(*from)?,
+                headers[0].prev_blockhash.clone(),
+            ),
+        }
+    } else {
+        return Err(CompactFiltersError::InvalidResponse);
+    };
+
+    let mut sync_height = store.get_height()?;
+    while sync_height < peer.get_version().start_height as usize {
+        peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
+            vec![last_hash],
+            Default::default(),
+        )))?;
+        if let NetworkMessage::Headers(headers) = peer
+            .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?
+        {
+            let batch_len = headers.len();
+            last_hash = snapshot.apply(sync_height, headers)?;
+
+            sync_height += batch_len;
+            sync_fn(sync_height)?;
+        } else {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+    }
+
+    Ok(Some(snapshot))
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/electrum.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/electrum.rs.html new file mode 100644 index 0000000000..c12b391f32 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/electrum.rs.html @@ -0,0 +1,353 @@ +electrum.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Electrum
+//!
+//! This module defines a [`Blockchain`] struct that wraps an [`electrum_client::Client`]
+//! and implements the logic required to populate the wallet's [database](crate::database::Database) by
+//! querying the inner client.
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use bdk::blockchain::electrum::ElectrumBlockchain;
+//! let client = electrum_client::Client::new("ssl://electrum.blockstream.info:50002", None)?;
+//! let blockchain = ElectrumBlockchain::from(client);
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::collections::HashSet;
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use bitcoin::{Script, Transaction, Txid};
+
+use electrum_client::{Client, ElectrumApi};
+
+use self::utils::{ELSGetHistoryRes, ELSListUnspentRes, ElectrumLikeSync};
+use super::*;
+use crate::database::BatchDatabase;
+use crate::error::Error;
+use crate::FeeRate;
+
+/// Wrapper over an Electrum Client that implements the required blockchain traits
+///
+/// ## Example
+/// See the [`blockchain::electrum`](crate::blockchain::electrum) module for a usage example.
+pub struct ElectrumBlockchain(Client);
+
+#[cfg(test)]
+#[cfg(feature = "test-electrum")]
+#[bdk_blockchain_tests(crate)]
+fn local_electrs() -> ElectrumBlockchain {
+    ElectrumBlockchain::from(Client::new(&testutils::get_electrum_url(), None).unwrap())
+}
+
+impl std::convert::From<Client> for ElectrumBlockchain {
+    fn from(client: Client) -> Self {
+        ElectrumBlockchain(client)
+    }
+}
+
+impl Blockchain for ElectrumBlockchain {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        vec![
+            Capability::FullHistory,
+            Capability::GetAnyTx,
+            Capability::AccurateFees,
+        ]
+        .into_iter()
+        .collect()
+    }
+
+    fn setup<D: BatchDatabase, P: Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        self.0
+            .electrum_like_setup(stop_gap, database, progress_update)
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        Ok(self.0.transaction_get(txid).map(Option::Some)?)
+    }
+
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        Ok(self.0.transaction_broadcast(tx).map(|_| ())?)
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        // TODO: unsubscribe when added to the client, or is there a better call to use here?
+
+        Ok(self
+            .0
+            .block_headers_subscribe()
+            .map(|data| data.height as u32)?)
+    }
+
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
+        Ok(FeeRate::from_btc_per_kvb(
+            self.0.estimate_fee(target)? as f32
+        ))
+    }
+}
+
+impl ElectrumLikeSync for Client {
+    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error> {
+        self.batch_script_get_history(scripts)
+            .map(|v| {
+                v.into_iter()
+                    .map(|v| {
+                        v.into_iter()
+                            .map(
+                                |electrum_client::GetHistoryRes {
+                                     height, tx_hash, ..
+                                 }| ELSGetHistoryRes {
+                                    height,
+                                    tx_hash,
+                                },
+                            )
+                            .collect()
+                    })
+                    .collect()
+            })
+            .map_err(Error::Electrum)
+    }
+
+    fn els_batch_script_list_unspent<'s, I: IntoIterator<Item = &'s Script>>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSListUnspentRes>>, Error> {
+        self.batch_script_list_unspent(scripts)
+            .map(|v| {
+                v.into_iter()
+                    .map(|v| {
+                        v.into_iter()
+                            .map(
+                                |electrum_client::ListUnspentRes {
+                                     height,
+                                     tx_hash,
+                                     tx_pos,
+                                     ..
+                                 }| ELSListUnspentRes {
+                                    height,
+                                    tx_hash,
+                                    tx_pos,
+                                },
+                            )
+                            .collect()
+                    })
+                    .collect()
+            })
+            .map_err(Error::Electrum)
+    }
+
+    fn els_transaction_get(&self, txid: &Txid) -> Result<Transaction, Error> {
+        self.transaction_get(txid).map_err(Error::Electrum)
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/esplora.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/esplora.rs.html new file mode 100644 index 0000000000..635d250df6 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/esplora.rs.html @@ -0,0 +1,765 @@ +esplora.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Esplora
+//!
+//! This module defines a [`Blockchain`] struct that can query an Esplora backend
+//! populate the wallet's [database](crate::database::Database) by
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use bdk::blockchain::esplora::EsploraBlockchain;
+//! let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api");
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::collections::{HashMap, HashSet};
+use std::fmt;
+
+use futures::stream::{self, StreamExt, TryStreamExt};
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use serde::Deserialize;
+
+use reqwest::{Client, StatusCode};
+
+use bitcoin::consensus::{deserialize, serialize};
+use bitcoin::hashes::hex::ToHex;
+use bitcoin::hashes::{sha256, Hash};
+use bitcoin::{Script, Transaction, Txid};
+
+use self::utils::{ELSGetHistoryRes, ELSListUnspentRes, ElectrumLikeSync};
+use super::*;
+use crate::database::BatchDatabase;
+use crate::error::Error;
+use crate::FeeRate;
+
+#[derive(Debug)]
+struct UrlClient {
+    url: String,
+    // We use the async client instead of the blocking one because it automatically uses `fetch`
+    // when the target platform is wasm32.
+    client: Client,
+}
+
+/// Structure that implements the logic to sync with Esplora
+///
+/// ## Example
+/// See the [`blockchain::esplora`](crate::blockchain::esplora) module for a usage example.
+#[derive(Debug)]
+pub struct EsploraBlockchain(UrlClient);
+
+impl std::convert::From<UrlClient> for EsploraBlockchain {
+    fn from(url_client: UrlClient) -> Self {
+        EsploraBlockchain(url_client)
+    }
+}
+
+impl EsploraBlockchain {
+    /// Create a new instance of the client from a base URL
+    pub fn new(base_url: &str) -> Self {
+        EsploraBlockchain(UrlClient {
+            url: base_url.to_string(),
+            client: Client::new(),
+        })
+    }
+}
+
+#[maybe_async]
+impl Blockchain for EsploraBlockchain {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        vec![
+            Capability::FullHistory,
+            Capability::GetAnyTx,
+            Capability::AccurateFees,
+        ]
+        .into_iter()
+        .collect()
+    }
+
+    fn setup<D: BatchDatabase, P: Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self
+            .0
+            .electrum_like_setup(stop_gap, database, progress_update))
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        Ok(await_or_block!(self.0._get_tx(txid))?)
+    }
+
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        Ok(await_or_block!(self.0._broadcast(tx))?)
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        Ok(await_or_block!(self.0._get_height())?)
+    }
+
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
+        let estimates = await_or_block!(self.0._get_fee_estimates())?;
+
+        let fee_val = estimates
+            .into_iter()
+            .map(|(k, v)| Ok::<_, std::num::ParseIntError>((k.parse::<usize>()?, v)))
+            .collect::<Result<Vec<_>, _>>()
+            .map_err(|e| Error::Generic(e.to_string()))?
+            .into_iter()
+            .take_while(|(k, _)| k <= &target)
+            .map(|(_, v)| v)
+            .last()
+            .unwrap_or(1.0);
+
+        Ok(FeeRate::from_sat_per_vb(fee_val as f32))
+    }
+}
+
+impl UrlClient {
+    fn script_to_scripthash(script: &Script) -> String {
+        sha256::Hash::hash(script.as_bytes()).into_inner().to_hex()
+    }
+
+    async fn _get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, EsploraError> {
+        let resp = self
+            .client
+            .get(&format!("{}/tx/{}/raw", self.url, txid))
+            .send()
+            .await?;
+
+        if let StatusCode::NOT_FOUND = resp.status() {
+            return Ok(None);
+        }
+
+        Ok(Some(deserialize(&resp.error_for_status()?.bytes().await?)?))
+    }
+
+    async fn _broadcast(&self, transaction: &Transaction) -> Result<(), EsploraError> {
+        self.client
+            .post(&format!("{}/tx", self.url))
+            .body(serialize(transaction).to_hex())
+            .send()
+            .await?
+            .error_for_status()?;
+
+        Ok(())
+    }
+
+    async fn _get_height(&self) -> Result<u32, EsploraError> {
+        let req = self
+            .client
+            .get(&format!("{}/blocks/tip/height", self.url))
+            .send()
+            .await?;
+
+        Ok(req.error_for_status()?.text().await?.parse()?)
+    }
+
+    async fn _script_get_history(
+        &self,
+        script: &Script,
+    ) -> Result<Vec<ELSGetHistoryRes>, EsploraError> {
+        let mut result = Vec::new();
+        let scripthash = Self::script_to_scripthash(script);
+
+        // Add the unconfirmed transactions first
+        result.extend(
+            self.client
+                .get(&format!(
+                    "{}/scripthash/{}/txs/mempool",
+                    self.url, scripthash
+                ))
+                .send()
+                .await?
+                .error_for_status()?
+                .json::<Vec<EsploraGetHistory>>()
+                .await?
+                .into_iter()
+                .map(|x| ELSGetHistoryRes {
+                    tx_hash: x.txid,
+                    height: x.status.block_height.unwrap_or(0) as i32,
+                }),
+        );
+
+        debug!(
+            "Found {} mempool txs for {} - {:?}",
+            result.len(),
+            scripthash,
+            script
+        );
+
+        // Then go through all the pages of confirmed transactions
+        let mut last_txid = String::new();
+        loop {
+            let response = self
+                .client
+                .get(&format!(
+                    "{}/scripthash/{}/txs/chain/{}",
+                    self.url, scripthash, last_txid
+                ))
+                .send()
+                .await?
+                .error_for_status()?
+                .json::<Vec<EsploraGetHistory>>()
+                .await?;
+            let len = response.len();
+            if let Some(elem) = response.last() {
+                last_txid = elem.txid.to_hex();
+            }
+
+            debug!("... adding {} confirmed transactions", len);
+
+            result.extend(response.into_iter().map(|x| ELSGetHistoryRes {
+                tx_hash: x.txid,
+                height: x.status.block_height.unwrap_or(0) as i32,
+            }));
+
+            if len < 25 {
+                break;
+            }
+        }
+
+        Ok(result)
+    }
+
+    async fn _script_list_unspent(
+        &self,
+        script: &Script,
+    ) -> Result<Vec<ELSListUnspentRes>, EsploraError> {
+        Ok(self
+            .client
+            .get(&format!(
+                "{}/scripthash/{}/utxo",
+                self.url,
+                Self::script_to_scripthash(script)
+            ))
+            .send()
+            .await?
+            .error_for_status()?
+            .json::<Vec<EsploraListUnspent>>()
+            .await?
+            .into_iter()
+            .map(|x| ELSListUnspentRes {
+                tx_hash: x.txid,
+                height: x.status.block_height.unwrap_or(0),
+                tx_pos: x.vout,
+            })
+            .collect())
+    }
+
+    async fn _get_fee_estimates(&self) -> Result<HashMap<String, f64>, EsploraError> {
+        Ok(self
+            .client
+            .get(&format!("{}/fee-estimates", self.url,))
+            .send()
+            .await?
+            .error_for_status()?
+            .json::<HashMap<String, f64>>()
+            .await?)
+    }
+}
+
+#[maybe_async]
+impl ElectrumLikeSync for UrlClient {
+    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error> {
+        let future = async {
+            Ok(stream::iter(scripts)
+                .then(|script| self._script_get_history(&script))
+                .try_collect()
+                .await?)
+        };
+
+        await_or_block!(future)
+    }
+
+    fn els_batch_script_list_unspent<'s, I: IntoIterator<Item = &'s Script>>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSListUnspentRes>>, Error> {
+        let future = async {
+            Ok(stream::iter(scripts)
+                .then(|script| self._script_list_unspent(&script))
+                .try_collect()
+                .await?)
+        };
+
+        await_or_block!(future)
+    }
+
+    fn els_transaction_get(&self, txid: &Txid) -> Result<Transaction, Error> {
+        Ok(await_or_block!(self._get_tx(txid))?
+            .ok_or_else(|| EsploraError::TransactionNotFound(*txid))?)
+    }
+}
+
+#[derive(Deserialize)]
+struct EsploraGetHistoryStatus {
+    block_height: Option<usize>,
+}
+
+#[derive(Deserialize)]
+struct EsploraGetHistory {
+    txid: Txid,
+    status: EsploraGetHistoryStatus,
+}
+
+#[derive(Deserialize)]
+struct EsploraListUnspent {
+    txid: Txid,
+    vout: usize,
+    status: EsploraGetHistoryStatus,
+}
+
+/// Errors that can happen during a sync with [`EsploraBlockchain`]
+#[derive(Debug)]
+pub enum EsploraError {
+    /// Error with the HTTP call
+    Reqwest(reqwest::Error),
+    /// Invalid number returned
+    Parsing(std::num::ParseIntError),
+    /// Invalid Bitcoin data returned
+    BitcoinEncoding(bitcoin::consensus::encode::Error),
+
+    /// Transaction not found
+    TransactionNotFound(Txid),
+}
+
+impl fmt::Display for EsploraError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for EsploraError {}
+
+impl From<reqwest::Error> for EsploraError {
+    fn from(other: reqwest::Error) -> Self {
+        EsploraError::Reqwest(other)
+    }
+}
+
+impl From<std::num::ParseIntError> for EsploraError {
+    fn from(other: std::num::ParseIntError) -> Self {
+        EsploraError::Parsing(other)
+    }
+}
+
+impl From<bitcoin::consensus::encode::Error> for EsploraError {
+    fn from(other: bitcoin::consensus::encode::Error) -> Self {
+        EsploraError::BitcoinEncoding(other)
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/mod.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/mod.rs.html new file mode 100644 index 0000000000..a059a898bb --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/mod.rs.html @@ -0,0 +1,509 @@ +mod.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Blockchain backends
+//!
+//! This module provides the implementation of a few commonly-used backends like
+//! [Electrum](crate::blockchain::electrum), [Esplora](crate::blockchain::esplora) and
+//! [Compact Filters/Neutrino](crate::blockchain::compact_filters), along with a generalized trait
+//! [`Blockchain`] that can be implemented to build customized backends.
+
+use std::collections::HashSet;
+use std::ops::Deref;
+use std::sync::mpsc::{channel, Receiver, Sender};
+use std::sync::Arc;
+
+use bitcoin::{Transaction, Txid};
+
+use crate::database::BatchDatabase;
+use crate::error::Error;
+use crate::FeeRate;
+
+pub(crate) mod utils;
+
+#[cfg(feature = "electrum")]
+#[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
+pub mod electrum;
+#[cfg(feature = "electrum")]
+pub use self::electrum::ElectrumBlockchain;
+
+#[cfg(feature = "esplora")]
+#[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
+pub mod esplora;
+#[cfg(feature = "esplora")]
+pub use self::esplora::EsploraBlockchain;
+
+#[cfg(feature = "compact_filters")]
+#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
+pub mod compact_filters;
+#[cfg(feature = "compact_filters")]
+pub use self::compact_filters::CompactFiltersBlockchain;
+
+/// Capabilities that can be supported by a [`Blockchain`] backend
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum Capability {
+    /// Can recover the full history of a wallet and not only the set of currently spendable UTXOs
+    FullHistory,
+    /// Can fetch any historical transaction given its txid
+    GetAnyTx,
+    /// Can compute accurate fees for the transactions found during sync
+    AccurateFees,
+}
+
+/// Marker trait for a blockchain backend
+///
+/// This is a marker trait for blockchain types. It is automatically implemented for types that
+/// implement [`Blockchain`], so as a user of the library you won't have to implement this
+/// manually.
+///
+/// Users of the library will probably never have to implement this trait manually, but they
+/// could still need to import it to define types and structs with generics;
+/// Implementing only the marker trait is pointless, since [`OfflineBlockchain`]
+/// already does that, and whenever [`Blockchain`] is implemented, the marker trait is also
+/// automatically implemented by the library.
+pub trait BlockchainMarker {}
+
+/// The [`BlockchainMarker`] marker trait is automatically implemented for [`Blockchain`] types
+impl<T: Blockchain> BlockchainMarker for T {}
+
+/// Type that only implements [`Blockchain`] and is always "offline"
+pub struct OfflineBlockchain;
+impl BlockchainMarker for OfflineBlockchain {}
+
+/// Trait that defines the actions that must be supported by a blockchain backend
+#[maybe_async]
+pub trait Blockchain: BlockchainMarker {
+    /// Return the set of [`Capability`] supported by this backend
+    fn get_capabilities(&self) -> HashSet<Capability>;
+
+    /// Setup the backend and populate the internal database for the first time
+    ///
+    /// This method is the equivalent of [`Blockchain::sync`], but it's guaranteed to only be
+    /// called once, at the first [`Wallet::sync`](crate::wallet::Wallet::sync).
+    ///
+    /// The rationale behind the distinction between `sync` and `setup` is that some custom backends
+    /// might need to perform specific actions only the first time they are synced.
+    ///
+    /// For types that do not have that distinction, only this method can be implemented, since
+    /// [`Blockchain::sync`] defaults to calling this internally if not overridden.
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error>;
+    /// Populate the internal database with transactions and UTXOs
+    ///
+    /// If not overridden, it defaults to calling [`Blockchain::setup`] internally.
+    ///
+    /// This method should implement the logic required to iterate over the list of the wallet's
+    /// script_pubkeys using [`Database::iter_script_pubkeys`] and look for relevant transactions
+    /// in the blockchain to populate the database with [`BatchOperations::set_tx`] and
+    /// [`BatchOperations::set_utxo`].
+    ///
+    /// This method should also take care of removing UTXOs that are seen as spent in the
+    /// blockchain, using [`BatchOperations::del_utxo`].
+    ///
+    /// The `progress_update` object can be used to give the caller updates about the progress by using
+    /// [`Progress::update`].
+    ///
+    /// [`Database::iter_script_pubkeys`]: crate::database::Database::iter_script_pubkeys
+    /// [`BatchOperations::set_tx`]: crate::database::BatchOperations::set_tx
+    /// [`BatchOperations::set_utxo`]: crate::database::BatchOperations::set_utxo
+    /// [`BatchOperations::del_utxo`]: crate::database::BatchOperations::del_utxo
+    fn sync<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self.setup(stop_gap, database, progress_update))
+    }
+
+    /// Fetch a transaction from the blockchain given its txid
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
+    /// Broadcast a transaction
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error>;
+
+    /// Return the current height
+    fn get_height(&self) -> Result<u32, Error>;
+    /// Estimate the fee rate required to confirm a transaction in a given `target` of blocks
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>;
+}
+
+/// Data sent with a progress update over a [`channel`]
+pub type ProgressData = (f32, Option<String>);
+
+/// Trait for types that can receive and process progress updates during [`Blockchain::sync`] and
+/// [`Blockchain::setup`]
+pub trait Progress: Send {
+    /// Send a new progress update
+    ///
+    /// The `progress` value should be in the range 0.0 - 100.0, and the `message` value is an
+    /// optional text message that can be displayed to the user.
+    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error>;
+}
+
+/// Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]
+pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>) {
+    channel()
+}
+
+impl Progress for Sender<ProgressData> {
+    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
+        if progress < 0.0 || progress > 100.0 {
+            return Err(Error::InvalidProgressValue(progress));
+        }
+
+        self.send((progress, message))
+            .map_err(|_| Error::ProgressUpdateError)
+    }
+}
+
+/// Type that implements [`Progress`] and drops every update received
+#[derive(Clone)]
+pub struct NoopProgress;
+
+/// Create a new instance of [`NoopProgress`]
+pub fn noop_progress() -> NoopProgress {
+    NoopProgress
+}
+
+impl Progress for NoopProgress {
+    fn update(&self, _progress: f32, _message: Option<String>) -> Result<(), Error> {
+        Ok(())
+    }
+}
+
+/// Type that implements [`Progress`] and logs at level `INFO` every update received
+#[derive(Clone)]
+pub struct LogProgress;
+
+/// Create a nwe instance of [`LogProgress`]
+pub fn log_progress() -> LogProgress {
+    LogProgress
+}
+
+impl Progress for LogProgress {
+    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
+        log::info!("Sync {:.3}%: `{}`", progress, message.unwrap_or("".into()));
+
+        Ok(())
+    }
+}
+
+#[maybe_async]
+impl<T: Blockchain> Blockchain for Arc<T> {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        maybe_await!(self.deref().get_capabilities())
+    }
+
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self.deref().setup(stop_gap, database, progress_update))
+    }
+
+    fn sync<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self.deref().sync(stop_gap, database, progress_update))
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        maybe_await!(self.deref().get_tx(txid))
+    }
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        maybe_await!(self.deref().broadcast(tx))
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        maybe_await!(self.deref().get_height())
+    }
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
+        maybe_await!(self.deref().estimate_fee(target))
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/utils.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/utils.rs.html new file mode 100644 index 0000000000..6983da4834 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/utils.rs.html @@ -0,0 +1,719 @@ +utils.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::cmp;
+use std::collections::{HashSet, VecDeque};
+use std::convert::TryFrom;
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use bitcoin::{Address, Network, OutPoint, Script, Transaction, Txid};
+
+use super::*;
+use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
+use crate::error::Error;
+use crate::types::{ScriptType, TransactionDetails, UTXO};
+use crate::wallet::utils::ChunksIterator;
+
+#[derive(Debug)]
+pub struct ELSGetHistoryRes {
+    pub height: i32,
+    pub tx_hash: Txid,
+}
+
+#[derive(Debug)]
+pub struct ELSListUnspentRes {
+    pub height: usize,
+    pub tx_hash: Txid,
+    pub tx_pos: usize,
+}
+
+/// Implements the synchronization logic for an Electrum-like client.
+#[maybe_async]
+pub trait ElectrumLikeSync {
+    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error>;
+
+    fn els_batch_script_list_unspent<'s, I: IntoIterator<Item = &'s Script>>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSListUnspentRes>>, Error>;
+
+    fn els_transaction_get(&self, txid: &Txid) -> Result<Transaction, Error>;
+
+    // Provided methods down here...
+
+    fn electrum_like_setup<D: BatchDatabase, P: Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        _progress_update: P,
+    ) -> Result<(), Error> {
+        // TODO: progress
+
+        let stop_gap = stop_gap.unwrap_or(20);
+        let batch_query_size = 20;
+
+        // check unconfirmed tx, delete so they are retrieved later
+        let mut del_batch = database.begin_batch();
+        for tx in database.iter_txs(false)? {
+            if tx.height.is_none() {
+                del_batch.del_tx(&tx.txid, false)?;
+            }
+        }
+        database.commit_batch(del_batch)?;
+
+        // maximum derivation index for a change address that we've seen during sync
+        let mut change_max_deriv = None;
+
+        let mut already_checked: HashSet<Script> = HashSet::new();
+        let mut to_check_later = VecDeque::with_capacity(batch_query_size);
+
+        // insert the first chunk
+        let mut iter_scriptpubkeys = database
+            .iter_script_pubkeys(Some(ScriptType::External))?
+            .into_iter();
+        let chunk: Vec<Script> = iter_scriptpubkeys.by_ref().take(batch_query_size).collect();
+        for item in chunk.into_iter().rev() {
+            to_check_later.push_front(item);
+        }
+
+        let mut iterating_external = true;
+        let mut index = 0;
+        let mut last_found = None;
+        while !to_check_later.is_empty() {
+            trace!("to_check_later size {}", to_check_later.len());
+
+            let until = cmp::min(to_check_later.len(), batch_query_size);
+            let chunk: Vec<Script> = to_check_later.drain(..until).collect();
+            let call_result = maybe_await!(self.els_batch_script_get_history(chunk.iter()))?;
+
+            for (script, history) in chunk.into_iter().zip(call_result.into_iter()) {
+                trace!("received history for {:?}, size {}", script, history.len());
+
+                if !history.is_empty() {
+                    last_found = Some(index);
+
+                    let mut check_later_scripts = maybe_await!(self.check_history(
+                        database,
+                        script,
+                        history,
+                        &mut change_max_deriv
+                    ))?
+                    .into_iter()
+                    .filter(|x| already_checked.insert(x.clone()))
+                    .collect();
+                    to_check_later.append(&mut check_later_scripts);
+                }
+
+                index += 1;
+            }
+
+            match iterating_external {
+                true if index - last_found.unwrap_or(0) >= stop_gap => iterating_external = false,
+                true => {
+                    trace!("pushing one more batch from `iter_scriptpubkeys`. index = {}, last_found = {:?}, stop_gap = {}", index, last_found, stop_gap);
+
+                    let chunk: Vec<Script> =
+                        iter_scriptpubkeys.by_ref().take(batch_query_size).collect();
+                    for item in chunk.into_iter().rev() {
+                        to_check_later.push_front(item);
+                    }
+                }
+                _ => {}
+            }
+        }
+
+        // check utxo
+        // TODO: try to minimize network requests and re-use scripts if possible
+        let mut batch = database.begin_batch();
+        for chunk in ChunksIterator::new(database.iter_utxos()?.into_iter(), batch_query_size) {
+            let scripts: Vec<_> = chunk.iter().map(|u| &u.txout.script_pubkey).collect();
+            let call_result = maybe_await!(self.els_batch_script_list_unspent(scripts))?;
+
+            // check which utxos are actually still unspent
+            for (utxo, list_unspent) in chunk.into_iter().zip(call_result.iter()) {
+                debug!(
+                    "outpoint {:?} is unspent for me, list unspent is {:?}",
+                    utxo.outpoint, list_unspent
+                );
+
+                let mut spent = true;
+                for unspent in list_unspent {
+                    let res_outpoint = OutPoint::new(unspent.tx_hash, unspent.tx_pos as u32);
+                    if utxo.outpoint == res_outpoint {
+                        spent = false;
+                        break;
+                    }
+                }
+                if spent {
+                    info!("{} not anymore unspent, removing", utxo.outpoint);
+                    batch.del_utxo(&utxo.outpoint)?;
+                }
+            }
+        }
+
+        let current_ext = database.get_last_index(ScriptType::External)?.unwrap_or(0);
+        let first_ext_new = last_found.map(|x| x + 1).unwrap_or(0) as u32;
+        if first_ext_new > current_ext {
+            info!("Setting external index to {}", first_ext_new);
+            database.set_last_index(ScriptType::External, first_ext_new)?;
+        }
+
+        let current_int = database.get_last_index(ScriptType::Internal)?.unwrap_or(0);
+        let first_int_new = change_max_deriv.map(|x| x + 1).unwrap_or(0);
+        if first_int_new > current_int {
+            info!("Setting internal index to {}", first_int_new);
+            database.set_last_index(ScriptType::Internal, first_int_new)?;
+        }
+
+        database.commit_batch(batch)?;
+
+        Ok(())
+    }
+
+    fn check_tx_and_descendant<D: BatchDatabase>(
+        &self,
+        database: &mut D,
+        txid: &Txid,
+        height: Option<u32>,
+        cur_script: &Script,
+        change_max_deriv: &mut Option<u32>,
+    ) -> Result<Vec<Script>, Error> {
+        debug!(
+            "check_tx_and_descendant of {}, height: {:?}, script: {}",
+            txid, height, cur_script
+        );
+        let mut updates = database.begin_batch();
+        let tx = match database.get_tx(&txid, true)? {
+            Some(mut saved_tx) => {
+                // update the height if it's different (in case of reorg)
+                if saved_tx.height != height {
+                    info!(
+                        "updating height from {:?} to {:?} for tx {}",
+                        saved_tx.height, height, txid
+                    );
+                    saved_tx.height = height;
+                    updates.set_tx(&saved_tx)?;
+                }
+
+                debug!("already have {} in db, returning the cached version", txid);
+
+                // unwrap since we explicitly ask for the raw_tx, if it's not present something
+                // went wrong
+                saved_tx.transaction.unwrap()
+            }
+            None => {
+                let fetched_tx = maybe_await!(self.els_transaction_get(&txid))?;
+                database.set_raw_tx(&fetched_tx)?;
+
+                fetched_tx
+            }
+        };
+
+        let mut incoming: u64 = 0;
+        let mut outgoing: u64 = 0;
+
+        let mut inputs_sum: u64 = 0;
+        let mut outputs_sum: u64 = 0;
+
+        // look for our own inputs
+        for (i, input) in tx.input.iter().enumerate() {
+            // the fact that we visit addresses in a BFS fashion starting from the external addresses
+            // should ensure that this query is always consistent (i.e. when we get to call this all
+            // the transactions at a lower depth have already been indexed, so if an outpoint is ours
+            // we are guaranteed to have it in the db).
+            if let Some(previous_output) = database.get_previous_output(&input.previous_output)? {
+                inputs_sum += previous_output.value;
+
+                if database.is_mine(&previous_output.script_pubkey)? {
+                    outgoing += previous_output.value;
+
+                    debug!("{} input #{} is mine, removing from utxo", txid, i);
+                    updates.del_utxo(&input.previous_output)?;
+                }
+            } else {
+                // The input is not ours, but we still need to count it for the fees. so fetch the
+                // tx (from the database or from network) and check it
+                let tx = match database.get_tx(&input.previous_output.txid, true)? {
+                    Some(saved_tx) => saved_tx.transaction.unwrap(),
+                    None => {
+                        let fetched_tx =
+                            maybe_await!(self.els_transaction_get(&input.previous_output.txid))?;
+                        database.set_raw_tx(&fetched_tx)?;
+
+                        fetched_tx
+                    }
+                };
+
+                inputs_sum += tx.output[input.previous_output.vout as usize].value;
+            }
+        }
+
+        let mut to_check_later = vec![];
+        for (i, output) in tx.output.iter().enumerate() {
+            // to compute the fees later
+            outputs_sum += output.value;
+
+            // this output is ours, we have a path to derive it
+            if let Some((script_type, child)) =
+                database.get_path_from_script_pubkey(&output.script_pubkey)?
+            {
+                debug!("{} output #{} is mine, adding utxo", txid, i);
+                updates.set_utxo(&UTXO {
+                    outpoint: OutPoint::new(tx.txid(), i as u32),
+                    txout: output.clone(),
+                    is_internal: script_type.is_internal(),
+                })?;
+                incoming += output.value;
+
+                if output.script_pubkey != *cur_script {
+                    debug!("{} output #{} script {} was not current script, adding script to be checked later", txid, i, output.script_pubkey);
+                    to_check_later.push(output.script_pubkey.clone())
+                }
+
+                // derive as many change addrs as external addresses that we've seen
+                if script_type == ScriptType::Internal
+                    && (change_max_deriv.is_none() || child > change_max_deriv.unwrap_or(0))
+                {
+                    *change_max_deriv = Some(child);
+                }
+            }
+        }
+
+        let tx = TransactionDetails {
+            txid: tx.txid(),
+            transaction: Some(tx),
+            received: incoming,
+            sent: outgoing,
+            height,
+            timestamp: 0,
+            fees: inputs_sum - outputs_sum,
+        };
+        info!("Saving tx {}", txid);
+        updates.set_tx(&tx)?;
+
+        database.commit_batch(updates)?;
+
+        Ok(to_check_later)
+    }
+
+    fn check_history<D: BatchDatabase>(
+        &self,
+        database: &mut D,
+        script_pubkey: Script,
+        txs: Vec<ELSGetHistoryRes>,
+        change_max_deriv: &mut Option<u32>,
+    ) -> Result<Vec<Script>, Error> {
+        let mut to_check_later = Vec::new();
+
+        debug!(
+            "history of {} script {} has {} tx",
+            Address::from_script(&script_pubkey, Network::Testnet).unwrap(),
+            script_pubkey,
+            txs.len()
+        );
+
+        for tx in txs {
+            let height: Option<u32> = match tx.height {
+                0 | -1 => None,
+                x => u32::try_from(x).ok(),
+            };
+
+            to_check_later.extend_from_slice(&maybe_await!(self.check_tx_and_descendant(
+                database,
+                &tx.tx_hash,
+                height,
+                &script_pubkey,
+                change_max_deriv,
+            ))?);
+        }
+
+        Ok(to_check_later)
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/keyvalue.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/keyvalue.rs.html new file mode 100644 index 0000000000..8e338397ad --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/keyvalue.rs.html @@ -0,0 +1,965 @@ +keyvalue.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::convert::TryInto;
+
+use sled::{Batch, Tree};
+
+use bitcoin::consensus::encode::{deserialize, serialize};
+use bitcoin::hash_types::Txid;
+use bitcoin::{OutPoint, Script, Transaction};
+
+use crate::database::memory::MapKey;
+use crate::database::{BatchDatabase, BatchOperations, Database};
+use crate::error::Error;
+use crate::types::*;
+
+macro_rules! impl_batch_operations {
+    ( { $($after_insert:tt)* }, $process_delete:ident ) => {
+        fn set_script_pubkey(&mut self, script: &Script, script_type: ScriptType, path: u32) -> Result<(), Error> {
+            let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
+            self.insert(key, serialize(script))$($after_insert)*;
+
+            let key = MapKey::Script(Some(script)).as_map_key();
+            let value = json!({
+                "t": script_type,
+                "p": path,
+            });
+            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
+            let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
+            let value = json!({
+                "t": utxo.txout,
+                "i": utxo.is_internal,
+            });
+            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
+            let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
+            let value = serialize(transaction);
+            self.insert(key, value)$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
+            let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
+
+            // remove the raw tx from the serialized version
+            let mut value = serde_json::to_value(transaction)?;
+            value["transaction"] = serde_json::Value::Null;
+            let value = serde_json::to_vec(&value)?;
+
+            self.insert(key, value)$($after_insert)*;
+
+            // insert the raw_tx if present
+            if let Some(ref tx) = transaction.transaction {
+                self.set_raw_tx(tx)?;
+            }
+
+            Ok(())
+        }
+
+        fn set_last_index(&mut self, script_type: ScriptType, value: u32) -> Result<(), Error> {
+            let key = MapKey::LastIndex(script_type).as_map_key();
+            self.insert(key, &value.to_be_bytes())$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn del_script_pubkey_from_path(&mut self, script_type: ScriptType, path: u32) -> Result<Option<Script>, Error> {
+            let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
+        }
+
+        fn del_path_from_script_pubkey(&mut self, script: &Script) -> Result<Option<(ScriptType, u32)>, Error> {
+            let key = MapKey::Script(Some(script)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                    let st = serde_json::from_value(val["t"].take())?;
+                    let path = serde_json::from_value(val["p"].take())?;
+
+                    Ok(Some((st, path)))
+                }
+            }
+        }
+
+        fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+            let key = MapKey::UTXO(Some(outpoint)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                    let txout = serde_json::from_value(val["t"].take())?;
+                    let is_internal = serde_json::from_value(val["i"].take())?;
+
+                    Ok(Some(UTXO { outpoint: outpoint.clone(), txout, is_internal }))
+                }
+            }
+        }
+
+        fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+            let key = MapKey::RawTx(Some(txid)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
+        }
+
+        fn del_tx(&mut self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+            let raw_tx = if include_raw {
+                self.del_raw_tx(txid)?
+            } else {
+                None
+            };
+
+            let key = MapKey::Transaction(Some(txid)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let mut val: TransactionDetails = serde_json::from_slice(&b)?;
+                    val.transaction = raw_tx;
+
+                    Ok(Some(val))
+                }
+            }
+        }
+
+        fn del_last_index(&mut self, script_type: ScriptType) -> Result<Option<u32>, Error> {
+            let key = MapKey::LastIndex(script_type).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let array: [u8; 4] = b.as_ref().try_into().map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
+                    let val = u32::from_be_bytes(array);
+                    Ok(Some(val))
+                }
+            }
+        }
+    }
+}
+
+macro_rules! process_delete_tree {
+    ($res:expr) => {
+        $res?
+    };
+}
+impl BatchOperations for Tree {
+    impl_batch_operations!({?}, process_delete_tree);
+}
+
+macro_rules! process_delete_batch {
+    ($res:expr) => {
+        None as Option<sled::IVec>
+    };
+}
+#[allow(unused_variables)]
+impl BatchOperations for Batch {
+    impl_batch_operations!({}, process_delete_batch);
+}
+
+impl Database for Tree {
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        script_type: ScriptType,
+        bytes: B,
+    ) -> Result<(), Error> {
+        let key = MapKey::DescriptorChecksum(script_type).as_map_key();
+
+        let prev = self.get(&key)?.map(|x| x.to_vec());
+        if let Some(val) = prev {
+            if val == bytes.as_ref() {
+                Ok(())
+            } else {
+                Err(Error::ChecksumMismatch)
+            }
+        } else {
+            self.insert(&key, bytes.as_ref())?;
+            Ok(())
+        }
+    }
+
+    fn iter_script_pubkeys(&self, script_type: Option<ScriptType>) -> Result<Vec<Script>, Error> {
+        let key = MapKey::Path((script_type, None)).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (_, v) = x?;
+                Ok(deserialize(&v)?)
+            })
+            .collect()
+    }
+
+    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error> {
+        let key = MapKey::UTXO(None).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (k, v) = x?;
+                let outpoint = deserialize(&k[1..])?;
+
+                let mut val: serde_json::Value = serde_json::from_slice(&v)?;
+                let txout = serde_json::from_value(val["t"].take())?;
+                let is_internal = serde_json::from_value(val["i"].take())?;
+
+                Ok(UTXO {
+                    outpoint,
+                    txout,
+                    is_internal,
+                })
+            })
+            .collect()
+    }
+
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
+        let key = MapKey::RawTx(None).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (_, v) = x?;
+                Ok(deserialize(&v)?)
+            })
+            .collect()
+    }
+
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(None).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (k, v) = x?;
+                let mut txdetails: TransactionDetails = serde_json::from_slice(&v)?;
+                if include_raw {
+                    let txid = deserialize(&k[1..])?;
+                    txdetails.transaction = self.get_raw_tx(&txid)?;
+                }
+
+                Ok(txdetails)
+            })
+            .collect()
+    }
+
+    fn get_script_pubkey_from_path(
+        &self,
+        script_type: ScriptType,
+        path: u32,
+    ) -> Result<Option<Script>, Error> {
+        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
+        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
+    }
+
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(ScriptType, u32)>, Error> {
+        let key = MapKey::Script(Some(script)).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                let st = serde_json::from_value(val["t"].take())?;
+                let path = serde_json::from_value(val["p"].take())?;
+
+                Ok((st, path))
+            })
+            .transpose()
+    }
+
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                let txout = serde_json::from_value(val["t"].take())?;
+                let is_internal = serde_json::from_value(val["i"].take())?;
+
+                Ok(UTXO {
+                    outpoint: outpoint.clone(),
+                    txout,
+                    is_internal,
+                })
+            })
+            .transpose()
+    }
+
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        let key = MapKey::RawTx(Some(txid)).as_map_key();
+        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
+    }
+
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(Some(txid)).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let mut txdetails: TransactionDetails = serde_json::from_slice(&b)?;
+                if include_raw {
+                    txdetails.transaction = self.get_raw_tx(&txid)?;
+                }
+
+                Ok(txdetails)
+            })
+            .transpose()
+    }
+
+    fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error> {
+        let key = MapKey::LastIndex(script_type).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let array: [u8; 4] = b
+                    .as_ref()
+                    .try_into()
+                    .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
+                let val = u32::from_be_bytes(array);
+                Ok(val)
+            })
+            .transpose()
+    }
+
+    // inserts 0 if not present
+    fn increment_last_index(&mut self, script_type: ScriptType) -> Result<u32, Error> {
+        let key = MapKey::LastIndex(script_type).as_map_key();
+        self.update_and_fetch(key, |prev| {
+            let new = match prev {
+                Some(b) => {
+                    let array: [u8; 4] = b.try_into().unwrap_or([0; 4]);
+                    let val = u32::from_be_bytes(array);
+
+                    val + 1
+                }
+                None => 0,
+            };
+
+            Some(new.to_be_bytes().to_vec())
+        })?
+        .map_or(Ok(0), |b| -> Result<_, Error> {
+            let array: [u8; 4] = b
+                .as_ref()
+                .try_into()
+                .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
+            let val = u32::from_be_bytes(array);
+            Ok(val)
+        })
+    }
+}
+
+impl BatchDatabase for Tree {
+    type Batch = sled::Batch;
+
+    fn begin_batch(&self) -> Self::Batch {
+        sled::Batch::default()
+    }
+
+    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
+        Ok(self.apply_batch(batch)?)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::sync::{Arc, Condvar, Mutex, Once};
+    use std::time::{SystemTime, UNIX_EPOCH};
+
+    use sled::{Db, Tree};
+
+    static mut COUNT: usize = 0;
+
+    lazy_static! {
+        static ref DB: Arc<(Mutex<Option<Db>>, Condvar)> =
+            Arc::new((Mutex::new(None), Condvar::new()));
+        static ref INIT: Once = Once::new();
+    }
+
+    fn get_tree() -> Tree {
+        unsafe {
+            let cloned = DB.clone();
+            let (mutex, cvar) = &*cloned;
+
+            INIT.call_once(|| {
+                let mut db = mutex.lock().unwrap();
+
+                let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
+                let mut dir = std::env::temp_dir();
+                dir.push(format!("mbw_{}", time.as_nanos()));
+
+                *db = Some(sled::open(dir).unwrap());
+                cvar.notify_all();
+            });
+
+            let mut db = mutex.lock().unwrap();
+            while !db.is_some() {
+                db = cvar.wait(db).unwrap();
+            }
+
+            COUNT += 1;
+
+            db.as_ref()
+                .unwrap()
+                .open_tree(format!("tree_{}", COUNT))
+                .unwrap()
+        }
+    }
+
+    #[test]
+    fn test_script_pubkey() {
+        crate::database::test::test_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_batch_script_pubkey() {
+        crate::database::test::test_batch_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_iter_script_pubkey() {
+        crate::database::test::test_iter_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_del_script_pubkey() {
+        crate::database::test::test_del_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_utxo() {
+        crate::database::test::test_utxo(get_tree());
+    }
+
+    #[test]
+    fn test_raw_tx() {
+        crate::database::test::test_raw_tx(get_tree());
+    }
+
+    #[test]
+    fn test_tx() {
+        crate::database::test::test_tx(get_tree());
+    }
+
+    #[test]
+    fn test_last_index() {
+        crate::database::test::test_last_index(get_tree());
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/memory.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/memory.rs.html new file mode 100644 index 0000000000..7f900ff53a --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/memory.rs.html @@ -0,0 +1,1119 @@ +memory.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! In-memory ephemeral database
+//!
+//! This module defines an in-memory database type called [`MemoryDatabase`] that is based on a
+//! [`BTreeMap`].
+
+use std::collections::BTreeMap;
+use std::ops::Bound::{Excluded, Included};
+
+use bitcoin::consensus::encode::{deserialize, serialize};
+use bitcoin::hash_types::Txid;
+use bitcoin::{OutPoint, Script, Transaction};
+
+use crate::database::{BatchDatabase, BatchOperations, Database};
+use crate::error::Error;
+use crate::types::*;
+
+// path -> script       p{i,e}<path> -> script
+// script -> path       s<script> -> {i,e}<path>
+// outpoint             u<outpoint> -> txout
+// rawtx                r<txid> -> tx
+// transactions         t<txid> -> tx details
+// deriv indexes        c{i,e} -> u32
+// descriptor checksum  d{i,e} -> vec<u8>
+
+pub(crate) enum MapKey<'a> {
+    Path((Option<ScriptType>, Option<u32>)),
+    Script(Option<&'a Script>),
+    UTXO(Option<&'a OutPoint>),
+    RawTx(Option<&'a Txid>),
+    Transaction(Option<&'a Txid>),
+    LastIndex(ScriptType),
+    DescriptorChecksum(ScriptType),
+}
+
+impl MapKey<'_> {
+    pub fn as_prefix(&self) -> Vec<u8> {
+        match self {
+            MapKey::Path((st, _)) => {
+                let mut v = b"p".to_vec();
+                if let Some(st) = st {
+                    v.push(st.as_byte());
+                }
+                v
+            }
+            MapKey::Script(_) => b"s".to_vec(),
+            MapKey::UTXO(_) => b"u".to_vec(),
+            MapKey::RawTx(_) => b"r".to_vec(),
+            MapKey::Transaction(_) => b"t".to_vec(),
+            MapKey::LastIndex(st) => [b"c", st.as_ref()].concat(),
+            MapKey::DescriptorChecksum(st) => [b"d", st.as_ref()].concat(),
+        }
+    }
+
+    fn serialize_content(&self) -> Vec<u8> {
+        match self {
+            MapKey::Path((_, Some(child))) => u32::from(*child).to_be_bytes().to_vec(),
+            MapKey::Script(Some(s)) => serialize(*s),
+            MapKey::UTXO(Some(s)) => serialize(*s),
+            MapKey::RawTx(Some(s)) => serialize(*s),
+            MapKey::Transaction(Some(s)) => serialize(*s),
+            _ => vec![],
+        }
+    }
+
+    pub fn as_map_key(&self) -> Vec<u8> {
+        let mut v = self.as_prefix();
+        v.extend_from_slice(&self.serialize_content());
+
+        v
+    }
+}
+
+fn after(key: &Vec<u8>) -> Vec<u8> {
+    let mut key = key.clone();
+    let mut idx = key.len();
+    while idx > 0 {
+        if key[idx - 1] == 0xFF {
+            idx -= 1;
+            continue;
+        } else {
+            key[idx - 1] += 1;
+            break;
+        }
+    }
+
+    key
+}
+
+/// In-memory ephemeral database
+///
+/// This database can be used as a temporary storage for wallets that are not kept permanently on
+/// a device, or on platforms that don't provide a filesystem, like `wasm32`.
+///
+/// Once it's dropped its content will be lost.
+///
+/// If you are looking for a permanent storage solution, you can try with the default key-value
+/// database called [`sled`]. See the [`database`] module documentation for more defailts.
+///
+/// [`database`]: crate::database
+#[derive(Debug, Default)]
+pub struct MemoryDatabase {
+    map: BTreeMap<Vec<u8>, Box<dyn std::any::Any>>,
+    deleted_keys: Vec<Vec<u8>>,
+}
+
+impl MemoryDatabase {
+    /// Create a new empty database
+    pub fn new() -> Self {
+        MemoryDatabase {
+            map: BTreeMap::new(),
+            deleted_keys: Vec::new(),
+        }
+    }
+}
+
+impl BatchOperations for MemoryDatabase {
+    fn set_script_pubkey(
+        &mut self,
+        script: &Script,
+        script_type: ScriptType,
+        path: u32,
+    ) -> Result<(), Error> {
+        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
+        self.map.insert(key, Box::new(script.clone()));
+
+        let key = MapKey::Script(Some(script)).as_map_key();
+        let value = json!({
+            "t": script_type,
+            "p": path,
+        });
+        self.map.insert(key, Box::new(value));
+
+        Ok(())
+    }
+
+    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
+        let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
+        self.map
+            .insert(key, Box::new((utxo.txout.clone(), utxo.is_internal)));
+
+        Ok(())
+    }
+    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
+        let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
+        self.map.insert(key, Box::new(transaction.clone()));
+
+        Ok(())
+    }
+    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
+        let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
+
+        // insert the raw_tx if present
+        if let Some(ref tx) = transaction.transaction {
+            self.set_raw_tx(tx)?;
+        }
+
+        // remove the raw tx from the serialized version
+        let mut transaction = transaction.clone();
+        transaction.transaction = None;
+
+        self.map.insert(key, Box::new(transaction));
+
+        Ok(())
+    }
+    fn set_last_index(&mut self, script_type: ScriptType, value: u32) -> Result<(), Error> {
+        let key = MapKey::LastIndex(script_type).as_map_key();
+        self.map.insert(key, Box::new(value));
+
+        Ok(())
+    }
+
+    fn del_script_pubkey_from_path(
+        &mut self,
+        script_type: ScriptType,
+        path: u32,
+    ) -> Result<Option<Script>, Error> {
+        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
+    }
+    fn del_path_from_script_pubkey(
+        &mut self,
+        script: &Script,
+    ) -> Result<Option<(ScriptType, u32)>, Error> {
+        let key = MapKey::Script(Some(script)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => {
+                let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
+                let st = serde_json::from_value(val["t"].take())?;
+                let path = serde_json::from_value(val["p"].take())?;
+
+                Ok(Some((st, path)))
+            }
+        }
+    }
+    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => {
+                let (txout, is_internal) = b.downcast_ref().cloned().unwrap();
+                Ok(Some(UTXO {
+                    outpoint: outpoint.clone(),
+                    txout,
+                    is_internal,
+                }))
+            }
+        }
+    }
+    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        let key = MapKey::RawTx(Some(txid)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
+    }
+    fn del_tx(
+        &mut self,
+        txid: &Txid,
+        include_raw: bool,
+    ) -> Result<Option<TransactionDetails>, Error> {
+        let raw_tx = if include_raw {
+            self.del_raw_tx(txid)?
+        } else {
+            None
+        };
+
+        let key = MapKey::Transaction(Some(txid)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => {
+                let mut val: TransactionDetails = b.downcast_ref().cloned().unwrap();
+                val.transaction = raw_tx;
+
+                Ok(Some(val))
+            }
+        }
+    }
+    fn del_last_index(&mut self, script_type: ScriptType) -> Result<Option<u32>, Error> {
+        let key = MapKey::LastIndex(script_type).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => Ok(Some(*b.downcast_ref().unwrap())),
+        }
+    }
+}
+
+impl Database for MemoryDatabase {
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        script_type: ScriptType,
+        bytes: B,
+    ) -> Result<(), Error> {
+        let key = MapKey::DescriptorChecksum(script_type).as_map_key();
+
+        let prev = self
+            .map
+            .get(&key)
+            .map(|x| x.downcast_ref::<Vec<u8>>().unwrap());
+        if let Some(val) = prev {
+            if val == &bytes.as_ref().to_vec() {
+                Ok(())
+            } else {
+                Err(Error::ChecksumMismatch)
+            }
+        } else {
+            self.map.insert(key, Box::new(bytes.as_ref().to_vec()));
+            Ok(())
+        }
+    }
+
+    fn iter_script_pubkeys(&self, script_type: Option<ScriptType>) -> Result<Vec<Script>, Error> {
+        let key = MapKey::Path((script_type, None)).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
+            .collect()
+    }
+
+    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error> {
+        let key = MapKey::UTXO(None).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(k, v)| {
+                let outpoint = deserialize(&k[1..]).unwrap();
+                let (txout, is_internal) = v.downcast_ref().cloned().unwrap();
+                Ok(UTXO {
+                    outpoint,
+                    txout,
+                    is_internal,
+                })
+            })
+            .collect()
+    }
+
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
+        let key = MapKey::RawTx(None).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
+            .collect()
+    }
+
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(None).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(k, v)| {
+                let mut txdetails: TransactionDetails = v.downcast_ref().cloned().unwrap();
+                if include_raw {
+                    let txid = deserialize(&k[1..])?;
+                    txdetails.transaction = self.get_raw_tx(&txid)?;
+                }
+
+                Ok(txdetails)
+            })
+            .collect()
+    }
+
+    fn get_script_pubkey_from_path(
+        &self,
+        script_type: ScriptType,
+        path: u32,
+    ) -> Result<Option<Script>, Error> {
+        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
+        Ok(self
+            .map
+            .get(&key)
+            .map(|b| b.downcast_ref().cloned().unwrap()))
+    }
+
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(ScriptType, u32)>, Error> {
+        let key = MapKey::Script(Some(script)).as_map_key();
+        Ok(self.map.get(&key).map(|b| {
+            let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
+            let st = serde_json::from_value(val["t"].take()).unwrap();
+            let path = serde_json::from_value(val["p"].take()).unwrap();
+
+            (st, path)
+        }))
+    }
+
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
+        Ok(self.map.get(&key).map(|b| {
+            let (txout, is_internal) = b.downcast_ref().cloned().unwrap();
+            UTXO {
+                outpoint: outpoint.clone(),
+                txout,
+                is_internal,
+            }
+        }))
+    }
+
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        let key = MapKey::RawTx(Some(txid)).as_map_key();
+        Ok(self
+            .map
+            .get(&key)
+            .map(|b| b.downcast_ref().cloned().unwrap()))
+    }
+
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(Some(txid)).as_map_key();
+        Ok(self.map.get(&key).map(|b| {
+            let mut txdetails: TransactionDetails = b.downcast_ref().cloned().unwrap();
+            if include_raw {
+                txdetails.transaction = self.get_raw_tx(&txid).unwrap();
+            }
+
+            txdetails
+        }))
+    }
+
+    fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error> {
+        let key = MapKey::LastIndex(script_type).as_map_key();
+        Ok(self.map.get(&key).map(|b| *b.downcast_ref().unwrap()))
+    }
+
+    // inserts 0 if not present
+    fn increment_last_index(&mut self, script_type: ScriptType) -> Result<u32, Error> {
+        let key = MapKey::LastIndex(script_type).as_map_key();
+        let value = self
+            .map
+            .entry(key.clone())
+            .and_modify(|x| *x.downcast_mut::<u32>().unwrap() += 1)
+            .or_insert(Box::<u32>::new(0))
+            .downcast_mut()
+            .unwrap();
+
+        Ok(*value)
+    }
+}
+
+impl BatchDatabase for MemoryDatabase {
+    type Batch = Self;
+
+    fn begin_batch(&self) -> Self::Batch {
+        MemoryDatabase::new()
+    }
+
+    fn commit_batch(&mut self, mut batch: Self::Batch) -> Result<(), Error> {
+        for key in batch.deleted_keys {
+            self.map.remove(&key);
+        }
+
+        Ok(self.map.append(&mut batch.map))
+    }
+}
+
+#[cfg(test)]
+impl MemoryDatabase {
+    // Artificially insert a tx in the database, as if we had found it with a `sync`
+    pub fn received_tx(
+        &mut self,
+        tx_meta: testutils::TestIncomingTx,
+        current_height: Option<u32>,
+    ) -> bitcoin::Txid {
+        use std::str::FromStr;
+
+        let tx = Transaction {
+            version: 1,
+            lock_time: 0,
+            input: vec![],
+            output: tx_meta
+                .output
+                .iter()
+                .map(|out_meta| bitcoin::TxOut {
+                    value: out_meta.value,
+                    script_pubkey: bitcoin::Address::from_str(&out_meta.to_address)
+                        .unwrap()
+                        .script_pubkey(),
+                })
+                .collect(),
+        };
+
+        let txid = tx.txid();
+        let height = tx_meta
+            .min_confirmations
+            .map(|conf| current_height.unwrap().checked_sub(conf as u32).unwrap());
+
+        let tx_details = TransactionDetails {
+            transaction: Some(tx.clone()),
+            txid,
+            timestamp: 0,
+            height,
+            received: 0,
+            sent: 0,
+            fees: 0,
+        };
+
+        self.set_tx(&tx_details).unwrap();
+        for (vout, out) in tx.output.iter().enumerate() {
+            self.set_utxo(&UTXO {
+                txout: out.clone(),
+                outpoint: OutPoint {
+                    txid,
+                    vout: vout as u32,
+                },
+                is_internal: false,
+            })
+            .unwrap();
+        }
+
+        txid
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::MemoryDatabase;
+
+    fn get_tree() -> MemoryDatabase {
+        MemoryDatabase::new()
+    }
+
+    #[test]
+    fn test_script_pubkey() {
+        crate::database::test::test_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_batch_script_pubkey() {
+        crate::database::test::test_batch_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_iter_script_pubkey() {
+        crate::database::test::test_iter_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_del_script_pubkey() {
+        crate::database::test::test_del_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_utxo() {
+        crate::database::test::test_utxo(get_tree());
+    }
+
+    #[test]
+    fn test_raw_tx() {
+        crate::database::test::test_raw_tx(get_tree());
+    }
+
+    #[test]
+    fn test_tx() {
+        crate::database::test::test_tx(get_tree());
+    }
+
+    #[test]
+    fn test_last_index() {
+        crate::database::test::test_last_index(get_tree());
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/mod.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/mod.rs.html new file mode 100644 index 0000000000..5836fe48fd --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/mod.rs.html @@ -0,0 +1,739 @@ +mod.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Database types
+//!
+//! This module provides the implementation of some defaults database types, along with traits that
+//! can be implemented externally to let [`Wallet`]s use customized databases.
+//!
+//! It's important to note that the databases defined here only contains "blockchain-related" data.
+//! They can be seen more as a cache than a critical piece of storage that contains secrets and
+//! keys.
+//!
+//! The currently recommended database is [`sled`], which is a pretty simple key-value embedded
+//! database written in Rust. If the `key-value-db` feature is enabled (which by default is),
+//! this library automatically implements all the required traits for [`sled::Tree`].
+//!
+//! [`Wallet`]: crate::wallet::Wallet
+
+use bitcoin::hash_types::Txid;
+use bitcoin::{OutPoint, Script, Transaction, TxOut};
+
+use crate::error::Error;
+use crate::types::*;
+
+#[cfg(feature = "key-value-db")]
+pub(crate) mod keyvalue;
+
+pub mod memory;
+pub use memory::MemoryDatabase;
+
+/// Trait for operations that can be batched
+///
+/// This trait defines the list of operations that must be implemented on the [`Database`] type and
+/// the [`BatchDatabase::Batch`] type.
+pub trait BatchOperations {
+    /// Store a script_pubkey along with its script type and child number
+    fn set_script_pubkey(
+        &mut self,
+        script: &Script,
+        script_type: ScriptType,
+        child: u32,
+    ) -> Result<(), Error>;
+    /// Store a [`UTXO`]
+    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>;
+    /// Store a raw transaction
+    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>;
+    /// Store the metadata of a transaction
+    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>;
+    /// Store the last derivation index for a given script type
+    fn set_last_index(&mut self, script_type: ScriptType, value: u32) -> Result<(), Error>;
+
+    /// Delete a script_pubkey given the script type and its child number
+    fn del_script_pubkey_from_path(
+        &mut self,
+        script_type: ScriptType,
+        child: u32,
+    ) -> Result<Option<Script>, Error>;
+    /// Delete the data related to a specific script_pubkey, meaning the script type and the child
+    /// number
+    fn del_path_from_script_pubkey(
+        &mut self,
+        script: &Script,
+    ) -> Result<Option<(ScriptType, u32)>, Error>;
+    /// Delete a [`UTXO`] given its [`OutPoint`]
+    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>;
+    /// Delete a raw transaction given its [`Txid`]
+    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>;
+    /// Delete the metadata of a transaction and optionally the raw transaction itself
+    fn del_tx(
+        &mut self,
+        txid: &Txid,
+        include_raw: bool,
+    ) -> Result<Option<TransactionDetails>, Error>;
+    /// Delete the last derivation index for a script type
+    fn del_last_index(&mut self, script_type: ScriptType) -> Result<Option<u32>, Error>;
+}
+
+/// Trait for reading data from a database
+///
+/// This traits defines the operations that can be used to read data out of a database
+pub trait Database: BatchOperations {
+    /// Read and checks the descriptor checksum for a given script type
+    ///
+    /// Should return [`Error::ChecksumMismatch`](crate::error::Error::ChecksumMismatch) if the
+    /// checksum doesn't match. If there's no checksum in the database, simply store it for the
+    /// next time.
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        script_type: ScriptType,
+        bytes: B,
+    ) -> Result<(), Error>;
+
+    /// Return the list of script_pubkeys
+    fn iter_script_pubkeys(&self, script_type: Option<ScriptType>) -> Result<Vec<Script>, Error>;
+    /// Return the list of [`UTXO`]s
+    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>;
+    /// Return the list of raw transactions
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>;
+    /// Return the list of transactions metadata
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error>;
+
+    /// Fetch a script_pubkey given the script type and child number
+    fn get_script_pubkey_from_path(
+        &self,
+        script_type: ScriptType,
+        child: u32,
+    ) -> Result<Option<Script>, Error>;
+    /// Fetch the script type and child number of a given script_pubkey
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(ScriptType, u32)>, Error>;
+    /// Fetch a [`UTXO`] given its [`OutPoint`]
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>;
+    /// Fetch a raw transaction given its [`Txid`]
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
+    /// Fetch the transaction metadata and optionally also the raw transaction
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error>;
+    /// Return the last defivation index for a script type
+    fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error>;
+
+    /// Increment the last derivation index for a script type and returns it
+    ///
+    /// It should insert and return `0` if not present in the database
+    fn increment_last_index(&mut self, script_type: ScriptType) -> Result<u32, Error>;
+}
+
+/// Trait for a database that supports batch operations
+///
+/// This trait defines the methods to start and apply a batch of operations.
+pub trait BatchDatabase: Database {
+    /// Container for the operations
+    type Batch: BatchOperations;
+
+    /// Create a new batch container
+    fn begin_batch(&self) -> Self::Batch;
+    /// Consume and apply a batch of operations
+    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>;
+}
+
+pub(crate) trait DatabaseUtils: Database {
+    fn is_mine(&self, script: &Script) -> Result<bool, Error> {
+        self.get_path_from_script_pubkey(script)
+            .map(|o| o.is_some())
+    }
+
+    fn get_raw_tx_or<F>(&self, txid: &Txid, f: F) -> Result<Option<Transaction>, Error>
+    where
+        F: FnOnce() -> Result<Option<Transaction>, Error>,
+    {
+        self.get_tx(txid, true)?
+            .map(|t| t.transaction)
+            .flatten()
+            .map_or_else(f, |t| Ok(Some(t)))
+    }
+
+    fn get_previous_output(&self, outpoint: &OutPoint) -> Result<Option<TxOut>, Error> {
+        self.get_raw_tx(&outpoint.txid)?
+            .map(|previous_tx| {
+                if outpoint.vout as usize >= previous_tx.output.len() {
+                    Err(Error::InvalidOutpoint(outpoint.clone()))
+                } else {
+                    Ok(previous_tx.output[outpoint.vout as usize].clone())
+                }
+            })
+            .transpose()
+    }
+}
+
+impl<T: Database> DatabaseUtils for T {}
+
+#[cfg(test)]
+pub mod test {
+    use std::str::FromStr;
+
+    use bitcoin::consensus::encode::deserialize;
+    use bitcoin::hashes::hex::*;
+    use bitcoin::*;
+
+    use super::*;
+
+    pub fn test_script_pubkey<D: Database>(mut tree: D) {
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let script_type = ScriptType::External;
+
+        tree.set_script_pubkey(&script, script_type, path).unwrap();
+
+        assert_eq!(
+            tree.get_script_pubkey_from_path(script_type, path).unwrap(),
+            Some(script.clone())
+        );
+        assert_eq!(
+            tree.get_path_from_script_pubkey(&script).unwrap(),
+            Some((script_type, path.clone()))
+        );
+    }
+
+    pub fn test_batch_script_pubkey<D: BatchDatabase>(mut tree: D) {
+        let mut batch = tree.begin_batch();
+
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let script_type = ScriptType::External;
+
+        batch.set_script_pubkey(&script, script_type, path).unwrap();
+
+        assert_eq!(
+            tree.get_script_pubkey_from_path(script_type, path).unwrap(),
+            None
+        );
+        assert_eq!(tree.get_path_from_script_pubkey(&script).unwrap(), None);
+
+        tree.commit_batch(batch).unwrap();
+
+        assert_eq!(
+            tree.get_script_pubkey_from_path(script_type, path).unwrap(),
+            Some(script.clone())
+        );
+        assert_eq!(
+            tree.get_path_from_script_pubkey(&script).unwrap(),
+            Some((script_type, path.clone()))
+        );
+    }
+
+    pub fn test_iter_script_pubkey<D: Database>(mut tree: D) {
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let script_type = ScriptType::External;
+
+        tree.set_script_pubkey(&script, script_type, path).unwrap();
+
+        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
+    }
+
+    pub fn test_del_script_pubkey<D: Database>(mut tree: D) {
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let script_type = ScriptType::External;
+
+        tree.set_script_pubkey(&script, script_type, path).unwrap();
+        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
+
+        tree.del_script_pubkey_from_path(script_type, path).unwrap();
+        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 0);
+    }
+
+    pub fn test_utxo<D: Database>(mut tree: D) {
+        let outpoint = OutPoint::from_str(
+            "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0",
+        )
+        .unwrap();
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let txout = TxOut {
+            value: 133742,
+            script_pubkey: script,
+        };
+        let utxo = UTXO {
+            txout,
+            outpoint,
+            is_internal: false,
+        };
+
+        tree.set_utxo(&utxo).unwrap();
+
+        assert_eq!(tree.get_utxo(&outpoint).unwrap(), Some(utxo));
+    }
+
+    pub fn test_raw_tx<D: Database>(mut tree: D) {
+        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
+        let tx: Transaction = deserialize(&hex_tx).unwrap();
+
+        tree.set_raw_tx(&tx).unwrap();
+
+        let txid = tx.txid();
+
+        assert_eq!(tree.get_raw_tx(&txid).unwrap(), Some(tx));
+    }
+
+    pub fn test_tx<D: Database>(mut tree: D) {
+        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
+        let tx: Transaction = deserialize(&hex_tx).unwrap();
+        let txid = tx.txid();
+        let mut tx_details = TransactionDetails {
+            transaction: Some(tx),
+            txid,
+            timestamp: 123456,
+            received: 1337,
+            sent: 420420,
+            fees: 140,
+            height: Some(1000),
+        };
+
+        tree.set_tx(&tx_details).unwrap();
+
+        // get with raw tx too
+        assert_eq!(
+            tree.get_tx(&tx_details.txid, true).unwrap(),
+            Some(tx_details.clone())
+        );
+        // get only raw_tx
+        assert_eq!(
+            tree.get_raw_tx(&tx_details.txid).unwrap(),
+            tx_details.transaction
+        );
+
+        // now get without raw_tx
+        tx_details.transaction = None;
+        assert_eq!(
+            tree.get_tx(&tx_details.txid, false).unwrap(),
+            Some(tx_details)
+        );
+    }
+
+    pub fn test_last_index<D: Database>(mut tree: D) {
+        tree.set_last_index(ScriptType::External, 1337).unwrap();
+
+        assert_eq!(
+            tree.get_last_index(ScriptType::External).unwrap(),
+            Some(1337)
+        );
+        assert_eq!(tree.get_last_index(ScriptType::Internal).unwrap(), None);
+
+        let res = tree.increment_last_index(ScriptType::External).unwrap();
+        assert_eq!(res, 1338);
+        let res = tree.increment_last_index(ScriptType::Internal).unwrap();
+        assert_eq!(res, 0);
+
+        assert_eq!(
+            tree.get_last_index(ScriptType::External).unwrap(),
+            Some(1338)
+        );
+        assert_eq!(tree.get_last_index(ScriptType::Internal).unwrap(), Some(0));
+    }
+
+    // TODO: more tests...
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/checksum.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/checksum.rs.html new file mode 100644 index 0000000000..33f8d47a15 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/checksum.rs.html @@ -0,0 +1,191 @@ +checksum.rs.html -- source
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Descriptor checksum
+//!
+//! This module contains a re-implementation of the function used by Bitcoin Core to calculate the
+//! checksum of a descriptor
+
+use std::iter::FromIterator;
+
+use crate::descriptor::Error;
+
+const INPUT_CHARSET: &str =  "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
+const CHECKSUM_CHARSET: &str = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
+
+fn poly_mod(mut c: u64, val: u64) -> u64 {
+    let c0 = c >> 35;
+    c = ((c & 0x7ffffffff) << 5) ^ val;
+    if c0 & 1 > 0 {
+        c ^= 0xf5dee51989
+    };
+    if c0 & 2 > 0 {
+        c ^= 0xa9fdca3312
+    };
+    if c0 & 4 > 0 {
+        c ^= 0x1bab10e32d
+    };
+    if c0 & 8 > 0 {
+        c ^= 0x3706b1677a
+    };
+    if c0 & 16 > 0 {
+        c ^= 0x644d626ffd
+    };
+
+    c
+}
+
+/// Compute the checksum of a descriptor
+pub fn get_checksum(desc: &str) -> Result<String, Error> {
+    let mut c = 1;
+    let mut cls = 0;
+    let mut clscount = 0;
+    for ch in desc.chars() {
+        let pos = INPUT_CHARSET
+            .find(ch)
+            .ok_or(Error::InvalidDescriptorCharacter(ch))? as u64;
+        c = poly_mod(c, pos & 31);
+        cls = cls * 3 + (pos >> 5);
+        clscount += 1;
+        if clscount == 3 {
+            c = poly_mod(c, cls);
+            cls = 0;
+            clscount = 0;
+        }
+    }
+    if clscount > 0 {
+        c = poly_mod(c, cls);
+    }
+    (0..8).for_each(|_| c = poly_mod(c, 0));
+    c ^= 1;
+
+    let mut chars = Vec::with_capacity(8);
+    for j in 0..8 {
+        chars.push(
+            CHECKSUM_CHARSET
+                .chars()
+                .nth(((c >> (5 * (7 - j))) & 31) as usize)
+                .unwrap(),
+        );
+    }
+
+    Ok(String::from_iter(chars))
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/error.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/error.rs.html new file mode 100644 index 0000000000..78518b4f6b --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/error.rs.html @@ -0,0 +1,135 @@ +error.rs.html -- source
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Descriptor errors
+
+/// Errors related to the parsing and usage of descriptors
+#[derive(Debug)]
+pub enum Error {
+    InternalError,
+    InvalidPrefix(Vec<u8>),
+    HardenedDerivationOnXpub,
+    MalformedInput,
+    KeyParsingError(String),
+
+    Policy(crate::descriptor::policy::PolicyError),
+
+    InputIndexDoesntExist,
+    MissingPublicKey,
+    MissingDetails,
+
+    InvalidDescriptorCharacter(char),
+
+    CantDeriveWithMiniscript,
+
+    BIP32(bitcoin::util::bip32::Error),
+    Base58(bitcoin::util::base58::Error),
+    PK(bitcoin::util::key::Error),
+    Miniscript(miniscript::Error),
+    Hex(bitcoin::hashes::hex::Error),
+}
+
+impl std::fmt::Display for Error {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for Error {}
+
+impl_error!(bitcoin::util::bip32::Error, BIP32);
+impl_error!(bitcoin::util::base58::Error, Base58);
+impl_error!(bitcoin::util::key::Error, PK);
+impl_error!(miniscript::Error, Miniscript);
+impl_error!(bitcoin::hashes::hex::Error, Hex);
+impl_error!(crate::descriptor::policy::PolicyError, Policy);
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/mod.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/mod.rs.html new file mode 100644 index 0000000000..2e600ffa85 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/mod.rs.html @@ -0,0 +1,883 @@ +mod.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Descriptors
+//!
+//! This module contains generic utilities to work with descriptors, plus some re-exported types
+//! from [`miniscript`].
+
+use std::collections::{BTreeMap, HashMap};
+use std::fmt;
+use std::sync::Arc;
+
+use bitcoin::hashes::hash160;
+use bitcoin::secp256k1::Secp256k1;
+use bitcoin::util::bip32::{ChildNumber, DerivationPath, Fingerprint};
+use bitcoin::util::psbt;
+use bitcoin::{PublicKey, Script, TxOut};
+
+use miniscript::descriptor::{DescriptorPublicKey, DescriptorXKey, InnerXKey};
+pub use miniscript::{
+    Descriptor, Legacy, Miniscript, MiniscriptKey, ScriptContext, Segwitv0, Terminal, ToPublicKey,
+};
+
+pub mod checksum;
+pub mod error;
+pub mod policy;
+
+pub use self::checksum::get_checksum;
+use self::error::Error;
+pub use self::policy::Policy;
+use crate::wallet::signer::SignersContainer;
+
+/// Alias for a [`Descriptor`] that can contain extended keys using [`DescriptorPublicKey`]
+pub type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;
+
+/// Alias for the type of maps that represent derivation paths in a [`psbt::Input`] or
+/// [`psbt::Output`]
+///
+/// [`psbt::Input`]: bitcoin::util::psbt::Input
+/// [`psbt::Output`]: bitcoin::util::psbt::Output
+pub type HDKeyPaths = BTreeMap<PublicKey, (Fingerprint, DerivationPath)>;
+
+/// Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]
+pub trait ExtractPolicy {
+    fn extract_policy(
+        &self,
+        signers: Arc<SignersContainer<DescriptorPublicKey>>,
+    ) -> Result<Option<Policy>, Error>;
+}
+
+pub(crate) trait XKeyUtils {
+    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath;
+    fn root_fingerprint(&self) -> Fingerprint;
+}
+
+impl<K: InnerXKey> XKeyUtils for DescriptorXKey<K> {
+    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath {
+        let full_path = match &self.source {
+            &Some((_, ref path)) => path
+                .into_iter()
+                .chain(self.derivation_path.into_iter())
+                .cloned()
+                .collect(),
+            &None => self.derivation_path.clone(),
+        };
+
+        if self.is_wildcard {
+            full_path
+                .into_iter()
+                .chain(append.into_iter())
+                .cloned()
+                .collect()
+        } else {
+            full_path
+        }
+    }
+
+    fn root_fingerprint(&self) -> Fingerprint {
+        match &self.source {
+            &Some((fingerprint, _)) => fingerprint.clone(),
+            &None => self.xkey.xkey_fingerprint(),
+        }
+    }
+}
+
+pub(crate) trait DescriptorMeta: Sized {
+    fn is_witness(&self) -> bool;
+    fn get_hd_keypaths(&self, index: u32) -> Result<HDKeyPaths, Error>;
+    fn is_fixed(&self) -> bool;
+    fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths) -> Option<Self>;
+    fn derive_from_psbt_input(&self, psbt_input: &psbt::Input, utxo: Option<TxOut>)
+        -> Option<Self>;
+}
+
+pub(crate) trait DescriptorScripts {
+    fn psbt_redeem_script(&self) -> Option<Script>;
+    fn psbt_witness_script(&self) -> Option<Script>;
+}
+
+impl<T> DescriptorScripts for Descriptor<T>
+where
+    T: miniscript::MiniscriptKey + miniscript::ToPublicKey,
+{
+    fn psbt_redeem_script(&self) -> Option<Script> {
+        match self {
+            Descriptor::ShWpkh(_) => Some(self.witness_script()),
+            Descriptor::ShWsh(ref script) => Some(script.encode().to_v0_p2wsh()),
+            Descriptor::Sh(ref script) => Some(script.encode()),
+            Descriptor::Bare(ref script) => Some(script.encode()),
+            _ => None,
+        }
+    }
+
+    fn psbt_witness_script(&self) -> Option<Script> {
+        match self {
+            Descriptor::Wsh(ref script) => Some(script.encode()),
+            Descriptor::ShWsh(ref script) => Some(script.encode()),
+            _ => None,
+        }
+    }
+}
+
+impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
+    fn is_witness(&self) -> bool {
+        match self {
+            Descriptor::Bare(_) | Descriptor::Pk(_) | Descriptor::Pkh(_) | Descriptor::Sh(_) => {
+                false
+            }
+            Descriptor::Wpkh(_)
+            | Descriptor::ShWpkh(_)
+            | Descriptor::Wsh(_)
+            | Descriptor::ShWsh(_) => true,
+        }
+    }
+
+    fn get_hd_keypaths(&self, index: u32) -> Result<HDKeyPaths, Error> {
+        let mut answer = BTreeMap::new();
+
+        let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
+            match key {
+                DescriptorPublicKey::PubKey(_) => {}
+                DescriptorPublicKey::XPub(xpub) => {
+                    let derive_path = if xpub.is_wildcard {
+                        xpub.derivation_path
+                            .into_iter()
+                            .chain([ChildNumber::from_normal_idx(index)?].iter())
+                            .cloned()
+                            .collect()
+                    } else {
+                        xpub.derivation_path.clone()
+                    };
+                    let derived_pubkey = xpub
+                        .xkey
+                        .derive_pub(&Secp256k1::verification_only(), &derive_path)?;
+
+                    answer.insert(
+                        derived_pubkey.public_key,
+                        (
+                            xpub.root_fingerprint(),
+                            xpub.full_path(&[ChildNumber::from_normal_idx(index)?]),
+                        ),
+                    );
+                }
+            }
+
+            Ok(DummyKey::default())
+        };
+        let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
+
+        self.translate_pk(translatefpk, translatefpkh)?;
+
+        Ok(answer)
+    }
+
+    fn is_fixed(&self) -> bool {
+        let mut found_wildcard = false;
+
+        let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
+            match key {
+                DescriptorPublicKey::PubKey(_) => {}
+                DescriptorPublicKey::XPub(xpub) => {
+                    if xpub.is_wildcard {
+                        found_wildcard = true;
+                    }
+                }
+            }
+
+            Ok(DummyKey::default())
+        };
+        let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
+
+        self.translate_pk(translatefpk, translatefpkh).unwrap();
+
+        !found_wildcard
+    }
+
+    fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths) -> Option<Self> {
+        let index: HashMap<_, _> = hd_keypaths.values().cloned().collect();
+
+        let mut derive_path = None::<DerivationPath>;
+        let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
+            if derive_path.is_some() {
+                // already found a matching path, we are done
+                return Ok(DummyKey::default());
+            }
+
+            if let DescriptorPublicKey::XPub(xpub) = key {
+                // Check if the key matches one entry in our `index`. If it does, `matches()` will
+                // return the "prefix" that matched, so we remove that prefix from the full path
+                // found in `index` and save it in `derive_path`
+                let root_fingerprint = xpub.root_fingerprint();
+                derive_path = index
+                    .get_key_value(&root_fingerprint)
+                    .and_then(|(fingerprint, path)| xpub.matches(*fingerprint, path))
+                    .map(|prefix_path| prefix_path.into_iter().cloned().collect::<Vec<_>>())
+                    .map(|prefix| {
+                        index
+                            .get(&xpub.root_fingerprint())
+                            .unwrap()
+                            .into_iter()
+                            .skip(prefix.len())
+                            .cloned()
+                            .collect()
+                    });
+            }
+
+            Ok(DummyKey::default())
+        };
+        let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
+
+        self.translate_pk(translatefpk, translatefpkh).unwrap();
+
+        derive_path.map(|path| self.derive(path.as_ref()))
+    }
+
+    fn derive_from_psbt_input(
+        &self,
+        psbt_input: &psbt::Input,
+        utxo: Option<TxOut>,
+    ) -> Option<Self> {
+        if let Some(derived) = self.derive_from_hd_keypaths(&psbt_input.hd_keypaths) {
+            return Some(derived);
+        } else if !self.is_fixed() {
+            // If the descriptor is not fixed we can't brute-force the derivation address, so just
+            // exit here
+            return None;
+        }
+
+        match self {
+            Descriptor::Pk(_)
+            | Descriptor::Pkh(_)
+            | Descriptor::Wpkh(_)
+            | Descriptor::ShWpkh(_)
+                if utxo.is_some()
+                    && self.script_pubkey() == utxo.as_ref().unwrap().script_pubkey =>
+            {
+                Some(self.clone())
+            }
+            Descriptor::Bare(ms) | Descriptor::Sh(ms)
+                if psbt_input.redeem_script.is_some()
+                    && &ms.encode() == psbt_input.redeem_script.as_ref().unwrap() =>
+            {
+                Some(self.clone())
+            }
+            Descriptor::Wsh(ms) | Descriptor::ShWsh(ms)
+                if psbt_input.witness_script.is_some()
+                    && &ms.encode() == psbt_input.witness_script.as_ref().unwrap() =>
+            {
+                Some(self.clone())
+            }
+            _ => None,
+        }
+    }
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Eq, Ord, Default)]
+struct DummyKey();
+
+impl fmt::Display for DummyKey {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "DummyKey")
+    }
+}
+
+impl std::str::FromStr for DummyKey {
+    type Err = ();
+
+    fn from_str(_: &str) -> Result<Self, Self::Err> {
+        Ok(DummyKey::default())
+    }
+}
+
+impl miniscript::MiniscriptKey for DummyKey {
+    type Hash = DummyKey;
+
+    fn to_pubkeyhash(&self) -> DummyKey {
+        DummyKey::default()
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::consensus::encode::deserialize;
+    use bitcoin::hashes::hex::FromHex;
+    use bitcoin::util::psbt;
+
+    use super::*;
+    use crate::psbt::PSBTUtils;
+
+    #[test]
+    fn test_derive_from_psbt_input_wpkh_wif() {
+        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
+            "wpkh(02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737)",
+        )
+        .unwrap();
+        let psbt: psbt::PartiallySignedTransaction = deserialize(
+            &Vec::<u8>::from_hex(
+                "70736274ff010052010000000162307be8e431fbaff807cdf9cdc3fde44d7402\
+                 11bc8342c31ffd6ec11fe35bcc0100000000ffffffff01328601000000000016\
+                 001493ce48570b55c42c2af816aeaba06cfee1224fae000000000001011fa086\
+                 01000000000016001493ce48570b55c42c2af816aeaba06cfee1224fae010304\
+                 010000000000",
+            )
+            .unwrap(),
+        )
+        .unwrap();
+
+        assert!(descriptor
+            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0))
+            .is_some());
+    }
+
+    #[test]
+    fn test_derive_from_psbt_input_pkh_tpub() {
+        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
+            "pkh([0f056943/44h/0h/0h]tpubDDpWvmUrPZrhSPmUzCMBHffvC3HyMAPnWDSAQNBTnj1iZeJa7BZQEttFiP4DS4GCcXQHezdXhn86Hj6LHX5EDstXPWrMaSneRWM8yUf6NFd/10/*)",
+        )
+        .unwrap();
+        let psbt: psbt::PartiallySignedTransaction = deserialize(
+            &Vec::<u8>::from_hex(
+                "70736274ff010053010000000145843b86be54a3cd8c9e38444e1162676c00df\
+                 e7964122a70df491ea12fd67090100000000ffffffff01c19598000000000017\
+                 a91432bb94283282f72b2e034709e348c44d5a4db0ef8700000000000100f902\
+                 0000000001010167e99c0eb67640f3a1b6805f2d8be8238c947f8aaf49eb0a9c\
+                 bee6a42c984200000000171600142b29a22019cca05b9c2b2d283a4c4489e1cf\
+                 9f8ffeffffff02a01dced06100000017a914e2abf033cadbd74f0f4c74946201\
+                 decd20d5c43c8780969800000000001976a9148b0fce5fb1264e599a65387313\
+                 3c95478b902eb288ac02473044022015d9211576163fa5b001e84dfa3d44efd9\
+                 86b8f3a0d3d2174369288b2b750906022048dacc0e5d73ae42512fd2b97e2071\
+                 a8d0bce443b390b1fe0b8128fe70ec919e01210232dad1c5a67dcb0116d407e2\
+                 52584228ab7ec00e8b9779d0c3ffe8114fc1a7d2c80600000103040100000022\
+                 0603433b83583f8c4879b329dd08bbc7da935e4cc02f637ff746e05f0466ffb2\
+                 a6a2180f0569432c00008000000080000000800a000000000000000000",
+            )
+            .unwrap(),
+        )
+        .unwrap();
+
+        assert!(descriptor
+            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0))
+            .is_some());
+    }
+
+    #[test]
+    fn test_derive_from_psbt_input_wsh() {
+        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
+            "wsh(and_v(v:pk(03b6633fef2397a0a9de9d7b6f23aef8368a6e362b0581f0f0af70d5ecfd254b14),older(6)))",
+        )
+        .unwrap();
+        let psbt: psbt::PartiallySignedTransaction = deserialize(
+            &Vec::<u8>::from_hex(
+                "70736274ff01005302000000011c8116eea34408ab6529223c9a176606742207\
+                 67a1ff1d46a6e3c4a88243ea6e01000000000600000001109698000000000017\
+                 a914ad105f61102e0d01d7af40d06d6a5c3ae2f7fde387000000000001012b80\
+                 969800000000002200203ca72f106a72234754890ca7640c43f65d2174e44d33\
+                 336030f9059345091044010304010000000105252103b6633fef2397a0a9de9d\
+                 7b6f23aef8368a6e362b0581f0f0af70d5ecfd254b14ad56b20000",
+            )
+            .unwrap(),
+        )
+        .unwrap();
+
+        assert!(descriptor
+            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0))
+            .is_some());
+    }
+
+    #[test]
+    fn test_derive_from_psbt_input_sh() {
+        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
+            "sh(and_v(v:pk(021403881a5587297818fcaf17d239cefca22fce84a45b3b1d23e836c4af671dbb),after(630000)))",
+        )
+        .unwrap();
+        let psbt: psbt::PartiallySignedTransaction = deserialize(
+            &Vec::<u8>::from_hex(
+                "70736274ff0100530100000001bc8c13df445dfadcc42afa6dc841f85d22b01d\
+                 a6270ebf981740f4b7b1d800390000000000feffffff01ba9598000000000017\
+                 a91457b148ba4d3e5fa8608a8657875124e3d1c9390887f09c0900000100e002\
+                 0000000001016ba1bbe05cc93574a0d611ec7d93ad0ab6685b28d0cd80e8a82d\
+                 debb326643c90100000000feffffff02809698000000000017a914d9a6e8c455\
+                 8e16c8253afe53ce37ad61cf4c38c487403504cf6100000017a9144044fb6e0b\
+                 757dfc1b34886b6a95aef4d3db137e870247304402202a9b72d939bcde8ba2a1\
+                 e0980597e47af4f5c152a78499143c3d0a78ac2286a602207a45b1df9e93b8c9\
+                 6f09f5c025fe3e413ca4b905fe65ee55d32a3276439a9b8f012102dc1fcc2636\
+                 4da1aa718f03d8d9bd6f2ff410ed2cf1245a168aa3bcc995ac18e0a806000001\
+                 03040100000001042821021403881a5587297818fcaf17d239cefca22fce84a4\
+                 5b3b1d23e836c4af671dbbad03f09c09b10000",
+            )
+            .unwrap(),
+        )
+        .unwrap();
+
+        assert!(descriptor
+            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0))
+            .is_some());
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/policy.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/policy.rs.html new file mode 100644 index 0000000000..b094837b39 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/policy.rs.html @@ -0,0 +1,1593 @@ +policy.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Descriptor policy
+//!
+//! This module implements the logic to extract and represent the spending policies of a descriptor
+//! in a more human-readable format.
+//!
+//! ## Example
+//!
+//! ```
+//! # use std::sync::Arc;
+//! # use bdk::descriptor::*;
+//! let desc = "wsh(and_v(v:pk(cV3oCth6zxZ1UVsHLnGothsWNsaoxRhC6aeNi5VbSdFpwUkgkEci),or_d(pk(cVMTy7uebJgvFaSBwcgvwk8qn8xSLc97dKow4MBetjrrahZoimm2),older(12960))))";
+//!
+//! let (extended_desc, key_map) = ExtendedDescriptor::parse_secret(desc)?;
+//! println!("{:?}", extended_desc);
+//!
+//! let signers = Arc::new(key_map.into());
+//! let policy = extended_desc.extract_policy(signers)?;
+//! println!("policy: {}", serde_json::to_string(&policy)?);
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::cmp::max;
+use std::collections::{BTreeMap, HashSet, VecDeque};
+use std::fmt;
+use std::sync::Arc;
+
+use serde::ser::SerializeMap;
+use serde::{Serialize, Serializer};
+
+use bitcoin::hashes::*;
+use bitcoin::util::bip32::Fingerprint;
+use bitcoin::PublicKey;
+
+use miniscript::descriptor::DescriptorPublicKey;
+use miniscript::{Descriptor, Miniscript, MiniscriptKey, ScriptContext, Terminal};
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use crate::descriptor::ExtractPolicy;
+use crate::wallet::signer::{SignerId, SignersContainer};
+
+use super::checksum::get_checksum;
+use super::error::Error;
+use super::XKeyUtils;
+
+/// Raw public key or extended key fingerprint
+#[derive(Debug, Clone, Default, Serialize)]
+pub struct PKOrF {
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pubkey: Option<PublicKey>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pubkey_hash: Option<hash160::Hash>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    fingerprint: Option<Fingerprint>,
+}
+
+impl PKOrF {
+    fn from_key(k: &DescriptorPublicKey) -> Self {
+        match k {
+            DescriptorPublicKey::PubKey(pubkey) => PKOrF {
+                pubkey: Some(*pubkey),
+                ..Default::default()
+            },
+            DescriptorPublicKey::XPub(xpub) => PKOrF {
+                fingerprint: Some(xpub.root_fingerprint()),
+                ..Default::default()
+            },
+        }
+    }
+
+    fn from_key_hash(k: hash160::Hash) -> Self {
+        PKOrF {
+            pubkey_hash: Some(k),
+            ..Default::default()
+        }
+    }
+}
+
+/// An item that need to be satisfied
+#[derive(Debug, Clone, Serialize)]
+#[serde(tag = "type", rename_all = "UPPERCASE")]
+pub enum SatisfiableItem {
+    // Leaves
+    Signature(PKOrF),
+    SignatureKey(PKOrF),
+    SHA256Preimage {
+        hash: sha256::Hash,
+    },
+    HASH256Preimage {
+        hash: sha256d::Hash,
+    },
+    RIPEMD160Preimage {
+        hash: ripemd160::Hash,
+    },
+    HASH160Preimage {
+        hash: hash160::Hash,
+    },
+    AbsoluteTimelock {
+        value: u32,
+    },
+    RelativeTimelock {
+        value: u32,
+    },
+
+    // Complex item
+    Thresh {
+        items: Vec<Policy>,
+        threshold: usize,
+    },
+    Multisig {
+        keys: Vec<PKOrF>,
+        threshold: usize,
+    },
+}
+
+impl SatisfiableItem {
+    pub fn is_leaf(&self) -> bool {
+        match self {
+            SatisfiableItem::Thresh {
+                items: _,
+                threshold: _,
+            } => false,
+            _ => true,
+        }
+    }
+
+    pub fn id(&self) -> String {
+        get_checksum(&serde_json::to_string(self).expect("Failed to serialize a SatisfiableItem"))
+            .expect("Failed to compute a SatisfiableItem id")
+    }
+}
+
+fn combinations(vec: &Vec<usize>, size: usize) -> Vec<Vec<usize>> {
+    assert!(vec.len() >= size);
+
+    let mut answer = Vec::new();
+
+    let mut queue = VecDeque::new();
+    for (index, val) in vec.iter().enumerate() {
+        let mut new_vec = Vec::with_capacity(size);
+        new_vec.push(*val);
+        queue.push_back((index, new_vec));
+    }
+
+    while let Some((index, vals)) = queue.pop_front() {
+        if vals.len() >= size {
+            answer.push(vals);
+        } else {
+            for (new_index, val) in vec.iter().skip(index + 1).enumerate() {
+                let mut cloned = vals.clone();
+                cloned.push(*val);
+                queue.push_front((new_index, cloned));
+            }
+        }
+    }
+
+    answer
+}
+
+fn mix<T: Clone>(vec: Vec<Vec<T>>) -> Vec<Vec<T>> {
+    if vec.is_empty() || vec.iter().any(Vec::is_empty) {
+        return vec![];
+    }
+
+    let mut answer = Vec::new();
+    let size = vec.len();
+
+    let mut queue = VecDeque::new();
+    for i in &vec[0] {
+        let mut new_vec = Vec::with_capacity(size);
+        new_vec.push(i.clone());
+        queue.push_back(new_vec);
+    }
+
+    while let Some(vals) = queue.pop_front() {
+        if vals.len() >= size {
+            answer.push(vals);
+        } else {
+            let level = vals.len();
+            for i in &vec[level] {
+                let mut cloned = vals.clone();
+                cloned.push(i.clone());
+                queue.push_front(cloned);
+            }
+        }
+    }
+
+    answer
+}
+
+pub type ConditionMap = BTreeMap<usize, HashSet<Condition>>;
+pub type FoldedConditionMap = BTreeMap<Vec<usize>, HashSet<Condition>>;
+
+fn serialize_folded_cond_map<S>(
+    input_map: &FoldedConditionMap,
+    serializer: S,
+) -> Result<S::Ok, S::Error>
+where
+    S: Serializer,
+{
+    let mut map = serializer.serialize_map(Some(input_map.len()))?;
+    for (k, v) in input_map {
+        let k_string = format!("{:?}", k);
+        map.serialize_entry(&k_string, v)?;
+    }
+    map.end()
+}
+
+/// Represent if and how much a policy item is satisfied by the wallet's descriptor
+#[derive(Debug, Clone, Serialize)]
+#[serde(tag = "type", rename_all = "UPPERCASE")]
+pub enum Satisfaction {
+    /// Only a partial satisfaction of some kind of threshold policy
+    Partial {
+        /// Total number of items
+        n: usize,
+        /// Threshold
+        m: usize,
+        /// The items that can be satisfied by the descriptor
+        items: Vec<usize>,
+        #[serde(skip_serializing_if = "BTreeMap::is_empty")]
+        /// Extra conditions that also need to be satisfied
+        conditions: ConditionMap,
+    },
+    /// Can reach the threshold of some kind of threshold policy
+    PartialComplete {
+        /// Total number of items
+        n: usize,
+        /// Threshold
+        m: usize,
+        /// The items that can be satisfied by the descriptor
+        items: Vec<usize>,
+        #[serde(
+            serialize_with = "serialize_folded_cond_map",
+            skip_serializing_if = "BTreeMap::is_empty"
+        )]
+        /// Extra conditions that also need to be satisfied
+        conditions: FoldedConditionMap,
+    },
+
+    /// Can satisfy the policy item
+    Complete {
+        /// Extra conditions that also need to be satisfied
+        condition: Condition,
+    },
+    /// Cannot satisfy or contribute to the policy item
+    None,
+}
+
+impl Satisfaction {
+    pub fn is_leaf(&self) -> bool {
+        match self {
+            Satisfaction::None | Satisfaction::Complete { .. } => true,
+            Satisfaction::PartialComplete { .. } | Satisfaction::Partial { .. } => false,
+        }
+    }
+
+    // add `inner` as one of self's partial items. this only makes sense on partials
+    fn add(&mut self, inner: &Satisfaction, inner_index: usize) -> Result<(), PolicyError> {
+        match self {
+            Satisfaction::None | Satisfaction::Complete { .. } => Err(PolicyError::AddOnLeaf),
+            Satisfaction::PartialComplete { .. } => Err(PolicyError::AddOnPartialComplete),
+            Satisfaction::Partial {
+                n,
+                ref mut conditions,
+                ref mut items,
+                ..
+            } => {
+                if inner_index >= *n || items.contains(&inner_index) {
+                    return Err(PolicyError::IndexOutOfRange(inner_index));
+                }
+
+                match inner {
+                    // not relevant if not completed yet
+                    Satisfaction::None | Satisfaction::Partial { .. } => return Ok(()),
+                    Satisfaction::Complete { condition } => {
+                        items.push(inner_index);
+                        conditions.insert(inner_index, vec![*condition].into_iter().collect());
+                    }
+                    Satisfaction::PartialComplete {
+                        conditions: other_conditions,
+                        ..
+                    } => {
+                        items.push(inner_index);
+                        let conditions_set = other_conditions
+                            .values()
+                            .fold(HashSet::new(), |set, i| set.union(&i).cloned().collect());
+                        conditions.insert(inner_index, conditions_set);
+                    }
+                }
+
+                Ok(())
+            }
+        }
+    }
+
+    fn finalize(&mut self) -> Result<(), PolicyError> {
+        // if partial try to bump it to a partialcomplete
+        if let Satisfaction::Partial {
+            n,
+            m,
+            items,
+            conditions,
+        } = self
+        {
+            if items.len() >= *m {
+                let mut map = BTreeMap::new();
+                let indexes = combinations(items, *m);
+                // `indexes` at this point is a Vec<Vec<usize>>, with the "n choose k" of items (m of n)
+                indexes
+                    .into_iter()
+                    // .inspect(|x| println!("--- orig --- {:?}", x))
+                    // we map each of the combinations of elements into a tuple of ([choosen items], [conditions]). unfortunately, those items have potentially more than one
+                    // condition (think about ORs), so we also use `mix` to expand those, i.e. [[0], [1, 2]] becomes [[0, 1], [0, 2]]. This is necessary to make sure that we
+                    // consider every possibile options and check whether or not they are compatible.
+                    .map(|i_vec| {
+                        mix(i_vec
+                            .iter()
+                            .map(|i| {
+                                conditions
+                                    .get(i)
+                                    .and_then(|set| Some(set.clone().into_iter().collect()))
+                                    .unwrap_or(vec![])
+                            })
+                            .collect())
+                        .into_iter()
+                        .map(|x| (i_vec.clone(), x))
+                        .collect::<Vec<(Vec<usize>, Vec<Condition>)>>()
+                    })
+                    // .inspect(|x: &Vec<(Vec<usize>, Vec<Condition>)>| println!("fetch {:?}", x))
+                    // since the previous step can turn one item of the iterator into multiple ones, we call flatten to expand them out
+                    .flatten()
+                    // .inspect(|x| println!("flat {:?}", x))
+                    // try to fold all the conditions for this specific combination of indexes/options. if they are not compatibile, try_fold will be Err
+                    .map(|(key, val)| {
+                        (
+                            key,
+                            val.into_iter()
+                                .try_fold(Condition::default(), |acc, v| acc.merge(&v)),
+                        )
+                    })
+                    // .inspect(|x| println!("try_fold {:?}", x))
+                    // filter out all the incompatible combinations
+                    .filter(|(_, val)| val.is_ok())
+                    // .inspect(|x| println!("filter {:?}", x))
+                    // push them into the map
+                    .for_each(|(key, val)| {
+                        map.entry(key)
+                            .or_insert_with(HashSet::new)
+                            .insert(val.unwrap());
+                    });
+                // TODO: if the map is empty, the conditions are not compatible, return an error?
+                *self = Satisfaction::PartialComplete {
+                    n: *n,
+                    m: *m,
+                    items: items.clone(),
+                    conditions: map,
+                };
+            }
+        }
+
+        Ok(())
+    }
+}
+
+impl From<bool> for Satisfaction {
+    fn from(other: bool) -> Self {
+        if other {
+            Satisfaction::Complete {
+                condition: Default::default(),
+            }
+        } else {
+            Satisfaction::None
+        }
+    }
+}
+
+/// Descriptor spending policy
+#[derive(Debug, Clone, Serialize)]
+pub struct Policy {
+    /// Identifier for this policy node
+    pub id: String,
+
+    /// Type of this policy node
+    #[serde(flatten)]
+    pub item: SatisfiableItem,
+    /// How a much given PSBT already satisfies this polcy node **(currently unused)**
+    pub satisfaction: Satisfaction,
+    /// How the wallet's descriptor can satisfy this policy node
+    pub contribution: Satisfaction,
+}
+
+/// An extra condition that must be satisfied but that is out of control of the user
+#[derive(Hash, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default, Serialize)]
+pub struct Condition {
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub csv: Option<u32>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub timelock: Option<u32>,
+}
+
+impl Condition {
+    fn merge_timelock(a: u32, b: u32) -> Result<u32, PolicyError> {
+        const BLOCKS_TIMELOCK_THRESHOLD: u32 = 500000000;
+
+        if (a < BLOCKS_TIMELOCK_THRESHOLD) != (b < BLOCKS_TIMELOCK_THRESHOLD) {
+            Err(PolicyError::MixedTimelockUnits)
+        } else {
+            Ok(max(a, b))
+        }
+    }
+
+    fn merge(mut self, other: &Condition) -> Result<Self, PolicyError> {
+        match (self.csv, other.csv) {
+            (Some(a), Some(b)) => self.csv = Some(Self::merge_timelock(a, b)?),
+            (None, any) => self.csv = any,
+            _ => {}
+        }
+
+        match (self.timelock, other.timelock) {
+            (Some(a), Some(b)) => self.timelock = Some(Self::merge_timelock(a, b)?),
+            (None, any) => self.timelock = any,
+            _ => {}
+        }
+
+        Ok(self)
+    }
+
+    pub fn is_null(&self) -> bool {
+        self.csv.is_none() && self.timelock.is_none()
+    }
+}
+
+/// Errors that can happen while extracting and manipulating policies
+#[derive(Debug)]
+pub enum PolicyError {
+    NotEnoughItemsSelected(String),
+    TooManyItemsSelected(String),
+    IndexOutOfRange(usize),
+    AddOnLeaf,
+    AddOnPartialComplete,
+    MixedTimelockUnits,
+    IncompatibleConditions,
+}
+
+impl fmt::Display for PolicyError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for PolicyError {}
+
+impl Policy {
+    fn new(item: SatisfiableItem) -> Self {
+        Policy {
+            id: item.id(),
+            item,
+            satisfaction: Satisfaction::None,
+            contribution: Satisfaction::None,
+        }
+    }
+
+    fn make_and(a: Option<Policy>, b: Option<Policy>) -> Result<Option<Policy>, PolicyError> {
+        match (a, b) {
+            (None, None) => Ok(None),
+            (Some(x), None) | (None, Some(x)) => Ok(Some(x)),
+            (Some(a), Some(b)) => Self::make_thresh(vec![a, b], 2),
+        }
+    }
+
+    fn make_or(a: Option<Policy>, b: Option<Policy>) -> Result<Option<Policy>, PolicyError> {
+        match (a, b) {
+            (None, None) => Ok(None),
+            (Some(x), None) | (None, Some(x)) => Ok(Some(x)),
+            (Some(a), Some(b)) => Self::make_thresh(vec![a, b], 1),
+        }
+    }
+
+    fn make_thresh(items: Vec<Policy>, threshold: usize) -> Result<Option<Policy>, PolicyError> {
+        if threshold == 0 {
+            return Ok(None);
+        }
+
+        let mut contribution = Satisfaction::Partial {
+            n: items.len(),
+            m: threshold,
+            items: vec![],
+            conditions: Default::default(),
+        };
+        for (index, item) in items.iter().enumerate() {
+            contribution.add(&item.contribution, index)?;
+        }
+        contribution.finalize()?;
+
+        let mut policy: Policy = SatisfiableItem::Thresh { items, threshold }.into();
+        policy.contribution = contribution;
+
+        Ok(Some(policy))
+    }
+
+    fn make_multisig(
+        keys: &Vec<DescriptorPublicKey>,
+        signers: Arc<SignersContainer<DescriptorPublicKey>>,
+        threshold: usize,
+    ) -> Result<Option<Policy>, PolicyError> {
+        if threshold == 0 {
+            return Ok(None);
+        }
+
+        let parsed_keys = keys.iter().map(|k| PKOrF::from_key(k)).collect();
+
+        let mut contribution = Satisfaction::Partial {
+            n: keys.len(),
+            m: threshold,
+            items: vec![],
+            conditions: Default::default(),
+        };
+        for (index, key) in keys.iter().enumerate() {
+            if let Some(_) = signers.find(signer_id(key)) {
+                contribution.add(
+                    &Satisfaction::Complete {
+                        condition: Default::default(),
+                    },
+                    index,
+                )?;
+            }
+        }
+        contribution.finalize()?;
+
+        let mut policy: Policy = SatisfiableItem::Multisig {
+            keys: parsed_keys,
+            threshold,
+        }
+        .into();
+        policy.contribution = contribution;
+
+        Ok(Some(policy))
+    }
+
+    /// Return whether or not a specific path in the policy tree is required to unambiguously
+    /// create a transaction
+    ///
+    /// What this means is that for some spending policies the user should select which paths in
+    /// the tree it intends to satisfy while signing, because the transaction must be created differently based
+    /// on that.
+    pub fn requires_path(&self) -> bool {
+        self.get_condition(&BTreeMap::new()).is_err()
+    }
+
+    /// Return the conditions that are set by the spending policy for a given path in the
+    /// policy tree
+    pub fn get_condition(
+        &self,
+        path: &BTreeMap<String, Vec<usize>>,
+    ) -> Result<Condition, PolicyError> {
+        // if items.len() == threshold, selected can be omitted and we take all of them by default
+        let default = match &self.item {
+            SatisfiableItem::Thresh { items, threshold } if items.len() == *threshold => {
+                (0..*threshold).into_iter().collect()
+            }
+            _ => vec![],
+        };
+        let selected = match path.get(&self.id) {
+            _ if !default.is_empty() => &default,
+            Some(arr) => arr,
+            _ => &default,
+        };
+
+        match &self.item {
+            SatisfiableItem::Thresh { items, threshold } => {
+                let mapped_req = items
+                    .iter()
+                    .map(|i| i.get_condition(path))
+                    .collect::<Result<Vec<_>, _>>()?;
+
+                // if all the requirements are null we don't care about `selected` because there
+                // are no requirements
+                if mapped_req.iter().all(Condition::is_null) {
+                    return Ok(Condition::default());
+                }
+
+                // if we have something, make sure we have enough items. note that the user can set
+                // an empty value for this step in case of n-of-n, because `selected` is set to all
+                // the elements above
+                if selected.len() < *threshold {
+                    return Err(PolicyError::NotEnoughItemsSelected(self.id.clone()));
+                } else if selected.len() > *threshold {
+                    return Err(PolicyError::TooManyItemsSelected(self.id.clone()));
+                }
+
+                // check the selected items, see if there are conflicting requirements
+                let mut requirements = Condition::default();
+                for item_index in selected {
+                    requirements = requirements.merge(
+                        mapped_req
+                            .get(*item_index)
+                            .ok_or(PolicyError::IndexOutOfRange(*item_index))?,
+                    )?;
+                }
+
+                Ok(requirements)
+            }
+            _ if !selected.is_empty() => Err(PolicyError::TooManyItemsSelected(self.id.clone())),
+            SatisfiableItem::AbsoluteTimelock { value } => Ok(Condition {
+                csv: None,
+                timelock: Some(*value),
+            }),
+            SatisfiableItem::RelativeTimelock { value } => Ok(Condition {
+                csv: Some(*value),
+                timelock: None,
+            }),
+            _ => Ok(Condition::default()),
+        }
+    }
+}
+
+impl From<SatisfiableItem> for Policy {
+    fn from(other: SatisfiableItem) -> Self {
+        Self::new(other)
+    }
+}
+
+fn signer_id(key: &DescriptorPublicKey) -> SignerId<DescriptorPublicKey> {
+    match key {
+        DescriptorPublicKey::PubKey(pubkey) => pubkey.to_pubkeyhash().into(),
+        DescriptorPublicKey::XPub(xpub) => xpub.root_fingerprint().into(),
+    }
+}
+
+fn signature(
+    key: &DescriptorPublicKey,
+    signers: Arc<SignersContainer<DescriptorPublicKey>>,
+) -> Policy {
+    let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key(key)).into();
+
+    policy.contribution = if signers.find(signer_id(key)).is_some() {
+        Satisfaction::Complete {
+            condition: Default::default(),
+        }
+    } else {
+        Satisfaction::None
+    };
+
+    policy
+}
+
+fn signature_key(
+    key_hash: &<DescriptorPublicKey as MiniscriptKey>::Hash,
+    signers: Arc<SignersContainer<DescriptorPublicKey>>,
+) -> Policy {
+    let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key_hash(*key_hash)).into();
+
+    if let Some(_) = signers.find(SignerId::PkHash(*key_hash)) {
+        policy.contribution = Satisfaction::Complete {
+            condition: Default::default(),
+        }
+    }
+
+    policy
+}
+
+impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx> {
+    fn extract_policy(
+        &self,
+        signers: Arc<SignersContainer<DescriptorPublicKey>>,
+    ) -> Result<Option<Policy>, Error> {
+        Ok(match &self.node {
+            // Leaves
+            Terminal::True | Terminal::False => None,
+            Terminal::PkK(pubkey) => Some(signature(pubkey, Arc::clone(&signers))),
+            Terminal::PkH(pubkey_hash) => Some(signature_key(pubkey_hash, Arc::clone(&signers))),
+            Terminal::After(value) => {
+                let mut policy: Policy = SatisfiableItem::AbsoluteTimelock { value: *value }.into();
+                policy.contribution = Satisfaction::Complete {
+                    condition: Condition {
+                        timelock: Some(*value),
+                        csv: None,
+                    },
+                };
+
+                Some(policy)
+            }
+            Terminal::Older(value) => {
+                let mut policy: Policy = SatisfiableItem::RelativeTimelock { value: *value }.into();
+                policy.contribution = Satisfaction::Complete {
+                    condition: Condition {
+                        timelock: None,
+                        csv: Some(*value),
+                    },
+                };
+
+                Some(policy)
+            }
+            Terminal::Sha256(hash) => Some(SatisfiableItem::SHA256Preimage { hash: *hash }.into()),
+            Terminal::Hash256(hash) => {
+                Some(SatisfiableItem::HASH256Preimage { hash: *hash }.into())
+            }
+            Terminal::Ripemd160(hash) => {
+                Some(SatisfiableItem::RIPEMD160Preimage { hash: *hash }.into())
+            }
+            Terminal::Hash160(hash) => {
+                Some(SatisfiableItem::HASH160Preimage { hash: *hash }.into())
+            }
+            Terminal::Multi(k, pks) => Policy::make_multisig(pks, Arc::clone(&signers), *k)?,
+            // Identities
+            Terminal::Alt(inner)
+            | Terminal::Swap(inner)
+            | Terminal::Check(inner)
+            | Terminal::DupIf(inner)
+            | Terminal::Verify(inner)
+            | Terminal::NonZero(inner)
+            | Terminal::ZeroNotEqual(inner) => inner.extract_policy(Arc::clone(&signers))?,
+            // Complex policies
+            Terminal::AndV(a, b) | Terminal::AndB(a, b) => Policy::make_and(
+                a.extract_policy(Arc::clone(&signers))?,
+                b.extract_policy(Arc::clone(&signers))?,
+            )?,
+            Terminal::AndOr(x, y, z) => Policy::make_or(
+                Policy::make_and(
+                    x.extract_policy(Arc::clone(&signers))?,
+                    y.extract_policy(Arc::clone(&signers))?,
+                )?,
+                z.extract_policy(Arc::clone(&signers))?,
+            )?,
+            Terminal::OrB(a, b)
+            | Terminal::OrD(a, b)
+            | Terminal::OrC(a, b)
+            | Terminal::OrI(a, b) => Policy::make_or(
+                a.extract_policy(Arc::clone(&signers))?,
+                b.extract_policy(Arc::clone(&signers))?,
+            )?,
+            Terminal::Thresh(k, nodes) => {
+                let mut threshold = *k;
+                let mapped: Vec<_> = nodes
+                    .iter()
+                    .map(|n| n.extract_policy(Arc::clone(&signers)))
+                    .collect::<Result<Vec<_>, _>>()?
+                    .into_iter()
+                    .filter_map(|x| x)
+                    .collect();
+
+                if mapped.len() < nodes.len() {
+                    threshold = match threshold.checked_sub(nodes.len() - mapped.len()) {
+                        None => return Ok(None),
+                        Some(x) => x,
+                    };
+                }
+
+                Policy::make_thresh(mapped, threshold)?
+            }
+        })
+    }
+}
+
+impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
+    fn extract_policy(
+        &self,
+        signers: Arc<SignersContainer<DescriptorPublicKey>>,
+    ) -> Result<Option<Policy>, Error> {
+        match self {
+            Descriptor::Pk(pubkey)
+            | Descriptor::Pkh(pubkey)
+            | Descriptor::Wpkh(pubkey)
+            | Descriptor::ShWpkh(pubkey) => Ok(Some(signature(pubkey, signers))),
+            Descriptor::Bare(inner) | Descriptor::Sh(inner) => Ok(inner.extract_policy(signers)?),
+            Descriptor::Wsh(inner) | Descriptor::ShWsh(inner) => Ok(inner.extract_policy(signers)?),
+        }
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/error.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/error.rs.html new file mode 100644 index 0000000000..930ba161c0 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/error.rs.html @@ -0,0 +1,283 @@ +error.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::fmt;
+
+use bitcoin::{Address, OutPoint};
+
+/// Errors that can be thrown by the [`Wallet`](crate::wallet::Wallet)
+#[derive(Debug)]
+pub enum Error {
+    KeyMismatch(bitcoin::secp256k1::PublicKey, bitcoin::secp256k1::PublicKey),
+    MissingInputUTXO(usize),
+    InvalidU32Bytes(Vec<u8>),
+    Generic(String),
+    ScriptDoesntHaveAddressForm,
+    SendAllMultipleOutputs,
+    NoAddressees,
+    OutputBelowDustLimit(usize),
+    InsufficientFunds,
+    InvalidAddressNetwork(Address),
+    UnknownUTXO,
+    DifferentTransactions,
+    TransactionNotFound,
+    TransactionConfirmed,
+    IrreplaceableTransaction,
+    FeeRateTooLow {
+        required: crate::types::FeeRate,
+    },
+
+    ChecksumMismatch,
+    DifferentDescriptorStructure,
+
+    SpendingPolicyRequired,
+    InvalidPolicyPathError(crate::descriptor::policy::PolicyError),
+
+    Signer(crate::wallet::signer::SignerError),
+
+    // Blockchain interface errors
+    Uncapable(crate::blockchain::Capability),
+    OfflineClient,
+    InvalidProgressValue(f32),
+    ProgressUpdateError,
+    MissingCachedAddresses,
+    InvalidOutpoint(OutPoint),
+
+    Descriptor(crate::descriptor::error::Error),
+    AddressValidator(crate::wallet::address_validator::AddressValidatorError),
+
+    Encode(bitcoin::consensus::encode::Error),
+    Miniscript(miniscript::Error),
+    BIP32(bitcoin::util::bip32::Error),
+    Secp256k1(bitcoin::secp256k1::Error),
+    JSON(serde_json::Error),
+    Hex(bitcoin::hashes::hex::Error),
+    PSBT(bitcoin::util::psbt::Error),
+
+    #[cfg(feature = "electrum")]
+    Electrum(electrum_client::Error),
+    #[cfg(feature = "esplora")]
+    Esplora(crate::blockchain::esplora::EsploraError),
+    #[cfg(feature = "compact_filters")]
+    CompactFilters(crate::blockchain::compact_filters::CompactFiltersError),
+    #[cfg(feature = "key-value-db")]
+    Sled(sled::Error),
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for Error {}
+
+macro_rules! impl_error {
+    ( $from:ty, $to:ident ) => {
+        impl std::convert::From<$from> for Error {
+            fn from(err: $from) -> Self {
+                Error::$to(err)
+            }
+        }
+    };
+}
+
+impl_error!(crate::descriptor::error::Error, Descriptor);
+impl_error!(
+    crate::wallet::address_validator::AddressValidatorError,
+    AddressValidator
+);
+impl_error!(
+    crate::descriptor::policy::PolicyError,
+    InvalidPolicyPathError
+);
+impl_error!(crate::wallet::signer::SignerError, Signer);
+
+impl_error!(bitcoin::consensus::encode::Error, Encode);
+impl_error!(miniscript::Error, Miniscript);
+impl_error!(bitcoin::util::bip32::Error, BIP32);
+impl_error!(bitcoin::secp256k1::Error, Secp256k1);
+impl_error!(serde_json::Error, JSON);
+impl_error!(bitcoin::hashes::hex::Error, Hex);
+impl_error!(bitcoin::util::psbt::Error, PSBT);
+
+#[cfg(feature = "electrum")]
+impl_error!(electrum_client::Error, Electrum);
+#[cfg(feature = "esplora")]
+impl_error!(crate::blockchain::esplora::EsploraError, Esplora);
+#[cfg(feature = "key-value-db")]
+impl_error!(sled::Error, Sled);
+
+#[cfg(feature = "compact_filters")]
+impl From<crate::blockchain::compact_filters::CompactFiltersError> for Error {
+    fn from(other: crate::blockchain::compact_filters::CompactFiltersError) -> Self {
+        match other {
+            crate::blockchain::compact_filters::CompactFiltersError::Global(e) => *e,
+            err @ _ => Error::CompactFilters(err),
+        }
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/lib.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/lib.rs.html new file mode 100644 index 0000000000..01356c108c --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/lib.rs.html @@ -0,0 +1,179 @@ +lib.rs.html -- source
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+// only enables the `doc_cfg` feature when
+// the `docsrs` configuration attribute is defined
+#![cfg_attr(docsrs, feature(doc_cfg))]
+// only enables the nightly `external_doc` feature when
+// `test-md-docs` is enabled
+#![cfg_attr(feature = "test-md-docs", feature(external_doc))]
+
+pub extern crate bitcoin;
+extern crate log;
+pub extern crate miniscript;
+extern crate serde;
+#[macro_use]
+extern crate serde_json;
+
+#[cfg(any(target_arch = "wasm32", feature = "async-interface"))]
+#[macro_use]
+extern crate async_trait;
+#[macro_use]
+extern crate bdk_macros;
+
+#[cfg(any(test, feature = "compact_filters"))]
+#[macro_use]
+extern crate lazy_static;
+
+#[cfg(feature = "electrum")]
+pub extern crate electrum_client;
+
+#[cfg(feature = "esplora")]
+pub extern crate reqwest;
+
+#[cfg(feature = "key-value-db")]
+pub extern crate sled;
+
+#[cfg(feature = "cli-utils")]
+pub mod cli;
+
+#[cfg(test)]
+#[macro_use]
+extern crate testutils;
+#[cfg(test)]
+#[macro_use]
+extern crate testutils_macros;
+#[cfg(test)]
+#[macro_use]
+extern crate serial_test;
+
+#[macro_use]
+pub(crate) mod error;
+pub mod blockchain;
+pub mod database;
+pub mod descriptor;
+#[cfg(feature = "test-md-docs")]
+mod doctest;
+pub(crate) mod psbt;
+pub(crate) mod types;
+pub mod wallet;
+
+pub use descriptor::HDKeyPaths;
+pub use error::Error;
+pub use types::*;
+pub use wallet::address_validator;
+pub use wallet::signer;
+pub use wallet::tx_builder::TxBuilder;
+pub use wallet::{OfflineWallet, Wallet};
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/psbt/mod.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/psbt/mod.rs.html new file mode 100644 index 0000000000..cd35634064 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/psbt/mod.rs.html @@ -0,0 +1,107 @@ +mod.rs.html -- source
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
+use bitcoin::TxOut;
+
+pub trait PSBTUtils {
+    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut>;
+}
+
+impl PSBTUtils for PSBT {
+    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut> {
+        let tx = &self.global.unsigned_tx;
+
+        if input_index >= tx.input.len() {
+            return None;
+        }
+
+        if let Some(input) = self.inputs.get(input_index) {
+            if let Some(wit_utxo) = &input.witness_utxo {
+                Some(wit_utxo.clone())
+            } else if let Some(in_tx) = &input.non_witness_utxo {
+                Some(in_tx.output[tx.input[input_index].previous_output.vout as usize].clone())
+            } else {
+                None
+            }
+        } else {
+            None
+        }
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/types.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/types.rs.html new file mode 100644 index 0000000000..8fe99a773d --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/types.rs.html @@ -0,0 +1,227 @@ +types.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::convert::AsRef;
+
+use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxOut};
+use bitcoin::hash_types::Txid;
+
+use serde::{Deserialize, Serialize};
+
+/// Types of script
+#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum ScriptType {
+    External = 0,
+    Internal = 1,
+}
+
+impl ScriptType {
+    pub fn as_byte(&self) -> u8 {
+        match self {
+            ScriptType::External => 'e' as u8,
+            ScriptType::Internal => 'i' as u8,
+        }
+    }
+
+    pub fn is_internal(&self) -> bool {
+        self == &ScriptType::Internal
+    }
+}
+
+impl AsRef<[u8]> for ScriptType {
+    fn as_ref(&self) -> &[u8] {
+        match self {
+            ScriptType::External => b"e",
+            ScriptType::Internal => b"i",
+        }
+    }
+}
+
+/// Fee rate
+#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
+// Internally stored as satoshi/vbyte
+pub struct FeeRate(f32);
+
+impl FeeRate {
+    /// Create a new instance of [`FeeRate`] given a float fee rate in btc/kvbytes
+    pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self {
+        FeeRate(btc_per_kvb * 1e5)
+    }
+
+    /// Create a new instance of [`FeeRate`] given a float fee rate in satoshi/vbyte
+    pub fn from_sat_per_vb(sat_per_vb: f32) -> Self {
+        FeeRate(sat_per_vb)
+    }
+
+    /// Create a new [`FeeRate`] with the default min relay fee value
+    pub fn default_min_relay_fee() -> Self {
+        FeeRate(1.0)
+    }
+
+    /// Return the value as satoshi/vbyte
+    pub fn as_sat_vb(&self) -> f32 {
+        self.0
+    }
+}
+
+impl std::default::Default for FeeRate {
+    fn default() -> Self {
+        FeeRate::default_min_relay_fee()
+    }
+}
+
+/// A wallet unspent output
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
+pub struct UTXO {
+    pub outpoint: OutPoint,
+    pub txout: TxOut,
+    pub is_internal: bool,
+}
+
+/// A wallet transaction
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
+pub struct TransactionDetails {
+    pub transaction: Option<Transaction>,
+    pub txid: Txid,
+    pub timestamp: u64,
+    pub received: u64,
+    pub sent: u64,
+    pub fees: u64,
+    pub height: Option<u32>,
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/address_validator.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/address_validator.rs.html new file mode 100644 index 0000000000..c674ae642a --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/address_validator.rs.html @@ -0,0 +1,327 @@ +address_validator.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Address validation callbacks
+//!
+//! The typical usage of those callbacks is for displaying the newly-generated address on a
+//! hardware wallet, so that the user can cross-check its correctness.
+//!
+//! More generally speaking though, these callbacks can also be used to "do something" every time
+//! an address is generated, without necessarily checking or validating it.
+//!
+//! An address validator can be attached to a [`Wallet`](super::Wallet) by using the
+//! [`Wallet::add_address_validator`](super::Wallet::add_address_validator) method, and
+//! whenever a new address is generated (either explicitly by the user with
+//! [`Wallet::get_new_address`](super::Wallet::get_new_address) or internally to create a change
+//! address) all the attached validators will be polled, in sequence. All of them must complete
+//! successfully to continue.
+//!
+//! ## Example
+//!
+//! ```
+//! # use std::sync::Arc;
+//! # use bitcoin::*;
+//! # use bdk::address_validator::*;
+//! # use bdk::database::*;
+//! # use bdk::*;
+//! struct PrintAddressAndContinue;
+//!
+//! impl AddressValidator for PrintAddressAndContinue {
+//!     fn validate(
+//!         &self,
+//!         script_type: ScriptType,
+//!         hd_keypaths: &HDKeyPaths,
+//!         script: &Script
+//!     ) -> Result<(), AddressValidatorError> {
+//!         let address = Address::from_script(script, Network::Testnet)
+//!             .as_ref()
+//!             .map(Address::to_string)
+//!             .unwrap_or(script.to_string());
+//!         println!("New address of type {:?}: {}", script_type, address);
+//!         println!("HD keypaths: {:#?}", hd_keypaths);
+//!
+//!         Ok(())
+//!     }
+//! }
+//!
+//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+//! let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+//! wallet.add_address_validator(Arc::new(Box::new(PrintAddressAndContinue)));
+//!
+//! let address = wallet.get_new_address()?;
+//! println!("Address: {}", address);
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::fmt;
+
+use bitcoin::Script;
+
+use crate::descriptor::HDKeyPaths;
+use crate::types::ScriptType;
+
+/// Errors that can be returned to fail the validation of an address
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum AddressValidatorError {
+    UserRejected,
+    ConnectionError,
+    TimeoutError,
+    InvalidScript,
+    Message(String),
+}
+
+impl fmt::Display for AddressValidatorError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for AddressValidatorError {}
+
+/// Trait to build address validators
+///
+/// All the address validators attached to a wallet with [`Wallet::add_address_validator`](super::Wallet::add_address_validator) will be polled
+/// every time an address (external or internal) is generated by the wallet. Errors returned in the
+/// validator will be propagated up to the original caller that triggered the address generation.
+///
+/// For a usage example see [this module](crate::address_validator)'s documentation.
+pub trait AddressValidator {
+    /// Validate or inspect an address
+    fn validate(
+        &self,
+        script_type: ScriptType,
+        hd_keypaths: &HDKeyPaths,
+        script: &Script,
+    ) -> Result<(), AddressValidatorError>;
+}
+
+#[cfg(test)]
+mod test {
+    use std::sync::Arc;
+
+    use super::*;
+    use crate::wallet::test::{get_funded_wallet, get_test_wpkh};
+    use crate::wallet::TxBuilder;
+
+    struct TestValidator;
+    impl AddressValidator for TestValidator {
+        fn validate(
+            &self,
+            _script_type: ScriptType,
+            _hd_keypaths: &HDKeyPaths,
+            _script: &bitcoin::Script,
+        ) -> Result<(), AddressValidatorError> {
+            Err(AddressValidatorError::InvalidScript)
+        }
+    }
+
+    #[test]
+    #[should_panic(expected = "InvalidScript")]
+    fn test_address_validator_external() {
+        let (mut wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        wallet.add_address_validator(Arc::new(Box::new(TestValidator)));
+
+        wallet.get_new_address().unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InvalidScript")]
+    fn test_address_validator_internal() {
+        let (mut wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        wallet.add_address_validator(Arc::new(Box::new(TestValidator)));
+
+        let addr = testutils!(@external descriptors, 10);
+        wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/coin_selection.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/coin_selection.rs.html new file mode 100644 index 0000000000..f795967e71 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/coin_selection.rs.html @@ -0,0 +1,701 @@ +coin_selection.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Coin selection
+//!
+//! This module provides the trait [`CoinSelectionAlgorithm`] that can be implemented to
+//! define custom coin selection algorithms.
+//!
+//! The coin selection algorithm is not globally part of a [`Wallet`](super::Wallet), instead it
+//! is selected whenever a [`Wallet::create_tx`](super::Wallet::create_tx) call is made, through
+//! the use of the [`TxBuilder`] structure, specifically with
+//! [`TxBuilder::coin_selection`](super::tx_builder::TxBuilder::coin_selection) method.
+//!
+//! The [`DefaultCoinSelectionAlgorithm`] selects the default coin selection algorithm that
+//! [`TxBuilder`] uses, if it's not explicitly overridden.
+//!
+//! [`TxBuilder`]: super::tx_builder::TxBuilder
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use std::str::FromStr;
+//! # use bitcoin::*;
+//! # use bitcoin::consensus::serialize;
+//! # use bdk::wallet::coin_selection::*;
+//! # use bdk::*;
+//! #[derive(Debug)]
+//! struct AlwaysSpendEverything;
+//!
+//! impl CoinSelectionAlgorithm for AlwaysSpendEverything {
+//!     fn coin_select(
+//!         &self,
+//!         utxos: Vec<UTXO>,
+//!         _use_all_utxos: bool,
+//!         fee_rate: FeeRate,
+//!         amount_needed: u64,
+//!         input_witness_weight: usize,
+//!         fee_amount: f32,
+//!     ) -> Result<CoinSelectionResult, bdk::Error> {
+//!         let selected_amount = utxos.iter().fold(0, |acc, utxo| acc + utxo.txout.value);
+//!         let all_utxos_selected = utxos
+//!             .into_iter()
+//!             .map(|utxo| {
+//!                 (
+//!                     TxIn {
+//!                         previous_output: utxo.outpoint,
+//!                         ..Default::default()
+//!                     },
+//!                     utxo.txout.script_pubkey,
+//!                 )
+//!             })
+//!             .collect::<Vec<_>>();
+//!         let additional_weight = all_utxos_selected.iter().fold(0, |acc, (txin, _)| {
+//!             acc + serialize(txin).len() * 4 + input_witness_weight
+//!         });
+//!         let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
+//!
+//!         if (fee_amount + additional_fees).ceil() as u64 + amount_needed > selected_amount {
+//!             return Err(bdk::Error::InsufficientFunds);
+//!         }
+//!
+//!         Ok(CoinSelectionResult {
+//!             txin: all_utxos_selected,
+//!             selected_amount,
+//!             fee_amount: fee_amount + additional_fees,
+//!         })
+//!     }
+//! }
+//!
+//! # let wallet: OfflineWallet<_> = Wallet::new_offline("", None, Network::Testnet, bdk::database::MemoryDatabase::default())?;
+//! // create wallet, sync, ...
+//!
+//! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+//! let (psbt, details) = wallet.create_tx(
+//!     TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+//!         .coin_selection(AlwaysSpendEverything),
+//! )?;
+//!
+//! // inspect, sign, broadcast, ...
+//!
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use bitcoin::consensus::encode::serialize;
+use bitcoin::{Script, TxIn};
+
+use crate::error::Error;
+use crate::types::{FeeRate, UTXO};
+
+/// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
+/// overridden
+pub type DefaultCoinSelectionAlgorithm = DumbCoinSelection;
+
+/// Result of a successful coin selection
+#[derive(Debug)]
+pub struct CoinSelectionResult {
+    /// List of inputs to use, with the respective previous script_pubkey
+    pub txin: Vec<(TxIn, Script)>,
+    /// Sum of the selected inputs' value
+    pub selected_amount: u64,
+    /// Total fee amount in satoshi
+    pub fee_amount: f32,
+}
+
+/// Trait for generalized coin selection algorithms
+///
+/// This trait can be implemented to make the [`Wallet`](super::Wallet) use a customized coin
+/// selection algorithm when it creates transactions.
+///
+/// For an example see [this module](crate::wallet::coin_selection)'s documentation.
+pub trait CoinSelectionAlgorithm: std::fmt::Debug {
+    /// Perform the coin selection
+    ///
+    /// - `utxos`: the list of spendable UTXOs
+    /// - `use_all_utxos`: if true all utxos should be spent unconditionally
+    /// - `fee_rate`: fee rate to use
+    /// - `amount_needed`: the amount in satoshi to select
+    /// - `input_witness_weight`: the weight of an input's witness to keep into account for the fees
+    /// - `fee_amount`: the amount of fees in satoshi already accumulated from adding outputs
+    fn coin_select(
+        &self,
+        utxos: Vec<UTXO>,
+        use_all_utxos: bool,
+        fee_rate: FeeRate,
+        amount_needed: u64,
+        input_witness_weight: usize,
+        fee_amount: f32,
+    ) -> Result<CoinSelectionResult, Error>;
+}
+
+/// Simple and dumb coin selection
+///
+/// This coin selection algorithm sorts the available UTXOs by value and then picks them starting
+/// from the largest ones until the required amount is reached.
+#[derive(Debug, Default)]
+pub struct DumbCoinSelection;
+
+impl CoinSelectionAlgorithm for DumbCoinSelection {
+    fn coin_select(
+        &self,
+        mut utxos: Vec<UTXO>,
+        use_all_utxos: bool,
+        fee_rate: FeeRate,
+        outgoing_amount: u64,
+        input_witness_weight: usize,
+        mut fee_amount: f32,
+    ) -> Result<CoinSelectionResult, Error> {
+        let mut txin = Vec::new();
+        let calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
+
+        log::debug!(
+            "outgoing_amount = `{}`, fee_amount = `{}`, fee_rate = `{:?}`",
+            outgoing_amount,
+            fee_amount,
+            fee_rate
+        );
+
+        // sort so that we pick them starting from the larger.
+        utxos.sort_by(|a, b| a.txout.value.partial_cmp(&b.txout.value).unwrap());
+
+        let mut selected_amount: u64 = 0;
+        while use_all_utxos || selected_amount < outgoing_amount + (fee_amount.ceil() as u64) {
+            let utxo = match utxos.pop() {
+                Some(utxo) => utxo,
+                None if selected_amount < outgoing_amount + (fee_amount.ceil() as u64) => {
+                    return Err(Error::InsufficientFunds)
+                }
+                None if use_all_utxos => break,
+                None => return Err(Error::InsufficientFunds),
+            };
+
+            let new_in = TxIn {
+                previous_output: utxo.outpoint,
+                script_sig: Script::default(),
+                sequence: 0, // Let the caller choose the right nSequence
+                witness: vec![],
+            };
+            fee_amount += calc_fee_bytes(serialize(&new_in).len() * 4 + input_witness_weight);
+            log::debug!(
+                "Selected {}, updated fee_amount = `{}`",
+                new_in.previous_output,
+                fee_amount
+            );
+
+            txin.push((new_in, utxo.txout.script_pubkey));
+            selected_amount += utxo.txout.value;
+        }
+
+        Ok(CoinSelectionResult {
+            txin,
+            fee_amount,
+            selected_amount,
+        })
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::{OutPoint, Script, TxOut};
+
+    use super::*;
+    use crate::types::*;
+
+    const P2WPKH_WITNESS_SIZE: usize = 73 + 33 + 2;
+
+    fn get_test_utxos() -> Vec<UTXO> {
+        vec![
+            UTXO {
+                outpoint: OutPoint::from_str(
+                    "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0",
+                )
+                .unwrap(),
+                txout: TxOut {
+                    value: 100_000,
+                    script_pubkey: Script::new(),
+                },
+                is_internal: false,
+            },
+            UTXO {
+                outpoint: OutPoint::from_str(
+                    "65d92ddff6b6dc72c89624a6491997714b90f6004f928d875bc0fd53f264fa85:0",
+                )
+                .unwrap(),
+                txout: TxOut {
+                    value: 200_000,
+                    script_pubkey: Script::new(),
+                },
+                is_internal: true,
+            },
+        ]
+    }
+
+    #[test]
+    fn test_dumb_coin_selection_success() {
+        let utxos = get_test_utxos();
+
+        let result = DumbCoinSelection
+            .coin_select(
+                utxos,
+                false,
+                FeeRate::from_sat_per_vb(1.0),
+                250_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
+            .unwrap();
+
+        assert_eq!(result.txin.len(), 2);
+        assert_eq!(result.selected_amount, 300_000);
+        assert_eq!(result.fee_amount, 186.0);
+    }
+
+    #[test]
+    fn test_dumb_coin_selection_use_all() {
+        let utxos = get_test_utxos();
+
+        let result = DumbCoinSelection
+            .coin_select(
+                utxos,
+                true,
+                FeeRate::from_sat_per_vb(1.0),
+                20_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
+            .unwrap();
+
+        assert_eq!(result.txin.len(), 2);
+        assert_eq!(result.selected_amount, 300_000);
+        assert_eq!(result.fee_amount, 186.0);
+    }
+
+    #[test]
+    fn test_dumb_coin_selection_use_only_necessary() {
+        let utxos = get_test_utxos();
+
+        let result = DumbCoinSelection
+            .coin_select(
+                utxos,
+                false,
+                FeeRate::from_sat_per_vb(1.0),
+                20_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
+            .unwrap();
+
+        assert_eq!(result.txin.len(), 1);
+        assert_eq!(result.selected_amount, 200_000);
+        assert_eq!(result.fee_amount, 118.0);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_dumb_coin_selection_insufficient_funds() {
+        let utxos = get_test_utxos();
+
+        DumbCoinSelection
+            .coin_select(
+                utxos,
+                false,
+                FeeRate::from_sat_per_vb(1.0),
+                500_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_dumb_coin_selection_insufficient_funds_high_fees() {
+        let utxos = get_test_utxos();
+
+        DumbCoinSelection
+            .coin_select(
+                utxos,
+                false,
+                FeeRate::from_sat_per_vb(1000.0),
+                250_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
+            .unwrap();
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/export.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/export.rs.html new file mode 100644 index 0000000000..eae5ac9953 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/export.rs.html @@ -0,0 +1,683 @@ +export.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Wallet export
+//!
+//! This modules implements the wallet export format used by [FullyNoded](https://github.com/Fonta1n3/FullyNoded/blob/10b7808c8b929b171cca537fb50522d015168ac9/Docs/Wallets/Wallet-Export-Spec.md).
+//!
+//! ## Examples
+//!
+//! ### Import from JSON
+//!
+//! ```
+//! # use std::str::FromStr;
+//! # use bitcoin::*;
+//! # use bdk::database::*;
+//! # use bdk::wallet::export::*;
+//! # use bdk::*;
+//! let import = r#"{
+//!     "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
+//!     "blockheight":1782088,
+//!     "label":"testnet"
+//! }"#;
+//!
+//! let import = WalletExport::from_str(import)?;
+//! let wallet: OfflineWallet<_> = Wallet::new_offline(&import.descriptor(), import.change_descriptor().as_deref(), Network::Testnet, MemoryDatabase::default())?;
+//! # Ok::<_, bdk::Error>(())
+//! ```
+//!
+//! ### Export a `Wallet`
+//! ```
+//! # use bitcoin::*;
+//! # use bdk::database::*;
+//! # use bdk::wallet::export::*;
+//! # use bdk::*;
+//! let wallet: OfflineWallet<_> = Wallet::new_offline(
+//!     "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
+//!     Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
+//!     Network::Testnet,
+//!     MemoryDatabase::default()
+//! )?;
+//! let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
+//!     .map_err(ToString::to_string)
+//!     .map_err(bdk::Error::Generic)?;
+//!
+//! println!("Exported: {}", export.to_string());
+//! # Ok::<_, bdk::Error>(())
+//! ```
+
+use std::str::FromStr;
+
+use serde::{Deserialize, Serialize};
+
+use miniscript::{Descriptor, ScriptContext, Terminal};
+
+use crate::blockchain::BlockchainMarker;
+use crate::database::BatchDatabase;
+use crate::wallet::Wallet;
+
+/// Structure that contains the export of a wallet
+///
+/// For a usage example see [this module](crate::wallet::export)'s documentation.
+#[derive(Debug, Serialize, Deserialize)]
+pub struct WalletExport {
+    descriptor: String,
+    /// Earliest block to rescan when looking for the wallet's transactions
+    pub blockheight: u32,
+    /// Arbitrary label for the wallet
+    pub label: String,
+}
+
+impl ToString for WalletExport {
+    fn to_string(&self) -> String {
+        serde_json::to_string(self).unwrap()
+    }
+}
+
+impl FromStr for WalletExport {
+    type Err = serde_json::Error;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        serde_json::from_str(s)
+    }
+}
+
+impl WalletExport {
+    /// Export a wallet
+    ///
+    /// This function returns an error if it determines that the `wallet`'s descriptor(s) are not
+    /// supported by Bitcoin Core or don't follow the standard derivation paths defined by BIP44
+    /// and others.
+    ///
+    /// If `include_blockheight` is `true`, this function will look into the `wallet`'s database
+    /// for the oldest transaction it knows and use that as the earliest block to rescan.
+    ///
+    /// If the database is empty or `include_blockheight` is false, the `blockheight` field
+    /// returned will be `0`.
+    pub fn export_wallet<B: BlockchainMarker, D: BatchDatabase>(
+        wallet: &Wallet<B, D>,
+        label: &str,
+        include_blockheight: bool,
+    ) -> Result<Self, &'static str> {
+        let descriptor = wallet
+            .descriptor
+            .to_string_with_secret(&wallet.signers.as_key_map());
+        Self::is_compatible_with_core(&descriptor)?;
+
+        let blockheight = match wallet.database.borrow().iter_txs(false) {
+            _ if !include_blockheight => 0,
+            Err(_) => 0,
+            Ok(txs) => {
+                let mut heights = txs
+                    .into_iter()
+                    .map(|tx| tx.height.unwrap_or(0))
+                    .collect::<Vec<_>>();
+                heights.sort();
+
+                *heights.last().unwrap_or(&0)
+            }
+        };
+
+        let export = WalletExport {
+            descriptor,
+            label: label.into(),
+            blockheight,
+        };
+
+        if export.change_descriptor()
+            != wallet
+                .change_descriptor
+                .as_ref()
+                .map(|d| d.to_string_with_secret(&wallet.change_signers.as_key_map()))
+        {
+            return Err("Incompatible change descriptor");
+        }
+
+        Ok(export)
+    }
+
+    fn is_compatible_with_core(descriptor: &str) -> Result<(), &'static str> {
+        fn check_ms<Ctx: ScriptContext>(
+            terminal: Terminal<String, Ctx>,
+        ) -> Result<(), &'static str> {
+            if let Terminal::Multi(_, _) = terminal {
+                Ok(())
+            } else {
+                Err("The descriptor contains operators not supported by Bitcoin Core")
+            }
+        }
+
+        match Descriptor::<String>::from_str(descriptor).map_err(|_| "Invalid descriptor")? {
+            Descriptor::Pk(_)
+            | Descriptor::Pkh(_)
+            | Descriptor::Wpkh(_)
+            | Descriptor::ShWpkh(_) => Ok(()),
+            Descriptor::Sh(ms) => check_ms(ms.node),
+            Descriptor::Wsh(ms) | Descriptor::ShWsh(ms) => check_ms(ms.node),
+            _ => Err("The descriptor is not compatible with Bitcoin Core"),
+        }
+    }
+
+    /// Return the external descriptor
+    pub fn descriptor(&self) -> String {
+        self.descriptor.clone()
+    }
+
+    /// Return the internal descriptor, if present
+    pub fn change_descriptor(&self) -> Option<String> {
+        let replaced = self.descriptor.replace("/0/*", "/1/*");
+
+        if replaced != self.descriptor {
+            Some(replaced)
+        } else {
+            None
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::{Network, Txid};
+
+    use super::*;
+    use crate::database::{memory::MemoryDatabase, BatchOperations};
+    use crate::types::TransactionDetails;
+    use crate::wallet::{OfflineWallet, Wallet};
+
+    fn get_test_db() -> MemoryDatabase {
+        let mut db = MemoryDatabase::new();
+        db.set_tx(&TransactionDetails {
+            transaction: None,
+            txid: Txid::from_str(
+                "4ddff1fa33af17f377f62b72357b43107c19110a8009b36fb832af505efed98a",
+            )
+            .unwrap(),
+            timestamp: 12345678,
+            received: 100_000,
+            sent: 0,
+            fees: 500,
+            height: Some(5000),
+        })
+        .unwrap();
+
+        db
+    }
+
+    #[test]
+    fn test_export_bip44() {
+        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
+        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
+
+        let wallet: OfflineWallet<_> = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Testnet,
+            get_test_db(),
+        )
+        .unwrap();
+        let export = WalletExport::export_wallet(&wallet, "Test Label", true).unwrap();
+
+        assert_eq!(export.descriptor(), descriptor);
+        assert_eq!(export.change_descriptor(), Some(change_descriptor.into()));
+        assert_eq!(export.blockheight, 5000);
+        assert_eq!(export.label, "Test Label");
+    }
+
+    #[test]
+    #[should_panic(expected = "Incompatible change descriptor")]
+    fn test_export_no_change() {
+        // This wallet explicitly doesn't have a change descriptor. It should be impossible to
+        // export, because exporting this kind of external descriptor normally implies the
+        // existence of an internal descriptor
+
+        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
+
+        let wallet: OfflineWallet<_> =
+            Wallet::new_offline(descriptor, None, Network::Testnet, get_test_db()).unwrap();
+        WalletExport::export_wallet(&wallet, "Test Label", true).unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "Incompatible change descriptor")]
+    fn test_export_incompatible_change() {
+        // This wallet has a change descriptor, but the derivation path is not in the "standard"
+        // bip44/49/etc format
+
+        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
+        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/50'/0'/1/*)";
+
+        let wallet: OfflineWallet<_> = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Testnet,
+            get_test_db(),
+        )
+        .unwrap();
+        WalletExport::export_wallet(&wallet, "Test Label", true).unwrap();
+    }
+
+    #[test]
+    fn test_export_multi() {
+        let descriptor = "wsh(multi(2,\
+                                [73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*,\
+                                [f9f62194/48'/0'/0'/2']tpubDDp3ZSH1yCwusRppH7zgSxq2t1VEUyXSeEp8E5aFS8m43MknUjiF1bSLo3CGWAxbDyhF1XowA5ukPzyJZjznYk3kYi6oe7QxtX2euvKWsk4/0/*,\
+                                [c98b1535/48'/0'/0'/2']tpubDCDi5W4sP6zSnzJeowy8rQDVhBdRARaPhK1axABi8V1661wEPeanpEXj4ZLAUEoikVtoWcyK26TKKJSecSfeKxwHCcRrge9k1ybuiL71z4a/0/*\
+                          ))";
+        let change_descriptor = "wsh(multi(2,\
+                                       [73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/1/*,\
+                                       [f9f62194/48'/0'/0'/2']tpubDDp3ZSH1yCwusRppH7zgSxq2t1VEUyXSeEp8E5aFS8m43MknUjiF1bSLo3CGWAxbDyhF1XowA5ukPzyJZjznYk3kYi6oe7QxtX2euvKWsk4/1/*,\
+                                       [c98b1535/48'/0'/0'/2']tpubDCDi5W4sP6zSnzJeowy8rQDVhBdRARaPhK1axABi8V1661wEPeanpEXj4ZLAUEoikVtoWcyK26TKKJSecSfeKxwHCcRrge9k1ybuiL71z4a/1/*\
+                                 ))";
+
+        let wallet: OfflineWallet<_> = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Testnet,
+            get_test_db(),
+        )
+        .unwrap();
+        let export = WalletExport::export_wallet(&wallet, "Test Label", true).unwrap();
+
+        assert_eq!(export.descriptor(), descriptor);
+        assert_eq!(export.change_descriptor(), Some(change_descriptor.into()));
+        assert_eq!(export.blockheight, 5000);
+        assert_eq!(export.label, "Test Label");
+    }
+
+    #[test]
+    fn test_export_to_json() {
+        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
+        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
+
+        let wallet: OfflineWallet<_> = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Testnet,
+            get_test_db(),
+        )
+        .unwrap();
+        let export = WalletExport::export_wallet(&wallet, "Test Label", true).unwrap();
+
+        assert_eq!(export.to_string(), "{\"descriptor\":\"wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44\'/0\'/0\'/0/*)\",\"blockheight\":5000,\"label\":\"Test Label\"}");
+    }
+
+    #[test]
+    fn test_export_from_json() {
+        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
+        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
+
+        let import_str = "{\"descriptor\":\"wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44\'/0\'/0\'/0/*)\",\"blockheight\":5000,\"label\":\"Test Label\"}";
+        let export = WalletExport::from_str(import_str).unwrap();
+
+        assert_eq!(export.descriptor(), descriptor);
+        assert_eq!(export.change_descriptor(), Some(change_descriptor.into()));
+        assert_eq!(export.blockheight, 5000);
+        assert_eq!(export.label, "Test Label");
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/mod.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/mod.rs.html new file mode 100644 index 0000000000..46a90673f2 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/mod.rs.html @@ -0,0 +1,4881 @@ +mod.rs.html -- source
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+1435
+1436
+1437
+1438
+1439
+1440
+1441
+1442
+1443
+1444
+1445
+1446
+1447
+1448
+1449
+1450
+1451
+1452
+1453
+1454
+1455
+1456
+1457
+1458
+1459
+1460
+1461
+1462
+1463
+1464
+1465
+1466
+1467
+1468
+1469
+1470
+1471
+1472
+1473
+1474
+1475
+1476
+1477
+1478
+1479
+1480
+1481
+1482
+1483
+1484
+1485
+1486
+1487
+1488
+1489
+1490
+1491
+1492
+1493
+1494
+1495
+1496
+1497
+1498
+1499
+1500
+1501
+1502
+1503
+1504
+1505
+1506
+1507
+1508
+1509
+1510
+1511
+1512
+1513
+1514
+1515
+1516
+1517
+1518
+1519
+1520
+1521
+1522
+1523
+1524
+1525
+1526
+1527
+1528
+1529
+1530
+1531
+1532
+1533
+1534
+1535
+1536
+1537
+1538
+1539
+1540
+1541
+1542
+1543
+1544
+1545
+1546
+1547
+1548
+1549
+1550
+1551
+1552
+1553
+1554
+1555
+1556
+1557
+1558
+1559
+1560
+1561
+1562
+1563
+1564
+1565
+1566
+1567
+1568
+1569
+1570
+1571
+1572
+1573
+1574
+1575
+1576
+1577
+1578
+1579
+1580
+1581
+1582
+1583
+1584
+1585
+1586
+1587
+1588
+1589
+1590
+1591
+1592
+1593
+1594
+1595
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+1603
+1604
+1605
+1606
+1607
+1608
+1609
+1610
+1611
+1612
+1613
+1614
+1615
+1616
+1617
+1618
+1619
+1620
+1621
+1622
+1623
+1624
+1625
+1626
+1627
+1628
+1629
+1630
+1631
+1632
+1633
+1634
+1635
+1636
+1637
+1638
+1639
+1640
+1641
+1642
+1643
+1644
+1645
+1646
+1647
+1648
+1649
+1650
+1651
+1652
+1653
+1654
+1655
+1656
+1657
+1658
+1659
+1660
+1661
+1662
+1663
+1664
+1665
+1666
+1667
+1668
+1669
+1670
+1671
+1672
+1673
+1674
+1675
+1676
+1677
+1678
+1679
+1680
+1681
+1682
+1683
+1684
+1685
+1686
+1687
+1688
+1689
+1690
+1691
+1692
+1693
+1694
+1695
+1696
+1697
+1698
+1699
+1700
+1701
+1702
+1703
+1704
+1705
+1706
+1707
+1708
+1709
+1710
+1711
+1712
+1713
+1714
+1715
+1716
+1717
+1718
+1719
+1720
+1721
+1722
+1723
+1724
+1725
+1726
+1727
+1728
+1729
+1730
+1731
+1732
+1733
+1734
+1735
+1736
+1737
+1738
+1739
+1740
+1741
+1742
+1743
+1744
+1745
+1746
+1747
+1748
+1749
+1750
+1751
+1752
+1753
+1754
+1755
+1756
+1757
+1758
+1759
+1760
+1761
+1762
+1763
+1764
+1765
+1766
+1767
+1768
+1769
+1770
+1771
+1772
+1773
+1774
+1775
+1776
+1777
+1778
+1779
+1780
+1781
+1782
+1783
+1784
+1785
+1786
+1787
+1788
+1789
+1790
+1791
+1792
+1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+1801
+1802
+1803
+1804
+1805
+1806
+1807
+1808
+1809
+1810
+1811
+1812
+1813
+1814
+1815
+1816
+1817
+1818
+1819
+1820
+1821
+1822
+1823
+1824
+1825
+1826
+1827
+1828
+1829
+1830
+1831
+1832
+1833
+1834
+1835
+1836
+1837
+1838
+1839
+1840
+1841
+1842
+1843
+1844
+1845
+1846
+1847
+1848
+1849
+1850
+1851
+1852
+1853
+1854
+1855
+1856
+1857
+1858
+1859
+1860
+1861
+1862
+1863
+1864
+1865
+1866
+1867
+1868
+1869
+1870
+1871
+1872
+1873
+1874
+1875
+1876
+1877
+1878
+1879
+1880
+1881
+1882
+1883
+1884
+1885
+1886
+1887
+1888
+1889
+1890
+1891
+1892
+1893
+1894
+1895
+1896
+1897
+1898
+1899
+1900
+1901
+1902
+1903
+1904
+1905
+1906
+1907
+1908
+1909
+1910
+1911
+1912
+1913
+1914
+1915
+1916
+1917
+1918
+1919
+1920
+1921
+1922
+1923
+1924
+1925
+1926
+1927
+1928
+1929
+1930
+1931
+1932
+1933
+1934
+1935
+1936
+1937
+1938
+1939
+1940
+1941
+1942
+1943
+1944
+1945
+1946
+1947
+1948
+1949
+1950
+1951
+1952
+1953
+1954
+1955
+1956
+1957
+1958
+1959
+1960
+1961
+1962
+1963
+1964
+1965
+1966
+1967
+1968
+1969
+1970
+1971
+1972
+1973
+1974
+1975
+1976
+1977
+1978
+1979
+1980
+1981
+1982
+1983
+1984
+1985
+1986
+1987
+1988
+1989
+1990
+1991
+1992
+1993
+1994
+1995
+1996
+1997
+1998
+1999
+2000
+2001
+2002
+2003
+2004
+2005
+2006
+2007
+2008
+2009
+2010
+2011
+2012
+2013
+2014
+2015
+2016
+2017
+2018
+2019
+2020
+2021
+2022
+2023
+2024
+2025
+2026
+2027
+2028
+2029
+2030
+2031
+2032
+2033
+2034
+2035
+2036
+2037
+2038
+2039
+2040
+2041
+2042
+2043
+2044
+2045
+2046
+2047
+2048
+2049
+2050
+2051
+2052
+2053
+2054
+2055
+2056
+2057
+2058
+2059
+2060
+2061
+2062
+2063
+2064
+2065
+2066
+2067
+2068
+2069
+2070
+2071
+2072
+2073
+2074
+2075
+2076
+2077
+2078
+2079
+2080
+2081
+2082
+2083
+2084
+2085
+2086
+2087
+2088
+2089
+2090
+2091
+2092
+2093
+2094
+2095
+2096
+2097
+2098
+2099
+2100
+2101
+2102
+2103
+2104
+2105
+2106
+2107
+2108
+2109
+2110
+2111
+2112
+2113
+2114
+2115
+2116
+2117
+2118
+2119
+2120
+2121
+2122
+2123
+2124
+2125
+2126
+2127
+2128
+2129
+2130
+2131
+2132
+2133
+2134
+2135
+2136
+2137
+2138
+2139
+2140
+2141
+2142
+2143
+2144
+2145
+2146
+2147
+2148
+2149
+2150
+2151
+2152
+2153
+2154
+2155
+2156
+2157
+2158
+2159
+2160
+2161
+2162
+2163
+2164
+2165
+2166
+2167
+2168
+2169
+2170
+2171
+2172
+2173
+2174
+2175
+2176
+2177
+2178
+2179
+2180
+2181
+2182
+2183
+2184
+2185
+2186
+2187
+2188
+2189
+2190
+2191
+2192
+2193
+2194
+2195
+2196
+2197
+2198
+2199
+2200
+2201
+2202
+2203
+2204
+2205
+2206
+2207
+2208
+2209
+2210
+2211
+2212
+2213
+2214
+2215
+2216
+2217
+2218
+2219
+2220
+2221
+2222
+2223
+2224
+2225
+2226
+2227
+2228
+2229
+2230
+2231
+2232
+2233
+2234
+2235
+2236
+2237
+2238
+2239
+2240
+2241
+2242
+2243
+2244
+2245
+2246
+2247
+2248
+2249
+2250
+2251
+2252
+2253
+2254
+2255
+2256
+2257
+2258
+2259
+2260
+2261
+2262
+2263
+2264
+2265
+2266
+2267
+2268
+2269
+2270
+2271
+2272
+2273
+2274
+2275
+2276
+2277
+2278
+2279
+2280
+2281
+2282
+2283
+2284
+2285
+2286
+2287
+2288
+2289
+2290
+2291
+2292
+2293
+2294
+2295
+2296
+2297
+2298
+2299
+2300
+2301
+2302
+2303
+2304
+2305
+2306
+2307
+2308
+2309
+2310
+2311
+2312
+2313
+2314
+2315
+2316
+2317
+2318
+2319
+2320
+2321
+2322
+2323
+2324
+2325
+2326
+2327
+2328
+2329
+2330
+2331
+2332
+2333
+2334
+2335
+2336
+2337
+2338
+2339
+2340
+2341
+2342
+2343
+2344
+2345
+2346
+2347
+2348
+2349
+2350
+2351
+2352
+2353
+2354
+2355
+2356
+2357
+2358
+2359
+2360
+2361
+2362
+2363
+2364
+2365
+2366
+2367
+2368
+2369
+2370
+2371
+2372
+2373
+2374
+2375
+2376
+2377
+2378
+2379
+2380
+2381
+2382
+2383
+2384
+2385
+2386
+2387
+2388
+2389
+2390
+2391
+2392
+2393
+2394
+2395
+2396
+2397
+2398
+2399
+2400
+2401
+2402
+2403
+2404
+2405
+2406
+2407
+2408
+2409
+2410
+2411
+2412
+2413
+2414
+2415
+2416
+2417
+2418
+2419
+2420
+2421
+2422
+2423
+2424
+2425
+2426
+2427
+2428
+2429
+2430
+2431
+2432
+2433
+2434
+2435
+2436
+2437
+2438
+2439
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Wallet
+//!
+//! This module defines the [`Wallet`] structure.
+
+use std::cell::RefCell;
+use std::collections::HashMap;
+use std::collections::{BTreeMap, HashSet};
+use std::ops::{Deref, DerefMut};
+use std::sync::Arc;
+
+use bitcoin::consensus::encode::serialize;
+use bitcoin::util::bip32::ChildNumber;
+use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
+use bitcoin::{Address, Network, OutPoint, Script, SigHashType, Transaction, TxOut, Txid};
+
+use miniscript::descriptor::DescriptorPublicKey;
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+pub mod address_validator;
+pub mod coin_selection;
+pub mod export;
+mod rbf;
+pub mod signer;
+pub mod time;
+pub mod tx_builder;
+pub(crate) mod utils;
+
+pub use utils::IsDust;
+
+use address_validator::AddressValidator;
+use signer::{Signer, SignerId, SignerOrdering, SignersContainer};
+use tx_builder::TxBuilder;
+use utils::{After, Older};
+
+use crate::blockchain::{Blockchain, BlockchainMarker, OfflineBlockchain, Progress};
+use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
+use crate::descriptor::{
+    get_checksum, DescriptorMeta, DescriptorScripts, ExtendedDescriptor, ExtractPolicy, Policy,
+};
+use crate::error::Error;
+use crate::psbt::PSBTUtils;
+use crate::types::*;
+
+const CACHE_ADDR_BATCH_SIZE: u32 = 100;
+
+/// Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]
+pub type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;
+
+/// A Bitcoin wallet
+///
+/// A wallet takes descriptors, a [`database`](crate::database) and a
+/// [`blockchain`](crate::blockchain) and implements the basic functions that a Bitcoin wallets
+/// needs to operate, like [generating addresses](Wallet::get_new_address), [returning the balance](Wallet::get_balance),
+/// [creating transactions](Wallet::create_tx), etc.
+///
+/// A wallet can be either "online" if the [`blockchain`](crate::blockchain) type provided
+/// implements [`Blockchain`], or "offline" [`OfflineBlockchain`] is used. Offline wallets only expose
+/// methods that don't need any interaction with the blockchain to work.
+pub struct Wallet<B: BlockchainMarker, D: BatchDatabase> {
+    descriptor: ExtendedDescriptor,
+    change_descriptor: Option<ExtendedDescriptor>,
+
+    signers: Arc<SignersContainer<DescriptorPublicKey>>,
+    change_signers: Arc<SignersContainer<DescriptorPublicKey>>,
+
+    address_validators: Vec<Arc<Box<dyn AddressValidator>>>,
+
+    network: Network,
+
+    current_height: Option<u32>,
+
+    client: Option<B>,
+    database: RefCell<D>,
+}
+
+// offline actions, always available
+impl<B, D> Wallet<B, D>
+where
+    B: BlockchainMarker,
+    D: BatchDatabase,
+{
+    /// Create a new "offline" wallet
+    pub fn new_offline(
+        descriptor: &str,
+        change_descriptor: Option<&str>,
+        network: Network,
+        mut database: D,
+    ) -> Result<Self, Error> {
+        database.check_descriptor_checksum(
+            ScriptType::External,
+            get_checksum(descriptor)?.as_bytes(),
+        )?;
+        let (descriptor, keymap) = ExtendedDescriptor::parse_secret(descriptor)?;
+        let signers = Arc::new(SignersContainer::from(keymap));
+        let (change_descriptor, change_signers) = match change_descriptor {
+            Some(desc) => {
+                database.check_descriptor_checksum(
+                    ScriptType::Internal,
+                    get_checksum(desc)?.as_bytes(),
+                )?;
+
+                let (change_descriptor, change_keymap) = ExtendedDescriptor::parse_secret(desc)?;
+                let change_signers = Arc::new(SignersContainer::from(change_keymap));
+                // if !parsed.same_structure(descriptor.as_ref()) {
+                //     return Err(Error::DifferentDescriptorStructure);
+                // }
+
+                (Some(change_descriptor), change_signers)
+            }
+            None => (None, Arc::new(SignersContainer::new())),
+        };
+
+        Ok(Wallet {
+            descriptor,
+            change_descriptor,
+            signers,
+            change_signers,
+            address_validators: Vec::new(),
+
+            network,
+
+            current_height: None,
+
+            client: None,
+            database: RefCell::new(database),
+        })
+    }
+
+    /// Return a newly generated address using the external descriptor
+    pub fn get_new_address(&self) -> Result<Address, Error> {
+        let index = self.fetch_and_increment_index(ScriptType::External)?;
+
+        self.descriptor
+            .derive(&[ChildNumber::from_normal_idx(index).unwrap()])
+            .address(self.network)
+            .ok_or(Error::ScriptDoesntHaveAddressForm)
+    }
+
+    /// Return whether or not a `script` is part of this wallet (either internal or external)
+    pub fn is_mine(&self, script: &Script) -> Result<bool, Error> {
+        self.database.borrow().is_mine(script)
+    }
+
+    /// Return the list of unspent outputs of this wallet
+    ///
+    /// Note that this methods only operate on the internal database, which first needs to be
+    /// [`Wallet::sync`] manually.
+    pub fn list_unspent(&self) -> Result<Vec<UTXO>, Error> {
+        self.database.borrow().iter_utxos()
+    }
+
+    /// Return the list of transactions made and received by the wallet
+    ///
+    /// Optionally fill the [`TransactionDetails::transaction`] field with the raw transaction if
+    /// `include_raw` is `true`.
+    ///
+    /// Note that this methods only operate on the internal database, which first needs to be
+    /// [`Wallet::sync`] manually.
+    pub fn list_transactions(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        self.database.borrow().iter_txs(include_raw)
+    }
+
+    /// Return the balance, meaning the sum of this wallet's unspent outputs' values
+    ///
+    /// Note that this methods only operate on the internal database, which first needs to be
+    /// [`Wallet::sync`] manually.
+    pub fn get_balance(&self) -> Result<u64, Error> {
+        Ok(self
+            .list_unspent()?
+            .iter()
+            .fold(0, |sum, i| sum + i.txout.value))
+    }
+
+    /// Add an external signer
+    ///
+    /// See [the `signer` module](signer) for an example.
+    pub fn add_signer(
+        &mut self,
+        script_type: ScriptType,
+        id: SignerId<DescriptorPublicKey>,
+        ordering: SignerOrdering,
+        signer: Arc<Box<dyn Signer>>,
+    ) {
+        let signers = match script_type {
+            ScriptType::External => Arc::make_mut(&mut self.signers),
+            ScriptType::Internal => Arc::make_mut(&mut self.change_signers),
+        };
+
+        signers.add_external(id, ordering, signer);
+    }
+
+    /// Add an address validator
+    ///
+    /// See [the `address_validator` module](address_validator) for an example.
+    pub fn add_address_validator(&mut self, validator: Arc<Box<dyn AddressValidator>>) {
+        self.address_validators.push(validator);
+    }
+
+    /// Create a new transaction following the options specified in the `builder`
+    ///
+    /// ## Example
+    ///
+    /// ```no_run
+    /// # use std::str::FromStr;
+    /// # use bitcoin::*;
+    /// # use bdk::*;
+    /// # use bdk::database::*;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+    /// let (psbt, details) = wallet.create_tx(
+    ///     TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+    /// )?;
+    /// // sign and broadcast ...
+    /// # Ok::<(), bdk::Error>(())
+    /// ```
+    pub fn create_tx<Cs: coin_selection::CoinSelectionAlgorithm>(
+        &self,
+        builder: TxBuilder<Cs>,
+    ) -> Result<(PSBT, TransactionDetails), Error> {
+        if builder.recipients.is_empty() {
+            return Err(Error::NoAddressees);
+        }
+
+        // TODO: fetch both internal and external policies
+        let policy = self
+            .descriptor
+            .extract_policy(Arc::clone(&self.signers))?
+            .unwrap();
+        if policy.requires_path() && builder.policy_path.is_none() {
+            return Err(Error::SpendingPolicyRequired);
+        }
+        let requirements =
+            policy.get_condition(builder.policy_path.as_ref().unwrap_or(&BTreeMap::new()))?;
+        debug!("requirements: {:?}", requirements);
+
+        let version = match builder.version {
+            Some(tx_builder::Version(0)) => {
+                return Err(Error::Generic("Invalid version `0`".into()))
+            }
+            Some(tx_builder::Version(1)) if requirements.csv.is_some() => {
+                return Err(Error::Generic(
+                    "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
+                        .into(),
+                ))
+            }
+            Some(tx_builder::Version(x)) => x,
+            None if requirements.csv.is_some() => 2,
+            _ => 1,
+        };
+
+        let lock_time = match builder.locktime {
+            None => requirements.timelock.unwrap_or(0),
+            Some(x) if requirements.timelock.is_none() => x,
+            Some(x) if requirements.timelock.unwrap() <= x => x,
+            Some(x) => return Err(Error::Generic(format!("TxBuilder requested timelock of `{}`, but at least `{}` is required to spend from this script", x, requirements.timelock.unwrap())))
+        };
+
+        let n_sequence = match (builder.rbf, requirements.csv) {
+            (None, Some(csv)) => csv,
+            (Some(rbf), Some(csv)) if rbf < csv => return Err(Error::Generic(format!("Cannot enable RBF with nSequence `{}`, since at least `{}` is required to spend with OP_CSV", rbf, csv))),
+            (None, _) if requirements.timelock.is_some() => 0xFFFFFFFE,
+            (Some(rbf), _) if rbf >= 0xFFFFFFFE => return Err(Error::Generic("Cannot enable RBF with a nSequence >= 0xFFFFFFFE".into())),
+            (Some(rbf), _) => rbf,
+            (None, _) => 0xFFFFFFFF,
+        };
+
+        let mut tx = Transaction {
+            version,
+            lock_time,
+            input: vec![],
+            output: vec![],
+        };
+
+        let fee_rate = builder.fee_rate.unwrap_or_default();
+        if builder.send_all && builder.recipients.len() != 1 {
+            return Err(Error::SendAllMultipleOutputs);
+        }
+
+        // we keep it as a float while we accumulate it, and only round it at the end
+        let mut fee_amount: f32 = 0.0;
+        let mut outgoing: u64 = 0;
+        let mut received: u64 = 0;
+
+        let calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
+        fee_amount += calc_fee_bytes(tx.get_weight());
+
+        for (index, (script_pubkey, satoshi)) in builder.recipients.iter().enumerate() {
+            let value = match builder.send_all {
+                true => 0,
+                false if satoshi.is_dust() => return Err(Error::OutputBelowDustLimit(index)),
+                false => *satoshi,
+            };
+
+            if self.is_mine(script_pubkey)? {
+                received += value;
+            }
+
+            let new_out = TxOut {
+                script_pubkey: script_pubkey.clone(),
+                value,
+            };
+            fee_amount += calc_fee_bytes(serialize(&new_out).len() * 4);
+
+            tx.output.push(new_out);
+
+            outgoing += value;
+        }
+
+        // TODO: use the right weight instead of the maximum, and only fall-back to it if the
+        // script is unknown in the database
+        let input_witness_weight = std::cmp::max(
+            self.get_descriptor_for_script_type(ScriptType::Internal)
+                .0
+                .max_satisfaction_weight(),
+            self.get_descriptor_for_script_type(ScriptType::External)
+                .0
+                .max_satisfaction_weight(),
+        );
+
+        if builder.change_policy != tx_builder::ChangeSpendPolicy::ChangeAllowed
+            && self.change_descriptor.is_none()
+        {
+            return Err(Error::Generic(
+                "The `change_policy` can be set only if the wallet has a change_descriptor".into(),
+            ));
+        }
+
+        let (available_utxos, use_all_utxos) = self.get_available_utxos(
+            builder.change_policy,
+            &builder.utxos,
+            &builder.unspendable,
+            builder.send_all,
+        )?;
+        let coin_selection::CoinSelectionResult {
+            txin,
+            selected_amount,
+            mut fee_amount,
+        } = builder.coin_selection.coin_select(
+            available_utxos,
+            use_all_utxos,
+            fee_rate,
+            outgoing,
+            input_witness_weight,
+            fee_amount,
+        )?;
+        let (mut txin, prev_script_pubkeys): (Vec<_>, Vec<_>) = txin.into_iter().unzip();
+        // map that allows us to lookup the prev_script_pubkey for a given previous_output
+        let prev_script_pubkeys = txin
+            .iter()
+            .zip(prev_script_pubkeys.into_iter())
+            .map(|(txin, script)| (txin.previous_output, script))
+            .collect::<HashMap<_, _>>();
+
+        txin.iter_mut().for_each(|i| i.sequence = n_sequence);
+        tx.input = txin;
+
+        // prepare the change output
+        let change_output = match builder.send_all {
+            true => None,
+            false => {
+                let change_script = self.get_change_address()?;
+                let change_output = TxOut {
+                    script_pubkey: change_script,
+                    value: 0,
+                };
+
+                // take the change into account for fees
+                fee_amount += calc_fee_bytes(serialize(&change_output).len() * 4);
+                Some(change_output)
+            }
+        };
+
+        let mut fee_amount = fee_amount.ceil() as u64;
+        let change_val = selected_amount - outgoing - fee_amount;
+        if !builder.send_all && !change_val.is_dust() {
+            let mut change_output = change_output.unwrap();
+            change_output.value = change_val;
+            received += change_val;
+
+            tx.output.push(change_output);
+        } else if builder.send_all && !change_val.is_dust() {
+            // there's only one output, send everything to it
+            tx.output[0].value = change_val;
+
+            // send_all to our address
+            if self.is_mine(&tx.output[0].script_pubkey)? {
+                received = change_val;
+            }
+        } else if !builder.send_all && change_val.is_dust() {
+            // skip the change output because it's dust, this adds up to the fees
+            fee_amount += change_val;
+        } else if builder.send_all {
+            // send_all but the only output would be below dust limit
+            return Err(Error::InsufficientFunds); // TODO: or OutputBelowDustLimit?
+        }
+
+        // sort input/outputs according to the chosen algorithm
+        builder.ordering.sort_tx(&mut tx);
+
+        let txid = tx.txid();
+        let psbt = self.complete_transaction(tx, prev_script_pubkeys, builder)?;
+
+        let transaction_details = TransactionDetails {
+            transaction: None,
+            txid,
+            timestamp: time::get_timestamp(),
+            received,
+            sent: selected_amount,
+            fees: fee_amount,
+            height: None,
+        };
+
+        Ok((psbt, transaction_details))
+    }
+
+    /// Bump the fee of a transaction following the options specified in the `builder`
+    ///
+    /// Return an error if the transaction is already confirmed or doesn't explicitly signal RBF.
+    ///
+    /// **NOTE**: if the original transaction was made with [`TxBuilder::send_all`], the same
+    /// option must be enabled when bumping its fees to correctly reduce the only output's value to
+    /// increase the fees.
+    ///
+    /// ## Example
+    ///
+    /// ```no_run
+    /// # use std::str::FromStr;
+    /// # use bitcoin::*;
+    /// # use bdk::*;
+    /// # use bdk::database::*;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+    /// let txid = Txid::from_str("faff0a466b70f5d5f92bd757a92c1371d4838bdd5bc53a06764e2488e51ce8f8").unwrap();
+    /// let (psbt, details) = wallet.bump_fee(
+    ///     &txid,
+    ///     TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(5.0)),
+    /// )?;
+    /// // sign and broadcast ...
+    /// # Ok::<(), bdk::Error>(())
+    /// ```
+    // TODO: support for merging multiple transactions while bumping the fees
+    // TODO: option to force addition of an extra output? seems bad for privacy to update the
+    // change
+    pub fn bump_fee<Cs: coin_selection::CoinSelectionAlgorithm>(
+        &self,
+        txid: &Txid,
+        builder: TxBuilder<Cs>,
+    ) -> Result<(PSBT, TransactionDetails), Error> {
+        let mut details = match self.database.borrow().get_tx(&txid, true)? {
+            None => return Err(Error::TransactionNotFound),
+            Some(tx) if tx.transaction.is_none() => return Err(Error::TransactionNotFound),
+            Some(tx) if tx.height.is_some() => return Err(Error::TransactionConfirmed),
+            Some(tx) => tx,
+        };
+        let mut tx = details.transaction.take().unwrap();
+        if !tx.input.iter().any(|txin| txin.sequence <= 0xFFFFFFFD) {
+            return Err(Error::IrreplaceableTransaction);
+        }
+
+        // the new tx must "pay for its bandwidth"
+        let vbytes = tx.get_weight() as f32 / 4.0;
+        let required_feerate = FeeRate::from_sat_per_vb(details.fees as f32 / vbytes + 1.0);
+        let new_feerate = builder.fee_rate.unwrap_or_default();
+
+        if new_feerate < required_feerate {
+            return Err(Error::FeeRateTooLow {
+                required: required_feerate,
+            });
+        }
+        let mut fee_difference =
+            (new_feerate.as_sat_vb() * tx.get_weight() as f32 / 4.0).ceil() as u64 - details.fees;
+
+        if builder.send_all && tx.output.len() > 1 {
+            return Err(Error::SendAllMultipleOutputs);
+        }
+
+        // find the index of the output that we can update. either the change or the only one if
+        // it's `send_all`
+        let updatable_output = if builder.send_all {
+            0
+        } else {
+            let mut change_output = None;
+            for (index, txout) in tx.output.iter().enumerate() {
+                // look for an output that we know and that has the right ScriptType. We use
+                // `get_deget_descriptor_for` to find what's the ScriptType for `Internal`
+                // addresses really is, because if there's no change_descriptor it's actually equal
+                // to "External"
+                let (_, change_type) = self.get_descriptor_for_script_type(ScriptType::Internal);
+                match self
+                    .database
+                    .borrow()
+                    .get_path_from_script_pubkey(&txout.script_pubkey)?
+                {
+                    Some((script_type, _)) if script_type == change_type => {
+                        change_output = Some(index);
+                        break;
+                    }
+                    _ => {}
+                }
+            }
+
+            // we need a change output, add one here and take into account the extra fees for it
+            if change_output.is_none() {
+                let change_script = self.get_change_address()?;
+                let change_txout = TxOut {
+                    script_pubkey: change_script,
+                    value: 0,
+                };
+                fee_difference +=
+                    (serialize(&change_txout).len() as f32 * new_feerate.as_sat_vb()).ceil() as u64;
+                tx.output.push(change_txout);
+
+                change_output = Some(tx.output.len() - 1);
+            }
+
+            change_output.unwrap()
+        };
+
+        // if `builder.utxos` is Some(_) we have to add inputs and we skip down to the last branch
+        match tx.output[updatable_output]
+            .value
+            .checked_sub(fee_difference)
+        {
+            Some(new_value) if !new_value.is_dust() && builder.utxos.is_none() => {
+                // try to reduce the "updatable output" amount
+                tx.output[updatable_output].value = new_value;
+                if self.is_mine(&tx.output[updatable_output].script_pubkey)? {
+                    details.received -= fee_difference;
+                }
+
+                details.fees += fee_difference;
+            }
+            _ if builder.send_all && builder.utxos.is_none() => {
+                // if the tx is "send_all" it doesn't make sense to either remove the only output
+                // or add more inputs
+                return Err(Error::InsufficientFunds);
+            }
+            _ => {
+                // initially always remove the change output
+                let mut removed_change_output = tx.output.remove(updatable_output);
+                if self.is_mine(&removed_change_output.script_pubkey)? {
+                    details.received -= removed_change_output.value;
+                }
+
+                // we want to add more inputs if:
+                // - builder.utxos tells us to do so
+                // - the removed change value is lower than the fee_difference we want to add
+                let needs_more_inputs =
+                    builder.utxos.is_some() || removed_change_output.value <= fee_difference;
+                let added_amount = if needs_more_inputs {
+                    // TODO: use the right weight instead of the maximum, and only fall-back to it if the
+                    // script is unknown in the database
+                    let input_witness_weight = std::cmp::max(
+                        self.get_descriptor_for_script_type(ScriptType::Internal)
+                            .0
+                            .max_satisfaction_weight(),
+                        self.get_descriptor_for_script_type(ScriptType::External)
+                            .0
+                            .max_satisfaction_weight(),
+                    );
+
+                    let (available_utxos, use_all_utxos) = self.get_available_utxos(
+                        builder.change_policy,
+                        &builder.utxos,
+                        &builder.unspendable,
+                        false,
+                    )?;
+                    let available_utxos = rbf::filter_available(
+                        self.database.borrow().deref(),
+                        available_utxos.into_iter(),
+                    )?;
+                    let coin_selection::CoinSelectionResult {
+                        txin,
+                        selected_amount,
+                        fee_amount,
+                    } = builder.coin_selection.coin_select(
+                        available_utxos,
+                        use_all_utxos,
+                        new_feerate,
+                        fee_difference
+                            .checked_sub(removed_change_output.value)
+                            .unwrap_or(0),
+                        input_witness_weight,
+                        0.0,
+                    )?;
+                    fee_difference += fee_amount.ceil() as u64;
+
+                    // add the new inputs
+                    let (mut txin, _): (Vec<_>, Vec<_>) = txin.into_iter().unzip();
+
+                    // TODO: use tx_builder.sequence ??
+                    // copy the n_sequence from the inputs that were already in the transaction
+                    txin.iter_mut()
+                        .for_each(|i| i.sequence = tx.input[0].sequence);
+                    tx.input.extend_from_slice(&mut txin);
+
+                    details.sent += selected_amount;
+                    selected_amount
+                } else {
+                    // otherwise just remove the output and add 0 new coins
+                    0
+                };
+
+                match (removed_change_output.value + added_amount).checked_sub(fee_difference) {
+                    None => return Err(Error::InsufficientFunds),
+                    Some(new_value) if new_value.is_dust() => {
+                        // the change would be dust, add that to fees
+                        details.fees += fee_difference + new_value;
+                    }
+                    Some(new_value) => {
+                        // add the change back
+                        removed_change_output.value = new_value;
+                        tx.output.push(removed_change_output);
+
+                        details.received += new_value;
+                        details.fees += fee_difference;
+                    }
+                }
+            }
+        };
+
+        // clear witnesses
+        for input in &mut tx.input {
+            input.script_sig = Script::default();
+            input.witness = vec![];
+        }
+
+        // sort input/outputs according to the chosen algorithm
+        builder.ordering.sort_tx(&mut tx);
+
+        // TODO: check that we are not replacing more than 100 txs from mempool
+
+        details.txid = tx.txid();
+        details.timestamp = time::get_timestamp();
+
+        let prev_script_pubkeys = tx
+            .input
+            .iter()
+            .map(|txin| {
+                Ok((
+                    txin.previous_output.clone(),
+                    self.database
+                        .borrow()
+                        .get_previous_output(&txin.previous_output)?,
+                ))
+            })
+            .collect::<Result<Vec<_>, Error>>()?
+            .into_iter()
+            .filter_map(|(outpoint, txout)| match txout {
+                Some(txout) => Some((outpoint, txout.script_pubkey)),
+                None => None,
+            })
+            .collect();
+        let psbt = self.complete_transaction(tx, prev_script_pubkeys, builder)?;
+
+        Ok((psbt, details))
+    }
+
+    /// Sign a transaction with all the wallet's signers, in the order specified by every signer's
+    /// [`SignerOrdering`]
+    ///
+    /// ## Example
+    ///
+    /// ```no_run
+    /// # use std::str::FromStr;
+    /// # use bitcoin::*;
+    /// # use bdk::*;
+    /// # use bdk::database::*;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+    /// # let (psbt, _) = wallet.create_tx(TxBuilder::new())?;
+    /// let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
+    /// # Ok::<(), bdk::Error>(())
+    pub fn sign(&self, mut psbt: PSBT, assume_height: Option<u32>) -> Result<(PSBT, bool), Error> {
+        // this helps us doing our job later
+        self.add_input_hd_keypaths(&mut psbt)?;
+
+        for signer in self
+            .signers
+            .signers()
+            .iter()
+            .chain(self.change_signers.signers().iter())
+        {
+            if signer.sign_whole_tx() {
+                signer.sign(&mut psbt, None)?;
+            } else {
+                for index in 0..psbt.inputs.len() {
+                    signer.sign(&mut psbt, Some(index))?;
+                }
+            }
+        }
+
+        // attempt to finalize
+        self.finalize_psbt(psbt, assume_height)
+    }
+
+    /// Return the spending policies for the wallet's descriptor
+    pub fn policies(&self, script_type: ScriptType) -> Result<Option<Policy>, Error> {
+        match (script_type, self.change_descriptor.as_ref()) {
+            (ScriptType::External, _) => {
+                Ok(self.descriptor.extract_policy(Arc::clone(&self.signers))?)
+            }
+            (ScriptType::Internal, None) => Ok(None),
+            (ScriptType::Internal, Some(desc)) => {
+                Ok(desc.extract_policy(Arc::clone(&self.change_signers))?)
+            }
+        }
+    }
+
+    /// Return the "public" version of the wallet's descriptor, meaning a new descriptor that has
+    /// the same structure but with every secret key removed
+    ///
+    /// This can be used to build a watch-only version of a wallet
+    pub fn public_descriptor(
+        &self,
+        script_type: ScriptType,
+    ) -> Result<Option<ExtendedDescriptor>, Error> {
+        match (script_type, self.change_descriptor.as_ref()) {
+            (ScriptType::External, _) => Ok(Some(self.descriptor.clone())),
+            (ScriptType::Internal, None) => Ok(None),
+            (ScriptType::Internal, Some(desc)) => Ok(Some(desc.clone())),
+        }
+    }
+
+    /// Try to finalize a PSBT
+    pub fn finalize_psbt(
+        &self,
+        mut psbt: PSBT,
+        assume_height: Option<u32>,
+    ) -> Result<(PSBT, bool), Error> {
+        let mut tx = psbt.global.unsigned_tx.clone();
+
+        for (n, (input, psbt_input)) in tx.input.iter_mut().zip(psbt.inputs.iter()).enumerate() {
+            // if the height is None in the database it means it's still unconfirmed, so consider
+            // that as a very high value
+            let create_height = self
+                .database
+                .borrow()
+                .get_tx(&input.previous_output.txid, false)?
+                .and_then(|tx| Some(tx.height.unwrap_or(std::u32::MAX)));
+            let current_height = assume_height.or(self.current_height);
+
+            debug!(
+                "Input #{} - {}, using `create_height` = {:?}, `current_height` = {:?}",
+                n, input.previous_output, create_height, current_height
+            );
+
+            // - Try to derive the descriptor by looking at the txout. If it's in our database, we
+            //   know exactly which `script_type` to use, and which derivation index it is
+            // - If that fails, try to derive it by looking at the psbt input: the complete logic
+            //   is in `src/descriptor/mod.rs`, but it will basically look at `hd_keypaths`,
+            //   `redeem_script` and `witness_script` to determine the right derivation
+            // - If that also fails, it will try it on the internal descriptor, if present
+            let desc = if let Some(desc) = psbt
+                .get_utxo_for(n)
+                .map(|txout| self.get_descriptor_for_txout(&txout))
+                .transpose()?
+                .flatten()
+            {
+                desc
+            } else if let Some(desc) = self
+                .descriptor
+                .derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n))
+            {
+                desc
+            } else if let Some(desc) = self
+                .change_descriptor
+                .as_ref()
+                .and_then(|desc| desc.derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n)))
+            {
+                desc
+            } else {
+                debug!("Couldn't find the right derived descriptor for input {}", n);
+                return Ok((psbt, false));
+            };
+
+            match desc.satisfy(
+                input,
+                (
+                    psbt_input.clone(),
+                    After::new(current_height, false),
+                    Older::new(current_height, create_height, false),
+                ),
+            ) {
+                Ok(_) => continue,
+                Err(e) => {
+                    debug!("satisfy error {:?} for input {}", e, n);
+                    return Ok((psbt, false));
+                }
+            }
+        }
+
+        // consume tx to extract its input's script_sig and witnesses and move them into the psbt
+        for (input, psbt_input) in tx.input.into_iter().zip(psbt.inputs.iter_mut()) {
+            psbt_input.final_script_sig = Some(input.script_sig);
+            psbt_input.final_script_witness = Some(input.witness);
+        }
+
+        Ok((psbt, true))
+    }
+
+    // Internals
+
+    fn get_descriptor_for_script_type(
+        &self,
+        script_type: ScriptType,
+    ) -> (&ExtendedDescriptor, ScriptType) {
+        let desc = match script_type {
+            ScriptType::Internal if self.change_descriptor.is_some() => (
+                self.change_descriptor.as_ref().unwrap(),
+                ScriptType::Internal,
+            ),
+            _ => (&self.descriptor, ScriptType::External),
+        };
+
+        desc
+    }
+
+    fn get_descriptor_for_txout(&self, txout: &TxOut) -> Result<Option<ExtendedDescriptor>, Error> {
+        Ok(self
+            .database
+            .borrow()
+            .get_path_from_script_pubkey(&txout.script_pubkey)?
+            .map(|(script_type, child)| (self.get_descriptor_for_script_type(script_type).0, child))
+            .map(|(desc, child)| desc.derive(&[ChildNumber::from_normal_idx(child).unwrap()])))
+    }
+
+    fn get_change_address(&self) -> Result<Script, Error> {
+        let (desc, script_type) = self.get_descriptor_for_script_type(ScriptType::Internal);
+        let index = self.fetch_and_increment_index(script_type)?;
+
+        Ok(desc
+            .derive(&[ChildNumber::from_normal_idx(index).unwrap()])
+            .script_pubkey())
+    }
+
+    fn fetch_and_increment_index(&self, script_type: ScriptType) -> Result<u32, Error> {
+        let (descriptor, script_type) = self.get_descriptor_for_script_type(script_type);
+        let index = match descriptor.is_fixed() {
+            true => 0,
+            false => self
+                .database
+                .borrow_mut()
+                .increment_last_index(script_type)?,
+        };
+
+        if self
+            .database
+            .borrow()
+            .get_script_pubkey_from_path(script_type, index)?
+            .is_none()
+        {
+            self.cache_addresses(script_type, index, CACHE_ADDR_BATCH_SIZE)?;
+        }
+
+        let hd_keypaths = descriptor.get_hd_keypaths(index)?;
+        let script = descriptor
+            .derive(&[ChildNumber::from_normal_idx(index).unwrap()])
+            .script_pubkey();
+        for validator in &self.address_validators {
+            validator.validate(script_type, &hd_keypaths, &script)?;
+        }
+
+        Ok(index)
+    }
+
+    fn cache_addresses(
+        &self,
+        script_type: ScriptType,
+        from: u32,
+        mut count: u32,
+    ) -> Result<(), Error> {
+        let (descriptor, script_type) = self.get_descriptor_for_script_type(script_type);
+        if descriptor.is_fixed() {
+            if from > 0 {
+                return Ok(());
+            }
+
+            count = 1;
+        }
+
+        let mut address_batch = self.database.borrow().begin_batch();
+
+        let start_time = time::Instant::new();
+        for i in from..(from + count) {
+            address_batch.set_script_pubkey(
+                &descriptor
+                    .derive(&[ChildNumber::from_normal_idx(i).unwrap()])
+                    .script_pubkey(),
+                script_type,
+                i,
+            )?;
+        }
+
+        info!(
+            "Derivation of {} addresses from {} took {} ms",
+            count,
+            from,
+            start_time.elapsed().as_millis()
+        );
+
+        self.database.borrow_mut().commit_batch(address_batch)?;
+
+        Ok(())
+    }
+
+    fn get_available_utxos(
+        &self,
+        change_policy: tx_builder::ChangeSpendPolicy,
+        utxo: &Option<Vec<OutPoint>>,
+        unspendable: &Option<Vec<OutPoint>>,
+        send_all: bool,
+    ) -> Result<(Vec<UTXO>, bool), Error> {
+        let unspendable_set = match unspendable {
+            None => HashSet::new(),
+            Some(vec) => vec.into_iter().collect(),
+        };
+
+        match utxo {
+            // with manual coin selection we always want to spend all the selected utxos, no matter
+            // what (even if they are marked as unspendable)
+            Some(raw_utxos) => {
+                let full_utxos = raw_utxos
+                    .iter()
+                    .map(|u| self.database.borrow().get_utxo(&u))
+                    .collect::<Result<Vec<_>, _>>()?;
+                if !full_utxos.iter().all(|u| u.is_some()) {
+                    return Err(Error::UnknownUTXO);
+                }
+
+                Ok((full_utxos.into_iter().map(|x| x.unwrap()).collect(), true))
+            }
+            // otherwise limit ourselves to the spendable utxos for the selected policy, and the `send_all` setting
+            None => {
+                let utxos = self.list_unspent()?.into_iter();
+                let utxos = change_policy.filter_utxos(utxos).into_iter();
+
+                Ok((
+                    utxos
+                        .filter(|u| !unspendable_set.contains(&u.outpoint))
+                        .collect(),
+                    send_all,
+                ))
+            }
+        }
+    }
+
+    fn complete_transaction<Cs: coin_selection::CoinSelectionAlgorithm>(
+        &self,
+        tx: Transaction,
+        prev_script_pubkeys: HashMap<OutPoint, Script>,
+        builder: TxBuilder<Cs>,
+    ) -> Result<PSBT, Error> {
+        let mut psbt = PSBT::from_unsigned_tx(tx)?;
+
+        // add metadata for the inputs
+        for (psbt_input, input) in psbt
+            .inputs
+            .iter_mut()
+            .zip(psbt.global.unsigned_tx.input.iter())
+        {
+            let prev_script = match prev_script_pubkeys.get(&input.previous_output) {
+                Some(prev_script) => prev_script,
+                None => continue,
+            };
+
+            // Add sighash, default is obviously "ALL"
+            psbt_input.sighash_type = builder.sighash.or(Some(SigHashType::All));
+
+            // Try to find the prev_script in our db to figure out if this is internal or external,
+            // and the derivation index
+            let (script_type, child) = match self
+                .database
+                .borrow()
+                .get_path_from_script_pubkey(&prev_script)?
+            {
+                Some(x) => x,
+                None => continue,
+            };
+
+            let (desc, _) = self.get_descriptor_for_script_type(script_type);
+            psbt_input.hd_keypaths = desc.get_hd_keypaths(child)?;
+            let derived_descriptor = desc.derive(&[ChildNumber::from_normal_idx(child).unwrap()]);
+
+            psbt_input.redeem_script = derived_descriptor.psbt_redeem_script();
+            psbt_input.witness_script = derived_descriptor.psbt_witness_script();
+
+            let prev_output = input.previous_output;
+            if let Some(prev_tx) = self.database.borrow().get_raw_tx(&prev_output.txid)? {
+                if derived_descriptor.is_witness() {
+                    psbt_input.witness_utxo =
+                        Some(prev_tx.output[prev_output.vout as usize].clone());
+                }
+                if !derived_descriptor.is_witness() || builder.force_non_witness_utxo {
+                    psbt_input.non_witness_utxo = Some(prev_tx);
+                }
+            }
+        }
+
+        // probably redundant but it doesn't hurt...
+        self.add_input_hd_keypaths(&mut psbt)?;
+
+        // add metadata for the outputs
+        for (psbt_output, tx_output) in psbt
+            .outputs
+            .iter_mut()
+            .zip(psbt.global.unsigned_tx.output.iter())
+        {
+            if let Some((script_type, child)) = self
+                .database
+                .borrow()
+                .get_path_from_script_pubkey(&tx_output.script_pubkey)?
+            {
+                let (desc, _) = self.get_descriptor_for_script_type(script_type);
+                psbt_output.hd_keypaths = desc.get_hd_keypaths(child)?;
+            }
+        }
+
+        Ok(psbt)
+    }
+
+    fn add_input_hd_keypaths(&self, psbt: &mut PSBT) -> Result<(), Error> {
+        let mut input_utxos = Vec::with_capacity(psbt.inputs.len());
+        for n in 0..psbt.inputs.len() {
+            input_utxos.push(psbt.get_utxo_for(n).clone());
+        }
+
+        // try to add hd_keypaths if we've already seen the output
+        for (psbt_input, out) in psbt.inputs.iter_mut().zip(input_utxos.iter()) {
+            if let Some(out) = out {
+                if let Some((script_type, child)) = self
+                    .database
+                    .borrow()
+                    .get_path_from_script_pubkey(&out.script_pubkey)?
+                {
+                    debug!("Found descriptor {:?}/{}", script_type, child);
+
+                    // merge hd_keypaths
+                    let (desc, _) = self.get_descriptor_for_script_type(script_type);
+                    let mut hd_keypaths = desc.get_hd_keypaths(child)?;
+                    psbt_input.hd_keypaths.append(&mut hd_keypaths);
+                }
+            }
+        }
+
+        Ok(())
+    }
+}
+
+impl<B, D> Wallet<B, D>
+where
+    B: Blockchain,
+    D: BatchDatabase,
+{
+    /// Create a new "online" wallet
+    #[maybe_async]
+    pub fn new(
+        descriptor: &str,
+        change_descriptor: Option<&str>,
+        network: Network,
+        database: D,
+        client: B,
+    ) -> Result<Self, Error> {
+        let mut wallet = Self::new_offline(descriptor, change_descriptor, network, database)?;
+
+        wallet.current_height = Some(maybe_await!(client.get_height())? as u32);
+        wallet.client = Some(client);
+
+        Ok(wallet)
+    }
+
+    /// Sync the internal database with the blockchain
+    #[maybe_async]
+    pub fn sync<P: 'static + Progress>(
+        &self,
+        progress_update: P,
+        max_address_param: Option<u32>,
+    ) -> Result<(), Error> {
+        debug!("Begin sync...");
+
+        let mut run_setup = false;
+
+        let max_address = match self.descriptor.is_fixed() {
+            true => 0,
+            false => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
+        };
+        if self
+            .database
+            .borrow()
+            .get_script_pubkey_from_path(ScriptType::External, max_address)?
+            .is_none()
+        {
+            run_setup = true;
+            self.cache_addresses(ScriptType::External, 0, max_address)?;
+        }
+
+        if let Some(change_descriptor) = &self.change_descriptor {
+            let max_address = match change_descriptor.is_fixed() {
+                true => 0,
+                false => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
+            };
+
+            if self
+                .database
+                .borrow()
+                .get_script_pubkey_from_path(
+                    ScriptType::Internal,
+                    max_address.checked_sub(1).unwrap_or(0),
+                )?
+                .is_none()
+            {
+                run_setup = true;
+                self.cache_addresses(ScriptType::Internal, 0, max_address)?;
+            }
+        }
+
+        // TODO: what if i generate an address first and cache some addresses?
+        // TODO: we should sync if generating an address triggers a new batch to be stored
+        if run_setup {
+            maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.setup(
+                None,
+                self.database.borrow_mut().deref_mut(),
+                progress_update,
+            ))
+        } else {
+            maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.sync(
+                None,
+                self.database.borrow_mut().deref_mut(),
+                progress_update,
+            ))
+        }
+    }
+
+    /// Return a reference to the internal blockchain client
+    pub fn client(&self) -> Option<&B> {
+        self.client.as_ref()
+    }
+
+    /// Broadcast a transaction to the network
+    #[maybe_async]
+    pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error> {
+        maybe_await!(self
+            .client
+            .as_ref()
+            .ok_or(Error::OfflineClient)?
+            .broadcast(&tx))?;
+
+        Ok(tx.txid())
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::Network;
+
+    use crate::database::memory::MemoryDatabase;
+    use crate::database::Database;
+    use crate::types::ScriptType;
+
+    use super::*;
+
+    #[test]
+    fn test_cache_addresses_fixed() {
+        let db = MemoryDatabase::new();
+        let wallet: OfflineWallet<_> = Wallet::new_offline(
+            "wpkh(L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6)",
+            None,
+            Network::Testnet,
+            db,
+        )
+        .unwrap();
+
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
+        );
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
+        );
+
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(ScriptType::External, 0)
+            .unwrap()
+            .is_some());
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(ScriptType::Internal, 0)
+            .unwrap()
+            .is_none());
+    }
+
+    #[test]
+    fn test_cache_addresses() {
+        let db = MemoryDatabase::new();
+        let wallet: OfflineWallet<_> = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
+
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
+        );
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
+        );
+
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE - 1)
+            .unwrap()
+            .is_some());
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE)
+            .unwrap()
+            .is_none());
+    }
+
+    #[test]
+    fn test_cache_addresses_refill() {
+        let db = MemoryDatabase::new();
+        let wallet: OfflineWallet<_> = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
+
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
+        );
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE - 1)
+            .unwrap()
+            .is_some());
+
+        for _ in 0..CACHE_ADDR_BATCH_SIZE {
+            wallet.get_new_address().unwrap();
+        }
+
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE * 2 - 1)
+            .unwrap()
+            .is_some());
+    }
+
+    pub(crate) fn get_test_wpkh() -> &'static str {
+        "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)"
+    }
+
+    pub(crate) fn get_test_single_sig_csv() -> &'static str {
+        // and(pk(Alice),older(6))
+        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),older(6)))"
+    }
+
+    pub(crate) fn get_test_single_sig_cltv() -> &'static str {
+        // and(pk(Alice),after(100000))
+        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100000)))"
+    }
+
+    pub(crate) fn get_funded_wallet(
+        descriptor: &str,
+    ) -> (
+        OfflineWallet<MemoryDatabase>,
+        (String, Option<String>),
+        bitcoin::Txid,
+    ) {
+        let descriptors = testutils!(@descriptors (descriptor));
+        let wallet: OfflineWallet<_> = Wallet::new_offline(
+            &descriptors.0,
+            None,
+            Network::Regtest,
+            MemoryDatabase::new(),
+        )
+        .unwrap();
+
+        let txid = wallet.database.borrow_mut().received_tx(
+            testutils! {
+                @tx ( (@external descriptors, 0) => 50_000 ) (@confirmations 1)
+            },
+            Some(100),
+        );
+
+        (wallet, descriptors, txid)
+    }
+
+    macro_rules! assert_fee_rate {
+        ($tx:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({
+            let mut tx = $tx.clone();
+            $(
+                $( $add_signature )*
+                for txin in &mut tx.input {
+                    txin.witness.push([0x00; 108].to_vec()); // fake signature
+                }
+            )*
+
+            #[allow(unused_mut)]
+            #[allow(unused_assignments)]
+            let mut dust_change = false;
+            $(
+                $( $dust_change )*
+                dust_change = true;
+            )*
+
+            let tx_fee_rate = $fees as f32 / (tx.get_weight() as f32 / 4.0);
+            let fee_rate = $fee_rate.as_sat_vb();
+
+            if !dust_change {
+                assert!((tx_fee_rate - fee_rate).abs() < 0.5, format!("Expected fee rate of {}, the tx has {}", fee_rate, tx_fee_rate));
+            } else {
+                assert!(tx_fee_rate >= fee_rate, format!("Expected fee rate of at least {}, the tx has {}", fee_rate, tx_fee_rate));
+            }
+        });
+    }
+
+    #[test]
+    #[should_panic(expected = "NoAddressees")]
+    fn test_create_tx_empty_recipients() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        wallet
+            .create_tx(TxBuilder::with_recipients(vec![]).version(0))
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "Invalid version `0`")]
+    fn test_create_tx_version_0() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(0))
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
+    )]
+    fn test_create_tx_version_1_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(1))
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_custom_version() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(42))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.version, 42);
+    }
+
+    #[test]
+    fn test_create_tx_default_locktime() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 0);
+    }
+
+    #[test]
+    fn test_create_tx_default_locktime_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 100_000);
+    }
+
+    #[test]
+    fn test_create_tx_custom_locktime() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(630_000),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
+    }
+
+    #[test]
+    fn test_create_tx_custom_locktime_compatible_with_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(630_000),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "TxBuilder requested timelock of `50000`, but at least `100000` is required to spend from this script"
+    )]
+    fn test_create_tx_custom_locktime_incompatible_with_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(50000),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_no_rbf_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
+    }
+
+    #[test]
+    fn test_create_tx_with_default_rbf_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFD);
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "Cannot enable RBF with nSequence `3`, since at least `6` is required to spend with OP_CSV"
+    )]
+    fn test_create_tx_with_custom_rbf_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .enable_rbf_with_sequence(3),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_no_rbf_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFE);
+    }
+
+    #[test]
+    #[should_panic(expected = "Cannot enable RBF with a nSequence >= 0xFFFFFFFE")]
+    fn test_create_tx_invalid_rbf_sequence() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .enable_rbf_with_sequence(0xFFFFFFFE),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_custom_rbf_sequence() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .enable_rbf_with_sequence(0xDEADBEEF),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xDEADBEEF);
+    }
+
+    #[test]
+    fn test_create_tx_default_sequence() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "The `change_policy` can be set only if the wallet has a change_descriptor"
+    )]
+    fn test_create_tx_change_policy_no_internal() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .do_not_spend_change(),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "SendAllMultipleOutputs")]
+    fn test_create_tx_send_all_multiple_outputs() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![
+                    (addr.script_pubkey(), 25_000),
+                    (addr.script_pubkey(), 10_000),
+                ])
+                .send_all(),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_send_all() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[0].value,
+            50_000 - details.fees
+        );
+    }
+
+    #[test]
+    fn test_create_tx_default_fee_rate() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::default(), @add_signature);
+    }
+
+    #[test]
+    fn test_create_tx_custom_fee_rate() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
+                    .fee_rate(FeeRate::from_sat_per_vb(5.0))
+                    .send_all(),
+            )
+            .unwrap();
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
+    }
+
+    #[test]
+    fn test_create_tx_add_change() {
+        use super::tx_builder::TxOrdering;
+
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .ordering(TxOrdering::Untouched),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 2);
+        assert_eq!(psbt.global.unsigned_tx.output[0].value, 25_000);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[1].value,
+            25_000 - details.fees
+        );
+    }
+
+    #[test]
+    fn test_create_tx_skip_change_dust() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                49_800,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
+        assert_eq!(psbt.global.unsigned_tx.output[0].value, 49_800);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_create_tx_send_all_dust_amount() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        // very high fee rate, so that the only output would be below dust
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
+                    .send_all()
+                    .fee_rate(crate::FeeRate::from_sat_per_vb(453.0)),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_ordering_respected() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![
+                    (addr.script_pubkey(), 30_000),
+                    (addr.script_pubkey(), 10_000),
+                ])
+                .ordering(super::tx_builder::TxOrdering::BIP69Lexicographic),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 3);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[0].value,
+            10_000 - details.fees
+        );
+        assert_eq!(psbt.global.unsigned_tx.output[1].value, 10_000);
+        assert_eq!(psbt.global.unsigned_tx.output[2].value, 30_000);
+    }
+
+    #[test]
+    fn test_create_tx_default_sighash() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                30_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.inputs[0].sighash_type, Some(bitcoin::SigHashType::All));
+    }
+
+    #[test]
+    fn test_create_tx_custom_sighash() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 30_000)])
+                    .sighash(bitcoin::SigHashType::Single),
+            )
+            .unwrap();
+
+        assert_eq!(
+            psbt.inputs[0].sighash_type,
+            Some(bitcoin::SigHashType::Single)
+        );
+    }
+
+    #[test]
+    fn test_create_tx_input_hd_keypaths() {
+        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
+        use std::str::FromStr;
+
+        let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*)");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert_eq!(psbt.inputs[0].hd_keypaths.len(), 1);
+        assert_eq!(
+            psbt.inputs[0].hd_keypaths.values().nth(0).unwrap(),
+            &(
+                Fingerprint::from_str("d34db33f").unwrap(),
+                DerivationPath::from_str("m/44'/0'/0'/0/0").unwrap()
+            )
+        );
+    }
+
+    #[test]
+    fn test_create_tx_output_hd_keypaths() {
+        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
+        use std::str::FromStr;
+
+        let (wallet, descriptors, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*)");
+        // cache some addresses
+        wallet.get_new_address().unwrap();
+
+        let addr = testutils!(@external descriptors, 5);
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert_eq!(psbt.outputs[0].hd_keypaths.len(), 1);
+        assert_eq!(
+            psbt.outputs[0].hd_keypaths.values().nth(0).unwrap(),
+            &(
+                Fingerprint::from_str("d34db33f").unwrap(),
+                DerivationPath::from_str("m/44'/0'/0'/0/5").unwrap()
+            )
+        );
+    }
+
+    #[test]
+    fn test_create_tx_set_redeem_script_p2sh() {
+        use bitcoin::hashes::hex::FromHex;
+
+        let (wallet, _, _) =
+            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert_eq!(
+            psbt.inputs[0].redeem_script,
+            Some(Script::from(
+                Vec::<u8>::from_hex(
+                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
+                )
+                .unwrap()
+            ))
+        );
+        assert_eq!(psbt.inputs[0].witness_script, None);
+    }
+
+    #[test]
+    fn test_create_tx_set_witness_script_p2wsh() {
+        use bitcoin::hashes::hex::FromHex;
+
+        let (wallet, _, _) =
+            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert_eq!(psbt.inputs[0].redeem_script, None);
+        assert_eq!(
+            psbt.inputs[0].witness_script,
+            Some(Script::from(
+                Vec::<u8>::from_hex(
+                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
+                )
+                .unwrap()
+            ))
+        );
+    }
+
+    #[test]
+    fn test_create_tx_set_redeem_witness_script_p2wsh_p2sh() {
+        use bitcoin::hashes::hex::FromHex;
+
+        let (wallet, _, _) =
+            get_funded_wallet("sh(wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        let script = Script::from(
+            Vec::<u8>::from_hex(
+                "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac",
+            )
+            .unwrap(),
+        );
+
+        assert_eq!(psbt.inputs[0].redeem_script, Some(script.to_v0_p2wsh()));
+        assert_eq!(psbt.inputs[0].witness_script, Some(script));
+    }
+
+    #[test]
+    fn test_create_tx_non_witness_utxo() {
+        let (wallet, _, _) =
+            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert!(psbt.inputs[0].non_witness_utxo.is_some());
+        assert!(psbt.inputs[0].witness_utxo.is_none());
+    }
+
+    #[test]
+    fn test_create_tx_only_witness_utxo() {
+        let (wallet, _, _) =
+            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert!(psbt.inputs[0].non_witness_utxo.is_none());
+        assert!(psbt.inputs[0].witness_utxo.is_some());
+    }
+
+    #[test]
+    fn test_create_tx_both_non_witness_utxo_and_witness_utxo() {
+        let (wallet, _, _) =
+            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
+                    .force_non_witness_utxo()
+                    .send_all(),
+            )
+            .unwrap();
+
+        assert!(psbt.inputs[0].non_witness_utxo.is_some());
+        assert!(psbt.inputs[0].witness_utxo.is_some());
+    }
+
+    #[test]
+    #[should_panic(expected = "IrreplaceableTransaction")]
+    fn test_bump_fee_irreplaceable_tx() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, mut details) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        wallet.bump_fee(&txid, TxBuilder::new()).unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "TransactionConfirmed")]
+    fn test_bump_fee_confirmed_tx() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, mut details) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        details.height = Some(42);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        wallet.bump_fee(&txid, TxBuilder::new()).unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "FeeRateTooLow")]
+    fn test_bump_fee_low_fee_rate() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, mut details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(1.0)),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_bump_fee_reduce_change() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(2.5)),
+            )
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent);
+        assert_eq!(
+            details.received + details.fees,
+            original_details.received + original_details.fees
+        );
+        assert!(details.fees > original_details.fees);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            25_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(2.5), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_reduce_send_all() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
+                    .send_all()
+                    .enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new()
+                    .send_all()
+                    .fee_rate(FeeRate::from_sat_per_vb(2.5)),
+            )
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent);
+        assert!(details.fees > original_details.fees);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.output.len(), 1);
+        assert_eq!(tx.output[0].value + details.fees, details.sent);
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(2.5), @add_signature);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_bump_fee_remove_send_all_output() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        // receive an extra tx, to make sure that in case of "send_all" we get an error and it
+        // doesn't try to pick more inputs
+        let incoming_txid = wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
+                    .utxos(vec![OutPoint {
+                        txid: incoming_txid,
+                        vout: 0,
+                    }])
+                    .send_all()
+                    .enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+        assert_eq!(original_details.sent, 25_000);
+
+        wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new()
+                    .send_all()
+                    .fee_rate(FeeRate::from_sat_per_vb(225.0)),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_bump_fee_add_input() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(50.0)),
+            )
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fees + details.received, 30_000);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(50.0), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_no_change_add_input_and_change() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        let incoming_txid = wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
+                    .send_all()
+                    .add_utxo(OutPoint {
+                        txid: incoming_txid,
+                        vout: 0,
+                    })
+                    .enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        // NOTE: we don't set "send_all" here. so we have a transaction with only one input, but
+        // here we are allowed to add more, and we will also have to add a change
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(50.0)),
+            )
+            .unwrap();
+
+        let original_send_all_amount = original_details.sent - original_details.fees;
+        assert_eq!(details.sent, original_details.sent + 50_000);
+        assert_eq!(
+            details.received,
+            75_000 - original_send_all_amount - details.fees
+        );
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            original_send_all_amount
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            75_000 - original_send_all_amount - details.fees
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(50.0), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_add_input_change_dust() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        assert_eq!(tx.input.len(), 1);
+        assert_eq!(tx.output.len(), 2);
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(140.0)),
+            )
+            .unwrap();
+
+        assert_eq!(original_details.received, 5_000 - original_details.fees);
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fees, 30_000);
+        assert_eq!(details.received, 0);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 1);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(140.0), @dust_change, @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_force_add_input() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        let incoming_txid = wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        // the new fee_rate is low enough that just reducing the change would be fine, but we force
+        // the addition of an extra input with `add_utxo()`
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new()
+                    .add_utxo(OutPoint {
+                        txid: incoming_txid,
+                        vout: 0,
+                    })
+                    .fee_rate(FeeRate::from_sat_per_vb(5.0)),
+            )
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fees + details.received, 30_000);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
+    }
+
+    #[test]
+    fn test_sign_single_xprv() {
+        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
+        assert_eq!(finalized, true);
+
+        let extracted = signed_psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_sign_single_wif() {
+        let (wallet, _, _) =
+            get_funded_wallet("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
+        assert_eq!(finalized, true);
+
+        let extracted = signed_psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_sign_single_xprv_no_hd_keypaths() {
+        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
+        let addr = wallet.get_new_address().unwrap();
+        let (mut psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        psbt.inputs[0].hd_keypaths.clear();
+        assert_eq!(psbt.inputs[0].hd_keypaths.len(), 0);
+
+        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
+        assert_eq!(finalized, true);
+
+        let extracted = signed_psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/rbf.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/rbf.rs.html new file mode 100644 index 0000000000..2f536bf64b --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/rbf.rs.html @@ -0,0 +1,257 @@ +rbf.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use crate::database::Database;
+use crate::error::Error;
+use crate::types::*;
+
+/// Filters unspent utxos
+pub(super) fn filter_available<I: Iterator<Item = UTXO>, D: Database>(
+    database: &D,
+    iter: I,
+) -> Result<Vec<UTXO>, Error> {
+    Ok(iter
+        .map(|utxo| {
+            Ok(match database.get_tx(&utxo.outpoint.txid, true)? {
+                None => None,
+                Some(tx) if tx.height.is_none() => None,
+                Some(_) => Some(utxo),
+            })
+        })
+        .collect::<Result<Vec<_>, Error>>()?
+        .into_iter()
+        .filter_map(|x| x)
+        .collect())
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::{OutPoint, Transaction, TxIn, TxOut, Txid};
+
+    use super::*;
+    use crate::database::{BatchOperations, MemoryDatabase};
+
+    fn add_transaction(
+        database: &mut MemoryDatabase,
+        spend: Vec<OutPoint>,
+        outputs: Vec<u64>,
+    ) -> Txid {
+        let tx = Transaction {
+            version: 1,
+            lock_time: 0,
+            input: spend
+                .iter()
+                .cloned()
+                .map(|previous_output| TxIn {
+                    previous_output,
+                    ..Default::default()
+                })
+                .collect(),
+            output: outputs
+                .iter()
+                .cloned()
+                .map(|value| TxOut {
+                    value,
+                    ..Default::default()
+                })
+                .collect(),
+        };
+        let txid = tx.txid();
+
+        for input in &spend {
+            database.del_utxo(input).unwrap();
+        }
+        for vout in 0..outputs.len() {
+            database
+                .set_utxo(&UTXO {
+                    txout: tx.output[vout].clone(),
+                    outpoint: OutPoint {
+                        txid,
+                        vout: vout as u32,
+                    },
+                    is_internal: true,
+                })
+                .unwrap();
+        }
+        database
+            .set_tx(&TransactionDetails {
+                txid,
+                transaction: Some(tx),
+                height: None,
+                ..Default::default()
+            })
+            .unwrap();
+
+        txid
+    }
+
+    #[test]
+    fn test_filter_available() {
+        let mut database = MemoryDatabase::new();
+        add_transaction(
+            &mut database,
+            vec![OutPoint::from_str(
+                "aad194c72fd5cfd16d23da9462930ca91e35df1cfee05242b62f4034f50c3d41:5",
+            )
+            .unwrap()],
+            vec![50_000],
+        );
+
+        let filtered =
+            filter_available(&database, database.iter_utxos().unwrap().into_iter()).unwrap();
+        assert_eq!(filtered, &[]);
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/signer.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/signer.rs.html new file mode 100644 index 0000000000..8678817881 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/signer.rs.html @@ -0,0 +1,1029 @@ +signer.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Generalized signers
+//!
+//! This module provides the ability to add customized signers to a [`Wallet`](super::Wallet)
+//! through the [`Wallet::add_signer`](super::Wallet::add_signer) function.
+//!
+//! ```
+//! # use std::sync::Arc;
+//! # use std::str::FromStr;
+//! # use bitcoin::*;
+//! # use bitcoin::util::psbt;
+//! # use bitcoin::util::bip32::Fingerprint;
+//! # use bdk::signer::*;
+//! # use bdk::database::*;
+//! # use bdk::*;
+//! # #[derive(Debug)]
+//! # struct CustomHSM;
+//! # impl CustomHSM {
+//! #     fn sign_input(&self, _psbt: &mut psbt::PartiallySignedTransaction, _input: usize) -> Result<(), SignerError> {
+//! #         Ok(())
+//! #     }
+//! #     fn connect() -> Self {
+//! #         CustomHSM
+//! #     }
+//! # }
+//! #[derive(Debug)]
+//! struct CustomSigner {
+//!     device: CustomHSM,
+//! }
+//!
+//! impl CustomSigner {
+//!     fn connect() -> Self {
+//!         CustomSigner { device: CustomHSM::connect() }
+//!     }
+//! }
+//!
+//! impl Signer for CustomSigner {
+//!     fn sign(
+//!         &self,
+//!         psbt: &mut psbt::PartiallySignedTransaction,
+//!         input_index: Option<usize>,
+//!     ) -> Result<(), SignerError> {
+//!         let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
+//!         self.device.sign_input(psbt, input_index)?;
+//!
+//!         Ok(())
+//!     }
+//!
+//!     fn sign_whole_tx(&self) -> bool {
+//!         false
+//!     }
+//! }
+//!
+//! let custom_signer = CustomSigner::connect();
+//!
+//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+//! let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+//! wallet.add_signer(
+//!     ScriptType::External,
+//!     Fingerprint::from_str("e30f11b8").unwrap().into(),
+//!     SignerOrdering(200),
+//!     Arc::new(Box::new(custom_signer))
+//! );
+//!
+//! # Ok::<_, bdk::Error>(())
+//! ```
+
+use std::cmp::Ordering;
+use std::collections::BTreeMap;
+use std::fmt;
+use std::ops::Bound::Included;
+use std::sync::Arc;
+
+use bitcoin::blockdata::opcodes;
+use bitcoin::blockdata::script::Builder as ScriptBuilder;
+use bitcoin::hashes::{hash160, Hash};
+use bitcoin::secp256k1::{Message, Secp256k1};
+use bitcoin::util::bip32::{ExtendedPrivKey, Fingerprint};
+use bitcoin::util::{bip143, psbt};
+use bitcoin::{PrivateKey, SigHash, SigHashType};
+
+use miniscript::descriptor::{DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey, KeyMap};
+use miniscript::{Legacy, MiniscriptKey, Segwitv0};
+
+use crate::descriptor::XKeyUtils;
+
+/// Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among
+/// multiple of them
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum SignerId<Pk: MiniscriptKey> {
+    PkHash(<Pk as MiniscriptKey>::Hash),
+    Fingerprint(Fingerprint),
+}
+
+impl From<hash160::Hash> for SignerId<DescriptorPublicKey> {
+    fn from(hash: hash160::Hash) -> SignerId<DescriptorPublicKey> {
+        SignerId::PkHash(hash)
+    }
+}
+
+impl From<Fingerprint> for SignerId<DescriptorPublicKey> {
+    fn from(fing: Fingerprint) -> SignerId<DescriptorPublicKey> {
+        SignerId::Fingerprint(fing)
+    }
+}
+
+/// Signing error
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub enum SignerError {
+    /// The private key is missing for the required public key
+    MissingKey,
+    /// The user canceled the operation
+    UserCanceled,
+    /// The sighash is missing in the PSBT input
+    MissingSighash,
+    /// Input index is out of range
+    InputIndexOutOfRange,
+    /// The `non_witness_utxo` field of the transaction is required to sign this input
+    MissingNonWitnessUtxo,
+    /// The `non_witness_utxo` specified is invalid
+    InvalidNonWitnessUtxo,
+    /// The `witness_utxo` field of the transaction is required to sign this input
+    MissingWitnessUtxo,
+    /// The `witness_script` field of the transaction is requied to sign this input
+    MissingWitnessScript,
+    /// The fingerprint and derivation path are missing from the psbt input
+    MissingHDKeypath,
+}
+
+impl fmt::Display for SignerError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for SignerError {}
+
+/// Trait for signers
+///
+/// This trait can be implemented to provide customized signers to the wallet. For an example see
+/// [`this module`](crate::wallet::signer)'s documentation.
+pub trait Signer: fmt::Debug {
+    /// Sign a PSBT
+    ///
+    /// The `input_index` argument is only provided if the wallet doesn't declare to sign the whole
+    /// transaction in one go (see [`Signer::sign_whole_tx`]). Otherwise its value is `None` and
+    /// can be ignored.
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+    ) -> Result<(), SignerError>;
+
+    /// Return whether or not the signer signs the whole transaction in one go instead of every
+    /// input individually
+    fn sign_whole_tx(&self) -> bool;
+
+    /// Return the secret key for the signer
+    ///
+    /// This is used internally to reconstruct the original descriptor that may contain secrets.
+    /// External signers that are meant to keep key isolated should just return `None` here (which
+    /// is the default for this method, if not overridden).
+    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
+        None
+    }
+}
+
+impl Signer for DescriptorXKey<ExtendedPrivKey> {
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+    ) -> Result<(), SignerError> {
+        let input_index = input_index.unwrap();
+        if input_index >= psbt.inputs.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let deriv_path = match psbt.inputs[input_index]
+            .hd_keypaths
+            .iter()
+            .filter_map(|(_, &(fingerprint, ref path))| self.matches(fingerprint.clone(), &path))
+            .next()
+        {
+            Some(deriv_path) => deriv_path,
+            None => return Ok(()), // TODO: should report an error maybe?
+        };
+
+        let ctx = Secp256k1::signing_only();
+
+        let derived_key = self.xkey.derive_priv(&ctx, &deriv_path).unwrap();
+        derived_key.private_key.sign(psbt, Some(input_index))
+    }
+
+    fn sign_whole_tx(&self) -> bool {
+        false
+    }
+
+    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
+        Some(DescriptorSecretKey::XPrv(self.clone()))
+    }
+}
+
+impl Signer for PrivateKey {
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+    ) -> Result<(), SignerError> {
+        let input_index = input_index.unwrap();
+        if input_index >= psbt.inputs.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let ctx = Secp256k1::signing_only();
+
+        let pubkey = self.public_key(&ctx);
+        if psbt.inputs[input_index].partial_sigs.contains_key(&pubkey) {
+            return Ok(());
+        }
+
+        // FIXME: use the presence of `witness_utxo` as an indication that we should make a bip143
+        // sig. Does this make sense? Should we add an extra argument to explicitly swith between
+        // these? The original idea was to declare sign() as sign<Ctx: ScriptContex>() and use Ctx,
+        // but that violates the rules for trait-objects, so we can't do it.
+        let (hash, sighash) = match psbt.inputs[input_index].witness_utxo {
+            Some(_) => Segwitv0::sighash(psbt, input_index)?,
+            None => Legacy::sighash(psbt, input_index)?,
+        };
+
+        let signature = ctx.sign(
+            &Message::from_slice(&hash.into_inner()[..]).unwrap(),
+            &self.key,
+        );
+
+        let mut final_signature = Vec::with_capacity(75);
+        final_signature.extend_from_slice(&signature.serialize_der());
+        final_signature.push(sighash.as_u32() as u8);
+
+        psbt.inputs[input_index]
+            .partial_sigs
+            .insert(pubkey, final_signature);
+
+        Ok(())
+    }
+
+    fn sign_whole_tx(&self) -> bool {
+        false
+    }
+
+    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
+        Some(DescriptorSecretKey::PrivKey(self.clone()))
+    }
+}
+
+/// Defines the order in which signers are called
+///
+/// The default value is `100`. Signers with an ordering above that will be called later,
+/// and they will thus see the partial signatures added to the transaction once they get to sign
+/// themselves.
+#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)]
+pub struct SignerOrdering(pub usize);
+
+impl std::default::Default for SignerOrdering {
+    fn default() -> Self {
+        SignerOrdering(100)
+    }
+}
+
+#[derive(Debug, Clone)]
+struct SignersContainerKey<Pk: MiniscriptKey> {
+    id: SignerId<Pk>,
+    ordering: SignerOrdering,
+}
+
+impl<Pk: MiniscriptKey> From<(SignerId<Pk>, SignerOrdering)> for SignersContainerKey<Pk> {
+    fn from(tuple: (SignerId<Pk>, SignerOrdering)) -> Self {
+        SignersContainerKey {
+            id: tuple.0,
+            ordering: tuple.1,
+        }
+    }
+}
+
+/// Container for multiple signers
+#[derive(Debug, Default, Clone)]
+pub struct SignersContainer<Pk: MiniscriptKey>(
+    BTreeMap<SignersContainerKey<Pk>, Arc<Box<dyn Signer>>>,
+);
+
+impl SignersContainer<DescriptorPublicKey> {
+    pub fn as_key_map(&self) -> KeyMap {
+        self.0
+            .values()
+            .filter_map(|signer| signer.descriptor_secret_key())
+            .filter_map(|secret| secret.as_public().ok().map(|public| (public, secret)))
+            .collect()
+    }
+}
+
+impl From<KeyMap> for SignersContainer<DescriptorPublicKey> {
+    fn from(keymap: KeyMap) -> SignersContainer<DescriptorPublicKey> {
+        let mut container = SignersContainer::new();
+
+        for (_, secret) in keymap {
+            match secret {
+                DescriptorSecretKey::PrivKey(private_key) => container.add_external(
+                    SignerId::from(
+                        private_key
+                            .public_key(&Secp256k1::signing_only())
+                            .to_pubkeyhash(),
+                    ),
+                    SignerOrdering::default(),
+                    Arc::new(Box::new(private_key)),
+                ),
+                DescriptorSecretKey::XPrv(xprv) => container.add_external(
+                    SignerId::from(xprv.root_fingerprint()),
+                    SignerOrdering::default(),
+                    Arc::new(Box::new(xprv)),
+                ),
+            };
+        }
+
+        container
+    }
+}
+
+impl<Pk: MiniscriptKey> SignersContainer<Pk> {
+    /// Default constructor
+    pub fn new() -> Self {
+        SignersContainer(Default::default())
+    }
+
+    /// Adds an external signer to the container for the specified id. Optionally returns the
+    /// signer that was previosuly in the container, if any
+    pub fn add_external(
+        &mut self,
+        id: SignerId<Pk>,
+        ordering: SignerOrdering,
+        signer: Arc<Box<dyn Signer>>,
+    ) -> Option<Arc<Box<dyn Signer>>> {
+        self.0.insert((id, ordering).into(), signer)
+    }
+
+    /// Removes a signer from the container and returns it
+    pub fn remove(
+        &mut self,
+        id: SignerId<Pk>,
+        ordering: SignerOrdering,
+    ) -> Option<Arc<Box<dyn Signer>>> {
+        self.0.remove(&(id, ordering).into())
+    }
+
+    /// Returns the list of identifiers of all the signers in the container
+    pub fn ids(&self) -> Vec<&SignerId<Pk>> {
+        self.0
+            .keys()
+            .map(|SignersContainerKey { id, .. }| id)
+            .collect()
+    }
+
+    /// Returns the list of signers in the container, sorted by lowest to highest `ordering`
+    pub fn signers(&self) -> Vec<&Arc<Box<dyn Signer>>> {
+        self.0.values().collect()
+    }
+
+    /// Finds the signer with lowest ordering for a given id in the container.
+    pub fn find(&self, id: SignerId<Pk>) -> Option<&Arc<Box<dyn Signer>>> {
+        self.0
+            .range((
+                Included(&(id.clone(), SignerOrdering(0)).into()),
+                Included(&(id, SignerOrdering(usize::MAX)).into()),
+            ))
+            .map(|(_, v)| v)
+            .nth(0)
+    }
+}
+
+pub(crate) trait ComputeSighash {
+    fn sighash(
+        psbt: &psbt::PartiallySignedTransaction,
+        input_index: usize,
+    ) -> Result<(SigHash, SigHashType), SignerError>;
+}
+
+impl ComputeSighash for Legacy {
+    fn sighash(
+        psbt: &psbt::PartiallySignedTransaction,
+        input_index: usize,
+    ) -> Result<(SigHash, SigHashType), SignerError> {
+        if input_index >= psbt.inputs.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let psbt_input = &psbt.inputs[input_index];
+        let tx_input = &psbt.global.unsigned_tx.input[input_index];
+
+        let sighash = psbt_input.sighash_type.ok_or(SignerError::MissingSighash)?;
+        let script = match &psbt_input.redeem_script {
+            &Some(ref redeem_script) => redeem_script.clone(),
+            &None => {
+                let non_witness_utxo = psbt_input
+                    .non_witness_utxo
+                    .as_ref()
+                    .ok_or(SignerError::MissingNonWitnessUtxo)?;
+                let prev_out = non_witness_utxo
+                    .output
+                    .get(tx_input.previous_output.vout as usize)
+                    .ok_or(SignerError::InvalidNonWitnessUtxo)?;
+
+                prev_out.script_pubkey.clone()
+            }
+        };
+
+        Ok((
+            psbt.global
+                .unsigned_tx
+                .signature_hash(input_index, &script, sighash.as_u32()),
+            sighash,
+        ))
+    }
+}
+
+impl ComputeSighash for Segwitv0 {
+    fn sighash(
+        psbt: &psbt::PartiallySignedTransaction,
+        input_index: usize,
+    ) -> Result<(SigHash, SigHashType), SignerError> {
+        if input_index >= psbt.inputs.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let psbt_input = &psbt.inputs[input_index];
+
+        let sighash = psbt_input.sighash_type.ok_or(SignerError::MissingSighash)?;
+
+        let witness_utxo = psbt_input
+            .witness_utxo
+            .as_ref()
+            .ok_or(SignerError::MissingNonWitnessUtxo)?;
+        let value = witness_utxo.value;
+
+        let script = match &psbt_input.witness_script {
+            &Some(ref witness_script) => witness_script.clone(),
+            &None => {
+                if witness_utxo.script_pubkey.is_v0_p2wpkh() {
+                    ScriptBuilder::new()
+                        .push_opcode(opcodes::all::OP_DUP)
+                        .push_opcode(opcodes::all::OP_HASH160)
+                        .push_slice(&witness_utxo.script_pubkey[2..])
+                        .push_opcode(opcodes::all::OP_EQUALVERIFY)
+                        .push_opcode(opcodes::all::OP_CHECKSIG)
+                        .into_script()
+                } else {
+                    return Err(SignerError::MissingWitnessScript);
+                }
+            }
+        };
+
+        Ok((
+            bip143::SigHashCache::new(&psbt.global.unsigned_tx).signature_hash(
+                input_index,
+                &script,
+                value,
+                sighash,
+            ),
+            sighash,
+        ))
+    }
+}
+
+impl<Pk: MiniscriptKey> PartialOrd for SignersContainerKey<Pk> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl<Pk: MiniscriptKey> Ord for SignersContainerKey<Pk> {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.ordering.cmp(&other.ordering)
+    }
+}
+
+impl<Pk: MiniscriptKey> PartialEq for SignersContainerKey<Pk> {
+    fn eq(&self, other: &Self) -> bool {
+        self.ordering == other.ordering
+    }
+}
+
+impl<Pk: MiniscriptKey> Eq for SignersContainerKey<Pk> {}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/time.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/time.rs.html new file mode 100644 index 0000000000..a608dd4158 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/time.rs.html @@ -0,0 +1,175 @@ +time.rs.html -- source
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Cross-platform time
+//!
+//! This module provides a function to get the current timestamp that works on all the platforms
+//! supported by the library.
+//!
+//! It can be useful to compare it with the timestamps found in
+//! [`TransactionDetails`](crate::types::TransactionDetails).
+
+use std::time::Duration;
+
+#[cfg(target_arch = "wasm32")]
+use js_sys::Date;
+#[cfg(not(target_arch = "wasm32"))]
+use std::time::{Instant as SystemInstant, SystemTime, UNIX_EPOCH};
+
+/// Return the current timestamp in seconds
+#[cfg(not(target_arch = "wasm32"))]
+pub fn get_timestamp() -> u64 {
+    SystemTime::now()
+        .duration_since(UNIX_EPOCH)
+        .unwrap()
+        .as_secs()
+}
+/// Return the current timestamp in seconds
+#[cfg(target_arch = "wasm32")]
+pub fn get_timestamp() -> u64 {
+    let millis = Date::now();
+
+    (millis / 1000.0) as u64
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+pub(crate) struct Instant(SystemInstant);
+#[cfg(target_arch = "wasm32")]
+pub(crate) struct Instant(Duration);
+
+impl Instant {
+    #[cfg(not(target_arch = "wasm32"))]
+    pub fn new() -> Self {
+        Instant(SystemInstant::now())
+    }
+    #[cfg(target_arch = "wasm32")]
+    pub fn new() -> Self {
+        let millis = Date::now();
+
+        let secs = millis / 1000.0;
+        let nanos = (millis % 1000.0) * 1e6;
+
+        Instant(Duration::new(secs as u64, nanos as u32))
+    }
+
+    #[cfg(not(target_arch = "wasm32"))]
+    pub fn elapsed(&self) -> Duration {
+        self.0.elapsed()
+    }
+    #[cfg(target_arch = "wasm32")]
+    pub fn elapsed(&self) -> Duration {
+        let now = Instant::new();
+
+        now.0.checked_sub(self.0).unwrap_or(Duration::new(0, 0))
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/tx_builder.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/tx_builder.rs.html new file mode 100644 index 0000000000..389d6daf07 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/tx_builder.rs.html @@ -0,0 +1,979 @@ +tx_builder.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Transaction builder
+//!
+//! ## Example
+//!
+//! ```
+//! # use std::str::FromStr;
+//! # use bitcoin::*;
+//! # use bdk::*;
+//! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+//! // Create a transaction with one output to `to_address` of 50_000 satoshi, with a custom fee rate
+//! // of 5.0 satoshi/vbyte, only spending non-change outputs and with RBF signaling
+//! // enabled
+//! let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+//!     .fee_rate(FeeRate::from_sat_per_vb(5.0))
+//!     .do_not_spend_change()
+//!     .enable_rbf();
+//! ```
+
+use std::collections::BTreeMap;
+use std::default::Default;
+
+use bitcoin::{OutPoint, Script, SigHashType, Transaction};
+
+use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm};
+use crate::types::{FeeRate, UTXO};
+
+/// A transaction builder
+///
+/// This structure contains the configuration that the wallet must follow to build a transaction.
+///
+/// For an example see [this module](super::tx_builder)'s documentation;
+#[derive(Debug, Default)]
+pub struct TxBuilder<Cs: CoinSelectionAlgorithm> {
+    pub(crate) recipients: Vec<(Script, u64)>,
+    pub(crate) send_all: bool,
+    pub(crate) fee_rate: Option<FeeRate>,
+    pub(crate) policy_path: Option<BTreeMap<String, Vec<usize>>>,
+    pub(crate) utxos: Option<Vec<OutPoint>>,
+    pub(crate) unspendable: Option<Vec<OutPoint>>,
+    pub(crate) sighash: Option<SigHashType>,
+    pub(crate) ordering: TxOrdering,
+    pub(crate) locktime: Option<u32>,
+    pub(crate) rbf: Option<u32>,
+    pub(crate) version: Option<Version>,
+    pub(crate) change_policy: ChangeSpendPolicy,
+    pub(crate) force_non_witness_utxo: bool,
+    pub(crate) coin_selection: Cs,
+}
+
+impl TxBuilder<DefaultCoinSelectionAlgorithm> {
+    /// Create an empty builder
+    pub fn new() -> Self {
+        Self::default()
+    }
+
+    /// Create a builder starting from a list of recipients
+    pub fn with_recipients(recipients: Vec<(Script, u64)>) -> Self {
+        Self::default().set_recipients(recipients)
+    }
+}
+
+impl<Cs: CoinSelectionAlgorithm> TxBuilder<Cs> {
+    /// Replace the recipients already added with a new list
+    pub fn set_recipients(mut self, recipients: Vec<(Script, u64)>) -> Self {
+        self.recipients = recipients;
+        self
+    }
+
+    /// Add a recipient to the internal list
+    pub fn add_recipient(mut self, script_pubkey: Script, amount: u64) -> Self {
+        self.recipients.push((script_pubkey, amount));
+        self
+    }
+
+    /// Send all the selected utxos to a single output
+    ///
+    /// Adding more than one recipients with this option enabled will result in an error.
+    ///
+    /// The value associated with the only recipient is irrelevant and will be replaced by the wallet.
+    pub fn send_all(mut self) -> Self {
+        self.send_all = true;
+        self
+    }
+
+    /// Set a custom fee rate
+    pub fn fee_rate(mut self, fee_rate: FeeRate) -> Self {
+        self.fee_rate = Some(fee_rate);
+        self
+    }
+
+    /// Set the policy path to use while creating the transaction
+    ///
+    /// This method accepts a map where the key is the policy node id (see
+    /// [`Policy::id`](crate::descriptor::Policy::id)) and the value is the list of the indexes of
+    /// the items that are intended to be satisfied from the policy node (see
+    /// [`SatisfiableItem::Thresh::items`](crate::descriptor::policy::SatisfiableItem::Thresh::items)).
+    pub fn policy_path(mut self, policy_path: BTreeMap<String, Vec<usize>>) -> Self {
+        self.policy_path = Some(policy_path);
+        self
+    }
+
+    /// Replace the internal list of utxos that **must** be spent with a new list
+    ///
+    /// These have priority over the "unspendable" utxos, meaning that if a utxo is present both in
+    /// the "utxos" and the "unspendable" list, it will be spent.
+    pub fn utxos(mut self, utxos: Vec<OutPoint>) -> Self {
+        self.utxos = Some(utxos);
+        self
+    }
+
+    /// Add a utxo to the internal list of utxos that **must** be spent
+    ///
+    /// These have priority over the "unspendable" utxos, meaning that if a utxo is present both in
+    /// the "utxos" and the "unspendable" list, it will be spent.
+    pub fn add_utxo(mut self, utxo: OutPoint) -> Self {
+        self.utxos.get_or_insert(vec![]).push(utxo);
+        self
+    }
+
+    /// Replace the internal list of unspendable utxos with a new list
+    ///
+    /// It's important to note that the "must-be-spent" utxos added with [`TxBuilder::utxos`] and
+    /// [`TxBuilder::add_utxo`] have priority over these. See the docs of the two linked methods
+    /// for more details.
+    pub fn unspendable(mut self, unspendable: Vec<OutPoint>) -> Self {
+        self.unspendable = Some(unspendable);
+        self
+    }
+
+    /// Add a utxo to the internal list of unspendable utxos
+    ///
+    /// It's important to note that the "must-be-spent" utxos added with [`TxBuilder::utxos`] and
+    /// [`TxBuilder::add_utxo`] have priority over this. See the docs of the two linked methods
+    /// for more details.
+    pub fn add_unspendable(mut self, unspendable: OutPoint) -> Self {
+        self.unspendable.get_or_insert(vec![]).push(unspendable);
+        self
+    }
+
+    /// Sign with a specific sig hash
+    ///
+    /// **Use this option very carefully**
+    pub fn sighash(mut self, sighash: SigHashType) -> Self {
+        self.sighash = Some(sighash);
+        self
+    }
+
+    /// Choose the ordering for inputs and outputs of the transaction
+    pub fn ordering(mut self, ordering: TxOrdering) -> Self {
+        self.ordering = ordering;
+        self
+    }
+
+    /// Use a specific nLockTime while creating the transaction
+    ///
+    /// This can cause conflicts if the wallet's descriptors contain an "after" (OP_CLTV) operator.
+    pub fn nlocktime(mut self, locktime: u32) -> Self {
+        self.locktime = Some(locktime);
+        self
+    }
+
+    /// Enable signaling RBF
+    ///
+    /// This will use the default nSequence value of `0xFFFFFFFD`.
+    pub fn enable_rbf(self) -> Self {
+        self.enable_rbf_with_sequence(0xFFFFFFFD)
+    }
+
+    /// Enable signaling RBF with a specific nSequence value
+    ///
+    /// This can cause conflicts if the wallet's descriptors contain an "older" (OP_CSV) operator
+    /// and the given `nsequence` is lower than the CSV value.
+    ///
+    /// If the `nsequence` is higher than `0xFFFFFFFD` an error will be thrown, since it would not
+    /// be a valid nSequence to signal RBF.
+    pub fn enable_rbf_with_sequence(mut self, nsequence: u32) -> Self {
+        self.rbf = Some(nsequence);
+        self
+    }
+
+    /// Build a transaction with a specific version
+    ///
+    /// The `version` should always be greater than `0` and greater than `1` if the wallet's
+    /// descriptors contain an "older" (OP_CSV) operator.
+    pub fn version(mut self, version: u32) -> Self {
+        self.version = Some(Version(version));
+        self
+    }
+
+    /// Do not spend change outputs
+    ///
+    /// This effectively adds all the change outputs to the "unspendable" list. See
+    /// [`TxBuilder::unspendable`].
+    pub fn do_not_spend_change(mut self) -> Self {
+        self.change_policy = ChangeSpendPolicy::ChangeForbidden;
+        self
+    }
+
+    /// Only spend change outputs
+    ///
+    /// This effectively adds all the non-change outputs to the "unspendable" list. See
+    /// [`TxBuilder::unspendable`].
+    pub fn only_spend_change(mut self) -> Self {
+        self.change_policy = ChangeSpendPolicy::OnlyChange;
+        self
+    }
+
+    /// Set a specific [`ChangeSpendPolicy`]. See [`TxBuilder::do_not_spend_change`] and
+    /// [`TxBuilder::only_spend_change`] for some shortcuts.
+    pub fn change_policy(mut self, change_policy: ChangeSpendPolicy) -> Self {
+        self.change_policy = change_policy;
+        self
+    }
+
+    /// Fill-in the [`psbt::Input::non_witness_utxo`](bitcoin::util::psbt::Input::non_witness_utxo) field even if the wallet only has SegWit
+    /// descriptors.
+    ///
+    /// This is useful for signers which always require it, like Trezor hardware wallets.
+    pub fn force_non_witness_utxo(mut self) -> Self {
+        self.force_non_witness_utxo = true;
+        self
+    }
+
+    /// Choose the coin selection algorithm
+    ///
+    /// Overrides the [`DefaultCoinSelectionAlgorithm`](super::coin_selection::DefaultCoinSelectionAlgorithm).
+    pub fn coin_selection<P: CoinSelectionAlgorithm>(self, coin_selection: P) -> TxBuilder<P> {
+        TxBuilder {
+            recipients: self.recipients,
+            send_all: self.send_all,
+            fee_rate: self.fee_rate,
+            policy_path: self.policy_path,
+            utxos: self.utxos,
+            unspendable: self.unspendable,
+            sighash: self.sighash,
+            ordering: self.ordering,
+            locktime: self.locktime,
+            rbf: self.rbf,
+            version: self.version,
+            change_policy: self.change_policy,
+            force_non_witness_utxo: self.force_non_witness_utxo,
+            coin_selection,
+        }
+    }
+}
+
+/// Ordering of the transaction's inputs and outputs
+#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
+pub enum TxOrdering {
+    /// Randomized (default)
+    Shuffle,
+    /// Unchanged
+    Untouched,
+    /// BIP69 / Lexicographic
+    BIP69Lexicographic,
+}
+
+impl Default for TxOrdering {
+    fn default() -> Self {
+        TxOrdering::Shuffle
+    }
+}
+
+impl TxOrdering {
+    pub fn sort_tx(&self, tx: &mut Transaction) {
+        match self {
+            TxOrdering::Untouched => {}
+            TxOrdering::Shuffle => {
+                use rand::seq::SliceRandom;
+                #[cfg(test)]
+                use rand::SeedableRng;
+
+                #[cfg(not(test))]
+                let mut rng = rand::thread_rng();
+                #[cfg(test)]
+                let mut rng = rand::rngs::StdRng::seed_from_u64(0);
+
+                tx.output.shuffle(&mut rng);
+            }
+            TxOrdering::BIP69Lexicographic => {
+                tx.input.sort_unstable_by_key(|txin| {
+                    (txin.previous_output.txid, txin.previous_output.vout)
+                });
+                tx.output
+                    .sort_unstable_by_key(|txout| (txout.value, txout.script_pubkey.clone()));
+            }
+        }
+    }
+}
+
+/// Transaction version
+///
+/// Has a default value of `1`
+#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
+pub(crate) struct Version(pub(crate) u32);
+
+impl Default for Version {
+    fn default() -> Self {
+        Version(1)
+    }
+}
+
+/// Policy regarding the use of change outputs when creating a transaction
+#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
+pub enum ChangeSpendPolicy {
+    /// Use both change and non-change outputs (default)
+    ChangeAllowed,
+    /// Only use change outputs (see [`TxBuilder::only_spend_change`])
+    OnlyChange,
+    /// Only use non-change outputs (see [`TxBuilder::do_not_spend_change`])
+    ChangeForbidden,
+}
+
+impl Default for ChangeSpendPolicy {
+    fn default() -> Self {
+        ChangeSpendPolicy::ChangeAllowed
+    }
+}
+
+impl ChangeSpendPolicy {
+    pub(crate) fn filter_utxos<I: Iterator<Item = UTXO>>(&self, iter: I) -> Vec<UTXO> {
+        match self {
+            ChangeSpendPolicy::ChangeAllowed => iter.collect(),
+            ChangeSpendPolicy::OnlyChange => iter.filter(|utxo| utxo.is_internal).collect(),
+            ChangeSpendPolicy::ChangeForbidden => iter.filter(|utxo| !utxo.is_internal).collect(),
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    const ORDERING_TEST_TX: &'static str = "0200000003c26f3eb7932f7acddc5ddd26602b77e7516079b03090a16e2c2f54\
+                                            85d1fd600f0100000000ffffffffc26f3eb7932f7acddc5ddd26602b77e75160\
+                                            79b03090a16e2c2f5485d1fd600f0000000000ffffffff571fb3e02278217852\
+                                            dd5d299947e2b7354a639adc32ec1fa7b82cfb5dec530e0500000000ffffffff\
+                                            03e80300000000000002aaeee80300000000000001aa200300000000000001ff\
+                                            00000000";
+    macro_rules! ordering_test_tx {
+        () => {
+            deserialize::<bitcoin::Transaction>(&Vec::<u8>::from_hex(ORDERING_TEST_TX).unwrap())
+                .unwrap()
+        };
+    }
+
+    use bitcoin::consensus::deserialize;
+    use bitcoin::hashes::hex::FromHex;
+
+    use super::*;
+
+    #[test]
+    fn test_output_ordering_default_shuffle() {
+        assert_eq!(TxOrdering::default(), TxOrdering::Shuffle);
+    }
+
+    #[test]
+    fn test_output_ordering_untouched() {
+        let original_tx = ordering_test_tx!();
+        let mut tx = original_tx.clone();
+
+        TxOrdering::Untouched.sort_tx(&mut tx);
+
+        assert_eq!(original_tx, tx);
+    }
+
+    #[test]
+    fn test_output_ordering_shuffle() {
+        let original_tx = ordering_test_tx!();
+        let mut tx = original_tx.clone();
+
+        TxOrdering::Shuffle.sort_tx(&mut tx);
+
+        assert_eq!(original_tx.input, tx.input);
+        assert_ne!(original_tx.output, tx.output);
+    }
+
+    #[test]
+    fn test_output_ordering_bip69() {
+        use std::str::FromStr;
+
+        let original_tx = ordering_test_tx!();
+        let mut tx = original_tx.clone();
+
+        TxOrdering::BIP69Lexicographic.sort_tx(&mut tx);
+
+        assert_eq!(
+            tx.input[0].previous_output,
+            bitcoin::OutPoint::from_str(
+                "0e53ec5dfb2cb8a71fec32dc9a634a35b7e24799295ddd5278217822e0b31f57:5"
+            )
+            .unwrap()
+        );
+        assert_eq!(
+            tx.input[1].previous_output,
+            bitcoin::OutPoint::from_str(
+                "0f60fdd185542f2c6ea19030b0796051e7772b6026dd5ddccd7a2f93b73e6fc2:0"
+            )
+            .unwrap()
+        );
+        assert_eq!(
+            tx.input[2].previous_output,
+            bitcoin::OutPoint::from_str(
+                "0f60fdd185542f2c6ea19030b0796051e7772b6026dd5ddccd7a2f93b73e6fc2:1"
+            )
+            .unwrap()
+        );
+
+        assert_eq!(tx.output[0].value, 800);
+        assert_eq!(tx.output[1].script_pubkey, From::from(vec![0xAA]));
+        assert_eq!(tx.output[2].script_pubkey, From::from(vec![0xAA, 0xEE]));
+    }
+
+    fn get_test_utxos() -> Vec<UTXO> {
+        vec![
+            UTXO {
+                outpoint: OutPoint {
+                    txid: Default::default(),
+                    vout: 0,
+                },
+                txout: Default::default(),
+                is_internal: false,
+            },
+            UTXO {
+                outpoint: OutPoint {
+                    txid: Default::default(),
+                    vout: 1,
+                },
+                txout: Default::default(),
+                is_internal: true,
+            },
+        ]
+    }
+
+    #[test]
+    fn test_change_spend_policy_default() {
+        let change_spend_policy = ChangeSpendPolicy::default();
+        let filtered = change_spend_policy.filter_utxos(get_test_utxos().into_iter());
+
+        assert_eq!(filtered.len(), 2);
+    }
+
+    #[test]
+    fn test_change_spend_policy_no_internal() {
+        let change_spend_policy = ChangeSpendPolicy::ChangeForbidden;
+        let filtered = change_spend_policy.filter_utxos(get_test_utxos().into_iter());
+
+        assert_eq!(filtered.len(), 1);
+        assert_eq!(filtered[0].is_internal, false);
+    }
+
+    #[test]
+    fn test_change_spend_policy_only_internal() {
+        let change_spend_policy = ChangeSpendPolicy::OnlyChange;
+        let filtered = change_spend_policy.filter_utxos(get_test_utxos().into_iter());
+
+        assert_eq!(filtered.len(), 1);
+        assert_eq!(filtered[0].is_internal, true);
+    }
+
+    #[test]
+    fn test_default_tx_version_1() {
+        let version = Version::default();
+        assert_eq!(version.0, 1);
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/utils.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/utils.rs.html new file mode 100644 index 0000000000..7fda4f9243 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/utils.rs.html @@ -0,0 +1,311 @@ +utils.rs.html -- source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use miniscript::{MiniscriptKey, Satisfier};
+
+// De-facto standard "dust limit" (even though it should change based on the output type)
+const DUST_LIMIT_SATOSHI: u64 = 546;
+
+/// Trait to check if a value is below the dust limit
+// we implement this trait to make sure we don't mess up the comparison with off-by-one like a <
+// instead of a <= etc. The constant value for the dust limit is not public on purpose, to
+// encourage the usage of this trait.
+pub trait IsDust {
+    /// Check whether or not a value is below dust limit
+    fn is_dust(&self) -> bool;
+}
+
+impl IsDust for u64 {
+    fn is_dust(&self) -> bool {
+        *self <= DUST_LIMIT_SATOSHI
+    }
+}
+
+pub struct After {
+    pub current_height: Option<u32>,
+    pub assume_height_reached: bool,
+}
+
+impl After {
+    pub(crate) fn new(current_height: Option<u32>, assume_height_reached: bool) -> After {
+        After {
+            current_height,
+            assume_height_reached,
+        }
+    }
+}
+
+impl<Pk: MiniscriptKey> Satisfier<Pk> for After {
+    fn check_after(&self, n: u32) -> bool {
+        if let Some(current_height) = self.current_height {
+            current_height >= n
+        } else {
+            self.assume_height_reached
+        }
+    }
+}
+
+pub struct Older {
+    pub current_height: Option<u32>,
+    pub create_height: Option<u32>,
+    pub assume_height_reached: bool,
+}
+
+impl Older {
+    pub(crate) fn new(
+        current_height: Option<u32>,
+        create_height: Option<u32>,
+        assume_height_reached: bool,
+    ) -> Older {
+        Older {
+            current_height,
+            create_height,
+            assume_height_reached,
+        }
+    }
+}
+
+impl<Pk: MiniscriptKey> Satisfier<Pk> for Older {
+    fn check_older(&self, n: u32) -> bool {
+        if let Some(current_height) = self.current_height {
+            // TODO: test >= / >
+            current_height as u64 >= self.create_height.unwrap_or(0) as u64 + n as u64
+        } else {
+            self.assume_height_reached
+        }
+    }
+}
+
+pub struct ChunksIterator<I: Iterator> {
+    iter: I,
+    size: usize,
+}
+
+impl<I: Iterator> ChunksIterator<I> {
+    pub fn new(iter: I, size: usize) -> Self {
+        ChunksIterator { iter, size }
+    }
+}
+
+impl<I: Iterator> Iterator for ChunksIterator<I> {
+    type Item = Vec<<I as std::iter::Iterator>::Item>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let mut v = Vec::new();
+        for _ in 0..self.size {
+            let e = self.iter.next();
+
+            match e {
+                None => break,
+                Some(val) => v.push(val),
+            }
+        }
+
+        if v.is_empty() {
+            return None;
+        }
+
+        Some(v)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use crate::types::FeeRate;
+
+    #[test]
+    fn test_fee_from_btc_per_kb() {
+        let fee = FeeRate::from_btc_per_kvb(1e-5);
+        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
+    }
+
+    #[test]
+    fn test_fee_from_sats_vbyte() {
+        let fee = FeeRate::from_sat_per_vb(1.0);
+        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
+    }
+
+    #[test]
+    fn test_fee_default_min_relay_fee() {
+        let fee = FeeRate::default_min_relay_fee();
+        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
+    }
+}
+
+
\ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/storage.js b/static/docs-rs/bdk/0.1.0-beta.1/storage.js new file mode 100644 index 0000000000..1b5225126f --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/storage.js @@ -0,0 +1 @@ +var resourcesSuffix="";var currentTheme=document.getElementById("themeStyle");var mainTheme=document.getElementById("mainThemeStyle");var savedHref=[];function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(!elem||!elem.classList){return}elem.classList.add(className)}function removeClass(elem,className){if(!elem||!elem.classList){return}elem.classList.remove(className)}function onEach(arr,func,reversed){if(arr&&arr.length>0&&func){var length=arr.length;var i;if(reversed!==true){for(i=0;i=0;--i){if(func(arr[i])===true){return true}}}}return false}function onEachLazy(lazyArray,func,reversed){return onEach(Array.prototype.slice.call(lazyArray),func,reversed)}function hasOwnProperty(obj,property){return Object.prototype.hasOwnProperty.call(obj,property)}function usableLocalStorage(){if(typeof Storage==="undefined"){return false}try{return window.localStorage!==null&&window.localStorage!==undefined}catch(err){return false}}function updateLocalStorage(name,value){if(usableLocalStorage()){localStorage[name]=value}else{}}function getCurrentValue(name){if(usableLocalStorage()&&localStorage[name]!==undefined){return localStorage[name]}return null}function switchTheme(styleElem,mainStyleElem,newTheme,saveTheme){var fullBasicCss="rustdoc"+resourcesSuffix+".css";var fullNewTheme=newTheme+resourcesSuffix+".css";var newHref=mainStyleElem.href.replace(fullBasicCss,fullNewTheme);if(styleElem.href===newHref){return}var found=false;if(savedHref.length===0){onEachLazy(document.getElementsByTagName("link"),function(el){savedHref.push(el.href)})}onEach(savedHref,function(el){if(el===newHref){found=true;return true}});if(found===true){styleElem.href=newHref;if(saveTheme===true){updateLocalStorage("rustdoc-theme",newTheme)}}}function getSystemValue(){var property=getComputedStyle(document.documentElement).getPropertyValue('content');return property.replace(/[\"\']/g,"")}switchTheme(currentTheme,mainTheme,getCurrentValue("rustdoc-theme")||getSystemValue()||"light",false) \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/theme.js b/static/docs-rs/bdk/0.1.0-beta.1/theme.js new file mode 100644 index 0000000000..ebd1a87271 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/theme.js @@ -0,0 +1 @@ +var themes=document.getElementById("theme-choices");var themePicker=document.getElementById("theme-picker");function showThemeButtonState(){themes.style.display="block";themePicker.style.borderBottomRightRadius="0";themePicker.style.borderBottomLeftRadius="0"}function hideThemeButtonState(){themes.style.display="none";themePicker.style.borderBottomRightRadius="3px";themePicker.style.borderBottomLeftRadius="3px"}function switchThemeButtonState(){if(themes.style.display==="block"){hideThemeButtonState()}else{showThemeButtonState()}};function handleThemeButtonsBlur(e){var active=document.activeElement;var related=e.relatedTarget;if(active.id!=="themePicker"&&(!active.parentNode||active.parentNode.id!=="theme-choices")&&(!related||(related.id!=="themePicker"&&(!related.parentNode||related.parentNode.id!=="theme-choices")))){hideThemeButtonState()}}themePicker.onclick=switchThemeButtonState;themePicker.onblur=handleThemeButtonsBlur;["dark","light"].forEach(function(item){var but=document.createElement('button');but.textContent=item;but.onclick=function(el){switchTheme(currentTheme,mainTheme,item,true)};but.onblur=handleThemeButtonsBlur;themes.appendChild(but)}) \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/wheel.svg b/static/docs-rs/bdk/0.1.0-beta.1/wheel.svg new file mode 100644 index 0000000000..01da3b24c7 --- /dev/null +++ b/static/docs-rs/bdk/0.1.0-beta.1/wheel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/docs-rs/bdk/index.html b/static/docs-rs/bdk/index.html new file mode 100644 index 0000000000..2a1a8bba18 --- /dev/null +++ b/static/docs-rs/bdk/index.html @@ -0,0 +1,12 @@ + + + Redirect + + + +

+ You are being re-directed to the latest version.
+ If that doesn't happen click here. +

+ + diff --git a/static/docs-rs/magical/0.1.0-beta.1/COPYRIGHT.txt b/static/docs-rs/magical/0.1.0-beta.1/COPYRIGHT.txt deleted file mode 100644 index af77776cca..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/COPYRIGHT.txt +++ /dev/null @@ -1,45 +0,0 @@ -These documentation pages include resources by third parties. This copyright -file applies only to those resources. The following third party resources are -included, and carry their own copyright notices and license terms: - -* Fira Sans (FiraSans-Regular.woff, FiraSans-Medium.woff): - - Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ - with Reserved Font Name Fira Sans. - - Copyright (c) 2014, Telefonica S.A. - - Licensed under the SIL Open Font License, Version 1.1. - See FiraSans-LICENSE.txt. - -* rustdoc.css, main.js, and playpen.js: - - Copyright 2015 The Rust Developers. - Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or - the MIT license (LICENSE-MIT.txt) at your option. - -* normalize.css: - - Copyright (c) Nicolas Gallagher and Jonathan Neal. - Licensed under the MIT license (see LICENSE-MIT.txt). - -* Source Code Pro (SourceCodePro-Regular.woff, SourceCodePro-Semibold.woff): - - Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), - with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark - of Adobe Systems Incorporated in the United States and/or other countries. - - Licensed under the SIL Open Font License, Version 1.1. - See SourceCodePro-LICENSE.txt. - -* Source Serif Pro (SourceSerifPro-Regular.ttf.woff, - SourceSerifPro-Bold.ttf.woff, SourceSerifPro-It.ttf.woff): - - Copyright 2014 Adobe Systems Incorporated (http://www.adobe.com/), with - Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of - Adobe Systems Incorporated in the United States and/or other countries. - - Licensed under the SIL Open Font License, Version 1.1. - See SourceSerifPro-LICENSE.txt. - -This copyright file is intended to be distributed with rustdoc output. diff --git a/static/docs-rs/magical/0.1.0-beta.1/FiraSans-LICENSE.txt b/static/docs-rs/magical/0.1.0-beta.1/FiraSans-LICENSE.txt deleted file mode 100644 index d444ea92b6..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/FiraSans-LICENSE.txt +++ /dev/null @@ -1,94 +0,0 @@ -Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. -with Reserved Font Name < Fira >, - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/magical/0.1.0-beta.1/FiraSans-Medium.woff b/static/docs-rs/magical/0.1.0-beta.1/FiraSans-Medium.woff deleted file mode 100644 index 7d742c5fb7..0000000000 Binary files a/static/docs-rs/magical/0.1.0-beta.1/FiraSans-Medium.woff and /dev/null differ diff --git a/static/docs-rs/magical/0.1.0-beta.1/FiraSans-Regular.woff b/static/docs-rs/magical/0.1.0-beta.1/FiraSans-Regular.woff deleted file mode 100644 index d8e0363f4e..0000000000 Binary files a/static/docs-rs/magical/0.1.0-beta.1/FiraSans-Regular.woff and /dev/null differ diff --git a/static/docs-rs/magical/0.1.0-beta.1/LICENSE-APACHE.txt b/static/docs-rs/magical/0.1.0-beta.1/LICENSE-APACHE.txt deleted file mode 100644 index 16fe87b06e..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/LICENSE-APACHE.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/static/docs-rs/magical/0.1.0-beta.1/LICENSE-MIT.txt b/static/docs-rs/magical/0.1.0-beta.1/LICENSE-MIT.txt deleted file mode 100644 index 31aa79387f..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/LICENSE-MIT.txt +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/static/docs-rs/magical/0.1.0-beta.1/SourceCodePro-LICENSE.txt b/static/docs-rs/magical/0.1.0-beta.1/SourceCodePro-LICENSE.txt deleted file mode 100644 index 07542572e3..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/SourceCodePro-LICENSE.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. - -This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/magical/0.1.0-beta.1/SourceCodePro-Regular.woff b/static/docs-rs/magical/0.1.0-beta.1/SourceCodePro-Regular.woff deleted file mode 100644 index 5576670903..0000000000 Binary files a/static/docs-rs/magical/0.1.0-beta.1/SourceCodePro-Regular.woff and /dev/null differ diff --git a/static/docs-rs/magical/0.1.0-beta.1/SourceCodePro-Semibold.woff b/static/docs-rs/magical/0.1.0-beta.1/SourceCodePro-Semibold.woff deleted file mode 100644 index ca972a11dc..0000000000 Binary files a/static/docs-rs/magical/0.1.0-beta.1/SourceCodePro-Semibold.woff and /dev/null differ diff --git a/static/docs-rs/magical/0.1.0-beta.1/SourceSerifPro-Bold.ttf.woff b/static/docs-rs/magical/0.1.0-beta.1/SourceSerifPro-Bold.ttf.woff deleted file mode 100644 index ca254318fe..0000000000 Binary files a/static/docs-rs/magical/0.1.0-beta.1/SourceSerifPro-Bold.ttf.woff and /dev/null differ diff --git a/static/docs-rs/magical/0.1.0-beta.1/SourceSerifPro-It.ttf.woff b/static/docs-rs/magical/0.1.0-beta.1/SourceSerifPro-It.ttf.woff deleted file mode 100644 index a287bbe6ed..0000000000 Binary files a/static/docs-rs/magical/0.1.0-beta.1/SourceSerifPro-It.ttf.woff and /dev/null differ diff --git a/static/docs-rs/magical/0.1.0-beta.1/SourceSerifPro-LICENSE.md b/static/docs-rs/magical/0.1.0-beta.1/SourceSerifPro-LICENSE.md deleted file mode 100644 index 22cb755f2f..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/SourceSerifPro-LICENSE.md +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2014-2018 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. - -This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/magical/0.1.0-beta.1/SourceSerifPro-Regular.ttf.woff b/static/docs-rs/magical/0.1.0-beta.1/SourceSerifPro-Regular.ttf.woff deleted file mode 100644 index a3d55cfdf2..0000000000 Binary files a/static/docs-rs/magical/0.1.0-beta.1/SourceSerifPro-Regular.ttf.woff and /dev/null differ diff --git a/static/docs-rs/magical/0.1.0-beta.1/brush.svg b/static/docs-rs/magical/0.1.0-beta.1/brush.svg deleted file mode 100644 index ea266e856a..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/brush.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/dark.css b/static/docs-rs/magical/0.1.0-beta.1/dark.css deleted file mode 100644 index 5df3fef0bc..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/dark.css +++ /dev/null @@ -1 +0,0 @@ -body{background-color:#353535;color:#ddd;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:#ddd;}h1.fqn{border-bottom-color:#d2d2d2;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){border-bottom-color:#d2d2d2;}.in-band{background-color:#353535;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#2A2A2A;}pre{background-color:#2A2A2A;}.sidebar{background-color:#505050;}*{scrollbar-color:rgb(64,65,67) #717171;}.sidebar{scrollbar-color:rgba(32,34,37,.6) transparent;}::-webkit-scrollbar-track{background-color:#717171;}::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar::-webkit-scrollbar-track{background-color:#717171;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar .current{background-color:#333;}.source .sidebar{background-color:#353535;}.sidebar .location{border-color:#fff;background:#575757;color:#DDD;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#444;}.line-numbers span{color:#3B91E2;}.line-numbers .line-highlighted{background-color:#0a042f !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#DDD;}.docblock table,.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#ddd;}.content .highlighted{color:#eee !important;background-color:#616161;}.content .highlighted a,.content .highlighted span{color:#eee !important;}.content .highlighted.trait{background-color:#013191;}.content .highlighted.traitalias{background-color:#013191;}.content .highlighted.mod,.content .highlighted.externcrate{background-color:#afc6e4;}.content .highlighted.mod{background-color:#803a1b;}.content .highlighted.externcrate{background-color:#396bac;}.content .highlighted.enum{background-color:#5b4e68;}.content .highlighted.struct{background-color:#194e9f;}.content .highlighted.union{background-color:#b7bd49;}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{background-color:#4950ed;}.content .highlighted.type{background-color:#38902c;}.content .highlighted.foreigntype{background-color:#b200d6;}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{background-color:#217d1c;}.content .highlighted.constant,.content .highlighted.static{background-color:#0063cc;}.content .highlighted.primitive{background-color:#00708a;}.content .highlighted.keyword{background-color:#884719;}.content .stability::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#82b089;}.content span.struct,.content a.struct,.block a.current.struct{color:#2dbfb8;}.content span.type,.content a.type,.block a.current.type{color:#ff7f00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#dd7de8;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#09bd00;}.content span.union,.content a.union,.block a.current.union{color:#a6ae37;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#82a5c9;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#43aec7;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#bda000;}.content span.trait,.content a.trait,.block a.current.trait{color:#b78cf2;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#b397da;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#2BAB63;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8d8d8b;}pre.rust .doccomment{color:#8ca375;}nav:not(.sidebar){border-bottom-color:#4e4e4e;}nav.main .current{border-top-color:#eee;border-bottom-color:#eee;}nav.main .separator{border-color:#eee;}a{color:#ddd;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.stability a{color:#D2991D;}.stab.internal a{color:#304FFE;}a.test-arrow{color:#dedede;}.collapse-toggle{color:#999;}#crate-search{color:#111;background-color:#f0f0f0;border-color:#000;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input{color:#111;background-color:#f0f0f0;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input:focus{border-color:#008dfd;}.search-focus:disabled{background-color:#c5c4c4;}#crate-search+.search-input:focus{box-shadow:0 0 8px 4px #078dd8;}.module-item .stab{color:#ddd;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;color:#2f2f2f;}.stab.internal{background:#FFB9B3;border-color:#B71C1C;color:#2f2f2f;}.stab.deprecated{background:#F3DFFF;border-color:#7F0087;color:#2f2f2f;}.stab.portability{background:#C4ECFF;border-color:#7BA5DB;color:#2f2f2f;}.stab.portability>code{color:#ddd;}#help>div{background:#4d4d4d;border-color:#bfbfbf;}#help dt{border-color:#bfbfbf;background:rgba(0,0,0,0);color:black;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:#ddd;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#ab8ac1;}pre.rust .kw-2,pre.rust .prelude-ty{color:#769acb;}pre.rust .number,pre.rust .string{color:#83a300;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#ee6868;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#d97f26;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#4a4949;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label{color:#999;}:target>code,:target>.in-band{background-color:#494a3d;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.8);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.8);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.8);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.8);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip .tooltiptext{background-color:#000;color:#fff;border-color:#000;}.tooltip .tooltiptext::after{border-color:transparent black transparent transparent;}#titles>div:not(.selected){background-color:#252525;border-top-color:#252525;}#titles>div:hover,#titles>div.selected{border-top-color:#0089ff;}#titles>div>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#505050;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#505050;border-right-color:#000;}#sidebar-filler{background-color:#505050;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu{border-color:#e0e0e0;background:#f0f0f0;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus{border-color:#ffb900;}#theme-choices{border-color:#e0e0e0;background-color:#353535;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#4e4e4e;}@media (max-width:700px){#theme-picker{background:#f0f0f0;}}#all-types{background-color:#505050;}#all-types:hover{background-color:#606060;}.search-results td span.alias{color:#fff;}.search-results td span.grey{color:#ccc;}#sidebar-toggle{background-color:#565656;}#sidebar-toggle:hover{background-color:#676767;}#source-sidebar{background-color:#565656;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#444;}div.files>.selected{background-color:#333;}.setting-line>.title{border-bottom-color:#ddd;} \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/down-arrow.svg b/static/docs-rs/magical/0.1.0-beta.1/down-arrow.svg deleted file mode 100644 index 35437e77a7..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/down-arrow.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/favicon.ico b/static/docs-rs/magical/0.1.0-beta.1/favicon.ico deleted file mode 100644 index b8ad23769a..0000000000 Binary files a/static/docs-rs/magical/0.1.0-beta.1/favicon.ico and /dev/null differ diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/alloc/string/trait.ToString.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/alloc/string/trait.ToString.js deleted file mode 100644 index 855a6488c0..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/alloc/string/trait.ToString.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl ToString for WalletExport","synthetic":false,"types":["magical::wallet::export::WalletExport"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/clone/trait.Clone.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/clone/trait.Clone.js deleted file mode 100644 index b0a9a778cb..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/clone/trait.Clone.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl Clone for Capability","synthetic":false,"types":["magical::blockchain::Capability"]},{"text":"impl Clone for NoopProgress","synthetic":false,"types":["magical::blockchain::NoopProgress"]},{"text":"impl Clone for LogProgress","synthetic":false,"types":["magical::blockchain::LogProgress"]},{"text":"impl Clone for PKOrF","synthetic":false,"types":["magical::descriptor::policy::PKOrF"]},{"text":"impl Clone for SatisfiableItem","synthetic":false,"types":["magical::descriptor::policy::SatisfiableItem"]},{"text":"impl Clone for Satisfaction","synthetic":false,"types":["magical::descriptor::policy::Satisfaction"]},{"text":"impl Clone for Policy","synthetic":false,"types":["magical::descriptor::policy::Policy"]},{"text":"impl Clone for Condition","synthetic":false,"types":["magical::descriptor::policy::Condition"]},{"text":"impl Clone for ScriptType","synthetic":false,"types":["magical::types::ScriptType"]},{"text":"impl Clone for FeeRate","synthetic":false,"types":["magical::types::FeeRate"]},{"text":"impl Clone for UTXO","synthetic":false,"types":["magical::types::UTXO"]},{"text":"impl Clone for TransactionDetails","synthetic":false,"types":["magical::types::TransactionDetails"]},{"text":"impl Clone for AddressValidatorError","synthetic":false,"types":["magical::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: Clone + MiniscriptKey> Clone for SignerId<Pk>","synthetic":false,"types":["magical::wallet::signer::SignerId"]},{"text":"impl Clone for SignerError","synthetic":false,"types":["magical::wallet::signer::SignerError"]},{"text":"impl Clone for SignerOrdering","synthetic":false,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl<Pk: Clone + MiniscriptKey> Clone for SignersContainer<Pk>","synthetic":false,"types":["magical::wallet::signer::SignersContainer"]},{"text":"impl Clone for TxOrdering","synthetic":false,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl Clone for ChangeSpendPolicy","synthetic":false,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/cmp/trait.Eq.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/cmp/trait.Eq.js deleted file mode 100644 index 385336954e..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/cmp/trait.Eq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl Eq for Capability","synthetic":false,"types":["magical::blockchain::Capability"]},{"text":"impl Eq for Condition","synthetic":false,"types":["magical::descriptor::policy::Condition"]},{"text":"impl Eq for ScriptType","synthetic":false,"types":["magical::types::ScriptType"]},{"text":"impl Eq for UTXO","synthetic":false,"types":["magical::types::UTXO"]},{"text":"impl Eq for TransactionDetails","synthetic":false,"types":["magical::types::TransactionDetails"]},{"text":"impl Eq for AddressValidatorError","synthetic":false,"types":["magical::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: Eq + MiniscriptKey> Eq for SignerId<Pk>","synthetic":false,"types":["magical::wallet::signer::SignerId"]},{"text":"impl Eq for SignerError","synthetic":false,"types":["magical::wallet::signer::SignerError"]},{"text":"impl Eq for SignerOrdering","synthetic":false,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl Eq for TxOrdering","synthetic":false,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl Eq for ChangeSpendPolicy","synthetic":false,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/cmp/trait.Ord.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/cmp/trait.Ord.js deleted file mode 100644 index 163300a683..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/cmp/trait.Ord.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl Ord for Condition","synthetic":false,"types":["magical::descriptor::policy::Condition"]},{"text":"impl Ord for SignerOrdering","synthetic":false,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl Ord for TxOrdering","synthetic":false,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl Ord for ChangeSpendPolicy","synthetic":false,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/cmp/trait.PartialEq.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/cmp/trait.PartialEq.js deleted file mode 100644 index bc54e6fdde..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/cmp/trait.PartialEq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl PartialEq<Capability> for Capability","synthetic":false,"types":["magical::blockchain::Capability"]},{"text":"impl PartialEq<Condition> for Condition","synthetic":false,"types":["magical::descriptor::policy::Condition"]},{"text":"impl PartialEq<ScriptType> for ScriptType","synthetic":false,"types":["magical::types::ScriptType"]},{"text":"impl PartialEq<FeeRate> for FeeRate","synthetic":false,"types":["magical::types::FeeRate"]},{"text":"impl PartialEq<UTXO> for UTXO","synthetic":false,"types":["magical::types::UTXO"]},{"text":"impl PartialEq<TransactionDetails> for TransactionDetails","synthetic":false,"types":["magical::types::TransactionDetails"]},{"text":"impl PartialEq<AddressValidatorError> for AddressValidatorError","synthetic":false,"types":["magical::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: PartialEq + MiniscriptKey> PartialEq<SignerId<Pk>> for SignerId<Pk>","synthetic":false,"types":["magical::wallet::signer::SignerId"]},{"text":"impl PartialEq<SignerError> for SignerError","synthetic":false,"types":["magical::wallet::signer::SignerError"]},{"text":"impl PartialEq<SignerOrdering> for SignerOrdering","synthetic":false,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl PartialEq<TxOrdering> for TxOrdering","synthetic":false,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/cmp/trait.PartialOrd.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/cmp/trait.PartialOrd.js deleted file mode 100644 index ea5c0bf81c..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/cmp/trait.PartialOrd.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl PartialOrd<Condition> for Condition","synthetic":false,"types":["magical::descriptor::policy::Condition"]},{"text":"impl PartialOrd<FeeRate> for FeeRate","synthetic":false,"types":["magical::types::FeeRate"]},{"text":"impl PartialOrd<SignerOrdering> for SignerOrdering","synthetic":false,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl PartialOrd<TxOrdering> for TxOrdering","synthetic":false,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/convert/trait.AsRef.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/convert/trait.AsRef.js deleted file mode 100644 index 0a2537c5c9..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/convert/trait.AsRef.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl AsRef<[u8]> for ScriptType","synthetic":false,"types":["magical::types::ScriptType"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/convert/trait.From.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/convert/trait.From.js deleted file mode 100644 index e3cfe026ee..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/convert/trait.From.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<AddressValidatorError> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<SignerError> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<EsploraError> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<CompactFiltersError> for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl From<Client> for ElectrumBlockchain","synthetic":false,"types":["magical::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["magical::blockchain::esplora::EsploraError"]},{"text":"impl From<ParseIntError> for EsploraError","synthetic":false,"types":["magical::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["magical::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["magical::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["magical::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["magical::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<SystemTimeError> for CompactFiltersError","synthetic":false,"types":["magical::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["magical::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["magical::descriptor::error::Error"]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":["magical::descriptor::error::Error"]},{"text":"impl From<bool> for Satisfaction","synthetic":false,"types":["magical::descriptor::policy::Satisfaction"]},{"text":"impl From<SatisfiableItem> for Policy","synthetic":false,"types":["magical::descriptor::policy::Policy"]},{"text":"impl From<Hash> for SignerId<DescriptorPublicKey>","synthetic":false,"types":["magical::wallet::signer::SignerId"]},{"text":"impl From<Fingerprint> for SignerId<DescriptorPublicKey>","synthetic":false,"types":["magical::wallet::signer::SignerId"]},{"text":"impl From<HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>> for SignersContainer<DescriptorPublicKey>","synthetic":false,"types":["magical::wallet::signer::SignersContainer"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/default/trait.Default.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/default/trait.Default.js deleted file mode 100644 index db7e4a550d..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/default/trait.Default.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl Default for Mempool","synthetic":false,"types":["magical::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Default for MemoryDatabase","synthetic":false,"types":["magical::database::memory::MemoryDatabase"]},{"text":"impl Default for PKOrF","synthetic":false,"types":["magical::descriptor::policy::PKOrF"]},{"text":"impl Default for Condition","synthetic":false,"types":["magical::descriptor::policy::Condition"]},{"text":"impl Default for FeeRate","synthetic":false,"types":["magical::types::FeeRate"]},{"text":"impl Default for TransactionDetails","synthetic":false,"types":["magical::types::TransactionDetails"]},{"text":"impl Default for DumbCoinSelection","synthetic":false,"types":["magical::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Default for SignerOrdering","synthetic":false,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl<Pk: Default + MiniscriptKey> Default for SignersContainer<Pk>","synthetic":false,"types":["magical::wallet::signer::SignersContainer"]},{"text":"impl<Cs: Default + CoinSelectionAlgorithm> Default for TxBuilder<Cs>","synthetic":false,"types":["magical::wallet::tx_builder::TxBuilder"]},{"text":"impl Default for TxOrdering","synthetic":false,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl Default for ChangeSpendPolicy","synthetic":false,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/fmt/trait.Debug.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/fmt/trait.Debug.js deleted file mode 100644 index a6b72f5f74..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/fmt/trait.Debug.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl Debug for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl Debug for EsploraBlockchain","synthetic":false,"types":["magical::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Debug for EsploraError","synthetic":false,"types":["magical::blockchain::esplora::EsploraError"]},{"text":"impl Debug for Mempool","synthetic":false,"types":["magical::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Debug for Peer","synthetic":false,"types":["magical::blockchain::compact_filters::peer::Peer"]},{"text":"impl Debug for CompactFiltersBlockchain","synthetic":false,"types":["magical::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Debug for CompactFiltersError","synthetic":false,"types":["magical::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Debug for Capability","synthetic":false,"types":["magical::blockchain::Capability"]},{"text":"impl Debug for MemoryDatabase","synthetic":false,"types":["magical::database::memory::MemoryDatabase"]},{"text":"impl Debug for Error","synthetic":false,"types":["magical::descriptor::error::Error"]},{"text":"impl Debug for PKOrF","synthetic":false,"types":["magical::descriptor::policy::PKOrF"]},{"text":"impl Debug for SatisfiableItem","synthetic":false,"types":["magical::descriptor::policy::SatisfiableItem"]},{"text":"impl Debug for Satisfaction","synthetic":false,"types":["magical::descriptor::policy::Satisfaction"]},{"text":"impl Debug for Policy","synthetic":false,"types":["magical::descriptor::policy::Policy"]},{"text":"impl Debug for Condition","synthetic":false,"types":["magical::descriptor::policy::Condition"]},{"text":"impl Debug for PolicyError","synthetic":false,"types":["magical::descriptor::policy::PolicyError"]},{"text":"impl Debug for ScriptType","synthetic":false,"types":["magical::types::ScriptType"]},{"text":"impl Debug for FeeRate","synthetic":false,"types":["magical::types::FeeRate"]},{"text":"impl Debug for UTXO","synthetic":false,"types":["magical::types::UTXO"]},{"text":"impl Debug for TransactionDetails","synthetic":false,"types":["magical::types::TransactionDetails"]},{"text":"impl Debug for AddressValidatorError","synthetic":false,"types":["magical::wallet::address_validator::AddressValidatorError"]},{"text":"impl Debug for CoinSelectionResult","synthetic":false,"types":["magical::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Debug for DumbCoinSelection","synthetic":false,"types":["magical::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Debug for WalletExport","synthetic":false,"types":["magical::wallet::export::WalletExport"]},{"text":"impl<Pk: Debug + MiniscriptKey> Debug for SignerId<Pk>","synthetic":false,"types":["magical::wallet::signer::SignerId"]},{"text":"impl Debug for SignerError","synthetic":false,"types":["magical::wallet::signer::SignerError"]},{"text":"impl Debug for SignerOrdering","synthetic":false,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl<Pk: Debug + MiniscriptKey> Debug for SignersContainer<Pk>","synthetic":false,"types":["magical::wallet::signer::SignersContainer"]},{"text":"impl<Cs: Debug + CoinSelectionAlgorithm> Debug for TxBuilder<Cs>","synthetic":false,"types":["magical::wallet::tx_builder::TxBuilder"]},{"text":"impl Debug for TxOrdering","synthetic":false,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl Debug for ChangeSpendPolicy","synthetic":false,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/fmt/trait.Display.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/fmt/trait.Display.js deleted file mode 100644 index 18a1098da4..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/fmt/trait.Display.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl Display for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl Display for EsploraError","synthetic":false,"types":["magical::blockchain::esplora::EsploraError"]},{"text":"impl Display for CompactFiltersError","synthetic":false,"types":["magical::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Display for Error","synthetic":false,"types":["magical::descriptor::error::Error"]},{"text":"impl Display for PolicyError","synthetic":false,"types":["magical::descriptor::policy::PolicyError"]},{"text":"impl Display for AddressValidatorError","synthetic":false,"types":["magical::wallet::address_validator::AddressValidatorError"]},{"text":"impl Display for SignerError","synthetic":false,"types":["magical::wallet::signer::SignerError"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/hash/trait.Hash.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/hash/trait.Hash.js deleted file mode 100644 index 83baa0e684..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/hash/trait.Hash.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl Hash for Capability","synthetic":false,"types":["magical::blockchain::Capability"]},{"text":"impl Hash for Condition","synthetic":false,"types":["magical::descriptor::policy::Condition"]},{"text":"impl Hash for ScriptType","synthetic":false,"types":["magical::types::ScriptType"]},{"text":"impl<Pk: Hash + MiniscriptKey> Hash for SignerId<Pk>","synthetic":false,"types":["magical::wallet::signer::SignerId"]},{"text":"impl Hash for TxOrdering","synthetic":false,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl Hash for ChangeSpendPolicy","synthetic":false,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Copy.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Copy.js deleted file mode 100644 index e56eac854c..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Copy.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl Copy for Capability","synthetic":false,"types":["magical::blockchain::Capability"]},{"text":"impl Copy for Condition","synthetic":false,"types":["magical::descriptor::policy::Condition"]},{"text":"impl Copy for ScriptType","synthetic":false,"types":["magical::types::ScriptType"]},{"text":"impl Copy for FeeRate","synthetic":false,"types":["magical::types::FeeRate"]},{"text":"impl Copy for TxOrdering","synthetic":false,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl Copy for ChangeSpendPolicy","synthetic":false,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Freeze.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Freeze.js deleted file mode 100644 index e2700a8ff5..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Freeze.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl Freeze for FeeRate","synthetic":true,"types":["magical::types::FeeRate"]},{"text":"impl Freeze for UTXO","synthetic":true,"types":["magical::types::UTXO"]},{"text":"impl Freeze for TransactionDetails","synthetic":true,"types":["magical::types::TransactionDetails"]},{"text":"impl Freeze for Error","synthetic":true,"types":["magical::error::Error"]},{"text":"impl Freeze for ScriptType","synthetic":true,"types":["magical::types::ScriptType"]},{"text":"impl Freeze for OfflineBlockchain","synthetic":true,"types":["magical::blockchain::OfflineBlockchain"]},{"text":"impl Freeze for NoopProgress","synthetic":true,"types":["magical::blockchain::NoopProgress"]},{"text":"impl Freeze for LogProgress","synthetic":true,"types":["magical::blockchain::LogProgress"]},{"text":"impl Freeze for Capability","synthetic":true,"types":["magical::blockchain::Capability"]},{"text":"impl !Freeze for ElectrumBlockchain","synthetic":true,"types":["magical::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Freeze for EsploraBlockchain","synthetic":true,"types":["magical::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Freeze for EsploraError","synthetic":true,"types":["magical::blockchain::esplora::EsploraError"]},{"text":"impl !Freeze for Mempool","synthetic":true,"types":["magical::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Freeze for Peer","synthetic":true,"types":["magical::blockchain::compact_filters::peer::Peer"]},{"text":"impl Freeze for CompactFiltersBlockchain","synthetic":true,"types":["magical::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Freeze for CompactFiltersError","synthetic":true,"types":["magical::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Freeze for MemoryDatabase","synthetic":true,"types":["magical::database::memory::MemoryDatabase"]},{"text":"impl Freeze for Error","synthetic":true,"types":["magical::descriptor::error::Error"]},{"text":"impl Freeze for PKOrF","synthetic":true,"types":["magical::descriptor::policy::PKOrF"]},{"text":"impl Freeze for Policy","synthetic":true,"types":["magical::descriptor::policy::Policy"]},{"text":"impl Freeze for Condition","synthetic":true,"types":["magical::descriptor::policy::Condition"]},{"text":"impl Freeze for SatisfiableItem","synthetic":true,"types":["magical::descriptor::policy::SatisfiableItem"]},{"text":"impl Freeze for Satisfaction","synthetic":true,"types":["magical::descriptor::policy::Satisfaction"]},{"text":"impl Freeze for PolicyError","synthetic":true,"types":["magical::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !Freeze for Wallet<B, D>","synthetic":true,"types":["magical::wallet::Wallet"]},{"text":"impl Freeze for AddressValidatorError","synthetic":true,"types":["magical::wallet::address_validator::AddressValidatorError"]},{"text":"impl Freeze for CoinSelectionResult","synthetic":true,"types":["magical::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Freeze for DumbCoinSelection","synthetic":true,"types":["magical::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Freeze for WalletExport","synthetic":true,"types":["magical::wallet::export::WalletExport"]},{"text":"impl Freeze for SignerOrdering","synthetic":true,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> Freeze for SignersContainer<Pk>","synthetic":true,"types":["magical::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Freeze for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Freeze, 
","synthetic":true,"types":["magical::wallet::signer::SignerId"]},{"text":"impl Freeze for SignerError","synthetic":true,"types":["magical::wallet::signer::SignerError"]},{"text":"impl<Cs> Freeze for TxBuilder<Cs> where
    Cs: Freeze, 
","synthetic":true,"types":["magical::wallet::tx_builder::TxBuilder"]},{"text":"impl Freeze for TxOrdering","synthetic":true,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl Freeze for ChangeSpendPolicy","synthetic":true,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Send.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Send.js deleted file mode 100644 index de28e8b3b6..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Send.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl Send for FeeRate","synthetic":true,"types":["magical::types::FeeRate"]},{"text":"impl Send for UTXO","synthetic":true,"types":["magical::types::UTXO"]},{"text":"impl Send for TransactionDetails","synthetic":true,"types":["magical::types::TransactionDetails"]},{"text":"impl Send for Error","synthetic":true,"types":["magical::error::Error"]},{"text":"impl Send for ScriptType","synthetic":true,"types":["magical::types::ScriptType"]},{"text":"impl Send for OfflineBlockchain","synthetic":true,"types":["magical::blockchain::OfflineBlockchain"]},{"text":"impl Send for NoopProgress","synthetic":true,"types":["magical::blockchain::NoopProgress"]},{"text":"impl Send for LogProgress","synthetic":true,"types":["magical::blockchain::LogProgress"]},{"text":"impl Send for Capability","synthetic":true,"types":["magical::blockchain::Capability"]},{"text":"impl Send for ElectrumBlockchain","synthetic":true,"types":["magical::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Send for EsploraBlockchain","synthetic":true,"types":["magical::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Send for EsploraError","synthetic":true,"types":["magical::blockchain::esplora::EsploraError"]},{"text":"impl Send for Mempool","synthetic":true,"types":["magical::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Send for Peer","synthetic":true,"types":["magical::blockchain::compact_filters::peer::Peer"]},{"text":"impl Send for CompactFiltersBlockchain","synthetic":true,"types":["magical::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Send for CompactFiltersError","synthetic":true,"types":["magical::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !Send for MemoryDatabase","synthetic":true,"types":["magical::database::memory::MemoryDatabase"]},{"text":"impl Send for Error","synthetic":true,"types":["magical::descriptor::error::Error"]},{"text":"impl Send for PKOrF","synthetic":true,"types":["magical::descriptor::policy::PKOrF"]},{"text":"impl Send for Policy","synthetic":true,"types":["magical::descriptor::policy::Policy"]},{"text":"impl Send for Condition","synthetic":true,"types":["magical::descriptor::policy::Condition"]},{"text":"impl Send for SatisfiableItem","synthetic":true,"types":["magical::descriptor::policy::SatisfiableItem"]},{"text":"impl Send for Satisfaction","synthetic":true,"types":["magical::descriptor::policy::Satisfaction"]},{"text":"impl Send for PolicyError","synthetic":true,"types":["magical::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !Send for Wallet<B, D>","synthetic":true,"types":["magical::wallet::Wallet"]},{"text":"impl Send for AddressValidatorError","synthetic":true,"types":["magical::wallet::address_validator::AddressValidatorError"]},{"text":"impl Send for CoinSelectionResult","synthetic":true,"types":["magical::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Send for DumbCoinSelection","synthetic":true,"types":["magical::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Send for WalletExport","synthetic":true,"types":["magical::wallet::export::WalletExport"]},{"text":"impl Send for SignerOrdering","synthetic":true,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !Send for SignersContainer<Pk>","synthetic":true,"types":["magical::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Send for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Send
","synthetic":true,"types":["magical::wallet::signer::SignerId"]},{"text":"impl Send for SignerError","synthetic":true,"types":["magical::wallet::signer::SignerError"]},{"text":"impl<Cs> Send for TxBuilder<Cs> where
    Cs: Send
","synthetic":true,"types":["magical::wallet::tx_builder::TxBuilder"]},{"text":"impl Send for TxOrdering","synthetic":true,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl Send for ChangeSpendPolicy","synthetic":true,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.StructuralEq.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.StructuralEq.js deleted file mode 100644 index a87b9bc253..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.StructuralEq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl StructuralEq for Capability","synthetic":false,"types":["magical::blockchain::Capability"]},{"text":"impl StructuralEq for Condition","synthetic":false,"types":["magical::descriptor::policy::Condition"]},{"text":"impl StructuralEq for ScriptType","synthetic":false,"types":["magical::types::ScriptType"]},{"text":"impl StructuralEq for UTXO","synthetic":false,"types":["magical::types::UTXO"]},{"text":"impl StructuralEq for TransactionDetails","synthetic":false,"types":["magical::types::TransactionDetails"]},{"text":"impl StructuralEq for AddressValidatorError","synthetic":false,"types":["magical::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: MiniscriptKey> StructuralEq for SignerId<Pk>","synthetic":false,"types":["magical::wallet::signer::SignerId"]},{"text":"impl StructuralEq for SignerError","synthetic":false,"types":["magical::wallet::signer::SignerError"]},{"text":"impl StructuralEq for SignerOrdering","synthetic":false,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl StructuralEq for TxOrdering","synthetic":false,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl StructuralEq for ChangeSpendPolicy","synthetic":false,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.StructuralPartialEq.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.StructuralPartialEq.js deleted file mode 100644 index 206984880a..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.StructuralPartialEq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl StructuralPartialEq for Capability","synthetic":false,"types":["magical::blockchain::Capability"]},{"text":"impl StructuralPartialEq for Condition","synthetic":false,"types":["magical::descriptor::policy::Condition"]},{"text":"impl StructuralPartialEq for ScriptType","synthetic":false,"types":["magical::types::ScriptType"]},{"text":"impl StructuralPartialEq for FeeRate","synthetic":false,"types":["magical::types::FeeRate"]},{"text":"impl StructuralPartialEq for UTXO","synthetic":false,"types":["magical::types::UTXO"]},{"text":"impl StructuralPartialEq for TransactionDetails","synthetic":false,"types":["magical::types::TransactionDetails"]},{"text":"impl StructuralPartialEq for AddressValidatorError","synthetic":false,"types":["magical::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: MiniscriptKey> StructuralPartialEq for SignerId<Pk>","synthetic":false,"types":["magical::wallet::signer::SignerId"]},{"text":"impl StructuralPartialEq for SignerError","synthetic":false,"types":["magical::wallet::signer::SignerError"]},{"text":"impl StructuralPartialEq for SignerOrdering","synthetic":false,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl StructuralPartialEq for TxOrdering","synthetic":false,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl StructuralPartialEq for ChangeSpendPolicy","synthetic":false,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Sync.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Sync.js deleted file mode 100644 index 93c95f04b6..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Sync.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl Sync for FeeRate","synthetic":true,"types":["magical::types::FeeRate"]},{"text":"impl Sync for UTXO","synthetic":true,"types":["magical::types::UTXO"]},{"text":"impl Sync for TransactionDetails","synthetic":true,"types":["magical::types::TransactionDetails"]},{"text":"impl Sync for Error","synthetic":true,"types":["magical::error::Error"]},{"text":"impl Sync for ScriptType","synthetic":true,"types":["magical::types::ScriptType"]},{"text":"impl Sync for OfflineBlockchain","synthetic":true,"types":["magical::blockchain::OfflineBlockchain"]},{"text":"impl Sync for NoopProgress","synthetic":true,"types":["magical::blockchain::NoopProgress"]},{"text":"impl Sync for LogProgress","synthetic":true,"types":["magical::blockchain::LogProgress"]},{"text":"impl Sync for Capability","synthetic":true,"types":["magical::blockchain::Capability"]},{"text":"impl Sync for ElectrumBlockchain","synthetic":true,"types":["magical::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Sync for EsploraBlockchain","synthetic":true,"types":["magical::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Sync for EsploraError","synthetic":true,"types":["magical::blockchain::esplora::EsploraError"]},{"text":"impl Sync for Mempool","synthetic":true,"types":["magical::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Sync for Peer","synthetic":true,"types":["magical::blockchain::compact_filters::peer::Peer"]},{"text":"impl Sync for CompactFiltersBlockchain","synthetic":true,"types":["magical::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Sync for CompactFiltersError","synthetic":true,"types":["magical::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !Sync for MemoryDatabase","synthetic":true,"types":["magical::database::memory::MemoryDatabase"]},{"text":"impl Sync for Error","synthetic":true,"types":["magical::descriptor::error::Error"]},{"text":"impl Sync for PKOrF","synthetic":true,"types":["magical::descriptor::policy::PKOrF"]},{"text":"impl Sync for Policy","synthetic":true,"types":["magical::descriptor::policy::Policy"]},{"text":"impl Sync for Condition","synthetic":true,"types":["magical::descriptor::policy::Condition"]},{"text":"impl Sync for SatisfiableItem","synthetic":true,"types":["magical::descriptor::policy::SatisfiableItem"]},{"text":"impl Sync for Satisfaction","synthetic":true,"types":["magical::descriptor::policy::Satisfaction"]},{"text":"impl Sync for PolicyError","synthetic":true,"types":["magical::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !Sync for Wallet<B, D>","synthetic":true,"types":["magical::wallet::Wallet"]},{"text":"impl Sync for AddressValidatorError","synthetic":true,"types":["magical::wallet::address_validator::AddressValidatorError"]},{"text":"impl Sync for CoinSelectionResult","synthetic":true,"types":["magical::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Sync for DumbCoinSelection","synthetic":true,"types":["magical::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Sync for WalletExport","synthetic":true,"types":["magical::wallet::export::WalletExport"]},{"text":"impl Sync for SignerOrdering","synthetic":true,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !Sync for SignersContainer<Pk>","synthetic":true,"types":["magical::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Sync for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Sync
","synthetic":true,"types":["magical::wallet::signer::SignerId"]},{"text":"impl Sync for SignerError","synthetic":true,"types":["magical::wallet::signer::SignerError"]},{"text":"impl<Cs> Sync for TxBuilder<Cs> where
    Cs: Sync
","synthetic":true,"types":["magical::wallet::tx_builder::TxBuilder"]},{"text":"impl Sync for TxOrdering","synthetic":true,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl Sync for ChangeSpendPolicy","synthetic":true,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Unpin.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Unpin.js deleted file mode 100644 index 7d6d1eaaeb..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/marker/trait.Unpin.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl Unpin for FeeRate","synthetic":true,"types":["magical::types::FeeRate"]},{"text":"impl Unpin for UTXO","synthetic":true,"types":["magical::types::UTXO"]},{"text":"impl Unpin for TransactionDetails","synthetic":true,"types":["magical::types::TransactionDetails"]},{"text":"impl Unpin for Error","synthetic":true,"types":["magical::error::Error"]},{"text":"impl Unpin for ScriptType","synthetic":true,"types":["magical::types::ScriptType"]},{"text":"impl Unpin for OfflineBlockchain","synthetic":true,"types":["magical::blockchain::OfflineBlockchain"]},{"text":"impl Unpin for NoopProgress","synthetic":true,"types":["magical::blockchain::NoopProgress"]},{"text":"impl Unpin for LogProgress","synthetic":true,"types":["magical::blockchain::LogProgress"]},{"text":"impl Unpin for Capability","synthetic":true,"types":["magical::blockchain::Capability"]},{"text":"impl Unpin for ElectrumBlockchain","synthetic":true,"types":["magical::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Unpin for EsploraBlockchain","synthetic":true,"types":["magical::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Unpin for EsploraError","synthetic":true,"types":["magical::blockchain::esplora::EsploraError"]},{"text":"impl Unpin for Mempool","synthetic":true,"types":["magical::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Unpin for Peer","synthetic":true,"types":["magical::blockchain::compact_filters::peer::Peer"]},{"text":"impl Unpin for CompactFiltersBlockchain","synthetic":true,"types":["magical::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Unpin for CompactFiltersError","synthetic":true,"types":["magical::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Unpin for MemoryDatabase","synthetic":true,"types":["magical::database::memory::MemoryDatabase"]},{"text":"impl Unpin for Error","synthetic":true,"types":["magical::descriptor::error::Error"]},{"text":"impl Unpin for PKOrF","synthetic":true,"types":["magical::descriptor::policy::PKOrF"]},{"text":"impl Unpin for Policy","synthetic":true,"types":["magical::descriptor::policy::Policy"]},{"text":"impl Unpin for Condition","synthetic":true,"types":["magical::descriptor::policy::Condition"]},{"text":"impl Unpin for SatisfiableItem","synthetic":true,"types":["magical::descriptor::policy::SatisfiableItem"]},{"text":"impl Unpin for Satisfaction","synthetic":true,"types":["magical::descriptor::policy::Satisfaction"]},{"text":"impl Unpin for PolicyError","synthetic":true,"types":["magical::descriptor::policy::PolicyError"]},{"text":"impl<B, D> Unpin for Wallet<B, D> where
    B: Unpin,
    D: Unpin
","synthetic":true,"types":["magical::wallet::Wallet"]},{"text":"impl Unpin for AddressValidatorError","synthetic":true,"types":["magical::wallet::address_validator::AddressValidatorError"]},{"text":"impl Unpin for CoinSelectionResult","synthetic":true,"types":["magical::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Unpin for DumbCoinSelection","synthetic":true,"types":["magical::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Unpin for WalletExport","synthetic":true,"types":["magical::wallet::export::WalletExport"]},{"text":"impl Unpin for SignerOrdering","synthetic":true,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> Unpin for SignersContainer<Pk> where
    <Pk as MiniscriptKey>::Hash: Unpin
","synthetic":true,"types":["magical::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Unpin for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Unpin
","synthetic":true,"types":["magical::wallet::signer::SignerId"]},{"text":"impl Unpin for SignerError","synthetic":true,"types":["magical::wallet::signer::SignerError"]},{"text":"impl<Cs> Unpin for TxBuilder<Cs> where
    Cs: Unpin
","synthetic":true,"types":["magical::wallet::tx_builder::TxBuilder"]},{"text":"impl Unpin for TxOrdering","synthetic":true,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl Unpin for ChangeSpendPolicy","synthetic":true,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/str/trait.FromStr.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/core/str/trait.FromStr.js deleted file mode 100644 index 2704a1834d..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/core/str/trait.FromStr.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl FromStr for WalletExport","synthetic":false,"types":["magical::wallet::export::WalletExport"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/blockchain/trait.Blockchain.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/blockchain/trait.Blockchain.js deleted file mode 100644 index d1c7e760f1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/blockchain/trait.Blockchain.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/blockchain/trait.OnlineBlockchain.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/blockchain/trait.OnlineBlockchain.js deleted file mode 100644 index d1c7e760f1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/blockchain/trait.OnlineBlockchain.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/blockchain/trait.Progress.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/blockchain/trait.Progress.js deleted file mode 100644 index d1c7e760f1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/blockchain/trait.Progress.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/database/trait.BatchDatabase.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/database/trait.BatchDatabase.js deleted file mode 100644 index d1c7e760f1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/database/trait.BatchDatabase.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/database/trait.BatchOperations.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/database/trait.BatchOperations.js deleted file mode 100644 index d1c7e760f1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/database/trait.BatchOperations.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/database/trait.Database.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/database/trait.Database.js deleted file mode 100644 index d1c7e760f1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/database/trait.Database.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/descriptor/trait.ExtractPolicy.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/descriptor/trait.ExtractPolicy.js deleted file mode 100644 index d1c7e760f1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/descriptor/trait.ExtractPolicy.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/descriptor/trait.MiniscriptKey.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/descriptor/trait.MiniscriptKey.js deleted file mode 100644 index d1c7e760f1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/descriptor/trait.MiniscriptKey.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/descriptor/trait.ScriptContext.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/descriptor/trait.ScriptContext.js deleted file mode 100644 index d1c7e760f1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/descriptor/trait.ScriptContext.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/descriptor/trait.ToPublicKey.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/descriptor/trait.ToPublicKey.js deleted file mode 100644 index d1c7e760f1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/descriptor/trait.ToPublicKey.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/wallet/coin_selection/trait.CoinSelectionAlgorithm.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/wallet/coin_selection/trait.CoinSelectionAlgorithm.js deleted file mode 100644 index d1c7e760f1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/wallet/coin_selection/trait.CoinSelectionAlgorithm.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/wallet/signer/trait.Signer.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/wallet/signer/trait.Signer.js deleted file mode 100644 index d1c7e760f1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/wallet/signer/trait.Signer.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/wallet/trait.IsDust.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/wallet/trait.IsDust.js deleted file mode 100644 index d1c7e760f1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/magical/wallet/trait.IsDust.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/serde/de/trait.Deserialize.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/serde/de/trait.Deserialize.js deleted file mode 100644 index a6f4f75de7..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/serde/de/trait.Deserialize.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl<'de> Deserialize<'de> for ScriptType","synthetic":false,"types":["magical::types::ScriptType"]},{"text":"impl<'de> Deserialize<'de> for UTXO","synthetic":false,"types":["magical::types::UTXO"]},{"text":"impl<'de> Deserialize<'de> for TransactionDetails","synthetic":false,"types":["magical::types::TransactionDetails"]},{"text":"impl<'de> Deserialize<'de> for WalletExport","synthetic":false,"types":["magical::wallet::export::WalletExport"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/serde/ser/trait.Serialize.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/serde/ser/trait.Serialize.js deleted file mode 100644 index d7c8c7e8f7..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/serde/ser/trait.Serialize.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl Serialize for PKOrF","synthetic":false,"types":["magical::descriptor::policy::PKOrF"]},{"text":"impl Serialize for SatisfiableItem","synthetic":false,"types":["magical::descriptor::policy::SatisfiableItem"]},{"text":"impl Serialize for Satisfaction","synthetic":false,"types":["magical::descriptor::policy::Satisfaction"]},{"text":"impl Serialize for Policy","synthetic":false,"types":["magical::descriptor::policy::Policy"]},{"text":"impl Serialize for Condition","synthetic":false,"types":["magical::descriptor::policy::Condition"]},{"text":"impl Serialize for ScriptType","synthetic":false,"types":["magical::types::ScriptType"]},{"text":"impl Serialize for UTXO","synthetic":false,"types":["magical::types::UTXO"]},{"text":"impl Serialize for TransactionDetails","synthetic":false,"types":["magical::types::TransactionDetails"]},{"text":"impl Serialize for WalletExport","synthetic":false,"types":["magical::wallet::export::WalletExport"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/std/error/trait.Error.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/std/error/trait.Error.js deleted file mode 100644 index 8fbc02a1c9..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/std/error/trait.Error.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl Error for Error","synthetic":false,"types":["magical::error::Error"]},{"text":"impl Error for EsploraError","synthetic":false,"types":["magical::blockchain::esplora::EsploraError"]},{"text":"impl Error for CompactFiltersError","synthetic":false,"types":["magical::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Error for Error","synthetic":false,"types":["magical::descriptor::error::Error"]},{"text":"impl Error for PolicyError","synthetic":false,"types":["magical::descriptor::policy::PolicyError"]},{"text":"impl Error for AddressValidatorError","synthetic":false,"types":["magical::wallet::address_validator::AddressValidatorError"]},{"text":"impl Error for SignerError","synthetic":false,"types":["magical::wallet::signer::SignerError"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/std/panic/trait.RefUnwindSafe.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/std/panic/trait.RefUnwindSafe.js deleted file mode 100644 index 34cf2dfb24..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/std/panic/trait.RefUnwindSafe.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl RefUnwindSafe for FeeRate","synthetic":true,"types":["magical::types::FeeRate"]},{"text":"impl RefUnwindSafe for UTXO","synthetic":true,"types":["magical::types::UTXO"]},{"text":"impl RefUnwindSafe for TransactionDetails","synthetic":true,"types":["magical::types::TransactionDetails"]},{"text":"impl !RefUnwindSafe for Error","synthetic":true,"types":["magical::error::Error"]},{"text":"impl RefUnwindSafe for ScriptType","synthetic":true,"types":["magical::types::ScriptType"]},{"text":"impl RefUnwindSafe for OfflineBlockchain","synthetic":true,"types":["magical::blockchain::OfflineBlockchain"]},{"text":"impl RefUnwindSafe for NoopProgress","synthetic":true,"types":["magical::blockchain::NoopProgress"]},{"text":"impl RefUnwindSafe for LogProgress","synthetic":true,"types":["magical::blockchain::LogProgress"]},{"text":"impl RefUnwindSafe for Capability","synthetic":true,"types":["magical::blockchain::Capability"]},{"text":"impl RefUnwindSafe for ElectrumBlockchain","synthetic":true,"types":["magical::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl !RefUnwindSafe for EsploraBlockchain","synthetic":true,"types":["magical::blockchain::esplora::EsploraBlockchain"]},{"text":"impl !RefUnwindSafe for EsploraError","synthetic":true,"types":["magical::blockchain::esplora::EsploraError"]},{"text":"impl RefUnwindSafe for Mempool","synthetic":true,"types":["magical::blockchain::compact_filters::peer::Mempool"]},{"text":"impl !RefUnwindSafe for Peer","synthetic":true,"types":["magical::blockchain::compact_filters::peer::Peer"]},{"text":"impl !RefUnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":["magical::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl !RefUnwindSafe for CompactFiltersError","synthetic":true,"types":["magical::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !RefUnwindSafe for MemoryDatabase","synthetic":true,"types":["magical::database::memory::MemoryDatabase"]},{"text":"impl RefUnwindSafe for Error","synthetic":true,"types":["magical::descriptor::error::Error"]},{"text":"impl RefUnwindSafe for PKOrF","synthetic":true,"types":["magical::descriptor::policy::PKOrF"]},{"text":"impl RefUnwindSafe for Policy","synthetic":true,"types":["magical::descriptor::policy::Policy"]},{"text":"impl RefUnwindSafe for Condition","synthetic":true,"types":["magical::descriptor::policy::Condition"]},{"text":"impl RefUnwindSafe for SatisfiableItem","synthetic":true,"types":["magical::descriptor::policy::SatisfiableItem"]},{"text":"impl RefUnwindSafe for Satisfaction","synthetic":true,"types":["magical::descriptor::policy::Satisfaction"]},{"text":"impl RefUnwindSafe for PolicyError","synthetic":true,"types":["magical::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !RefUnwindSafe for Wallet<B, D>","synthetic":true,"types":["magical::wallet::Wallet"]},{"text":"impl RefUnwindSafe for AddressValidatorError","synthetic":true,"types":["magical::wallet::address_validator::AddressValidatorError"]},{"text":"impl RefUnwindSafe for CoinSelectionResult","synthetic":true,"types":["magical::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl RefUnwindSafe for DumbCoinSelection","synthetic":true,"types":["magical::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl RefUnwindSafe for WalletExport","synthetic":true,"types":["magical::wallet::export::WalletExport"]},{"text":"impl RefUnwindSafe for SignerOrdering","synthetic":true,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !RefUnwindSafe for SignersContainer<Pk>","synthetic":true,"types":["magical::wallet::signer::SignersContainer"]},{"text":"impl<Pk> RefUnwindSafe for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe
","synthetic":true,"types":["magical::wallet::signer::SignerId"]},{"text":"impl RefUnwindSafe for SignerError","synthetic":true,"types":["magical::wallet::signer::SignerError"]},{"text":"impl<Cs> RefUnwindSafe for TxBuilder<Cs> where
    Cs: RefUnwindSafe
","synthetic":true,"types":["magical::wallet::tx_builder::TxBuilder"]},{"text":"impl RefUnwindSafe for TxOrdering","synthetic":true,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl RefUnwindSafe for ChangeSpendPolicy","synthetic":true,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/implementors/std/panic/trait.UnwindSafe.js b/static/docs-rs/magical/0.1.0-beta.1/implementors/std/panic/trait.UnwindSafe.js deleted file mode 100644 index ed7f459e9d..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/implementors/std/panic/trait.UnwindSafe.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["magical"] = [{"text":"impl UnwindSafe for FeeRate","synthetic":true,"types":["magical::types::FeeRate"]},{"text":"impl UnwindSafe for UTXO","synthetic":true,"types":["magical::types::UTXO"]},{"text":"impl UnwindSafe for TransactionDetails","synthetic":true,"types":["magical::types::TransactionDetails"]},{"text":"impl !UnwindSafe for Error","synthetic":true,"types":["magical::error::Error"]},{"text":"impl UnwindSafe for ScriptType","synthetic":true,"types":["magical::types::ScriptType"]},{"text":"impl UnwindSafe for OfflineBlockchain","synthetic":true,"types":["magical::blockchain::OfflineBlockchain"]},{"text":"impl UnwindSafe for NoopProgress","synthetic":true,"types":["magical::blockchain::NoopProgress"]},{"text":"impl UnwindSafe for LogProgress","synthetic":true,"types":["magical::blockchain::LogProgress"]},{"text":"impl UnwindSafe for Capability","synthetic":true,"types":["magical::blockchain::Capability"]},{"text":"impl UnwindSafe for ElectrumBlockchain","synthetic":true,"types":["magical::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl !UnwindSafe for EsploraBlockchain","synthetic":true,"types":["magical::blockchain::esplora::EsploraBlockchain"]},{"text":"impl !UnwindSafe for EsploraError","synthetic":true,"types":["magical::blockchain::esplora::EsploraError"]},{"text":"impl UnwindSafe for Mempool","synthetic":true,"types":["magical::blockchain::compact_filters::peer::Mempool"]},{"text":"impl !UnwindSafe for Peer","synthetic":true,"types":["magical::blockchain::compact_filters::peer::Peer"]},{"text":"impl !UnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":["magical::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl !UnwindSafe for CompactFiltersError","synthetic":true,"types":["magical::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !UnwindSafe for MemoryDatabase","synthetic":true,"types":["magical::database::memory::MemoryDatabase"]},{"text":"impl UnwindSafe for Error","synthetic":true,"types":["magical::descriptor::error::Error"]},{"text":"impl UnwindSafe for PKOrF","synthetic":true,"types":["magical::descriptor::policy::PKOrF"]},{"text":"impl UnwindSafe for Policy","synthetic":true,"types":["magical::descriptor::policy::Policy"]},{"text":"impl UnwindSafe for Condition","synthetic":true,"types":["magical::descriptor::policy::Condition"]},{"text":"impl UnwindSafe for SatisfiableItem","synthetic":true,"types":["magical::descriptor::policy::SatisfiableItem"]},{"text":"impl UnwindSafe for Satisfaction","synthetic":true,"types":["magical::descriptor::policy::Satisfaction"]},{"text":"impl UnwindSafe for PolicyError","synthetic":true,"types":["magical::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !UnwindSafe for Wallet<B, D>","synthetic":true,"types":["magical::wallet::Wallet"]},{"text":"impl UnwindSafe for AddressValidatorError","synthetic":true,"types":["magical::wallet::address_validator::AddressValidatorError"]},{"text":"impl UnwindSafe for CoinSelectionResult","synthetic":true,"types":["magical::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl UnwindSafe for DumbCoinSelection","synthetic":true,"types":["magical::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl UnwindSafe for WalletExport","synthetic":true,"types":["magical::wallet::export::WalletExport"]},{"text":"impl UnwindSafe for SignerOrdering","synthetic":true,"types":["magical::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !UnwindSafe for SignersContainer<Pk>","synthetic":true,"types":["magical::wallet::signer::SignersContainer"]},{"text":"impl<Pk> UnwindSafe for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: UnwindSafe
","synthetic":true,"types":["magical::wallet::signer::SignerId"]},{"text":"impl UnwindSafe for SignerError","synthetic":true,"types":["magical::wallet::signer::SignerError"]},{"text":"impl<Cs> UnwindSafe for TxBuilder<Cs> where
    Cs: UnwindSafe
","synthetic":true,"types":["magical::wallet::tx_builder::TxBuilder"]},{"text":"impl UnwindSafe for TxOrdering","synthetic":true,"types":["magical::wallet::tx_builder::TxOrdering"]},{"text":"impl UnwindSafe for ChangeSpendPolicy","synthetic":true,"types":["magical::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/light.css b/static/docs-rs/magical/0.1.0-beta.1/light.css deleted file mode 100644 index 824281ebe9..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/light.css +++ /dev/null @@ -1 +0,0 @@ - body{background-color:white;color:black;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:black;}h1.fqn{border-bottom-color:#D5D5D5;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){border-bottom-color:#DDDDDD;}.in-band{background-color:white;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#F5F5F5;}pre{background-color:#F5F5F5;}.sidebar{background-color:#F1F1F1;}*{scrollbar-color:rgba(36,37,39,0.6) #e6e6e6;}.sidebar{scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;}::-webkit-scrollbar-track{background-color:#ecebeb;}::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar::-webkit-scrollbar-track{background-color:#dcdcdc;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar .current{background-color:#fff;}.source .sidebar{background-color:#fff;}.sidebar .location{border-color:#000;background-color:#fff;color:#333;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#F5F5F5;}.line-numbers span{color:#c67e2d;}.line-numbers .line-highlighted{background-color:#f6fdb0 !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#ddd;}.docblock table,.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#4E4C4C;}.content .highlighted{color:#000 !important;background-color:#ccc;}.content .highlighted a,.content .highlighted span{color:#000 !important;}.content .highlighted.trait{background-color:#c7b6ff;}.content .highlighted.traitalias{background-color:#c7b6ff;}.content .highlighted.mod,.content .highlighted.externcrate{background-color:#afc6e4;}.content .highlighted.enum{background-color:#b4d1b9;}.content .highlighted.struct{background-color:#e7b1a0;}.content .highlighted.union{background-color:#b7bd49;}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{background-color:#c6afb3;}.content .highlighted.type{background-color:#ffc891;}.content .highlighted.foreigntype{background-color:#f5c4ff;}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{background-color:#8ce488;}.content .highlighted.constant,.content .highlighted.static{background-color:#c3e0ff;}.content .highlighted.primitive{background-color:#9aecff;}.content .highlighted.keyword{background-color:#f99650;}.content .stability::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#508157;}.content span.struct,.content a.struct,.block a.current.struct{color:#ad448e;}.content span.type,.content a.type,.block a.current.type{color:#ba5d00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#cd00e2;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#068000;}.content span.union,.content a.union,.block a.current.union{color:#767b27;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#546e8a;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#2c8093;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#4d76ae;}.content span.trait,.content a.trait,.block a.current.trait{color:#7c5af3;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#6841f1;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#9a6e31;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8E908C;}pre.rust .doccomment{color:#4D4D4C;}nav:not(.sidebar){border-bottom-color:#e0e0e0;}nav.main .current{border-top-color:#000;border-bottom-color:#000;}nav.main .separator{border:1px solid #000;}a{color:#000;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.stability a{color:#3873AD;}.stab.internal a{color:#304FFE;}a.test-arrow{color:#f5f5f5;}.collapse-toggle{color:#999;}#crate-search{color:#555;background-color:white;border-color:#e0e0e0;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input{color:#555;background-color:white;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input:focus{border-color:#66afe9;}.search-focus:disabled{background-color:#e6e6e6;}#crate-search+.search-input:focus{box-shadow:0 0 8px #078dd8;}.module-item .stab{color:#000;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;}.stab.internal{background:#FFB9B3;border-color:#B71C1C;}.stab.deprecated{background:#F3DFFF;border-color:#7F0087;}.stab.portability{background:#C4ECFF;border-color:#7BA5DB;}.stab.portability>code{color:#000;}#help>div{background:#e9e9e9;border-color:#bfbfbf;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:black;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#8959A8;}pre.rust .kw-2,pre.rust .prelude-ty{color:#4271AE;}pre.rust .number,pre.rust .string{color:#718C00;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#C82829;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#B76514;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#c7c7c7;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label{color:#999;}:target>code,:target>.in-band{background:#FDFFD3;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.5);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.5);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip .tooltiptext{background-color:#000;color:#fff;}.tooltip .tooltiptext::after{border-color:transparent black transparent transparent;}#titles>div:not(.selected){background-color:#e6e6e6;border-top-color:#e6e6e6;}#titles>div:hover,#titles>div.selected{border-top-color:#0089ff;}#titles>div>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#F1F1F1;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#F1F1F1;border-right-color:#000;}#sidebar-filler{background-color:#F1F1F1;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu{border-color:#e0e0e0;background-color:#fff;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus{border-color:#717171;}#theme-choices{border-color:#ccc;background-color:#fff;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#eee;}@media (max-width:700px){#theme-picker{background:#fff;}}#all-types{background-color:#fff;}#all-types:hover{background-color:#f9f9f9;}.search-results td span.alias{color:#000;}.search-results td span.grey{color:#999;}#sidebar-toggle{background-color:#F1F1F1;}#sidebar-toggle:hover{background-color:#E0E0E0;}#source-sidebar{background-color:#F1F1F1;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#E0E0E0;}div.files>.selected{background-color:#fff;}.setting-line>.title{border-bottom-color:#D5D5D5;} \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/all.html b/static/docs-rs/magical/0.1.0-beta.1/magical/all.html deleted file mode 100644 index 64f8ae17af..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/all.html +++ /dev/null @@ -1,3 +0,0 @@ -List of all items in this crate

[] - - List of all items

Structs

Enums

Traits

Functions

Typedefs

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/enum.CompactFiltersError.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/enum.CompactFiltersError.html deleted file mode 100644 index 9ecce23aaf..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/enum.CompactFiltersError.html +++ /dev/null @@ -1,56 +0,0 @@ -magical::blockchain::compact_filters::CompactFiltersError - Rust

[][src]Enum magical::blockchain::compact_filters::CompactFiltersError

pub enum CompactFiltersError {
-    InvalidResponse,
-    InvalidHeaders,
-    InvalidFilterHeader,
-    InvalidFilter,
-    MissingBlock,
-    DataCorruption,
-    NotConnected,
-    Timeout,
-    NoPeers,
-    DB(Error),
-    IO(Error),
-    BIP158(Error),
-    Time(SystemTimeError),
-    Global(Box<Error>),
-}
This is supported on feature="compact_filters" only.

An error that can occur during sync with a CompactFiltersBlockchain

-

- Variants

-
InvalidResponse
This is supported on feature="compact_filters" only.

A peer sent an invalid or unexpected response

-
InvalidHeaders
This is supported on feature="compact_filters" only.

The headers returned are invalid

-
InvalidFilterHeader
This is supported on feature="compact_filters" only.

The compact filter headers returned are invalid

-
InvalidFilter
This is supported on feature="compact_filters" only.

The compact filter returned is invalid

-
MissingBlock
This is supported on feature="compact_filters" only.

The peer is missing a block in the valid chain

-
DataCorruption
This is supported on feature="compact_filters" only.

The data stored in the block filters storage are corrupted

-
NotConnected
This is supported on feature="compact_filters" only.

A peer is not connected

-
Timeout
This is supported on feature="compact_filters" only.

A peer took too long to reply to one of our messages

-
NoPeers
This is supported on feature="compact_filters" only.

No peers have been specified

-
DB(Error)
This is supported on feature="compact_filters" only.

Internal database error

-
IO(Error)
This is supported on feature="compact_filters" only.

Internal I/O error

-
BIP158(Error)
This is supported on feature="compact_filters" only.

Invalid BIP158 filter

-
This is supported on feature="compact_filters" only.

Internal system time error

-
Global(Box<Error>)
This is supported on feature="compact_filters" only.

Wrapper for crate::error::Error

-

Trait Implementations

impl Debug for CompactFiltersError[src]

impl Display for CompactFiltersError[src]

impl Error for CompactFiltersError[src]

impl From<CompactFiltersError> for Error[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for CompactFiltersError[src]

impl From<SystemTimeError> for CompactFiltersError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/index.html deleted file mode 100644 index 62db0b58ae..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/index.html +++ /dev/null @@ -1,31 +0,0 @@ -magical::blockchain::compact_filters - Rust

[][src]Module magical::blockchain::compact_filters

This is supported on feature="compact_filters" only.

Compact Filters

-

This module contains a multithreaded implementation of an OnlineBlockchain backend that -uses BIP157 (aka "Neutrino") to populate the wallet's database -by downloading compact filters from the P2P network.

-

Since there are currently very few peers "in the wild" that advertise the required service -flag, this implementation requires that one or more known peers are provided by the user. -No dns or other kinds of peer discovery are done internally.

-

Moreover, this module doesn't currently support detecting and resolving conflicts between -messages received by different peers. Thus, it's recommended to use this module by only -connecting to a single peer at a time, optionally by opening multiple connections if it's -desirable to use multiple threads at once to sync in parallel.

-

Example

-
-let num_threads = 4;
-
-let mempool = Arc::new(Mempool::default());
-let peers = (0..num_threads)
-    .map(|_| Peer::connect(
-        "btcd-mainnet.lightning.computer:8333",
-        Arc::clone(&mempool),
-        Network::Bitcoin,
-    ))
-    .collect::<Result<_, _>>()?;
-let blockchain = CompactFiltersBlockchain::new(peers, "./wallet-filters", Some(500_000))?;
-

Structs

-
CompactFiltersBlockchainfeature="compact_filters"

Structure implementing the required blockchain traits

-
Mempoolfeature="compact_filters"

Container for unconfirmed, but valid Bitcoin transactions

-
Peerfeature="compact_filters"

A Bitcoin peer

-

Enums

-
CompactFiltersErrorfeature="compact_filters"

An error that can occur during sync with a CompactFiltersBlockchain

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/peer/struct.Mempool.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/peer/struct.Mempool.html deleted file mode 100644 index f8926fff7b..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/peer/struct.Mempool.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

Redirecting to ../../../../magical/blockchain/compact_filters/struct.Mempool.html...

- - - \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/peer/struct.Peer.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/peer/struct.Peer.html deleted file mode 100644 index e30b50aa0e..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/peer/struct.Peer.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

Redirecting to ../../../../magical/blockchain/compact_filters/struct.Peer.html...

- - - \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/sidebar-items.js deleted file mode 100644 index 22c61151d6..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["CompactFiltersError","An error that can occur during sync with a [`CompactFiltersBlockchain`]"]],"struct":[["CompactFiltersBlockchain","Structure implementing the required blockchain traits"],["Mempool","Container for unconfirmed, but valid Bitcoin transactions"],["Peer","A Bitcoin peer"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/struct.CompactFiltersBlockchain.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/struct.CompactFiltersBlockchain.html deleted file mode 100644 index 6f6278dd3d..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/struct.CompactFiltersBlockchain.html +++ /dev/null @@ -1,30 +0,0 @@ -magical::blockchain::compact_filters::CompactFiltersBlockchain - Rust

[][src]Struct magical::blockchain::compact_filters::CompactFiltersBlockchain

pub struct CompactFiltersBlockchain(_);
This is supported on feature="compact_filters" only.

Structure implementing the required blockchain traits

-

Example

-

See the blockchain::compact_filters module for a usage example.

-

Implementations

impl CompactFiltersBlockchain[src]

pub fn new<P: AsRef<Path>>(
    peers: Vec<Peer>,
    storage_dir: P,
    skip_blocks: Option<usize>
) -> Result<Self, CompactFiltersError>
[src]

This is supported on feature="compact_filters" only.

Construct a new instance given a list of peers, a path to store headers and block -filters downloaded during the sync and optionally a number of blocks to ignore starting -from the genesis while scanning for the wallet's outputs.

-

For each Peer specified a new thread will be spawned to download and verify the filters -in parallel. It's currently recommended to only connect to a single peer to avoid -inconsistencies in the data returned, optionally with multiple connections in parallel to -speed-up the sync process.

-

Trait Implementations

impl Blockchain for CompactFiltersBlockchain[src]

impl Debug for CompactFiltersBlockchain[src]

impl OnlineBlockchain for CompactFiltersBlockchain[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/struct.Mempool.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/struct.Mempool.html deleted file mode 100644 index 7da018971b..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/struct.Mempool.html +++ /dev/null @@ -1,21 +0,0 @@ -magical::blockchain::compact_filters::Mempool - Rust

[][src]Struct magical::blockchain::compact_filters::Mempool

pub struct Mempool { /* fields omitted */ }
This is supported on feature="compact_filters" only.

Container for unconfirmed, but valid Bitcoin transactions

-

It is normally shared between Peers with the use of Arc, so that transactions are not -duplicated in memory.

-

Implementations

impl Mempool[src]

pub fn add_tx(&self, tx: Transaction)[src]

This is supported on feature="compact_filters" only.

Add a transaction to the mempool

-

Note that this doesn't propagate the transaction to other -peers. To do that, broadcast should be used.

-

pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction>[src]

This is supported on feature="compact_filters" only.

Look-up a transaction in the mempool given an [Inventory] request

-

pub fn has_tx(&self, txid: &Txid) -> bool[src]

This is supported on feature="compact_filters" only.

Return whether or not the mempool contains a transaction with a given txid

-

pub fn iter_txs(&self) -> Vec<Transaction>[src]

This is supported on feature="compact_filters" only.

Return the list of transactions contained in the mempool

-

Trait Implementations

impl Debug for Mempool[src]

impl Default for Mempool[src]

Auto Trait Implementations

impl RefUnwindSafe for Mempool

impl Send for Mempool

impl Sync for Mempool

impl Unpin for Mempool

impl UnwindSafe for Mempool

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/struct.Peer.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/struct.Peer.html deleted file mode 100644 index 0c1903c51c..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/compact_filters/struct.Peer.html +++ /dev/null @@ -1,25 +0,0 @@ -magical::blockchain::compact_filters::Peer - Rust

[][src]Struct magical::blockchain::compact_filters::Peer

pub struct Peer { /* fields omitted */ }
This is supported on feature="compact_filters" only.

A Bitcoin peer

-

Implementations

impl Peer[src]

pub fn connect<A: ToSocketAddrs>(
    address: A,
    mempool: Arc<Mempool>,
    network: Network
) -> Result<Self, CompactFiltersError>
[src]

This is supported on feature="compact_filters" only.

Connect to a peer over a plaintext TCP connection

-

This function internally spawns a new thread that will monitor incoming messages from the -peer, and optionally reply to some of them transparently, like pings

-

pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
    target: T,
    proxy: P,
    credentials: Option<(&str, &str)>,
    mempool: Arc<Mempool>,
    network: Network
) -> Result<Self, CompactFiltersError>
[src]

This is supported on feature="compact_filters" only.

Connect to a peer through a SOCKS5 proxy, optionally by using some credentials, specified -as a tuple of (username, password)

-

This function internally spawns a new thread that will monitor incoming messages from the -peer, and optionally reply to some of them transparently, like pings

-

pub fn get_version(&self) -> &VersionMessage[src]

This is supported on feature="compact_filters" only.

Return the [VersionMessage] sent by the peer

-

pub fn get_network(&self) -> Network[src]

This is supported on feature="compact_filters" only.

Return the Bitcoin [Network] in use

-

pub fn get_mempool(&self) -> Arc<Mempool>[src]

This is supported on feature="compact_filters" only.

Return the mempool used by this peer

-

pub fn is_connected(&self) -> bool[src]

This is supported on feature="compact_filters" only.

Return whether or not the peer is still connected

-

pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError>[src]

This is supported on feature="compact_filters" only.

Send a raw Bitcoin message to the peer

-

pub fn recv(
    &self,
    wait_for: &'static str,
    timeout: Option<Duration>
) -> Result<Option<NetworkMessage>, CompactFiltersError>
[src]

This is supported on feature="compact_filters" only.

Waits for a specific incoming Bitcoin message, optionally with a timeout

-

Trait Implementations

impl Debug for Peer[src]

Auto Trait Implementations

impl !RefUnwindSafe for Peer

impl Send for Peer

impl Sync for Peer

impl Unpin for Peer

impl !UnwindSafe for Peer

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/electrum/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/electrum/index.html deleted file mode 100644 index fbf4916cc9..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/electrum/index.html +++ /dev/null @@ -1,11 +0,0 @@ -magical::blockchain::electrum - Rust

[][src]Module magical::blockchain::electrum

This is supported on feature="electrum" only.

Electrum

-

This module defines an OnlineBlockchain struct that wraps an [electrum_client::Client] -and implements the logic required to populate the wallet's database by -querying the inner client.

-

Example

-
-let client = electrum_client::Client::new("ssl://electrum.blockstream.info:50002", None)?;
-let blockchain = ElectrumBlockchain::from(client);
-

Structs

-
ElectrumBlockchainfeature="electrum"

Wrapper over an Electrum Client that implements the required blockchain traits

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/electrum/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/electrum/sidebar-items.js deleted file mode 100644 index ca94a34fb0..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/electrum/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["ElectrumBlockchain","Wrapper over an Electrum Client that implements the required blockchain traits"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/electrum/struct.ElectrumBlockchain.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/electrum/struct.ElectrumBlockchain.html deleted file mode 100644 index bbef4d00d3..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/electrum/struct.ElectrumBlockchain.html +++ /dev/null @@ -1,23 +0,0 @@ -magical::blockchain::electrum::ElectrumBlockchain - Rust

[][src]Struct magical::blockchain::electrum::ElectrumBlockchain

pub struct ElectrumBlockchain(_);
This is supported on feature="electrum" only.

Wrapper over an Electrum Client that implements the required blockchain traits

-

Example

-

See the blockchain::electrum module for a usage example.

-

Trait Implementations

impl Blockchain for ElectrumBlockchain[src]

impl From<Client> for ElectrumBlockchain[src]

impl OnlineBlockchain for ElectrumBlockchain[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/enum.Capability.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/enum.Capability.html deleted file mode 100644 index efc9fa8421..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/enum.Capability.html +++ /dev/null @@ -1,32 +0,0 @@ -magical::blockchain::Capability - Rust

[][src]Enum magical::blockchain::Capability

pub enum Capability {
-    FullHistory,
-    GetAnyTx,
-    AccurateFees,
-}

Capabilities that can be supported by an OnlineBlockchain backend

-

- Variants

-
FullHistory

Can recover the full history of a wallet and not only the set of currently spendable UTXOs

-
GetAnyTx

Can fetch any historical transaction given its txid

-
AccurateFees

Can compute accurate fees for the transactions found during sync

-

Trait Implementations

impl Clone for Capability[src]

impl Copy for Capability[src]

impl Debug for Capability[src]

impl Eq for Capability[src]

impl Hash for Capability[src]

impl PartialEq<Capability> for Capability[src]

impl StructuralEq for Capability[src]

impl StructuralPartialEq for Capability[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/esplora/enum.EsploraError.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/esplora/enum.EsploraError.html deleted file mode 100644 index 7dd9e3bff2..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/esplora/enum.EsploraError.html +++ /dev/null @@ -1,34 +0,0 @@ -magical::blockchain::esplora::EsploraError - Rust

[][src]Enum magical::blockchain::esplora::EsploraError

pub enum EsploraError {
-    Reqwest(Error),
-    Parsing(ParseIntError),
-    BitcoinEncoding(Error),
-    TransactionNotFound(Txid),
-}
This is supported on feature="esplora" only.

Errors that can happen during a sync with EsploraBlockchain

-

- Variants

-
Reqwest(Error)
This is supported on feature="esplora" only.

Error with the HTTP call

-
Parsing(ParseIntError)
This is supported on feature="esplora" only.

Invalid number returned

-
BitcoinEncoding(Error)
This is supported on feature="esplora" only.

Invalid Bitcoin data returned

-
TransactionNotFound(Txid)
This is supported on feature="esplora" only.

Transaction not found

-

Trait Implementations

impl Debug for EsploraError[src]

impl Display for EsploraError[src]

impl Error for EsploraError[src]

impl From<Error> for EsploraError[src]

impl From<Error> for EsploraError[src]

impl From<EsploraError> for Error[src]

impl From<ParseIntError> for EsploraError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/esplora/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/esplora/index.html deleted file mode 100644 index 50a0aa3ead..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/esplora/index.html +++ /dev/null @@ -1,11 +0,0 @@ -magical::blockchain::esplora - Rust

[][src]Module magical::blockchain::esplora

This is supported on feature="esplora" only.

Esplora

-

This module defines an OnlineBlockchain struct that can query an Esplora backend -populate the wallet's database by

-

Example

-
-let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api");
-

Structs

-
EsploraBlockchainfeature="esplora"

Structure that implements the logic to sync with Esplora

-

Enums

-
EsploraErrorfeature="esplora"

Errors that can happen during a sync with EsploraBlockchain

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/esplora/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/esplora/sidebar-items.js deleted file mode 100644 index fc6ecf6be6..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/esplora/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["EsploraError","Errors that can happen during a sync with [`EsploraBlockchain`]"]],"struct":[["EsploraBlockchain","Structure that implements the logic to sync with Esplora"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/esplora/struct.EsploraBlockchain.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/esplora/struct.EsploraBlockchain.html deleted file mode 100644 index b5fc8be956..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/esplora/struct.EsploraBlockchain.html +++ /dev/null @@ -1,24 +0,0 @@ -magical::blockchain::esplora::EsploraBlockchain - Rust

[][src]Struct magical::blockchain::esplora::EsploraBlockchain

pub struct EsploraBlockchain(_);
This is supported on feature="esplora" only.

Structure that implements the logic to sync with Esplora

-

Example

-

See the blockchain::esplora module for a usage example.

-

Implementations

impl EsploraBlockchain[src]

pub fn new(base_url: &str) -> Self[src]

This is supported on feature="esplora" only.

Create a new instance of the client from a base URL

-

Trait Implementations

impl Blockchain for EsploraBlockchain[src]

impl Debug for EsploraBlockchain[src]

impl OnlineBlockchain for EsploraBlockchain[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/fn.log_progress.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/fn.log_progress.html deleted file mode 100644 index 7f947f9072..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/fn.log_progress.html +++ /dev/null @@ -1,2 +0,0 @@ -magical::blockchain::log_progress - Rust

[][src]Function magical::blockchain::log_progress

pub fn log_progress() -> LogProgress

Create a nwe instance of LogProgress

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/fn.noop_progress.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/fn.noop_progress.html deleted file mode 100644 index b3060a70e1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/fn.noop_progress.html +++ /dev/null @@ -1,2 +0,0 @@ -magical::blockchain::noop_progress - Rust

[][src]Function magical::blockchain::noop_progress

pub fn noop_progress() -> NoopProgress

Create a new instance of NoopProgress

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/fn.progress.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/fn.progress.html deleted file mode 100644 index e3ffe97977..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/fn.progress.html +++ /dev/null @@ -1,2 +0,0 @@ -magical::blockchain::progress - Rust

[][src]Function magical::blockchain::progress

pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>)

Shortcut to create a channel (pair of Sender and Receiver) that can transport ProgressData

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/index.html deleted file mode 100644 index c5ec9d6e30..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/index.html +++ /dev/null @@ -1,35 +0,0 @@ -magical::blockchain - Rust

[][src]Module magical::blockchain

Blockchain backends

-

This module provides the implementation of a few commonly-used backends like -Electrum, Esplora and -Compact Filters/Neutrino, along with two generalized -traits Blockchain and OnlineBlockchain that can be implemented to build customized -backends.

-

Types that only implement the Blockchain trait can be used as backends for Wallets, but any -action that requires interacting with the blockchain won't be available (Wallet::sync and -Wallet::broadcast). This allows the creation of physically air-gapped wallets, that have no -ability to contact the outside world. An example of an offline-only client is OfflineBlockchain.

-

Types that also implement OnlineBlockchain will make the two aforementioned actions -available.

-

Re-exports

-
pub use self::electrum::ElectrumBlockchain;
pub use self::esplora::EsploraBlockchain;
pub use self::compact_filters::CompactFiltersBlockchain;

Modules

-
compact_filtersfeature="compact_filters"

Compact Filters

-
electrumfeature="electrum"

Electrum

-
esplorafeature="esplora"

Esplora

-

Structs

-
LogProgress

Type that implements Progress and logs at level INFO every update received

-
NoopProgress

Type that implements Progress and drops every update received

-
OfflineBlockchain

Type that only implements Blockchain and is always offline

-

Enums

-
Capability

Capabilities that can be supported by an OnlineBlockchain backend

-

Traits

-
Blockchain

Base trait for a blockchain backend

-
OnlineBlockchain

Trait that defines the actions that must be supported by an online Blockchain

-
Progress

Trait for types that can receive and process progress updates during OnlineBlockchain::sync and -OnlineBlockchain::setup

-

Functions

-
log_progress

Create a nwe instance of LogProgress

-
noop_progress

Create a new instance of NoopProgress

-
progress

Shortcut to create a channel (pair of Sender and Receiver) that can transport ProgressData

-

Type Definitions

-
ProgressData

Data sent with a progress update over a channel

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/sidebar-items.js deleted file mode 100644 index 43daf08c27..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Capability","Capabilities that can be supported by an [`OnlineBlockchain`] backend"]],"fn":[["log_progress","Create a nwe instance of [`LogProgress`]"],["noop_progress","Create a new instance of [`NoopProgress`]"],["progress","Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]"]],"mod":[["compact_filters","Compact Filters"],["electrum","Electrum"],["esplora","Esplora"]],"struct":[["LogProgress","Type that implements [`Progress`] and logs at level `INFO` every update received"],["NoopProgress","Type that implements [`Progress`] and drops every update received"],["OfflineBlockchain","Type that only implements [`Blockchain`] and is always offline"]],"trait":[["Blockchain","Base trait for a blockchain backend"],["OnlineBlockchain","Trait that defines the actions that must be supported by an online [`Blockchain`]"],["Progress","Trait for types that can receive and process progress updates during [`OnlineBlockchain::sync`] and [`OnlineBlockchain::setup`]"]],"type":[["ProgressData","Data sent with a progress update over a [`channel`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/struct.LogProgress.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/struct.LogProgress.html deleted file mode 100644 index 6b22c6efd3..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/struct.LogProgress.html +++ /dev/null @@ -1,18 +0,0 @@ -magical::blockchain::LogProgress - Rust

[][src]Struct magical::blockchain::LogProgress

pub struct LogProgress;

Type that implements Progress and logs at level INFO every update received

-

Trait Implementations

impl Clone for LogProgress[src]

impl Progress for LogProgress[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/struct.NoopProgress.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/struct.NoopProgress.html deleted file mode 100644 index 0f3b5d948e..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/struct.NoopProgress.html +++ /dev/null @@ -1,18 +0,0 @@ -magical::blockchain::NoopProgress - Rust

[][src]Struct magical::blockchain::NoopProgress

pub struct NoopProgress;

Type that implements Progress and drops every update received

-

Trait Implementations

impl Clone for NoopProgress[src]

impl Progress for NoopProgress[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/struct.OfflineBlockchain.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/struct.OfflineBlockchain.html deleted file mode 100644 index 8bd05fb347..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/struct.OfflineBlockchain.html +++ /dev/null @@ -1,13 +0,0 @@ -magical::blockchain::OfflineBlockchain - Rust

[][src]Struct magical::blockchain::OfflineBlockchain

pub struct OfflineBlockchain;

Type that only implements Blockchain and is always offline

-

Trait Implementations

impl Blockchain for OfflineBlockchain[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/trait.Blockchain.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/trait.Blockchain.html deleted file mode 100644 index 99d792ef1a..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/trait.Blockchain.html +++ /dev/null @@ -1,19 +0,0 @@ -magical::blockchain::Blockchain - Rust

[][src]Trait magical::blockchain::Blockchain

pub trait Blockchain {
-    fn is_online(&self) -> bool;
-
fn offline() -> Self; -}

Base trait for a blockchain backend

-

This trait is always required, even for "air-gapped" backends that don't actually make any -external call. Clients that have the ability to make external calls must also implement OnlineBlockchain.

-
-

Required methods

fn is_online(&self) -> bool

Return whether or not the client has the ability to fullfill requests

-

This should always be false for offline-only types, and can be true for types that also -implement OnlineBlockchain, if they have the ability to fullfill requests.

-

fn offline() -> Self

Create a new instance of the client that is offline-only

-

For types that also implement OnlineBlockchain, this means creating an instance that -returns Error::OfflineClient if any of the "online" -methods are called.

-

This is generally implemented by wrapping the client in an Option that has Option::None value -when created with this method, and is Option::Some if properly instantiated.

-
Loading content... -

Implementations on Foreign Types

impl<T: Blockchain> Blockchain for Arc<T>[src]

Loading content... -

Implementors

impl Blockchain for CompactFiltersBlockchain[src]

impl Blockchain for ElectrumBlockchain[src]

impl Blockchain for EsploraBlockchain[src]

impl Blockchain for OfflineBlockchain[src]

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/trait.OnlineBlockchain.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/trait.OnlineBlockchain.html deleted file mode 100644 index 25e2622528..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/trait.OnlineBlockchain.html +++ /dev/null @@ -1,37 +0,0 @@ -magical::blockchain::OnlineBlockchain - Rust

[][src]Trait magical::blockchain::OnlineBlockchain

pub trait OnlineBlockchain: Blockchain {
-    fn get_capabilities(&self) -> HashSet<Capability>;
-
fn setup<D: BatchDatabase, P: 'static + Progress>(
        &self,
        stop_gap: Option<usize>,
        database: &mut D,
        progress_update: P
    ) -> Result<(), Error>; -
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>; -
fn broadcast(&self, tx: &Transaction) -> Result<(), Error>; -
fn get_height(&self) -> Result<u32, Error>; -
fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>; - - fn sync<D: BatchDatabase, P: 'static + Progress>(
        &self,
        stop_gap: Option<usize>,
        database: &mut D,
        progress_update: P
    ) -> Result<(), Error> { ... } -}

Trait that defines the actions that must be supported by an online Blockchain

-
-

Required methods

fn get_capabilities(&self) -> HashSet<Capability>

Return the set of Capability supported by this backend

-

fn setup<D: BatchDatabase, P: 'static + Progress>(
    &self,
    stop_gap: Option<usize>,
    database: &mut D,
    progress_update: P
) -> Result<(), Error>

Setup the backend and populate the internal database for the first time

-

This method is the equivalent of OnlineBlockchain::sync, but it's guaranteed to only be -called once, at the first Wallet::sync.

-

The rationale behind the distinction between sync and setup is that some custom backends -might need to perform specific actions only the first time they are synced.

-

For types that do not have that distinction, only this method can be implemented, since -OnlineBlockchain::sync defaults to calling this internally if not overridden.

-

fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>

Fetch a transaction from the blockchain given its txid

-

fn broadcast(&self, tx: &Transaction) -> Result<(), Error>

Broadcast a transaction

-

fn get_height(&self) -> Result<u32, Error>

Return the current height

-

fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>

Estimate the fee rate required to confirm a transaction in a given target of blocks

-
Loading content... -

Provided methods

fn sync<D: BatchDatabase, P: 'static + Progress>(
    &self,
    stop_gap: Option<usize>,
    database: &mut D,
    progress_update: P
) -> Result<(), Error>

Populate the internal database with transactions and UTXOs

-

If not overridden, it defaults to calling OnlineBlockchain::setup internally.

-

This method should implement the logic required to iterate over the list of the wallet's -script_pubkeys using Database::iter_script_pubkeys and look for relevant transactions -in the blockchain to populate the database with BatchOperations::set_tx and -BatchOperations::set_utxo.

-

This method should also take care of removing UTXOs that are seen as spent in the -blockchain, using BatchOperations::del_utxo.

-

The progress_update object can be used to give the caller updates about the progress by using -Progress::update.

-
Loading content... -

Implementations on Foreign Types

impl<T: OnlineBlockchain> OnlineBlockchain for Arc<T>[src]

Loading content... -

Implementors

impl OnlineBlockchain for CompactFiltersBlockchain[src]

impl OnlineBlockchain for ElectrumBlockchain[src]

impl OnlineBlockchain for EsploraBlockchain[src]

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/trait.Progress.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/trait.Progress.html deleted file mode 100644 index 7a04111481..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/trait.Progress.html +++ /dev/null @@ -1,11 +0,0 @@ -magical::blockchain::Progress - Rust

[][src]Trait magical::blockchain::Progress

pub trait Progress: Send {
-    fn update(
        &self,
        progress: f32,
        message: Option<String>
    ) -> Result<(), Error>; -}

Trait for types that can receive and process progress updates during OnlineBlockchain::sync and -OnlineBlockchain::setup

-
-

Required methods

fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error>

Send a new progress update

-

The progress value should be in the range 0.0 - 100.0, and the message value is an -optional text message that can be displayed to the user.

-
Loading content... -

Implementations on Foreign Types

impl Progress for Sender<ProgressData>[src]

Loading content... -

Implementors

impl Progress for LogProgress[src]

impl Progress for NoopProgress[src]

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/type.ProgressData.html b/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/type.ProgressData.html deleted file mode 100644 index fca05953bf..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/blockchain/type.ProgressData.html +++ /dev/null @@ -1,2 +0,0 @@ -magical::blockchain::ProgressData - Rust

[][src]Type Definition magical::blockchain::ProgressData

type ProgressData = (f32, Option<String>);

Data sent with a progress update over a channel

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/database/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/database/index.html deleted file mode 100644 index f816d30880..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/database/index.html +++ /dev/null @@ -1,17 +0,0 @@ -magical::database - Rust

[][src]Module magical::database

Database types

-

This module provides the implementation of some defaults database types, along with traits that -can be implemented externally to let Wallets use customized databases.

-

It's important to note that the databases defined here only contains "blockchain-related" data. -They can be seen more as a cache than a critical piece of storage that contains secrets and -keys.

-

The currently recommended database is [sled], which is a pretty simple key-value embedded -database written in Rust. If the key-value-db feature is enabled (which by default is), -this library automatically implements all the required traits for [sled::Tree].

-

Re-exports

-
pub use memory::MemoryDatabase;

Modules

-
memory

In-memory ephemeral database

-

Traits

-
BatchDatabase

Trait for a database that supports batch operations

-
BatchOperations

Trait for operations that can be batched

-
Database

Trait for reading data from a database

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/database/memory/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/database/memory/index.html deleted file mode 100644 index 056e5c0d13..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/database/memory/index.html +++ /dev/null @@ -1,6 +0,0 @@ -magical::database::memory - Rust

[][src]Module magical::database::memory

In-memory ephemeral database

-

This module defines an in-memory database type called MemoryDatabase that is based on a -BTreeMap.

-

Structs

-
MemoryDatabase

In-memory ephemeral database

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/database/memory/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/database/memory/sidebar-items.js deleted file mode 100644 index 665f6718d0..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/database/memory/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["MemoryDatabase","In-memory ephemeral database"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/database/memory/struct.MemoryDatabase.html b/static/docs-rs/magical/0.1.0-beta.1/magical/database/memory/struct.MemoryDatabase.html deleted file mode 100644 index d79841651b..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/database/memory/struct.MemoryDatabase.html +++ /dev/null @@ -1,45 +0,0 @@ -magical::database::memory::MemoryDatabase - Rust

[][src]Struct magical::database::memory::MemoryDatabase

pub struct MemoryDatabase { /* fields omitted */ }

In-memory ephemeral database

-

This database can be used as a temporary storage for wallets that are not kept permanently on -a device, or on platforms that don't provide a filesystem, like wasm32.

-

Once it's dropped its content will be lost.

-

If you are looking for a permanent storage solution, you can try with the default key-value -database called [sled]. See the database module documentation for more defailts.

-

Implementations

impl MemoryDatabase[src]

pub fn new() -> Self[src]

Create a new empty database

-

Trait Implementations

impl BatchDatabase for MemoryDatabase[src]

type Batch = Self

Container for the operations

-

impl BatchOperations for MemoryDatabase[src]

impl Database for MemoryDatabase[src]

impl Debug for MemoryDatabase[src]

impl Default for MemoryDatabase[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/database/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/database/sidebar-items.js deleted file mode 100644 index 1d5816196c..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/database/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"mod":[["memory","In-memory ephemeral database"]],"trait":[["BatchDatabase","Trait for a database that supports batch operations"],["BatchOperations","Trait for operations that can be batched"],["Database","Trait for reading data from a database"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/database/trait.BatchDatabase.html b/static/docs-rs/magical/0.1.0-beta.1/magical/database/trait.BatchDatabase.html deleted file mode 100644 index 6b5b608059..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/database/trait.BatchDatabase.html +++ /dev/null @@ -1,14 +0,0 @@ -magical::database::BatchDatabase - Rust

[][src]Trait magical::database::BatchDatabase

pub trait BatchDatabase: Database {
-    type Batch: BatchOperations;
-    fn begin_batch(&self) -> Self::Batch;
-
fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>; -}

Trait for a database that supports batch operations

-

This trait defines the methods to start and apply a batch of operations.

-
-

Associated Types

type Batch: BatchOperations

Container for the operations

-
Loading content... -

Required methods

fn begin_batch(&self) -> Self::Batch

Create a new batch container

-

fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>

Consume and apply a batch of operations

-
Loading content... -

Implementations on Foreign Types

impl BatchDatabase for Tree[src]

type Batch = Batch

Loading content... -

Implementors

impl BatchDatabase for MemoryDatabase[src]

type Batch = Self

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/database/trait.BatchOperations.html b/static/docs-rs/magical/0.1.0-beta.1/magical/database/trait.BatchOperations.html deleted file mode 100644 index bd30b70f9b..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/database/trait.BatchOperations.html +++ /dev/null @@ -1,31 +0,0 @@ -magical::database::BatchOperations - Rust

[][src]Trait magical::database::BatchOperations

pub trait BatchOperations {
-    fn set_script_pubkey(
        &mut self,
        script: &Script,
        script_type: ScriptType,
        child: u32
    ) -> Result<(), Error>; -
fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>; -
fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>; -
fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>; -
fn set_last_index(
        &mut self,
        script_type: ScriptType,
        value: u32
    ) -> Result<(), Error>; -
fn del_script_pubkey_from_path(
        &mut self,
        script_type: ScriptType,
        child: u32
    ) -> Result<Option<Script>, Error>; -
fn del_path_from_script_pubkey(
        &mut self,
        script: &Script
    ) -> Result<Option<(ScriptType, u32)>, Error>; -
fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>; -
fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>; -
fn del_tx(
        &mut self,
        txid: &Txid,
        include_raw: bool
    ) -> Result<Option<TransactionDetails>, Error>; -
fn del_last_index(
        &mut self,
        script_type: ScriptType
    ) -> Result<Option<u32>, Error>; -}

Trait for operations that can be batched

-

This trait defines the list of operations that must be implemented on the Database type and -the BatchDatabase::Batch type.

-
-

Required methods

fn set_script_pubkey(
    &mut self,
    script: &Script,
    script_type: ScriptType,
    child: u32
) -> Result<(), Error>

Store a script_pubkey along with its script type and child number

-

fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>

Store a UTXO

-

fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>

Store a raw transaction

-

fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>

Store the metadata of a transaction

-

fn set_last_index(
    &mut self,
    script_type: ScriptType,
    value: u32
) -> Result<(), Error>

Store the last derivation index for a given script type

-

fn del_script_pubkey_from_path(
    &mut self,
    script_type: ScriptType,
    child: u32
) -> Result<Option<Script>, Error>

Delete a script_pubkey given the script type and its child number

-

fn del_path_from_script_pubkey(
    &mut self,
    script: &Script
) -> Result<Option<(ScriptType, u32)>, Error>

Delete the data related to a specific script_pubkey, meaning the script type and the child -number

-

fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>

Delete a UTXO given its [OutPoint]

-

fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>

Delete a raw transaction given its [Txid]

-

fn del_tx(
    &mut self,
    txid: &Txid,
    include_raw: bool
) -> Result<Option<TransactionDetails>, Error>

Delete the metadata of a transaction and optionally the raw transaction itself

-

fn del_last_index(
    &mut self,
    script_type: ScriptType
) -> Result<Option<u32>, Error>

Delete the last derivation index for a script type

-
Loading content... -

Implementations on Foreign Types

impl BatchOperations for Tree[src]

impl BatchOperations for Batch[src]

Loading content... -

Implementors

impl BatchOperations for MemoryDatabase[src]

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/database/trait.Database.html b/static/docs-rs/magical/0.1.0-beta.1/magical/database/trait.Database.html deleted file mode 100644 index 23bf67d362..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/database/trait.Database.html +++ /dev/null @@ -1,35 +0,0 @@ -magical::database::Database - Rust

[][src]Trait magical::database::Database

pub trait Database: BatchOperations {
-    fn check_descriptor_checksum<B: AsRef<[u8]>>(
        &mut self,
        script_type: ScriptType,
        bytes: B
    ) -> Result<(), Error>; -
fn iter_script_pubkeys(
        &self,
        script_type: Option<ScriptType>
    ) -> Result<Vec<Script>, Error>; -
fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>; -
fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>; -
fn iter_txs(
        &self,
        include_raw: bool
    ) -> Result<Vec<TransactionDetails>, Error>; -
fn get_script_pubkey_from_path(
        &self,
        script_type: ScriptType,
        child: u32
    ) -> Result<Option<Script>, Error>; -
fn get_path_from_script_pubkey(
        &self,
        script: &Script
    ) -> Result<Option<(ScriptType, u32)>, Error>; -
fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>; -
fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>; -
fn get_tx(
        &self,
        txid: &Txid,
        include_raw: bool
    ) -> Result<Option<TransactionDetails>, Error>; -
fn get_last_index(
        &self,
        script_type: ScriptType
    ) -> Result<Option<u32>, Error>; -
fn increment_last_index(
        &mut self,
        script_type: ScriptType
    ) -> Result<u32, Error>; -}

Trait for reading data from a database

-

This traits defines the operations that can be used to read data out of a database

-
-

Required methods

fn check_descriptor_checksum<B: AsRef<[u8]>>(
    &mut self,
    script_type: ScriptType,
    bytes: B
) -> Result<(), Error>

Read and checks the descriptor checksum for a given script type

-

Should return Error::ChecksumMismatch if the -checksum doesn't match. If there's no checksum in the database, simply store it for the -next time.

-

fn iter_script_pubkeys(
    &self,
    script_type: Option<ScriptType>
) -> Result<Vec<Script>, Error>

Return the list of script_pubkeys

-

fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>

Return the list of UTXOs

-

fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>

Return the list of raw transactions

-

fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error>

Return the list of transactions metadata

-

fn get_script_pubkey_from_path(
    &self,
    script_type: ScriptType,
    child: u32
) -> Result<Option<Script>, Error>

Fetch a script_pubkey given the script type and child number

-

fn get_path_from_script_pubkey(
    &self,
    script: &Script
) -> Result<Option<(ScriptType, u32)>, Error>

Fetch the script type and child number of a given script_pubkey

-

fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>

Fetch a UTXO given its [OutPoint]

-

fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>

Fetch a raw transaction given its [Txid]

-

fn get_tx(
    &self,
    txid: &Txid,
    include_raw: bool
) -> Result<Option<TransactionDetails>, Error>

Fetch the transaction metadata and optionally also the raw transaction

-

fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error>

Return the last defivation index for a script type

-

fn increment_last_index(
    &mut self,
    script_type: ScriptType
) -> Result<u32, Error>

Increment the last derivation index for a script type and returns it

-

It should insert and return 0 if not present in the database

-
Loading content... -

Implementations on Foreign Types

impl Database for Tree[src]

Loading content... -

Implementors

impl Database for MemoryDatabase[src]

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/checksum/fn.get_checksum.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/checksum/fn.get_checksum.html deleted file mode 100644 index f67794fd52..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/checksum/fn.get_checksum.html +++ /dev/null @@ -1,2 +0,0 @@ -magical::descriptor::checksum::get_checksum - Rust

[][src]Function magical::descriptor::checksum::get_checksum

pub fn get_checksum(desc: &str) -> Result<String, Error>

Compute the checksum of a descriptor

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/checksum/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/checksum/index.html deleted file mode 100644 index 1300355ced..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/checksum/index.html +++ /dev/null @@ -1,6 +0,0 @@ -magical::descriptor::checksum - Rust

[][src]Module magical::descriptor::checksum

Descriptor checksum

-

This module contains a re-implementation of the function used by Bitcoin Core to calculate the -checksum of a descriptor

-

Functions

-
get_checksum

Compute the checksum of a descriptor

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/checksum/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/checksum/sidebar-items.js deleted file mode 100644 index e1add094a5..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/checksum/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"fn":[["get_checksum","Compute the checksum of a descriptor"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/enum.Descriptor.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/enum.Descriptor.html deleted file mode 100644 index 46ffe69ce9..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/enum.Descriptor.html +++ /dev/null @@ -1,80 +0,0 @@ -magical::descriptor::Descriptor - Rust

[]Enum magical::descriptor::Descriptor

pub enum Descriptor<Pk> where
    Pk: MiniscriptKey
{ - Bare(Miniscript<Pk, Legacy>), - Pk(Pk), - Pkh(Pk), - Wpkh(Pk), - ShWpkh(Pk), - Sh(Miniscript<Pk, Legacy>), - Wsh(Miniscript<Pk, Segwitv0>), - ShWsh(Miniscript<Pk, Segwitv0>), -}

Script descriptor

-

- Variants

-
Bare(Miniscript<Pk, Legacy>)

A raw scriptpubkey (including pay-to-pubkey) under Legacy context

-
Pk(Pk)

Pay-to-Pubkey

-
Pkh(Pk)

Pay-to-PubKey-Hash

-
Wpkh(Pk)

Pay-to-Witness-PubKey-Hash

-
ShWpkh(Pk)

Pay-to-Witness-PubKey-Hash inside P2SH

-

Pay-to-ScriptHash with Legacy context

-

Pay-to-Witness-ScriptHash with Segwitv0 context

-
ShWsh(Miniscript<Pk, Segwitv0>)

P2SH-P2WSH with Segwitv0 context

-

Implementations

impl<Pk> Descriptor<Pk> where
    Pk: MiniscriptKey

pub fn translate_pk<Fpk, Fpkh, Q, E>(
    &self,
    translatefpk: Fpk,
    translatefpkh: Fpkh
) -> Result<Descriptor<Q>, E> where
    Fpk: FnMut(&Pk) -> Result<Q, E>,
    Fpkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, E>,
    Q: MiniscriptKey

Convert a descriptor using abstract keys to one using specific keys -This will panic if translatefpk returns an uncompressed key when -converting to a Segwit descriptor. To prevent this panic, ensure -translatefpk returns an error in this case instead.

-

impl<Pk> Descriptor<Pk> where
    Pk: MiniscriptKey + ToPublicKey

pub fn address(&self, network: Network) -> Option<Address>

Computes the Bitcoin address of the descriptor, if one exists

-

pub fn script_pubkey(&self) -> Script

Computes the scriptpubkey of the descriptor

-

pub fn unsigned_script_sig(&self) -> Script

Computes the scriptSig that will be in place for an unsigned -input spending an output with this descriptor. For pre-segwit -descriptors, which use the scriptSig for signatures, this -returns the empty script.

-

This is used in Segwit transactions to produce an unsigned -transaction whose txid will not change during signing (since -only the witness data will change).

-

pub fn witness_script(&self) -> Script

Computes the "witness script" of the descriptor, i.e. the underlying -script before any hashing is done. For Bare, Pkh and Wpkh this -is the scriptPubkey; for ShWpkh and Sh this is the redeemScript; -for the others it is the witness script.

-

pub fn satisfy<S>(&self, txin: &mut TxIn, satisfier: S) -> Result<(), Error> where
    S: Satisfier<Pk>, 

Attempts to produce a satisfying witness and scriptSig to spend an -output controlled by the given descriptor; add the data to a given -TxIn output.

-

pub fn max_satisfaction_weight(&self) -> usize

Computes an upper bound on the weight of a satisfying witness to the -transaction. Assumes all signatures are 73 bytes, including push opcode -and sighash suffix. Includes the weight of the VarInts encoding the -scriptSig and witness stack length.

-

impl Descriptor<DescriptorPublicKey>

pub fn derive(&self, path: &[ChildNumber]) -> Descriptor<DescriptorPublicKey>

Derives all wildcard keys in the descriptor using the supplied path

-

pub fn parse_secret(
    s: &str
) -> Result<(Descriptor<DescriptorPublicKey>, HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>), Error>

pub fn to_string_with_secret(
    &self,
    key_map: &HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>
) -> String

Trait Implementations

impl<Pk> Clone for Descriptor<Pk> where
    Pk: MiniscriptKey + Clone

impl<Pk> Debug for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> Display for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> Eq for Descriptor<Pk> where
    Pk: MiniscriptKey + Eq

impl ExtractPolicy for Descriptor<DescriptorPublicKey>[src]

impl<Pk> FromStr for Descriptor<Pk> where
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

type Err = Error

The associated error which can be returned from parsing.

-

impl<Pk> FromTree for Descriptor<Pk> where
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

fn from_tree(top: &Tree) -> Result<Descriptor<Pk>, Error>

Parse an expression tree into a descriptor

-

impl<Pk> Liftable<Pk> for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> Ord for Descriptor<Pk> where
    Pk: MiniscriptKey + Ord

impl<Pk> PartialEq<Descriptor<Pk>> for Descriptor<Pk> where
    Pk: MiniscriptKey + PartialEq<Pk>, 

impl<Pk> PartialOrd<Descriptor<Pk>> for Descriptor<Pk> where
    Pk: MiniscriptKey + PartialOrd<Pk>, 

impl<Pk> StructuralEq for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> StructuralPartialEq for Descriptor<Pk> where
    Pk: MiniscriptKey

Auto Trait Implementations

impl<Pk> RefUnwindSafe for Descriptor<Pk> where
    Pk: RefUnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe

impl<Pk> Send for Descriptor<Pk> where
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk> Sync for Descriptor<Pk> where
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk> Unpin for Descriptor<Pk> where
    Pk: Unpin,
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk> UnwindSafe for Descriptor<Pk> where
    Pk: RefUnwindSafe + UnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/enum.Legacy.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/enum.Legacy.html deleted file mode 100644 index ab71011372..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/enum.Legacy.html +++ /dev/null @@ -1,32 +0,0 @@ -magical::descriptor::Legacy - Rust

[]Enum magical::descriptor::Legacy

pub enum Legacy {}

Legacy ScriptContext

-

Trait Implementations

impl Clone for Legacy

impl Debug for Legacy

impl Eq for Legacy

impl Ord for Legacy

impl PartialEq<Legacy> for Legacy

impl PartialOrd<Legacy> for Legacy

impl ScriptContext for Legacy

impl StructuralEq for Legacy

impl StructuralPartialEq for Legacy

Auto Trait Implementations

impl RefUnwindSafe for Legacy

impl Send for Legacy

impl Sync for Legacy

impl Unpin for Legacy

impl UnwindSafe for Legacy

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/enum.Segwitv0.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/enum.Segwitv0.html deleted file mode 100644 index 9108962288..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/enum.Segwitv0.html +++ /dev/null @@ -1,32 +0,0 @@ -magical::descriptor::Segwitv0 - Rust

[]Enum magical::descriptor::Segwitv0

pub enum Segwitv0 {}

Segwitv0 ScriptContext

-

Trait Implementations

impl Clone for Segwitv0

impl Debug for Segwitv0

impl Eq for Segwitv0

impl Ord for Segwitv0

impl PartialEq<Segwitv0> for Segwitv0

impl PartialOrd<Segwitv0> for Segwitv0

impl ScriptContext for Segwitv0

impl StructuralEq for Segwitv0

impl StructuralPartialEq for Segwitv0

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/enum.Terminal.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/enum.Terminal.html deleted file mode 100644 index d6ef92b9f4..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/enum.Terminal.html +++ /dev/null @@ -1,128 +0,0 @@ -magical::descriptor::Terminal - Rust

[]Enum magical::descriptor::Terminal

pub enum Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey
{ - True, - False, - PkK(Pk), - PkH(<Pk as MiniscriptKey>::Hash), - After(u32), - Older(u32), - Sha256(Hash), - Hash256(Hash), - Ripemd160(Hash), - Hash160(Hash), - Alt(Arc<Miniscript<Pk, Ctx>>), - Swap(Arc<Miniscript<Pk, Ctx>>), - Check(Arc<Miniscript<Pk, Ctx>>), - DupIf(Arc<Miniscript<Pk, Ctx>>), - Verify(Arc<Miniscript<Pk, Ctx>>), - NonZero(Arc<Miniscript<Pk, Ctx>>), - ZeroNotEqual(Arc<Miniscript<Pk, Ctx>>), - AndV(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - AndB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - AndOr(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - OrB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - OrD(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - OrC(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - OrI(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - Thresh(usizeVec<Arc<Miniscript<Pk, Ctx>>>), - Multi(usizeVec<Pk>), -}

All AST elements

-

- Variants

-
True

1

-
False

0

-
PkK(Pk)

<key>

-
PkH(<Pk as MiniscriptKey>::Hash)

DUP HASH160 <keyhash> EQUALVERIFY

-
After(u32)

n CHECKLOCKTIMEVERIFY

-
Older(u32)

n CHECKSEQUENCEVERIFY

-
Sha256(Hash)

SIZE 32 EQUALVERIFY SHA256 <hash> EQUAL

-
Hash256(Hash)

SIZE 32 EQUALVERIFY HASH256 <hash> EQUAL

-
Ripemd160(Hash)

SIZE 32 EQUALVERIFY RIPEMD160 <hash> EQUAL

-
Hash160(Hash)

SIZE 32 EQUALVERIFY HASH160 <hash> EQUAL

-
Alt(Arc<Miniscript<Pk, Ctx>>)

TOALTSTACK [E] FROMALTSTACK

-
Swap(Arc<Miniscript<Pk, Ctx>>)

SWAP [E1]

-
Check(Arc<Miniscript<Pk, Ctx>>)

[Kt]/[Ke] CHECKSIG

-
DupIf(Arc<Miniscript<Pk, Ctx>>)

DUP IF [V] ENDIF

-
Verify(Arc<Miniscript<Pk, Ctx>>)

[T] VERIFY

-
NonZero(Arc<Miniscript<Pk, Ctx>>)

SIZE 0NOTEQUAL IF Fn ENDIF

-
ZeroNotEqual(Arc<Miniscript<Pk, Ctx>>)

[X] 0NOTEQUAL

-
AndV(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[V] [T]/[V]/[F]/[Kt]

-
AndB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] [W] BOOLAND

-
AndOr(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[various] NOTIF [various] ELSE [various] ENDIF

-
OrB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] [W] BOOLOR

-
OrD(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] IFDUP NOTIF [T]/[E] ENDIF

-
OrC(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] NOTIF [V] ENDIF

-
OrI(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

IF [various] ELSE [various] ENDIF

-
Thresh(usizeVec<Arc<Miniscript<Pk, Ctx>>>)

[E] ([W] ADD)* k EQUAL

-
Multi(usizeVec<Pk>)

k ()* n CHECKMULTISIG

-

Implementations

impl<Pk, Ctx> Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn translate_pk<FPk, FPkh, Q, Error>(
    &self,
    translatefpk: &mut FPk,
    translatefpkh: &mut FPkh
) -> Result<Terminal<Q, Ctx>, Error> where
    FPk: FnMut(&Pk) -> Result<Q, Error>,
    FPkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, Error>,
    Q: MiniscriptKey

Convert an AST element with one public key type to one of another -public key type .This will panic while converting to -Segwit Miniscript using uncompressed public keys

-

impl<Pk, Ctx> Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey + ToPublicKey

pub fn encode(&self, builder: Builder) -> Builder

Encode the element as a fragment of Bitcoin Script. The inverse -function, from Script to an AST element, is implemented in the -parse module.

-

pub fn script_size(&self) -> usize

Size, in bytes of the script-pubkey. If this Miniscript is used outside -of segwit (e.g. in a bare or P2SH descriptor), this quantity should be -multiplied by 4 to compute the weight.

-

In general, it is not recommended to use this function directly, but -to instead call the corresponding function on a Descriptor, which -will handle the segwit/non-segwit technicalities for you.

-

pub fn max_dissatisfaction_witness_elements(&self) -> Option<usize>

Maximum number of witness elements used to dissatisfy the Miniscript -fragment. Used to estimate the weight of the VarInt that specifies -this number in a serialized transaction.

-

Will panic if the fragment is not an E, W or Ke.

-

pub fn max_dissatisfaction_size(&self, one_cost: usize) -> Option<usize>

Maximum dissatisfaction cost, in bytes, of a Miniscript fragment, -if it is possible to compute this. This function should probably -not ever be used directly. It is called from max_satisfaction_size.

-

Will panic if the fragment is not E, W or Ke

-

pub fn max_satisfaction_witness_elements(&self) -> usize

Maximum number of witness elements used to satisfy the Miniscript -fragment. Used to estimate the weight of the VarInt that specifies -this number in a serialized transaction.

-

This number does not include the witness script itself, so 1 needs -to be added to the final result.

-

pub fn max_satisfaction_size(&self, one_cost: usize) -> usize

Maximum size, in bytes, of a satisfying witness. For Segwit outputs -one_cost should be set to 2, since the number 1 requires two -bytes to encode. For non-segwit outputs one_cost should be set to -1, since OP_1 is available in scriptSigs.

-

In general, it is not recommended to use this function directly, but -to instead call the corresponding function on a Descriptor, which -will handle the segwit/non-segwit technicalities for you.

-

All signatures are assumed to be 73 bytes in size, including the -length prefix (segwit) or push opcode (pre-segwit) and sighash -postfix.

-

This function may panic on misformed Miniscript objects which do not -correspond to semantically sane Scripts. (Such scripts should be rejected -at parse time. Any exceptions are bugs.)

-

Trait Implementations

impl<Pk, Ctx> Clone for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Clone,
    Pk: MiniscriptKey + Clone,
    <Pk as MiniscriptKey>::Hash: Clone

impl<Pk, Ctx> Debug for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Display for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Eq for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Eq,
    Pk: MiniscriptKey + Eq,
    <Pk as MiniscriptKey>::Hash: Eq

impl<Pk, Ctx> FromTree for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

impl<Pk, Ctx> Hash for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Hash,
    Pk: MiniscriptKey + Hash,
    <Pk as MiniscriptKey>::Hash: Hash

impl<Pk, Ctx> Liftable<Pk> for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Ord for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Ord,
    Pk: MiniscriptKey + Ord,
    <Pk as MiniscriptKey>::Hash: Ord

impl<Pk, Ctx> PartialEq<Terminal<Pk, Ctx>> for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + PartialEq<Ctx>,
    Pk: MiniscriptKey + PartialEq<Pk>,
    <Pk as MiniscriptKey>::Hash: PartialEq<<Pk as MiniscriptKey>::Hash>, 

impl<Pk, Ctx> PartialOrd<Terminal<Pk, Ctx>> for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + PartialOrd<Ctx>,
    Pk: MiniscriptKey + PartialOrd<Pk>,
    <Pk as MiniscriptKey>::Hash: PartialOrd<<Pk as MiniscriptKey>::Hash>, 

impl<Pk, Ctx> StructuralEq for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> StructuralPartialEq for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Auto Trait Implementations

impl<Pk, Ctx> RefUnwindSafe for Terminal<Pk, Ctx> where
    Ctx: RefUnwindSafe,
    Pk: RefUnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe

impl<Pk, Ctx> Send for Terminal<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk, Ctx> Sync for Terminal<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk, Ctx> Unpin for Terminal<Pk, Ctx> where
    Pk: Unpin,
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk, Ctx> UnwindSafe for Terminal<Pk, Ctx> where
    Ctx: RefUnwindSafe,
    Pk: RefUnwindSafe + UnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/error/enum.Error.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/error/enum.Error.html deleted file mode 100644 index 97c9d10b58..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/error/enum.Error.html +++ /dev/null @@ -1,45 +0,0 @@ -magical::descriptor::error::Error - Rust

[][src]Enum magical::descriptor::error::Error

pub enum Error {
-    InternalError,
-    InvalidPrefix(Vec<u8>),
-    HardenedDerivationOnXpub,
-    MalformedInput,
-    KeyParsingError(String),
-    Policy(PolicyError),
-    InputIndexDoesntExist,
-    MissingPublicKey,
-    MissingDetails,
-    InvalidDescriptorCharacter(char),
-    CantDeriveWithMiniscript,
-    BIP32(Error),
-    Base58(Error),
-    PK(Error),
-    Miniscript(Error),
-    Hex(Error),
-}

Errors related to the parsing and usage of descriptors

-

- Variants

-
InternalError
InvalidPrefix(Vec<u8>)
HardenedDerivationOnXpub
MalformedInput
KeyParsingError(String)
Policy(PolicyError)
InputIndexDoesntExist
MissingPublicKey
MissingDetails
InvalidDescriptorCharacter(char)
CantDeriveWithMiniscript
BIP32(Error)
Base58(Error)
PK(Error)
Miniscript(Error)
Hex(Error)

Trait Implementations

impl Debug for Error[src]

impl Display for Error[src]

impl Error for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<PolicyError> for Error[src]

Auto Trait Implementations

impl RefUnwindSafe for Error

impl Send for Error

impl Sync for Error

impl Unpin for Error

impl UnwindSafe for Error

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/error/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/error/index.html deleted file mode 100644 index 6f6e41ec5c..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/error/index.html +++ /dev/null @@ -1,4 +0,0 @@ -magical::descriptor::error - Rust

[][src]Module magical::descriptor::error

Descriptor errors

-

Enums

-
Error

Errors related to the parsing and usage of descriptors

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/error/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/error/sidebar-items.js deleted file mode 100644 index 1ad99d4faf..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/error/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Error","Errors related to the parsing and usage of descriptors"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/index.html deleted file mode 100644 index a1a05fc9c7..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/index.html +++ /dev/null @@ -1,24 +0,0 @@ -magical::descriptor - Rust

[][src]Module magical::descriptor

Descriptors

-

This module contains generic utilities to work with descriptors, plus some re-exported types -from [miniscript].

-

Re-exports

-
pub use self::checksum::get_checksum;
pub use self::policy::Policy;

Modules

-
checksum

Descriptor checksum

-
error

Descriptor errors

-
policy

Descriptor policy

-

Structs

-
Miniscript

Top-level script AST type

-

Enums

-
Descriptor

Script descriptor

-
Legacy

Legacy ScriptContext

-
Segwitv0

Segwitv0 ScriptContext

-
Terminal

All AST elements

-

Traits

-
ExtractPolicy

Trait implemented on Descriptors to add a method to extract the spending policy

-
MiniscriptKey

Public key trait which can be converted to Hash type

-
ScriptContext
ToPublicKey

Trait describing public key types which can be converted to bitcoin pubkeys

-

Type Definitions

-
ExtendedDescriptor

Alias for a Descriptor that can contain extended keys using [DescriptorPublicKey]

-
HDKeyPaths

Alias for the type of maps that represent derivation paths in a psbt::Input or -psbt::Output

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/enum.PolicyError.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/enum.PolicyError.html deleted file mode 100644 index 12b69b8e98..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/enum.PolicyError.html +++ /dev/null @@ -1,31 +0,0 @@ -magical::descriptor::policy::PolicyError - Rust

[][src]Enum magical::descriptor::policy::PolicyError

pub enum PolicyError {
-    NotEnoughItemsSelected(String),
-    TooManyItemsSelected(String),
-    IndexOutOfRange(usize),
-    AddOnLeaf,
-    AddOnPartialComplete,
-    MixedTimelockUnits,
-    IncompatibleConditions,
-}

Errors that can happen while extracting and manipulating policies

-

- Variants

-
NotEnoughItemsSelected(String)
TooManyItemsSelected(String)
IndexOutOfRange(usize)
AddOnLeaf
AddOnPartialComplete
MixedTimelockUnits
IncompatibleConditions

Trait Implementations

impl Debug for PolicyError[src]

impl Display for PolicyError[src]

impl Error for PolicyError[src]

impl From<PolicyError> for Error[src]

impl From<PolicyError> for Error[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/enum.Satisfaction.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/enum.Satisfaction.html deleted file mode 100644 index af3b9c0330..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/enum.Satisfaction.html +++ /dev/null @@ -1,52 +0,0 @@ -magical::descriptor::policy::Satisfaction - Rust

[][src]Enum magical::descriptor::policy::Satisfaction

pub enum Satisfaction {
-    Partial {
-        n: usize,
-        m: usize,
-        items: Vec<usize>,
-        conditions: ConditionMap,
-    },
-    PartialComplete {
-        n: usize,
-        m: usize,
-        items: Vec<usize>,
-        conditions: FoldedConditionMap,
-    },
-    Complete {
-        condition: Condition,
-    },
-    None,
-}

Represent if and how much a policy item is satisfied by the wallet's descriptor

-

- Variants

-
Partial

Only a partial satisfaction of some kind of threshold policy

-

Fields of Partial

n: usize

Total number of items

-
m: usize

Threshold

-
items: Vec<usize>

The items that can be satisfied by the descriptor

-
conditions: ConditionMap

Extra conditions that also need to be satisfied

-
PartialComplete

Can reach the threshold of some kind of threshold policy

-

Fields of PartialComplete

n: usize

Total number of items

-
m: usize

Threshold

-
items: Vec<usize>

The items that can be satisfied by the descriptor

-
conditions: FoldedConditionMap

Extra conditions that also need to be satisfied

-
Complete

Can satisfy the policy item

-

Fields of Complete

condition: Condition

Extra conditions that also need to be satisfied

-
None

Cannot satisfy or contribute to the policy item

-

Implementations

impl Satisfaction[src]

pub fn is_leaf(&self) -> bool[src]

Trait Implementations

impl Clone for Satisfaction[src]

impl Debug for Satisfaction[src]

impl From<bool> for Satisfaction[src]

impl Serialize for Satisfaction[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/enum.SatisfiableItem.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/enum.SatisfiableItem.html deleted file mode 100644 index faccd39a33..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/enum.SatisfiableItem.html +++ /dev/null @@ -1,51 +0,0 @@ -magical::descriptor::policy::SatisfiableItem - Rust

[][src]Enum magical::descriptor::policy::SatisfiableItem

pub enum SatisfiableItem {
-    Signature(PKOrF),
-    SignatureKey(PKOrF),
-    SHA256Preimage {
-        hash: Hash,
-    },
-    HASH256Preimage {
-        hash: Hash,
-    },
-    RIPEMD160Preimage {
-        hash: Hash,
-    },
-    HASH160Preimage {
-        hash: Hash,
-    },
-    AbsoluteTimelock {
-        value: u32,
-    },
-    RelativeTimelock {
-        value: u32,
-    },
-    Thresh {
-        items: Vec<Policy>,
-        threshold: usize,
-    },
-    Multisig {
-        keys: Vec<PKOrF>,
-        threshold: usize,
-    },
-}

An item that need to be satisfied

-

- Variants

-
Signature(PKOrF)
SignatureKey(PKOrF)
SHA256Preimage

Fields of SHA256Preimage

hash: Hash
HASH256Preimage

Fields of HASH256Preimage

hash: Hash
RIPEMD160Preimage

Fields of RIPEMD160Preimage

hash: Hash
HASH160Preimage

Fields of HASH160Preimage

hash: Hash
AbsoluteTimelock

Fields of AbsoluteTimelock

value: u32
RelativeTimelock

Fields of RelativeTimelock

value: u32
Thresh

Fields of Thresh

items: Vec<Policy>threshold: usize
Multisig

Fields of Multisig

keys: Vec<PKOrF>threshold: usize

Implementations

impl SatisfiableItem[src]

pub fn is_leaf(&self) -> bool[src]

pub fn id(&self) -> String[src]

Trait Implementations

impl Clone for SatisfiableItem[src]

impl Debug for SatisfiableItem[src]

impl From<SatisfiableItem> for Policy[src]

impl Serialize for SatisfiableItem[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/index.html deleted file mode 100644 index 7860ebc778..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/index.html +++ /dev/null @@ -1,23 +0,0 @@ -magical::descriptor::policy - Rust

[][src]Module magical::descriptor::policy

Descriptor policy

-

This module implements the logic to extract and represent the spending policies of a descriptor -in a more human-readable format.

-

Example

-
-let desc = "wsh(and_v(v:pk(cV3oCth6zxZ1UVsHLnGothsWNsaoxRhC6aeNi5VbSdFpwUkgkEci),or_d(pk(cVMTy7uebJgvFaSBwcgvwk8qn8xSLc97dKow4MBetjrrahZoimm2),older(12960))))";
-
-let (extended_desc, key_map) = ExtendedDescriptor::parse_secret(desc)?;
-println!("{:?}", extended_desc);
-
-let signers = Arc::new(key_map.into());
-let policy = extended_desc.extract_policy(signers)?;
-println!("policy: {}", serde_json::to_string(&policy)?);
-

Structs

-
Condition

An extra condition that must be satisfied but that is out of control of the user

-
PKOrF

Raw public key or extended key fingerprint

-
Policy

Descriptor spending policy

-

Enums

-
PolicyError

Errors that can happen while extracting and manipulating policies

-
Satisfaction

Represent if and how much a policy item is satisfied by the wallet's descriptor

-
SatisfiableItem

An item that need to be satisfied

-

Type Definitions

-
ConditionMap
FoldedConditionMap
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/sidebar-items.js deleted file mode 100644 index 6928dca21e..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["PolicyError","Errors that can happen while extracting and manipulating policies"],["Satisfaction","Represent if and how much a policy item is satisfied by the wallet's descriptor"],["SatisfiableItem","An item that need to be satisfied"]],"struct":[["Condition","An extra condition that must be satisfied but that is out of control of the user"],["PKOrF","Raw public key or extended key fingerprint"],["Policy","Descriptor spending policy"]],"type":[["ConditionMap",""],["FoldedConditionMap",""]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/struct.Condition.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/struct.Condition.html deleted file mode 100644 index f021bdf21f..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/struct.Condition.html +++ /dev/null @@ -1,38 +0,0 @@ -magical::descriptor::policy::Condition - Rust

[][src]Struct magical::descriptor::policy::Condition

pub struct Condition {
-    pub csv: Option<u32>,
-    pub timelock: Option<u32>,
-}

An extra condition that must be satisfied but that is out of control of the user

-

- Fields

csv: Option<u32>timelock: Option<u32>

Implementations

impl Condition[src]

pub fn is_null(&self) -> bool[src]

Trait Implementations

impl Clone for Condition[src]

impl Copy for Condition[src]

impl Debug for Condition[src]

impl Default for Condition[src]

impl Eq for Condition[src]

impl Hash for Condition[src]

impl Ord for Condition[src]

impl PartialEq<Condition> for Condition[src]

impl PartialOrd<Condition> for Condition[src]

impl Serialize for Condition[src]

impl StructuralEq for Condition[src]

impl StructuralPartialEq for Condition[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/struct.PKOrF.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/struct.PKOrF.html deleted file mode 100644 index a5498f972d..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/struct.PKOrF.html +++ /dev/null @@ -1,20 +0,0 @@ -magical::descriptor::policy::PKOrF - Rust

[][src]Struct magical::descriptor::policy::PKOrF

pub struct PKOrF { /* fields omitted */ }

Raw public key or extended key fingerprint

-

Trait Implementations

impl Clone for PKOrF[src]

impl Debug for PKOrF[src]

impl Default for PKOrF[src]

impl Serialize for PKOrF[src]

Auto Trait Implementations

impl RefUnwindSafe for PKOrF

impl Send for PKOrF

impl Sync for PKOrF

impl Unpin for PKOrF

impl UnwindSafe for PKOrF

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/struct.Policy.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/struct.Policy.html deleted file mode 100644 index f54bed8664..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/struct.Policy.html +++ /dev/null @@ -1,37 +0,0 @@ -magical::descriptor::policy::Policy - Rust

[][src]Struct magical::descriptor::policy::Policy

pub struct Policy {
-    pub id: String,
-    pub item: SatisfiableItem,
-    pub satisfaction: Satisfaction,
-    pub contribution: Satisfaction,
-}

Descriptor spending policy

-

- Fields

id: String

Identifier for this policy node

-
item: SatisfiableItem

Type of this policy node

-
satisfaction: Satisfaction

How a much given PSBT already satisfies this polcy node (currently unused)

-
contribution: Satisfaction

How the wallet's descriptor can satisfy this policy node

-

Implementations

impl Policy[src]

pub fn requires_path(&self) -> bool[src]

Return whether or not a specific path in the policy tree is required to unambiguously -create a transaction

-

What this means is that for some spending policies the user should select which paths in -the tree it intends to satisfy while signing, because the transaction must be created differently based -on that.

-

pub fn get_condition(
    &self,
    path: &BTreeMap<String, Vec<usize>>
) -> Result<Condition, PolicyError>
[src]

Return the conditions that are set by the spending policy for a given path in the -policy tree

-

Trait Implementations

impl Clone for Policy[src]

impl Debug for Policy[src]

impl From<SatisfiableItem> for Policy[src]

impl Serialize for Policy[src]

Auto Trait Implementations

impl RefUnwindSafe for Policy

impl Send for Policy

impl Sync for Policy

impl Unpin for Policy

impl UnwindSafe for Policy

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/type.ConditionMap.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/type.ConditionMap.html deleted file mode 100644 index f6cbf94081..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/type.ConditionMap.html +++ /dev/null @@ -1 +0,0 @@ -magical::descriptor::policy::ConditionMap - Rust

[][src]Type Definition magical::descriptor::policy::ConditionMap

type ConditionMap = BTreeMap<usize, HashSet<Condition>>;
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/type.FoldedConditionMap.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/type.FoldedConditionMap.html deleted file mode 100644 index 34cec054b7..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/policy/type.FoldedConditionMap.html +++ /dev/null @@ -1 +0,0 @@ -magical::descriptor::policy::FoldedConditionMap - Rust

[][src]Type Definition magical::descriptor::policy::FoldedConditionMap

type FoldedConditionMap = BTreeMap<Vec<usize>, HashSet<Condition>>;
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/sidebar-items.js deleted file mode 100644 index 8460b2d5c8..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Descriptor","Script descriptor"],["Legacy","Legacy ScriptContext"],["Segwitv0","Segwitv0 ScriptContext"],["Terminal","All AST elements"]],"mod":[["checksum","Descriptor checksum"],["error","Descriptor errors"],["policy","Descriptor policy"]],"struct":[["Miniscript","Top-level script AST type"]],"trait":[["ExtractPolicy","Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]"],["MiniscriptKey","Public key trait which can be converted to Hash type"],["ScriptContext",""],["ToPublicKey","Trait describing public key types which can be converted to bitcoin pubkeys"]],"type":[["ExtendedDescriptor","Alias for a [`Descriptor`] that can contain extended keys using [`DescriptorPublicKey`]"],["HDKeyPaths","Alias for the type of maps that represent derivation paths in a [`psbt::Input`] or [`psbt::Output`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/struct.Miniscript.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/struct.Miniscript.html deleted file mode 100644 index 490d975dfe..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/struct.Miniscript.html +++ /dev/null @@ -1,97 +0,0 @@ -magical::descriptor::Miniscript - Rust

[]Struct magical::descriptor::Miniscript

pub struct Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey
{ - pub node: Terminal<Pk, Ctx>, - pub ty: Type, - pub ext: ExtData, - // some fields omitted -}

Top-level script AST type

-

- Fields

node: Terminal<Pk, Ctx>

A node in the Abstract Syntax Tree(

-
ty: Type

The correctness and malleability type information for the AST node

-
ext: ExtData

Additional information helpful for extra analysis.

-

Implementations

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn from_ast(t: Terminal<Pk, Ctx>) -> Result<Miniscript<Pk, Ctx>, Error>

Add type information(Type and Extdata) to Miniscript based on -AstElem fragment. Dependent on display and clone because of Error -Display code of type_check.

-

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn into_inner(self) -> Terminal<Pk, Ctx>

Extracts the AstElem representing the root of the miniscript

-

pub fn as_inner(&self) -> &Terminal<Pk, Ctx>

impl<Ctx> Miniscript<PublicKey, Ctx> where
    Ctx: ScriptContext

pub fn parse(script: &Script) -> Result<Miniscript<PublicKey, Ctx>, Error>

Attempt to parse a script into a Miniscript representation

-

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey + ToPublicKey

pub fn encode(&self) -> Script

Encode as a Bitcoin script

-

pub fn script_size(&self) -> usize

Size, in bytes of the script-pubkey. If this Miniscript is used outside -of segwit (e.g. in a bare or P2SH descriptor), this quantity should be -multiplied by 4 to compute the weight.

-

In general, it is not recommended to use this function directly, but -to instead call the corresponding function on a Descriptor, which -will handle the segwit/non-segwit technicalities for you.

-

pub fn max_satisfaction_witness_elements(&self) -> usize

Maximum number of witness elements used to satisfy the Miniscript -fragment, including the witness script itself. Used to estimate -the weight of the VarInt that specifies this number in a serialized -transaction.

-

This function may panic on misformed Miniscript objects which do -not correspond to semantically sane Scripts. (Such scripts should be -rejected at parse time. Any exceptions are bugs.)

-

pub fn max_satisfaction_size(&self, one_cost: usize) -> usize

Maximum size, in bytes, of a satisfying witness. For Segwit outputs -one_cost should be set to 2, since the number 1 requires two -bytes to encode. For non-segwit outputs one_cost should be set to -1, since OP_1 is available in scriptSigs.

-

In general, it is not recommended to use this function directly, but -to instead call the corresponding function on a Descriptor, which -will handle the segwit/non-segwit technicalities for you.

-

All signatures are assumed to be 73 bytes in size, including the -length prefix (segwit) or push opcode (pre-segwit) and sighash -postfix.

-

This function may panic on misformed Miniscript objects which do not -correspond to semantically sane Scripts. (Such scripts should be -rejected at parse time. Any exceptions are bugs.)

-

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn translate_pk<FPk, FPkh, Q, FuncError>(
    &self,
    translatefpk: &mut FPk,
    translatefpkh: &mut FPkh
) -> Result<Miniscript<Q, Ctx>, FuncError> where
    FPk: FnMut(&Pk) -> Result<Q, FuncError>,
    FPkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, FuncError>,
    Q: MiniscriptKey

This will panic if translatefpk returns an uncompressed key when -converting to a Segwit descriptor. To prevent this panic, ensure -translatefpk returns an error in this case instead.

-

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey + ToPublicKey

pub fn satisfy<S>(&self, satisfier: S) -> Option<Vec<Vec<u8>>> where
    S: Satisfier<Pk>, 

Attempt to produce a satisfying witness for the -witness script represented by the parse tree

-

Trait Implementations

impl<Pk, Ctx> Clone for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext + Clone,
    Pk: MiniscriptKey + Clone

impl<Pk, Ctx> Debug for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Display for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Eq for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Eq of Miniscript must depend only on node and not the type information. -The type information and extra_properties can be deterministically determined -by the ast.

-

impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>[src]

impl<Pk, Ctx> FromStr for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

type Err = Error

The associated error which can be returned from parsing.

-

impl<Pk, Ctx> FromTree for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

fn from_tree(top: &Tree) -> Result<Miniscript<Pk, Ctx>, Error>

Parse an expression tree into a Miniscript. As a general rule, this -should not be called directly; rather go through the descriptor API.

-

impl<Pk, Ctx> Hash for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext + Hash,
    Pk: MiniscriptKey + Hash

impl<Pk, Ctx> Liftable<Pk> for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Ord for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Ord of Miniscript must depend only on node and not the type information. -The type information and extra_properties can be deterministically determined -by the ast.

-

impl<Pk, Ctx> PartialEq<Miniscript<Pk, Ctx>> for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

PartialEq of Miniscript must depend only on node and not the type information. -The type information and extra_properties can be deterministically determined -by the ast.

-

impl<Pk, Ctx> PartialOrd<Miniscript<Pk, Ctx>> for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

PartialOrd of Miniscript must depend only on node and not the type information. -The type information and extra_properties can be deterministically determined -by the ast.

-

Auto Trait Implementations

impl<Pk, Ctx> RefUnwindSafe for Miniscript<Pk, Ctx> where
    Ctx: RefUnwindSafe,
    Pk: RefUnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe

impl<Pk, Ctx> Send for Miniscript<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk, Ctx> Sync for Miniscript<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk, Ctx> Unpin for Miniscript<Pk, Ctx> where
    Ctx: Unpin,
    Pk: Unpin,
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk, Ctx> UnwindSafe for Miniscript<Pk, Ctx> where
    Ctx: RefUnwindSafe + UnwindSafe,
    Pk: RefUnwindSafe + UnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/trait.ExtractPolicy.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/trait.ExtractPolicy.html deleted file mode 100644 index 226892196c..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/trait.ExtractPolicy.html +++ /dev/null @@ -1,6 +0,0 @@ -magical::descriptor::ExtractPolicy - Rust

[][src]Trait magical::descriptor::ExtractPolicy

pub trait ExtractPolicy {
-    fn extract_policy(
        &self,
        signers: Arc<SignersContainer<DescriptorPublicKey>>
    ) -> Result<Option<Policy>, Error>; -}

Trait implemented on Descriptors to add a method to extract the spending policy

-
-

Required methods

fn extract_policy(
    &self,
    signers: Arc<SignersContainer<DescriptorPublicKey>>
) -> Result<Option<Policy>, Error>

Loading content... -

Implementors

impl ExtractPolicy for Descriptor<DescriptorPublicKey>[src]

impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>[src]

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/trait.MiniscriptKey.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/trait.MiniscriptKey.html deleted file mode 100644 index a7106566b0..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/trait.MiniscriptKey.html +++ /dev/null @@ -1,18 +0,0 @@ -magical::descriptor::MiniscriptKey - Rust

[]Trait magical::descriptor::MiniscriptKey

pub trait MiniscriptKey: Clone + Eq + Ord + Debug + Display + Hash + FromStr {
-    type Hash: Clone + Eq + Ord + Debug + Display + Hash + FromStr;
-    fn to_pubkeyhash(&self) -> Self::Hash;
-
-    fn is_uncompressed(&self) -> bool { ... }
-}

Public key trait which can be converted to Hash type

-
-

Associated Types

type Hash: Clone + Eq + Ord + Debug + Display + Hash + FromStr

The associated Hash type with the publicKey

-
Loading content... -

Required methods

fn to_pubkeyhash(&self) -> Self::Hash

Converts an object to PublicHash

-
Loading content... -

Provided methods

fn is_uncompressed(&self) -> bool

Check if the publicKey is uncompressed. The default -implementation returns false

-
Loading content... -

Implementations on Foreign Types

impl MiniscriptKey for PublicKey

fn is_uncompressed(&self) -> bool

is_uncompressed returns true only for -bitcoin::Publickey type if the underlying key is uncompressed.

-

type Hash = Hash

impl MiniscriptKey for DummyKey

type Hash = DummyKeyHash

impl MiniscriptKey for DescriptorPublicKey

type Hash = Hash

impl MiniscriptKey for String

Loading content... -

Implementors

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/trait.ScriptContext.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/trait.ScriptContext.html deleted file mode 100644 index a09697ab00..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/trait.ScriptContext.html +++ /dev/null @@ -1,19 +0,0 @@ -magical::descriptor::ScriptContext - Rust

[]Trait magical::descriptor::ScriptContext

pub trait ScriptContext: Sealed + Clone + PartialEq<Self> + Eq + Ord + PartialOrd<Self> + Debug {
-    fn check_frag_non_malleable<Pk, Ctx>(
        _frag: &Terminal<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
; -
fn check_frag_validity<Pk, Ctx>(
        _frag: &Terminal<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
; -}
-

Required methods

fn check_frag_non_malleable<Pk, Ctx>(
    _frag: &Terminal<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Depending on ScriptContext, fragments can be malleable. For Example, -under Legacy context, PkH is malleable because it is possible to -estimate the cost of satisfaction because of compressed keys -This is currently only used in compiler code for removing malleable -compilations. -This does NOT recursively check if the children of the fragment are -valid or not. Since the compilation proceeds in a leaf to root fashion, -a recursive check is unnecessary.

-

fn check_frag_validity<Pk, Ctx>(
    _frag: &Terminal<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Depending on script Context, some of the Terminals might not be valid. -For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey -uncompressed public keys are non-standard and thus invalid. -Post Tapscript upgrade, this would have to consider other nodes. -This does not recursively check

-
Loading content... -

Implementors

impl ScriptContext for Legacy

impl ScriptContext for Segwitv0

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/trait.ToPublicKey.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/trait.ToPublicKey.html deleted file mode 100644 index eeecfcc5e3..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/trait.ToPublicKey.html +++ /dev/null @@ -1,19 +0,0 @@ -magical::descriptor::ToPublicKey - Rust

[]Trait magical::descriptor::ToPublicKey

pub trait ToPublicKey: MiniscriptKey {
-    fn to_public_key(&self) -> PublicKey;
-
fn hash_to_hash160(hash: &Self::Hash) -> Hash; - - fn serialized_len(&self) -> usize { ... } -}

Trait describing public key types which can be converted to bitcoin pubkeys

-
-

Required methods

fn to_public_key(&self) -> PublicKey

Converts an object to a public key

-

fn hash_to_hash160(hash: &Self::Hash) -> Hash

Converts a hashed version of the public key to a hash160 hash.

-

This method must be consistent with to_public_key, in the sense -that calling MiniscriptKey::to_pubkeyhash followed by this function -should give the same result as calling to_public_key and hashing -the result directly.

-
Loading content... -

Provided methods

fn serialized_len(&self) -> usize

Computes the size of a public key when serialized in a script, -including the length bytes

-
Loading content... -

Implementations on Foreign Types

impl ToPublicKey for DummyKey

impl ToPublicKey for DescriptorPublicKey

impl ToPublicKey for PublicKey

Loading content... -

Implementors

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/type.ExtendedDescriptor.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/type.ExtendedDescriptor.html deleted file mode 100644 index c07cb642df..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/type.ExtendedDescriptor.html +++ /dev/null @@ -1,2 +0,0 @@ -magical::descriptor::ExtendedDescriptor - Rust

[][src]Type Definition magical::descriptor::ExtendedDescriptor

type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;

Alias for a Descriptor that can contain extended keys using [DescriptorPublicKey]

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/type.HDKeyPaths.html b/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/type.HDKeyPaths.html deleted file mode 100644 index 967ee0b076..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/descriptor/type.HDKeyPaths.html +++ /dev/null @@ -1,3 +0,0 @@ -magical::descriptor::HDKeyPaths - Rust

[][src]Type Definition magical::descriptor::HDKeyPaths

type HDKeyPaths = BTreeMap<PublicKey, (Fingerprint, DerivationPath)>;

Alias for the type of maps that represent derivation paths in a psbt::Input or -psbt::Output

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/enum.Error.html b/static/docs-rs/magical/0.1.0-beta.1/magical/enum.Error.html deleted file mode 100644 index 0d32d511ca..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/enum.Error.html +++ /dev/null @@ -1,80 +0,0 @@ -magical::Error - Rust

[][src]Enum magical::Error

pub enum Error {
-    KeyMismatch(PublicKey, PublicKey),
-    MissingInputUTXO(usize),
-    InvalidU32Bytes(Vec<u8>),
-    Generic(String),
-    ScriptDoesntHaveAddressForm,
-    SendAllMultipleOutputs,
-    NoAddressees,
-    OutputBelowDustLimit(usize),
-    InsufficientFunds,
-    InvalidAddressNetwork(Address),
-    UnknownUTXO,
-    DifferentTransactions,
-    TransactionNotFound,
-    TransactionConfirmed,
-    IrreplaceableTransaction,
-    FeeRateTooLow {
-        required: FeeRate,
-    },
-    ChecksumMismatch,
-    DifferentDescriptorStructure,
-    SpendingPolicyRequired,
-    InvalidPolicyPathError(PolicyError),
-    Signer(SignerError),
-    Uncapable(Capability),
-    OfflineClient,
-    InvalidProgressValue(f32),
-    ProgressUpdateError,
-    MissingCachedAddresses,
-    InvalidOutpoint(OutPoint),
-    Descriptor(Error),
-    AddressValidator(AddressValidatorError),
-    Encode(Error),
-    Miniscript(Error),
-    BIP32(Error),
-    Secp256k1(Error),
-    JSON(Error),
-    Hex(Error),
-    PSBT(Error),
-    Electrum(Error),
-    Esplora(EsploraError),
-    CompactFilters(CompactFiltersError),
-    Sled(Error),
-}

Errors that can be thrown by the Wallet

-

- Variants

-
KeyMismatch(PublicKey, PublicKey)
MissingInputUTXO(usize)
InvalidU32Bytes(Vec<u8>)
Generic(String)
ScriptDoesntHaveAddressForm
SendAllMultipleOutputs
NoAddressees
OutputBelowDustLimit(usize)
InsufficientFunds
InvalidAddressNetwork(Address)
UnknownUTXO
DifferentTransactions
TransactionNotFound
TransactionConfirmed
IrreplaceableTransaction
FeeRateTooLow

Fields of FeeRateTooLow

required: FeeRate
ChecksumMismatch
DifferentDescriptorStructure
SpendingPolicyRequired
InvalidPolicyPathError(PolicyError)
Signer(SignerError)
Uncapable(Capability)
OfflineClient
InvalidProgressValue(f32)
ProgressUpdateError
MissingCachedAddresses
InvalidOutpoint(OutPoint)
Descriptor(Error)
AddressValidator(AddressValidatorError)
Encode(Error)
Miniscript(Error)
BIP32(Error)
Secp256k1(Error)
JSON(Error)
Hex(Error)
PSBT(Error)
Electrum(Error)
Esplora(EsploraError)
CompactFilters(CompactFiltersError)
Sled(Error)

Trait Implementations

impl Debug for Error[src]

impl Display for Error[src]

impl Error for Error[src]

impl From<AddressValidatorError> for Error[src]

impl From<CompactFiltersError> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<EsploraError> for Error[src]

impl From<PolicyError> for Error[src]

impl From<SignerError> for Error[src]

Auto Trait Implementations

impl !RefUnwindSafe for Error

impl Send for Error

impl Sync for Error

impl Unpin for Error

impl !UnwindSafe for Error

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/enum.ScriptType.html b/static/docs-rs/magical/0.1.0-beta.1/magical/enum.ScriptType.html deleted file mode 100644 index d7bb1aecb2..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/enum.ScriptType.html +++ /dev/null @@ -1,36 +0,0 @@ -magical::ScriptType - Rust

[][src]Enum magical::ScriptType

pub enum ScriptType {
-    External,
-    Internal,
-}

Types of script

-

- Variants

-
External
Internal

Implementations

impl ScriptType[src]

pub fn as_byte(&self) -> u8[src]

pub fn is_internal(&self) -> bool[src]

Trait Implementations

impl AsRef<[u8]> for ScriptType[src]

impl Clone for ScriptType[src]

impl Copy for ScriptType[src]

impl Debug for ScriptType[src]

impl<'de> Deserialize<'de> for ScriptType[src]

impl Eq for ScriptType[src]

impl Hash for ScriptType[src]

impl PartialEq<ScriptType> for ScriptType[src]

impl Serialize for ScriptType[src]

impl StructuralEq for ScriptType[src]

impl StructuralPartialEq for ScriptType[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Base32Len for T where
    T: AsRef<[u8]>, 

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<'f, T> CheckBase32<Vec<u5>> for T where
    T: AsRef<[u8]>, 

type Err = Error

Error type if conversion fails

-

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToBase32 for T where
    T: AsRef<[u8]>, 

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/error/enum.Error.html b/static/docs-rs/magical/0.1.0-beta.1/magical/error/enum.Error.html deleted file mode 100644 index cae24e162f..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/error/enum.Error.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

Redirecting to ../../magical/enum.Error.html...

- - - \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/index.html deleted file mode 100644 index d4037ece5b..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/index.html +++ /dev/null @@ -1,14 +0,0 @@ -magical - Rust

[][src]Crate magical

Re-exports

-
pub extern crate bitcoin;
pub extern crate miniscript;
pub extern crate electrum_client;
pub extern crate reqwest;
pub extern crate sled;
pub use descriptor::HDKeyPaths;
pub use wallet::address_validator;
pub use wallet::signer;
pub use wallet::tx_builder::TxBuilder;
pub use wallet::OfflineWallet;
pub use wallet::Wallet;

Modules

-
blockchain

Blockchain backends

-
database

Database types

-
descriptor

Descriptors

-
wallet

Wallet

-

Structs

-
FeeRate

Fee rate

-
TransactionDetails

A wallet transaction

-
UTXO

A wallet unspent output

-

Enums

-
Error

Errors that can be thrown by the Wallet

-
ScriptType

Types of script

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/sidebar-items.js deleted file mode 100644 index 9e94a707e4..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Error","Errors that can be thrown by the `Wallet`"],["ScriptType","Types of script"]],"mod":[["blockchain","Blockchain backends"],["database","Database types"],["descriptor","Descriptors"],["wallet","Wallet"]],"struct":[["FeeRate","Fee rate"],["TransactionDetails","A wallet transaction"],["UTXO","A wallet unspent output"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/struct.FeeRate.html b/static/docs-rs/magical/0.1.0-beta.1/magical/struct.FeeRate.html deleted file mode 100644 index 615c2d6104..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/struct.FeeRate.html +++ /dev/null @@ -1,30 +0,0 @@ -magical::FeeRate - Rust

[][src]Struct magical::FeeRate

pub struct FeeRate(_);

Fee rate

-

Implementations

impl FeeRate[src]

pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self[src]

Create a new instance of FeeRate given a float fee rate in btc/kvbytes

-

pub fn from_sat_per_vb(sat_per_vb: f32) -> Self[src]

Create a new instance of FeeRate given a float fee rate in satoshi/vbyte

-

pub fn default_min_relay_fee() -> Self[src]

Create a new FeeRate with the default min relay fee value

-

pub fn as_sat_vb(&self) -> f32[src]

Return the value as satoshi/vbyte

-

Trait Implementations

impl Clone for FeeRate[src]

impl Copy for FeeRate[src]

impl Debug for FeeRate[src]

impl Default for FeeRate[src]

impl PartialEq<FeeRate> for FeeRate[src]

impl PartialOrd<FeeRate> for FeeRate[src]

impl StructuralPartialEq for FeeRate[src]

Auto Trait Implementations

impl RefUnwindSafe for FeeRate

impl Send for FeeRate

impl Sync for FeeRate

impl Unpin for FeeRate

impl UnwindSafe for FeeRate

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/struct.TransactionDetails.html b/static/docs-rs/magical/0.1.0-beta.1/magical/struct.TransactionDetails.html deleted file mode 100644 index ae8b2dad72..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/struct.TransactionDetails.html +++ /dev/null @@ -1,33 +0,0 @@ -magical::TransactionDetails - Rust

[][src]Struct magical::TransactionDetails

pub struct TransactionDetails {
-    pub transaction: Option<Transaction>,
-    pub txid: Txid,
-    pub timestamp: u64,
-    pub received: u64,
-    pub sent: u64,
-    pub fees: u64,
-    pub height: Option<u32>,
-}

A wallet transaction

-

- Fields

transaction: Option<Transaction>txid: Txidtimestamp: u64received: u64sent: u64fees: u64height: Option<u32>

Trait Implementations

impl Clone for TransactionDetails[src]

impl Debug for TransactionDetails[src]

impl Default for TransactionDetails[src]

impl<'de> Deserialize<'de> for TransactionDetails[src]

impl Eq for TransactionDetails[src]

impl PartialEq<TransactionDetails> for TransactionDetails[src]

impl Serialize for TransactionDetails[src]

impl StructuralEq for TransactionDetails[src]

impl StructuralPartialEq for TransactionDetails[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/struct.UTXO.html b/static/docs-rs/magical/0.1.0-beta.1/magical/struct.UTXO.html deleted file mode 100644 index e98d7da0ae..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/struct.UTXO.html +++ /dev/null @@ -1,28 +0,0 @@ -magical::UTXO - Rust

[][src]Struct magical::UTXO

pub struct UTXO {
-    pub outpoint: OutPoint,
-    pub txout: TxOut,
-    pub is_internal: bool,
-}

A wallet unspent output

-

- Fields

outpoint: OutPointtxout: TxOutis_internal: bool

Trait Implementations

impl Clone for UTXO[src]

impl Debug for UTXO[src]

impl<'de> Deserialize<'de> for UTXO[src]

impl Eq for UTXO[src]

impl PartialEq<UTXO> for UTXO[src]

impl Serialize for UTXO[src]

impl StructuralEq for UTXO[src]

impl StructuralPartialEq for UTXO[src]

Auto Trait Implementations

impl RefUnwindSafe for UTXO

impl Send for UTXO

impl Sync for UTXO

impl Unpin for UTXO

impl UnwindSafe for UTXO

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/types/enum.ScriptType.html b/static/docs-rs/magical/0.1.0-beta.1/magical/types/enum.ScriptType.html deleted file mode 100644 index d52af2e3e8..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/types/enum.ScriptType.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

Redirecting to ../../magical/enum.ScriptType.html...

- - - \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/types/struct.FeeRate.html b/static/docs-rs/magical/0.1.0-beta.1/magical/types/struct.FeeRate.html deleted file mode 100644 index ef730fbb6d..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/types/struct.FeeRate.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

Redirecting to ../../magical/struct.FeeRate.html...

- - - \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/types/struct.TransactionDetails.html b/static/docs-rs/magical/0.1.0-beta.1/magical/types/struct.TransactionDetails.html deleted file mode 100644 index e2749d225f..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/types/struct.TransactionDetails.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

Redirecting to ../../magical/struct.TransactionDetails.html...

- - - \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/types/struct.UTXO.html b/static/docs-rs/magical/0.1.0-beta.1/magical/types/struct.UTXO.html deleted file mode 100644 index 4394daf8e0..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/types/struct.UTXO.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

Redirecting to ../../magical/struct.UTXO.html...

- - - \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/address_validator/enum.AddressValidatorError.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/address_validator/enum.AddressValidatorError.html deleted file mode 100644 index 706463f315..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/address_validator/enum.AddressValidatorError.html +++ /dev/null @@ -1,37 +0,0 @@ -magical::wallet::address_validator::AddressValidatorError - Rust

[][src]Enum magical::wallet::address_validator::AddressValidatorError

pub enum AddressValidatorError {
-    UserRejected,
-    ConnectionError,
-    TimeoutError,
-    InvalidScript,
-    Message(String),
-}

Errors that can be returned to fail the validation of an address

-

- Variants

-
UserRejected
ConnectionError
TimeoutError
InvalidScript
Message(String)

Trait Implementations

impl Clone for AddressValidatorError[src]

impl Debug for AddressValidatorError[src]

impl Display for AddressValidatorError[src]

impl Eq for AddressValidatorError[src]

impl Error for AddressValidatorError[src]

impl From<AddressValidatorError> for Error[src]

impl PartialEq<AddressValidatorError> for AddressValidatorError[src]

impl StructuralEq for AddressValidatorError[src]

impl StructuralPartialEq for AddressValidatorError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/address_validator/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/address_validator/index.html deleted file mode 100644 index 9f1605c409..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/address_validator/index.html +++ /dev/null @@ -1,44 +0,0 @@ -magical::wallet::address_validator - Rust

[][src]Module magical::wallet::address_validator

Address validation callbacks

-

The typical usage of those callbacks is for displaying the newly-generated address on a -hardware wallet, so that the user can cross-check its correctness.

-

More generally speaking though, these callbacks can also be used to "do something" every time -an address is generated, without necessarily checking or validating it.

-

An address validator can be attached to a Wallet by using the -Wallet::add_address_validator method, and -whenever a new address is generated (either explicitly by the user with -Wallet::get_new_address or internally to create a change -address) all the attached validators will be polled, in sequence. All of them must complete -successfully to continue.

-

Example

-
-struct PrintAddressAndContinue;
-
-impl AddressValidator for PrintAddressAndContinue {
-    fn validate(
-        &self,
-        script_type: ScriptType,
-        hd_keypaths: &HDKeyPaths,
-        script: &Script
-    ) -> Result<(), AddressValidatorError> {
-        let address = Address::from_script(script, Network::Testnet)
-            .as_ref()
-            .map(Address::to_string)
-            .unwrap_or(script.to_string());
-        println!("New address of type {:?}: {}", script_type, address);
-        println!("HD keypaths: {:#?}", hd_keypaths);
-
-        Ok(())
-    }
-}
-
-let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
-wallet.add_address_validator(Arc::new(Box::new(PrintAddressAndContinue)));
-
-let address = wallet.get_new_address()?;
-println!("Address: {}", address);
-

Enums

-
AddressValidatorError

Errors that can be returned to fail the validation of an address

-

Traits

-
AddressValidator

Trait to build address validators

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/address_validator/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/address_validator/sidebar-items.js deleted file mode 100644 index 58959ba340..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/address_validator/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["AddressValidatorError","Errors that can be returned to fail the validation of an address"]],"trait":[["AddressValidator","Trait to build address validators"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/address_validator/trait.AddressValidator.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/address_validator/trait.AddressValidator.html deleted file mode 100644 index bb8d12b193..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/address_validator/trait.AddressValidator.html +++ /dev/null @@ -1,11 +0,0 @@ -magical::wallet::address_validator::AddressValidator - Rust

[][src]Trait magical::wallet::address_validator::AddressValidator

pub trait AddressValidator {
-    fn validate(
        &self,
        script_type: ScriptType,
        hd_keypaths: &HDKeyPaths,
        script: &Script
    ) -> Result<(), AddressValidatorError>; -}

Trait to build address validators

-

All the address validators attached to a wallet with Wallet::add_address_validator will be polled -every time an address (external or internal) is generated by the wallet. Errors returned in the -validator will be propagated up to the original caller that triggered the address generation.

-

For a usage example see this module's documentation.

-
-

Required methods

fn validate(
    &self,
    script_type: ScriptType,
    hd_keypaths: &HDKeyPaths,
    script: &Script
) -> Result<(), AddressValidatorError>

Validate or inspect an address

-
Loading content... -

Implementors

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/index.html deleted file mode 100644 index 526f58e3fd..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/index.html +++ /dev/null @@ -1,73 +0,0 @@ -magical::wallet::coin_selection - Rust

[][src]Module magical::wallet::coin_selection

Coin selection

-

This module provides the trait CoinSelectionAlgorithm that can be implemented to -define custom coin selection algorithms.

-

The coin selection algorithm is not globally part of a Wallet, instead it -is selected whenever a Wallet::create_tx call is made, through -the use of the TxBuilder structure, specifically with -TxBuilder::coin_selection method.

-

The DefaultCoinSelectionAlgorithm selects the default coin selection algorithm that -TxBuilder uses, if it's not explicitly overridden.

-

Example

-
-#[derive(Debug)]
-struct AlwaysSpendEverything;
-
-impl CoinSelectionAlgorithm for AlwaysSpendEverything {
-    fn coin_select(
-        &self,
-        utxos: Vec<UTXO>,
-        _use_all_utxos: bool,
-        fee_rate: FeeRate,
-        amount_needed: u64,
-        input_witness_weight: usize,
-        fee_amount: f32,
-    ) -> Result<CoinSelectionResult, magical::Error> {
-        let selected_amount = utxos.iter().fold(0, |acc, utxo| acc + utxo.txout.value);
-        let all_utxos_selected = utxos
-            .into_iter()
-            .map(|utxo| {
-                (
-                    TxIn {
-                        previous_output: utxo.outpoint,
-                        ..Default::default()
-                    },
-                    utxo.txout.script_pubkey,
-                )
-            })
-            .collect::<Vec<_>>();
-        let additional_weight = all_utxos_selected.iter().fold(0, |acc, (txin, _)| {
-            acc + serialize(txin).len() * 4 + input_witness_weight
-        });
-        let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
-
-        if (fee_amount + additional_fees).ceil() as u64 + amount_needed > selected_amount {
-            return Err(magical::Error::InsufficientFunds);
-        }
-
-        Ok(CoinSelectionResult {
-            txin: all_utxos_selected,
-            selected_amount,
-            fee_amount: fee_amount + additional_fees,
-        })
-    }
-}
-
-// create wallet, sync, ...
-
-let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
-let (psbt, details) = wallet.create_tx(
-    TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
-        .coin_selection(AlwaysSpendEverything),
-)?;
-
-// inspect, sign, broadcast, ...
-
-

Structs

-
CoinSelectionResult

Result of a successful coin selection

-
DumbCoinSelection

Simple and dumb coin selection

-

Traits

-
CoinSelectionAlgorithm

Trait for generalized coin selection algorithms

-

Type Definitions

-
DefaultCoinSelectionAlgorithm

Default coin selection algorithm used by TxBuilder if not -overridden

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/sidebar-items.js deleted file mode 100644 index d124fee721..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["CoinSelectionResult","Result of a successful coin selection"],["DumbCoinSelection","Simple and dumb coin selection"]],"trait":[["CoinSelectionAlgorithm","Trait for generalized coin selection algorithms"]],"type":[["DefaultCoinSelectionAlgorithm","Default coin selection algorithm used by `TxBuilder` if not overridden"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/struct.CoinSelectionResult.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/struct.CoinSelectionResult.html deleted file mode 100644 index 376302e388..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/struct.CoinSelectionResult.html +++ /dev/null @@ -1,20 +0,0 @@ -magical::wallet::coin_selection::CoinSelectionResult - Rust

[][src]Struct magical::wallet::coin_selection::CoinSelectionResult

pub struct CoinSelectionResult {
-    pub txin: Vec<(TxIn, Script)>,
-    pub selected_amount: u64,
-    pub fee_amount: f32,
-}

Result of a successful coin selection

-

- Fields

txin: Vec<(TxIn, Script)>

List of inputs to use, with the respective previous script_pubkey

-
selected_amount: u64

Sum of the selected inputs' value

-
fee_amount: f32

Total fee amount in satoshi

-

Trait Implementations

impl Debug for CoinSelectionResult[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/struct.DumbCoinSelection.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/struct.DumbCoinSelection.html deleted file mode 100644 index 0abdf3b021..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/struct.DumbCoinSelection.html +++ /dev/null @@ -1,16 +0,0 @@ -magical::wallet::coin_selection::DumbCoinSelection - Rust

[][src]Struct magical::wallet::coin_selection::DumbCoinSelection

pub struct DumbCoinSelection;

Simple and dumb coin selection

-

This coin selection algorithm sorts the available UTXOs by value and then picks them starting -from the largest ones until the required amount is reached.

-

Trait Implementations

impl CoinSelectionAlgorithm for DumbCoinSelection[src]

impl Debug for DumbCoinSelection[src]

impl Default for DumbCoinSelection[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/trait.CoinSelectionAlgorithm.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/trait.CoinSelectionAlgorithm.html deleted file mode 100644 index bd5a635402..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/trait.CoinSelectionAlgorithm.html +++ /dev/null @@ -1,18 +0,0 @@ -magical::wallet::coin_selection::CoinSelectionAlgorithm - Rust

[][src]Trait magical::wallet::coin_selection::CoinSelectionAlgorithm

pub trait CoinSelectionAlgorithm: Debug {
-    fn coin_select(
        &self,
        utxos: Vec<UTXO>,
        use_all_utxos: bool,
        fee_rate: FeeRate,
        amount_needed: u64,
        input_witness_weight: usize,
        fee_amount: f32
    ) -> Result<CoinSelectionResult, Error>; -}

Trait for generalized coin selection algorithms

-

This trait can be implemented to make the Wallet use a customized coin -selection algorithm when it creates transactions.

-

For an example see this module's documentation.

-
-

Required methods

fn coin_select(
    &self,
    utxos: Vec<UTXO>,
    use_all_utxos: bool,
    fee_rate: FeeRate,
    amount_needed: u64,
    input_witness_weight: usize,
    fee_amount: f32
) -> Result<CoinSelectionResult, Error>

Perform the coin selection

-
    -
  • utxos: the list of spendable UTXOs
  • -
  • use_all_utxos: if true all utxos should be spent unconditionally
  • -
  • fee_rate: fee rate to use
  • -
  • amount_needed: the amount in satoshi to select
  • -
  • input_witness_weight: the weight of an input's witness to keep into account for the fees
  • -
  • fee_amount: the amount of fees in satoshi already accumulated from adding outputs
  • -
-
Loading content... -

Implementors

impl CoinSelectionAlgorithm for DumbCoinSelection[src]

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html deleted file mode 100644 index e93bddea36..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html +++ /dev/null @@ -1,3 +0,0 @@ -magical::wallet::coin_selection::DefaultCoinSelectionAlgorithm - Rust

[][src]Type Definition magical::wallet::coin_selection::DefaultCoinSelectionAlgorithm

type DefaultCoinSelectionAlgorithm = DumbCoinSelection;

Default coin selection algorithm used by TxBuilder if not -overridden

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/export/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/export/index.html deleted file mode 100644 index 4b9ff97e6e..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/export/index.html +++ /dev/null @@ -1,28 +0,0 @@ -magical::wallet::export - Rust

[][src]Module magical::wallet::export

Wallet export

-

This modules implements the wallet export format used by FullyNoded.

-

Examples

Import from JSON

-
-let import = r#"{
-    "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
-    "blockheight":1782088,
-    "label":"testnet"
-}"#;
-
-let import = WalletExport::from_str(import)?;
-let wallet: OfflineWallet<_> = Wallet::new_offline(&import.descriptor(), import.change_descriptor().as_deref(), Network::Testnet, MemoryDatabase::default())?;
-

Export a Wallet

-
-let wallet: OfflineWallet<_> = Wallet::new_offline(
-    "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
-    Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
-    Network::Testnet,
-    MemoryDatabase::default()
-)?;
-let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
-    .map_err(ToString::to_string)
-    .map_err(magical::Error::Generic)?;
-
-println!("Exported: {}", export.to_string());
-

Structs

-
WalletExport

Structure that contains the export of a wallet

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/export/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/export/sidebar-items.js deleted file mode 100644 index 06abb3c4ee..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/export/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["WalletExport","Structure that contains the export of a wallet"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/export/struct.WalletExport.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/export/struct.WalletExport.html deleted file mode 100644 index faa02230b8..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/export/struct.WalletExport.html +++ /dev/null @@ -1,36 +0,0 @@ -magical::wallet::export::WalletExport - Rust

[][src]Struct magical::wallet::export::WalletExport

pub struct WalletExport {
-    pub blockheight: u32,
-    pub label: String,
-    // some fields omitted
-}

Structure that contains the export of a wallet

-

For a usage example see this module's documentation.

-

- Fields

blockheight: u32

Earliest block to rescan when looking for the wallet's transactions

-
label: String

Arbitrary label for the wallet

-

Implementations

impl WalletExport[src]

pub fn export_wallet<B: Blockchain, D: BatchDatabase>(
    wallet: &Wallet<B, D>,
    label: &str,
    include_blockheight: bool
) -> Result<Self, &'static str>
[src]

Export a wallet

-

This function returns an error if it determines that the wallet's descriptor(s) are not -supported by Bitcoin Core or don't follow the standard derivation paths defined by BIP44 -and others.

-

If include_blockheight is true, this function will look into the wallet's database -for the oldest transaction it knows and use that as the earliest block to rescan.

-

If the database is empty or include_blockheight is false, the blockheight field -returned will be 0.

-

pub fn descriptor(&self) -> String[src]

Return the external descriptor

-

pub fn change_descriptor(&self) -> Option<String>[src]

Return the internal descriptor, if present

-

Trait Implementations

impl Debug for WalletExport[src]

impl<'de> Deserialize<'de> for WalletExport[src]

impl FromStr for WalletExport[src]

type Err = Error

The associated error which can be returned from parsing.

-

impl Serialize for WalletExport[src]

impl ToString for WalletExport[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/index.html deleted file mode 100644 index af40e78f72..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/index.html +++ /dev/null @@ -1,16 +0,0 @@ -magical::wallet - Rust

[][src]Module magical::wallet

Wallet

-

This module defines the Wallet structure.

-

Modules

-
address_validator

Address validation callbacks

-
coin_selection

Coin selection

-
export

Wallet export

-
signer

Generalized signers

-
time

Cross-platform time

-
tx_builder

Transaction builder

-

Structs

-
Wallet

A Bitcoin wallet

-

Traits

-
IsDust

Trait to check if a value is below the dust limit

-

Type Definitions

-
OfflineWallet

Type alias for a Wallet that uses OfflineBlockchain

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/sidebar-items.js deleted file mode 100644 index 811ec3c2b5..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"mod":[["address_validator","Address validation callbacks"],["coin_selection","Coin selection"],["export","Wallet export"],["signer","Generalized signers"],["time","Cross-platform time"],["tx_builder","Transaction builder"]],"struct":[["Wallet","A Bitcoin wallet"]],"trait":[["IsDust","Trait to check if a value is below the dust limit"]],"type":[["OfflineWallet","Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/enum.SignerError.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/enum.SignerError.html deleted file mode 100644 index bac6385676..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/enum.SignerError.html +++ /dev/null @@ -1,50 +0,0 @@ -magical::wallet::signer::SignerError - Rust

[][src]Enum magical::wallet::signer::SignerError

pub enum SignerError {
-    MissingKey,
-    UserCanceled,
-    MissingSighash,
-    InputIndexOutOfRange,
-    MissingNonWitnessUtxo,
-    InvalidNonWitnessUtxo,
-    MissingWitnessUtxo,
-    MissingWitnessScript,
-    MissingHDKeypath,
-}

Signing error

-

- Variants

-
MissingKey

The private key is missing for the required public key

-
UserCanceled

The user canceled the operation

-
MissingSighash

The sighash is missing in the PSBT input

-
InputIndexOutOfRange

Input index is out of range

-
MissingNonWitnessUtxo

The non_witness_utxo field of the transaction is required to sign this input

-
InvalidNonWitnessUtxo

The non_witness_utxo specified is invalid

-
MissingWitnessUtxo

The witness_utxo field of the transaction is required to sign this input

-
MissingWitnessScript

The witness_script field of the transaction is requied to sign this input

-
MissingHDKeypath

The fingerprint and derivation path are missing from the psbt input

-

Trait Implementations

impl Clone for SignerError[src]

impl Debug for SignerError[src]

impl Display for SignerError[src]

impl Eq for SignerError[src]

impl Error for SignerError[src]

impl From<SignerError> for Error[src]

impl PartialEq<SignerError> for SignerError[src]

impl StructuralEq for SignerError[src]

impl StructuralPartialEq for SignerError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/enum.SignerId.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/enum.SignerId.html deleted file mode 100644 index cb6472e346..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/enum.SignerId.html +++ /dev/null @@ -1,31 +0,0 @@ -magical::wallet::signer::SignerId - Rust

[][src]Enum magical::wallet::signer::SignerId

pub enum SignerId<Pk: MiniscriptKey> {
-    PkHash(<Pk as MiniscriptKey>::Hash),
-    Fingerprint(Fingerprint),
-}

Identifier of a signer in the SignersContainers. Used as a key to find the right signer among -multiple of them

-

- Variants

-
PkHash(<Pk as MiniscriptKey>::Hash)
Fingerprint(Fingerprint)

Trait Implementations

impl<Pk: Clone + MiniscriptKey> Clone for SignerId<Pk>[src]

impl<Pk: Debug + MiniscriptKey> Debug for SignerId<Pk>[src]

impl<Pk: Eq + MiniscriptKey> Eq for SignerId<Pk>[src]

impl From<Fingerprint> for SignerId<DescriptorPublicKey>[src]

impl From<Hash> for SignerId<DescriptorPublicKey>[src]

impl<Pk: Hash + MiniscriptKey> Hash for SignerId<Pk>[src]

impl<Pk: PartialEq + MiniscriptKey> PartialEq<SignerId<Pk>> for SignerId<Pk>[src]

impl<Pk: MiniscriptKey> StructuralEq for SignerId<Pk>[src]

impl<Pk: MiniscriptKey> StructuralPartialEq for SignerId<Pk>[src]

Auto Trait Implementations

impl<Pk> RefUnwindSafe for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe

impl<Pk> Send for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Send

impl<Pk> Sync for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Sync

impl<Pk> Unpin for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk> UnwindSafe for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/index.html deleted file mode 100644 index 5556a2f081..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/index.html +++ /dev/null @@ -1,54 +0,0 @@ -magical::wallet::signer - Rust

[][src]Module magical::wallet::signer

Generalized signers

-

This module provides the ability to add customized signers to a Wallet -through the Wallet::add_signer function.

- -
-#[derive(Debug)]
-struct CustomSigner {
-    device: CustomHSM,
-}
-
-impl CustomSigner {
-    fn connect() -> Self {
-        CustomSigner { device: CustomHSM::connect() }
-    }
-}
-
-impl Signer for CustomSigner {
-    fn sign(
-        &self,
-        psbt: &mut psbt::PartiallySignedTransaction,
-        input_index: Option<usize>,
-    ) -> Result<(), SignerError> {
-        let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
-        self.device.sign_input(psbt, input_index)?;
-
-        Ok(())
-    }
-
-    fn sign_whole_tx(&self) -> bool {
-        false
-    }
-}
-
-let custom_signer = CustomSigner::connect();
-
-let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
-wallet.add_signer(
-    ScriptType::External,
-    Fingerprint::from_str("e30f11b8").unwrap().into(),
-    SignerOrdering(200),
-    Arc::new(Box::new(custom_signer))
-);
-
-

Structs

-
SignerOrdering

Defines the order in which signers are called

-
SignersContainer

Container for multiple signers

-

Enums

-
SignerError

Signing error

-
SignerId

Identifier of a signer in the SignersContainers. Used as a key to find the right signer among -multiple of them

-

Traits

-
Signer

Trait for signers

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/sidebar-items.js deleted file mode 100644 index 8f3e3d79b6..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["SignerError","Signing error"],["SignerId","Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among multiple of them"]],"struct":[["SignerOrdering","Defines the order in which signers are called"],["SignersContainer","Container for multiple signers"]],"trait":[["Signer","Trait for signers"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/struct.SignerOrdering.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/struct.SignerOrdering.html deleted file mode 100644 index 6cedae6f8b..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/struct.SignerOrdering.html +++ /dev/null @@ -1,34 +0,0 @@ -magical::wallet::signer::SignerOrdering - Rust

[][src]Struct magical::wallet::signer::SignerOrdering

pub struct SignerOrdering(pub usize);

Defines the order in which signers are called

-

The default value is 100. Signers with an ordering above that will be called later, -and they will thus see the partial signatures added to the transaction once they get to sign -themselves.

-

Trait Implementations

impl Clone for SignerOrdering[src]

impl Debug for SignerOrdering[src]

impl Default for SignerOrdering[src]

impl Eq for SignerOrdering[src]

impl Ord for SignerOrdering[src]

impl PartialEq<SignerOrdering> for SignerOrdering[src]

impl PartialOrd<SignerOrdering> for SignerOrdering[src]

impl StructuralEq for SignerOrdering[src]

impl StructuralPartialEq for SignerOrdering[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/struct.SignersContainer.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/struct.SignersContainer.html deleted file mode 100644 index e28d3e9518..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/struct.SignersContainer.html +++ /dev/null @@ -1,27 +0,0 @@ -magical::wallet::signer::SignersContainer - Rust

[][src]Struct magical::wallet::signer::SignersContainer

pub struct SignersContainer<Pk: MiniscriptKey>(_);

Container for multiple signers

-

Implementations

impl SignersContainer<DescriptorPublicKey>[src]

pub fn as_key_map(&self) -> KeyMap[src]

impl<Pk: MiniscriptKey> SignersContainer<Pk>[src]

pub fn new() -> Self[src]

Default constructor

-

pub fn add_external(
    &mut self,
    id: SignerId<Pk>,
    ordering: SignerOrdering,
    signer: Arc<Box<dyn Signer>>
) -> Option<Arc<Box<dyn Signer>>>
[src]

Adds an external signer to the container for the specified id. Optionally returns the -signer that was previosuly in the container, if any

-

pub fn remove(
    &mut self,
    id: SignerId<Pk>,
    ordering: SignerOrdering
) -> Option<Arc<Box<dyn Signer>>>
[src]

Removes a signer from the container and returns it

-

pub fn ids(&self) -> Vec<&SignerId<Pk>>[src]

Returns the list of identifiers of all the signers in the container

-

pub fn signers(&self) -> Vec<&Arc<Box<dyn Signer>>>[src]

Returns the list of signers in the container, sorted by lowest to highest ordering

-

pub fn find(&self, id: SignerId<Pk>) -> Option<&Arc<Box<dyn Signer>>>[src]

Finds the signer with lowest ordering for a given id in the container.

-

Trait Implementations

impl<Pk: Clone + MiniscriptKey> Clone for SignersContainer<Pk>[src]

impl<Pk: Debug + MiniscriptKey> Debug for SignersContainer<Pk>[src]

impl<Pk: Default + MiniscriptKey> Default for SignersContainer<Pk>[src]

impl From<HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>> for SignersContainer<DescriptorPublicKey>[src]

Auto Trait Implementations

impl<Pk> !RefUnwindSafe for SignersContainer<Pk>

impl<Pk> !Send for SignersContainer<Pk>

impl<Pk> !Sync for SignersContainer<Pk>

impl<Pk> Unpin for SignersContainer<Pk> where
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk> !UnwindSafe for SignersContainer<Pk>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/trait.Signer.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/trait.Signer.html deleted file mode 100644 index 9bf09f094e..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/signer/trait.Signer.html +++ /dev/null @@ -1,23 +0,0 @@ -magical::wallet::signer::Signer - Rust

[][src]Trait magical::wallet::signer::Signer

pub trait Signer: Debug {
-    fn sign(
        &self,
        psbt: &mut PartiallySignedTransaction,
        input_index: Option<usize>
    ) -> Result<(), SignerError>; -
fn sign_whole_tx(&self) -> bool; - - fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> { ... } -}

Trait for signers

-

This trait can be implemented to provide customized signers to the wallet. For an example see -this module's documentation.

-
-

Required methods

fn sign(
    &self,
    psbt: &mut PartiallySignedTransaction,
    input_index: Option<usize>
) -> Result<(), SignerError>

Sign a PSBT

-

The input_index argument is only provided if the wallet doesn't declare to sign the whole -transaction in one go (see Signer::sign_whole_tx). Otherwise its value is None and -can be ignored.

-

fn sign_whole_tx(&self) -> bool

Return whether or not the signer signs the whole transaction in one go instead of every -input individually

-
Loading content... -

Provided methods

fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey>

Return the secret key for the signer

-

This is used internally to reconstruct the original descriptor that may contain secrets. -External signers that are meant to keep key isolated should just return None here (which -is the default for this method, if not overridden).

-
Loading content... -

Implementations on Foreign Types

impl Signer for DescriptorXKey<ExtendedPrivKey>[src]

impl Signer for PrivateKey[src]

Loading content... -

Implementors

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/struct.Wallet.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/struct.Wallet.html deleted file mode 100644 index 7c033f7285..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/struct.Wallet.html +++ /dev/null @@ -1,70 +0,0 @@ -magical::wallet::Wallet - Rust

[][src]Struct magical::wallet::Wallet

pub struct Wallet<B: Blockchain, D: BatchDatabase> { /* fields omitted */ }

A Bitcoin wallet

-

A wallet takes descriptors, a database and a -blockchain and implements the basic functions that a Bitcoin wallets -needs to operate, like generating addresses, returning the balance, -creating transactions, etc.

-

A wallet can be either "online" if the blockchain type provided -implements OnlineBlockchain, or "offline" if it doesn't. Offline wallets only expose -methods that don't need any interaction with the blockchain to work.

-

Implementations

impl<B, D> Wallet<B, D> where
    B: Blockchain,
    D: BatchDatabase
[src]

pub fn new_offline(
    descriptor: &str,
    change_descriptor: Option<&str>,
    network: Network,
    database: D
) -> Result<Self, Error>
[src]

Create a new "offline" wallet

-

pub fn get_new_address(&self) -> Result<Address, Error>[src]

Return a newly generated address using the external descriptor

-

pub fn is_mine(&self, script: &Script) -> Result<bool, Error>[src]

Return whether or not a script is part of this wallet (either internal or external)

-

pub fn list_unspent(&self) -> Result<Vec<UTXO>, Error>[src]

Return the list of unspent outputs of this wallet

-

Note that this methods only operate on the internal database, which first needs to be -Wallet::sync manually.

-

pub fn list_transactions(
    &self,
    include_raw: bool
) -> Result<Vec<TransactionDetails>, Error>
[src]

Return the list of transactions made and received by the wallet

-

Optionally fill the TransactionDetails::transaction field with the raw transaction if -include_raw is true.

-

Note that this methods only operate on the internal database, which first needs to be -Wallet::sync manually.

-

pub fn get_balance(&self) -> Result<u64, Error>[src]

Return the balance, meaning the sum of this wallet's unspent outputs' values

-

Note that this methods only operate on the internal database, which first needs to be -Wallet::sync manually.

-

pub fn add_signer(
    &mut self,
    script_type: ScriptType,
    id: SignerId<DescriptorPublicKey>,
    ordering: SignerOrdering,
    signer: Arc<Box<dyn Signer>>
)
[src]

Add an external signer

-

See the signer module for an example.

-

pub fn add_address_validator(
    &mut self,
    validator: Arc<Box<dyn AddressValidator>>
)
[src]

Add an address validator

-

See the address_validator module for an example.

-

pub fn create_tx<Cs: CoinSelectionAlgorithm>(
    &self,
    builder: TxBuilder<Cs>
) -> Result<(PSBT, TransactionDetails), Error>
[src]

Create a new transaction following the options specified in the builder

-

Example

-
-let (psbt, details) = wallet.create_tx(
-    TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
-)?;
-// sign and broadcast ...
-

pub fn bump_fee<Cs: CoinSelectionAlgorithm>(
    &self,
    txid: &Txid,
    builder: TxBuilder<Cs>
) -> Result<(PSBT, TransactionDetails), Error>
[src]

Bump the fee of a transaction following the options specified in the builder

-

Return an error if the transaction is already confirmed or doesn't explicitly signal RBF.

-

NOTE: if the original transaction was made with TxBuilder::send_all, the same -option must be enabled when bumping its fees to correctly reduce the only output's value to -increase the fees.

-

Example

-
-let txid = Txid::from_str("faff0a466b70f5d5f92bd757a92c1371d4838bdd5bc53a06764e2488e51ce8f8").unwrap();
-let (psbt, details) = wallet.bump_fee(
-    &txid,
-    TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(5.0)),
-)?;
-// sign and broadcast ...
-

pub fn sign(
    &self,
    psbt: PSBT,
    assume_height: Option<u32>
) -> Result<(PSBT, bool), Error>
[src]

Sign a transaction with all the wallet's signers, in the order specified by every signer's -SignerOrdering

-

Example

-
-let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
-

pub fn policies(&self, script_type: ScriptType) -> Result<Option<Policy>, Error>[src]

Return the spending policies for the wallet's descriptor

-

pub fn public_descriptor(
    &self,
    script_type: ScriptType
) -> Result<Option<ExtendedDescriptor>, Error>
[src]

Return the "public" version of the wallet's descriptor, meaning a new descriptor that has -the same structure but with every secret key removed

-

This can be used to build a watch-only version of a wallet

-

pub fn finalize_psbt(
    &self,
    psbt: PSBT,
    assume_height: Option<u32>
) -> Result<(PSBT, bool), Error>
[src]

Try to finalize a PSBT

-

impl<B, D> Wallet<B, D> where
    B: OnlineBlockchain,
    D: BatchDatabase
[src]

pub fn new(
    descriptor: &str,
    change_descriptor: Option<&str>,
    network: Network,
    database: D,
    client: B
) -> Result<Self, Error>
[src]

Create a new "online" wallet

-

pub fn sync<P: 'static + Progress>(
    &self,
    progress_update: P,
    max_address_param: Option<u32>
) -> Result<(), Error>
[src]

Sync the internal database with the blockchain

-

pub fn client(&self) -> &B[src]

Return a reference to the internal blockchain client

-

pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error>[src]

Broadcast a transaction to the network

-

Auto Trait Implementations

impl<B, D> !RefUnwindSafe for Wallet<B, D>

impl<B, D> !Send for Wallet<B, D>

impl<B, D> !Sync for Wallet<B, D>

impl<B, D> Unpin for Wallet<B, D> where
    B: Unpin,
    D: Unpin

impl<B, D> !UnwindSafe for Wallet<B, D>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/time/fn.get_timestamp.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/time/fn.get_timestamp.html deleted file mode 100644 index cd40bebf24..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/time/fn.get_timestamp.html +++ /dev/null @@ -1,2 +0,0 @@ -magical::wallet::time::get_timestamp - Rust

[][src]Function magical::wallet::time::get_timestamp

pub fn get_timestamp() -> u64

Return the current timestamp in seconds

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/time/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/time/index.html deleted file mode 100644 index ec69ac5801..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/time/index.html +++ /dev/null @@ -1,8 +0,0 @@ -magical::wallet::time - Rust

[][src]Module magical::wallet::time

Cross-platform time

-

This module provides a function to get the current timestamp that works on all the platforms -supported by the library.

-

It can be useful to compare it with the timestamps found in -TransactionDetails.

-

Functions

-
get_timestamp

Return the current timestamp in seconds

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/time/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/time/sidebar-items.js deleted file mode 100644 index 22164ef49f..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/time/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"fn":[["get_timestamp","Return the current timestamp in seconds"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/trait.IsDust.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/trait.IsDust.html deleted file mode 100644 index 7a73d9bfc6..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/trait.IsDust.html +++ /dev/null @@ -1,8 +0,0 @@ -magical::wallet::IsDust - Rust

[][src]Trait magical::wallet::IsDust

pub trait IsDust {
-    fn is_dust(&self) -> bool;
-}

Trait to check if a value is below the dust limit

-
-

Required methods

fn is_dust(&self) -> bool

Check whether or not a value is below dust limit

-
Loading content... -

Implementations on Foreign Types

impl IsDust for u64[src]

Loading content... -

Implementors

Loading content...
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/enum.ChangeSpendPolicy.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/enum.ChangeSpendPolicy.html deleted file mode 100644 index 8d7e37f3d5..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/enum.ChangeSpendPolicy.html +++ /dev/null @@ -1,42 +0,0 @@ -magical::wallet::tx_builder::ChangeSpendPolicy - Rust

[][src]Enum magical::wallet::tx_builder::ChangeSpendPolicy

pub enum ChangeSpendPolicy {
-    ChangeAllowed,
-    OnlyChange,
-    ChangeForbidden,
-}

Policy regarding the use of change outputs when creating a transaction

-

- Variants

-
ChangeAllowed

Use both change and non-change outputs (default)

-
OnlyChange

Only use change outputs (see TxBuilder::only_spend_change)

-
ChangeForbidden

Only use non-change outputs (see TxBuilder::do_not_spend_change)

-

Trait Implementations

impl Clone for ChangeSpendPolicy[src]

impl Copy for ChangeSpendPolicy[src]

impl Debug for ChangeSpendPolicy[src]

impl Default for ChangeSpendPolicy[src]

impl Eq for ChangeSpendPolicy[src]

impl Hash for ChangeSpendPolicy[src]

impl Ord for ChangeSpendPolicy[src]

impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy[src]

impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy[src]

impl StructuralEq for ChangeSpendPolicy[src]

impl StructuralPartialEq for ChangeSpendPolicy[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/enum.TxOrdering.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/enum.TxOrdering.html deleted file mode 100644 index b29bf7613f..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/enum.TxOrdering.html +++ /dev/null @@ -1,42 +0,0 @@ -magical::wallet::tx_builder::TxOrdering - Rust

[][src]Enum magical::wallet::tx_builder::TxOrdering

pub enum TxOrdering {
-    Shuffle,
-    Untouched,
-    BIP69Lexicographic,
-}

Ordering of the transaction's inputs and outputs

-

- Variants

-
Shuffle

Randomized (default)

-
Untouched

Unchanged

-
BIP69Lexicographic

BIP69 / Lexicographic

-

Implementations

impl TxOrdering[src]

pub fn sort_tx(&self, tx: &mut Transaction)[src]

Trait Implementations

impl Clone for TxOrdering[src]

impl Copy for TxOrdering[src]

impl Debug for TxOrdering[src]

impl Default for TxOrdering[src]

impl Eq for TxOrdering[src]

impl Hash for TxOrdering[src]

impl Ord for TxOrdering[src]

impl PartialEq<TxOrdering> for TxOrdering[src]

impl PartialOrd<TxOrdering> for TxOrdering[src]

impl StructuralEq for TxOrdering[src]

impl StructuralPartialEq for TxOrdering[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

-

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/index.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/index.html deleted file mode 100644 index c66475003b..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/index.html +++ /dev/null @@ -1,16 +0,0 @@ -magical::wallet::tx_builder - Rust

[][src]Module magical::wallet::tx_builder

Transaction builder

-

Example

-
-// Create a transaction with one output to `to_address` of 50_000 satoshi, with a custom fee rate
-// of 5.0 satoshi/vbyte, only spending non-change outputs and with RBF signaling
-// enabled
-let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
-    .fee_rate(FeeRate::from_sat_per_vb(5.0))
-    .do_not_spend_change()
-    .enable_rbf();
-

Structs

-
TxBuilder

A transaction builder

-

Enums

-
ChangeSpendPolicy

Policy regarding the use of change outputs when creating a transaction

-
TxOrdering

Ordering of the transaction's inputs and outputs

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/sidebar-items.js b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/sidebar-items.js deleted file mode 100644 index e51db729e0..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["ChangeSpendPolicy","Policy regarding the use of change outputs when creating a transaction"],["TxOrdering","Ordering of the transaction's inputs and outputs"]],"struct":[["TxBuilder","A transaction builder"]]}); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/struct.TxBuilder.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/struct.TxBuilder.html deleted file mode 100644 index a9649353d1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/tx_builder/struct.TxBuilder.html +++ /dev/null @@ -1,70 +0,0 @@ -magical::wallet::tx_builder::TxBuilder - Rust

[][src]Struct magical::wallet::tx_builder::TxBuilder

pub struct TxBuilder<Cs: CoinSelectionAlgorithm> { /* fields omitted */ }

A transaction builder

-

This structure contains the configuration that the wallet must follow to build a transaction.

-

For an example see this module's documentation;

-

Implementations

impl TxBuilder<DefaultCoinSelectionAlgorithm>[src]

pub fn new() -> Self[src]

Create an empty builder

-

pub fn with_recipients(recipients: Vec<(Script, u64)>) -> Self[src]

Create a builder starting from a list of recipients

-

impl<Cs: CoinSelectionAlgorithm> TxBuilder<Cs>[src]

pub fn set_recipients(self, recipients: Vec<(Script, u64)>) -> Self[src]

Replace the recipients already added with a new list

-

pub fn add_recipient(self, script_pubkey: Script, amount: u64) -> Self[src]

Add a recipient to the internal list

-

pub fn send_all(self) -> Self[src]

Send all the selected utxos to a single output

-

Adding more than one recipients with this option enabled will result in an error.

-

The value associated with the only recipient is irrelevant and will be replaced by the wallet.

-

pub fn fee_rate(self, fee_rate: FeeRate) -> Self[src]

Set a custom fee rate

-

pub fn policy_path(self, policy_path: BTreeMap<String, Vec<usize>>) -> Self[src]

Set the policy path to use while creating the transaction

-

This method accepts a map where the key is the policy node id (see -Policy::id) and the value is the list of the indexes of -the items that are intended to be satisfied from the policy node (see -SatisfiableItem::Thresh::items).

-

pub fn utxos(self, utxos: Vec<OutPoint>) -> Self[src]

Replace the internal list of utxos that must be spent with a new list

-

These have priority over the "unspendable" utxos, meaning that if a utxo is present both in -the "utxos" and the "unspendable" list, it will be spent.

-

pub fn add_utxo(self, utxo: OutPoint) -> Self[src]

Add a utxo to the internal list of utxos that must be spent

-

These have priority over the "unspendable" utxos, meaning that if a utxo is present both in -the "utxos" and the "unspendable" list, it will be spent.

-

pub fn unspendable(self, unspendable: Vec<OutPoint>) -> Self[src]

Replace the internal list of unspendable utxos with a new list

-

It's important to note that the "must-be-spent" utxos added with TxBuilder::utxos and -TxBuilder::add_utxo have priority over these. See the docs of the two linked methods -for more details.

-

pub fn add_unspendable(self, unspendable: OutPoint) -> Self[src]

Add a utxo to the internal list of unspendable utxos

-

It's important to note that the "must-be-spent" utxos added with TxBuilder::utxos and -TxBuilder::add_utxo have priority over this. See the docs of the two linked methods -for more details.

-

pub fn sighash(self, sighash: SigHashType) -> Self[src]

Sign with a specific sig hash

-

Use this option very carefully

-

pub fn ordering(self, ordering: TxOrdering) -> Self[src]

Choose the ordering for inputs and outputs of the transaction

-

pub fn nlocktime(self, locktime: u32) -> Self[src]

Use a specific nLockTime while creating the transaction

-

This can cause conflicts if the wallet's descriptors contain an "after" (OP_CLTV) operator.

-

pub fn enable_rbf(self) -> Self[src]

Enable signaling RBF

-

This will use the default nSequence value of 0xFFFFFFFD.

-

pub fn enable_rbf_with_sequence(self, nsequence: u32) -> Self[src]

Enable signaling RBF with a specific nSequence value

-

This can cause conflicts if the wallet's descriptors contain an "older" (OP_CSV) operator -and the given nsequence is lower than the CSV value.

-

If the nsequence is higher than 0xFFFFFFFD an error will be thrown, since it would not -be a valid nSequence to signal RBF.

-

pub fn version(self, version: u32) -> Self[src]

Build a transaction with a specific version

-

The version should always be greater than 0 and greater than 1 if the wallet's -descriptors contain an "older" (OP_CSV) operator.

-

pub fn do_not_spend_change(self) -> Self[src]

Do not spend change outputs

-

This effectively adds all the change outputs to the "unspendable" list. See -TxBuilder::unspendable.

-

pub fn only_spend_change(self) -> Self[src]

Only spend change outputs

-

This effectively adds all the non-change outputs to the "unspendable" list. See -TxBuilder::unspendable.

-

pub fn change_policy(self, change_policy: ChangeSpendPolicy) -> Self[src]

pub fn force_non_witness_utxo(self) -> Self[src]

Fill-in the psbt::Input::non_witness_utxo field even if the wallet only has SegWit -descriptors.

-

This is useful for signers which always require it, like Trezor hardware wallets.

-

pub fn coin_selection<P: CoinSelectionAlgorithm>(
    self,
    coin_selection: P
) -> TxBuilder<P>
[src]

Choose the coin selection algorithm

-

Overrides the DefaultCoinSelectionAlgorithm.

-

Trait Implementations

impl<Cs: Debug + CoinSelectionAlgorithm> Debug for TxBuilder<Cs>[src]

impl<Cs: Default + CoinSelectionAlgorithm> Default for TxBuilder<Cs>[src]

Auto Trait Implementations

impl<Cs> RefUnwindSafe for TxBuilder<Cs> where
    Cs: RefUnwindSafe

impl<Cs> Send for TxBuilder<Cs> where
    Cs: Send

impl<Cs> Sync for TxBuilder<Cs> where
    Cs: Sync

impl<Cs> Unpin for TxBuilder<Cs> where
    Cs: Unpin

impl<Cs> UnwindSafe for TxBuilder<Cs> where
    Cs: UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

-

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

-

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/type.OfflineWallet.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/type.OfflineWallet.html deleted file mode 100644 index 4f6a751bba..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/type.OfflineWallet.html +++ /dev/null @@ -1,2 +0,0 @@ -magical::wallet::OfflineWallet - Rust

[][src]Type Definition magical::wallet::OfflineWallet

type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;

Type alias for a Wallet that uses OfflineBlockchain

-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/utils/trait.IsDust.html b/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/utils/trait.IsDust.html deleted file mode 100644 index 90122f3cfc..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/magical/wallet/utils/trait.IsDust.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

Redirecting to ../../../magical/wallet/trait.IsDust.html...

- - - \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/main.js b/static/docs-rs/magical/0.1.0-beta.1/main.js deleted file mode 100644 index 0bdb14b511..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/main.js +++ /dev/null @@ -1,7 +0,0 @@ -if(!String.prototype.startsWith){String.prototype.startsWith=function(searchString,position){position=position||0;return this.indexOf(searchString,position)===position}}if(!String.prototype.endsWith){String.prototype.endsWith=function(suffix,length){var l=length||this.length;return this.indexOf(suffix,l-suffix.length)!==-1}}if(!DOMTokenList.prototype.add){DOMTokenList.prototype.add=function(className){if(className&&!hasClass(this,className)){if(this.className&&this.className.length>0){this.className+=" "+className}else{this.className=className}}}}if(!DOMTokenList.prototype.remove){DOMTokenList.prototype.remove=function(className){if(className&&this.className){this.className=(" "+this.className+" ").replace(" "+className+" "," ").trim()}}}function getSearchInput(){return document.getElementsByClassName("search-input")[0]}function getSearchElement(){return document.getElementById("search")}function focusSearchBar(){getSearchInput().focus()}function defocusSearchBar(){getSearchInput().blur()}(function(){"use strict";var itemTypes=["mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","primitive","associatedtype","constant","associatedconstant","union","foreigntype","keyword","existential","attr","derive","traitalias"];var disableShortcuts=getCurrentValue("rustdoc-disable-shortcuts")==="true";var search_input=getSearchInput();var searchTimeout=null;var currentTab=0;var mouseMovedAfterSearch=true;var titleBeforeSearch=document.title;function clearInputTimeout(){if(searchTimeout!==null){clearTimeout(searchTimeout);searchTimeout=null}}function getPageId(){if(window.location.hash){var tmp=window.location.hash.replace(/^#/,"");if(tmp.length>0){return tmp}}return null}function showSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){addClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];if(sidebar){addClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(!filler){var div=document.createElement("div");div.id="sidebar-filler";sidebar.appendChild(div)}}var themePickers=document.getElementsByClassName("theme-picker");if(themePickers&&themePickers.length>0){themePickers[0].style.display="none"}}function hideSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){removeClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(filler){filler.remove()}document.getElementsByTagName("body")[0].style.marginTop="";var themePickers=document.getElementsByClassName("theme-picker");if(themePickers&&themePickers.length>0){themePickers[0].style.display=null}}function showSearchResults(search){if(search===null||typeof search==='undefined'){search=getSearchElement()}addClass(main,"hidden");removeClass(search,"hidden");mouseMovedAfterSearch=false}function hideSearchResults(search){if(search===null||typeof search==='undefined'){search=getSearchElement()}addClass(search,"hidden");removeClass(main,"hidden")}var TY_PRIMITIVE=itemTypes.indexOf("primitive");var TY_KEYWORD=itemTypes.indexOf("keyword");function getQueryStringParams(){var params={};window.location.search.substring(1).split("&").map(function(s){var pair=s.split("=");params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function isHidden(elem){return elem.offsetHeight===0}var main=document.getElementById("main");var savedHash="";function handleHashes(ev){var elem;var search=getSearchElement();if(ev!==null&&search&&!hasClass(search,"hidden")&&ev.newURL){hideSearchResults(search);var hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(hash,"","?search=#"+hash)}elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}if(savedHash!==window.location.hash){savedHash=window.location.hash;if(savedHash.length===0){return}elem=document.getElementById(savedHash.slice(1));if(!elem||!isHidden(elem)){return}var parent=elem.parentNode;if(parent&&hasClass(parent,"impl-items")){onEachLazy(parent.getElementsByClassName("collapsed"),function(e){if(e.parentNode===parent){e.click();return true}});if(isHidden(elem)){if(hasClass(parent.lastElementChild,"collapse-toggle")){parent.lastElementChild.click()}}}}}function highlightSourceLines(match,ev){if(typeof match==="undefined"){hideSidebar();match=window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/)}if(!match){return}var from=parseInt(match[1],10);var to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to0){collapseDocs(collapses[0],"show")}}}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!="undefined"){return ev.key}var c=ev.charCode||ev.keyCode;if(c==27){return"Escape"}return String.fromCharCode(c)}function getHelpElement(){return document.getElementById("help")}function displayHelp(display,ev,help){help=help?help:getHelpElement();if(display===true){if(hasClass(help,"hidden")){ev.preventDefault();removeClass(help,"hidden");addClass(document.body,"blur")}}else if(hasClass(help,"hidden")===false){ev.preventDefault();addClass(help,"hidden");removeClass(document.body,"blur")}}function handleEscape(ev){var help=getHelpElement();var search=getSearchElement();if(hasClass(help,"hidden")===false){displayHelp(false,ev,help)}else if(hasClass(search,"hidden")===false){clearInputTimeout();ev.preventDefault();hideSearchResults(search);document.title=titleBeforeSearch}defocusSearchBar()}function handleShortcut(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts===true){return}if(document.activeElement.tagName==="INPUT"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":displayHelp(false,ev);ev.preventDefault();focusSearchBar();break;case"+":case"-":ev.preventDefault();toggleAllDocs();break;case"?":if(ev.shiftKey){displayHelp(true,ev)}break}}}function findParentElement(elem,tagName){do{if(elem&&elem.tagName===tagName){return elem}elem=elem.parentNode}while(elem);return null}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);function resetMouseMoved(ev){mouseMovedAfterSearch=true}document.addEventListener("mousemove",resetMouseMoved);var handleSourceHighlight=(function(){var prev_line_id=0;var set_fragment=function(name){var x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSourceLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return function(ev){var cur_line_id=parseInt(ev.target.id,10);ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){var tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());document.addEventListener("click",function(ev){if(hasClass(ev.target,"collapse-toggle")){collapseDocs(ev.target,"toggle")}else if(hasClass(ev.target.parentNode,"collapse-toggle")){collapseDocs(ev.target.parentNode,"toggle")}else if(ev.target.tagName==="SPAN"&&hasClass(ev.target.parentNode,"line-numbers")){handleSourceHighlight(ev)}else if(hasClass(getHelpElement(),"hidden")===false){var help=getHelpElement();var is_inside_help_popup=ev.target!==help&&help.contains(ev.target);if(is_inside_help_popup===false){addClass(help,"hidden");removeClass(document.body,"blur")}}else{var a=findParentElement(ev.target,"A");if(a&&a.hash){expandSection(a.hash.replace(/^#/,""))}}});(function(){var x=document.getElementsByClassName("version-selector");if(x.length>0){x[0].onchange=function(){var i,match,url=document.location.href,stripped="",len=rootPath.match(/\.\.\//g).length+1;for(i=0;i-1){var obj=searchIndex[results[i].id];obj.lev=results[i].lev;if(isType!==true||obj.type){var res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=obj.displayPath+obj.name;obj.fullPath+="|"+obj.ty;obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}}return out}function sortResults(results,isType){var ar=[];for(var entry in results){if(hasOwnProperty(results,entry)){ar.push(results[entry])}}results=ar;var i;var nresults=results.length;for(i=0;ib?+1:-1)}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}if((aaa.item.ty===TY_PRIMITIVE&&bbb.item.ty!==TY_KEYWORD)||(aaa.item.ty===TY_KEYWORD&&bbb.item.ty!==TY_PRIMITIVE)){return-1}if((bbb.item.ty===TY_PRIMITIVE&&aaa.item.ty!==TY_PRIMITIVE)||(bbb.item.ty===TY_KEYWORD&&aaa.item.ty!==TY_KEYWORD)){return 1}a=(aaa.item.desc==="");b=(bbb.item.desc==="");if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});var length=results.length;for(i=0;i"));return{name:val.substring(0,val.indexOf("<")),generics:values.split(/\s*,\s*/),}}return{name:val,generics:[],}}function getObjectFromId(id){if(typeof id==="number"){return searchIndex[id]}return{'name':id}}function checkGenerics(obj,val){var lev_distance=MAX_LEV_DISTANCE+1;if(val.generics.length>0){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=obj[GENERICS_DATA].slice(0);var total=0;var done=0;var vlength=val.generics.length;for(var y=0;yGENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=obj[GENERICS_DATA].slice(0);var allFound=true;for(var y=0;allFound===true&&yGENERICS_DATA&&obj[GENERICS_DATA].length!==0){var tmp_lev=checkGenerics(obj,val);if(tmp_lev<=MAX_LEV_DISTANCE){return tmp_lev}}else{return 0}}if(literalSearch===true){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>0){var length=obj[GENERICS_DATA].length;for(x=0;xGENERICS_DATA&&obj[GENERICS_DATA].length>0){var olength=obj[GENERICS_DATA].length;for(x=0;x0){var length=obj.type[INPUTS_DATA].length;for(var i=0;iOUTPUT_DATA){var ret=obj.type[OUTPUT_DATA];if(typeof ret[0]==="string"){ret=[ret]}for(var x=0;xlength){return MAX_LEV_DISTANCE+1}for(var i=0;ilength){break}var lev_total=0;var aborted=false;for(var x=0;xMAX_LEV_DISTANCE){aborted=true;break}lev_total+=lev}if(aborted===false){ret_lev=Math.min(ret_lev,Math.round(lev_total/clength))}}return ret_lev}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER)return true;if(filter===type)return true;var name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function generateId(ty){if(ty.parent&&ty.parent.name){return itemTypes[ty.ty]+ty.path+ty.parent.name+ty.name}return itemTypes[ty.ty]+ty.path+ty.name}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,desc:item.desc,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,}}function handleAliases(ret,query,filterCrates){var aliases=[];var crateAliases=[];var i;if(filterCrates!==undefined){if(ALIASES[filterCrates]&&ALIASES[filterCrates][query.search]){for(i=0;iMAX_RESULTS){ret.others.pop()}};onEach(aliases,pushFunc);onEach(crateAliases,pushFunc)}var nSearchWords=searchWords.length;var i;var ty;var fullId;var returned;var in_args;if((val.charAt(0)==="\""||val.charAt(0)==="'")&&val.charAt(val.length-1)===val.charAt(0)){val=extractGenerics(val.substr(1,val.length-2));for(i=0;i")>-1){var trimmer=function(s){return s.trim()};var parts=val.split("->").map(trimmer);var input=parts[0];var inputs=input.split(",").map(trimmer).sort();for(i=0;i1?paths.length-1:1);var lev;for(j=0;j1){lev=checkPath(contains,paths[paths.length-1],ty);if(lev>MAX_LEV_DISTANCE){continue}else if(lev>0){lev_add=lev/10}}returned=MAX_LEV_DISTANCE+1;in_args=MAX_LEV_DISTANCE+1;var index=-1;lev=MAX_LEV_DISTANCE+1;fullId=generateId(ty);if(searchWords[j].indexOf(split[i])>-1||searchWords[j].indexOf(val)>-1||searchWords[j].replace(/_/g,"").indexOf(val)>-1){if(typePassesFilter(typeFilter,ty.ty)&&results[fullId]===undefined){index=searchWords[j].replace(/_/g,"").indexOf(val)}}if((lev=levenshtein(searchWords[j],val))<=MAX_LEV_DISTANCE){if(typePassesFilter(typeFilter,ty.ty)===false){lev=MAX_LEV_DISTANCE+1}else{lev+=1}}in_args=findArg(ty,valGenerics,false,typeFilter);returned=checkReturned(ty,valGenerics,false,typeFilter);lev+=lev_add;if(lev>0&&val.length>3&&searchWords[j].indexOf(val)>-1){if(val.length<6){lev-=1}else{lev=0}}if(in_args<=MAX_LEV_DISTANCE){if(results_in_args[fullId]===undefined){results_in_args[fullId]={id:j,index:index,lev:in_args,}}results_in_args[fullId].lev=Math.min(results_in_args[fullId].lev,in_args)}if(returned<=MAX_LEV_DISTANCE){if(results_returned[fullId]===undefined){results_returned[fullId]={id:j,index:index,lev:returned,}}results_returned[fullId].lev=Math.min(results_returned[fullId].lev,returned)}if(index!==-1||lev<=MAX_LEV_DISTANCE){if(index!==-1&&paths.length<2){lev=0}if(results[fullId]===undefined){results[fullId]={id:j,index:index,lev:lev,}}results[fullId].lev=Math.min(results[fullId].lev,lev)}}}var ret={"in_args":sortResults(results_in_args,true),"returned":sortResults(results_returned,true),"others":sortResults(results),};handleAliases(ret,query,filterCrates);return ret}function validateResult(name,path,keys,parent){for(var i=0;i-1||path.indexOf(keys[i])>-1||(parent!==undefined&&parent.name!==undefined&&parent.name.toLowerCase().indexOf(keys[i])>-1)||levenshtein(name,keys[i])<=MAX_LEV_DISTANCE)){return false}}return true}function getQuery(raw){var matches,type,query;query=raw;matches=query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);if(matches){type=matches[1].replace(/^const$/,"constant");query=query.substring(matches[0].length)}return{raw:raw,query:query,type:type,id:query+type}}function initSearchNav(){var hoverTimeout;var click_func=function(e){var el=e.target;while(el.tagName!=="TR"){el=el.parentNode}var dst=e.target.getElementsByTagName("a");if(dst.length<1){return}dst=dst[0];if(window.location.pathname===dst.pathname){hideSearchResults();document.location.href=dst.href}};var mouseover_func=function(e){if(mouseMovedAfterSearch){var el=e.target;while(el.tagName!=="TR"){el=el.parentNode}clearTimeout(hoverTimeout);hoverTimeout=setTimeout(function(){onEachLazy(document.getElementsByClassName("search-results"),function(e){onEachLazy(e.getElementsByClassName("result"),function(i_e){removeClass(i_e,"highlighted")})});addClass(el,"highlighted")},20)}};onEachLazy(document.getElementsByClassName("search-results"),function(e){onEachLazy(e.getElementsByClassName("result"),function(i_e){i_e.onclick=click_func;i_e.onmouseover=mouseover_func})});search_input.onkeydown=function(e){var actives=[[],[],[]];var current=0;onEachLazy(document.getElementById("results").childNodes,function(e){onEachLazy(e.getElementsByClassName("highlighted"),function(e){actives[current].push(e)});current+=1});if(e.which===38){if(!actives[currentTab].length||!actives[currentTab][0].previousElementSibling){return}addClass(actives[currentTab][0].previousElementSibling,"highlighted");removeClass(actives[currentTab][0],"highlighted");e.preventDefault()}else if(e.which===40){if(!actives[currentTab].length){var results=document.getElementById("results").childNodes;if(results.length>0){var res=results[currentTab].getElementsByClassName("result");if(res.length>0){addClass(res[0],"highlighted")}}}else if(actives[currentTab][0].nextElementSibling){addClass(actives[currentTab][0].nextElementSibling,"highlighted");removeClass(actives[currentTab][0],"highlighted")}e.preventDefault()}else if(e.which===13){if(actives[currentTab].length){document.location.href=actives[currentTab][0].getElementsByTagName("a")[0].href}}else if(e.which===9){if(e.shiftKey){printTab(currentTab>0?currentTab-1:2)}else{printTab(currentTab>1?0:currentTab+1)}e.preventDefault()}else if(e.which===16){}else if(actives[currentTab].length>0){removeClass(actives[currentTab][0],"highlighted")}}}function buildHrefAndPath(item){var displayPath;var href;var type=itemTypes[item.ty];var name=item.name;var path=item.path;if(type==="mod"){displayPath=path+"::";href=rootPath+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="primitive"||type==="keyword"){displayPath="";href=rootPath+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=rootPath+name+"/index.html"}else if(item.parent!==undefined){var myparent=item.parent;var anchor="#"+type+"."+name;var parentType=itemTypes[myparent.ty];var pageType=parentType;var pageName=myparent.name;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){var splitPath=item.path.split("::");var enumName=splitPath.pop();path=splitPath.join("::");displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="#variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}href=rootPath+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html"+anchor}else{displayPath=item.path+"::";href=rootPath+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href]}function escape(content){var h1=document.createElement("h1");h1.textContent=content;return h1.innerHTML}function pathSplitter(path){var tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}function addTab(array,query,display){var extraStyle="";if(display===false){extraStyle=" style=\"display: none;\""}var output="";var duplicates={};var length=0;if(array.length>0){output="";array.forEach(function(item){var name,type;name=item.name;type=itemTypes[item.ty];if(item.is_alias!==true){if(duplicates[item.fullPath]){return}duplicates[item.fullPath]=true}length+=1;output+=""});output+="
"+""+(item.is_alias===true?(""+item.alias+"  - see "):"")+item.displayPath+""+name+""+""+""+escape(item.desc)+" 
"}else{output="
No results :(
"+"Try on DuckDuckGo?

"+"Or try looking in one of these:
"}return[output,length]}function makeTabHeader(tabNb,text,nbElems){if(currentTab===tabNb){return"
"+text+"
("+nbElems+")
"}return"
"+text+"
("+nbElems+")
"}function showResults(results){if(results.others.length===1&&getCurrentValue("rustdoc-go-to-only-result")==="true"){var elem=document.createElement("a");elem.href=results.others[0].href;elem.style.display="none";document.body.appendChild(elem);elem.click()}var query=getQuery(search_input.value);currentResults=query.id;var ret_others=addTab(results.others,query);var ret_in_args=addTab(results.in_args,query,false);var ret_returned=addTab(results.returned,query,false);var output="

Results for "+escape(query.query)+(query.type?" (type: "+escape(query.type)+")":"")+"

"+"
"+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
"+ret_others[0]+ret_in_args[0]+ret_returned[0]+"
";var search=getSearchElement();search.innerHTML=output;showSearchResults(search);var tds=search.getElementsByTagName("td");var td_width=0;if(tds.length>0){td_width=tds[0].offsetWidth}var width=search.offsetWidth-40-td_width;onEachLazy(search.getElementsByClassName("desc"),function(e){e.style.width=width+"px"});initSearchNav();var elems=document.getElementById("titles").childNodes;elems[0].onclick=function(){printTab(0)};elems[1].onclick=function(){printTab(1)};elems[2].onclick=function(){printTab(2)};printTab(currentTab)}function execSearch(query,searchWords,filterCrates){function getSmallest(arrays,positions,notDuplicates){var start=null;for(var it=0;itpositions[it]&&(start===null||start>arrays[it][positions[it]].lev)&&!notDuplicates[arrays[it][positions[it]].fullPath]){start=arrays[it][positions[it]].lev}}return start}function mergeArrays(arrays){var ret=[];var positions=[];var notDuplicates={};for(var x=0;xpositions[x]&&arrays[x][positions[x]].lev===smallest&&!notDuplicates[arrays[x][positions[x]].fullPath]){ret.push(arrays[x][positions[x]]);notDuplicates[arrays[x][positions[x]].fullPath]=true;positions[x]+=1}}}return ret}var queries=query.raw.split(",");var results={"in_args":[],"returned":[],"others":[],};for(var i=0;i1){return{"in_args":mergeArrays(results.in_args),"returned":mergeArrays(results.returned),"others":mergeArrays(results.others),}}return{"in_args":results.in_args[0],"returned":results.returned[0],"others":results.others[0],}}function getFilterCrates(){var elem=document.getElementById("crate-search");if(elem&&elem.value!=="All crates"&&hasOwnProperty(rawSearchIndex,elem.value)){return elem.value}return undefined}function search(e,forced){var params=getQueryStringParams();var query=getQuery(search_input.value.trim());if(e){e.preventDefault()}if(query.query.length===0){return}if(forced!==true&&query.id===currentResults){if(query.query.length>0){putBackSearch(search_input)}return}document.title="Results for "+query.query+" - Rust";if(browserSupportsHistoryApi()){if(!history.state&&!params.search){history.pushState(query,"","?search="+encodeURIComponent(query.raw))}else{history.replaceState(query,"","?search="+encodeURIComponent(query.raw))}}var filterCrates=getFilterCrates();showResults(execSearch(query,index,filterCrates))}function buildIndex(rawSearchIndex){searchIndex=[];var searchWords=[];var i;var currentIndex=0;for(var crate in rawSearchIndex){if(!hasOwnProperty(rawSearchIndex,crate)){continue}var crateSize=0;searchWords.push(crate);searchIndex.push({crate:crate,ty:1,name:crate,path:"",desc:rawSearchIndex[crate].doc,type:null,});currentIndex+=1;var items=rawSearchIndex[crate].i;var paths=rawSearchIndex[crate].p;var aliases=rawSearchIndex[crate].a;var len=paths.length;for(i=0;i0){search_input.value=params.search;search(e)}else{search_input.value="";hideSearchResults()}})}search()}index=buildIndex(rawSearchIndex);startSearch();if(rootPath==="../"||rootPath==="./"){var sidebar=document.getElementsByClassName("sidebar-elems")[0];if(sidebar){var div=document.createElement("div");div.className="block crate";div.innerHTML="

Crates

";var ul=document.createElement("ul");div.appendChild(ul);var crates=[];for(var crate in rawSearchIndex){if(!hasOwnProperty(rawSearchIndex,crate)){continue}crates.push(crate)}crates.sort();for(var i=0;i"+""+"
"+code.outerHTML+"
";list.appendChild(display)}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}function labelForToggleButton(sectionIsCollapsed){if(sectionIsCollapsed){return"+"}return"\u2212"}function onEveryMatchingChild(elem,className,func){if(elem&&className&&func){var length=elem.childNodes.length;var nodes=elem.childNodes;for(var i=0;i"+labelForToggleButton(sectionIsCollapsed)+"
]";return toggle}function createToggle(toggle,otherMessage,fontSize,extraClass,show){var span=document.createElement("span");span.className="toggle-label";if(show){span.style.display="none"}if(!otherMessage){span.innerHTML=" Expand description"}else{span.innerHTML=otherMessage}if(fontSize){span.style.fontSize=fontSize}var mainToggle=toggle.cloneNode(true);mainToggle.appendChild(span);var wrapper=document.createElement("div");wrapper.className="toggle-wrapper";if(!show){addClass(wrapper,"collapsed");var inner=mainToggle.getElementsByClassName("inner");if(inner&&inner.length>0){inner[0].innerHTML="+"}}if(extraClass){addClass(wrapper,extraClass)}wrapper.appendChild(mainToggle);return wrapper}(function(){var toggle=createSimpleToggle(false);var hideMethodDocs=getCurrentValue("rustdoc-auto-hide-method-docs")==="true";var pageId=getPageId();var func=function(e){var next=e.nextElementSibling;if(!next){return}if(hasClass(next,"docblock")===true||(hasClass(next,"stability")===true&&hasClass(next.nextElementSibling,"docblock")===true)){var newToggle=toggle.cloneNode(true);insertAfter(newToggle,e.childNodes[e.childNodes.length-1]);if(hideMethodDocs===true&&hasClass(e,"method")===true){collapseDocs(newToggle,"hide",pageId)}}};var funcImpl=function(e){var next=e.nextElementSibling;if(next&&hasClass(next,"docblock")){next=next.nextElementSibling}if(!next){return}if(hasClass(e,"impl")&&(next.getElementsByClassName("method").length>0||next.getElementsByClassName("associatedconstant").length>0)){insertAfter(toggle.cloneNode(true),e.childNodes[e.childNodes.length-1])}};onEachLazy(document.getElementsByClassName("method"),func);onEachLazy(document.getElementsByClassName("associatedconstant"),func);onEachLazy(document.getElementsByClassName("impl"),funcImpl);var impl_call=function(){};if(hideMethodDocs===true){impl_call=function(e,newToggle){if(e.id.match(/^impl(?:-\d+)?$/)===null){if(hasClass(e,"impl")===true){collapseDocs(newToggle,"hide",pageId)}}}}var newToggle=document.createElement("a");newToggle.href="javascript:void(0)";newToggle.className="collapse-toggle hidden-default collapsed";newToggle.innerHTML="["+labelForToggleButton(true)+"] Show hidden undocumented items";function toggleClicked(){if(hasClass(this,"collapsed")){removeClass(this,"collapsed");onEachLazy(this.parentNode.getElementsByClassName("hidden"),function(x){if(hasClass(x,"content")===false){removeClass(x,"hidden");addClass(x,"x")}},true);this.innerHTML="["+labelForToggleButton(false)+"] Hide undocumented items"}else{addClass(this,"collapsed");onEachLazy(this.parentNode.getElementsByClassName("x"),function(x){if(hasClass(x,"content")===false){addClass(x,"hidden");removeClass(x,"x")}},true);this.innerHTML="["+labelForToggleButton(true)+"] Show hidden undocumented items"}}onEachLazy(document.getElementsByClassName("impl-items"),function(e){onEachLazy(e.getElementsByClassName("associatedconstant"),func);var hiddenElems=e.getElementsByClassName("hidden");var needToggle=false;var hlength=hiddenElems.length;for(var i=0;iLoading search results...";showSearchResults(search)}var sidebar_menu=document.getElementsByClassName("sidebar-menu")[0];if(sidebar_menu){sidebar_menu.onclick=function(){var sidebar=document.getElementsByClassName("sidebar")[0];if(hasClass(sidebar,"mobile")===true){hideSidebar()}else{showSidebar()}}}window.onresize=function(){hideSidebar()};if(main){onEachLazy(main.getElementsByClassName("loading-content"),function(e){e.remove()});onEachLazy(main.childNodes,function(e){if(e.tagName==="H2"||e.tagName==="H3"){var nextTagName=e.nextElementSibling.tagName;if(nextTagName=="H2"||nextTagName=="H3"){e.nextElementSibling.style.display="flex"}else{e.nextElementSibling.style.display="block"}}})}window.addSearchOptions=function(crates){var elem=document.getElementById("crate-search");if(!elem){return}var crates_text=[];if(Object.keys(crates).length>1){for(var crate in crates){if(hasOwnProperty(crates,crate)){crates_text.push(crate)}}}crates_text.sort(function(a,b){var lower_a=a.toLowerCase();var lower_b=b.toLowerCase();if(lower_alower_b){return 1}return 0});var savedCrate=getCurrentValue("rustdoc-saved-filter-crate");for(var i=0;i"
"+x[0]+"
"+x[1]+"
").join("");var div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

Keyboard Shortcuts

"+shortcuts+"
";var infos=["Prefix searches with a type followed by a colon (e.g., fn:) to \ - restrict the search to a given type.","Accepted types are: fn, mod, struct, \ - enum, trait, type, macro, \ - and const.","Search functions by type signature (e.g., vec -> usize or \ - * -> vec)","Search multiple things at once by splitting your query with comma (e.g., \ - str,u8 or String,struct:Vec,test)","You can look for items with an exact name by putting double quotes around \ - your request: \"string\"","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

"+x+"

").join("");var div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

Search Tricks

"+infos;container.appendChild(div_shortcuts);container.appendChild(div_infos);popup.appendChild(container);insertAfter(popup,getSearchElement())}onHashChange(null);window.onhashchange=onHashChange;buildHelperPopup()}());window.onunload=function(){} \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/normalize.css b/static/docs-rs/magical/0.1.0-beta.1/normalize.css deleted file mode 100644 index 45b6cb2638..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/normalize.css +++ /dev/null @@ -1,2 +0,0 @@ -/*! normalize.css v3.0.0 | MIT License | git.io/normalize */ -html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/noscript.css b/static/docs-rs/magical/0.1.0-beta.1/noscript.css deleted file mode 100644 index 351b41cf8e..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/noscript.css +++ /dev/null @@ -1 +0,0 @@ -#main>h2+div,#main>h2+h3,#main>h3+div{display:block;}.loading-content{display:none;}#main>h2+div,#main>h3+div{display:block;}#main>h2+h3{display:flex;} \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/rust-logo.png b/static/docs-rs/magical/0.1.0-beta.1/rust-logo.png deleted file mode 100644 index 74b4bd6950..0000000000 Binary files a/static/docs-rs/magical/0.1.0-beta.1/rust-logo.png and /dev/null differ diff --git a/static/docs-rs/magical/0.1.0-beta.1/rustdoc.css b/static/docs-rs/magical/0.1.0-beta.1/rustdoc.css deleted file mode 100644 index cbf40b2271..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/rustdoc.css +++ /dev/null @@ -1 +0,0 @@ - @font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular.woff") format('woff');}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:normal;font-weight:400;src:local('Source Serif Pro'),url("SourceSerifPro-Regular.ttf.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:italic;font-weight:400;src:local('Source Serif Pro Italic'),url("SourceSerifPro-It.ttf.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:normal;font-weight:700;src:local('Source Serif Pro Bold'),url("SourceSerifPro-Bold.ttf.woff") format('woff');}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular.woff") format('woff');}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold.woff") format('woff');}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}html{content:"";}@media (prefers-color-scheme:light){html{content:"light";}}@media (prefers-color-scheme:dark){html{content:"dark";}}body{font:16px/1.4 "Source Serif Pro",serif;margin:0;position:relative;padding:10px 15px 20px 15px;-webkit-font-feature-settings:"kern","liga";-moz-font-feature-settings:"kern","liga";font-feature-settings:"kern","liga";}h1{font-size:1.5em;}h2{font-size:1.4em;}h3{font-size:1.3em;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.important),h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){font-weight:500;margin:20px 0 15px 0;padding-bottom:6px;}h1.fqn{border-bottom:1px dashed;margin-top:0;}h1.fqn>.in-band>a:hover{text-decoration:underline;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){border-bottom:1px solid;}h3.impl,h3.method,h4.method,h3.type,h4.type,h4.associatedconstant{flex-basis:100%;font-weight:600;margin-top:16px;margin-bottom:10px;position:relative;}h3.impl,h3.method,h3.type{padding-left:15px;}h1,h2,h3,h4,.sidebar,a.source,.search-input,.content table :not(code)>a,.collapse-toggle,div.item-list .out-of-band,#source-sidebar,#sidebar-toggle{font-family:"Fira Sans",sans-serif;}ol,ul{padding-left:25px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.6em;}p{margin:0 0 .6em 0;}summary{outline:none;}code,pre,a.test-arrow{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.1em;}.docblock pre code,.docblock-short pre code{padding:0;}pre{padding:14px;}.source .content pre{padding:20px;}img{max-width:100%;}li{position:relative;}.source .content{margin-top:50px;max-width:none;overflow:visible;margin-left:0px;min-width:70em;}nav.sub{font-size:16px;text-transform:uppercase;}.sidebar{width:200px;position:fixed;left:0;top:0;bottom:0;overflow:auto;}*{scrollbar-width:initial;}.sidebar{scrollbar-width:thin;}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;}.sidebar .block>ul>li{margin-right:-10px;}.content,nav{max-width:960px;}.hidden{display:none !important;}.logo-container{height:100px;width:100px;position:relative;margin:20px auto;display:block;margin-top:10px;}.logo-container>img{max-width:100px;max-height:100px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:block;}.sidebar .location{border:1px solid;font-size:17px;margin:30px 10px 20px 10px;text-align:center;word-wrap:break-word;}.sidebar .version{font-size:15px;text-align:center;border-bottom:1px solid;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;}.location:empty{border:none;}.location a:first-child{font-weight:500;}.block{padding:0;margin-bottom:14px;}.block h2,.block h3{margin-top:0;margin-bottom:8px;text-align:center;}.block ul,.block li{margin:0 10px;padding:0;list-style:none;}.block a{display:block;text-overflow:ellipsis;overflow:hidden;line-height:15px;padding:7px 5px;font-size:14px;font-weight:300;transition:border 500ms ease-out;}.sidebar-title{border-top:1px solid;border-bottom:1px solid;text-align:center;font-size:17px;margin-bottom:5px;}.sidebar-links{margin-bottom:15px;}.sidebar-links>a{padding-left:10px;width:100%;}.sidebar-menu{display:none;}.content{padding:15px 0;}.source .content pre.rust{white-space:pre;overflow:auto;padding-left:0;}.rustdoc:not(.source) .example-wrap{display:inline-flex;margin-bottom:10px;position:relative;}.example-wrap{width:100%;}.example-wrap>pre.line-number{overflow:initial;border:1px solid;border-top-left-radius:5px;border-bottom-left-radius:5px;padding:13px 8px;text-align:right;}.rustdoc:not(.source) .example-wrap>pre.rust{width:100%;overflow-x:auto;}.rustdoc:not(.source) .example-wrap>pre{margin:0;}#search{margin-left:230px;position:relative;}#results{position:absolute;right:0;left:0;overflow:auto;}#results>table{width:100%;table-layout:fixed;}.content pre.line-numbers{float:left;border:none;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}.line-numbers span{cursor:pointer;}.docblock-short p{display:inline;}.docblock-short.nowrap{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.docblock-short p{overflow:hidden;text-overflow:ellipsis;margin:0;}.docblock code,.docblock-short code{white-space:pre-wrap;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom:1px solid;}#main>.docblock h1{font-size:1.3em;}#main>.docblock h2{font-size:1.15em;}#main>.docblock h3,#main>.docblock h4,#main>.docblock h5{font-size:1em;}#main>h2+div,#main>h2+h3,#main>h3+div{display:none;flex-wrap:wrap;}.docblock h1{font-size:1em;}.docblock h2{font-size:0.95em;}.docblock h3,.docblock h4,.docblock h5{font-size:0.9em;}.docblock{margin-left:24px;position:relative;}.content .out-of-band{float:right;font-size:23px;margin:0px;padding:0px;font-weight:normal;}h3.impl>.out-of-band{font-size:21px;}h4.method>.out-of-band{font-size:19px;}h4>code,h3>code,.invisible>code{max-width:calc(100% - 41px);display:block;}.invisible{width:100%;display:inline-block;}.content .in-band{margin:0px;padding:0px;}.in-band>code{display:inline-block;}#main{position:relative;}#main>.since{top:inherit;font-family:"Fira Sans",sans-serif;}.content table:not(.table-display){border-spacing:0 5px;}.content td{vertical-align:top;}.content td:first-child{padding-right:20px;}.content td p:first-child{margin-top:0;}.content td h1,.content td h2{margin-left:0;font-size:1.1em;}.content tr:first-child td{border-top:0;}.docblock table{margin:.5em 0;width:calc(100% - 2px);border:1px dashed;}.docblock table td{padding:.5em;border:1px dashed;}.docblock table th{padding:.5em;text-align:left;border:1px solid;}.fields+table{margin-bottom:1em;}.content .item-list{list-style-type:none;padding:0;}.content .multi-column{-moz-column-count:5;-moz-column-gap:2.5em;-webkit-column-count:5;-webkit-column-gap:2.5em;column-count:5;column-gap:2.5em;}.content .multi-column li{width:100%;display:inline-block;}.content .method{font-size:1em;position:relative;}.content .method .where,.content .fn .where,.content .where.fmt-newline{display:block;font-size:0.8em;}.content .methods>div{margin-left:40px;margin-bottom:15px;}.content .docblock>.impl-items{margin-left:20px;margin-top:-34px;}.content .docblock>.impl-items>h4{border-bottom:0;}.content .docblock>.impl-items .table-display{margin:0;}.content .docblock>.impl-items table td{padding:0;}.toggle-wrapper.marg-left>.collapse-toggle{left:-24px;}.content .docblock>.impl-items .table-display,.impl-items table td{border:none;}.content .stability code{font-size:90%;}.content .stability{position:relative;margin-left:33px;margin-top:-13px;}.sub-variant>div>.stability{margin-top:initial;}.content .stability::before{content:'⬑';font-size:25px;position:absolute;top:-6px;left:-19px;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant{margin-left:20px;}.content .impl-items .docblock,.content .impl-items .stability{margin-bottom:.6em;}.content .impl-items>.stability{margin-left:40px;}.methods>.stability,.content .impl-items>.stability{margin-top:-8px;}.impl-items{flex-basis:100%;}#main>.stability{margin-top:0;}nav:not(.sidebar){border-bottom:1px solid;padding-bottom:10px;margin-bottom:10px;}nav.main{padding:20px 0;text-align:center;}nav.main .current{border-top:1px solid;border-bottom:1px solid;}nav.main .separator{border:1px solid;display:inline-block;height:23px;margin:0 20px;}nav.sum{text-align:right;}nav.sub form{display:inline;}nav.sub,.content{margin-left:230px;}a{text-decoration:none;background:transparent;}.small-section-header:hover>.anchor{display:initial;}.in-band:hover>.anchor,.impl:hover>.anchor{display:inline-block;position:absolute;}.anchor{display:none;position:absolute;left:-7px;}.anchor.field{left:-5px;}.small-section-header>.anchor{left:-28px;padding-right:10px;}.anchor:before{content:'\2002\00a7\2002';}.docblock a:not(.srclink):not(.test-arrow):hover,.docblock-short a:not(.srclink):not(.test-arrow):hover,.stability a{text-decoration:underline;}.invisible>.srclink,h4>code+.srclink{position:absolute;top:0;right:0;font-size:17px;font-weight:normal;}.block a.current.crate{font-weight:500;}.search-container{position:relative;}.search-container>div{display:inline-flex;width:calc(100% - 34px);}#crate-search{margin-top:5px;padding:6px;padding-right:19px;flex:none;border:0;border-right:0;border-radius:4px 0 0 4px;outline:none;cursor:pointer;border-right:1px solid;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;text-overflow:"";background-repeat:no-repeat;background-color:transparent;background-size:20px;background-position:calc(100% - 1px) 56%;}.search-container>.top-button{position:absolute;right:0;top:10px;}.search-input{-moz-box-sizing:border-box !important;box-sizing:border-box !important;outline:none;border:none;border-radius:1px;margin-top:5px;padding:10px 16px;font-size:17px;transition:border-color 300ms ease;transition:border-radius 300ms ease-in-out;transition:box-shadow 300ms ease-in-out;width:100%;}#crate-search+.search-input{border-radius:0 1px 1px 0;width:calc(100% - 32px);}.search-input:focus{border-radius:2px;border:0;outline:0;}.search-results .desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;display:block;}.search-results a{display:block;}.content .search-results td:first-child{padding-right:0;width:50%;}.content .search-results td:first-child a{padding-right:10px;}.content .search-results td:first-child a:after{clear:both;content:"";display:block;}.content .search-results td:first-child a span{float:left;}tr.result span.primitive::after{content:' (primitive type)';font-style:italic;}tr.result span.keyword::after{content:' (keyword)';font-style:italic;}body.blur>:not(#help){filter:blur(8px);-webkit-filter:blur(8px);opacity:.7;}#help{width:100%;height:100vh;position:fixed;top:0;left:0;display:flex;justify-content:center;align-items:center;}#help>div{flex:0 0 auto;box-shadow:0 0 6px rgba(0,0,0,.2);width:550px;height:auto;border:1px solid;}#help dt{float:left;clear:left;display:block;}#help dd{margin:5px 35px;}#help .infos{padding-left:0;}#help h1,#help h2{margin-top:0;}#help>div div{width:50%;float:left;padding:20px;padding-left:17px;}.stab{display:table;border-width:1px;border-style:solid;padding:3px;margin-bottom:5px;font-size:90%;}.stab p{display:inline;}.stab summary{display:list-item;}.stab .emoji{font-size:1.5em;}.module-item .stab{border-radius:3px;display:inline-block;font-size:80%;line-height:1.2;margin-bottom:0;margin-right:.3em;padding:2px;vertical-align:text-bottom;}.module-item.unstable{opacity:0.65;}.since{font-weight:normal;font-size:initial;position:absolute;right:0;top:0;}.impl-items .since,.impl .since{flex-grow:0;padding-left:12px;padding-right:2px;position:initial;}.impl-items .srclink,.impl .srclink{flex-grow:0;font-size:17px;font-weight:normal;}.impl-items code,.impl code{flex-grow:1;}.impl-items h4,h4.impl,h3.impl{display:flex;flex-basis:100%;font-size:16px;margin-bottom:12px;justify-content:space-between;}.variants_table{width:100%;}.variants_table tbody tr td:first-child{width:1%;}td.summary-column{width:100%;}.summary{padding-right:0px;}pre.rust .question-mark{font-weight:bold;}a.test-arrow{display:inline-block;position:absolute;padding:5px 10px 5px 10px;border-radius:5px;font-size:130%;top:5px;right:5px;z-index:1;}a.test-arrow:hover{text-decoration:none;}.section-header:hover a:before{position:absolute;left:-25px;padding-right:10px;content:'\2002\00a7\2002';}.section-header:hover a{text-decoration:none;}.section-header a{color:inherit;}.collapse-toggle{font-weight:300;position:absolute;left:-23px;top:0;}h3>.collapse-toggle,h4>.collapse-toggle{font-size:0.8em;top:5px;}.toggle-wrapper>.collapse-toggle{left:-24px;margin-top:0px;}.toggle-wrapper{position:relative;margin-top:0;}.toggle-wrapper.collapsed{height:25px;transition:height .2s;margin-bottom:.6em;}.collapse-toggle>.inner{display:inline-block;width:1.2ch;text-align:center;}.collapse-toggle.hidden-default{position:relative;margin-left:20px;}.since+.srclink{display:table-cell;padding-left:10px;}.item-spacer{width:100%;height:12px;}.out-of-band>span.since{position:initial;font-size:20px;margin-right:5px;}.toggle-wrapper>.collapse-toggle{left:0;}.variant+.toggle-wrapper+.docblock>p{margin-top:5px;}.sub-variant,.sub-variant>h3{margin-top:1px !important;}#main>.sub-variant>h3{font-size:15px;margin-left:25px;margin-bottom:5px;}.sub-variant>div{margin-left:20px;margin-bottom:10px;}.sub-variant>div>span{display:block;position:relative;}.toggle-label{display:inline-block;margin-left:4px;margin-top:3px;}.enum>.toggle-wrapper+.docblock,.struct>.toggle-wrapper+.docblock{margin-left:30px;margin-bottom:20px;margin-top:5px;}.docblock>.section-header:first-child{margin-left:15px;margin-top:0;}.docblock>.section-header:first-child:hover>a:before{left:-10px;}.enum>.collapsed,.struct>.collapsed{margin-bottom:25px;}#main>.variant,#main>.structfield{display:block;}.attributes{display:block;margin-top:0px !important;margin-right:0px;margin-bottom:0px !important;margin-left:30px;}.toggle-attributes.collapsed{margin-bottom:0;}.impl-items>.toggle-attributes{margin-left:20px;}.impl-items .attributes{font-weight:500;}:target>code{opacity:1;}.information{position:absolute;left:-25px;margin-top:7px;z-index:1;}.tooltip{position:relative;display:inline-block;cursor:pointer;}.tooltip .tooltiptext{width:120px;display:none;text-align:center;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;top:-5px;left:105%;z-index:10;font-size:16px;}.tooltip:hover .tooltiptext{display:inline;}.tooltip .tooltiptext::after{content:" ";position:absolute;top:50%;left:16px;margin-top:-5px;border-width:5px;border-style:solid;}.tooltip.compile_fail,.tooltip.should_panic,.tooltip.ignore{font-weight:bold;font-size:20px;}.tooltip .tooltiptext{border:1px solid;font-weight:normal;}pre.rust{position:relative;tab-size:4;-moz-tab-size:4;}.search-failed{text-align:center;margin-top:20px;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#titles{height:35px;}#titles>div{float:left;width:33.3%;text-align:center;font-size:18px;cursor:pointer;border-top:2px solid;}#titles>div:not(:last-child){margin-right:1px;width:calc(33.3% - 1px);}#titles>div>div.count{display:inline-block;font-size:16px;}#all-types{text-align:center;border:1px solid;margin:0 10px;margin-bottom:10px;display:block;border-radius:7px;}#all-types>p{margin:5px 0;}#sidebar-toggle{position:fixed;top:30px;left:300px;z-index:10;padding:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;cursor:pointer;font-weight:bold;transition:left .5s;font-size:1.2em;border:1px solid;border-left:0;}#source-sidebar{position:fixed;top:0;bottom:0;left:0;width:300px;z-index:1;overflow:auto;transition:left .5s;border-right:1px solid;}#source-sidebar>.title{font-size:1.5em;text-align:center;border-bottom:1px solid;margin-bottom:6px;}.theme-picker{position:absolute;left:211px;top:19px;}.theme-picker button{outline:none;}#settings-menu{position:absolute;right:0;top:10px;outline:none;}#theme-picker,#settings-menu{padding:4px;width:27px;height:29px;border:1px solid;border-radius:3px;cursor:pointer;}#theme-choices{display:none;position:absolute;left:0;top:28px;border:1px solid;border-radius:3px;z-index:1;cursor:pointer;}#theme-choices>button{border:none;width:100%;padding:4px;text-align:center;background:rgba(0,0,0,0);}#theme-choices>button:not(:first-child){border-top:1px solid;}@media (max-width:700px){body{padding-top:0px;}.rustdoc>.sidebar{height:45px;min-height:40px;margin:0;margin-left:-15px;padding:0 15px;position:static;z-index:11;}.sidebar>.location{float:right;margin:0px;margin-top:2px;padding:3px 10px 1px 10px;min-height:39px;background:inherit;text-align:left;font-size:24px;}.sidebar .location:empty{padding:0;}.sidebar .logo-container{width:35px;height:35px;margin-top:5px;margin-bottom:5px;float:left;margin-left:50px;}.sidebar .logo-container>img{max-width:35px;max-height:35px;}.sidebar-menu{position:fixed;z-index:10;font-size:2rem;cursor:pointer;width:45px;left:0;text-align:center;display:block;border-bottom:1px solid;border-right:1px solid;height:45px;}.rustdoc.source>.sidebar>.sidebar-menu{display:none;}.sidebar-elems{position:fixed;z-index:1;left:0;top:45px;bottom:0;overflow-y:auto;border-right:1px solid;display:none;}.sidebar>.block.version{border-bottom:none;margin-top:12px;}nav.sub{width:calc(100% - 32px);float:right;}.content{margin-left:0px;}#main{margin-top:45px;padding:0;}.content .in-band{width:100%;}.content h4>.out-of-band{position:inherit;}.toggle-wrapper>.collapse-toggle{left:0px;}.toggle-wrapper{height:1.5em;}#search{margin-left:0;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant{display:flex;}.anchor{display:none !important;}h1.fqn{overflow:initial;}.theme-picker{left:10px;top:54px;z-index:1;}#titles>div>div.count{float:left;width:100%;}#titles{height:50px;}.sidebar.mobile{position:fixed;width:100%;margin-left:0;background-color:rgba(0,0,0,0);height:100%;}.sidebar{width:calc(100% + 30px);}.show-it{display:block;width:246px;}.show-it>.block.items{margin:8px 0;}.show-it>.block.items>ul{margin:0;}.show-it>.block.items>ul>li{text-align:center;margin:2px 0;}.show-it>.block.items>ul>li>a{font-size:21px;}#sidebar-filler{position:fixed;left:45px;width:calc(100% - 45px);top:0;height:45px;z-index:-1;border-bottom:1px solid;}.collapse-toggle{left:-20px;}.impl>.collapse-toggle{left:-10px;}#all-types{margin:10px;}#sidebar-toggle{top:100px;width:30px;font-size:1.5rem;text-align:center;padding:0;}#source-sidebar{z-index:11;}#main>.line-numbers{margin-top:0;}}@media print{nav.sub,.content .out-of-band,.collapse-toggle{display:none;}}@media (max-width:416px){#titles{height:73px;}#titles>div{height:73px;}}h3.important{margin:0;margin-bottom:13px;font-size:19px;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px;border-radius:3px;box-shadow:inset 0 -1px 0;cursor:default;}.hidden-by-impl-hider,.hidden-by-usual-hider{display:none !important;}#implementations-list>h3>span.in-band{width:100%;}.table-display{width:100%;border:0;border-collapse:collapse;border-spacing:0;font-size:16px;}.table-display tr td:first-child{padding-right:0;}.table-display tr td:last-child{float:right;}.table-display .out-of-band{position:relative;font-size:19px;display:block;}#implementors-list>.impl-items .table-display .out-of-band{font-size:17px;}.table-display td:hover .anchor{display:block;top:2px;left:-5px;}#main>ul{padding-left:10px;}#main>ul>li{list-style:none;}.non-exhaustive{margin-bottom:1em;}div.children{padding-left:27px;display:none;}div.name{cursor:pointer;position:relative;margin-left:16px;}div.files>a{display:block;padding:0 3px;}div.files>a:hover,div.name:hover{background-color:#a14b4b;}div.name.expand+.children{display:block;}div.name::before{content:"\25B6";padding-left:4px;font-size:0.7em;position:absolute;left:-16px;top:4px;}div.name.expand::before{transform:rotate(90deg);left:-15px;top:2px;}.type-decl>pre>.toggle-wrapper.toggle-attributes.top-attr{margin-left:0 !important;}.type-decl>pre>.docblock.attributes.top-attr{margin-left:1.8em !important;}.type-decl>pre>.toggle-attributes{margin-left:2.2em;}.type-decl>pre>.docblock.attributes{margin-left:4em;} \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/search-index.js b/static/docs-rs/magical/0.1.0-beta.1/search-index.js deleted file mode 100644 index 4715c5c29d..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/search-index.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchIndex = JSON.parse('{\ -"magical":{"doc":"","i":[[3,"FeeRate","magical","Fee rate",null,null],[3,"UTXO","","A wallet unspent output",null,null],[12,"outpoint","","",0,null],[12,"txout","","",0,null],[12,"is_internal","","",0,null],[3,"TransactionDetails","","A wallet transaction",null,null],[12,"transaction","","",1,null],[12,"txid","","",1,null],[12,"timestamp","","",1,null],[12,"received","","",1,null],[12,"sent","","",1,null],[12,"fees","","",1,null],[12,"height","","",1,null],[4,"Error","","Errors that can be thrown by the `Wallet`",null,null],[13,"KeyMismatch","","",2,null],[13,"MissingInputUTXO","","",2,null],[13,"InvalidU32Bytes","","",2,null],[13,"Generic","","",2,null],[13,"ScriptDoesntHaveAddressForm","","",2,null],[13,"SendAllMultipleOutputs","","",2,null],[13,"NoAddressees","","",2,null],[13,"OutputBelowDustLimit","","",2,null],[13,"InsufficientFunds","","",2,null],[13,"InvalidAddressNetwork","","",2,null],[13,"UnknownUTXO","","",2,null],[13,"DifferentTransactions","","",2,null],[13,"TransactionNotFound","","",2,null],[13,"TransactionConfirmed","","",2,null],[13,"IrreplaceableTransaction","","",2,null],[13,"FeeRateTooLow","","",2,null],[12,"required","magical::Error","",3,null],[13,"ChecksumMismatch","magical","",2,null],[13,"DifferentDescriptorStructure","","",2,null],[13,"SpendingPolicyRequired","","",2,null],[13,"InvalidPolicyPathError","","",2,null],[13,"Signer","","",2,null],[13,"Uncapable","","",2,null],[13,"OfflineClient","","",2,null],[13,"InvalidProgressValue","","",2,null],[13,"ProgressUpdateError","","",2,null],[13,"MissingCachedAddresses","","",2,null],[13,"InvalidOutpoint","","",2,null],[13,"Descriptor","","",2,null],[13,"AddressValidator","","",2,null],[13,"Encode","","",2,null],[13,"Miniscript","","",2,null],[13,"BIP32","","",2,null],[13,"Secp256k1","","",2,null],[13,"JSON","","",2,null],[13,"Hex","","",2,null],[13,"PSBT","","",2,null],[13,"Electrum","","",2,null],[13,"Esplora","","",2,null],[13,"CompactFilters","","",2,null],[13,"Sled","","",2,null],[4,"ScriptType","","Types of script",null,null],[13,"External","","",4,null],[13,"Internal","","",4,null],[0,"blockchain","","Blockchain backends",null,null],[3,"OfflineBlockchain","magical::blockchain","Type that only implements [`Blockchain`] and is always…",null,null],[3,"NoopProgress","","Type that implements [`Progress`] and drops every update…",null,null],[3,"LogProgress","","Type that implements [`Progress`] and logs at level `INFO`…",null,null],[4,"Capability","","Capabilities that can be supported by an…",null,null],[13,"FullHistory","","Can recover the full history of a wallet and not only the…",5,null],[13,"GetAnyTx","","Can fetch any historical transaction given its txid",5,null],[13,"AccurateFees","","Can compute accurate fees for the transactions found…",5,null],[5,"progress","","Shortcut to create a [`channel`] (pair of [`Sender`] and…",null,[[]]],[5,"noop_progress","","Create a new instance of [`NoopProgress`]",null,[[],["noopprogress",3]]],[5,"log_progress","","Create a nwe instance of [`LogProgress`]",null,[[],["logprogress",3]]],[0,"electrum","","Electrum",null,null],[3,"ElectrumBlockchain","magical::blockchain::electrum","Wrapper over an Electrum Client that implements the…",null,null],[0,"esplora","magical::blockchain","Esplora",null,null],[3,"EsploraBlockchain","magical::blockchain::esplora","Structure that implements the logic to sync with Esplora",null,null],[4,"EsploraError","","Errors that can happen during a sync with…",null,null],[13,"Reqwest","","Error with the HTTP call",6,null],[13,"Parsing","","Invalid number returned",6,null],[13,"BitcoinEncoding","","Invalid Bitcoin data returned",6,null],[13,"TransactionNotFound","","Transaction not found",6,null],[11,"new","","Create a new instance of the client from a base URL",7,[[]]],[0,"compact_filters","magical::blockchain","Compact Filters",null,null],[3,"Mempool","magical::blockchain::compact_filters","Container for unconfirmed, but valid Bitcoin transactions",null,null],[3,"Peer","","A Bitcoin peer",null,null],[3,"CompactFiltersBlockchain","","Structure implementing the required blockchain traits",null,null],[4,"CompactFiltersError","","An error that can occur during sync with a…",null,null],[13,"InvalidResponse","","A peer sent an invalid or unexpected response",8,null],[13,"InvalidHeaders","","The headers returned are invalid",8,null],[13,"InvalidFilterHeader","","The compact filter headers returned are invalid",8,null],[13,"InvalidFilter","","The compact filter returned is invalid",8,null],[13,"MissingBlock","","The peer is missing a block in the valid chain",8,null],[13,"DataCorruption","","The data stored in the block filters storage are corrupted",8,null],[13,"NotConnected","","A peer is not connected",8,null],[13,"Timeout","","A peer took too long to reply to one of our messages",8,null],[13,"NoPeers","","No peers have been specified",8,null],[13,"DB","","Internal database error",8,null],[13,"IO","","Internal I/O error",8,null],[13,"BIP158","","Invalid BIP158 filter",8,null],[13,"Time","","Internal system time error",8,null],[13,"Global","","Wrapper for [`crate::error::Error`]",8,null],[11,"add_tx","","Add a transaction to the mempool",9,[[["transaction",3]]]],[11,"get_tx","","Look-up a transaction in the mempool given an…",9,[[["inventory",4]],[["option",4],["transaction",3]]]],[11,"has_tx","","Return whether or not the mempool contains a transaction…",9,[[["txid",3]]]],[11,"iter_txs","","Return the list of transactions contained in the mempool",9,[[],[["transaction",3],["vec",3]]]],[11,"connect","","Connect to a peer over a plaintext TCP connection",10,[[["mempool",3],["tosocketaddrs",8],["arc",3],["network",4]],[["result",4],["compactfilterserror",4]]]],[11,"connect_proxy","","Connect to a peer through a SOCKS5 proxy, optionally by…",10,[[["mempool",3],["tosocketaddrs",8],["option",4],["totargetaddr",8],["arc",3],["network",4]],[["result",4],["compactfilterserror",4]]]],[11,"get_version","","Return the [`VersionMessage`] sent by the peer",10,[[],["versionmessage",3]]],[11,"get_network","","Return the Bitcoin [`Network`] in use",10,[[],["network",4]]],[11,"get_mempool","","Return the mempool used by this peer",10,[[],[["mempool",3],["arc",3]]]],[11,"is_connected","","Return whether or not the peer is still connected",10,[[]]],[11,"send","","Send a raw Bitcoin message to the peer",10,[[["networkmessage",4]],[["result",4],["compactfilterserror",4]]]],[11,"recv","","Waits for a specific incoming Bitcoin message, optionally…",10,[[["option",4],["duration",3]],[["result",4],["compactfilterserror",4],["option",4]]]],[11,"new","","Construct a new instance given a list of peers, a path to…",11,[[["asref",8],["option",4],["peer",3],["vec",3],["path",3]],[["result",4],["compactfilterserror",4]]]],[6,"ProgressData","magical::blockchain","Data sent with a progress update over a [`channel`]",null,null],[8,"Blockchain","","Base trait for a blockchain backend",null,null],[10,"is_online","","Return whether or not the client has the ability to…",12,[[]]],[10,"offline","","Create a new instance of the client that is offline-only",12,[[]]],[8,"OnlineBlockchain","","Trait that defines the actions that must be supported by…",null,null],[10,"get_capabilities","","Return the set of [`Capability`] supported by this backend",13,[[],[["hashset",3],["capability",4]]]],[10,"setup","","Setup the backend and populate the internal database for…",13,[[["option",4],["progress",8]],[["error",4],["result",4]]]],[11,"sync","","Populate the internal database with transactions and UTXOs",13,[[["option",4],["progress",8]],[["error",4],["result",4]]]],[10,"get_tx","","Fetch a transaction from the blockchain given its txid",13,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"broadcast","","Broadcast a transaction",13,[[["transaction",3]],[["error",4],["result",4]]]],[10,"get_height","","Return the current height",13,[[],[["result",4],["error",4]]]],[10,"estimate_fee","","Estimate the fee rate required to confirm a transaction in…",13,[[],[["result",4],["feerate",3],["error",4]]]],[8,"Progress","","Trait for types that can receive and process progress…",null,null],[10,"update","","Send a new progress update",14,[[["string",3],["option",4]],[["error",4],["result",4]]]],[0,"database","magical","Database types",null,null],[0,"memory","magical::database","In-memory ephemeral database",null,null],[3,"MemoryDatabase","magical::database::memory","In-memory ephemeral database",null,null],[11,"new","","Create a new empty database",15,[[]]],[8,"BatchOperations","magical::database","Trait for operations that can be batched",null,null],[10,"set_script_pubkey","","Store a script_pubkey along with its script type and child…",16,[[["script",3],["scripttype",4]],[["error",4],["result",4]]]],[10,"set_utxo","","Store a [`UTXO`]",16,[[["utxo",3]],[["error",4],["result",4]]]],[10,"set_raw_tx","","Store a raw transaction",16,[[["transaction",3]],[["error",4],["result",4]]]],[10,"set_tx","","Store the metadata of a transaction",16,[[["transactiondetails",3]],[["error",4],["result",4]]]],[10,"set_last_index","","Store the last derivation index for a given script type",16,[[["scripttype",4]],[["error",4],["result",4]]]],[10,"del_script_pubkey_from_path","","Delete a script_pubkey given the script type and its child…",16,[[["scripttype",4]],[["error",4],["result",4],["option",4]]]],[10,"del_path_from_script_pubkey","","Delete the data related to a specific script_pubkey,…",16,[[["script",3]],[["result",4],["option",4],["error",4]]]],[10,"del_utxo","","Delete a [`UTXO`] given its [`OutPoint`]",16,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[10,"del_raw_tx","","Delete a raw transaction given its [`Txid`]",16,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"del_tx","","Delete the metadata of a transaction and optionally the…",16,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"del_last_index","","Delete the last derivation index for a script type",16,[[["scripttype",4]],[["option",4],["result",4],["error",4]]]],[8,"Database","","Trait for reading data from a database",null,null],[10,"check_descriptor_checksum","","Read and checks the descriptor checksum for a given script…",17,[[["scripttype",4],["asref",8]],[["error",4],["result",4]]]],[10,"iter_script_pubkeys","","Return the list of script_pubkeys",17,[[["option",4],["scripttype",4]],[["result",4],["vec",3],["error",4]]]],[10,"iter_utxos","","Return the list of [`UTXO`]s",17,[[],[["error",4],["vec",3],["result",4]]]],[10,"iter_raw_txs","","Return the list of raw transactions",17,[[],[["result",4],["vec",3],["error",4]]]],[10,"iter_txs","","Return the list of transactions metadata",17,[[],[["result",4],["vec",3],["error",4]]]],[10,"get_script_pubkey_from_path","","Fetch a script_pubkey given the script type and child number",17,[[["scripttype",4]],[["error",4],["result",4],["option",4]]]],[10,"get_path_from_script_pubkey","","Fetch the script type and child number of a given…",17,[[["script",3]],[["result",4],["option",4],["error",4]]]],[10,"get_utxo","","Fetch a [`UTXO`] given its [`OutPoint`]",17,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[10,"get_raw_tx","","Fetch a raw transaction given its [`Txid`]",17,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"get_tx","","Fetch the transaction metadata and optionally also the raw…",17,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"get_last_index","","Return the last defivation index for a script type",17,[[["scripttype",4]],[["option",4],["result",4],["error",4]]]],[10,"increment_last_index","","Increment the last derivation index for a script type and…",17,[[["scripttype",4]],[["result",4],["error",4]]]],[8,"BatchDatabase","","Trait for a database that supports batch operations",null,null],[16,"Batch","","Container for the operations",18,null],[10,"begin_batch","","Create a new batch container",18,[[]]],[10,"commit_batch","","Consume and apply a batch of operations",18,[[],[["error",4],["result",4]]]],[0,"descriptor","magical","Descriptors",null,null],[4,"Descriptor","magical::descriptor","Script descriptor",null,null],[13,"Bare","","A raw scriptpubkey (including pay-to-pubkey) under Legacy…",19,null],[13,"Pk","","Pay-to-Pubkey",19,null],[13,"Pkh","","Pay-to-PubKey-Hash",19,null],[13,"Wpkh","","Pay-to-Witness-PubKey-Hash",19,null],[13,"ShWpkh","","Pay-to-Witness-PubKey-Hash inside P2SH",19,null],[13,"Sh","","Pay-to-ScriptHash with Legacy context",19,null],[13,"Wsh","","Pay-to-Witness-ScriptHash with Segwitv0 context",19,null],[13,"ShWsh","","P2SH-P2WSH with Segwitv0 context",19,null],[4,"Legacy","","Legacy ScriptContext",null,null],[3,"Miniscript","","Top-level script AST type",null,null],[12,"node","","A node in the Abstract Syntax Tree(",20,null],[12,"ty","","The correctness and malleability type information for the…",20,null],[12,"ext","","Additional information helpful for extra analysis.",20,null],[8,"MiniscriptKey","","Public key trait which can be converted to Hash type",null,null],[11,"is_uncompressed","","Check if the publicKey is uncompressed. The default…",21,[[]]],[16,"Hash","","The associated Hash type with the publicKey",21,null],[10,"to_pubkeyhash","","Converts an object to PublicHash",21,[[]]],[8,"ScriptContext","","",null,null],[10,"check_frag_non_malleable","","Depending on ScriptContext, fragments can be malleable.…",22,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[10,"check_frag_validity","","Depending on script Context, some of the Terminals might…",22,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[4,"Segwitv0","","Segwitv0 ScriptContext",null,null],[4,"Terminal","","All AST elements",null,null],[13,"True","","`1`",23,null],[13,"False","","`0`",23,null],[13,"PkK","","``",23,null],[13,"PkH","","`DUP HASH160 EQUALVERIFY`",23,null],[13,"After","","`n CHECKLOCKTIMEVERIFY`",23,null],[13,"Older","","`n CHECKSEQUENCEVERIFY`",23,null],[13,"Sha256","","`SIZE 32 EQUALVERIFY SHA256 EQUAL`",23,null],[13,"Hash256","","`SIZE 32 EQUALVERIFY HASH256 EQUAL`",23,null],[13,"Ripemd160","","`SIZE 32 EQUALVERIFY RIPEMD160 EQUAL`",23,null],[13,"Hash160","","`SIZE 32 EQUALVERIFY HASH160 EQUAL`",23,null],[13,"Alt","","`TOALTSTACK [E] FROMALTSTACK`",23,null],[13,"Swap","","`SWAP [E1]`",23,null],[13,"Check","","`[Kt]/[Ke] CHECKSIG`",23,null],[13,"DupIf","","`DUP IF [V] ENDIF`",23,null],[13,"Verify","","[T] VERIFY",23,null],[13,"NonZero","","SIZE 0NOTEQUAL IF [Fn] ENDIF",23,null],[13,"ZeroNotEqual","","[X] 0NOTEQUAL",23,null],[13,"AndV","","[V] [T]/[V]/[F]/[Kt]",23,null],[13,"AndB","","[E] [W] BOOLAND",23,null],[13,"AndOr","","[various] NOTIF [various] ELSE [various] ENDIF",23,null],[13,"OrB","","[E] [W] BOOLOR",23,null],[13,"OrD","","[E] IFDUP NOTIF [T]/[E] ENDIF",23,null],[13,"OrC","","[E] NOTIF [V] ENDIF",23,null],[13,"OrI","","IF [various] ELSE [various] ENDIF",23,null],[13,"Thresh","","[E] ([W] ADD)* k EQUAL",23,null],[13,"Multi","","k ()* n CHECKMULTISIG",23,null],[8,"ToPublicKey","","Trait describing public key types which can be converted…",null,null],[10,"to_public_key","","Converts an object to a public key",24,[[],["publickey",3]]],[11,"serialized_len","","Computes the size of a public key when serialized in a…",24,[[]]],[10,"hash_to_hash160","","Converts a hashed version of the public key to a `hash160`…",24,[[],["hash",3]]],[0,"checksum","","Descriptor checksum",null,null],[5,"get_checksum","magical::descriptor::checksum","Compute the checksum of a descriptor",null,[[],[["string",3],["error",4],["result",4]]]],[0,"error","magical::descriptor","Descriptor errors",null,null],[4,"Error","magical::descriptor::error","Errors related to the parsing and usage of descriptors",null,null],[13,"InternalError","","",25,null],[13,"InvalidPrefix","","",25,null],[13,"HardenedDerivationOnXpub","","",25,null],[13,"MalformedInput","","",25,null],[13,"KeyParsingError","","",25,null],[13,"Policy","","",25,null],[13,"InputIndexDoesntExist","","",25,null],[13,"MissingPublicKey","","",25,null],[13,"MissingDetails","","",25,null],[13,"InvalidDescriptorCharacter","","",25,null],[13,"CantDeriveWithMiniscript","","",25,null],[13,"BIP32","","",25,null],[13,"Base58","","",25,null],[13,"PK","","",25,null],[13,"Miniscript","","",25,null],[13,"Hex","","",25,null],[0,"policy","magical::descriptor","Descriptor policy",null,null],[3,"PKOrF","magical::descriptor::policy","Raw public key or extended key fingerprint",null,null],[3,"Policy","","Descriptor spending policy",null,null],[12,"id","","Identifier for this policy node",26,null],[12,"item","","Type of this policy node",26,null],[12,"satisfaction","","How a much given PSBT already satisfies this polcy node…",26,null],[12,"contribution","","How the wallet\'s descriptor can satisfy this policy node",26,null],[3,"Condition","","An extra condition that must be satisfied but that is out…",null,null],[12,"csv","","",27,null],[12,"timelock","","",27,null],[4,"SatisfiableItem","","An item that need to be satisfied",null,null],[13,"Signature","","",28,null],[13,"SignatureKey","","",28,null],[13,"SHA256Preimage","","",28,null],[12,"hash","magical::descriptor::policy::SatisfiableItem","",29,null],[13,"HASH256Preimage","magical::descriptor::policy","",28,null],[12,"hash","magical::descriptor::policy::SatisfiableItem","",30,null],[13,"RIPEMD160Preimage","magical::descriptor::policy","",28,null],[12,"hash","magical::descriptor::policy::SatisfiableItem","",31,null],[13,"HASH160Preimage","magical::descriptor::policy","",28,null],[12,"hash","magical::descriptor::policy::SatisfiableItem","",32,null],[13,"AbsoluteTimelock","magical::descriptor::policy","",28,null],[12,"value","magical::descriptor::policy::SatisfiableItem","",33,null],[13,"RelativeTimelock","magical::descriptor::policy","",28,null],[12,"value","magical::descriptor::policy::SatisfiableItem","",34,null],[13,"Thresh","magical::descriptor::policy","",28,null],[12,"items","magical::descriptor::policy::SatisfiableItem","",35,null],[12,"threshold","","",35,null],[13,"Multisig","magical::descriptor::policy","",28,null],[12,"keys","magical::descriptor::policy::SatisfiableItem","",36,null],[12,"threshold","","",36,null],[4,"Satisfaction","magical::descriptor::policy","Represent if and how much a policy item is satisfied by…",null,null],[13,"Partial","","Only a partial satisfaction of some kind of threshold policy",37,null],[12,"n","magical::descriptor::policy::Satisfaction","Total number of items",38,null],[12,"m","","Threshold",38,null],[12,"items","","The items that can be satisfied by the descriptor",38,null],[12,"conditions","","Extra conditions that also need to be satisfied",38,null],[13,"PartialComplete","magical::descriptor::policy","Can reach the threshold of some kind of threshold policy",37,null],[12,"n","magical::descriptor::policy::Satisfaction","Total number of items",39,null],[12,"m","","Threshold",39,null],[12,"items","","The items that can be satisfied by the descriptor",39,null],[12,"conditions","","Extra conditions that also need to be satisfied",39,null],[13,"Complete","magical::descriptor::policy","Can satisfy the policy item",37,null],[12,"condition","magical::descriptor::policy::Satisfaction","Extra conditions that also need to be satisfied",40,null],[13,"None","magical::descriptor::policy","Cannot satisfy or contribute to the policy item",37,null],[4,"PolicyError","","Errors that can happen while extracting and manipulating…",null,null],[13,"NotEnoughItemsSelected","","",41,null],[13,"TooManyItemsSelected","","",41,null],[13,"IndexOutOfRange","","",41,null],[13,"AddOnLeaf","","",41,null],[13,"AddOnPartialComplete","","",41,null],[13,"MixedTimelockUnits","","",41,null],[13,"IncompatibleConditions","","",41,null],[6,"ConditionMap","","",null,null],[6,"FoldedConditionMap","","",null,null],[11,"is_leaf","","",28,[[]]],[11,"id","","",28,[[],["string",3]]],[11,"is_leaf","","",37,[[]]],[11,"is_null","","",27,[[]]],[11,"requires_path","","Return whether or not a specific path in the policy tree…",26,[[]]],[11,"get_condition","","Return the conditions that are set by the spending policy…",26,[[["btreemap",3]],[["condition",3],["policyerror",4],["result",4]]]],[6,"ExtendedDescriptor","magical::descriptor","Alias for a [`Descriptor`] that can contain extended keys…",null,null],[6,"HDKeyPaths","","Alias for the type of maps that represent derivation paths…",null,null],[8,"ExtractPolicy","","Trait implemented on [`Descriptor`]s to add a method to…",null,null],[10,"extract_policy","","",42,[[["arc",3],["signerscontainer",3]],[["result",4],["option",4],["error",4]]]],[11,"as_byte","magical","",4,[[]]],[11,"is_internal","","",4,[[]]],[11,"from_btc_per_kvb","","Create a new instance of [`FeeRate`] given a float fee…",43,[[]]],[11,"from_sat_per_vb","","Create a new instance of [`FeeRate`] given a float fee…",43,[[]]],[11,"default_min_relay_fee","","Create a new [`FeeRate`] with the default min relay fee…",43,[[]]],[11,"as_sat_vb","","Return the value as satoshi/vbyte",43,[[]]],[0,"wallet","","Wallet",null,null],[3,"Wallet","magical::wallet","A Bitcoin wallet",null,null],[0,"address_validator","","Address validation callbacks",null,null],[4,"AddressValidatorError","magical::wallet::address_validator","Errors that can be returned to fail the validation of an…",null,null],[13,"UserRejected","","",44,null],[13,"ConnectionError","","",44,null],[13,"TimeoutError","","",44,null],[13,"InvalidScript","","",44,null],[13,"Message","","",44,null],[8,"AddressValidator","","Trait to build address validators",null,null],[10,"validate","","Validate or inspect an address",45,[[["script",3],["scripttype",4],["hdkeypaths",6]],[["result",4],["addressvalidatorerror",4]]]],[0,"coin_selection","magical::wallet","Coin selection",null,null],[3,"CoinSelectionResult","magical::wallet::coin_selection","Result of a successful coin selection",null,null],[12,"txin","","List of inputs to use, with the respective previous…",46,null],[12,"selected_amount","","Sum of the selected inputs\' value",46,null],[12,"fee_amount","","Total fee amount in satoshi",46,null],[3,"DumbCoinSelection","","Simple and dumb coin selection",null,null],[6,"DefaultCoinSelectionAlgorithm","","Default coin selection algorithm used by `TxBuilder` if…",null,null],[8,"CoinSelectionAlgorithm","","Trait for generalized coin selection algorithms",null,null],[10,"coin_select","","Perform the coin selection",47,[[["utxo",3],["vec",3],["feerate",3]],[["coinselectionresult",3],["result",4],["error",4]]]],[0,"export","magical::wallet","Wallet export",null,null],[3,"WalletExport","magical::wallet::export","Structure that contains the export of a wallet",null,null],[12,"blockheight","","Earliest block to rescan when looking for the wallet\'s…",48,null],[12,"label","","Arbitrary label for the wallet",48,null],[11,"export_wallet","","Export a wallet",48,[[["wallet",3]],["result",4]]],[11,"descriptor","","Return the external descriptor",48,[[],["string",3]]],[11,"change_descriptor","","Return the internal descriptor, if present",48,[[],[["string",3],["option",4]]]],[0,"signer","magical::wallet","Generalized signers",null,null],[3,"SignerOrdering","magical::wallet::signer","Defines the order in which signers are called",null,null],[12,"0","","",49,null],[3,"SignersContainer","","Container for multiple signers",null,null],[4,"SignerId","","Identifier of a signer in the `SignersContainers`. Used as…",null,null],[13,"PkHash","","",50,null],[13,"Fingerprint","","",50,null],[4,"SignerError","","Signing error",null,null],[13,"MissingKey","","The private key is missing for the required public key",51,null],[13,"UserCanceled","","The user canceled the operation",51,null],[13,"MissingSighash","","The sighash is missing in the PSBT input",51,null],[13,"InputIndexOutOfRange","","Input index is out of range",51,null],[13,"MissingNonWitnessUtxo","","The `non_witness_utxo` field of the transaction is…",51,null],[13,"InvalidNonWitnessUtxo","","The `non_witness_utxo` specified is invalid",51,null],[13,"MissingWitnessUtxo","","The `witness_utxo` field of the transaction is required to…",51,null],[13,"MissingWitnessScript","","The `witness_script` field of the transaction is requied…",51,null],[13,"MissingHDKeypath","","The fingerprint and derivation path are missing from the…",51,null],[8,"Signer","","Trait for signers",null,null],[10,"sign","","Sign a PSBT",52,[[["partiallysignedtransaction",3],["option",4]],[["signererror",4],["result",4]]]],[10,"sign_whole_tx","","Return whether or not the signer signs the whole…",52,[[]]],[11,"descriptor_secret_key","","Return the secret key for the signer",52,[[],[["descriptorsecretkey",4],["option",4]]]],[11,"as_key_map","","",53,[[],["keymap",6]]],[11,"new","","Default constructor",53,[[]]],[11,"add_external","","Adds an external signer to the container for the specified…",53,[[["signerordering",3],["box",3],["signerid",4],["arc",3]],[["option",4],["arc",3]]]],[11,"remove","","Removes a signer from the container and returns it",53,[[["signerordering",3],["signerid",4]],[["option",4],["arc",3]]]],[11,"ids","","Returns the list of identifiers of all the signers in the…",53,[[],[["vec",3],["signerid",4]]]],[11,"signers","","Returns the list of signers in the container, sorted by…",53,[[],[["arc",3],["vec",3]]]],[11,"find","","Finds the signer with lowest ordering for a given id in…",53,[[["signerid",4]],[["arc",3],["option",4]]]],[0,"time","magical::wallet","Cross-platform time",null,null],[5,"get_timestamp","magical::wallet::time","Return the current timestamp in seconds",null,[[]]],[0,"tx_builder","magical::wallet","Transaction builder",null,null],[3,"TxBuilder","magical::wallet::tx_builder","A transaction builder",null,null],[4,"TxOrdering","","Ordering of the transaction\'s inputs and outputs",null,null],[13,"Shuffle","","Randomized (default)",54,null],[13,"Untouched","","Unchanged",54,null],[13,"BIP69Lexicographic","","BIP69 / Lexicographic",54,null],[4,"ChangeSpendPolicy","","Policy regarding the use of change outputs when creating a…",null,null],[13,"ChangeAllowed","","Use both change and non-change outputs (default)",55,null],[13,"OnlyChange","","Only use change outputs (see…",55,null],[13,"ChangeForbidden","","Only use non-change outputs (see…",55,null],[11,"new","","Create an empty builder",56,[[]]],[11,"with_recipients","","Create a builder starting from a list of recipients",56,[[["vec",3]]]],[11,"set_recipients","","Replace the recipients already added with a new list",56,[[["vec",3]]]],[11,"add_recipient","","Add a recipient to the internal list",56,[[["script",3]]]],[11,"send_all","","Send all the selected utxos to a single output",56,[[]]],[11,"fee_rate","","Set a custom fee rate",56,[[["feerate",3]]]],[11,"policy_path","","Set the policy path to use while creating the transaction",56,[[["vec",3],["string",3],["btreemap",3]]]],[11,"utxos","","Replace the internal list of utxos that must be spent with…",56,[[["vec",3],["outpoint",3]]]],[11,"add_utxo","","Add a utxo to the internal list of utxos that must be spent",56,[[["outpoint",3]]]],[11,"unspendable","","Replace the internal list of unspendable utxos with a new…",56,[[["vec",3],["outpoint",3]]]],[11,"add_unspendable","","Add a utxo to the internal list of unspendable utxos",56,[[["outpoint",3]]]],[11,"sighash","","Sign with a specific sig hash",56,[[["sighashtype",4]]]],[11,"ordering","","Choose the ordering for inputs and outputs of the…",56,[[["txordering",4]]]],[11,"nlocktime","","Use a specific nLockTime while creating the transaction",56,[[]]],[11,"enable_rbf","","Enable signaling RBF",56,[[]]],[11,"enable_rbf_with_sequence","","Enable signaling RBF with a specific nSequence value",56,[[]]],[11,"version","","Build a transaction with a specific version",56,[[]]],[11,"do_not_spend_change","","Do not spend change outputs",56,[[]]],[11,"only_spend_change","","Only spend change outputs",56,[[]]],[11,"change_policy","","Set a specific [`ChangeSpendPolicy`]. See…",56,[[["changespendpolicy",4]]]],[11,"force_non_witness_utxo","","Fill-in the `psbt::Input::non_witness_utxo` field even if…",56,[[]]],[11,"coin_selection","","Choose the coin selection algorithm",56,[[["coinselectionalgorithm",8]],[["coinselectionalgorithm",8],["txbuilder",3]]]],[11,"sort_tx","","",54,[[["transaction",3]]]],[6,"OfflineWallet","magical::wallet","Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]",null,null],[8,"IsDust","","Trait to check if a value is below the dust limit",null,null],[10,"is_dust","","Check whether or not a value is below dust limit",57,[[]]],[11,"new_offline","","Create a new \\\"offline\\\" wallet",58,[[["option",4],["network",4]],[["error",4],["result",4]]]],[11,"get_new_address","","Return a newly generated address using the external…",58,[[],[["result",4],["address",3],["error",4]]]],[11,"is_mine","","Return whether or not a `script` is part of this wallet…",58,[[["script",3]],[["result",4],["error",4]]]],[11,"list_unspent","","Return the list of unspent outputs of this wallet",58,[[],[["error",4],["vec",3],["result",4]]]],[11,"list_transactions","","Return the list of transactions made and received by the…",58,[[],[["result",4],["vec",3],["error",4]]]],[11,"get_balance","","Return the balance, meaning the sum of this wallet\'s…",58,[[],[["result",4],["error",4]]]],[11,"add_signer","","Add an external signer",58,[[["signerordering",3],["scripttype",4],["descriptorpublickey",4],["box",3],["arc",3],["signerid",4]]]],[11,"add_address_validator","","Add an address validator",58,[[["box",3],["arc",3]]]],[11,"create_tx","","Create a new transaction following the options specified…",58,[[["coinselectionalgorithm",8],["txbuilder",3]],[["result",4],["error",4]]]],[11,"bump_fee","","Bump the fee of a transaction following the options…",58,[[["txid",3],["coinselectionalgorithm",8],["txbuilder",3]],[["result",4],["error",4]]]],[11,"sign","","Sign a transaction with all the wallet\'s signers, in the…",58,[[["psbt",3],["option",4]],[["result",4],["error",4]]]],[11,"policies","","Return the spending policies for the wallet\'s descriptor",58,[[["scripttype",4]],[["error",4],["option",4],["result",4]]]],[11,"public_descriptor","","Return the \\\"public\\\" version of the wallet\'s descriptor,…",58,[[["scripttype",4]],[["option",4],["result",4],["error",4]]]],[11,"finalize_psbt","","Try to finalize a PSBT",58,[[["psbt",3],["option",4]],[["result",4],["error",4]]]],[11,"new","","Create a new \\\"online\\\" wallet",58,[[["option",4],["network",4]],[["error",4],["result",4]]]],[11,"sync","","Sync the internal database with the blockchain",58,[[["option",4],["progress",8]],[["error",4],["result",4]]]],[11,"client","","Return a reference to the internal blockchain client",58,[[]]],[11,"broadcast","","Broadcast a transaction to the network",58,[[["transaction",3]],[["error",4],["result",4],["txid",3]]]],[11,"from","magical","",43,[[]]],[11,"into","","",43,[[]]],[11,"to_owned","","",43,[[]]],[11,"clone_into","","",43,[[]]],[11,"try_from","","",43,[[],["result",4]]],[11,"try_into","","",43,[[],["result",4]]],[11,"borrow","","",43,[[]]],[11,"borrow_mut","","",43,[[]]],[11,"type_id","","",43,[[],["typeid",3]]],[11,"vzip","","",43,[[]]],[11,"from","","",0,[[]]],[11,"into","","",0,[[]]],[11,"to_owned","","",0,[[]]],[11,"clone_into","","",0,[[]]],[11,"try_from","","",0,[[],["result",4]]],[11,"try_into","","",0,[[],["result",4]]],[11,"borrow","","",0,[[]]],[11,"borrow_mut","","",0,[[]]],[11,"type_id","","",0,[[],["typeid",3]]],[11,"equivalent","","",0,[[]]],[11,"vzip","","",0,[[]]],[11,"from","","",1,[[]]],[11,"into","","",1,[[]]],[11,"to_owned","","",1,[[]]],[11,"clone_into","","",1,[[]]],[11,"try_from","","",1,[[],["result",4]]],[11,"try_into","","",1,[[],["result",4]]],[11,"borrow","","",1,[[]]],[11,"borrow_mut","","",1,[[]]],[11,"type_id","","",1,[[],["typeid",3]]],[11,"equivalent","","",1,[[]]],[11,"vzip","","",1,[[]]],[11,"from","","",2,[[]]],[11,"into","","",2,[[]]],[11,"to_string","","",2,[[],["string",3]]],[11,"try_from","","",2,[[],["result",4]]],[11,"try_into","","",2,[[],["result",4]]],[11,"borrow","","",2,[[]]],[11,"borrow_mut","","",2,[[]]],[11,"type_id","","",2,[[],["typeid",3]]],[11,"vzip","","",2,[[]]],[11,"from","","",4,[[]]],[11,"into","","",4,[[]]],[11,"to_owned","","",4,[[]]],[11,"clone_into","","",4,[[]]],[11,"try_from","","",4,[[],["result",4]]],[11,"try_into","","",4,[[],["result",4]]],[11,"borrow","","",4,[[]]],[11,"borrow_mut","","",4,[[]]],[11,"type_id","","",4,[[],["typeid",3]]],[11,"write_base32","","",4,[[],["result",4]]],[11,"base32_len","","",4,[[]]],[11,"check_base32","","",4,[[],[["result",4],["vec",3]]]],[11,"equivalent","","",4,[[]]],[11,"vzip","","",4,[[]]],[11,"from","magical::blockchain","",59,[[]]],[11,"into","","",59,[[]]],[11,"try_from","","",59,[[],["result",4]]],[11,"try_into","","",59,[[],["result",4]]],[11,"borrow","","",59,[[]]],[11,"borrow_mut","","",59,[[]]],[11,"type_id","","",59,[[],["typeid",3]]],[11,"vzip","","",59,[[]]],[11,"from","","",60,[[]]],[11,"into","","",60,[[]]],[11,"to_owned","","",60,[[]]],[11,"clone_into","","",60,[[]]],[11,"try_from","","",60,[[],["result",4]]],[11,"try_into","","",60,[[],["result",4]]],[11,"borrow","","",60,[[]]],[11,"borrow_mut","","",60,[[]]],[11,"type_id","","",60,[[],["typeid",3]]],[11,"vzip","","",60,[[]]],[11,"from","","",61,[[]]],[11,"into","","",61,[[]]],[11,"to_owned","","",61,[[]]],[11,"clone_into","","",61,[[]]],[11,"try_from","","",61,[[],["result",4]]],[11,"try_into","","",61,[[],["result",4]]],[11,"borrow","","",61,[[]]],[11,"borrow_mut","","",61,[[]]],[11,"type_id","","",61,[[],["typeid",3]]],[11,"vzip","","",61,[[]]],[11,"from","","",5,[[]]],[11,"into","","",5,[[]]],[11,"to_owned","","",5,[[]]],[11,"clone_into","","",5,[[]]],[11,"try_from","","",5,[[],["result",4]]],[11,"try_into","","",5,[[],["result",4]]],[11,"borrow","","",5,[[]]],[11,"borrow_mut","","",5,[[]]],[11,"type_id","","",5,[[],["typeid",3]]],[11,"equivalent","","",5,[[]]],[11,"vzip","","",5,[[]]],[11,"from","magical::blockchain::electrum","",62,[[]]],[11,"into","","",62,[[]]],[11,"try_from","","",62,[[],["result",4]]],[11,"try_into","","",62,[[],["result",4]]],[11,"borrow","","",62,[[]]],[11,"borrow_mut","","",62,[[]]],[11,"type_id","","",62,[[],["typeid",3]]],[11,"vzip","","",62,[[]]],[11,"from","magical::blockchain::esplora","",7,[[]]],[11,"into","","",7,[[]]],[11,"try_from","","",7,[[],["result",4]]],[11,"try_into","","",7,[[],["result",4]]],[11,"borrow","","",7,[[]]],[11,"borrow_mut","","",7,[[]]],[11,"type_id","","",7,[[],["typeid",3]]],[11,"vzip","","",7,[[]]],[11,"from","","",6,[[]]],[11,"into","","",6,[[]]],[11,"to_string","","",6,[[],["string",3]]],[11,"try_from","","",6,[[],["result",4]]],[11,"try_into","","",6,[[],["result",4]]],[11,"borrow","","",6,[[]]],[11,"borrow_mut","","",6,[[]]],[11,"type_id","","",6,[[],["typeid",3]]],[11,"vzip","","",6,[[]]],[11,"from","magical::blockchain::compact_filters","",9,[[]]],[11,"into","","",9,[[]]],[11,"try_from","","",9,[[],["result",4]]],[11,"try_into","","",9,[[],["result",4]]],[11,"borrow","","",9,[[]]],[11,"borrow_mut","","",9,[[]]],[11,"type_id","","",9,[[],["typeid",3]]],[11,"vzip","","",9,[[]]],[11,"from","","",10,[[]]],[11,"into","","",10,[[]]],[11,"try_from","","",10,[[],["result",4]]],[11,"try_into","","",10,[[],["result",4]]],[11,"borrow","","",10,[[]]],[11,"borrow_mut","","",10,[[]]],[11,"type_id","","",10,[[],["typeid",3]]],[11,"vzip","","",10,[[]]],[11,"from","","",11,[[]]],[11,"into","","",11,[[]]],[11,"try_from","","",11,[[],["result",4]]],[11,"try_into","","",11,[[],["result",4]]],[11,"borrow","","",11,[[]]],[11,"borrow_mut","","",11,[[]]],[11,"type_id","","",11,[[],["typeid",3]]],[11,"vzip","","",11,[[]]],[11,"from","","",8,[[]]],[11,"into","","",8,[[]]],[11,"to_string","","",8,[[],["string",3]]],[11,"try_from","","",8,[[],["result",4]]],[11,"try_into","","",8,[[],["result",4]]],[11,"borrow","","",8,[[]]],[11,"borrow_mut","","",8,[[]]],[11,"type_id","","",8,[[],["typeid",3]]],[11,"vzip","","",8,[[]]],[11,"from","magical::database::memory","",15,[[]]],[11,"into","","",15,[[]]],[11,"try_from","","",15,[[],["result",4]]],[11,"try_into","","",15,[[],["result",4]]],[11,"borrow","","",15,[[]]],[11,"borrow_mut","","",15,[[]]],[11,"type_id","","",15,[[],["typeid",3]]],[11,"vzip","","",15,[[]]],[11,"from","magical::descriptor","",19,[[]]],[11,"into","","",19,[[]]],[11,"to_owned","","",19,[[]]],[11,"clone_into","","",19,[[]]],[11,"to_string","","",19,[[],["string",3]]],[11,"try_from","","",19,[[],["result",4]]],[11,"try_into","","",19,[[],["result",4]]],[11,"borrow","","",19,[[]]],[11,"borrow_mut","","",19,[[]]],[11,"type_id","","",19,[[],["typeid",3]]],[11,"equivalent","","",19,[[]]],[11,"vzip","","",19,[[]]],[11,"from","","",63,[[]]],[11,"into","","",63,[[]]],[11,"to_owned","","",63,[[]]],[11,"clone_into","","",63,[[]]],[11,"try_from","","",63,[[],["result",4]]],[11,"try_into","","",63,[[],["result",4]]],[11,"borrow","","",63,[[]]],[11,"borrow_mut","","",63,[[]]],[11,"type_id","","",63,[[],["typeid",3]]],[11,"equivalent","","",63,[[]]],[11,"vzip","","",63,[[]]],[11,"from","","",20,[[]]],[11,"into","","",20,[[]]],[11,"to_owned","","",20,[[]]],[11,"clone_into","","",20,[[]]],[11,"to_string","","",20,[[],["string",3]]],[11,"try_from","","",20,[[],["result",4]]],[11,"try_into","","",20,[[],["result",4]]],[11,"borrow","","",20,[[]]],[11,"borrow_mut","","",20,[[]]],[11,"type_id","","",20,[[],["typeid",3]]],[11,"equivalent","","",20,[[]]],[11,"vzip","","",20,[[]]],[11,"from","","",64,[[]]],[11,"into","","",64,[[]]],[11,"to_owned","","",64,[[]]],[11,"clone_into","","",64,[[]]],[11,"try_from","","",64,[[],["result",4]]],[11,"try_into","","",64,[[],["result",4]]],[11,"borrow","","",64,[[]]],[11,"borrow_mut","","",64,[[]]],[11,"type_id","","",64,[[],["typeid",3]]],[11,"equivalent","","",64,[[]]],[11,"vzip","","",64,[[]]],[11,"from","","",23,[[]]],[11,"into","","",23,[[]]],[11,"to_owned","","",23,[[]]],[11,"clone_into","","",23,[[]]],[11,"to_string","","",23,[[],["string",3]]],[11,"try_from","","",23,[[],["result",4]]],[11,"try_into","","",23,[[],["result",4]]],[11,"borrow","","",23,[[]]],[11,"borrow_mut","","",23,[[]]],[11,"type_id","","",23,[[],["typeid",3]]],[11,"equivalent","","",23,[[]]],[11,"vzip","","",23,[[]]],[11,"from","magical::descriptor::error","",25,[[]]],[11,"into","","",25,[[]]],[11,"to_string","","",25,[[],["string",3]]],[11,"try_from","","",25,[[],["result",4]]],[11,"try_into","","",25,[[],["result",4]]],[11,"borrow","","",25,[[]]],[11,"borrow_mut","","",25,[[]]],[11,"type_id","","",25,[[],["typeid",3]]],[11,"vzip","","",25,[[]]],[11,"from","magical::descriptor::policy","",65,[[]]],[11,"into","","",65,[[]]],[11,"to_owned","","",65,[[]]],[11,"clone_into","","",65,[[]]],[11,"try_from","","",65,[[],["result",4]]],[11,"try_into","","",65,[[],["result",4]]],[11,"borrow","","",65,[[]]],[11,"borrow_mut","","",65,[[]]],[11,"type_id","","",65,[[],["typeid",3]]],[11,"vzip","","",65,[[]]],[11,"from","","",26,[[]]],[11,"into","","",26,[[]]],[11,"to_owned","","",26,[[]]],[11,"clone_into","","",26,[[]]],[11,"try_from","","",26,[[],["result",4]]],[11,"try_into","","",26,[[],["result",4]]],[11,"borrow","","",26,[[]]],[11,"borrow_mut","","",26,[[]]],[11,"type_id","","",26,[[],["typeid",3]]],[11,"vzip","","",26,[[]]],[11,"from","","",27,[[]]],[11,"into","","",27,[[]]],[11,"to_owned","","",27,[[]]],[11,"clone_into","","",27,[[]]],[11,"try_from","","",27,[[],["result",4]]],[11,"try_into","","",27,[[],["result",4]]],[11,"borrow","","",27,[[]]],[11,"borrow_mut","","",27,[[]]],[11,"type_id","","",27,[[],["typeid",3]]],[11,"equivalent","","",27,[[]]],[11,"vzip","","",27,[[]]],[11,"from","","",28,[[]]],[11,"into","","",28,[[]]],[11,"to_owned","","",28,[[]]],[11,"clone_into","","",28,[[]]],[11,"try_from","","",28,[[],["result",4]]],[11,"try_into","","",28,[[],["result",4]]],[11,"borrow","","",28,[[]]],[11,"borrow_mut","","",28,[[]]],[11,"type_id","","",28,[[],["typeid",3]]],[11,"vzip","","",28,[[]]],[11,"from","","",37,[[]]],[11,"into","","",37,[[]]],[11,"to_owned","","",37,[[]]],[11,"clone_into","","",37,[[]]],[11,"try_from","","",37,[[],["result",4]]],[11,"try_into","","",37,[[],["result",4]]],[11,"borrow","","",37,[[]]],[11,"borrow_mut","","",37,[[]]],[11,"type_id","","",37,[[],["typeid",3]]],[11,"vzip","","",37,[[]]],[11,"from","","",41,[[]]],[11,"into","","",41,[[]]],[11,"to_string","","",41,[[],["string",3]]],[11,"try_from","","",41,[[],["result",4]]],[11,"try_into","","",41,[[],["result",4]]],[11,"borrow","","",41,[[]]],[11,"borrow_mut","","",41,[[]]],[11,"type_id","","",41,[[],["typeid",3]]],[11,"vzip","","",41,[[]]],[11,"from","magical::wallet","",58,[[]]],[11,"into","","",58,[[]]],[11,"try_from","","",58,[[],["result",4]]],[11,"try_into","","",58,[[],["result",4]]],[11,"borrow","","",58,[[]]],[11,"borrow_mut","","",58,[[]]],[11,"type_id","","",58,[[],["typeid",3]]],[11,"vzip","","",58,[[]]],[11,"from","magical::wallet::address_validator","",44,[[]]],[11,"into","","",44,[[]]],[11,"to_owned","","",44,[[]]],[11,"clone_into","","",44,[[]]],[11,"to_string","","",44,[[],["string",3]]],[11,"try_from","","",44,[[],["result",4]]],[11,"try_into","","",44,[[],["result",4]]],[11,"borrow","","",44,[[]]],[11,"borrow_mut","","",44,[[]]],[11,"type_id","","",44,[[],["typeid",3]]],[11,"equivalent","","",44,[[]]],[11,"vzip","","",44,[[]]],[11,"from","magical::wallet::coin_selection","",46,[[]]],[11,"into","","",46,[[]]],[11,"try_from","","",46,[[],["result",4]]],[11,"try_into","","",46,[[],["result",4]]],[11,"borrow","","",46,[[]]],[11,"borrow_mut","","",46,[[]]],[11,"type_id","","",46,[[],["typeid",3]]],[11,"vzip","","",46,[[]]],[11,"from","","",66,[[]]],[11,"into","","",66,[[]]],[11,"try_from","","",66,[[],["result",4]]],[11,"try_into","","",66,[[],["result",4]]],[11,"borrow","","",66,[[]]],[11,"borrow_mut","","",66,[[]]],[11,"type_id","","",66,[[],["typeid",3]]],[11,"vzip","","",66,[[]]],[11,"from","magical::wallet::export","",48,[[]]],[11,"into","","",48,[[]]],[11,"to_string","","",48,[[],["string",3]]],[11,"try_from","","",48,[[],["result",4]]],[11,"try_into","","",48,[[],["result",4]]],[11,"borrow","","",48,[[]]],[11,"borrow_mut","","",48,[[]]],[11,"type_id","","",48,[[],["typeid",3]]],[11,"vzip","","",48,[[]]],[11,"from","magical::wallet::signer","",49,[[]]],[11,"into","","",49,[[]]],[11,"to_owned","","",49,[[]]],[11,"clone_into","","",49,[[]]],[11,"try_from","","",49,[[],["result",4]]],[11,"try_into","","",49,[[],["result",4]]],[11,"borrow","","",49,[[]]],[11,"borrow_mut","","",49,[[]]],[11,"type_id","","",49,[[],["typeid",3]]],[11,"equivalent","","",49,[[]]],[11,"vzip","","",49,[[]]],[11,"from","","",53,[[]]],[11,"into","","",53,[[]]],[11,"to_owned","","",53,[[]]],[11,"clone_into","","",53,[[]]],[11,"try_from","","",53,[[],["result",4]]],[11,"try_into","","",53,[[],["result",4]]],[11,"borrow","","",53,[[]]],[11,"borrow_mut","","",53,[[]]],[11,"type_id","","",53,[[],["typeid",3]]],[11,"vzip","","",53,[[]]],[11,"from","","",50,[[]]],[11,"into","","",50,[[]]],[11,"to_owned","","",50,[[]]],[11,"clone_into","","",50,[[]]],[11,"try_from","","",50,[[],["result",4]]],[11,"try_into","","",50,[[],["result",4]]],[11,"borrow","","",50,[[]]],[11,"borrow_mut","","",50,[[]]],[11,"type_id","","",50,[[],["typeid",3]]],[11,"equivalent","","",50,[[]]],[11,"vzip","","",50,[[]]],[11,"from","","",51,[[]]],[11,"into","","",51,[[]]],[11,"to_owned","","",51,[[]]],[11,"clone_into","","",51,[[]]],[11,"to_string","","",51,[[],["string",3]]],[11,"try_from","","",51,[[],["result",4]]],[11,"try_into","","",51,[[],["result",4]]],[11,"borrow","","",51,[[]]],[11,"borrow_mut","","",51,[[]]],[11,"type_id","","",51,[[],["typeid",3]]],[11,"equivalent","","",51,[[]]],[11,"vzip","","",51,[[]]],[11,"from","magical::wallet::tx_builder","",56,[[]]],[11,"into","","",56,[[]]],[11,"try_from","","",56,[[],["result",4]]],[11,"try_into","","",56,[[],["result",4]]],[11,"borrow","","",56,[[]]],[11,"borrow_mut","","",56,[[]]],[11,"type_id","","",56,[[],["typeid",3]]],[11,"vzip","","",56,[[]]],[11,"from","","",54,[[]]],[11,"into","","",54,[[]]],[11,"to_owned","","",54,[[]]],[11,"clone_into","","",54,[[]]],[11,"try_from","","",54,[[],["result",4]]],[11,"try_into","","",54,[[],["result",4]]],[11,"borrow","","",54,[[]]],[11,"borrow_mut","","",54,[[]]],[11,"type_id","","",54,[[],["typeid",3]]],[11,"equivalent","","",54,[[]]],[11,"vzip","","",54,[[]]],[11,"from","","",55,[[]]],[11,"into","","",55,[[]]],[11,"to_owned","","",55,[[]]],[11,"clone_into","","",55,[[]]],[11,"try_from","","",55,[[],["result",4]]],[11,"try_into","","",55,[[],["result",4]]],[11,"borrow","","",55,[[]]],[11,"borrow_mut","","",55,[[]]],[11,"type_id","","",55,[[],["typeid",3]]],[11,"equivalent","","",55,[[]]],[11,"vzip","","",55,[[]]],[11,"eq","magical::descriptor","",20,[[["miniscript",3]]]],[11,"eq","","",19,[[["descriptor",4]]]],[11,"ne","","",19,[[["descriptor",4]]]],[11,"eq","","",64,[[["segwitv0",4]]]],[11,"eq","","",23,[[["terminal",4]]]],[11,"ne","","",23,[[["terminal",4]]]],[11,"eq","","",63,[[["legacy",4]]]],[11,"check_frag_non_malleable","","",63,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_frag_validity","","",63,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_frag_non_malleable","","",64,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_frag_validity","","",64,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"cmp","","",23,[[["terminal",4]],["ordering",4]]],[11,"cmp","","",64,[[["segwitv0",4]],["ordering",4]]],[11,"cmp","","",63,[[["legacy",4]],["ordering",4]]],[11,"cmp","","",19,[[["descriptor",4]],["ordering",4]]],[11,"cmp","","",20,[[["miniscript",3]],["ordering",4]]],[11,"fmt","","",20,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",19,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",23,[[["formatter",3]],[["result",4],["error",3]]]],[11,"from_str","","",19,[[],[["error",4],["descriptor",4],["result",4]]]],[11,"from_str","","",20,[[],[["error",4],["miniscript",3],["result",4]]]],[11,"hash","","",20,[[]]],[11,"hash","","",23,[[]]],[11,"fmt","","",20,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",64,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",63,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",23,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",19,[[["formatter",3]],[["result",4],["error",3]]]],[11,"partial_cmp","","",20,[[["miniscript",3]],[["ordering",4],["option",4]]]],[11,"partial_cmp","","",64,[[["segwitv0",4]],[["ordering",4],["option",4]]]],[11,"partial_cmp","","",19,[[["descriptor",4]],[["ordering",4],["option",4]]]],[11,"lt","","",19,[[["descriptor",4]]]],[11,"le","","",19,[[["descriptor",4]]]],[11,"gt","","",19,[[["descriptor",4]]]],[11,"ge","","",19,[[["descriptor",4]]]],[11,"partial_cmp","","",23,[[["terminal",4]],[["ordering",4],["option",4]]]],[11,"lt","","",23,[[["terminal",4]]]],[11,"le","","",23,[[["terminal",4]]]],[11,"gt","","",23,[[["terminal",4]]]],[11,"ge","","",23,[[["terminal",4]]]],[11,"partial_cmp","","",63,[[["legacy",4]],[["ordering",4],["option",4]]]],[11,"from_tree","","Parse an expression tree into a Miniscript. As a general…",20,[[["tree",3]],[["error",4],["miniscript",3],["result",4]]]],[11,"from_tree","","",23,[[["tree",3]],[["error",4],["terminal",4],["result",4]]]],[11,"from_tree","","Parse an expression tree into a descriptor",19,[[["tree",3]],[["error",4],["descriptor",4],["result",4]]]],[11,"lift","","",19,[[],["policy",4]]],[11,"lift","","",20,[[],["policy",4]]],[11,"lift","","",23,[[],["policy",4]]],[11,"clone","","",19,[[],["descriptor",4]]],[11,"clone","","",20,[[],["miniscript",3]]],[11,"clone","","",63,[[],["legacy",4]]],[11,"clone","","",64,[[],["segwitv0",4]]],[11,"clone","","",23,[[],["terminal",4]]],[11,"offline","magical::blockchain::electrum","",62,[[]]],[11,"is_online","","",62,[[]]],[11,"offline","magical::blockchain::esplora","",7,[[]]],[11,"is_online","","",7,[[]]],[11,"offline","magical::blockchain::compact_filters","",11,[[]]],[11,"is_online","","",11,[[]]],[11,"offline","magical::blockchain","",59,[[]]],[11,"is_online","","",59,[[]]],[11,"update","","",60,[[["string",3],["option",4]],[["error",4],["result",4]]]],[11,"update","","",61,[[["string",3],["option",4]],[["error",4],["result",4]]]],[11,"set_script_pubkey","magical::database::memory","",15,[[["script",3],["scripttype",4]],[["error",4],["result",4]]]],[11,"set_utxo","","",15,[[["utxo",3]],[["error",4],["result",4]]]],[11,"set_raw_tx","","",15,[[["transaction",3]],[["error",4],["result",4]]]],[11,"set_tx","","",15,[[["transactiondetails",3]],[["error",4],["result",4]]]],[11,"set_last_index","","",15,[[["scripttype",4]],[["error",4],["result",4]]]],[11,"del_script_pubkey_from_path","","",15,[[["scripttype",4]],[["error",4],["result",4],["option",4]]]],[11,"del_path_from_script_pubkey","","",15,[[["script",3]],[["result",4],["option",4],["error",4]]]],[11,"del_utxo","","",15,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[11,"del_raw_tx","","",15,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"del_tx","","",15,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"del_last_index","","",15,[[["scripttype",4]],[["option",4],["result",4],["error",4]]]],[11,"check_descriptor_checksum","","",15,[[["scripttype",4],["asref",8]],[["error",4],["result",4]]]],[11,"iter_script_pubkeys","","",15,[[["option",4],["scripttype",4]],[["result",4],["vec",3],["error",4]]]],[11,"iter_utxos","","",15,[[],[["error",4],["vec",3],["result",4]]]],[11,"iter_raw_txs","","",15,[[],[["result",4],["vec",3],["error",4]]]],[11,"iter_txs","","",15,[[],[["result",4],["vec",3],["error",4]]]],[11,"get_script_pubkey_from_path","","",15,[[["scripttype",4]],[["error",4],["result",4],["option",4]]]],[11,"get_path_from_script_pubkey","","",15,[[["script",3]],[["result",4],["option",4],["error",4]]]],[11,"get_utxo","","",15,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[11,"get_raw_tx","","",15,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"get_tx","","",15,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"get_last_index","","",15,[[["scripttype",4]],[["option",4],["result",4],["error",4]]]],[11,"increment_last_index","","",15,[[["scripttype",4]],[["result",4],["error",4]]]],[11,"begin_batch","","",15,[[]]],[11,"commit_batch","","",15,[[],[["error",4],["result",4]]]],[11,"extract_policy","magical::descriptor","",20,[[["arc",3],["signerscontainer",3]],[["result",4],["option",4],["error",4]]]],[11,"extract_policy","","",19,[[["arc",3],["signerscontainer",3]],[["result",4],["option",4],["error",4]]]],[11,"coin_select","magical::wallet::coin_selection","",66,[[["utxo",3],["vec",3],["feerate",3]],[["coinselectionresult",3],["result",4],["error",4]]]],[11,"get_capabilities","magical::blockchain::electrum","",62,[[],[["hashset",3],["capability",4]]]],[11,"setup","","",62,[[["option",4],["progress",8]],[["error",4],["result",4]]]],[11,"get_tx","","",62,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"broadcast","","",62,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",62,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",62,[[],[["result",4],["feerate",3],["error",4]]]],[11,"get_capabilities","magical::blockchain::esplora","",7,[[],[["hashset",3],["capability",4]]]],[11,"setup","","",7,[[["option",4],["progress",8]],[["error",4],["result",4]]]],[11,"get_tx","","",7,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"broadcast","","",7,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",7,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",7,[[],[["result",4],["feerate",3],["error",4]]]],[11,"get_capabilities","magical::blockchain::compact_filters","",11,[[],[["hashset",3],["capability",4]]]],[11,"setup","","",11,[[["option",4],["progress",8]],[["error",4],["result",4]]]],[11,"get_tx","","",11,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"broadcast","","",11,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",11,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",11,[[],[["result",4],["feerate",3],["error",4]]]],[11,"as_ref","magical","",4,[[]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["addressvalidatorerror",4]]]],[11,"from","","",2,[[["policyerror",4]]]],[11,"from","","",2,[[["signererror",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",3]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["esploraerror",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["compactfilterserror",4]]]],[11,"from","magical::blockchain::electrum","",62,[[["client",4]]]],[11,"from","magical::blockchain::esplora","",6,[[["error",3]]]],[11,"from","","",6,[[["parseinterror",3]]]],[11,"from","","",6,[[["error",4]]]],[11,"from","magical::blockchain::compact_filters","",8,[[["error",3]]]],[11,"from","","",8,[[["error",3]]]],[11,"from","","",8,[[["error",4]]]],[11,"from","","",8,[[["systemtimeerror",3]]]],[11,"from","","",8,[[["error",4]]]],[11,"from","magical::descriptor::error","",25,[[["error",4]]]],[11,"from","","",25,[[["error",4]]]],[11,"from","","",25,[[["error",4]]]],[11,"from","","",25,[[["error",4]]]],[11,"from","","",25,[[["error",4]]]],[11,"from","","",25,[[["policyerror",4]]]],[11,"from","magical::descriptor::policy","",37,[[]]],[11,"from","","",26,[[["satisfiableitem",4]]]],[11,"from","magical::wallet::signer","",50,[[["hash",3]],[["descriptorpublickey",4],["signerid",4]]]],[11,"from","","",50,[[["fingerprint",3]],[["descriptorpublickey",4],["signerid",4]]]],[11,"from","","",53,[[["keymap",6]],[["descriptorpublickey",4],["signerscontainer",3]]]],[11,"clone","magical::blockchain","",5,[[],["capability",4]]],[11,"clone","","",60,[[],["noopprogress",3]]],[11,"clone","","",61,[[],["logprogress",3]]],[11,"clone","magical::descriptor::policy","",65,[[],["pkorf",3]]],[11,"clone","","",28,[[],["satisfiableitem",4]]],[11,"clone","","",37,[[],["satisfaction",4]]],[11,"clone","","",26,[[],["policy",3]]],[11,"clone","","",27,[[],["condition",3]]],[11,"clone","magical","",4,[[],["scripttype",4]]],[11,"clone","","",43,[[],["feerate",3]]],[11,"clone","","",0,[[],["utxo",3]]],[11,"clone","","",1,[[],["transactiondetails",3]]],[11,"clone","magical::wallet::address_validator","",44,[[],["addressvalidatorerror",4]]],[11,"clone","magical::wallet::signer","",50,[[],["signerid",4]]],[11,"clone","","",51,[[],["signererror",4]]],[11,"clone","","",49,[[],["signerordering",3]]],[11,"clone","","",53,[[],["signerscontainer",3]]],[11,"clone","magical::wallet::tx_builder","",54,[[],["txordering",4]]],[11,"clone","","",55,[[],["changespendpolicy",4]]],[11,"default","magical::blockchain::compact_filters","",9,[[],["mempool",3]]],[11,"default","magical::database::memory","",15,[[],["memorydatabase",3]]],[11,"default","magical::descriptor::policy","",65,[[],["pkorf",3]]],[11,"default","","",27,[[],["condition",3]]],[11,"default","magical","",43,[[]]],[11,"default","","",1,[[],["transactiondetails",3]]],[11,"default","magical::wallet::coin_selection","",66,[[],["dumbcoinselection",3]]],[11,"default","magical::wallet::signer","",49,[[]]],[11,"default","","",53,[[],["signerscontainer",3]]],[11,"default","magical::wallet::tx_builder","",56,[[],["txbuilder",3]]],[11,"default","","",54,[[]]],[11,"default","","",55,[[]]],[11,"cmp","magical::descriptor::policy","",27,[[["condition",3]],["ordering",4]]],[11,"cmp","magical::wallet::signer","",49,[[["signerordering",3]],["ordering",4]]],[11,"cmp","magical::wallet::tx_builder","",54,[[["txordering",4]],["ordering",4]]],[11,"cmp","","",55,[[["changespendpolicy",4]],["ordering",4]]],[11,"eq","magical::blockchain","",5,[[["capability",4]]]],[11,"eq","magical::descriptor::policy","",27,[[["condition",3]]]],[11,"ne","","",27,[[["condition",3]]]],[11,"eq","magical","",4,[[["scripttype",4]]]],[11,"eq","","",43,[[["feerate",3]]]],[11,"ne","","",43,[[["feerate",3]]]],[11,"eq","","",0,[[["utxo",3]]]],[11,"ne","","",0,[[["utxo",3]]]],[11,"eq","","",1,[[["transactiondetails",3]]]],[11,"ne","","",1,[[["transactiondetails",3]]]],[11,"eq","magical::wallet::address_validator","",44,[[["addressvalidatorerror",4]]]],[11,"ne","","",44,[[["addressvalidatorerror",4]]]],[11,"eq","magical::wallet::signer","",50,[[["signerid",4]]]],[11,"ne","","",50,[[["signerid",4]]]],[11,"eq","","",51,[[["signererror",4]]]],[11,"eq","","",49,[[["signerordering",3]]]],[11,"ne","","",49,[[["signerordering",3]]]],[11,"eq","magical::wallet::tx_builder","",54,[[["txordering",4]]]],[11,"eq","","",55,[[["changespendpolicy",4]]]],[11,"partial_cmp","magical::descriptor::policy","",27,[[["condition",3]],[["option",4],["ordering",4]]]],[11,"lt","","",27,[[["condition",3]]]],[11,"le","","",27,[[["condition",3]]]],[11,"gt","","",27,[[["condition",3]]]],[11,"ge","","",27,[[["condition",3]]]],[11,"partial_cmp","magical","",43,[[["feerate",3]],[["option",4],["ordering",4]]]],[11,"lt","","",43,[[["feerate",3]]]],[11,"le","","",43,[[["feerate",3]]]],[11,"gt","","",43,[[["feerate",3]]]],[11,"ge","","",43,[[["feerate",3]]]],[11,"partial_cmp","magical::wallet::signer","",49,[[["signerordering",3]],[["option",4],["ordering",4]]]],[11,"lt","","",49,[[["signerordering",3]]]],[11,"le","","",49,[[["signerordering",3]]]],[11,"gt","","",49,[[["signerordering",3]]]],[11,"ge","","",49,[[["signerordering",3]]]],[11,"partial_cmp","magical::wallet::tx_builder","",54,[[["txordering",4]],[["option",4],["ordering",4]]]],[11,"partial_cmp","","",55,[[["changespendpolicy",4]],[["option",4],["ordering",4]]]],[11,"to_string","magical::wallet::export","",48,[[],["string",3]]],[11,"fmt","magical","",2,[[["formatter",3]],["result",6]]],[11,"fmt","magical::blockchain::esplora","",7,[[["formatter",3]],["result",6]]],[11,"fmt","","",6,[[["formatter",3]],["result",6]]],[11,"fmt","magical::blockchain::compact_filters","",9,[[["formatter",3]],["result",6]]],[11,"fmt","","",10,[[["formatter",3]],["result",6]]],[11,"fmt","","",11,[[["formatter",3]],["result",6]]],[11,"fmt","","",8,[[["formatter",3]],["result",6]]],[11,"fmt","magical::blockchain","",5,[[["formatter",3]],["result",6]]],[11,"fmt","magical::database::memory","",15,[[["formatter",3]],["result",6]]],[11,"fmt","magical::descriptor::error","",25,[[["formatter",3]],["result",6]]],[11,"fmt","magical::descriptor::policy","",65,[[["formatter",3]],["result",6]]],[11,"fmt","","",28,[[["formatter",3]],["result",6]]],[11,"fmt","","",37,[[["formatter",3]],["result",6]]],[11,"fmt","","",26,[[["formatter",3]],["result",6]]],[11,"fmt","","",27,[[["formatter",3]],["result",6]]],[11,"fmt","","",41,[[["formatter",3]],["result",6]]],[11,"fmt","magical","",4,[[["formatter",3]],["result",6]]],[11,"fmt","","",43,[[["formatter",3]],["result",6]]],[11,"fmt","","",0,[[["formatter",3]],["result",6]]],[11,"fmt","","",1,[[["formatter",3]],["result",6]]],[11,"fmt","magical::wallet::address_validator","",44,[[["formatter",3]],["result",6]]],[11,"fmt","magical::wallet::coin_selection","",46,[[["formatter",3]],["result",6]]],[11,"fmt","","",66,[[["formatter",3]],["result",6]]],[11,"fmt","magical::wallet::export","",48,[[["formatter",3]],["result",6]]],[11,"fmt","magical::wallet::signer","",50,[[["formatter",3]],["result",6]]],[11,"fmt","","",51,[[["formatter",3]],["result",6]]],[11,"fmt","","",49,[[["formatter",3]],["result",6]]],[11,"fmt","","",53,[[["formatter",3]],["result",6]]],[11,"fmt","magical::wallet::tx_builder","",56,[[["formatter",3]],["result",6]]],[11,"fmt","","",54,[[["formatter",3]],["result",6]]],[11,"fmt","","",55,[[["formatter",3]],["result",6]]],[11,"fmt","magical","",2,[[["formatter",3]],["result",6]]],[11,"fmt","magical::blockchain::esplora","",6,[[["formatter",3]],["result",6]]],[11,"fmt","magical::blockchain::compact_filters","",8,[[["formatter",3]],["result",6]]],[11,"fmt","magical::descriptor::error","",25,[[["formatter",3]],["result",6]]],[11,"fmt","magical::descriptor::policy","",41,[[["formatter",3]],["result",6]]],[11,"fmt","magical::wallet::address_validator","",44,[[["formatter",3]],["result",6]]],[11,"fmt","magical::wallet::signer","",51,[[["formatter",3]],["result",6]]],[11,"hash","magical::blockchain","",5,[[]]],[11,"hash","magical::descriptor::policy","",27,[[]]],[11,"hash","magical","",4,[[]]],[11,"hash","magical::wallet::signer","",50,[[]]],[11,"hash","magical::wallet::tx_builder","",54,[[]]],[11,"hash","","",55,[[]]],[11,"from_str","magical::wallet::export","",48,[[],["result",4]]],[11,"serialize","magical::descriptor::policy","",65,[[],["result",4]]],[11,"serialize","","",28,[[],["result",4]]],[11,"serialize","","",37,[[],["result",4]]],[11,"serialize","","",26,[[],["result",4]]],[11,"serialize","","",27,[[],["result",4]]],[11,"serialize","magical","",4,[[],["result",4]]],[11,"serialize","","",0,[[],["result",4]]],[11,"serialize","","",1,[[],["result",4]]],[11,"serialize","magical::wallet::export","",48,[[],["result",4]]],[11,"deserialize","magical","",4,[[],["result",4]]],[11,"deserialize","","",0,[[],["result",4]]],[11,"deserialize","","",1,[[],["result",4]]],[11,"deserialize","magical::wallet::export","",48,[[],["result",4]]],[11,"translate_pk","magical::descriptor","Convert a descriptor using abstract keys to one using…",19,[[],[["result",4],["descriptor",4]]]],[11,"address","","Computes the Bitcoin address of the descriptor, if one…",19,[[["network",4]],[["option",4],["address",3]]]],[11,"script_pubkey","","Computes the scriptpubkey of the descriptor",19,[[],["script",3]]],[11,"unsigned_script_sig","","Computes the scriptSig that will be in place for an…",19,[[],["script",3]]],[11,"witness_script","","Computes the \\\"witness script\\\" of the descriptor, i.e. the…",19,[[],["script",3]]],[11,"satisfy","","Attempts to produce a satisfying witness and scriptSig to…",19,[[["txin",3]],[["error",4],["result",4]]]],[11,"max_satisfaction_weight","","Computes an upper bound on the weight of a satisfying…",19,[[]]],[11,"derive","","Derives all wildcard keys in the descriptor using the…",19,[[],[["descriptor",4],["descriptorpublickey",4]]]],[11,"parse_secret","","",19,[[],[["error",4],["result",4]]]],[11,"to_string_with_secret","","",19,[[["hashmap",3]],["string",3]]],[11,"from_ast","","Add type information(Type and Extdata) to Miniscript based…",20,[[["terminal",4]],[["error",4],["miniscript",3],["result",4]]]],[11,"into_inner","","Extracts the `AstElem` representing the root of the…",20,[[],["terminal",4]]],[11,"as_inner","","",20,[[],["terminal",4]]],[11,"parse","","Attempt to parse a script into a Miniscript representation",20,[[["script",3]],[["error",4],["miniscript",3],["result",4]]]],[11,"encode","","Encode as a Bitcoin script",20,[[],["script",3]]],[11,"script_size","","Size, in bytes of the script-pubkey. If this Miniscript is…",20,[[]]],[11,"max_satisfaction_witness_elements","","Maximum number of witness elements used to satisfy the…",20,[[]]],[11,"max_satisfaction_size","","Maximum size, in bytes, of a satisfying witness. For…",20,[[]]],[11,"translate_pk","","This will panic if translatefpk returns an uncompressed…",20,[[],[["miniscript",3],["result",4]]]],[11,"satisfy","","Attempt to produce a satisfying witness for the witness…",20,[[],[["vec",3],["option",4]]]],[11,"translate_pk","","Convert an AST element with one public key type to one of…",23,[[],[["terminal",4],["result",4]]]],[11,"encode","","Encode the element as a fragment of Bitcoin Script. The…",23,[[["builder",3]],["builder",3]]],[11,"script_size","","Size, in bytes of the script-pubkey. If this Miniscript is…",23,[[]]],[11,"max_dissatisfaction_witness_elements","","Maximum number of witness elements used to dissatisfy the…",23,[[],["option",4]]],[11,"max_dissatisfaction_size","","Maximum dissatisfaction cost, in bytes, of a Miniscript…",23,[[],["option",4]]],[11,"max_satisfaction_witness_elements","","Maximum number of witness elements used to satisfy the…",23,[[]]],[11,"max_satisfaction_size","","Maximum size, in bytes, of a satisfying witness. For…",23,[[]]]],"p":[[3,"UTXO"],[3,"TransactionDetails"],[4,"Error"],[13,"FeeRateTooLow"],[4,"ScriptType"],[4,"Capability"],[4,"EsploraError"],[3,"EsploraBlockchain"],[4,"CompactFiltersError"],[3,"Mempool"],[3,"Peer"],[3,"CompactFiltersBlockchain"],[8,"Blockchain"],[8,"OnlineBlockchain"],[8,"Progress"],[3,"MemoryDatabase"],[8,"BatchOperations"],[8,"Database"],[8,"BatchDatabase"],[4,"Descriptor"],[3,"Miniscript"],[8,"MiniscriptKey"],[8,"ScriptContext"],[4,"Terminal"],[8,"ToPublicKey"],[4,"Error"],[3,"Policy"],[3,"Condition"],[4,"SatisfiableItem"],[13,"SHA256Preimage"],[13,"HASH256Preimage"],[13,"RIPEMD160Preimage"],[13,"HASH160Preimage"],[13,"AbsoluteTimelock"],[13,"RelativeTimelock"],[13,"Thresh"],[13,"Multisig"],[4,"Satisfaction"],[13,"Partial"],[13,"PartialComplete"],[13,"Complete"],[4,"PolicyError"],[8,"ExtractPolicy"],[3,"FeeRate"],[4,"AddressValidatorError"],[8,"AddressValidator"],[3,"CoinSelectionResult"],[8,"CoinSelectionAlgorithm"],[3,"WalletExport"],[3,"SignerOrdering"],[4,"SignerId"],[4,"SignerError"],[8,"Signer"],[3,"SignersContainer"],[4,"TxOrdering"],[4,"ChangeSpendPolicy"],[3,"TxBuilder"],[8,"IsDust"],[3,"Wallet"],[3,"OfflineBlockchain"],[3,"NoopProgress"],[3,"LogProgress"],[3,"ElectrumBlockchain"],[4,"Legacy"],[4,"Segwitv0"],[3,"PKOrF"],[3,"DumbCoinSelection"]]}\ -}'); -addSearchOptions(searchIndex);initSearch(searchIndex); \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/settings.css b/static/docs-rs/magical/0.1.0-beta.1/settings.css deleted file mode 100644 index 6ce7665866..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/settings.css +++ /dev/null @@ -1 +0,0 @@ -.setting-line{padding:5px;position:relative;}.setting-line>div{max-width:calc(100% - 74px);display:inline-block;vertical-align:top;font-size:17px;padding-top:2px;}.setting-line>.title{font-size:19px;width:100%;max-width:none;border-bottom:1px solid;}.toggle{position:relative;display:inline-block;width:45px;height:27px;margin-right:20px;}.toggle input{display:none;}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.3s;transition:.3s;}.slider:before{position:absolute;content:"";height:19px;width:19px;left:4px;bottom:4px;background-color:white;-webkit-transition:.3s;transition:.3s;}input:checked+.slider{background-color:#2196F3;}input:focus+.slider{box-shadow:0 0 1px #2196F3;}input:checked+.slider:before{-webkit-transform:translateX(19px);-ms-transform:translateX(19px);transform:translateX(19px);}.setting-line>.sub-settings{padding-left:42px;width:100%;display:block;} \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/settings.html b/static/docs-rs/magical/0.1.0-beta.1/settings.html deleted file mode 100644 index ee333552ee..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/settings.html +++ /dev/null @@ -1,2 +0,0 @@ -Rustdoc settings

Rustdoc settings

Auto-hide item declarations
Auto-hide structs declaration
Auto-hide enums declaration
Auto-hide unions declaration
Auto-hide traits declaration
Auto-hide macros declaration
-
Auto-hide item attributes.
Auto-hide item methods' documentation
Auto-hide trait implementations documentation
Directly go to item in search if there is only one result
Show line numbers on code examples
Disable keyboard shortcuts
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/settings.js b/static/docs-rs/magical/0.1.0-beta.1/settings.js deleted file mode 100644 index 9930309054..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/settings.js +++ /dev/null @@ -1 +0,0 @@ -(function(){function changeSetting(settingName,isEnabled){updateLocalStorage('rustdoc-'+settingName,isEnabled)}function getSettingValue(settingName){return getCurrentValue('rustdoc-'+settingName)}function setEvents(){var elems=document.getElementsByClassName("slider");if(!elems||elems.length===0){return}for(var i=0;i"){sidebar.style.left="";this.style.left="";child.innerText="<";updateLocalStorage("rustdoc-source-sidebar-show","true")}else{sidebar.style.left="-300px";this.style.left="0";child.innerText=">";updateLocalStorage("rustdoc-source-sidebar-show","false")}}function createSidebarToggle(){var sidebarToggle=document.createElement("div");sidebarToggle.id="sidebar-toggle";sidebarToggle.onclick=toggleSidebar;var inner1=document.createElement("div");inner1.style.position="relative";var inner2=document.createElement("div");inner2.style.paddingTop="3px";if(getCurrentValue("rustdoc-source-sidebar-show")==="true"){inner2.innerText="<"}else{inner2.innerText=">";sidebarToggle.style.left="0"}inner1.appendChild(inner2);sidebarToggle.appendChild(inner1);return sidebarToggle}function createSourceSidebar(){if(window.rootPath.endsWith("/")===false){window.rootPath+="/"}var main=document.getElementById("main");var sidebarToggle=createSidebarToggle();main.insertBefore(sidebarToggle,main.firstChild);var sidebar=document.createElement("div");sidebar.id="source-sidebar";if(getCurrentValue("rustdoc-source-sidebar-show")!=="true"){sidebar.style.left="-300px"}var currentFile=getCurrentFilePath();var hasFoundFile=false;var title=document.createElement("div");title.className="title";title.innerText="Files";sidebar.appendChild(title);Object.keys(sourcesIndex).forEach(function(key){sourcesIndex[key].name=key;hasFoundFile=createDirEntry(sourcesIndex[key],sidebar,"",currentFile,hasFoundFile)});main.insertBefore(sidebar,main.firstChild)} \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/compact_filters/mod.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/compact_filters/mod.rs.html deleted file mode 100644 index f31479f75b..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/compact_filters/mod.rs.html +++ /dev/null @@ -1,1127 +0,0 @@ -mod.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-397
-398
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-409
-410
-411
-412
-413
-414
-415
-416
-417
-418
-419
-420
-421
-422
-423
-424
-425
-426
-427
-428
-429
-430
-431
-432
-433
-434
-435
-436
-437
-438
-439
-440
-441
-442
-443
-444
-445
-446
-447
-448
-449
-450
-451
-452
-453
-454
-455
-456
-457
-458
-459
-460
-461
-462
-463
-464
-465
-466
-467
-468
-469
-470
-471
-472
-473
-474
-475
-476
-477
-478
-479
-480
-481
-482
-483
-484
-485
-486
-487
-488
-489
-490
-491
-492
-493
-494
-495
-496
-497
-498
-499
-500
-501
-502
-503
-504
-505
-506
-507
-508
-509
-510
-511
-512
-513
-514
-515
-516
-517
-518
-519
-520
-521
-522
-523
-524
-525
-526
-527
-528
-529
-530
-531
-532
-533
-534
-535
-536
-537
-538
-539
-540
-541
-542
-543
-544
-545
-546
-547
-548
-549
-550
-551
-552
-553
-554
-555
-556
-557
-558
-559
-560
-561
-562
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Compact Filters
-//!
-//! This module contains a multithreaded implementation of an [`OnlineBlockchain`] backend that
-//! uses BIP157 (aka "Neutrino") to populate the wallet's [database](crate::database::Database)
-//! by downloading compact filters from the P2P network.
-//!
-//! Since there are currently very few peers "in the wild" that advertise the required service
-//! flag, this implementation requires that one or more known peers are provided by the user.
-//! No dns or other kinds of peer discovery are done internally.
-//!
-//! Moreover, this module doesn't currently support detecting and resolving conflicts between
-//! messages received by different peers. Thus, it's recommended to use this module by only
-//! connecting to a single peer at a time, optionally by opening multiple connections if it's
-//! desirable to use multiple threads at once to sync in parallel.
-//!
-//! ## Example
-//!
-//! ```no_run
-//! # use std::sync::Arc;
-//! # use bitcoin::*;
-//! # use magical::*;
-//! # use magical::blockchain::compact_filters::*;
-//! let num_threads = 4;
-//!
-//! let mempool = Arc::new(Mempool::default());
-//! let peers = (0..num_threads)
-//!     .map(|_| Peer::connect(
-//!         "btcd-mainnet.lightning.computer:8333",
-//!         Arc::clone(&mempool),
-//!         Network::Bitcoin,
-//!     ))
-//!     .collect::<Result<_, _>>()?;
-//! let blockchain = CompactFiltersBlockchain::new(peers, "./wallet-filters", Some(500_000))?;
-//! # Ok::<(), magical::error::Error>(())
-//! ```
-
-use std::collections::HashSet;
-use std::fmt;
-use std::path::Path;
-use std::sync::atomic::{AtomicUsize, Ordering};
-use std::sync::{Arc, Mutex};
-
-#[allow(unused_imports)]
-use log::{debug, error, info, trace};
-
-use bitcoin::network::message_blockdata::Inventory;
-use bitcoin::{OutPoint, Transaction, Txid};
-
-use rocksdb::{Options, SliceTransform, DB};
-
-mod peer;
-mod store;
-mod sync;
-
-use super::{Blockchain, Capability, OnlineBlockchain, Progress};
-use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
-use crate::error::Error;
-use crate::types::{ScriptType, TransactionDetails, UTXO};
-use crate::FeeRate;
-
-use peer::*;
-use store::*;
-use sync::*;
-
-pub use peer::{Mempool, Peer};
-
-const SYNC_HEADERS_COST: f32 = 1.0;
-const SYNC_FILTERS_COST: f32 = 11.6 * 1_000.0;
-const PROCESS_BLOCKS_COST: f32 = 20_000.0;
-
-/// Structure implementing the required blockchain traits
-///
-/// ## Example
-/// See the [`blockchain::compact_filters`](crate::blockchain::compact_filters) module for a usage example.
-#[derive(Debug)]
-pub struct CompactFiltersBlockchain(Option<CompactFilters>);
-
-impl CompactFiltersBlockchain {
-    /// Construct a new instance given a list of peers, a path to store headers and block
-    /// filters downloaded during the sync and optionally a number of blocks to ignore starting
-    /// from the genesis while scanning for the wallet's outputs.
-    ///
-    /// For each [`Peer`] specified a new thread will be spawned to download and verify the filters
-    /// in parallel. It's currently recommended to only connect to a single peer to avoid
-    /// inconsistencies in the data returned, optionally with multiple connections in parallel to
-    /// speed-up the sync process.
-    pub fn new<P: AsRef<Path>>(
-        peers: Vec<Peer>,
-        storage_dir: P,
-        skip_blocks: Option<usize>,
-    ) -> Result<Self, CompactFiltersError> {
-        Ok(CompactFiltersBlockchain(Some(CompactFilters::new(
-            peers,
-            storage_dir,
-            skip_blocks,
-        )?)))
-    }
-}
-
-/// Internal struct that contains the state of a [`CompactFiltersBlockchain`]
-#[derive(Debug)]
-struct CompactFilters {
-    peers: Vec<Arc<Peer>>,
-    headers: Arc<ChainStore<Full>>,
-    skip_blocks: Option<usize>,
-}
-
-impl CompactFilters {
-    /// Constructor, see [`CompactFiltersBlockchain::new`] for the documentation
-    pub fn new<P: AsRef<Path>>(
-        peers: Vec<Peer>,
-        storage_dir: P,
-        skip_blocks: Option<usize>,
-    ) -> Result<Self, CompactFiltersError> {
-        if peers.is_empty() {
-            return Err(CompactFiltersError::NoPeers);
-        }
-
-        let mut opts = Options::default();
-        opts.create_if_missing(true);
-        opts.set_prefix_extractor(SliceTransform::create_fixed_prefix(16));
-
-        let network = peers[0].get_network();
-
-        let cfs = DB::list_cf(&opts, &storage_dir).unwrap_or(vec!["default".to_string()]);
-        let db = DB::open_cf(&opts, &storage_dir, &cfs)?;
-        let headers = Arc::new(ChainStore::new(db, network)?);
-
-        // try to recover partial snapshots
-        for cf_name in &cfs {
-            if !cf_name.starts_with("_headers:") {
-                continue;
-            }
-
-            info!("Trying to recover: {:?}", cf_name);
-            headers.recover_snapshot(cf_name)?;
-        }
-
-        Ok(CompactFilters {
-            peers: peers.into_iter().map(Arc::new).collect(),
-            headers,
-            skip_blocks,
-        })
-    }
-
-    /// Process a transaction by looking for inputs that spend from a UTXO in the database or
-    /// outputs that send funds to a know script_pubkey.
-    fn process_tx<D: BatchDatabase>(
-        &self,
-        database: &mut D,
-        tx: &Transaction,
-        height: Option<u32>,
-        timestamp: u64,
-        internal_max_deriv: &mut Option<u32>,
-        external_max_deriv: &mut Option<u32>,
-    ) -> Result<(), Error> {
-        let mut updates = database.begin_batch();
-
-        let mut incoming: u64 = 0;
-        let mut outgoing: u64 = 0;
-
-        let mut inputs_sum: u64 = 0;
-        let mut outputs_sum: u64 = 0;
-
-        // look for our own inputs
-        for (i, input) in tx.input.iter().enumerate() {
-            if let Some(previous_output) = database.get_previous_output(&input.previous_output)? {
-                inputs_sum += previous_output.value;
-
-                if database.is_mine(&previous_output.script_pubkey)? {
-                    outgoing += previous_output.value;
-
-                    debug!("{} input #{} is mine, removing from utxo", tx.txid(), i);
-                    updates.del_utxo(&input.previous_output)?;
-                }
-            }
-        }
-
-        for (i, output) in tx.output.iter().enumerate() {
-            // to compute the fees later
-            outputs_sum += output.value;
-
-            // this output is ours, we have a path to derive it
-            if let Some((script_type, child)) =
-                database.get_path_from_script_pubkey(&output.script_pubkey)?
-            {
-                debug!("{} output #{} is mine, adding utxo", tx.txid(), i);
-                updates.set_utxo(&UTXO {
-                    outpoint: OutPoint::new(tx.txid(), i as u32),
-                    txout: output.clone(),
-                    is_internal: script_type.is_internal(),
-                })?;
-                incoming += output.value;
-
-                if script_type == ScriptType::Internal
-                    && (internal_max_deriv.is_none() || child > internal_max_deriv.unwrap_or(0))
-                {
-                    *internal_max_deriv = Some(child);
-                } else if script_type == ScriptType::External
-                    && (external_max_deriv.is_none() || child > external_max_deriv.unwrap_or(0))
-                {
-                    *external_max_deriv = Some(child);
-                }
-            }
-        }
-
-        if incoming > 0 || outgoing > 0 {
-            let tx = TransactionDetails {
-                txid: tx.txid(),
-                transaction: Some(tx.clone()),
-                received: incoming,
-                sent: outgoing,
-                height,
-                timestamp,
-                fees: inputs_sum.checked_sub(outputs_sum).unwrap_or(0),
-            };
-
-            info!("Saving tx {}", tx.txid);
-            updates.set_tx(&tx)?;
-        }
-
-        database.commit_batch(updates)?;
-
-        Ok(())
-    }
-}
-
-impl Blockchain for CompactFiltersBlockchain {
-    fn offline() -> Self {
-        CompactFiltersBlockchain(None)
-    }
-
-    fn is_online(&self) -> bool {
-        self.0.is_some()
-    }
-}
-
-impl OnlineBlockchain for CompactFiltersBlockchain {
-    fn get_capabilities(&self) -> HashSet<Capability> {
-        vec![Capability::FullHistory].into_iter().collect()
-    }
-
-    fn setup<D: BatchDatabase, P: 'static + Progress>(
-        &self,
-        _stop_gap: Option<usize>, // TODO: move to electrum and esplora only
-        database: &mut D,
-        progress_update: P,
-    ) -> Result<(), Error> {
-        let inner = self.0.as_ref().ok_or(Error::OfflineClient)?;
-        let first_peer = &inner.peers[0];
-
-        let skip_blocks = inner.skip_blocks.unwrap_or(0);
-
-        let cf_sync = Arc::new(CFSync::new(Arc::clone(&inner.headers), skip_blocks, 0x00)?);
-
-        let initial_height = inner.headers.get_height()?;
-        let total_bundles = (first_peer.get_version().start_height as usize)
-            .checked_sub(skip_blocks)
-            .map(|x| x / 1000)
-            .unwrap_or(0)
-            + 1;
-        let expected_bundles_to_sync = total_bundles
-            .checked_sub(cf_sync.pruned_bundles()?)
-            .unwrap_or(0);
-
-        let headers_cost = (first_peer.get_version().start_height as usize)
-            .checked_sub(initial_height)
-            .unwrap_or(0) as f32
-            * SYNC_HEADERS_COST;
-        let filters_cost = expected_bundles_to_sync as f32 * SYNC_FILTERS_COST;
-
-        let total_cost = headers_cost + filters_cost + PROCESS_BLOCKS_COST;
-
-        if let Some(snapshot) = sync::sync_headers(
-            Arc::clone(&first_peer),
-            Arc::clone(&inner.headers),
-            |new_height| {
-                let local_headers_cost =
-                    new_height.checked_sub(initial_height).unwrap_or(0) as f32 * SYNC_HEADERS_COST;
-                progress_update.update(
-                    local_headers_cost / total_cost * 100.0,
-                    Some(format!("Synced headers to {}", new_height)),
-                )
-            },
-        )? {
-            if snapshot.work()? > inner.headers.work()? {
-                info!("Applying snapshot with work: {}", snapshot.work()?);
-                inner.headers.apply_snapshot(snapshot)?;
-            }
-        }
-
-        let synced_height = inner.headers.get_height()?;
-        let buried_height = synced_height
-            .checked_sub(sync::BURIED_CONFIRMATIONS)
-            .unwrap_or(0);
-        info!("Synced headers to height: {}", synced_height);
-
-        cf_sync.prepare_sync(Arc::clone(&first_peer))?;
-
-        let all_scripts = Arc::new(
-            database
-                .iter_script_pubkeys(None)?
-                .into_iter()
-                .map(|s| s.to_bytes())
-                .collect::<Vec<_>>(),
-        );
-
-        let last_synced_block = Arc::new(Mutex::new(synced_height));
-        let synced_bundles = Arc::new(AtomicUsize::new(0));
-        let progress_update = Arc::new(Mutex::new(progress_update));
-
-        let mut threads = Vec::with_capacity(inner.peers.len());
-        for peer in &inner.peers {
-            let cf_sync = Arc::clone(&cf_sync);
-            let peer = Arc::clone(&peer);
-            let headers = Arc::clone(&inner.headers);
-            let all_scripts = Arc::clone(&all_scripts);
-            let last_synced_block = Arc::clone(&last_synced_block);
-            let progress_update = Arc::clone(&progress_update);
-            let synced_bundles = Arc::clone(&synced_bundles);
-
-            let thread = std::thread::spawn(move || {
-                cf_sync.capture_thread_for_sync(
-                    peer,
-                    |block_hash, filter| {
-                        if !filter
-                            .match_any(block_hash, &mut all_scripts.iter().map(AsRef::as_ref))?
-                        {
-                            return Ok(false);
-                        }
-
-                        let block_height = headers.get_height_for(block_hash)?.unwrap_or(0);
-                        let saved_correct_block = match headers.get_full_block(block_height)? {
-                            Some(block) if &block.block_hash() == block_hash => true,
-                            _ => false,
-                        };
-
-                        if saved_correct_block {
-                            Ok(false)
-                        } else {
-                            let mut last_synced_block = last_synced_block.lock().unwrap();
-
-                            // If we download a block older than `last_synced_block`, we update it so that
-                            // we know to delete and re-process all txs starting from that height
-                            if block_height < *last_synced_block {
-                                *last_synced_block = block_height;
-                            }
-
-                            Ok(true)
-                        }
-                    },
-                    |index| {
-                        let synced_bundles = synced_bundles.fetch_add(1, Ordering::SeqCst);
-                        let local_filters_cost = synced_bundles as f32 * SYNC_FILTERS_COST;
-                        progress_update.lock().unwrap().update(
-                            (headers_cost + local_filters_cost) / total_cost * 100.0,
-                            Some(format!(
-                                "Synced filters {} - {}",
-                                index * 1000 + 1,
-                                (index + 1) * 1000
-                            )),
-                        )
-                    },
-                )
-            });
-
-            threads.push(thread);
-        }
-
-        for t in threads {
-            t.join().unwrap()?;
-        }
-
-        progress_update.lock().unwrap().update(
-            (headers_cost + filters_cost) / total_cost * 100.0,
-            Some("Processing downloaded blocks and mempool".into()),
-        )?;
-
-        // delete all txs newer than last_synced_block
-        let last_synced_block = *last_synced_block.lock().unwrap();
-        log::debug!(
-            "Dropping transactions newer than `last_synced_block` = {}",
-            last_synced_block
-        );
-        let mut updates = database.begin_batch();
-        for details in database.iter_txs(false)? {
-            match details.height {
-                Some(height) if (height as usize) < last_synced_block => continue,
-                _ => updates.del_tx(&details.txid, false)?,
-            };
-        }
-        database.commit_batch(updates)?;
-
-        first_peer.ask_for_mempool()?;
-
-        let mut internal_max_deriv = None;
-        let mut external_max_deriv = None;
-
-        for (height, block) in inner.headers.iter_full_blocks()? {
-            for tx in &block.txdata {
-                inner.process_tx(
-                    database,
-                    tx,
-                    Some(height as u32),
-                    0,
-                    &mut internal_max_deriv,
-                    &mut external_max_deriv,
-                )?;
-            }
-        }
-        for tx in first_peer.get_mempool().iter_txs().iter() {
-            inner.process_tx(
-                database,
-                tx,
-                None,
-                0,
-                &mut internal_max_deriv,
-                &mut external_max_deriv,
-            )?;
-        }
-
-        let current_ext = database.get_last_index(ScriptType::External)?.unwrap_or(0);
-        let first_ext_new = external_max_deriv.map(|x| x + 1).unwrap_or(0);
-        if first_ext_new > current_ext {
-            info!("Setting external index to {}", first_ext_new);
-            database.set_last_index(ScriptType::External, first_ext_new)?;
-        }
-
-        let current_int = database.get_last_index(ScriptType::Internal)?.unwrap_or(0);
-        let first_int_new = internal_max_deriv.map(|x| x + 1).unwrap_or(0);
-        if first_int_new > current_int {
-            info!("Setting internal index to {}", first_int_new);
-            database.set_last_index(ScriptType::Internal, first_int_new)?;
-        }
-
-        info!("Dropping blocks until {}", buried_height);
-        inner.headers.delete_blocks_until(buried_height)?;
-
-        progress_update
-            .lock()
-            .unwrap()
-            .update(100.0, Some("Done".into()))?;
-
-        Ok(())
-    }
-
-    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
-        let inner = self.0.as_ref().ok_or(Error::OfflineClient)?;
-
-        Ok(inner.peers[0]
-            .get_mempool()
-            .get_tx(&Inventory::Transaction(*txid)))
-    }
-
-    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
-        let inner = self.0.as_ref().ok_or(Error::OfflineClient)?;
-        inner.peers[0].broadcast_tx(tx.clone())?;
-
-        Ok(())
-    }
-
-    fn get_height(&self) -> Result<u32, Error> {
-        let inner = self.0.as_ref().ok_or(Error::OfflineClient)?;
-
-        Ok(inner.headers.get_height()? as u32)
-    }
-
-    fn estimate_fee(&self, _target: usize) -> Result<FeeRate, Error> {
-        // TODO
-        Ok(FeeRate::default())
-    }
-}
-
-/// An error that can occur during sync with a [`CompactFiltersBlockchain`]
-#[derive(Debug)]
-pub enum CompactFiltersError {
-    /// A peer sent an invalid or unexpected response
-    InvalidResponse,
-    /// The headers returned are invalid
-    InvalidHeaders,
-    /// The compact filter headers returned are invalid
-    InvalidFilterHeader,
-    /// The compact filter returned is invalid
-    InvalidFilter,
-    /// The peer is missing a block in the valid chain
-    MissingBlock,
-    /// The data stored in the block filters storage are corrupted
-    DataCorruption,
-
-    /// A peer is not connected
-    NotConnected,
-    /// A peer took too long to reply to one of our messages
-    Timeout,
-
-    /// No peers have been specified
-    NoPeers,
-
-    /// Internal database error
-    DB(rocksdb::Error),
-    /// Internal I/O error
-    IO(std::io::Error),
-    /// Invalid BIP158 filter
-    BIP158(bitcoin::util::bip158::Error),
-    /// Internal system time error
-    Time(std::time::SystemTimeError),
-
-    /// Wrapper for [`crate::error::Error`]
-    Global(Box<crate::error::Error>),
-}
-
-impl fmt::Display for CompactFiltersError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}", self)
-    }
-}
-
-impl std::error::Error for CompactFiltersError {}
-
-macro_rules! impl_error {
-    ( $from:ty, $to:ident ) => {
-        impl std::convert::From<$from> for CompactFiltersError {
-            fn from(err: $from) -> Self {
-                CompactFiltersError::$to(err)
-            }
-        }
-    };
-}
-
-impl_error!(rocksdb::Error, DB);
-impl_error!(std::io::Error, IO);
-impl_error!(bitcoin::util::bip158::Error, BIP158);
-impl_error!(std::time::SystemTimeError, Time);
-
-impl From<crate::error::Error> for CompactFiltersError {
-    fn from(err: crate::error::Error) -> Self {
-        CompactFiltersError::Global(Box::new(err))
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/compact_filters/peer.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/compact_filters/peer.rs.html deleted file mode 100644 index 7022000955..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/compact_filters/peer.rs.html +++ /dev/null @@ -1,1103 +0,0 @@ -peer.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-397
-398
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-409
-410
-411
-412
-413
-414
-415
-416
-417
-418
-419
-420
-421
-422
-423
-424
-425
-426
-427
-428
-429
-430
-431
-432
-433
-434
-435
-436
-437
-438
-439
-440
-441
-442
-443
-444
-445
-446
-447
-448
-449
-450
-451
-452
-453
-454
-455
-456
-457
-458
-459
-460
-461
-462
-463
-464
-465
-466
-467
-468
-469
-470
-471
-472
-473
-474
-475
-476
-477
-478
-479
-480
-481
-482
-483
-484
-485
-486
-487
-488
-489
-490
-491
-492
-493
-494
-495
-496
-497
-498
-499
-500
-501
-502
-503
-504
-505
-506
-507
-508
-509
-510
-511
-512
-513
-514
-515
-516
-517
-518
-519
-520
-521
-522
-523
-524
-525
-526
-527
-528
-529
-530
-531
-532
-533
-534
-535
-536
-537
-538
-539
-540
-541
-542
-543
-544
-545
-546
-547
-548
-549
-550
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-use std::collections::HashMap;
-use std::net::{TcpStream, ToSocketAddrs};
-use std::sync::{Arc, Condvar, Mutex, RwLock};
-use std::thread;
-use std::time::{Duration, SystemTime, UNIX_EPOCH};
-
-use socks::{Socks5Stream, ToTargetAddr};
-
-use rand::{thread_rng, Rng};
-
-use bitcoin::consensus::Encodable;
-use bitcoin::hash_types::BlockHash;
-use bitcoin::hashes::Hash;
-use bitcoin::network::constants::ServiceFlags;
-use bitcoin::network::message::{NetworkMessage, RawNetworkMessage};
-use bitcoin::network::message_blockdata::*;
-use bitcoin::network::message_filter::*;
-use bitcoin::network::message_network::VersionMessage;
-use bitcoin::network::stream_reader::StreamReader;
-use bitcoin::network::Address;
-use bitcoin::{Block, Network, Transaction, Txid};
-
-use super::CompactFiltersError;
-
-type ResponsesMap = HashMap<&'static str, Arc<(Mutex<Vec<NetworkMessage>>, Condvar)>>;
-
-pub(crate) const TIMEOUT_SECS: u64 = 30;
-
-/// Container for unconfirmed, but valid Bitcoin transactions
-///
-/// It is normally shared between [`Peer`]s with the use of [`Arc`], so that transactions are not
-/// duplicated in memory.
-#[derive(Debug, Default)]
-pub struct Mempool {
-    txs: RwLock<HashMap<Txid, Transaction>>,
-}
-
-impl Mempool {
-    /// Add a transaction to the mempool
-    ///
-    /// Note that this doesn't propagate the transaction to other
-    /// peers. To do that, [`broadcast`](crate::blockchain::OnlineBlockchain::broadcast) should be used.
-    pub fn add_tx(&self, tx: Transaction) {
-        self.txs.write().unwrap().insert(tx.txid(), tx);
-    }
-
-    /// Look-up a transaction in the mempool given an [`Inventory`] request
-    pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction> {
-        let txid = match inventory {
-            Inventory::Error | Inventory::Block(_) | Inventory::WitnessBlock(_) => return None,
-            Inventory::Transaction(txid) => *txid,
-            Inventory::WitnessTransaction(wtxid) => Txid::from_inner(wtxid.into_inner()),
-        };
-        self.txs.read().unwrap().get(&txid).cloned()
-    }
-
-    /// Return whether or not the mempool contains a transaction with a given txid
-    pub fn has_tx(&self, txid: &Txid) -> bool {
-        self.txs.read().unwrap().contains_key(txid)
-    }
-
-    /// Return the list of transactions contained in the mempool
-    pub fn iter_txs(&self) -> Vec<Transaction> {
-        self.txs.read().unwrap().values().cloned().collect()
-    }
-}
-
-/// A Bitcoin peer
-#[derive(Debug)]
-pub struct Peer {
-    writer: Arc<Mutex<TcpStream>>,
-    responses: Arc<RwLock<ResponsesMap>>,
-
-    reader_thread: thread::JoinHandle<()>,
-    connected: Arc<RwLock<bool>>,
-
-    mempool: Arc<Mempool>,
-
-    version: VersionMessage,
-    network: Network,
-}
-
-impl Peer {
-    /// Connect to a peer over a plaintext TCP connection
-    ///
-    /// This function internally spawns a new thread that will monitor incoming messages from the
-    /// peer, and optionally reply to some of them transparently, like [pings](NetworkMessage::Ping)
-    pub fn connect<A: ToSocketAddrs>(
-        address: A,
-        mempool: Arc<Mempool>,
-        network: Network,
-    ) -> Result<Self, CompactFiltersError> {
-        let stream = TcpStream::connect(address)?;
-
-        Peer::from_stream(stream, mempool, network)
-    }
-
-    /// Connect to a peer through a SOCKS5 proxy, optionally by using some credentials, specified
-    /// as a tuple of `(username, password)`
-    ///
-    /// This function internally spawns a new thread that will monitor incoming messages from the
-    /// peer, and optionally reply to some of them transparently, like [pings](NetworkMessage::Ping)
-    pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
-        target: T,
-        proxy: P,
-        credentials: Option<(&str, &str)>,
-        mempool: Arc<Mempool>,
-        network: Network,
-    ) -> Result<Self, CompactFiltersError> {
-        let socks_stream = if let Some((username, password)) = credentials {
-            Socks5Stream::connect_with_password(proxy, target, username, password)?
-        } else {
-            Socks5Stream::connect(proxy, target)?
-        };
-
-        Peer::from_stream(socks_stream.into_inner(), mempool, network)
-    }
-
-    /// Create a [`Peer`] from an already connected TcpStream
-    fn from_stream(
-        stream: TcpStream,
-        mempool: Arc<Mempool>,
-        network: Network,
-    ) -> Result<Self, CompactFiltersError> {
-        let writer = Arc::new(Mutex::new(stream.try_clone()?));
-        let responses: Arc<RwLock<ResponsesMap>> = Arc::new(RwLock::new(HashMap::new()));
-        let connected = Arc::new(RwLock::new(true));
-
-        let mut locked_writer = writer.lock().unwrap();
-
-        let reader_thread_responses = Arc::clone(&responses);
-        let reader_thread_writer = Arc::clone(&writer);
-        let reader_thread_mempool = Arc::clone(&mempool);
-        let reader_thread_connected = Arc::clone(&connected);
-        let reader_thread = thread::spawn(move || {
-            Self::reader_thread(
-                network,
-                stream,
-                reader_thread_responses,
-                reader_thread_writer,
-                reader_thread_mempool,
-                reader_thread_connected,
-            )
-        });
-
-        let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i64;
-        let nonce = thread_rng().gen();
-        let receiver = Address::new(&locked_writer.peer_addr()?, ServiceFlags::NONE);
-        let sender = Address {
-            services: ServiceFlags::NONE,
-            address: [0u16; 8],
-            port: 0,
-        };
-
-        Self::_send(
-            &mut locked_writer,
-            network.magic(),
-            NetworkMessage::Version(VersionMessage::new(
-                ServiceFlags::WITNESS,
-                timestamp,
-                receiver,
-                sender,
-                nonce,
-                "MagicalBitcoinWallet".into(),
-                0,
-            )),
-        )?;
-        let version = if let NetworkMessage::Version(version) =
-            Self::_recv(&responses, "version", None)?.unwrap()
-        {
-            version
-        } else {
-            return Err(CompactFiltersError::InvalidResponse);
-        };
-
-        if let NetworkMessage::Verack = Self::_recv(&responses, "verack", None)?.unwrap() {
-            Self::_send(&mut locked_writer, network.magic(), NetworkMessage::Verack)?;
-        } else {
-            return Err(CompactFiltersError::InvalidResponse);
-        }
-
-        std::mem::drop(locked_writer);
-
-        Ok(Peer {
-            writer,
-            reader_thread,
-            responses,
-            connected,
-            mempool,
-            network,
-            version,
-        })
-    }
-
-    /// Send a Bitcoin network message
-    fn _send(
-        writer: &mut TcpStream,
-        magic: u32,
-        payload: NetworkMessage,
-    ) -> Result<(), CompactFiltersError> {
-        log::trace!("==> {:?}", payload);
-
-        let raw_message = RawNetworkMessage { magic, payload };
-
-        raw_message
-            .consensus_encode(writer)
-            .map_err(|_| CompactFiltersError::DataCorruption)?;
-
-        Ok(())
-    }
-
-    /// Wait for a specific incoming Bitcoin message, optionally with a timeout
-    fn _recv(
-        responses: &Arc<RwLock<ResponsesMap>>,
-        wait_for: &'static str,
-        timeout: Option<Duration>,
-    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
-        let message_resp = {
-            let mut lock = responses.write().unwrap();
-            let message_resp = lock.entry(wait_for).or_default();
-            Arc::clone(&message_resp)
-        };
-
-        let (lock, cvar) = &*message_resp;
-
-        let mut messages = lock.lock().unwrap();
-        while messages.is_empty() {
-            match timeout {
-                None => messages = cvar.wait(messages).unwrap(),
-                Some(t) => {
-                    let result = cvar.wait_timeout(messages, t).unwrap();
-                    if result.1.timed_out() {
-                        return Ok(None);
-                    }
-
-                    messages = result.0;
-                }
-            }
-        }
-
-        Ok(messages.pop())
-    }
-
-    /// Return the [`VersionMessage`] sent by the peer
-    pub fn get_version(&self) -> &VersionMessage {
-        &self.version
-    }
-
-    /// Return the Bitcoin [`Network`] in use
-    pub fn get_network(&self) -> Network {
-        self.network
-    }
-
-    /// Return the mempool used by this peer
-    pub fn get_mempool(&self) -> Arc<Mempool> {
-        Arc::clone(&self.mempool)
-    }
-
-    /// Return whether or not the peer is still connected
-    pub fn is_connected(&self) -> bool {
-        *self.connected.read().unwrap()
-    }
-
-    /// Internal function called once the `reader_thread` is spawned
-    fn reader_thread(
-        network: Network,
-        connection: TcpStream,
-        reader_thread_responses: Arc<RwLock<ResponsesMap>>,
-        reader_thread_writer: Arc<Mutex<TcpStream>>,
-        reader_thread_mempool: Arc<Mempool>,
-        reader_thread_connected: Arc<RwLock<bool>>,
-    ) {
-        macro_rules! check_disconnect {
-            ($call:expr) => {
-                match $call {
-                    Ok(good) => good,
-                    Err(e) => {
-                        log::debug!("Error {:?}", e);
-                        *reader_thread_connected.write().unwrap() = false;
-
-                        break;
-                    }
-                }
-            };
-        }
-
-        let mut reader = StreamReader::new(connection, None);
-        loop {
-            let raw_message: RawNetworkMessage = check_disconnect!(reader.read_next());
-
-            let in_message = if raw_message.magic != network.magic() {
-                continue;
-            } else {
-                raw_message.payload
-            };
-
-            log::trace!("<== {:?}", in_message);
-
-            match in_message {
-                NetworkMessage::Ping(nonce) => {
-                    check_disconnect!(Self::_send(
-                        &mut reader_thread_writer.lock().unwrap(),
-                        network.magic(),
-                        NetworkMessage::Pong(nonce),
-                    ));
-
-                    continue;
-                }
-                NetworkMessage::Alert(_) => continue,
-                NetworkMessage::GetData(ref inv) => {
-                    let (found, not_found): (Vec<_>, Vec<_>) = inv
-                        .into_iter()
-                        .map(|item| (*item, reader_thread_mempool.get_tx(item)))
-                        .partition(|(_, d)| d.is_some());
-                    for (_, found_tx) in found {
-                        check_disconnect!(Self::_send(
-                            &mut reader_thread_writer.lock().unwrap(),
-                            network.magic(),
-                            NetworkMessage::Tx(found_tx.unwrap()),
-                        ));
-                    }
-
-                    if !not_found.is_empty() {
-                        check_disconnect!(Self::_send(
-                            &mut reader_thread_writer.lock().unwrap(),
-                            network.magic(),
-                            NetworkMessage::NotFound(
-                                not_found.into_iter().map(|(i, _)| i).collect(),
-                            ),
-                        ));
-                    }
-                }
-                _ => {}
-            }
-
-            let message_resp = {
-                let mut lock = reader_thread_responses.write().unwrap();
-                let message_resp = lock.entry(in_message.cmd()).or_default();
-                Arc::clone(&message_resp)
-            };
-
-            let (lock, cvar) = &*message_resp;
-            let mut messages = lock.lock().unwrap();
-            messages.push(in_message);
-            cvar.notify_all();
-        }
-    }
-
-    /// Send a raw Bitcoin message to the peer
-    pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError> {
-        let mut writer = self.writer.lock().unwrap();
-        Self::_send(&mut writer, self.network.magic(), payload)
-    }
-
-    /// Waits for a specific incoming Bitcoin message, optionally with a timeout
-    pub fn recv(
-        &self,
-        wait_for: &'static str,
-        timeout: Option<Duration>,
-    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
-        Self::_recv(&self.responses, wait_for, timeout)
-    }
-}
-
-pub trait CompactFiltersPeer {
-    fn get_cf_checkpt(
-        &self,
-        filter_type: u8,
-        stop_hash: BlockHash,
-    ) -> Result<CFCheckpt, CompactFiltersError>;
-    fn get_cf_headers(
-        &self,
-        filter_type: u8,
-        start_height: u32,
-        stop_hash: BlockHash,
-    ) -> Result<CFHeaders, CompactFiltersError>;
-    fn get_cf_filters(
-        &self,
-        filter_type: u8,
-        start_height: u32,
-        stop_hash: BlockHash,
-    ) -> Result<(), CompactFiltersError>;
-    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError>;
-}
-
-impl CompactFiltersPeer for Peer {
-    fn get_cf_checkpt(
-        &self,
-        filter_type: u8,
-        stop_hash: BlockHash,
-    ) -> Result<CFCheckpt, CompactFiltersError> {
-        self.send(NetworkMessage::GetCFCheckpt(GetCFCheckpt {
-            filter_type,
-            stop_hash,
-        }))?;
-
-        let response = self
-            .recv("cfcheckpt", Some(Duration::from_secs(TIMEOUT_SECS)))?
-            .ok_or(CompactFiltersError::Timeout)?;
-        let response = match response {
-            NetworkMessage::CFCheckpt(response) => response,
-            _ => return Err(CompactFiltersError::InvalidResponse),
-        };
-
-        if response.filter_type != filter_type {
-            return Err(CompactFiltersError::InvalidResponse);
-        }
-
-        Ok(response)
-    }
-
-    fn get_cf_headers(
-        &self,
-        filter_type: u8,
-        start_height: u32,
-        stop_hash: BlockHash,
-    ) -> Result<CFHeaders, CompactFiltersError> {
-        self.send(NetworkMessage::GetCFHeaders(GetCFHeaders {
-            filter_type,
-            start_height,
-            stop_hash,
-        }))?;
-
-        let response = self
-            .recv("cfheaders", Some(Duration::from_secs(TIMEOUT_SECS)))?
-            .ok_or(CompactFiltersError::Timeout)?;
-        let response = match response {
-            NetworkMessage::CFHeaders(response) => response,
-            _ => return Err(CompactFiltersError::InvalidResponse),
-        };
-
-        if response.filter_type != filter_type {
-            return Err(CompactFiltersError::InvalidResponse);
-        }
-
-        Ok(response)
-    }
-
-    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError> {
-        let response = self
-            .recv("cfilter", Some(Duration::from_secs(TIMEOUT_SECS)))?
-            .ok_or(CompactFiltersError::Timeout)?;
-        let response = match response {
-            NetworkMessage::CFilter(response) => response,
-            _ => return Err(CompactFiltersError::InvalidResponse),
-        };
-
-        Ok(response)
-    }
-
-    fn get_cf_filters(
-        &self,
-        filter_type: u8,
-        start_height: u32,
-        stop_hash: BlockHash,
-    ) -> Result<(), CompactFiltersError> {
-        self.send(NetworkMessage::GetCFilters(GetCFilters {
-            filter_type,
-            start_height,
-            stop_hash,
-        }))?;
-
-        Ok(())
-    }
-}
-
-pub trait InvPeer {
-    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError>;
-    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError>;
-    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError>;
-}
-
-impl InvPeer for Peer {
-    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError> {
-        self.send(NetworkMessage::GetData(vec![Inventory::WitnessBlock(
-            block_hash,
-        )]))?;
-
-        match self.recv("block", Some(Duration::from_secs(TIMEOUT_SECS)))? {
-            None => Ok(None),
-            Some(NetworkMessage::Block(response)) => Ok(Some(response)),
-            _ => Err(CompactFiltersError::InvalidResponse),
-        }
-    }
-
-    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError> {
-        self.send(NetworkMessage::MemPool)?;
-        let inv = match self.recv("inv", Some(Duration::from_secs(5)))? {
-            None => return Ok(()), // empty mempool
-            Some(NetworkMessage::Inv(inv)) => inv,
-            _ => return Err(CompactFiltersError::InvalidResponse),
-        };
-
-        let getdata = inv
-            .iter()
-            .cloned()
-            .filter(|item| match item {
-                Inventory::Transaction(txid) if !self.mempool.has_tx(txid) => true,
-                _ => false,
-            })
-            .collect::<Vec<_>>();
-        let num_txs = getdata.len();
-        self.send(NetworkMessage::GetData(getdata))?;
-
-        for _ in 0..num_txs {
-            let tx = self
-                .recv("tx", Some(Duration::from_secs(TIMEOUT_SECS)))?
-                .ok_or(CompactFiltersError::Timeout)?;
-            let tx = match tx {
-                NetworkMessage::Tx(tx) => tx,
-                _ => return Err(CompactFiltersError::InvalidResponse),
-            };
-
-            self.mempool.add_tx(tx);
-        }
-
-        Ok(())
-    }
-
-    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError> {
-        self.mempool.add_tx(tx.clone());
-        self.send(NetworkMessage::Tx(tx))?;
-
-        Ok(())
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/compact_filters/store.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/compact_filters/store.rs.html deleted file mode 100644 index 400c769964..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/compact_filters/store.rs.html +++ /dev/null @@ -1,1811 +0,0 @@ -store.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-397
-398
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-409
-410
-411
-412
-413
-414
-415
-416
-417
-418
-419
-420
-421
-422
-423
-424
-425
-426
-427
-428
-429
-430
-431
-432
-433
-434
-435
-436
-437
-438
-439
-440
-441
-442
-443
-444
-445
-446
-447
-448
-449
-450
-451
-452
-453
-454
-455
-456
-457
-458
-459
-460
-461
-462
-463
-464
-465
-466
-467
-468
-469
-470
-471
-472
-473
-474
-475
-476
-477
-478
-479
-480
-481
-482
-483
-484
-485
-486
-487
-488
-489
-490
-491
-492
-493
-494
-495
-496
-497
-498
-499
-500
-501
-502
-503
-504
-505
-506
-507
-508
-509
-510
-511
-512
-513
-514
-515
-516
-517
-518
-519
-520
-521
-522
-523
-524
-525
-526
-527
-528
-529
-530
-531
-532
-533
-534
-535
-536
-537
-538
-539
-540
-541
-542
-543
-544
-545
-546
-547
-548
-549
-550
-551
-552
-553
-554
-555
-556
-557
-558
-559
-560
-561
-562
-563
-564
-565
-566
-567
-568
-569
-570
-571
-572
-573
-574
-575
-576
-577
-578
-579
-580
-581
-582
-583
-584
-585
-586
-587
-588
-589
-590
-591
-592
-593
-594
-595
-596
-597
-598
-599
-600
-601
-602
-603
-604
-605
-606
-607
-608
-609
-610
-611
-612
-613
-614
-615
-616
-617
-618
-619
-620
-621
-622
-623
-624
-625
-626
-627
-628
-629
-630
-631
-632
-633
-634
-635
-636
-637
-638
-639
-640
-641
-642
-643
-644
-645
-646
-647
-648
-649
-650
-651
-652
-653
-654
-655
-656
-657
-658
-659
-660
-661
-662
-663
-664
-665
-666
-667
-668
-669
-670
-671
-672
-673
-674
-675
-676
-677
-678
-679
-680
-681
-682
-683
-684
-685
-686
-687
-688
-689
-690
-691
-692
-693
-694
-695
-696
-697
-698
-699
-700
-701
-702
-703
-704
-705
-706
-707
-708
-709
-710
-711
-712
-713
-714
-715
-716
-717
-718
-719
-720
-721
-722
-723
-724
-725
-726
-727
-728
-729
-730
-731
-732
-733
-734
-735
-736
-737
-738
-739
-740
-741
-742
-743
-744
-745
-746
-747
-748
-749
-750
-751
-752
-753
-754
-755
-756
-757
-758
-759
-760
-761
-762
-763
-764
-765
-766
-767
-768
-769
-770
-771
-772
-773
-774
-775
-776
-777
-778
-779
-780
-781
-782
-783
-784
-785
-786
-787
-788
-789
-790
-791
-792
-793
-794
-795
-796
-797
-798
-799
-800
-801
-802
-803
-804
-805
-806
-807
-808
-809
-810
-811
-812
-813
-814
-815
-816
-817
-818
-819
-820
-821
-822
-823
-824
-825
-826
-827
-828
-829
-830
-831
-832
-833
-834
-835
-836
-837
-838
-839
-840
-841
-842
-843
-844
-845
-846
-847
-848
-849
-850
-851
-852
-853
-854
-855
-856
-857
-858
-859
-860
-861
-862
-863
-864
-865
-866
-867
-868
-869
-870
-871
-872
-873
-874
-875
-876
-877
-878
-879
-880
-881
-882
-883
-884
-885
-886
-887
-888
-889
-890
-891
-892
-893
-894
-895
-896
-897
-898
-899
-900
-901
-902
-903
-904
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-use std::convert::TryInto;
-use std::fmt;
-use std::io::{Read, Write};
-use std::marker::PhantomData;
-use std::ops::Deref;
-use std::sync::Arc;
-use std::sync::RwLock;
-
-use rand::distributions::Alphanumeric;
-use rand::{thread_rng, Rng};
-
-use rocksdb::{Direction, IteratorMode, ReadOptions, WriteBatch, DB};
-
-use bitcoin::consensus::{deserialize, encode::VarInt, serialize, Decodable, Encodable};
-use bitcoin::hash_types::FilterHash;
-use bitcoin::hashes::hex::FromHex;
-use bitcoin::hashes::{sha256d, Hash};
-use bitcoin::util::bip158::BlockFilter;
-use bitcoin::util::uint::Uint256;
-use bitcoin::Block;
-use bitcoin::BlockHash;
-use bitcoin::BlockHeader;
-use bitcoin::Network;
-
-use super::CompactFiltersError;
-
-lazy_static! {
-    static ref MAINNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A29AB5F49FFFF001D1DAC2B7C0101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
-    static ref TESTNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF001D1AA4AE180101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
-    static ref REGTEST_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF7F20020000000101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
-}
-
-pub trait StoreType: Default + fmt::Debug {}
-
-#[derive(Default, Debug)]
-pub struct Full;
-impl StoreType for Full {}
-#[derive(Default, Debug)]
-pub struct Snapshot;
-impl StoreType for Snapshot {}
-
-pub enum StoreEntry {
-    BlockHeader(Option<usize>),
-    Block(Option<usize>),
-    BlockHeaderIndex(Option<BlockHash>),
-    CFilterTable((u8, Option<usize>)),
-}
-
-impl StoreEntry {
-    pub fn get_prefix(&self) -> Vec<u8> {
-        match self {
-            StoreEntry::BlockHeader(_) => b"z",
-            StoreEntry::Block(_) => b"x",
-            StoreEntry::BlockHeaderIndex(_) => b"i",
-            StoreEntry::CFilterTable(_) => b"t",
-        }
-        .to_vec()
-    }
-
-    pub fn get_key(&self) -> Vec<u8> {
-        let mut prefix = self.get_prefix();
-        match self {
-            StoreEntry::BlockHeader(Some(height)) => {
-                prefix.extend_from_slice(&height.to_be_bytes())
-            }
-            StoreEntry::Block(Some(height)) => prefix.extend_from_slice(&height.to_be_bytes()),
-            StoreEntry::BlockHeaderIndex(Some(hash)) => {
-                prefix.extend_from_slice(&hash.into_inner())
-            }
-            StoreEntry::CFilterTable((filter_type, bundle_index)) => {
-                prefix.push(*filter_type);
-                if let Some(bundle_index) = bundle_index {
-                    prefix.extend_from_slice(&bundle_index.to_be_bytes());
-                }
-            }
-            _ => {}
-        }
-
-        prefix
-    }
-}
-
-pub trait SerializeDb: Sized {
-    fn serialize(&self) -> Vec<u8>;
-    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError>;
-}
-
-impl<T> SerializeDb for T
-where
-    T: Encodable + Decodable,
-{
-    fn serialize(&self) -> Vec<u8> {
-        serialize(self)
-    }
-
-    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError> {
-        Ok(deserialize(data).map_err(|_| CompactFiltersError::DataCorruption)?)
-    }
-}
-
-impl Encodable for FilterHeader {
-    fn consensus_encode<W: Write>(
-        &self,
-        mut e: W,
-    ) -> Result<usize, bitcoin::consensus::encode::Error> {
-        let mut written = self.prev_header_hash.consensus_encode(&mut e)?;
-        written += self.filter_hash.consensus_encode(&mut e)?;
-        Ok(written)
-    }
-}
-
-impl Decodable for FilterHeader {
-    fn consensus_decode<D: Read>(mut d: D) -> Result<Self, bitcoin::consensus::encode::Error> {
-        let prev_header_hash = FilterHeaderHash::consensus_decode(&mut d)?;
-        let filter_hash = FilterHash::consensus_decode(&mut d)?;
-
-        Ok(FilterHeader {
-            prev_header_hash,
-            filter_hash,
-        })
-    }
-}
-
-impl Encodable for BundleStatus {
-    fn consensus_encode<W: Write>(
-        &self,
-        mut e: W,
-    ) -> Result<usize, bitcoin::consensus::encode::Error> {
-        let mut written = 0;
-
-        match self {
-            BundleStatus::Init => {
-                written += 0x00u8.consensus_encode(&mut e)?;
-            }
-            BundleStatus::CFHeaders { cf_headers } => {
-                written += 0x01u8.consensus_encode(&mut e)?;
-                written += VarInt(cf_headers.len() as u64).consensus_encode(&mut e)?;
-                for header in cf_headers {
-                    written += header.consensus_encode(&mut e)?;
-                }
-            }
-            BundleStatus::CFilters { cf_filters } => {
-                written += 0x02u8.consensus_encode(&mut e)?;
-                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
-                for filter in cf_filters {
-                    written += filter.consensus_encode(&mut e)?;
-                }
-            }
-            BundleStatus::Processed { cf_filters } => {
-                written += 0x03u8.consensus_encode(&mut e)?;
-                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
-                for filter in cf_filters {
-                    written += filter.consensus_encode(&mut e)?;
-                }
-            }
-            BundleStatus::Pruned => {
-                written += 0x04u8.consensus_encode(&mut e)?;
-            }
-            BundleStatus::Tip { cf_filters } => {
-                written += 0x05u8.consensus_encode(&mut e)?;
-                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
-                for filter in cf_filters {
-                    written += filter.consensus_encode(&mut e)?;
-                }
-            }
-        }
-
-        Ok(written)
-    }
-}
-
-impl Decodable for BundleStatus {
-    fn consensus_decode<D: Read>(mut d: D) -> Result<Self, bitcoin::consensus::encode::Error> {
-        let byte_type = u8::consensus_decode(&mut d)?;
-        match byte_type {
-            0x00 => Ok(BundleStatus::Init),
-            0x01 => {
-                let num = VarInt::consensus_decode(&mut d)?;
-                let num = num.0 as usize;
-
-                let mut cf_headers = Vec::with_capacity(num);
-                for _ in 0..num {
-                    cf_headers.push(FilterHeader::consensus_decode(&mut d)?);
-                }
-
-                Ok(BundleStatus::CFHeaders { cf_headers })
-            }
-            0x02 => {
-                let num = VarInt::consensus_decode(&mut d)?;
-                let num = num.0 as usize;
-
-                let mut cf_filters = Vec::with_capacity(num);
-                for _ in 0..num {
-                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
-                }
-
-                Ok(BundleStatus::CFilters { cf_filters })
-            }
-            0x03 => {
-                let num = VarInt::consensus_decode(&mut d)?;
-                let num = num.0 as usize;
-
-                let mut cf_filters = Vec::with_capacity(num);
-                for _ in 0..num {
-                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
-                }
-
-                Ok(BundleStatus::Processed { cf_filters })
-            }
-            0x04 => Ok(BundleStatus::Pruned),
-            0x05 => {
-                let num = VarInt::consensus_decode(&mut d)?;
-                let num = num.0 as usize;
-
-                let mut cf_filters = Vec::with_capacity(num);
-                for _ in 0..num {
-                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
-                }
-
-                Ok(BundleStatus::Tip { cf_filters })
-            }
-            _ => Err(bitcoin::consensus::encode::Error::ParseFailed(
-                "Invalid byte type",
-            )),
-        }
-    }
-}
-
-pub struct ChainStore<T: StoreType> {
-    store: Arc<RwLock<DB>>,
-    cf_name: String,
-    min_height: usize,
-    network: Network,
-    phantom: PhantomData<T>,
-}
-
-impl ChainStore<Full> {
-    pub fn new(store: DB, network: Network) -> Result<Self, CompactFiltersError> {
-        let genesis = match network {
-            Network::Bitcoin => MAINNET_GENESIS.deref(),
-            Network::Testnet => TESTNET_GENESIS.deref(),
-            Network::Regtest => REGTEST_GENESIS.deref(),
-        };
-
-        let cf_name = "default".to_string();
-        let cf_handle = store.cf_handle(&cf_name).unwrap();
-
-        let genesis_key = StoreEntry::BlockHeader(Some(0)).get_key();
-
-        if store.get_pinned_cf(cf_handle, &genesis_key)?.is_none() {
-            let mut batch = WriteBatch::default();
-            batch.put_cf(
-                cf_handle,
-                genesis_key,
-                (genesis.header, genesis.header.work()).serialize(),
-            );
-            batch.put_cf(
-                cf_handle,
-                StoreEntry::BlockHeaderIndex(Some(genesis.block_hash())).get_key(),
-                &0usize.to_be_bytes(),
-            );
-            store.write(batch)?;
-        }
-
-        Ok(ChainStore {
-            store: Arc::new(RwLock::new(store)),
-            cf_name,
-            min_height: 0,
-            network,
-            phantom: PhantomData,
-        })
-    }
-
-    pub fn get_locators(&self) -> Result<Vec<(BlockHash, usize)>, CompactFiltersError> {
-        let mut step = 1;
-        let mut index = self.get_height()?;
-        let mut answer = Vec::new();
-
-        let store_read = self.store.read().unwrap();
-        let cf_handle = store_read.cf_handle(&self.cf_name).unwrap();
-
-        loop {
-            if answer.len() > 10 {
-                step *= 2;
-            }
-
-            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(
-                &store_read
-                    .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(index)).get_key())?
-                    .unwrap(),
-            )?;
-            answer.push((header.block_hash(), index));
-
-            if let Some(new_index) = index.checked_sub(step) {
-                index = new_index;
-            } else {
-                break;
-            }
-        }
-
-        Ok(answer)
-    }
-
-    pub fn start_snapshot(&self, from: usize) -> Result<ChainStore<Snapshot>, CompactFiltersError> {
-        let new_cf_name: String = thread_rng().sample_iter(&Alphanumeric).take(16).collect();
-        let new_cf_name = format!("_headers:{}", new_cf_name);
-
-        let mut write_store = self.store.write().unwrap();
-
-        write_store.create_cf(&new_cf_name, &Default::default())?;
-
-        let cf_handle = write_store.cf_handle(&self.cf_name).unwrap();
-        let new_cf_handle = write_store.cf_handle(&new_cf_name).unwrap();
-
-        let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(
-            &write_store
-                .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
-                .ok_or(CompactFiltersError::DataCorruption)?,
-        )?;
-
-        let mut batch = WriteBatch::default();
-        batch.put_cf(
-            new_cf_handle,
-            StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
-            &from.to_be_bytes(),
-        );
-        batch.put_cf(
-            new_cf_handle,
-            StoreEntry::BlockHeader(Some(from)).get_key(),
-            (header, work).serialize(),
-        );
-        write_store.write(batch)?;
-
-        let store = Arc::clone(&self.store);
-        Ok(ChainStore {
-            store,
-            cf_name: new_cf_name,
-            min_height: from,
-            network: self.network,
-            phantom: PhantomData,
-        })
-    }
-
-    pub fn recover_snapshot(&self, cf_name: &str) -> Result<(), CompactFiltersError> {
-        let mut write_store = self.store.write().unwrap();
-        let snapshot_cf_handle = write_store.cf_handle(cf_name).unwrap();
-
-        let prefix = StoreEntry::BlockHeader(None).get_key();
-        let mut iterator = write_store.prefix_iterator_cf(snapshot_cf_handle, prefix);
-
-        let min_height = match iterator
-            .next()
-            .and_then(|(k, _)| k[1..].try_into().ok())
-            .map(|bytes| usize::from_be_bytes(bytes))
-        {
-            None => {
-                std::mem::drop(iterator);
-                write_store.drop_cf(cf_name).ok();
-
-                return Ok(());
-            }
-            Some(x) => x,
-        };
-        std::mem::drop(iterator);
-        std::mem::drop(write_store);
-
-        let snapshot = ChainStore {
-            store: Arc::clone(&self.store),
-            cf_name: cf_name.into(),
-            min_height,
-            network: self.network,
-            phantom: PhantomData,
-        };
-        if snapshot.work()? > self.work()? {
-            self.apply_snapshot(snapshot)?;
-        }
-
-        Ok(())
-    }
-
-    pub fn apply_snapshot(
-        &self,
-        snaphost: ChainStore<Snapshot>,
-    ) -> Result<(), CompactFiltersError> {
-        let mut batch = WriteBatch::default();
-
-        let read_store = self.store.read().unwrap();
-        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
-        let snapshot_cf_handle = read_store.cf_handle(&snaphost.cf_name).unwrap();
-
-        let from_key = StoreEntry::BlockHeader(Some(snaphost.min_height)).get_key();
-        let to_key = StoreEntry::BlockHeader(Some(usize::MAX)).get_key();
-
-        let mut opts = ReadOptions::default();
-        opts.set_iterate_upper_bound(to_key.clone());
-
-        log::debug!("Removing items");
-        batch.delete_range_cf(cf_handle, &from_key, &to_key);
-        for (_, v) in read_store.iterator_cf_opt(
-            cf_handle,
-            opts,
-            IteratorMode::From(&from_key, Direction::Forward),
-        ) {
-            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
-
-            batch.delete_cf(
-                cf_handle,
-                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
-            );
-        }
-
-        // Delete full blocks overriden by snapshot
-        let from_key = StoreEntry::Block(Some(snaphost.min_height)).get_key();
-        let to_key = StoreEntry::Block(Some(usize::MAX)).get_key();
-        batch.delete_range(&from_key, &to_key);
-
-        log::debug!("Copying over new items");
-        for (k, v) in read_store.iterator_cf(snapshot_cf_handle, IteratorMode::Start) {
-            batch.put_cf(cf_handle, k, v);
-        }
-
-        read_store.write(batch)?;
-
-        std::mem::drop(snapshot_cf_handle);
-        std::mem::drop(cf_handle);
-        std::mem::drop(read_store);
-
-        self.store.write().unwrap().drop_cf(&snaphost.cf_name)?;
-
-        Ok(())
-    }
-
-    pub fn get_height_for(
-        &self,
-        block_hash: &BlockHash,
-    ) -> Result<Option<usize>, CompactFiltersError> {
-        let read_store = self.store.read().unwrap();
-        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
-
-        let key = StoreEntry::BlockHeaderIndex(Some(block_hash.clone())).get_key();
-        let data = read_store.get_pinned_cf(cf_handle, key)?;
-        Ok(data
-            .map(|data| {
-                Ok::<_, CompactFiltersError>(usize::from_be_bytes(
-                    data.as_ref()
-                        .try_into()
-                        .map_err(|_| CompactFiltersError::DataCorruption)?,
-                ))
-            })
-            .transpose()?)
-    }
-
-    pub fn get_block_hash(&self, height: usize) -> Result<Option<BlockHash>, CompactFiltersError> {
-        let read_store = self.store.read().unwrap();
-        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
-
-        let key = StoreEntry::BlockHeader(Some(height)).get_key();
-        let data = read_store.get_pinned_cf(cf_handle, key)?;
-        Ok(data
-            .map(|data| {
-                let (header, _): (BlockHeader, Uint256) =
-                    deserialize(&data).map_err(|_| CompactFiltersError::DataCorruption)?;
-                Ok::<_, CompactFiltersError>(header.block_hash())
-            })
-            .transpose()?)
-    }
-
-    pub fn save_full_block(&self, block: &Block, height: usize) -> Result<(), CompactFiltersError> {
-        let key = StoreEntry::Block(Some(height)).get_key();
-        self.store.read().unwrap().put(key, block.serialize())?;
-
-        Ok(())
-    }
-
-    pub fn get_full_block(&self, height: usize) -> Result<Option<Block>, CompactFiltersError> {
-        let read_store = self.store.read().unwrap();
-
-        let key = StoreEntry::Block(Some(height)).get_key();
-        let opt_block = read_store.get_pinned(key)?;
-
-        Ok(opt_block
-            .map(|data| deserialize(&data))
-            .transpose()
-            .map_err(|_| CompactFiltersError::DataCorruption)?)
-    }
-
-    pub fn delete_blocks_until(&self, height: usize) -> Result<(), CompactFiltersError> {
-        let from_key = StoreEntry::Block(Some(0)).get_key();
-        let to_key = StoreEntry::Block(Some(height)).get_key();
-
-        let mut batch = WriteBatch::default();
-        batch.delete_range(&from_key, &to_key);
-
-        self.store.read().unwrap().write(batch)?;
-
-        Ok(())
-    }
-
-    pub fn iter_full_blocks(&self) -> Result<Vec<(usize, Block)>, CompactFiltersError> {
-        let read_store = self.store.read().unwrap();
-
-        let prefix = StoreEntry::Block(None).get_key();
-
-        let iterator = read_store.prefix_iterator(&prefix);
-        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
-        // have the right prefix
-        iterator
-            .filter(|(k, _)| k.starts_with(&prefix))
-            .map(|(k, v)| {
-                let height: usize = usize::from_be_bytes(
-                    k[1..]
-                        .try_into()
-                        .map_err(|_| CompactFiltersError::DataCorruption)?,
-                );
-                let block = SerializeDb::deserialize(&v)?;
-
-                Ok((height, block))
-            })
-            .collect::<Result<_, _>>()
-    }
-}
-
-impl<T: StoreType> ChainStore<T> {
-    pub fn work(&self) -> Result<Uint256, CompactFiltersError> {
-        let read_store = self.store.read().unwrap();
-        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
-
-        let prefix = StoreEntry::BlockHeader(None).get_key();
-        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
-
-        Ok(iterator
-            .last()
-            .map(|(_, v)| -> Result<_, CompactFiltersError> {
-                let (_, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
-
-                Ok(work)
-            })
-            .transpose()?
-            .unwrap_or_default())
-    }
-
-    pub fn get_height(&self) -> Result<usize, CompactFiltersError> {
-        let read_store = self.store.read().unwrap();
-        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
-
-        let prefix = StoreEntry::BlockHeader(None).get_key();
-        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
-
-        Ok(iterator
-            .last()
-            .map(|(k, _)| -> Result<_, CompactFiltersError> {
-                let height = usize::from_be_bytes(
-                    k[1..]
-                        .try_into()
-                        .map_err(|_| CompactFiltersError::DataCorruption)?,
-                );
-
-                Ok(height)
-            })
-            .transpose()?
-            .unwrap_or_default())
-    }
-
-    pub fn get_tip_hash(&self) -> Result<Option<BlockHash>, CompactFiltersError> {
-        let read_store = self.store.read().unwrap();
-        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
-
-        let prefix = StoreEntry::BlockHeader(None).get_key();
-        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
-
-        Ok(iterator
-            .last()
-            .map(|(_, v)| -> Result<_, CompactFiltersError> {
-                let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
-
-                Ok(header.block_hash())
-            })
-            .transpose()?)
-    }
-
-    pub fn apply(
-        &mut self,
-        from: usize,
-        headers: Vec<BlockHeader>,
-    ) -> Result<BlockHash, CompactFiltersError> {
-        let mut batch = WriteBatch::default();
-
-        let read_store = self.store.read().unwrap();
-        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
-
-        let (mut last_hash, mut accumulated_work) = read_store
-            .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
-            .map(|result| {
-                let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&result)?;
-                Ok::<_, CompactFiltersError>((header.block_hash(), work))
-            })
-            .transpose()?
-            .ok_or(CompactFiltersError::DataCorruption)?;
-
-        for (index, header) in headers.into_iter().enumerate() {
-            if header.prev_blockhash != last_hash {
-                return Err(CompactFiltersError::InvalidHeaders);
-            }
-
-            last_hash = header.block_hash();
-            accumulated_work = accumulated_work + header.work();
-
-            let height = from + index + 1;
-            batch.put_cf(
-                cf_handle,
-                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
-                &(height).to_be_bytes(),
-            );
-            batch.put_cf(
-                cf_handle,
-                StoreEntry::BlockHeader(Some(height)).get_key(),
-                (header, accumulated_work).serialize(),
-            );
-        }
-
-        std::mem::drop(cf_handle);
-        std::mem::drop(read_store);
-
-        self.store.write().unwrap().write(batch)?;
-        Ok(last_hash)
-    }
-}
-
-impl<T: StoreType> fmt::Debug for ChainStore<T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct(&format!("ChainStore<{:?}>", T::default()))
-            .field("cf_name", &self.cf_name)
-            .field("min_height", &self.min_height)
-            .field("network", &self.network)
-            .field("headers_height", &self.get_height())
-            .field("tip_hash", &self.get_tip_hash())
-            .finish()
-    }
-}
-
-pub type FilterHeaderHash = FilterHash;
-
-#[derive(Debug, Clone)]
-pub struct FilterHeader {
-    prev_header_hash: FilterHeaderHash,
-    filter_hash: FilterHash,
-}
-
-impl FilterHeader {
-    fn header_hash(&self) -> FilterHeaderHash {
-        let mut hash_data = self.filter_hash.into_inner().to_vec();
-        hash_data.extend_from_slice(&self.prev_header_hash);
-        sha256d::Hash::hash(&hash_data).into()
-    }
-}
-
-pub enum BundleStatus {
-    Init,
-    CFHeaders { cf_headers: Vec<FilterHeader> },
-    CFilters { cf_filters: Vec<Vec<u8>> },
-    Processed { cf_filters: Vec<Vec<u8>> },
-    Tip { cf_filters: Vec<Vec<u8>> },
-    Pruned,
-}
-
-pub struct CFStore {
-    store: Arc<RwLock<DB>>,
-    filter_type: u8,
-}
-
-type BundleEntry = (BundleStatus, FilterHeaderHash);
-
-impl CFStore {
-    pub fn new(
-        headers_store: &ChainStore<Full>,
-        filter_type: u8,
-    ) -> Result<Self, CompactFiltersError> {
-        let cf_store = CFStore {
-            store: Arc::clone(&headers_store.store),
-            filter_type,
-        };
-
-        let genesis = match headers_store.network {
-            Network::Bitcoin => MAINNET_GENESIS.deref(),
-            Network::Testnet => TESTNET_GENESIS.deref(),
-            Network::Regtest => REGTEST_GENESIS.deref(),
-        };
-
-        let filter = BlockFilter::new_script_filter(genesis, |utxo| {
-            Err(bitcoin::util::bip158::Error::UtxoMissing(*utxo))
-        })?;
-        let first_key = StoreEntry::CFilterTable((filter_type, Some(0))).get_key();
-
-        // Add the genesis' filter
-        {
-            let read_store = cf_store.store.read().unwrap();
-            if read_store.get_pinned(&first_key)?.is_none() {
-                read_store.put(
-                    &first_key,
-                    (BundleStatus::Init, filter.filter_id(&FilterHash::default())).serialize(),
-                )?;
-            }
-        }
-
-        Ok(cf_store)
-    }
-
-    pub fn get_filter_type(&self) -> u8 {
-        self.filter_type
-    }
-
-    pub fn get_bundles(&self) -> Result<Vec<BundleEntry>, CompactFiltersError> {
-        let read_store = self.store.read().unwrap();
-
-        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
-        let iterator = read_store.prefix_iterator(&prefix);
-
-        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
-        // have the right prefix
-        iterator
-            .filter(|(k, _)| k.starts_with(&prefix))
-            .map(|(_, data)| BundleEntry::deserialize(&data))
-            .collect::<Result<_, _>>()
-    }
-
-    pub fn get_checkpoints(&self) -> Result<Vec<FilterHash>, CompactFiltersError> {
-        let read_store = self.store.read().unwrap();
-
-        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
-        let iterator = read_store.prefix_iterator(&prefix);
-
-        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
-        // have the right prefix
-        Ok(iterator
-            .filter(|(k, _)| k.starts_with(&prefix))
-            .skip(1)
-            .map(|(_, data)| Ok::<_, CompactFiltersError>(BundleEntry::deserialize(&data)?.1))
-            .collect::<Result<_, _>>()?)
-    }
-
-    pub fn replace_checkpoints(
-        &self,
-        checkpoints: Vec<FilterHash>,
-    ) -> Result<(), CompactFiltersError> {
-        let current_checkpoints = self.get_checkpoints()?;
-
-        let mut equal_bundles = 0;
-        for (index, (our, their)) in current_checkpoints
-            .iter()
-            .zip(checkpoints.iter())
-            .enumerate()
-        {
-            equal_bundles = index;
-
-            if our != their {
-                break;
-            }
-        }
-
-        let read_store = self.store.read().unwrap();
-        let mut batch = WriteBatch::default();
-
-        for (index, filter_hash) in checkpoints.iter().enumerate().skip(equal_bundles) {
-            let key = StoreEntry::CFilterTable((self.filter_type, Some(index + 1))).get_key(); // +1 to skip the genesis' filter
-
-            if let Some((BundleStatus::Tip { .. }, _)) = read_store
-                .get_pinned(&key)?
-                .map(|data| BundleEntry::deserialize(&data))
-                .transpose()?
-            {
-                println!("Keeping bundle #{} as Tip", index);
-            } else {
-                batch.put(&key, (BundleStatus::Init, *filter_hash).serialize());
-            }
-        }
-
-        read_store.write(batch)?;
-
-        Ok(())
-    }
-
-    pub fn advance_to_cf_headers(
-        &self,
-        bundle: usize,
-        checkpoint_hash: FilterHeaderHash,
-        filter_headers: Vec<FilterHash>,
-    ) -> Result<BundleStatus, CompactFiltersError> {
-        let mut last_hash = checkpoint_hash;
-        let cf_headers = filter_headers
-            .into_iter()
-            .map(|filter_hash| {
-                let filter_header = FilterHeader {
-                    prev_header_hash: last_hash,
-                    filter_hash,
-                };
-                last_hash = filter_header.header_hash();
-
-                filter_header
-            })
-            .collect();
-
-        let read_store = self.store.read().unwrap();
-
-        let next_key = StoreEntry::CFilterTable((self.filter_type, Some(bundle + 1))).get_key(); // +1 to skip the genesis' filter
-        if let Some((_, next_checkpoint)) = read_store
-            .get_pinned(&next_key)?
-            .map(|data| BundleEntry::deserialize(&data))
-            .transpose()?
-        {
-            // check connection with the next bundle if present
-            if last_hash != next_checkpoint {
-                return Err(CompactFiltersError::InvalidFilterHeader);
-            }
-        }
-
-        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
-        let value = (BundleStatus::CFHeaders { cf_headers }, checkpoint_hash);
-
-        read_store.put(key, value.serialize())?;
-
-        Ok(value.0)
-    }
-
-    pub fn advance_to_cf_filters(
-        &self,
-        bundle: usize,
-        checkpoint_hash: FilterHeaderHash,
-        headers: Vec<FilterHeader>,
-        filters: Vec<(usize, Vec<u8>)>,
-    ) -> Result<BundleStatus, CompactFiltersError> {
-        let cf_filters = filters
-            .into_iter()
-            .zip(headers.iter())
-            .map(|((_, filter_content), header)| {
-                if header.filter_hash != sha256d::Hash::hash(&filter_content).into() {
-                    return Err(CompactFiltersError::InvalidFilter);
-                }
-
-                Ok::<_, CompactFiltersError>(filter_content)
-            })
-            .collect::<Result<_, _>>()?;
-
-        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
-        let value = (BundleStatus::CFilters { cf_filters }, checkpoint_hash);
-
-        let read_store = self.store.read().unwrap();
-        read_store.put(key, value.serialize())?;
-
-        Ok(value.0)
-    }
-
-    pub fn prune_filters(
-        &self,
-        bundle: usize,
-        checkpoint_hash: FilterHeaderHash,
-    ) -> Result<BundleStatus, CompactFiltersError> {
-        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
-        let value = (BundleStatus::Pruned, checkpoint_hash);
-
-        let read_store = self.store.read().unwrap();
-        read_store.put(key, value.serialize())?;
-
-        Ok(value.0)
-    }
-
-    pub fn mark_as_tip(
-        &self,
-        bundle: usize,
-        cf_filters: Vec<Vec<u8>>,
-        checkpoint_hash: FilterHeaderHash,
-    ) -> Result<BundleStatus, CompactFiltersError> {
-        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
-        let value = (BundleStatus::Tip { cf_filters }, checkpoint_hash);
-
-        let read_store = self.store.read().unwrap();
-        read_store.put(key, value.serialize())?;
-
-        Ok(value.0)
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/compact_filters/sync.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/compact_filters/sync.rs.html deleted file mode 100644 index 7bedc0bce7..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/compact_filters/sync.rs.html +++ /dev/null @@ -1,629 +0,0 @@ -sync.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-use std::collections::{BTreeMap, HashMap, VecDeque};
-use std::sync::{Arc, Mutex};
-use std::time::Duration;
-
-use bitcoin::hash_types::{BlockHash, FilterHash};
-use bitcoin::network::message::NetworkMessage;
-use bitcoin::network::message_blockdata::GetHeadersMessage;
-use bitcoin::util::bip158::BlockFilter;
-
-use super::peer::*;
-use super::store::*;
-use super::CompactFiltersError;
-use crate::error::Error;
-
-pub(crate) const BURIED_CONFIRMATIONS: usize = 100;
-
-pub struct CFSync {
-    headers_store: Arc<ChainStore<Full>>,
-    cf_store: Arc<CFStore>,
-    skip_blocks: usize,
-    bundles: Mutex<VecDeque<(BundleStatus, FilterHash, usize)>>,
-}
-
-impl CFSync {
-    pub fn new(
-        headers_store: Arc<ChainStore<Full>>,
-        skip_blocks: usize,
-        filter_type: u8,
-    ) -> Result<Self, CompactFiltersError> {
-        let cf_store = Arc::new(CFStore::new(&headers_store, filter_type)?);
-
-        Ok(CFSync {
-            headers_store,
-            cf_store,
-            skip_blocks,
-            bundles: Mutex::new(VecDeque::new()),
-        })
-    }
-
-    pub fn pruned_bundles(&self) -> Result<usize, CompactFiltersError> {
-        Ok(self
-            .cf_store
-            .get_bundles()?
-            .into_iter()
-            .skip(self.skip_blocks / 1000)
-            .fold(0, |acc, (status, _)| match status {
-                BundleStatus::Pruned => acc + 1,
-                _ => acc,
-            }))
-    }
-
-    pub fn prepare_sync(&self, peer: Arc<Peer>) -> Result<(), CompactFiltersError> {
-        let mut bundles_lock = self.bundles.lock().unwrap();
-
-        let resp = peer.get_cf_checkpt(
-            self.cf_store.get_filter_type(),
-            self.headers_store.get_tip_hash()?.unwrap(),
-        )?;
-        self.cf_store.replace_checkpoints(resp.filter_headers)?;
-
-        bundles_lock.clear();
-        for (index, (status, checkpoint)) in self.cf_store.get_bundles()?.into_iter().enumerate() {
-            bundles_lock.push_back((status, checkpoint, index));
-        }
-
-        Ok(())
-    }
-
-    pub fn capture_thread_for_sync<F, Q>(
-        &self,
-        peer: Arc<Peer>,
-        process: F,
-        completed_bundle: Q,
-    ) -> Result<(), CompactFiltersError>
-    where
-        F: Fn(&BlockHash, &BlockFilter) -> Result<bool, CompactFiltersError>,
-        Q: Fn(usize) -> Result<(), Error>,
-    {
-        let current_height = self.headers_store.get_height()?; // TODO: we should update it in case headers_store is also updated
-
-        loop {
-            let (mut status, checkpoint, index) = match self.bundles.lock().unwrap().pop_front() {
-                None => break,
-                Some(x) => x,
-            };
-
-            log::debug!(
-                "Processing bundle #{} - height {} to {}",
-                index,
-                index * 1000 + 1,
-                (index + 1) * 1000
-            );
-
-            let process_received_filters =
-                |expected_filters| -> Result<BTreeMap<usize, Vec<u8>>, CompactFiltersError> {
-                    let mut filters_map = BTreeMap::new();
-                    for _ in 0..expected_filters {
-                        let filter = peer.pop_cf_filter_resp()?;
-                        if filter.filter_type != self.cf_store.get_filter_type() {
-                            return Err(CompactFiltersError::InvalidResponse);
-                        }
-
-                        match self.headers_store.get_height_for(&filter.block_hash)? {
-                            Some(height) => filters_map.insert(height, filter.filter),
-                            None => return Err(CompactFiltersError::InvalidFilter),
-                        };
-                    }
-
-                    Ok(filters_map)
-                };
-
-            let start_height = index * 1000 + 1;
-            let mut already_processed = 0;
-
-            if start_height < self.skip_blocks {
-                status = self.cf_store.prune_filters(index, checkpoint)?;
-            }
-
-            let stop_height = std::cmp::min(current_height, start_height + 999);
-            let stop_hash = self.headers_store.get_block_hash(stop_height)?.unwrap();
-
-            if let BundleStatus::Init = status {
-                log::trace!("status: Init");
-
-                let resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
-
-                assert!(resp.previous_filter == checkpoint);
-                status =
-                    self.cf_store
-                        .advance_to_cf_headers(index, checkpoint, resp.filter_hashes)?;
-            }
-            if let BundleStatus::Tip { cf_filters } = status {
-                log::trace!("status: Tip (beginning) ");
-
-                already_processed = cf_filters.len();
-                let headers_resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
-
-                let cf_headers = match self.cf_store.advance_to_cf_headers(
-                    index,
-                    checkpoint,
-                    headers_resp.filter_hashes,
-                )? {
-                    BundleStatus::CFHeaders { cf_headers } => cf_headers,
-                    _ => return Err(CompactFiltersError::InvalidResponse),
-                };
-
-                peer.get_cf_filters(
-                    self.cf_store.get_filter_type(),
-                    (start_height + cf_filters.len()) as u32,
-                    stop_hash,
-                )?;
-                let expected_filters = stop_height - start_height + 1 - cf_filters.len();
-                let filters_map = process_received_filters(expected_filters)?;
-                let filters = cf_filters
-                    .into_iter()
-                    .enumerate()
-                    .chain(filters_map.into_iter())
-                    .collect();
-                status = self
-                    .cf_store
-                    .advance_to_cf_filters(index, checkpoint, cf_headers, filters)?;
-            }
-            if let BundleStatus::CFHeaders { cf_headers } = status {
-                log::trace!("status: CFHeaders");
-
-                peer.get_cf_filters(
-                    self.cf_store.get_filter_type(),
-                    start_height as u32,
-                    stop_hash,
-                )?;
-                let expected_filters = stop_height - start_height + 1;
-                let filters_map = process_received_filters(expected_filters)?;
-                status = self.cf_store.advance_to_cf_filters(
-                    index,
-                    checkpoint,
-                    cf_headers,
-                    filters_map.into_iter().collect(),
-                )?;
-            }
-            if let BundleStatus::CFilters { cf_filters } = status {
-                log::trace!("status: CFilters");
-
-                let last_sync_buried_height = (start_height + already_processed)
-                    .checked_sub(BURIED_CONFIRMATIONS)
-                    .unwrap_or(0);
-
-                for (filter_index, filter) in cf_filters.iter().enumerate() {
-                    let height = filter_index + start_height;
-
-                    // do not download blocks that were already "buried" since the last sync
-                    if height < last_sync_buried_height {
-                        continue;
-                    }
-
-                    let block_hash = self.headers_store.get_block_hash(height)?.unwrap();
-
-                    // TODO: also download random blocks?
-                    if process(&block_hash, &BlockFilter::new(&filter))? {
-                        log::debug!("Downloading block {}", block_hash);
-
-                        let block = peer
-                            .get_block(block_hash)?
-                            .ok_or(CompactFiltersError::MissingBlock)?;
-                        self.headers_store.save_full_block(&block, height)?;
-                    }
-                }
-
-                status = BundleStatus::Processed { cf_filters };
-            }
-            if let BundleStatus::Processed { cf_filters } = status {
-                log::trace!("status: Processed");
-
-                if current_height - stop_height > 1000 {
-                    status = self.cf_store.prune_filters(index, checkpoint)?;
-                } else {
-                    status = self.cf_store.mark_as_tip(index, cf_filters, checkpoint)?;
-                }
-
-                completed_bundle(index)?;
-            }
-            if let BundleStatus::Pruned = status {
-                log::trace!("status: Pruned");
-            }
-            if let BundleStatus::Tip { .. } = status {
-                log::trace!("status: Tip");
-            }
-        }
-
-        Ok(())
-    }
-}
-
-pub fn sync_headers<F>(
-    peer: Arc<Peer>,
-    store: Arc<ChainStore<Full>>,
-    sync_fn: F,
-) -> Result<Option<ChainStore<Snapshot>>, CompactFiltersError>
-where
-    F: Fn(usize) -> Result<(), Error>,
-{
-    let locators = store.get_locators()?;
-    let locators_vec = locators.iter().map(|(hash, _)| hash).cloned().collect();
-    let locators_map: HashMap<_, _> = locators.into_iter().collect();
-
-    peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
-        locators_vec,
-        Default::default(),
-    )))?;
-    let (mut snapshot, mut last_hash) = if let NetworkMessage::Headers(headers) = peer
-        .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
-        .ok_or(CompactFiltersError::Timeout)?
-    {
-        if headers.is_empty() {
-            return Ok(None);
-        }
-
-        match locators_map.get(&headers[0].prev_blockhash) {
-            None => return Err(CompactFiltersError::InvalidHeaders),
-            Some(from) => (
-                store.start_snapshot(*from)?,
-                headers[0].prev_blockhash.clone(),
-            ),
-        }
-    } else {
-        return Err(CompactFiltersError::InvalidResponse);
-    };
-
-    let mut sync_height = store.get_height()?;
-    while sync_height < peer.get_version().start_height as usize {
-        peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
-            vec![last_hash],
-            Default::default(),
-        )))?;
-        if let NetworkMessage::Headers(headers) = peer
-            .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
-            .ok_or(CompactFiltersError::Timeout)?
-        {
-            let batch_len = headers.len();
-            last_hash = snapshot.apply(sync_height, headers)?;
-
-            sync_height += batch_len;
-            sync_fn(sync_height)?;
-        } else {
-            return Err(CompactFiltersError::InvalidResponse);
-        }
-    }
-
-    Ok(Some(snapshot))
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/electrum.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/electrum.rs.html deleted file mode 100644 index 438de43a53..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/electrum.rs.html +++ /dev/null @@ -1,407 +0,0 @@ -electrum.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Electrum
-//!
-//! This module defines an [`OnlineBlockchain`] struct that wraps an [`electrum_client::Client`]
-//! and implements the logic required to populate the wallet's [database](crate::database::Database) by
-//! querying the inner client.
-//!
-//! ## Example
-//!
-//! ```no_run
-//! # use magical::blockchain::electrum::ElectrumBlockchain;
-//! let client = electrum_client::Client::new("ssl://electrum.blockstream.info:50002", None)?;
-//! let blockchain = ElectrumBlockchain::from(client);
-//! # Ok::<(), magical::Error>(())
-//! ```
-
-use std::collections::HashSet;
-
-#[allow(unused_imports)]
-use log::{debug, error, info, trace};
-
-use bitcoin::{Script, Transaction, Txid};
-
-use electrum_client::{Client, ElectrumApi};
-
-use self::utils::{ELSGetHistoryRes, ELSListUnspentRes, ElectrumLikeSync};
-use super::*;
-use crate::database::BatchDatabase;
-use crate::error::Error;
-use crate::FeeRate;
-
-/// Wrapper over an Electrum Client that implements the required blockchain traits
-///
-/// ## Example
-/// See the [`blockchain::electrum`](crate::blockchain::electrum) module for a usage example.
-pub struct ElectrumBlockchain(Option<Client>);
-
-#[cfg(test)]
-#[cfg(feature = "test-electrum")]
-#[magical_blockchain_tests(crate)]
-fn local_electrs() -> ElectrumBlockchain {
-    ElectrumBlockchain::from(Client::new(&testutils::get_electrum_url(), None).unwrap())
-}
-
-impl std::convert::From<Client> for ElectrumBlockchain {
-    fn from(client: Client) -> Self {
-        ElectrumBlockchain(Some(client))
-    }
-}
-
-impl Blockchain for ElectrumBlockchain {
-    fn offline() -> Self {
-        ElectrumBlockchain(None)
-    }
-
-    fn is_online(&self) -> bool {
-        self.0.is_some()
-    }
-}
-
-impl OnlineBlockchain for ElectrumBlockchain {
-    fn get_capabilities(&self) -> HashSet<Capability> {
-        vec![
-            Capability::FullHistory,
-            Capability::GetAnyTx,
-            Capability::AccurateFees,
-        ]
-        .into_iter()
-        .collect()
-    }
-
-    fn setup<D: BatchDatabase, P: Progress>(
-        &self,
-        stop_gap: Option<usize>,
-        database: &mut D,
-        progress_update: P,
-    ) -> Result<(), Error> {
-        self.0
-            .as_ref()
-            .ok_or(Error::OfflineClient)?
-            .electrum_like_setup(stop_gap, database, progress_update)
-    }
-
-    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
-        Ok(self
-            .0
-            .as_ref()
-            .ok_or(Error::OfflineClient)?
-            .transaction_get(txid)
-            .map(Option::Some)?)
-    }
-
-    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
-        Ok(self
-            .0
-            .as_ref()
-            .ok_or(Error::OfflineClient)?
-            .transaction_broadcast(tx)
-            .map(|_| ())?)
-    }
-
-    fn get_height(&self) -> Result<u32, Error> {
-        // TODO: unsubscribe when added to the client, or is there a better call to use here?
-
-        Ok(self
-            .0
-            .as_ref()
-            .ok_or(Error::OfflineClient)?
-            .block_headers_subscribe()
-            .map(|data| data.height as u32)?)
-    }
-
-    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
-        Ok(FeeRate::from_btc_per_kvb(
-            self.0
-                .as_ref()
-                .ok_or(Error::OfflineClient)?
-                .estimate_fee(target)? as f32,
-        ))
-    }
-}
-
-impl ElectrumLikeSync for Client {
-    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
-        &self,
-        scripts: I,
-    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error> {
-        self.batch_script_get_history(scripts)
-            .map(|v| {
-                v.into_iter()
-                    .map(|v| {
-                        v.into_iter()
-                            .map(
-                                |electrum_client::GetHistoryRes {
-                                     height, tx_hash, ..
-                                 }| ELSGetHistoryRes {
-                                    height,
-                                    tx_hash,
-                                },
-                            )
-                            .collect()
-                    })
-                    .collect()
-            })
-            .map_err(Error::Electrum)
-    }
-
-    fn els_batch_script_list_unspent<'s, I: IntoIterator<Item = &'s Script>>(
-        &self,
-        scripts: I,
-    ) -> Result<Vec<Vec<ELSListUnspentRes>>, Error> {
-        self.batch_script_list_unspent(scripts)
-            .map(|v| {
-                v.into_iter()
-                    .map(|v| {
-                        v.into_iter()
-                            .map(
-                                |electrum_client::ListUnspentRes {
-                                     height,
-                                     tx_hash,
-                                     tx_pos,
-                                     ..
-                                 }| ELSListUnspentRes {
-                                    height,
-                                    tx_hash,
-                                    tx_pos,
-                                },
-                            )
-                            .collect()
-                    })
-                    .collect()
-            })
-            .map_err(Error::Electrum)
-    }
-
-    fn els_transaction_get(&self, txid: &Txid) -> Result<Transaction, Error> {
-        self.transaction_get(txid).map_err(Error::Electrum)
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/esplora.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/esplora.rs.html deleted file mode 100644 index d0203658fb..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/esplora.rs.html +++ /dev/null @@ -1,821 +0,0 @@ -esplora.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-397
-398
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-409
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Esplora
-//!
-//! This module defines an [`OnlineBlockchain`] struct that can query an Esplora backend
-//! populate the wallet's [database](crate::database::Database) by
-//!
-//! ## Example
-//!
-//! ```no_run
-//! # use magical::blockchain::esplora::EsploraBlockchain;
-//! let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api");
-//! # Ok::<(), magical::Error>(())
-//! ```
-
-use std::collections::{HashMap, HashSet};
-use std::fmt;
-
-use futures::stream::{self, StreamExt, TryStreamExt};
-
-#[allow(unused_imports)]
-use log::{debug, error, info, trace};
-
-use serde::Deserialize;
-
-use reqwest::{Client, StatusCode};
-
-use bitcoin::consensus::{deserialize, serialize};
-use bitcoin::hashes::hex::ToHex;
-use bitcoin::hashes::{sha256, Hash};
-use bitcoin::{Script, Transaction, Txid};
-
-use self::utils::{ELSGetHistoryRes, ELSListUnspentRes, ElectrumLikeSync};
-use super::*;
-use crate::database::BatchDatabase;
-use crate::error::Error;
-use crate::FeeRate;
-
-#[derive(Debug)]
-struct UrlClient {
-    url: String,
-    // We use the async client instead of the blocking one because it automatically uses `fetch`
-    // when the target platform is wasm32.
-    client: Client,
-}
-
-/// Structure that implements the logic to sync with Esplora
-///
-/// ## Example
-/// See the [`blockchain::esplora`](crate::blockchain::esplora) module for a usage example.
-#[derive(Debug)]
-pub struct EsploraBlockchain(Option<UrlClient>);
-
-impl std::convert::From<UrlClient> for EsploraBlockchain {
-    fn from(url_client: UrlClient) -> Self {
-        EsploraBlockchain(Some(url_client))
-    }
-}
-
-impl EsploraBlockchain {
-    /// Create a new instance of the client from a base URL
-    pub fn new(base_url: &str) -> Self {
-        EsploraBlockchain(Some(UrlClient {
-            url: base_url.to_string(),
-            client: Client::new(),
-        }))
-    }
-}
-
-impl Blockchain for EsploraBlockchain {
-    fn offline() -> Self {
-        EsploraBlockchain(None)
-    }
-
-    fn is_online(&self) -> bool {
-        self.0.is_some()
-    }
-}
-
-#[maybe_async]
-impl OnlineBlockchain for EsploraBlockchain {
-    fn get_capabilities(&self) -> HashSet<Capability> {
-        vec![
-            Capability::FullHistory,
-            Capability::GetAnyTx,
-            Capability::AccurateFees,
-        ]
-        .into_iter()
-        .collect()
-    }
-
-    fn setup<D: BatchDatabase, P: Progress>(
-        &self,
-        stop_gap: Option<usize>,
-        database: &mut D,
-        progress_update: P,
-    ) -> Result<(), Error> {
-        maybe_await!(self
-            .0
-            .as_ref()
-            .ok_or(Error::OfflineClient)?
-            .electrum_like_setup(stop_gap, database, progress_update))
-    }
-
-    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
-        Ok(await_or_block!(self
-            .0
-            .as_ref()
-            .ok_or(Error::OfflineClient)?
-            ._get_tx(txid))?)
-    }
-
-    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
-        Ok(await_or_block!(self
-            .0
-            .as_ref()
-            .ok_or(Error::OfflineClient)?
-            ._broadcast(tx))?)
-    }
-
-    fn get_height(&self) -> Result<u32, Error> {
-        Ok(await_or_block!(self
-            .0
-            .as_ref()
-            .ok_or(Error::OfflineClient)?
-            ._get_height())?)
-    }
-
-    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
-        let estimates = await_or_block!(self
-            .0
-            .as_ref()
-            .ok_or(Error::OfflineClient)?
-            ._get_fee_estimates())?;
-
-        let fee_val = estimates
-            .into_iter()
-            .map(|(k, v)| Ok::<_, std::num::ParseIntError>((k.parse::<usize>()?, v)))
-            .collect::<Result<Vec<_>, _>>()
-            .map_err(|e| Error::Generic(e.to_string()))?
-            .into_iter()
-            .take_while(|(k, _)| k <= &target)
-            .map(|(_, v)| v)
-            .last()
-            .unwrap_or(1.0);
-
-        Ok(FeeRate::from_sat_per_vb(fee_val as f32))
-    }
-}
-
-impl UrlClient {
-    fn script_to_scripthash(script: &Script) -> String {
-        sha256::Hash::hash(script.as_bytes()).into_inner().to_hex()
-    }
-
-    async fn _get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, EsploraError> {
-        let resp = self
-            .client
-            .get(&format!("{}/tx/{}/raw", self.url, txid))
-            .send()
-            .await?;
-
-        if let StatusCode::NOT_FOUND = resp.status() {
-            return Ok(None);
-        }
-
-        Ok(Some(deserialize(&resp.error_for_status()?.bytes().await?)?))
-    }
-
-    async fn _broadcast(&self, transaction: &Transaction) -> Result<(), EsploraError> {
-        self.client
-            .post(&format!("{}/tx", self.url))
-            .body(serialize(transaction).to_hex())
-            .send()
-            .await?
-            .error_for_status()?;
-
-        Ok(())
-    }
-
-    async fn _get_height(&self) -> Result<u32, EsploraError> {
-        let req = self
-            .client
-            .get(&format!("{}/blocks/tip/height", self.url))
-            .send()
-            .await?;
-
-        Ok(req.error_for_status()?.text().await?.parse()?)
-    }
-
-    async fn _script_get_history(
-        &self,
-        script: &Script,
-    ) -> Result<Vec<ELSGetHistoryRes>, EsploraError> {
-        let mut result = Vec::new();
-        let scripthash = Self::script_to_scripthash(script);
-
-        // Add the unconfirmed transactions first
-        result.extend(
-            self.client
-                .get(&format!(
-                    "{}/scripthash/{}/txs/mempool",
-                    self.url, scripthash
-                ))
-                .send()
-                .await?
-                .error_for_status()?
-                .json::<Vec<EsploraGetHistory>>()
-                .await?
-                .into_iter()
-                .map(|x| ELSGetHistoryRes {
-                    tx_hash: x.txid,
-                    height: x.status.block_height.unwrap_or(0) as i32,
-                }),
-        );
-
-        debug!(
-            "Found {} mempool txs for {} - {:?}",
-            result.len(),
-            scripthash,
-            script
-        );
-
-        // Then go through all the pages of confirmed transactions
-        let mut last_txid = String::new();
-        loop {
-            let response = self
-                .client
-                .get(&format!(
-                    "{}/scripthash/{}/txs/chain/{}",
-                    self.url, scripthash, last_txid
-                ))
-                .send()
-                .await?
-                .error_for_status()?
-                .json::<Vec<EsploraGetHistory>>()
-                .await?;
-            let len = response.len();
-            if let Some(elem) = response.last() {
-                last_txid = elem.txid.to_hex();
-            }
-
-            debug!("... adding {} confirmed transactions", len);
-
-            result.extend(response.into_iter().map(|x| ELSGetHistoryRes {
-                tx_hash: x.txid,
-                height: x.status.block_height.unwrap_or(0) as i32,
-            }));
-
-            if len < 25 {
-                break;
-            }
-        }
-
-        Ok(result)
-    }
-
-    async fn _script_list_unspent(
-        &self,
-        script: &Script,
-    ) -> Result<Vec<ELSListUnspentRes>, EsploraError> {
-        Ok(self
-            .client
-            .get(&format!(
-                "{}/scripthash/{}/utxo",
-                self.url,
-                Self::script_to_scripthash(script)
-            ))
-            .send()
-            .await?
-            .error_for_status()?
-            .json::<Vec<EsploraListUnspent>>()
-            .await?
-            .into_iter()
-            .map(|x| ELSListUnspentRes {
-                tx_hash: x.txid,
-                height: x.status.block_height.unwrap_or(0),
-                tx_pos: x.vout,
-            })
-            .collect())
-    }
-
-    async fn _get_fee_estimates(&self) -> Result<HashMap<String, f64>, EsploraError> {
-        Ok(self
-            .client
-            .get(&format!("{}/fee-estimates", self.url,))
-            .send()
-            .await?
-            .error_for_status()?
-            .json::<HashMap<String, f64>>()
-            .await?)
-    }
-}
-
-#[maybe_async]
-impl ElectrumLikeSync for UrlClient {
-    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
-        &self,
-        scripts: I,
-    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error> {
-        let future = async {
-            Ok(stream::iter(scripts)
-                .then(|script| self._script_get_history(&script))
-                .try_collect()
-                .await?)
-        };
-
-        await_or_block!(future)
-    }
-
-    fn els_batch_script_list_unspent<'s, I: IntoIterator<Item = &'s Script>>(
-        &self,
-        scripts: I,
-    ) -> Result<Vec<Vec<ELSListUnspentRes>>, Error> {
-        let future = async {
-            Ok(stream::iter(scripts)
-                .then(|script| self._script_list_unspent(&script))
-                .try_collect()
-                .await?)
-        };
-
-        await_or_block!(future)
-    }
-
-    fn els_transaction_get(&self, txid: &Txid) -> Result<Transaction, Error> {
-        Ok(await_or_block!(self._get_tx(txid))?
-            .ok_or_else(|| EsploraError::TransactionNotFound(*txid))?)
-    }
-}
-
-#[derive(Deserialize)]
-struct EsploraGetHistoryStatus {
-    block_height: Option<usize>,
-}
-
-#[derive(Deserialize)]
-struct EsploraGetHistory {
-    txid: Txid,
-    status: EsploraGetHistoryStatus,
-}
-
-#[derive(Deserialize)]
-struct EsploraListUnspent {
-    txid: Txid,
-    vout: usize,
-    status: EsploraGetHistoryStatus,
-}
-
-/// Errors that can happen during a sync with [`EsploraBlockchain`]
-#[derive(Debug)]
-pub enum EsploraError {
-    /// Error with the HTTP call
-    Reqwest(reqwest::Error),
-    /// Invalid number returned
-    Parsing(std::num::ParseIntError),
-    /// Invalid Bitcoin data returned
-    BitcoinEncoding(bitcoin::consensus::encode::Error),
-
-    /// Transaction not found
-    TransactionNotFound(Txid),
-}
-
-impl fmt::Display for EsploraError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}", self)
-    }
-}
-
-impl std::error::Error for EsploraError {}
-
-impl From<reqwest::Error> for EsploraError {
-    fn from(other: reqwest::Error) -> Self {
-        EsploraError::Reqwest(other)
-    }
-}
-
-impl From<std::num::ParseIntError> for EsploraError {
-    fn from(other: std::num::ParseIntError) -> Self {
-        EsploraError::Parsing(other)
-    }
-}
-
-impl From<bitcoin::consensus::encode::Error> for EsploraError {
-    fn from(other: bitcoin::consensus::encode::Error) -> Self {
-        EsploraError::BitcoinEncoding(other)
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/mod.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/mod.rs.html deleted file mode 100644 index 9c535b290c..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/mod.rs.html +++ /dev/null @@ -1,575 +0,0 @@ -mod.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Blockchain backends
-//!
-//! This module provides the implementation of a few commonly-used backends like
-//! [Electrum](crate::blockchain::electrum), [Esplora](crate::blockchain::esplora) and
-//! [Compact Filters/Neutrino](crate::blockchain::compact_filters), along with two generalized
-//! traits [`Blockchain`] and [`OnlineBlockchain`] that can be implemented to build customized
-//! backends.
-//!
-//! Types that only implement the [`Blockchain`] trait can be used as backends for [`Wallet`](crate::wallet::Wallet)s, but any
-//! action that requires interacting with the blockchain won't be available ([`Wallet::sync`](crate::wallet::Wallet::sync) and
-//! [`Wallet::broadcast`](crate::wallet::Wallet::broadcast)). This allows the creation of physically air-gapped wallets, that have no
-//! ability to contact the outside world. An example of an offline-only client is [`OfflineBlockchain`].
-//!
-//! Types that also implement [`OnlineBlockchain`] will make the two aforementioned actions
-//! available.
-
-use std::collections::HashSet;
-use std::ops::Deref;
-use std::sync::mpsc::{channel, Receiver, Sender};
-use std::sync::Arc;
-
-use bitcoin::{Transaction, Txid};
-
-use crate::database::BatchDatabase;
-use crate::error::Error;
-use crate::FeeRate;
-
-pub(crate) mod utils;
-
-#[cfg(feature = "electrum")]
-#[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
-pub mod electrum;
-#[cfg(feature = "electrum")]
-pub use self::electrum::ElectrumBlockchain;
-
-#[cfg(feature = "esplora")]
-#[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
-pub mod esplora;
-#[cfg(feature = "esplora")]
-pub use self::esplora::EsploraBlockchain;
-
-#[cfg(feature = "compact_filters")]
-#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
-pub mod compact_filters;
-#[cfg(feature = "compact_filters")]
-pub use self::compact_filters::CompactFiltersBlockchain;
-
-/// Capabilities that can be supported by an [`OnlineBlockchain`] backend
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub enum Capability {
-    /// Can recover the full history of a wallet and not only the set of currently spendable UTXOs
-    FullHistory,
-    /// Can fetch any historical transaction given its txid
-    GetAnyTx,
-    /// Can compute accurate fees for the transactions found during sync
-    AccurateFees,
-}
-
-/// Base trait for a blockchain backend
-///
-/// This trait is always required, even for "air-gapped" backends that don't actually make any
-/// external call. Clients that have the ability to make external calls must also implement `OnlineBlockchain`.
-pub trait Blockchain {
-    /// Return whether or not the client has the ability to fullfill requests
-    ///
-    /// This should always be `false` for offline-only types, and can be true for types that also
-    /// implement [`OnlineBlockchain`], if they have the ability to fullfill requests.
-    fn is_online(&self) -> bool;
-
-    /// Create a new instance of the client that is offline-only
-    ///
-    /// For types that also implement [`OnlineBlockchain`], this means creating an instance that
-    /// returns [`Error::OfflineClient`](crate::error::Error::OfflineClient) if any of the "online"
-    /// methods are called.
-    ///
-    /// This is generally implemented by wrapping the client in an [`Option`] that has [`Option::None`] value
-    /// when created with this method, and is [`Option::Some`] if properly instantiated.
-    fn offline() -> Self;
-}
-
-/// Type that only implements [`Blockchain`] and is always offline
-pub struct OfflineBlockchain;
-impl Blockchain for OfflineBlockchain {
-    fn offline() -> Self {
-        OfflineBlockchain
-    }
-
-    fn is_online(&self) -> bool {
-        false
-    }
-}
-
-/// Trait that defines the actions that must be supported by an online [`Blockchain`]
-#[maybe_async]
-pub trait OnlineBlockchain: Blockchain {
-    /// Return the set of [`Capability`] supported by this backend
-    fn get_capabilities(&self) -> HashSet<Capability>;
-
-    /// Setup the backend and populate the internal database for the first time
-    ///
-    /// This method is the equivalent of [`OnlineBlockchain::sync`], but it's guaranteed to only be
-    /// called once, at the first [`Wallet::sync`](crate::wallet::Wallet::sync).
-    ///
-    /// The rationale behind the distinction between `sync` and `setup` is that some custom backends
-    /// might need to perform specific actions only the first time they are synced.
-    ///
-    /// For types that do not have that distinction, only this method can be implemented, since
-    /// [`OnlineBlockchain::sync`] defaults to calling this internally if not overridden.
-    fn setup<D: BatchDatabase, P: 'static + Progress>(
-        &self,
-        stop_gap: Option<usize>,
-        database: &mut D,
-        progress_update: P,
-    ) -> Result<(), Error>;
-    /// Populate the internal database with transactions and UTXOs
-    ///
-    /// If not overridden, it defaults to calling [`OnlineBlockchain::setup`] internally.
-    ///
-    /// This method should implement the logic required to iterate over the list of the wallet's
-    /// script_pubkeys using [`Database::iter_script_pubkeys`] and look for relevant transactions
-    /// in the blockchain to populate the database with [`BatchOperations::set_tx`] and
-    /// [`BatchOperations::set_utxo`].
-    ///
-    /// This method should also take care of removing UTXOs that are seen as spent in the
-    /// blockchain, using [`BatchOperations::del_utxo`].
-    ///
-    /// The `progress_update` object can be used to give the caller updates about the progress by using
-    /// [`Progress::update`].
-    ///
-    /// [`Database::iter_script_pubkeys`]: crate::database::Database::iter_script_pubkeys
-    /// [`BatchOperations::set_tx`]: crate::database::BatchOperations::set_tx
-    /// [`BatchOperations::set_utxo`]: crate::database::BatchOperations::set_utxo
-    /// [`BatchOperations::del_utxo`]: crate::database::BatchOperations::del_utxo
-    fn sync<D: BatchDatabase, P: 'static + Progress>(
-        &self,
-        stop_gap: Option<usize>,
-        database: &mut D,
-        progress_update: P,
-    ) -> Result<(), Error> {
-        maybe_await!(self.setup(stop_gap, database, progress_update))
-    }
-
-    /// Fetch a transaction from the blockchain given its txid
-    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
-    /// Broadcast a transaction
-    fn broadcast(&self, tx: &Transaction) -> Result<(), Error>;
-
-    /// Return the current height
-    fn get_height(&self) -> Result<u32, Error>;
-    /// Estimate the fee rate required to confirm a transaction in a given `target` of blocks
-    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>;
-}
-
-/// Data sent with a progress update over a [`channel`]
-pub type ProgressData = (f32, Option<String>);
-
-/// Trait for types that can receive and process progress updates during [`OnlineBlockchain::sync`] and
-/// [`OnlineBlockchain::setup`]
-pub trait Progress: Send {
-    /// Send a new progress update
-    ///
-    /// The `progress` value should be in the range 0.0 - 100.0, and the `message` value is an
-    /// optional text message that can be displayed to the user.
-    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error>;
-}
-
-/// Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]
-pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>) {
-    channel()
-}
-
-impl Progress for Sender<ProgressData> {
-    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
-        if progress < 0.0 || progress > 100.0 {
-            return Err(Error::InvalidProgressValue(progress));
-        }
-
-        self.send((progress, message))
-            .map_err(|_| Error::ProgressUpdateError)
-    }
-}
-
-/// Type that implements [`Progress`] and drops every update received
-#[derive(Clone)]
-pub struct NoopProgress;
-
-/// Create a new instance of [`NoopProgress`]
-pub fn noop_progress() -> NoopProgress {
-    NoopProgress
-}
-
-impl Progress for NoopProgress {
-    fn update(&self, _progress: f32, _message: Option<String>) -> Result<(), Error> {
-        Ok(())
-    }
-}
-
-/// Type that implements [`Progress`] and logs at level `INFO` every update received
-#[derive(Clone)]
-pub struct LogProgress;
-
-/// Create a nwe instance of [`LogProgress`]
-pub fn log_progress() -> LogProgress {
-    LogProgress
-}
-
-impl Progress for LogProgress {
-    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
-        log::info!("Sync {:.3}%: `{}`", progress, message.unwrap_or("".into()));
-
-        Ok(())
-    }
-}
-
-impl<T: Blockchain> Blockchain for Arc<T> {
-    fn is_online(&self) -> bool {
-        self.deref().is_online()
-    }
-
-    fn offline() -> Self {
-        Arc::new(T::offline())
-    }
-}
-
-#[maybe_async]
-impl<T: OnlineBlockchain> OnlineBlockchain for Arc<T> {
-    fn get_capabilities(&self) -> HashSet<Capability> {
-        maybe_await!(self.deref().get_capabilities())
-    }
-
-    fn setup<D: BatchDatabase, P: 'static + Progress>(
-        &self,
-        stop_gap: Option<usize>,
-        database: &mut D,
-        progress_update: P,
-    ) -> Result<(), Error> {
-        maybe_await!(self.deref().setup(stop_gap, database, progress_update))
-    }
-
-    fn sync<D: BatchDatabase, P: 'static + Progress>(
-        &self,
-        stop_gap: Option<usize>,
-        database: &mut D,
-        progress_update: P,
-    ) -> Result<(), Error> {
-        maybe_await!(self.deref().sync(stop_gap, database, progress_update))
-    }
-
-    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
-        maybe_await!(self.deref().get_tx(txid))
-    }
-    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
-        maybe_await!(self.deref().broadcast(tx))
-    }
-
-    fn get_height(&self) -> Result<u32, Error> {
-        maybe_await!(self.deref().get_height())
-    }
-    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
-        maybe_await!(self.deref().estimate_fee(target))
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/utils.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/utils.rs.html deleted file mode 100644 index 1a950457b4..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/blockchain/utils.rs.html +++ /dev/null @@ -1,719 +0,0 @@ -utils.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-use std::cmp;
-use std::collections::{HashSet, VecDeque};
-use std::convert::TryFrom;
-
-#[allow(unused_imports)]
-use log::{debug, error, info, trace};
-
-use bitcoin::{Address, Network, OutPoint, Script, Transaction, Txid};
-
-use super::*;
-use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
-use crate::error::Error;
-use crate::types::{ScriptType, TransactionDetails, UTXO};
-use crate::wallet::utils::ChunksIterator;
-
-#[derive(Debug)]
-pub struct ELSGetHistoryRes {
-    pub height: i32,
-    pub tx_hash: Txid,
-}
-
-#[derive(Debug)]
-pub struct ELSListUnspentRes {
-    pub height: usize,
-    pub tx_hash: Txid,
-    pub tx_pos: usize,
-}
-
-/// Implements the synchronization logic for an Electrum-like client.
-#[maybe_async]
-pub trait ElectrumLikeSync {
-    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
-        &self,
-        scripts: I,
-    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error>;
-
-    fn els_batch_script_list_unspent<'s, I: IntoIterator<Item = &'s Script>>(
-        &self,
-        scripts: I,
-    ) -> Result<Vec<Vec<ELSListUnspentRes>>, Error>;
-
-    fn els_transaction_get(&self, txid: &Txid) -> Result<Transaction, Error>;
-
-    // Provided methods down here...
-
-    fn electrum_like_setup<D: BatchDatabase, P: Progress>(
-        &self,
-        stop_gap: Option<usize>,
-        database: &mut D,
-        _progress_update: P,
-    ) -> Result<(), Error> {
-        // TODO: progress
-
-        let stop_gap = stop_gap.unwrap_or(20);
-        let batch_query_size = 20;
-
-        // check unconfirmed tx, delete so they are retrieved later
-        let mut del_batch = database.begin_batch();
-        for tx in database.iter_txs(false)? {
-            if tx.height.is_none() {
-                del_batch.del_tx(&tx.txid, false)?;
-            }
-        }
-        database.commit_batch(del_batch)?;
-
-        // maximum derivation index for a change address that we've seen during sync
-        let mut change_max_deriv = None;
-
-        let mut already_checked: HashSet<Script> = HashSet::new();
-        let mut to_check_later = VecDeque::with_capacity(batch_query_size);
-
-        // insert the first chunk
-        let mut iter_scriptpubkeys = database
-            .iter_script_pubkeys(Some(ScriptType::External))?
-            .into_iter();
-        let chunk: Vec<Script> = iter_scriptpubkeys.by_ref().take(batch_query_size).collect();
-        for item in chunk.into_iter().rev() {
-            to_check_later.push_front(item);
-        }
-
-        let mut iterating_external = true;
-        let mut index = 0;
-        let mut last_found = None;
-        while !to_check_later.is_empty() {
-            trace!("to_check_later size {}", to_check_later.len());
-
-            let until = cmp::min(to_check_later.len(), batch_query_size);
-            let chunk: Vec<Script> = to_check_later.drain(..until).collect();
-            let call_result = maybe_await!(self.els_batch_script_get_history(chunk.iter()))?;
-
-            for (script, history) in chunk.into_iter().zip(call_result.into_iter()) {
-                trace!("received history for {:?}, size {}", script, history.len());
-
-                if !history.is_empty() {
-                    last_found = Some(index);
-
-                    let mut check_later_scripts = maybe_await!(self.check_history(
-                        database,
-                        script,
-                        history,
-                        &mut change_max_deriv
-                    ))?
-                    .into_iter()
-                    .filter(|x| already_checked.insert(x.clone()))
-                    .collect();
-                    to_check_later.append(&mut check_later_scripts);
-                }
-
-                index += 1;
-            }
-
-            match iterating_external {
-                true if index - last_found.unwrap_or(0) >= stop_gap => iterating_external = false,
-                true => {
-                    trace!("pushing one more batch from `iter_scriptpubkeys`. index = {}, last_found = {:?}, stop_gap = {}", index, last_found, stop_gap);
-
-                    let chunk: Vec<Script> =
-                        iter_scriptpubkeys.by_ref().take(batch_query_size).collect();
-                    for item in chunk.into_iter().rev() {
-                        to_check_later.push_front(item);
-                    }
-                }
-                _ => {}
-            }
-        }
-
-        // check utxo
-        // TODO: try to minimize network requests and re-use scripts if possible
-        let mut batch = database.begin_batch();
-        for chunk in ChunksIterator::new(database.iter_utxos()?.into_iter(), batch_query_size) {
-            let scripts: Vec<_> = chunk.iter().map(|u| &u.txout.script_pubkey).collect();
-            let call_result = maybe_await!(self.els_batch_script_list_unspent(scripts))?;
-
-            // check which utxos are actually still unspent
-            for (utxo, list_unspent) in chunk.into_iter().zip(call_result.iter()) {
-                debug!(
-                    "outpoint {:?} is unspent for me, list unspent is {:?}",
-                    utxo.outpoint, list_unspent
-                );
-
-                let mut spent = true;
-                for unspent in list_unspent {
-                    let res_outpoint = OutPoint::new(unspent.tx_hash, unspent.tx_pos as u32);
-                    if utxo.outpoint == res_outpoint {
-                        spent = false;
-                        break;
-                    }
-                }
-                if spent {
-                    info!("{} not anymore unspent, removing", utxo.outpoint);
-                    batch.del_utxo(&utxo.outpoint)?;
-                }
-            }
-        }
-
-        let current_ext = database.get_last_index(ScriptType::External)?.unwrap_or(0);
-        let first_ext_new = last_found.map(|x| x + 1).unwrap_or(0) as u32;
-        if first_ext_new > current_ext {
-            info!("Setting external index to {}", first_ext_new);
-            database.set_last_index(ScriptType::External, first_ext_new)?;
-        }
-
-        let current_int = database.get_last_index(ScriptType::Internal)?.unwrap_or(0);
-        let first_int_new = change_max_deriv.map(|x| x + 1).unwrap_or(0);
-        if first_int_new > current_int {
-            info!("Setting internal index to {}", first_int_new);
-            database.set_last_index(ScriptType::Internal, first_int_new)?;
-        }
-
-        database.commit_batch(batch)?;
-
-        Ok(())
-    }
-
-    fn check_tx_and_descendant<D: BatchDatabase>(
-        &self,
-        database: &mut D,
-        txid: &Txid,
-        height: Option<u32>,
-        cur_script: &Script,
-        change_max_deriv: &mut Option<u32>,
-    ) -> Result<Vec<Script>, Error> {
-        debug!(
-            "check_tx_and_descendant of {}, height: {:?}, script: {}",
-            txid, height, cur_script
-        );
-        let mut updates = database.begin_batch();
-        let tx = match database.get_tx(&txid, true)? {
-            Some(mut saved_tx) => {
-                // update the height if it's different (in case of reorg)
-                if saved_tx.height != height {
-                    info!(
-                        "updating height from {:?} to {:?} for tx {}",
-                        saved_tx.height, height, txid
-                    );
-                    saved_tx.height = height;
-                    updates.set_tx(&saved_tx)?;
-                }
-
-                debug!("already have {} in db, returning the cached version", txid);
-
-                // unwrap since we explicitly ask for the raw_tx, if it's not present something
-                // went wrong
-                saved_tx.transaction.unwrap()
-            }
-            None => {
-                let fetched_tx = maybe_await!(self.els_transaction_get(&txid))?;
-                database.set_raw_tx(&fetched_tx)?;
-
-                fetched_tx
-            }
-        };
-
-        let mut incoming: u64 = 0;
-        let mut outgoing: u64 = 0;
-
-        let mut inputs_sum: u64 = 0;
-        let mut outputs_sum: u64 = 0;
-
-        // look for our own inputs
-        for (i, input) in tx.input.iter().enumerate() {
-            // the fact that we visit addresses in a BFS fashion starting from the external addresses
-            // should ensure that this query is always consistent (i.e. when we get to call this all
-            // the transactions at a lower depth have already been indexed, so if an outpoint is ours
-            // we are guaranteed to have it in the db).
-            if let Some(previous_output) = database.get_previous_output(&input.previous_output)? {
-                inputs_sum += previous_output.value;
-
-                if database.is_mine(&previous_output.script_pubkey)? {
-                    outgoing += previous_output.value;
-
-                    debug!("{} input #{} is mine, removing from utxo", txid, i);
-                    updates.del_utxo(&input.previous_output)?;
-                }
-            } else {
-                // The input is not ours, but we still need to count it for the fees. so fetch the
-                // tx (from the database or from network) and check it
-                let tx = match database.get_tx(&input.previous_output.txid, true)? {
-                    Some(saved_tx) => saved_tx.transaction.unwrap(),
-                    None => {
-                        let fetched_tx =
-                            maybe_await!(self.els_transaction_get(&input.previous_output.txid))?;
-                        database.set_raw_tx(&fetched_tx)?;
-
-                        fetched_tx
-                    }
-                };
-
-                inputs_sum += tx.output[input.previous_output.vout as usize].value;
-            }
-        }
-
-        let mut to_check_later = vec![];
-        for (i, output) in tx.output.iter().enumerate() {
-            // to compute the fees later
-            outputs_sum += output.value;
-
-            // this output is ours, we have a path to derive it
-            if let Some((script_type, child)) =
-                database.get_path_from_script_pubkey(&output.script_pubkey)?
-            {
-                debug!("{} output #{} is mine, adding utxo", txid, i);
-                updates.set_utxo(&UTXO {
-                    outpoint: OutPoint::new(tx.txid(), i as u32),
-                    txout: output.clone(),
-                    is_internal: script_type.is_internal(),
-                })?;
-                incoming += output.value;
-
-                if output.script_pubkey != *cur_script {
-                    debug!("{} output #{} script {} was not current script, adding script to be checked later", txid, i, output.script_pubkey);
-                    to_check_later.push(output.script_pubkey.clone())
-                }
-
-                // derive as many change addrs as external addresses that we've seen
-                if script_type == ScriptType::Internal
-                    && (change_max_deriv.is_none() || child > change_max_deriv.unwrap_or(0))
-                {
-                    *change_max_deriv = Some(child);
-                }
-            }
-        }
-
-        let tx = TransactionDetails {
-            txid: tx.txid(),
-            transaction: Some(tx),
-            received: incoming,
-            sent: outgoing,
-            height,
-            timestamp: 0,
-            fees: inputs_sum - outputs_sum,
-        };
-        info!("Saving tx {}", txid);
-        updates.set_tx(&tx)?;
-
-        database.commit_batch(updates)?;
-
-        Ok(to_check_later)
-    }
-
-    fn check_history<D: BatchDatabase>(
-        &self,
-        database: &mut D,
-        script_pubkey: Script,
-        txs: Vec<ELSGetHistoryRes>,
-        change_max_deriv: &mut Option<u32>,
-    ) -> Result<Vec<Script>, Error> {
-        let mut to_check_later = Vec::new();
-
-        debug!(
-            "history of {} script {} has {} tx",
-            Address::from_script(&script_pubkey, Network::Testnet).unwrap(),
-            script_pubkey,
-            txs.len()
-        );
-
-        for tx in txs {
-            let height: Option<u32> = match tx.height {
-                0 | -1 => None,
-                x => u32::try_from(x).ok(),
-            };
-
-            to_check_later.extend_from_slice(&maybe_await!(self.check_tx_and_descendant(
-                database,
-                &tx.tx_hash,
-                height,
-                &script_pubkey,
-                change_max_deriv,
-            ))?);
-        }
-
-        Ok(to_check_later)
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/database/keyvalue.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/database/keyvalue.rs.html deleted file mode 100644 index 7661005fbc..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/database/keyvalue.rs.html +++ /dev/null @@ -1,965 +0,0 @@ -keyvalue.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-397
-398
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-409
-410
-411
-412
-413
-414
-415
-416
-417
-418
-419
-420
-421
-422
-423
-424
-425
-426
-427
-428
-429
-430
-431
-432
-433
-434
-435
-436
-437
-438
-439
-440
-441
-442
-443
-444
-445
-446
-447
-448
-449
-450
-451
-452
-453
-454
-455
-456
-457
-458
-459
-460
-461
-462
-463
-464
-465
-466
-467
-468
-469
-470
-471
-472
-473
-474
-475
-476
-477
-478
-479
-480
-481
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-use std::convert::TryInto;
-
-use sled::{Batch, Tree};
-
-use bitcoin::consensus::encode::{deserialize, serialize};
-use bitcoin::hash_types::Txid;
-use bitcoin::{OutPoint, Script, Transaction};
-
-use crate::database::memory::MapKey;
-use crate::database::{BatchDatabase, BatchOperations, Database};
-use crate::error::Error;
-use crate::types::*;
-
-macro_rules! impl_batch_operations {
-    ( { $($after_insert:tt)* }, $process_delete:ident ) => {
-        fn set_script_pubkey(&mut self, script: &Script, script_type: ScriptType, path: u32) -> Result<(), Error> {
-            let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
-            self.insert(key, serialize(script))$($after_insert)*;
-
-            let key = MapKey::Script(Some(script)).as_map_key();
-            let value = json!({
-                "t": script_type,
-                "p": path,
-            });
-            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
-
-            Ok(())
-        }
-
-        fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
-            let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
-            let value = json!({
-                "t": utxo.txout,
-                "i": utxo.is_internal,
-            });
-            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
-
-            Ok(())
-        }
-
-        fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
-            let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
-            let value = serialize(transaction);
-            self.insert(key, value)$($after_insert)*;
-
-            Ok(())
-        }
-
-        fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
-            let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
-
-            // remove the raw tx from the serialized version
-            let mut value = serde_json::to_value(transaction)?;
-            value["transaction"] = serde_json::Value::Null;
-            let value = serde_json::to_vec(&value)?;
-
-            self.insert(key, value)$($after_insert)*;
-
-            // insert the raw_tx if present
-            if let Some(ref tx) = transaction.transaction {
-                self.set_raw_tx(tx)?;
-            }
-
-            Ok(())
-        }
-
-        fn set_last_index(&mut self, script_type: ScriptType, value: u32) -> Result<(), Error> {
-            let key = MapKey::LastIndex(script_type).as_map_key();
-            self.insert(key, &value.to_be_bytes())$($after_insert)*;
-
-            Ok(())
-        }
-
-        fn del_script_pubkey_from_path(&mut self, script_type: ScriptType, path: u32) -> Result<Option<Script>, Error> {
-            let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
-            let res = self.remove(key);
-            let res = $process_delete!(res);
-
-            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
-        }
-
-        fn del_path_from_script_pubkey(&mut self, script: &Script) -> Result<Option<(ScriptType, u32)>, Error> {
-            let key = MapKey::Script(Some(script)).as_map_key();
-            let res = self.remove(key);
-            let res = $process_delete!(res);
-
-            match res {
-                None => Ok(None),
-                Some(b) => {
-                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
-                    let st = serde_json::from_value(val["t"].take())?;
-                    let path = serde_json::from_value(val["p"].take())?;
-
-                    Ok(Some((st, path)))
-                }
-            }
-        }
-
-        fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
-            let key = MapKey::UTXO(Some(outpoint)).as_map_key();
-            let res = self.remove(key);
-            let res = $process_delete!(res);
-
-            match res {
-                None => Ok(None),
-                Some(b) => {
-                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
-                    let txout = serde_json::from_value(val["t"].take())?;
-                    let is_internal = serde_json::from_value(val["i"].take())?;
-
-                    Ok(Some(UTXO { outpoint: outpoint.clone(), txout, is_internal }))
-                }
-            }
-        }
-
-        fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
-            let key = MapKey::RawTx(Some(txid)).as_map_key();
-            let res = self.remove(key);
-            let res = $process_delete!(res);
-
-            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
-        }
-
-        fn del_tx(&mut self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
-            let raw_tx = if include_raw {
-                self.del_raw_tx(txid)?
-            } else {
-                None
-            };
-
-            let key = MapKey::Transaction(Some(txid)).as_map_key();
-            let res = self.remove(key);
-            let res = $process_delete!(res);
-
-            match res {
-                None => Ok(None),
-                Some(b) => {
-                    let mut val: TransactionDetails = serde_json::from_slice(&b)?;
-                    val.transaction = raw_tx;
-
-                    Ok(Some(val))
-                }
-            }
-        }
-
-        fn del_last_index(&mut self, script_type: ScriptType) -> Result<Option<u32>, Error> {
-            let key = MapKey::LastIndex(script_type).as_map_key();
-            let res = self.remove(key);
-            let res = $process_delete!(res);
-
-            match res {
-                None => Ok(None),
-                Some(b) => {
-                    let array: [u8; 4] = b.as_ref().try_into().map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
-                    let val = u32::from_be_bytes(array);
-                    Ok(Some(val))
-                }
-            }
-        }
-    }
-}
-
-macro_rules! process_delete_tree {
-    ($res:expr) => {
-        $res?
-    };
-}
-impl BatchOperations for Tree {
-    impl_batch_operations!({?}, process_delete_tree);
-}
-
-macro_rules! process_delete_batch {
-    ($res:expr) => {
-        None as Option<sled::IVec>
-    };
-}
-#[allow(unused_variables)]
-impl BatchOperations for Batch {
-    impl_batch_operations!({}, process_delete_batch);
-}
-
-impl Database for Tree {
-    fn check_descriptor_checksum<B: AsRef<[u8]>>(
-        &mut self,
-        script_type: ScriptType,
-        bytes: B,
-    ) -> Result<(), Error> {
-        let key = MapKey::DescriptorChecksum(script_type).as_map_key();
-
-        let prev = self.get(&key)?.map(|x| x.to_vec());
-        if let Some(val) = prev {
-            if val == bytes.as_ref() {
-                Ok(())
-            } else {
-                Err(Error::ChecksumMismatch)
-            }
-        } else {
-            self.insert(&key, bytes.as_ref())?;
-            Ok(())
-        }
-    }
-
-    fn iter_script_pubkeys(&self, script_type: Option<ScriptType>) -> Result<Vec<Script>, Error> {
-        let key = MapKey::Path((script_type, None)).as_map_key();
-        self.scan_prefix(key)
-            .map(|x| -> Result<_, Error> {
-                let (_, v) = x?;
-                Ok(deserialize(&v)?)
-            })
-            .collect()
-    }
-
-    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error> {
-        let key = MapKey::UTXO(None).as_map_key();
-        self.scan_prefix(key)
-            .map(|x| -> Result<_, Error> {
-                let (k, v) = x?;
-                let outpoint = deserialize(&k[1..])?;
-
-                let mut val: serde_json::Value = serde_json::from_slice(&v)?;
-                let txout = serde_json::from_value(val["t"].take())?;
-                let is_internal = serde_json::from_value(val["i"].take())?;
-
-                Ok(UTXO {
-                    outpoint,
-                    txout,
-                    is_internal,
-                })
-            })
-            .collect()
-    }
-
-    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
-        let key = MapKey::RawTx(None).as_map_key();
-        self.scan_prefix(key)
-            .map(|x| -> Result<_, Error> {
-                let (_, v) = x?;
-                Ok(deserialize(&v)?)
-            })
-            .collect()
-    }
-
-    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
-        let key = MapKey::Transaction(None).as_map_key();
-        self.scan_prefix(key)
-            .map(|x| -> Result<_, Error> {
-                let (k, v) = x?;
-                let mut txdetails: TransactionDetails = serde_json::from_slice(&v)?;
-                if include_raw {
-                    let txid = deserialize(&k[1..])?;
-                    txdetails.transaction = self.get_raw_tx(&txid)?;
-                }
-
-                Ok(txdetails)
-            })
-            .collect()
-    }
-
-    fn get_script_pubkey_from_path(
-        &self,
-        script_type: ScriptType,
-        path: u32,
-    ) -> Result<Option<Script>, Error> {
-        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
-        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
-    }
-
-    fn get_path_from_script_pubkey(
-        &self,
-        script: &Script,
-    ) -> Result<Option<(ScriptType, u32)>, Error> {
-        let key = MapKey::Script(Some(script)).as_map_key();
-        self.get(key)?
-            .map(|b| -> Result<_, Error> {
-                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
-                let st = serde_json::from_value(val["t"].take())?;
-                let path = serde_json::from_value(val["p"].take())?;
-
-                Ok((st, path))
-            })
-            .transpose()
-    }
-
-    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
-        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
-        self.get(key)?
-            .map(|b| -> Result<_, Error> {
-                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
-                let txout = serde_json::from_value(val["t"].take())?;
-                let is_internal = serde_json::from_value(val["i"].take())?;
-
-                Ok(UTXO {
-                    outpoint: outpoint.clone(),
-                    txout,
-                    is_internal,
-                })
-            })
-            .transpose()
-    }
-
-    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
-        let key = MapKey::RawTx(Some(txid)).as_map_key();
-        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
-    }
-
-    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
-        let key = MapKey::Transaction(Some(txid)).as_map_key();
-        self.get(key)?
-            .map(|b| -> Result<_, Error> {
-                let mut txdetails: TransactionDetails = serde_json::from_slice(&b)?;
-                if include_raw {
-                    txdetails.transaction = self.get_raw_tx(&txid)?;
-                }
-
-                Ok(txdetails)
-            })
-            .transpose()
-    }
-
-    fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error> {
-        let key = MapKey::LastIndex(script_type).as_map_key();
-        self.get(key)?
-            .map(|b| -> Result<_, Error> {
-                let array: [u8; 4] = b
-                    .as_ref()
-                    .try_into()
-                    .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
-                let val = u32::from_be_bytes(array);
-                Ok(val)
-            })
-            .transpose()
-    }
-
-    // inserts 0 if not present
-    fn increment_last_index(&mut self, script_type: ScriptType) -> Result<u32, Error> {
-        let key = MapKey::LastIndex(script_type).as_map_key();
-        self.update_and_fetch(key, |prev| {
-            let new = match prev {
-                Some(b) => {
-                    let array: [u8; 4] = b.try_into().unwrap_or([0; 4]);
-                    let val = u32::from_be_bytes(array);
-
-                    val + 1
-                }
-                None => 0,
-            };
-
-            Some(new.to_be_bytes().to_vec())
-        })?
-        .map_or(Ok(0), |b| -> Result<_, Error> {
-            let array: [u8; 4] = b
-                .as_ref()
-                .try_into()
-                .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
-            let val = u32::from_be_bytes(array);
-            Ok(val)
-        })
-    }
-}
-
-impl BatchDatabase for Tree {
-    type Batch = sled::Batch;
-
-    fn begin_batch(&self) -> Self::Batch {
-        sled::Batch::default()
-    }
-
-    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
-        Ok(self.apply_batch(batch)?)
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use std::sync::{Arc, Condvar, Mutex, Once};
-    use std::time::{SystemTime, UNIX_EPOCH};
-
-    use sled::{Db, Tree};
-
-    static mut COUNT: usize = 0;
-
-    lazy_static! {
-        static ref DB: Arc<(Mutex<Option<Db>>, Condvar)> =
-            Arc::new((Mutex::new(None), Condvar::new()));
-        static ref INIT: Once = Once::new();
-    }
-
-    fn get_tree() -> Tree {
-        unsafe {
-            let cloned = DB.clone();
-            let (mutex, cvar) = &*cloned;
-
-            INIT.call_once(|| {
-                let mut db = mutex.lock().unwrap();
-
-                let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
-                let mut dir = std::env::temp_dir();
-                dir.push(format!("mbw_{}", time.as_nanos()));
-
-                *db = Some(sled::open(dir).unwrap());
-                cvar.notify_all();
-            });
-
-            let mut db = mutex.lock().unwrap();
-            while !db.is_some() {
-                db = cvar.wait(db).unwrap();
-            }
-
-            COUNT += 1;
-
-            db.as_ref()
-                .unwrap()
-                .open_tree(format!("tree_{}", COUNT))
-                .unwrap()
-        }
-    }
-
-    #[test]
-    fn test_script_pubkey() {
-        crate::database::test::test_script_pubkey(get_tree());
-    }
-
-    #[test]
-    fn test_batch_script_pubkey() {
-        crate::database::test::test_batch_script_pubkey(get_tree());
-    }
-
-    #[test]
-    fn test_iter_script_pubkey() {
-        crate::database::test::test_iter_script_pubkey(get_tree());
-    }
-
-    #[test]
-    fn test_del_script_pubkey() {
-        crate::database::test::test_del_script_pubkey(get_tree());
-    }
-
-    #[test]
-    fn test_utxo() {
-        crate::database::test::test_utxo(get_tree());
-    }
-
-    #[test]
-    fn test_raw_tx() {
-        crate::database::test::test_raw_tx(get_tree());
-    }
-
-    #[test]
-    fn test_tx() {
-        crate::database::test::test_tx(get_tree());
-    }
-
-    #[test]
-    fn test_last_index() {
-        crate::database::test::test_last_index(get_tree());
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/database/memory.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/database/memory.rs.html deleted file mode 100644 index 254c8a74af..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/database/memory.rs.html +++ /dev/null @@ -1,1119 +0,0 @@ -memory.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-397
-398
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-409
-410
-411
-412
-413
-414
-415
-416
-417
-418
-419
-420
-421
-422
-423
-424
-425
-426
-427
-428
-429
-430
-431
-432
-433
-434
-435
-436
-437
-438
-439
-440
-441
-442
-443
-444
-445
-446
-447
-448
-449
-450
-451
-452
-453
-454
-455
-456
-457
-458
-459
-460
-461
-462
-463
-464
-465
-466
-467
-468
-469
-470
-471
-472
-473
-474
-475
-476
-477
-478
-479
-480
-481
-482
-483
-484
-485
-486
-487
-488
-489
-490
-491
-492
-493
-494
-495
-496
-497
-498
-499
-500
-501
-502
-503
-504
-505
-506
-507
-508
-509
-510
-511
-512
-513
-514
-515
-516
-517
-518
-519
-520
-521
-522
-523
-524
-525
-526
-527
-528
-529
-530
-531
-532
-533
-534
-535
-536
-537
-538
-539
-540
-541
-542
-543
-544
-545
-546
-547
-548
-549
-550
-551
-552
-553
-554
-555
-556
-557
-558
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! In-memory ephemeral database
-//!
-//! This module defines an in-memory database type called [`MemoryDatabase`] that is based on a
-//! [`BTreeMap`].
-
-use std::collections::BTreeMap;
-use std::ops::Bound::{Excluded, Included};
-
-use bitcoin::consensus::encode::{deserialize, serialize};
-use bitcoin::hash_types::Txid;
-use bitcoin::{OutPoint, Script, Transaction};
-
-use crate::database::{BatchDatabase, BatchOperations, Database};
-use crate::error::Error;
-use crate::types::*;
-
-// path -> script       p{i,e}<path> -> script
-// script -> path       s<script> -> {i,e}<path>
-// outpoint             u<outpoint> -> txout
-// rawtx                r<txid> -> tx
-// transactions         t<txid> -> tx details
-// deriv indexes        c{i,e} -> u32
-// descriptor checksum  d{i,e} -> vec<u8>
-
-pub(crate) enum MapKey<'a> {
-    Path((Option<ScriptType>, Option<u32>)),
-    Script(Option<&'a Script>),
-    UTXO(Option<&'a OutPoint>),
-    RawTx(Option<&'a Txid>),
-    Transaction(Option<&'a Txid>),
-    LastIndex(ScriptType),
-    DescriptorChecksum(ScriptType),
-}
-
-impl MapKey<'_> {
-    pub fn as_prefix(&self) -> Vec<u8> {
-        match self {
-            MapKey::Path((st, _)) => {
-                let mut v = b"p".to_vec();
-                if let Some(st) = st {
-                    v.push(st.as_byte());
-                }
-                v
-            }
-            MapKey::Script(_) => b"s".to_vec(),
-            MapKey::UTXO(_) => b"u".to_vec(),
-            MapKey::RawTx(_) => b"r".to_vec(),
-            MapKey::Transaction(_) => b"t".to_vec(),
-            MapKey::LastIndex(st) => [b"c", st.as_ref()].concat(),
-            MapKey::DescriptorChecksum(st) => [b"d", st.as_ref()].concat(),
-        }
-    }
-
-    fn serialize_content(&self) -> Vec<u8> {
-        match self {
-            MapKey::Path((_, Some(child))) => u32::from(*child).to_be_bytes().to_vec(),
-            MapKey::Script(Some(s)) => serialize(*s),
-            MapKey::UTXO(Some(s)) => serialize(*s),
-            MapKey::RawTx(Some(s)) => serialize(*s),
-            MapKey::Transaction(Some(s)) => serialize(*s),
-            _ => vec![],
-        }
-    }
-
-    pub fn as_map_key(&self) -> Vec<u8> {
-        let mut v = self.as_prefix();
-        v.extend_from_slice(&self.serialize_content());
-
-        v
-    }
-}
-
-fn after(key: &Vec<u8>) -> Vec<u8> {
-    let mut key = key.clone();
-    let mut idx = key.len();
-    while idx > 0 {
-        if key[idx - 1] == 0xFF {
-            idx -= 1;
-            continue;
-        } else {
-            key[idx - 1] += 1;
-            break;
-        }
-    }
-
-    key
-}
-
-/// In-memory ephemeral database
-///
-/// This database can be used as a temporary storage for wallets that are not kept permanently on
-/// a device, or on platforms that don't provide a filesystem, like `wasm32`.
-///
-/// Once it's dropped its content will be lost.
-///
-/// If you are looking for a permanent storage solution, you can try with the default key-value
-/// database called [`sled`]. See the [`database`] module documentation for more defailts.
-///
-/// [`database`]: crate::database
-#[derive(Debug, Default)]
-pub struct MemoryDatabase {
-    map: BTreeMap<Vec<u8>, Box<dyn std::any::Any>>,
-    deleted_keys: Vec<Vec<u8>>,
-}
-
-impl MemoryDatabase {
-    /// Create a new empty database
-    pub fn new() -> Self {
-        MemoryDatabase {
-            map: BTreeMap::new(),
-            deleted_keys: Vec::new(),
-        }
-    }
-}
-
-impl BatchOperations for MemoryDatabase {
-    fn set_script_pubkey(
-        &mut self,
-        script: &Script,
-        script_type: ScriptType,
-        path: u32,
-    ) -> Result<(), Error> {
-        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
-        self.map.insert(key, Box::new(script.clone()));
-
-        let key = MapKey::Script(Some(script)).as_map_key();
-        let value = json!({
-            "t": script_type,
-            "p": path,
-        });
-        self.map.insert(key, Box::new(value));
-
-        Ok(())
-    }
-
-    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
-        let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
-        self.map
-            .insert(key, Box::new((utxo.txout.clone(), utxo.is_internal)));
-
-        Ok(())
-    }
-    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
-        let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
-        self.map.insert(key, Box::new(transaction.clone()));
-
-        Ok(())
-    }
-    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
-        let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
-
-        // insert the raw_tx if present
-        if let Some(ref tx) = transaction.transaction {
-            self.set_raw_tx(tx)?;
-        }
-
-        // remove the raw tx from the serialized version
-        let mut transaction = transaction.clone();
-        transaction.transaction = None;
-
-        self.map.insert(key, Box::new(transaction));
-
-        Ok(())
-    }
-    fn set_last_index(&mut self, script_type: ScriptType, value: u32) -> Result<(), Error> {
-        let key = MapKey::LastIndex(script_type).as_map_key();
-        self.map.insert(key, Box::new(value));
-
-        Ok(())
-    }
-
-    fn del_script_pubkey_from_path(
-        &mut self,
-        script_type: ScriptType,
-        path: u32,
-    ) -> Result<Option<Script>, Error> {
-        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
-        let res = self.map.remove(&key);
-        self.deleted_keys.push(key);
-
-        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
-    }
-    fn del_path_from_script_pubkey(
-        &mut self,
-        script: &Script,
-    ) -> Result<Option<(ScriptType, u32)>, Error> {
-        let key = MapKey::Script(Some(script)).as_map_key();
-        let res = self.map.remove(&key);
-        self.deleted_keys.push(key);
-
-        match res {
-            None => Ok(None),
-            Some(b) => {
-                let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
-                let st = serde_json::from_value(val["t"].take())?;
-                let path = serde_json::from_value(val["p"].take())?;
-
-                Ok(Some((st, path)))
-            }
-        }
-    }
-    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
-        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
-        let res = self.map.remove(&key);
-        self.deleted_keys.push(key);
-
-        match res {
-            None => Ok(None),
-            Some(b) => {
-                let (txout, is_internal) = b.downcast_ref().cloned().unwrap();
-                Ok(Some(UTXO {
-                    outpoint: outpoint.clone(),
-                    txout,
-                    is_internal,
-                }))
-            }
-        }
-    }
-    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
-        let key = MapKey::RawTx(Some(txid)).as_map_key();
-        let res = self.map.remove(&key);
-        self.deleted_keys.push(key);
-
-        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
-    }
-    fn del_tx(
-        &mut self,
-        txid: &Txid,
-        include_raw: bool,
-    ) -> Result<Option<TransactionDetails>, Error> {
-        let raw_tx = if include_raw {
-            self.del_raw_tx(txid)?
-        } else {
-            None
-        };
-
-        let key = MapKey::Transaction(Some(txid)).as_map_key();
-        let res = self.map.remove(&key);
-        self.deleted_keys.push(key);
-
-        match res {
-            None => Ok(None),
-            Some(b) => {
-                let mut val: TransactionDetails = b.downcast_ref().cloned().unwrap();
-                val.transaction = raw_tx;
-
-                Ok(Some(val))
-            }
-        }
-    }
-    fn del_last_index(&mut self, script_type: ScriptType) -> Result<Option<u32>, Error> {
-        let key = MapKey::LastIndex(script_type).as_map_key();
-        let res = self.map.remove(&key);
-        self.deleted_keys.push(key);
-
-        match res {
-            None => Ok(None),
-            Some(b) => Ok(Some(*b.downcast_ref().unwrap())),
-        }
-    }
-}
-
-impl Database for MemoryDatabase {
-    fn check_descriptor_checksum<B: AsRef<[u8]>>(
-        &mut self,
-        script_type: ScriptType,
-        bytes: B,
-    ) -> Result<(), Error> {
-        let key = MapKey::DescriptorChecksum(script_type).as_map_key();
-
-        let prev = self
-            .map
-            .get(&key)
-            .map(|x| x.downcast_ref::<Vec<u8>>().unwrap());
-        if let Some(val) = prev {
-            if val == &bytes.as_ref().to_vec() {
-                Ok(())
-            } else {
-                Err(Error::ChecksumMismatch)
-            }
-        } else {
-            self.map.insert(key, Box::new(bytes.as_ref().to_vec()));
-            Ok(())
-        }
-    }
-
-    fn iter_script_pubkeys(&self, script_type: Option<ScriptType>) -> Result<Vec<Script>, Error> {
-        let key = MapKey::Path((script_type, None)).as_map_key();
-        self.map
-            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
-            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
-            .collect()
-    }
-
-    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error> {
-        let key = MapKey::UTXO(None).as_map_key();
-        self.map
-            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
-            .map(|(k, v)| {
-                let outpoint = deserialize(&k[1..]).unwrap();
-                let (txout, is_internal) = v.downcast_ref().cloned().unwrap();
-                Ok(UTXO {
-                    outpoint,
-                    txout,
-                    is_internal,
-                })
-            })
-            .collect()
-    }
-
-    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
-        let key = MapKey::RawTx(None).as_map_key();
-        self.map
-            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
-            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
-            .collect()
-    }
-
-    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
-        let key = MapKey::Transaction(None).as_map_key();
-        self.map
-            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
-            .map(|(k, v)| {
-                let mut txdetails: TransactionDetails = v.downcast_ref().cloned().unwrap();
-                if include_raw {
-                    let txid = deserialize(&k[1..])?;
-                    txdetails.transaction = self.get_raw_tx(&txid)?;
-                }
-
-                Ok(txdetails)
-            })
-            .collect()
-    }
-
-    fn get_script_pubkey_from_path(
-        &self,
-        script_type: ScriptType,
-        path: u32,
-    ) -> Result<Option<Script>, Error> {
-        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
-        Ok(self
-            .map
-            .get(&key)
-            .map(|b| b.downcast_ref().cloned().unwrap()))
-    }
-
-    fn get_path_from_script_pubkey(
-        &self,
-        script: &Script,
-    ) -> Result<Option<(ScriptType, u32)>, Error> {
-        let key = MapKey::Script(Some(script)).as_map_key();
-        Ok(self.map.get(&key).map(|b| {
-            let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
-            let st = serde_json::from_value(val["t"].take()).unwrap();
-            let path = serde_json::from_value(val["p"].take()).unwrap();
-
-            (st, path)
-        }))
-    }
-
-    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
-        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
-        Ok(self.map.get(&key).map(|b| {
-            let (txout, is_internal) = b.downcast_ref().cloned().unwrap();
-            UTXO {
-                outpoint: outpoint.clone(),
-                txout,
-                is_internal,
-            }
-        }))
-    }
-
-    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
-        let key = MapKey::RawTx(Some(txid)).as_map_key();
-        Ok(self
-            .map
-            .get(&key)
-            .map(|b| b.downcast_ref().cloned().unwrap()))
-    }
-
-    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
-        let key = MapKey::Transaction(Some(txid)).as_map_key();
-        Ok(self.map.get(&key).map(|b| {
-            let mut txdetails: TransactionDetails = b.downcast_ref().cloned().unwrap();
-            if include_raw {
-                txdetails.transaction = self.get_raw_tx(&txid).unwrap();
-            }
-
-            txdetails
-        }))
-    }
-
-    fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error> {
-        let key = MapKey::LastIndex(script_type).as_map_key();
-        Ok(self.map.get(&key).map(|b| *b.downcast_ref().unwrap()))
-    }
-
-    // inserts 0 if not present
-    fn increment_last_index(&mut self, script_type: ScriptType) -> Result<u32, Error> {
-        let key = MapKey::LastIndex(script_type).as_map_key();
-        let value = self
-            .map
-            .entry(key.clone())
-            .and_modify(|x| *x.downcast_mut::<u32>().unwrap() += 1)
-            .or_insert(Box::<u32>::new(0))
-            .downcast_mut()
-            .unwrap();
-
-        Ok(*value)
-    }
-}
-
-impl BatchDatabase for MemoryDatabase {
-    type Batch = Self;
-
-    fn begin_batch(&self) -> Self::Batch {
-        MemoryDatabase::new()
-    }
-
-    fn commit_batch(&mut self, mut batch: Self::Batch) -> Result<(), Error> {
-        for key in batch.deleted_keys {
-            self.map.remove(&key);
-        }
-
-        Ok(self.map.append(&mut batch.map))
-    }
-}
-
-#[cfg(test)]
-impl MemoryDatabase {
-    // Artificially insert a tx in the database, as if we had found it with a `sync`
-    pub fn received_tx(
-        &mut self,
-        tx_meta: testutils::TestIncomingTx,
-        current_height: Option<u32>,
-    ) -> bitcoin::Txid {
-        use std::str::FromStr;
-
-        let tx = Transaction {
-            version: 1,
-            lock_time: 0,
-            input: vec![],
-            output: tx_meta
-                .output
-                .iter()
-                .map(|out_meta| bitcoin::TxOut {
-                    value: out_meta.value,
-                    script_pubkey: bitcoin::Address::from_str(&out_meta.to_address)
-                        .unwrap()
-                        .script_pubkey(),
-                })
-                .collect(),
-        };
-
-        let txid = tx.txid();
-        let height = tx_meta
-            .min_confirmations
-            .map(|conf| current_height.unwrap().checked_sub(conf as u32).unwrap());
-
-        let tx_details = TransactionDetails {
-            transaction: Some(tx.clone()),
-            txid,
-            timestamp: 0,
-            height,
-            received: 0,
-            sent: 0,
-            fees: 0,
-        };
-
-        self.set_tx(&tx_details).unwrap();
-        for (vout, out) in tx.output.iter().enumerate() {
-            self.set_utxo(&UTXO {
-                txout: out.clone(),
-                outpoint: OutPoint {
-                    txid,
-                    vout: vout as u32,
-                },
-                is_internal: false,
-            })
-            .unwrap();
-        }
-
-        txid
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use super::MemoryDatabase;
-
-    fn get_tree() -> MemoryDatabase {
-        MemoryDatabase::new()
-    }
-
-    #[test]
-    fn test_script_pubkey() {
-        crate::database::test::test_script_pubkey(get_tree());
-    }
-
-    #[test]
-    fn test_batch_script_pubkey() {
-        crate::database::test::test_batch_script_pubkey(get_tree());
-    }
-
-    #[test]
-    fn test_iter_script_pubkey() {
-        crate::database::test::test_iter_script_pubkey(get_tree());
-    }
-
-    #[test]
-    fn test_del_script_pubkey() {
-        crate::database::test::test_del_script_pubkey(get_tree());
-    }
-
-    #[test]
-    fn test_utxo() {
-        crate::database::test::test_utxo(get_tree());
-    }
-
-    #[test]
-    fn test_raw_tx() {
-        crate::database::test::test_raw_tx(get_tree());
-    }
-
-    #[test]
-    fn test_tx() {
-        crate::database::test::test_tx(get_tree());
-    }
-
-    #[test]
-    fn test_last_index() {
-        crate::database::test::test_last_index(get_tree());
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/database/mod.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/database/mod.rs.html deleted file mode 100644 index 18c99840e1..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/database/mod.rs.html +++ /dev/null @@ -1,739 +0,0 @@ -mod.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Database types
-//!
-//! This module provides the implementation of some defaults database types, along with traits that
-//! can be implemented externally to let [`Wallet`]s use customized databases.
-//!
-//! It's important to note that the databases defined here only contains "blockchain-related" data.
-//! They can be seen more as a cache than a critical piece of storage that contains secrets and
-//! keys.
-//!
-//! The currently recommended database is [`sled`], which is a pretty simple key-value embedded
-//! database written in Rust. If the `key-value-db` feature is enabled (which by default is),
-//! this library automatically implements all the required traits for [`sled::Tree`].
-//!
-//! [`Wallet`]: crate::wallet::Wallet
-
-use bitcoin::hash_types::Txid;
-use bitcoin::{OutPoint, Script, Transaction, TxOut};
-
-use crate::error::Error;
-use crate::types::*;
-
-#[cfg(feature = "key-value-db")]
-pub(crate) mod keyvalue;
-
-pub mod memory;
-pub use memory::MemoryDatabase;
-
-/// Trait for operations that can be batched
-///
-/// This trait defines the list of operations that must be implemented on the [`Database`] type and
-/// the [`BatchDatabase::Batch`] type.
-pub trait BatchOperations {
-    /// Store a script_pubkey along with its script type and child number
-    fn set_script_pubkey(
-        &mut self,
-        script: &Script,
-        script_type: ScriptType,
-        child: u32,
-    ) -> Result<(), Error>;
-    /// Store a [`UTXO`]
-    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>;
-    /// Store a raw transaction
-    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>;
-    /// Store the metadata of a transaction
-    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>;
-    /// Store the last derivation index for a given script type
-    fn set_last_index(&mut self, script_type: ScriptType, value: u32) -> Result<(), Error>;
-
-    /// Delete a script_pubkey given the script type and its child number
-    fn del_script_pubkey_from_path(
-        &mut self,
-        script_type: ScriptType,
-        child: u32,
-    ) -> Result<Option<Script>, Error>;
-    /// Delete the data related to a specific script_pubkey, meaning the script type and the child
-    /// number
-    fn del_path_from_script_pubkey(
-        &mut self,
-        script: &Script,
-    ) -> Result<Option<(ScriptType, u32)>, Error>;
-    /// Delete a [`UTXO`] given its [`OutPoint`]
-    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>;
-    /// Delete a raw transaction given its [`Txid`]
-    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>;
-    /// Delete the metadata of a transaction and optionally the raw transaction itself
-    fn del_tx(
-        &mut self,
-        txid: &Txid,
-        include_raw: bool,
-    ) -> Result<Option<TransactionDetails>, Error>;
-    /// Delete the last derivation index for a script type
-    fn del_last_index(&mut self, script_type: ScriptType) -> Result<Option<u32>, Error>;
-}
-
-/// Trait for reading data from a database
-///
-/// This traits defines the operations that can be used to read data out of a database
-pub trait Database: BatchOperations {
-    /// Read and checks the descriptor checksum for a given script type
-    ///
-    /// Should return [`Error::ChecksumMismatch`](crate::error::Error::ChecksumMismatch) if the
-    /// checksum doesn't match. If there's no checksum in the database, simply store it for the
-    /// next time.
-    fn check_descriptor_checksum<B: AsRef<[u8]>>(
-        &mut self,
-        script_type: ScriptType,
-        bytes: B,
-    ) -> Result<(), Error>;
-
-    /// Return the list of script_pubkeys
-    fn iter_script_pubkeys(&self, script_type: Option<ScriptType>) -> Result<Vec<Script>, Error>;
-    /// Return the list of [`UTXO`]s
-    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>;
-    /// Return the list of raw transactions
-    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>;
-    /// Return the list of transactions metadata
-    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error>;
-
-    /// Fetch a script_pubkey given the script type and child number
-    fn get_script_pubkey_from_path(
-        &self,
-        script_type: ScriptType,
-        child: u32,
-    ) -> Result<Option<Script>, Error>;
-    /// Fetch the script type and child number of a given script_pubkey
-    fn get_path_from_script_pubkey(
-        &self,
-        script: &Script,
-    ) -> Result<Option<(ScriptType, u32)>, Error>;
-    /// Fetch a [`UTXO`] given its [`OutPoint`]
-    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>;
-    /// Fetch a raw transaction given its [`Txid`]
-    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
-    /// Fetch the transaction metadata and optionally also the raw transaction
-    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error>;
-    /// Return the last defivation index for a script type
-    fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error>;
-
-    /// Increment the last derivation index for a script type and returns it
-    ///
-    /// It should insert and return `0` if not present in the database
-    fn increment_last_index(&mut self, script_type: ScriptType) -> Result<u32, Error>;
-}
-
-/// Trait for a database that supports batch operations
-///
-/// This trait defines the methods to start and apply a batch of operations.
-pub trait BatchDatabase: Database {
-    /// Container for the operations
-    type Batch: BatchOperations;
-
-    /// Create a new batch container
-    fn begin_batch(&self) -> Self::Batch;
-    /// Consume and apply a batch of operations
-    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>;
-}
-
-pub(crate) trait DatabaseUtils: Database {
-    fn is_mine(&self, script: &Script) -> Result<bool, Error> {
-        self.get_path_from_script_pubkey(script)
-            .map(|o| o.is_some())
-    }
-
-    fn get_raw_tx_or<F>(&self, txid: &Txid, f: F) -> Result<Option<Transaction>, Error>
-    where
-        F: FnOnce() -> Result<Option<Transaction>, Error>,
-    {
-        self.get_tx(txid, true)?
-            .map(|t| t.transaction)
-            .flatten()
-            .map_or_else(f, |t| Ok(Some(t)))
-    }
-
-    fn get_previous_output(&self, outpoint: &OutPoint) -> Result<Option<TxOut>, Error> {
-        self.get_raw_tx(&outpoint.txid)?
-            .map(|previous_tx| {
-                if outpoint.vout as usize >= previous_tx.output.len() {
-                    Err(Error::InvalidOutpoint(outpoint.clone()))
-                } else {
-                    Ok(previous_tx.output[outpoint.vout as usize].clone())
-                }
-            })
-            .transpose()
-    }
-}
-
-impl<T: Database> DatabaseUtils for T {}
-
-#[cfg(test)]
-pub mod test {
-    use std::str::FromStr;
-
-    use bitcoin::consensus::encode::deserialize;
-    use bitcoin::hashes::hex::*;
-    use bitcoin::*;
-
-    use super::*;
-
-    pub fn test_script_pubkey<D: Database>(mut tree: D) {
-        let script = Script::from(
-            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
-        );
-        let path = 42;
-        let script_type = ScriptType::External;
-
-        tree.set_script_pubkey(&script, script_type, path).unwrap();
-
-        assert_eq!(
-            tree.get_script_pubkey_from_path(script_type, path).unwrap(),
-            Some(script.clone())
-        );
-        assert_eq!(
-            tree.get_path_from_script_pubkey(&script).unwrap(),
-            Some((script_type, path.clone()))
-        );
-    }
-
-    pub fn test_batch_script_pubkey<D: BatchDatabase>(mut tree: D) {
-        let mut batch = tree.begin_batch();
-
-        let script = Script::from(
-            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
-        );
-        let path = 42;
-        let script_type = ScriptType::External;
-
-        batch.set_script_pubkey(&script, script_type, path).unwrap();
-
-        assert_eq!(
-            tree.get_script_pubkey_from_path(script_type, path).unwrap(),
-            None
-        );
-        assert_eq!(tree.get_path_from_script_pubkey(&script).unwrap(), None);
-
-        tree.commit_batch(batch).unwrap();
-
-        assert_eq!(
-            tree.get_script_pubkey_from_path(script_type, path).unwrap(),
-            Some(script.clone())
-        );
-        assert_eq!(
-            tree.get_path_from_script_pubkey(&script).unwrap(),
-            Some((script_type, path.clone()))
-        );
-    }
-
-    pub fn test_iter_script_pubkey<D: Database>(mut tree: D) {
-        let script = Script::from(
-            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
-        );
-        let path = 42;
-        let script_type = ScriptType::External;
-
-        tree.set_script_pubkey(&script, script_type, path).unwrap();
-
-        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
-    }
-
-    pub fn test_del_script_pubkey<D: Database>(mut tree: D) {
-        let script = Script::from(
-            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
-        );
-        let path = 42;
-        let script_type = ScriptType::External;
-
-        tree.set_script_pubkey(&script, script_type, path).unwrap();
-        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
-
-        tree.del_script_pubkey_from_path(script_type, path).unwrap();
-        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 0);
-    }
-
-    pub fn test_utxo<D: Database>(mut tree: D) {
-        let outpoint = OutPoint::from_str(
-            "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0",
-        )
-        .unwrap();
-        let script = Script::from(
-            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
-        );
-        let txout = TxOut {
-            value: 133742,
-            script_pubkey: script,
-        };
-        let utxo = UTXO {
-            txout,
-            outpoint,
-            is_internal: false,
-        };
-
-        tree.set_utxo(&utxo).unwrap();
-
-        assert_eq!(tree.get_utxo(&outpoint).unwrap(), Some(utxo));
-    }
-
-    pub fn test_raw_tx<D: Database>(mut tree: D) {
-        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
-        let tx: Transaction = deserialize(&hex_tx).unwrap();
-
-        tree.set_raw_tx(&tx).unwrap();
-
-        let txid = tx.txid();
-
-        assert_eq!(tree.get_raw_tx(&txid).unwrap(), Some(tx));
-    }
-
-    pub fn test_tx<D: Database>(mut tree: D) {
-        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
-        let tx: Transaction = deserialize(&hex_tx).unwrap();
-        let txid = tx.txid();
-        let mut tx_details = TransactionDetails {
-            transaction: Some(tx),
-            txid,
-            timestamp: 123456,
-            received: 1337,
-            sent: 420420,
-            fees: 140,
-            height: Some(1000),
-        };
-
-        tree.set_tx(&tx_details).unwrap();
-
-        // get with raw tx too
-        assert_eq!(
-            tree.get_tx(&tx_details.txid, true).unwrap(),
-            Some(tx_details.clone())
-        );
-        // get only raw_tx
-        assert_eq!(
-            tree.get_raw_tx(&tx_details.txid).unwrap(),
-            tx_details.transaction
-        );
-
-        // now get without raw_tx
-        tx_details.transaction = None;
-        assert_eq!(
-            tree.get_tx(&tx_details.txid, false).unwrap(),
-            Some(tx_details)
-        );
-    }
-
-    pub fn test_last_index<D: Database>(mut tree: D) {
-        tree.set_last_index(ScriptType::External, 1337).unwrap();
-
-        assert_eq!(
-            tree.get_last_index(ScriptType::External).unwrap(),
-            Some(1337)
-        );
-        assert_eq!(tree.get_last_index(ScriptType::Internal).unwrap(), None);
-
-        let res = tree.increment_last_index(ScriptType::External).unwrap();
-        assert_eq!(res, 1338);
-        let res = tree.increment_last_index(ScriptType::Internal).unwrap();
-        assert_eq!(res, 0);
-
-        assert_eq!(
-            tree.get_last_index(ScriptType::External).unwrap(),
-            Some(1338)
-        );
-        assert_eq!(tree.get_last_index(ScriptType::Internal).unwrap(), Some(0));
-    }
-
-    // TODO: more tests...
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/descriptor/checksum.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/descriptor/checksum.rs.html deleted file mode 100644 index 27e088c1a8..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/descriptor/checksum.rs.html +++ /dev/null @@ -1,191 +0,0 @@ -checksum.rs.html -- source
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Descriptor checksum
-//!
-//! This module contains a re-implementation of the function used by Bitcoin Core to calculate the
-//! checksum of a descriptor
-
-use std::iter::FromIterator;
-
-use crate::descriptor::Error;
-
-const INPUT_CHARSET: &str =  "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
-const CHECKSUM_CHARSET: &str = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
-
-fn poly_mod(mut c: u64, val: u64) -> u64 {
-    let c0 = c >> 35;
-    c = ((c & 0x7ffffffff) << 5) ^ val;
-    if c0 & 1 > 0 {
-        c ^= 0xf5dee51989
-    };
-    if c0 & 2 > 0 {
-        c ^= 0xa9fdca3312
-    };
-    if c0 & 4 > 0 {
-        c ^= 0x1bab10e32d
-    };
-    if c0 & 8 > 0 {
-        c ^= 0x3706b1677a
-    };
-    if c0 & 16 > 0 {
-        c ^= 0x644d626ffd
-    };
-
-    c
-}
-
-/// Compute the checksum of a descriptor
-pub fn get_checksum(desc: &str) -> Result<String, Error> {
-    let mut c = 1;
-    let mut cls = 0;
-    let mut clscount = 0;
-    for ch in desc.chars() {
-        let pos = INPUT_CHARSET
-            .find(ch)
-            .ok_or(Error::InvalidDescriptorCharacter(ch))? as u64;
-        c = poly_mod(c, pos & 31);
-        cls = cls * 3 + (pos >> 5);
-        clscount += 1;
-        if clscount == 3 {
-            c = poly_mod(c, cls);
-            cls = 0;
-            clscount = 0;
-        }
-    }
-    if clscount > 0 {
-        c = poly_mod(c, cls);
-    }
-    (0..8).for_each(|_| c = poly_mod(c, 0));
-    c ^= 1;
-
-    let mut chars = Vec::with_capacity(8);
-    for j in 0..8 {
-        chars.push(
-            CHECKSUM_CHARSET
-                .chars()
-                .nth(((c >> (5 * (7 - j))) & 31) as usize)
-                .unwrap(),
-        );
-    }
-
-    Ok(String::from_iter(chars))
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/descriptor/error.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/descriptor/error.rs.html deleted file mode 100644 index 18abe65079..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/descriptor/error.rs.html +++ /dev/null @@ -1,135 +0,0 @@ -error.rs.html -- source
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Descriptor errors
-
-/// Errors related to the parsing and usage of descriptors
-#[derive(Debug)]
-pub enum Error {
-    InternalError,
-    InvalidPrefix(Vec<u8>),
-    HardenedDerivationOnXpub,
-    MalformedInput,
-    KeyParsingError(String),
-
-    Policy(crate::descriptor::policy::PolicyError),
-
-    InputIndexDoesntExist,
-    MissingPublicKey,
-    MissingDetails,
-
-    InvalidDescriptorCharacter(char),
-
-    CantDeriveWithMiniscript,
-
-    BIP32(bitcoin::util::bip32::Error),
-    Base58(bitcoin::util::base58::Error),
-    PK(bitcoin::util::key::Error),
-    Miniscript(miniscript::Error),
-    Hex(bitcoin::hashes::hex::Error),
-}
-
-impl std::fmt::Display for Error {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "{:?}", self)
-    }
-}
-
-impl std::error::Error for Error {}
-
-impl_error!(bitcoin::util::bip32::Error, BIP32);
-impl_error!(bitcoin::util::base58::Error, Base58);
-impl_error!(bitcoin::util::key::Error, PK);
-impl_error!(miniscript::Error, Miniscript);
-impl_error!(bitcoin::hashes::hex::Error, Hex);
-impl_error!(crate::descriptor::policy::PolicyError, Policy);
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/descriptor/mod.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/descriptor/mod.rs.html deleted file mode 100644 index 4718081e6a..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/descriptor/mod.rs.html +++ /dev/null @@ -1,883 +0,0 @@ -mod.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-397
-398
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-409
-410
-411
-412
-413
-414
-415
-416
-417
-418
-419
-420
-421
-422
-423
-424
-425
-426
-427
-428
-429
-430
-431
-432
-433
-434
-435
-436
-437
-438
-439
-440
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Descriptors
-//!
-//! This module contains generic utilities to work with descriptors, plus some re-exported types
-//! from [`miniscript`].
-
-use std::collections::{BTreeMap, HashMap};
-use std::fmt;
-use std::sync::Arc;
-
-use bitcoin::hashes::hash160;
-use bitcoin::secp256k1::Secp256k1;
-use bitcoin::util::bip32::{ChildNumber, DerivationPath, Fingerprint};
-use bitcoin::util::psbt;
-use bitcoin::{PublicKey, Script, TxOut};
-
-use miniscript::descriptor::{DescriptorPublicKey, DescriptorXKey, InnerXKey};
-pub use miniscript::{
-    Descriptor, Legacy, Miniscript, MiniscriptKey, ScriptContext, Segwitv0, Terminal, ToPublicKey,
-};
-
-pub mod checksum;
-pub mod error;
-pub mod policy;
-
-pub use self::checksum::get_checksum;
-use self::error::Error;
-pub use self::policy::Policy;
-use crate::wallet::signer::SignersContainer;
-
-/// Alias for a [`Descriptor`] that can contain extended keys using [`DescriptorPublicKey`]
-pub type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;
-
-/// Alias for the type of maps that represent derivation paths in a [`psbt::Input`] or
-/// [`psbt::Output`]
-///
-/// [`psbt::Input`]: bitcoin::util::psbt::Input
-/// [`psbt::Output`]: bitcoin::util::psbt::Output
-pub type HDKeyPaths = BTreeMap<PublicKey, (Fingerprint, DerivationPath)>;
-
-/// Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]
-pub trait ExtractPolicy {
-    fn extract_policy(
-        &self,
-        signers: Arc<SignersContainer<DescriptorPublicKey>>,
-    ) -> Result<Option<Policy>, Error>;
-}
-
-pub(crate) trait XKeyUtils {
-    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath;
-    fn root_fingerprint(&self) -> Fingerprint;
-}
-
-impl<K: InnerXKey> XKeyUtils for DescriptorXKey<K> {
-    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath {
-        let full_path = match &self.source {
-            &Some((_, ref path)) => path
-                .into_iter()
-                .chain(self.derivation_path.into_iter())
-                .cloned()
-                .collect(),
-            &None => self.derivation_path.clone(),
-        };
-
-        if self.is_wildcard {
-            full_path
-                .into_iter()
-                .chain(append.into_iter())
-                .cloned()
-                .collect()
-        } else {
-            full_path
-        }
-    }
-
-    fn root_fingerprint(&self) -> Fingerprint {
-        match &self.source {
-            &Some((fingerprint, _)) => fingerprint.clone(),
-            &None => self.xkey.xkey_fingerprint(),
-        }
-    }
-}
-
-pub(crate) trait DescriptorMeta: Sized {
-    fn is_witness(&self) -> bool;
-    fn get_hd_keypaths(&self, index: u32) -> Result<HDKeyPaths, Error>;
-    fn is_fixed(&self) -> bool;
-    fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths) -> Option<Self>;
-    fn derive_from_psbt_input(&self, psbt_input: &psbt::Input, utxo: Option<TxOut>)
-        -> Option<Self>;
-}
-
-pub(crate) trait DescriptorScripts {
-    fn psbt_redeem_script(&self) -> Option<Script>;
-    fn psbt_witness_script(&self) -> Option<Script>;
-}
-
-impl<T> DescriptorScripts for Descriptor<T>
-where
-    T: miniscript::MiniscriptKey + miniscript::ToPublicKey,
-{
-    fn psbt_redeem_script(&self) -> Option<Script> {
-        match self {
-            Descriptor::ShWpkh(_) => Some(self.witness_script()),
-            Descriptor::ShWsh(ref script) => Some(script.encode().to_v0_p2wsh()),
-            Descriptor::Sh(ref script) => Some(script.encode()),
-            Descriptor::Bare(ref script) => Some(script.encode()),
-            _ => None,
-        }
-    }
-
-    fn psbt_witness_script(&self) -> Option<Script> {
-        match self {
-            Descriptor::Wsh(ref script) => Some(script.encode()),
-            Descriptor::ShWsh(ref script) => Some(script.encode()),
-            _ => None,
-        }
-    }
-}
-
-impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
-    fn is_witness(&self) -> bool {
-        match self {
-            Descriptor::Bare(_) | Descriptor::Pk(_) | Descriptor::Pkh(_) | Descriptor::Sh(_) => {
-                false
-            }
-            Descriptor::Wpkh(_)
-            | Descriptor::ShWpkh(_)
-            | Descriptor::Wsh(_)
-            | Descriptor::ShWsh(_) => true,
-        }
-    }
-
-    fn get_hd_keypaths(&self, index: u32) -> Result<HDKeyPaths, Error> {
-        let mut answer = BTreeMap::new();
-
-        let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
-            match key {
-                DescriptorPublicKey::PubKey(_) => {}
-                DescriptorPublicKey::XPub(xpub) => {
-                    let derive_path = if xpub.is_wildcard {
-                        xpub.derivation_path
-                            .into_iter()
-                            .chain([ChildNumber::from_normal_idx(index)?].iter())
-                            .cloned()
-                            .collect()
-                    } else {
-                        xpub.derivation_path.clone()
-                    };
-                    let derived_pubkey = xpub
-                        .xkey
-                        .derive_pub(&Secp256k1::verification_only(), &derive_path)?;
-
-                    answer.insert(
-                        derived_pubkey.public_key,
-                        (
-                            xpub.root_fingerprint(),
-                            xpub.full_path(&[ChildNumber::from_normal_idx(index)?]),
-                        ),
-                    );
-                }
-            }
-
-            Ok(DummyKey::default())
-        };
-        let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
-
-        self.translate_pk(translatefpk, translatefpkh)?;
-
-        Ok(answer)
-    }
-
-    fn is_fixed(&self) -> bool {
-        let mut found_wildcard = false;
-
-        let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
-            match key {
-                DescriptorPublicKey::PubKey(_) => {}
-                DescriptorPublicKey::XPub(xpub) => {
-                    if xpub.is_wildcard {
-                        found_wildcard = true;
-                    }
-                }
-            }
-
-            Ok(DummyKey::default())
-        };
-        let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
-
-        self.translate_pk(translatefpk, translatefpkh).unwrap();
-
-        !found_wildcard
-    }
-
-    fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths) -> Option<Self> {
-        let index: HashMap<_, _> = hd_keypaths.values().cloned().collect();
-
-        let mut derive_path = None::<DerivationPath>;
-        let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
-            if derive_path.is_some() {
-                // already found a matching path, we are done
-                return Ok(DummyKey::default());
-            }
-
-            if let DescriptorPublicKey::XPub(xpub) = key {
-                // Check if the key matches one entry in our `index`. If it does, `matches()` will
-                // return the "prefix" that matched, so we remove that prefix from the full path
-                // found in `index` and save it in `derive_path`
-                let root_fingerprint = xpub.root_fingerprint();
-                derive_path = index
-                    .get_key_value(&root_fingerprint)
-                    .and_then(|(fingerprint, path)| xpub.matches(*fingerprint, path))
-                    .map(|prefix_path| prefix_path.into_iter().cloned().collect::<Vec<_>>())
-                    .map(|prefix| {
-                        index
-                            .get(&xpub.root_fingerprint())
-                            .unwrap()
-                            .into_iter()
-                            .skip(prefix.len())
-                            .cloned()
-                            .collect()
-                    });
-            }
-
-            Ok(DummyKey::default())
-        };
-        let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
-
-        self.translate_pk(translatefpk, translatefpkh).unwrap();
-
-        derive_path.map(|path| self.derive(path.as_ref()))
-    }
-
-    fn derive_from_psbt_input(
-        &self,
-        psbt_input: &psbt::Input,
-        utxo: Option<TxOut>,
-    ) -> Option<Self> {
-        if let Some(derived) = self.derive_from_hd_keypaths(&psbt_input.hd_keypaths) {
-            return Some(derived);
-        } else if !self.is_fixed() {
-            // If the descriptor is not fixed we can't brute-force the derivation address, so just
-            // exit here
-            return None;
-        }
-
-        match self {
-            Descriptor::Pk(_)
-            | Descriptor::Pkh(_)
-            | Descriptor::Wpkh(_)
-            | Descriptor::ShWpkh(_)
-                if utxo.is_some()
-                    && self.script_pubkey() == utxo.as_ref().unwrap().script_pubkey =>
-            {
-                Some(self.clone())
-            }
-            Descriptor::Bare(ms) | Descriptor::Sh(ms)
-                if psbt_input.redeem_script.is_some()
-                    && &ms.encode() == psbt_input.redeem_script.as_ref().unwrap() =>
-            {
-                Some(self.clone())
-            }
-            Descriptor::Wsh(ms) | Descriptor::ShWsh(ms)
-                if psbt_input.witness_script.is_some()
-                    && &ms.encode() == psbt_input.witness_script.as_ref().unwrap() =>
-            {
-                Some(self.clone())
-            }
-            _ => None,
-        }
-    }
-}
-
-#[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Eq, Ord, Default)]
-struct DummyKey();
-
-impl fmt::Display for DummyKey {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "DummyKey")
-    }
-}
-
-impl std::str::FromStr for DummyKey {
-    type Err = ();
-
-    fn from_str(_: &str) -> Result<Self, Self::Err> {
-        Ok(DummyKey::default())
-    }
-}
-
-impl miniscript::MiniscriptKey for DummyKey {
-    type Hash = DummyKey;
-
-    fn to_pubkeyhash(&self) -> DummyKey {
-        DummyKey::default()
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use std::str::FromStr;
-
-    use bitcoin::consensus::encode::deserialize;
-    use bitcoin::hashes::hex::FromHex;
-    use bitcoin::util::psbt;
-
-    use super::*;
-    use crate::psbt::PSBTUtils;
-
-    #[test]
-    fn test_derive_from_psbt_input_wpkh_wif() {
-        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
-            "wpkh(02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737)",
-        )
-        .unwrap();
-        let psbt: psbt::PartiallySignedTransaction = deserialize(
-            &Vec::<u8>::from_hex(
-                "70736274ff010052010000000162307be8e431fbaff807cdf9cdc3fde44d7402\
-                 11bc8342c31ffd6ec11fe35bcc0100000000ffffffff01328601000000000016\
-                 001493ce48570b55c42c2af816aeaba06cfee1224fae000000000001011fa086\
-                 01000000000016001493ce48570b55c42c2af816aeaba06cfee1224fae010304\
-                 010000000000",
-            )
-            .unwrap(),
-        )
-        .unwrap();
-
-        assert!(descriptor
-            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0))
-            .is_some());
-    }
-
-    #[test]
-    fn test_derive_from_psbt_input_pkh_tpub() {
-        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
-            "pkh([0f056943/44h/0h/0h]tpubDDpWvmUrPZrhSPmUzCMBHffvC3HyMAPnWDSAQNBTnj1iZeJa7BZQEttFiP4DS4GCcXQHezdXhn86Hj6LHX5EDstXPWrMaSneRWM8yUf6NFd/10/*)",
-        )
-        .unwrap();
-        let psbt: psbt::PartiallySignedTransaction = deserialize(
-            &Vec::<u8>::from_hex(
-                "70736274ff010053010000000145843b86be54a3cd8c9e38444e1162676c00df\
-                 e7964122a70df491ea12fd67090100000000ffffffff01c19598000000000017\
-                 a91432bb94283282f72b2e034709e348c44d5a4db0ef8700000000000100f902\
-                 0000000001010167e99c0eb67640f3a1b6805f2d8be8238c947f8aaf49eb0a9c\
-                 bee6a42c984200000000171600142b29a22019cca05b9c2b2d283a4c4489e1cf\
-                 9f8ffeffffff02a01dced06100000017a914e2abf033cadbd74f0f4c74946201\
-                 decd20d5c43c8780969800000000001976a9148b0fce5fb1264e599a65387313\
-                 3c95478b902eb288ac02473044022015d9211576163fa5b001e84dfa3d44efd9\
-                 86b8f3a0d3d2174369288b2b750906022048dacc0e5d73ae42512fd2b97e2071\
-                 a8d0bce443b390b1fe0b8128fe70ec919e01210232dad1c5a67dcb0116d407e2\
-                 52584228ab7ec00e8b9779d0c3ffe8114fc1a7d2c80600000103040100000022\
-                 0603433b83583f8c4879b329dd08bbc7da935e4cc02f637ff746e05f0466ffb2\
-                 a6a2180f0569432c00008000000080000000800a000000000000000000",
-            )
-            .unwrap(),
-        )
-        .unwrap();
-
-        assert!(descriptor
-            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0))
-            .is_some());
-    }
-
-    #[test]
-    fn test_derive_from_psbt_input_wsh() {
-        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
-            "wsh(and_v(v:pk(03b6633fef2397a0a9de9d7b6f23aef8368a6e362b0581f0f0af70d5ecfd254b14),older(6)))",
-        )
-        .unwrap();
-        let psbt: psbt::PartiallySignedTransaction = deserialize(
-            &Vec::<u8>::from_hex(
-                "70736274ff01005302000000011c8116eea34408ab6529223c9a176606742207\
-                 67a1ff1d46a6e3c4a88243ea6e01000000000600000001109698000000000017\
-                 a914ad105f61102e0d01d7af40d06d6a5c3ae2f7fde387000000000001012b80\
-                 969800000000002200203ca72f106a72234754890ca7640c43f65d2174e44d33\
-                 336030f9059345091044010304010000000105252103b6633fef2397a0a9de9d\
-                 7b6f23aef8368a6e362b0581f0f0af70d5ecfd254b14ad56b20000",
-            )
-            .unwrap(),
-        )
-        .unwrap();
-
-        assert!(descriptor
-            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0))
-            .is_some());
-    }
-
-    #[test]
-    fn test_derive_from_psbt_input_sh() {
-        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
-            "sh(and_v(v:pk(021403881a5587297818fcaf17d239cefca22fce84a45b3b1d23e836c4af671dbb),after(630000)))",
-        )
-        .unwrap();
-        let psbt: psbt::PartiallySignedTransaction = deserialize(
-            &Vec::<u8>::from_hex(
-                "70736274ff0100530100000001bc8c13df445dfadcc42afa6dc841f85d22b01d\
-                 a6270ebf981740f4b7b1d800390000000000feffffff01ba9598000000000017\
-                 a91457b148ba4d3e5fa8608a8657875124e3d1c9390887f09c0900000100e002\
-                 0000000001016ba1bbe05cc93574a0d611ec7d93ad0ab6685b28d0cd80e8a82d\
-                 debb326643c90100000000feffffff02809698000000000017a914d9a6e8c455\
-                 8e16c8253afe53ce37ad61cf4c38c487403504cf6100000017a9144044fb6e0b\
-                 757dfc1b34886b6a95aef4d3db137e870247304402202a9b72d939bcde8ba2a1\
-                 e0980597e47af4f5c152a78499143c3d0a78ac2286a602207a45b1df9e93b8c9\
-                 6f09f5c025fe3e413ca4b905fe65ee55d32a3276439a9b8f012102dc1fcc2636\
-                 4da1aa718f03d8d9bd6f2ff410ed2cf1245a168aa3bcc995ac18e0a806000001\
-                 03040100000001042821021403881a5587297818fcaf17d239cefca22fce84a4\
-                 5b3b1d23e836c4af671dbbad03f09c09b10000",
-            )
-            .unwrap(),
-        )
-        .unwrap();
-
-        assert!(descriptor
-            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0))
-            .is_some());
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/descriptor/policy.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/descriptor/policy.rs.html deleted file mode 100644 index 55668f53af..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/descriptor/policy.rs.html +++ /dev/null @@ -1,1593 +0,0 @@ -policy.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-397
-398
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-409
-410
-411
-412
-413
-414
-415
-416
-417
-418
-419
-420
-421
-422
-423
-424
-425
-426
-427
-428
-429
-430
-431
-432
-433
-434
-435
-436
-437
-438
-439
-440
-441
-442
-443
-444
-445
-446
-447
-448
-449
-450
-451
-452
-453
-454
-455
-456
-457
-458
-459
-460
-461
-462
-463
-464
-465
-466
-467
-468
-469
-470
-471
-472
-473
-474
-475
-476
-477
-478
-479
-480
-481
-482
-483
-484
-485
-486
-487
-488
-489
-490
-491
-492
-493
-494
-495
-496
-497
-498
-499
-500
-501
-502
-503
-504
-505
-506
-507
-508
-509
-510
-511
-512
-513
-514
-515
-516
-517
-518
-519
-520
-521
-522
-523
-524
-525
-526
-527
-528
-529
-530
-531
-532
-533
-534
-535
-536
-537
-538
-539
-540
-541
-542
-543
-544
-545
-546
-547
-548
-549
-550
-551
-552
-553
-554
-555
-556
-557
-558
-559
-560
-561
-562
-563
-564
-565
-566
-567
-568
-569
-570
-571
-572
-573
-574
-575
-576
-577
-578
-579
-580
-581
-582
-583
-584
-585
-586
-587
-588
-589
-590
-591
-592
-593
-594
-595
-596
-597
-598
-599
-600
-601
-602
-603
-604
-605
-606
-607
-608
-609
-610
-611
-612
-613
-614
-615
-616
-617
-618
-619
-620
-621
-622
-623
-624
-625
-626
-627
-628
-629
-630
-631
-632
-633
-634
-635
-636
-637
-638
-639
-640
-641
-642
-643
-644
-645
-646
-647
-648
-649
-650
-651
-652
-653
-654
-655
-656
-657
-658
-659
-660
-661
-662
-663
-664
-665
-666
-667
-668
-669
-670
-671
-672
-673
-674
-675
-676
-677
-678
-679
-680
-681
-682
-683
-684
-685
-686
-687
-688
-689
-690
-691
-692
-693
-694
-695
-696
-697
-698
-699
-700
-701
-702
-703
-704
-705
-706
-707
-708
-709
-710
-711
-712
-713
-714
-715
-716
-717
-718
-719
-720
-721
-722
-723
-724
-725
-726
-727
-728
-729
-730
-731
-732
-733
-734
-735
-736
-737
-738
-739
-740
-741
-742
-743
-744
-745
-746
-747
-748
-749
-750
-751
-752
-753
-754
-755
-756
-757
-758
-759
-760
-761
-762
-763
-764
-765
-766
-767
-768
-769
-770
-771
-772
-773
-774
-775
-776
-777
-778
-779
-780
-781
-782
-783
-784
-785
-786
-787
-788
-789
-790
-791
-792
-793
-794
-795
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Descriptor policy
-//!
-//! This module implements the logic to extract and represent the spending policies of a descriptor
-//! in a more human-readable format.
-//!
-//! ## Example
-//!
-//! ```
-//! # use std::sync::Arc;
-//! # use magical::descriptor::*;
-//! let desc = "wsh(and_v(v:pk(cV3oCth6zxZ1UVsHLnGothsWNsaoxRhC6aeNi5VbSdFpwUkgkEci),or_d(pk(cVMTy7uebJgvFaSBwcgvwk8qn8xSLc97dKow4MBetjrrahZoimm2),older(12960))))";
-//!
-//! let (extended_desc, key_map) = ExtendedDescriptor::parse_secret(desc)?;
-//! println!("{:?}", extended_desc);
-//!
-//! let signers = Arc::new(key_map.into());
-//! let policy = extended_desc.extract_policy(signers)?;
-//! println!("policy: {}", serde_json::to_string(&policy)?);
-//! # Ok::<(), magical::Error>(())
-//! ```
-
-use std::cmp::max;
-use std::collections::{BTreeMap, HashSet, VecDeque};
-use std::fmt;
-use std::sync::Arc;
-
-use serde::ser::SerializeMap;
-use serde::{Serialize, Serializer};
-
-use bitcoin::hashes::*;
-use bitcoin::util::bip32::Fingerprint;
-use bitcoin::PublicKey;
-
-use miniscript::descriptor::DescriptorPublicKey;
-use miniscript::{Descriptor, Miniscript, MiniscriptKey, ScriptContext, Terminal};
-
-#[allow(unused_imports)]
-use log::{debug, error, info, trace};
-
-use crate::descriptor::ExtractPolicy;
-use crate::wallet::signer::{SignerId, SignersContainer};
-
-use super::checksum::get_checksum;
-use super::error::Error;
-use super::XKeyUtils;
-
-/// Raw public key or extended key fingerprint
-#[derive(Debug, Clone, Default, Serialize)]
-pub struct PKOrF {
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pubkey: Option<PublicKey>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pubkey_hash: Option<hash160::Hash>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    fingerprint: Option<Fingerprint>,
-}
-
-impl PKOrF {
-    fn from_key(k: &DescriptorPublicKey) -> Self {
-        match k {
-            DescriptorPublicKey::PubKey(pubkey) => PKOrF {
-                pubkey: Some(*pubkey),
-                ..Default::default()
-            },
-            DescriptorPublicKey::XPub(xpub) => PKOrF {
-                fingerprint: Some(xpub.root_fingerprint()),
-                ..Default::default()
-            },
-        }
-    }
-
-    fn from_key_hash(k: hash160::Hash) -> Self {
-        PKOrF {
-            pubkey_hash: Some(k),
-            ..Default::default()
-        }
-    }
-}
-
-/// An item that need to be satisfied
-#[derive(Debug, Clone, Serialize)]
-#[serde(tag = "type", rename_all = "UPPERCASE")]
-pub enum SatisfiableItem {
-    // Leaves
-    Signature(PKOrF),
-    SignatureKey(PKOrF),
-    SHA256Preimage {
-        hash: sha256::Hash,
-    },
-    HASH256Preimage {
-        hash: sha256d::Hash,
-    },
-    RIPEMD160Preimage {
-        hash: ripemd160::Hash,
-    },
-    HASH160Preimage {
-        hash: hash160::Hash,
-    },
-    AbsoluteTimelock {
-        value: u32,
-    },
-    RelativeTimelock {
-        value: u32,
-    },
-
-    // Complex item
-    Thresh {
-        items: Vec<Policy>,
-        threshold: usize,
-    },
-    Multisig {
-        keys: Vec<PKOrF>,
-        threshold: usize,
-    },
-}
-
-impl SatisfiableItem {
-    pub fn is_leaf(&self) -> bool {
-        match self {
-            SatisfiableItem::Thresh {
-                items: _,
-                threshold: _,
-            } => false,
-            _ => true,
-        }
-    }
-
-    pub fn id(&self) -> String {
-        get_checksum(&serde_json::to_string(self).expect("Failed to serialize a SatisfiableItem"))
-            .expect("Failed to compute a SatisfiableItem id")
-    }
-}
-
-fn combinations(vec: &Vec<usize>, size: usize) -> Vec<Vec<usize>> {
-    assert!(vec.len() >= size);
-
-    let mut answer = Vec::new();
-
-    let mut queue = VecDeque::new();
-    for (index, val) in vec.iter().enumerate() {
-        let mut new_vec = Vec::with_capacity(size);
-        new_vec.push(*val);
-        queue.push_back((index, new_vec));
-    }
-
-    while let Some((index, vals)) = queue.pop_front() {
-        if vals.len() >= size {
-            answer.push(vals);
-        } else {
-            for (new_index, val) in vec.iter().skip(index + 1).enumerate() {
-                let mut cloned = vals.clone();
-                cloned.push(*val);
-                queue.push_front((new_index, cloned));
-            }
-        }
-    }
-
-    answer
-}
-
-fn mix<T: Clone>(vec: Vec<Vec<T>>) -> Vec<Vec<T>> {
-    if vec.is_empty() || vec.iter().any(Vec::is_empty) {
-        return vec![];
-    }
-
-    let mut answer = Vec::new();
-    let size = vec.len();
-
-    let mut queue = VecDeque::new();
-    for i in &vec[0] {
-        let mut new_vec = Vec::with_capacity(size);
-        new_vec.push(i.clone());
-        queue.push_back(new_vec);
-    }
-
-    while let Some(vals) = queue.pop_front() {
-        if vals.len() >= size {
-            answer.push(vals);
-        } else {
-            let level = vals.len();
-            for i in &vec[level] {
-                let mut cloned = vals.clone();
-                cloned.push(i.clone());
-                queue.push_front(cloned);
-            }
-        }
-    }
-
-    answer
-}
-
-pub type ConditionMap = BTreeMap<usize, HashSet<Condition>>;
-pub type FoldedConditionMap = BTreeMap<Vec<usize>, HashSet<Condition>>;
-
-fn serialize_folded_cond_map<S>(
-    input_map: &FoldedConditionMap,
-    serializer: S,
-) -> Result<S::Ok, S::Error>
-where
-    S: Serializer,
-{
-    let mut map = serializer.serialize_map(Some(input_map.len()))?;
-    for (k, v) in input_map {
-        let k_string = format!("{:?}", k);
-        map.serialize_entry(&k_string, v)?;
-    }
-    map.end()
-}
-
-/// Represent if and how much a policy item is satisfied by the wallet's descriptor
-#[derive(Debug, Clone, Serialize)]
-#[serde(tag = "type", rename_all = "UPPERCASE")]
-pub enum Satisfaction {
-    /// Only a partial satisfaction of some kind of threshold policy
-    Partial {
-        /// Total number of items
-        n: usize,
-        /// Threshold
-        m: usize,
-        /// The items that can be satisfied by the descriptor
-        items: Vec<usize>,
-        #[serde(skip_serializing_if = "BTreeMap::is_empty")]
-        /// Extra conditions that also need to be satisfied
-        conditions: ConditionMap,
-    },
-    /// Can reach the threshold of some kind of threshold policy
-    PartialComplete {
-        /// Total number of items
-        n: usize,
-        /// Threshold
-        m: usize,
-        /// The items that can be satisfied by the descriptor
-        items: Vec<usize>,
-        #[serde(
-            serialize_with = "serialize_folded_cond_map",
-            skip_serializing_if = "BTreeMap::is_empty"
-        )]
-        /// Extra conditions that also need to be satisfied
-        conditions: FoldedConditionMap,
-    },
-
-    /// Can satisfy the policy item
-    Complete {
-        /// Extra conditions that also need to be satisfied
-        condition: Condition,
-    },
-    /// Cannot satisfy or contribute to the policy item
-    None,
-}
-
-impl Satisfaction {
-    pub fn is_leaf(&self) -> bool {
-        match self {
-            Satisfaction::None | Satisfaction::Complete { .. } => true,
-            Satisfaction::PartialComplete { .. } | Satisfaction::Partial { .. } => false,
-        }
-    }
-
-    // add `inner` as one of self's partial items. this only makes sense on partials
-    fn add(&mut self, inner: &Satisfaction, inner_index: usize) -> Result<(), PolicyError> {
-        match self {
-            Satisfaction::None | Satisfaction::Complete { .. } => Err(PolicyError::AddOnLeaf),
-            Satisfaction::PartialComplete { .. } => Err(PolicyError::AddOnPartialComplete),
-            Satisfaction::Partial {
-                n,
-                ref mut conditions,
-                ref mut items,
-                ..
-            } => {
-                if inner_index >= *n || items.contains(&inner_index) {
-                    return Err(PolicyError::IndexOutOfRange(inner_index));
-                }
-
-                match inner {
-                    // not relevant if not completed yet
-                    Satisfaction::None | Satisfaction::Partial { .. } => return Ok(()),
-                    Satisfaction::Complete { condition } => {
-                        items.push(inner_index);
-                        conditions.insert(inner_index, vec![*condition].into_iter().collect());
-                    }
-                    Satisfaction::PartialComplete {
-                        conditions: other_conditions,
-                        ..
-                    } => {
-                        items.push(inner_index);
-                        let conditions_set = other_conditions
-                            .values()
-                            .fold(HashSet::new(), |set, i| set.union(&i).cloned().collect());
-                        conditions.insert(inner_index, conditions_set);
-                    }
-                }
-
-                Ok(())
-            }
-        }
-    }
-
-    fn finalize(&mut self) -> Result<(), PolicyError> {
-        // if partial try to bump it to a partialcomplete
-        if let Satisfaction::Partial {
-            n,
-            m,
-            items,
-            conditions,
-        } = self
-        {
-            if items.len() >= *m {
-                let mut map = BTreeMap::new();
-                let indexes = combinations(items, *m);
-                // `indexes` at this point is a Vec<Vec<usize>>, with the "n choose k" of items (m of n)
-                indexes
-                    .into_iter()
-                    // .inspect(|x| println!("--- orig --- {:?}", x))
-                    // we map each of the combinations of elements into a tuple of ([choosen items], [conditions]). unfortunately, those items have potentially more than one
-                    // condition (think about ORs), so we also use `mix` to expand those, i.e. [[0], [1, 2]] becomes [[0, 1], [0, 2]]. This is necessary to make sure that we
-                    // consider every possibile options and check whether or not they are compatible.
-                    .map(|i_vec| {
-                        mix(i_vec
-                            .iter()
-                            .map(|i| {
-                                conditions
-                                    .get(i)
-                                    .and_then(|set| Some(set.clone().into_iter().collect()))
-                                    .unwrap_or(vec![])
-                            })
-                            .collect())
-                        .into_iter()
-                        .map(|x| (i_vec.clone(), x))
-                        .collect::<Vec<(Vec<usize>, Vec<Condition>)>>()
-                    })
-                    // .inspect(|x: &Vec<(Vec<usize>, Vec<Condition>)>| println!("fetch {:?}", x))
-                    // since the previous step can turn one item of the iterator into multiple ones, we call flatten to expand them out
-                    .flatten()
-                    // .inspect(|x| println!("flat {:?}", x))
-                    // try to fold all the conditions for this specific combination of indexes/options. if they are not compatibile, try_fold will be Err
-                    .map(|(key, val)| {
-                        (
-                            key,
-                            val.into_iter()
-                                .try_fold(Condition::default(), |acc, v| acc.merge(&v)),
-                        )
-                    })
-                    // .inspect(|x| println!("try_fold {:?}", x))
-                    // filter out all the incompatible combinations
-                    .filter(|(_, val)| val.is_ok())
-                    // .inspect(|x| println!("filter {:?}", x))
-                    // push them into the map
-                    .for_each(|(key, val)| {
-                        map.entry(key)
-                            .or_insert_with(HashSet::new)
-                            .insert(val.unwrap());
-                    });
-                // TODO: if the map is empty, the conditions are not compatible, return an error?
-                *self = Satisfaction::PartialComplete {
-                    n: *n,
-                    m: *m,
-                    items: items.clone(),
-                    conditions: map,
-                };
-            }
-        }
-
-        Ok(())
-    }
-}
-
-impl From<bool> for Satisfaction {
-    fn from(other: bool) -> Self {
-        if other {
-            Satisfaction::Complete {
-                condition: Default::default(),
-            }
-        } else {
-            Satisfaction::None
-        }
-    }
-}
-
-/// Descriptor spending policy
-#[derive(Debug, Clone, Serialize)]
-pub struct Policy {
-    /// Identifier for this policy node
-    pub id: String,
-
-    /// Type of this policy node
-    #[serde(flatten)]
-    pub item: SatisfiableItem,
-    /// How a much given PSBT already satisfies this polcy node **(currently unused)**
-    pub satisfaction: Satisfaction,
-    /// How the wallet's descriptor can satisfy this policy node
-    pub contribution: Satisfaction,
-}
-
-/// An extra condition that must be satisfied but that is out of control of the user
-#[derive(Hash, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default, Serialize)]
-pub struct Condition {
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub csv: Option<u32>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub timelock: Option<u32>,
-}
-
-impl Condition {
-    fn merge_timelock(a: u32, b: u32) -> Result<u32, PolicyError> {
-        const BLOCKS_TIMELOCK_THRESHOLD: u32 = 500000000;
-
-        if (a < BLOCKS_TIMELOCK_THRESHOLD) != (b < BLOCKS_TIMELOCK_THRESHOLD) {
-            Err(PolicyError::MixedTimelockUnits)
-        } else {
-            Ok(max(a, b))
-        }
-    }
-
-    fn merge(mut self, other: &Condition) -> Result<Self, PolicyError> {
-        match (self.csv, other.csv) {
-            (Some(a), Some(b)) => self.csv = Some(Self::merge_timelock(a, b)?),
-            (None, any) => self.csv = any,
-            _ => {}
-        }
-
-        match (self.timelock, other.timelock) {
-            (Some(a), Some(b)) => self.timelock = Some(Self::merge_timelock(a, b)?),
-            (None, any) => self.timelock = any,
-            _ => {}
-        }
-
-        Ok(self)
-    }
-
-    pub fn is_null(&self) -> bool {
-        self.csv.is_none() && self.timelock.is_none()
-    }
-}
-
-/// Errors that can happen while extracting and manipulating policies
-#[derive(Debug)]
-pub enum PolicyError {
-    NotEnoughItemsSelected(String),
-    TooManyItemsSelected(String),
-    IndexOutOfRange(usize),
-    AddOnLeaf,
-    AddOnPartialComplete,
-    MixedTimelockUnits,
-    IncompatibleConditions,
-}
-
-impl fmt::Display for PolicyError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}", self)
-    }
-}
-
-impl std::error::Error for PolicyError {}
-
-impl Policy {
-    fn new(item: SatisfiableItem) -> Self {
-        Policy {
-            id: item.id(),
-            item,
-            satisfaction: Satisfaction::None,
-            contribution: Satisfaction::None,
-        }
-    }
-
-    fn make_and(a: Option<Policy>, b: Option<Policy>) -> Result<Option<Policy>, PolicyError> {
-        match (a, b) {
-            (None, None) => Ok(None),
-            (Some(x), None) | (None, Some(x)) => Ok(Some(x)),
-            (Some(a), Some(b)) => Self::make_thresh(vec![a, b], 2),
-        }
-    }
-
-    fn make_or(a: Option<Policy>, b: Option<Policy>) -> Result<Option<Policy>, PolicyError> {
-        match (a, b) {
-            (None, None) => Ok(None),
-            (Some(x), None) | (None, Some(x)) => Ok(Some(x)),
-            (Some(a), Some(b)) => Self::make_thresh(vec![a, b], 1),
-        }
-    }
-
-    fn make_thresh(items: Vec<Policy>, threshold: usize) -> Result<Option<Policy>, PolicyError> {
-        if threshold == 0 {
-            return Ok(None);
-        }
-
-        let mut contribution = Satisfaction::Partial {
-            n: items.len(),
-            m: threshold,
-            items: vec![],
-            conditions: Default::default(),
-        };
-        for (index, item) in items.iter().enumerate() {
-            contribution.add(&item.contribution, index)?;
-        }
-        contribution.finalize()?;
-
-        let mut policy: Policy = SatisfiableItem::Thresh { items, threshold }.into();
-        policy.contribution = contribution;
-
-        Ok(Some(policy))
-    }
-
-    fn make_multisig(
-        keys: &Vec<DescriptorPublicKey>,
-        signers: Arc<SignersContainer<DescriptorPublicKey>>,
-        threshold: usize,
-    ) -> Result<Option<Policy>, PolicyError> {
-        if threshold == 0 {
-            return Ok(None);
-        }
-
-        let parsed_keys = keys.iter().map(|k| PKOrF::from_key(k)).collect();
-
-        let mut contribution = Satisfaction::Partial {
-            n: keys.len(),
-            m: threshold,
-            items: vec![],
-            conditions: Default::default(),
-        };
-        for (index, key) in keys.iter().enumerate() {
-            if let Some(_) = signers.find(signer_id(key)) {
-                contribution.add(
-                    &Satisfaction::Complete {
-                        condition: Default::default(),
-                    },
-                    index,
-                )?;
-            }
-        }
-        contribution.finalize()?;
-
-        let mut policy: Policy = SatisfiableItem::Multisig {
-            keys: parsed_keys,
-            threshold,
-        }
-        .into();
-        policy.contribution = contribution;
-
-        Ok(Some(policy))
-    }
-
-    /// Return whether or not a specific path in the policy tree is required to unambiguously
-    /// create a transaction
-    ///
-    /// What this means is that for some spending policies the user should select which paths in
-    /// the tree it intends to satisfy while signing, because the transaction must be created differently based
-    /// on that.
-    pub fn requires_path(&self) -> bool {
-        self.get_condition(&BTreeMap::new()).is_err()
-    }
-
-    /// Return the conditions that are set by the spending policy for a given path in the
-    /// policy tree
-    pub fn get_condition(
-        &self,
-        path: &BTreeMap<String, Vec<usize>>,
-    ) -> Result<Condition, PolicyError> {
-        // if items.len() == threshold, selected can be omitted and we take all of them by default
-        let default = match &self.item {
-            SatisfiableItem::Thresh { items, threshold } if items.len() == *threshold => {
-                (0..*threshold).into_iter().collect()
-            }
-            _ => vec![],
-        };
-        let selected = match path.get(&self.id) {
-            _ if !default.is_empty() => &default,
-            Some(arr) => arr,
-            _ => &default,
-        };
-
-        match &self.item {
-            SatisfiableItem::Thresh { items, threshold } => {
-                let mapped_req = items
-                    .iter()
-                    .map(|i| i.get_condition(path))
-                    .collect::<Result<Vec<_>, _>>()?;
-
-                // if all the requirements are null we don't care about `selected` because there
-                // are no requirements
-                if mapped_req.iter().all(Condition::is_null) {
-                    return Ok(Condition::default());
-                }
-
-                // if we have something, make sure we have enough items. note that the user can set
-                // an empty value for this step in case of n-of-n, because `selected` is set to all
-                // the elements above
-                if selected.len() < *threshold {
-                    return Err(PolicyError::NotEnoughItemsSelected(self.id.clone()));
-                } else if selected.len() > *threshold {
-                    return Err(PolicyError::TooManyItemsSelected(self.id.clone()));
-                }
-
-                // check the selected items, see if there are conflicting requirements
-                let mut requirements = Condition::default();
-                for item_index in selected {
-                    requirements = requirements.merge(
-                        mapped_req
-                            .get(*item_index)
-                            .ok_or(PolicyError::IndexOutOfRange(*item_index))?,
-                    )?;
-                }
-
-                Ok(requirements)
-            }
-            _ if !selected.is_empty() => Err(PolicyError::TooManyItemsSelected(self.id.clone())),
-            SatisfiableItem::AbsoluteTimelock { value } => Ok(Condition {
-                csv: None,
-                timelock: Some(*value),
-            }),
-            SatisfiableItem::RelativeTimelock { value } => Ok(Condition {
-                csv: Some(*value),
-                timelock: None,
-            }),
-            _ => Ok(Condition::default()),
-        }
-    }
-}
-
-impl From<SatisfiableItem> for Policy {
-    fn from(other: SatisfiableItem) -> Self {
-        Self::new(other)
-    }
-}
-
-fn signer_id(key: &DescriptorPublicKey) -> SignerId<DescriptorPublicKey> {
-    match key {
-        DescriptorPublicKey::PubKey(pubkey) => pubkey.to_pubkeyhash().into(),
-        DescriptorPublicKey::XPub(xpub) => xpub.root_fingerprint().into(),
-    }
-}
-
-fn signature(
-    key: &DescriptorPublicKey,
-    signers: Arc<SignersContainer<DescriptorPublicKey>>,
-) -> Policy {
-    let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key(key)).into();
-
-    policy.contribution = if signers.find(signer_id(key)).is_some() {
-        Satisfaction::Complete {
-            condition: Default::default(),
-        }
-    } else {
-        Satisfaction::None
-    };
-
-    policy
-}
-
-fn signature_key(
-    key_hash: &<DescriptorPublicKey as MiniscriptKey>::Hash,
-    signers: Arc<SignersContainer<DescriptorPublicKey>>,
-) -> Policy {
-    let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key_hash(*key_hash)).into();
-
-    if let Some(_) = signers.find(SignerId::PkHash(*key_hash)) {
-        policy.contribution = Satisfaction::Complete {
-            condition: Default::default(),
-        }
-    }
-
-    policy
-}
-
-impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx> {
-    fn extract_policy(
-        &self,
-        signers: Arc<SignersContainer<DescriptorPublicKey>>,
-    ) -> Result<Option<Policy>, Error> {
-        Ok(match &self.node {
-            // Leaves
-            Terminal::True | Terminal::False => None,
-            Terminal::PkK(pubkey) => Some(signature(pubkey, Arc::clone(&signers))),
-            Terminal::PkH(pubkey_hash) => Some(signature_key(pubkey_hash, Arc::clone(&signers))),
-            Terminal::After(value) => {
-                let mut policy: Policy = SatisfiableItem::AbsoluteTimelock { value: *value }.into();
-                policy.contribution = Satisfaction::Complete {
-                    condition: Condition {
-                        timelock: Some(*value),
-                        csv: None,
-                    },
-                };
-
-                Some(policy)
-            }
-            Terminal::Older(value) => {
-                let mut policy: Policy = SatisfiableItem::RelativeTimelock { value: *value }.into();
-                policy.contribution = Satisfaction::Complete {
-                    condition: Condition {
-                        timelock: None,
-                        csv: Some(*value),
-                    },
-                };
-
-                Some(policy)
-            }
-            Terminal::Sha256(hash) => Some(SatisfiableItem::SHA256Preimage { hash: *hash }.into()),
-            Terminal::Hash256(hash) => {
-                Some(SatisfiableItem::HASH256Preimage { hash: *hash }.into())
-            }
-            Terminal::Ripemd160(hash) => {
-                Some(SatisfiableItem::RIPEMD160Preimage { hash: *hash }.into())
-            }
-            Terminal::Hash160(hash) => {
-                Some(SatisfiableItem::HASH160Preimage { hash: *hash }.into())
-            }
-            Terminal::Multi(k, pks) => Policy::make_multisig(pks, Arc::clone(&signers), *k)?,
-            // Identities
-            Terminal::Alt(inner)
-            | Terminal::Swap(inner)
-            | Terminal::Check(inner)
-            | Terminal::DupIf(inner)
-            | Terminal::Verify(inner)
-            | Terminal::NonZero(inner)
-            | Terminal::ZeroNotEqual(inner) => inner.extract_policy(Arc::clone(&signers))?,
-            // Complex policies
-            Terminal::AndV(a, b) | Terminal::AndB(a, b) => Policy::make_and(
-                a.extract_policy(Arc::clone(&signers))?,
-                b.extract_policy(Arc::clone(&signers))?,
-            )?,
-            Terminal::AndOr(x, y, z) => Policy::make_or(
-                Policy::make_and(
-                    x.extract_policy(Arc::clone(&signers))?,
-                    y.extract_policy(Arc::clone(&signers))?,
-                )?,
-                z.extract_policy(Arc::clone(&signers))?,
-            )?,
-            Terminal::OrB(a, b)
-            | Terminal::OrD(a, b)
-            | Terminal::OrC(a, b)
-            | Terminal::OrI(a, b) => Policy::make_or(
-                a.extract_policy(Arc::clone(&signers))?,
-                b.extract_policy(Arc::clone(&signers))?,
-            )?,
-            Terminal::Thresh(k, nodes) => {
-                let mut threshold = *k;
-                let mapped: Vec<_> = nodes
-                    .iter()
-                    .map(|n| n.extract_policy(Arc::clone(&signers)))
-                    .collect::<Result<Vec<_>, _>>()?
-                    .into_iter()
-                    .filter_map(|x| x)
-                    .collect();
-
-                if mapped.len() < nodes.len() {
-                    threshold = match threshold.checked_sub(nodes.len() - mapped.len()) {
-                        None => return Ok(None),
-                        Some(x) => x,
-                    };
-                }
-
-                Policy::make_thresh(mapped, threshold)?
-            }
-        })
-    }
-}
-
-impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
-    fn extract_policy(
-        &self,
-        signers: Arc<SignersContainer<DescriptorPublicKey>>,
-    ) -> Result<Option<Policy>, Error> {
-        match self {
-            Descriptor::Pk(pubkey)
-            | Descriptor::Pkh(pubkey)
-            | Descriptor::Wpkh(pubkey)
-            | Descriptor::ShWpkh(pubkey) => Ok(Some(signature(pubkey, signers))),
-            Descriptor::Bare(inner) | Descriptor::Sh(inner) => Ok(inner.extract_policy(signers)?),
-            Descriptor::Wsh(inner) | Descriptor::ShWsh(inner) => Ok(inner.extract_policy(signers)?),
-        }
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/error.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/error.rs.html deleted file mode 100644 index 8d8316a7c5..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/error.rs.html +++ /dev/null @@ -1,283 +0,0 @@ -error.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-use std::fmt;
-
-use bitcoin::{Address, OutPoint};
-
-/// Errors that can be thrown by the [`Wallet`](crate::wallet::Wallet)
-#[derive(Debug)]
-pub enum Error {
-    KeyMismatch(bitcoin::secp256k1::PublicKey, bitcoin::secp256k1::PublicKey),
-    MissingInputUTXO(usize),
-    InvalidU32Bytes(Vec<u8>),
-    Generic(String),
-    ScriptDoesntHaveAddressForm,
-    SendAllMultipleOutputs,
-    NoAddressees,
-    OutputBelowDustLimit(usize),
-    InsufficientFunds,
-    InvalidAddressNetwork(Address),
-    UnknownUTXO,
-    DifferentTransactions,
-    TransactionNotFound,
-    TransactionConfirmed,
-    IrreplaceableTransaction,
-    FeeRateTooLow {
-        required: crate::types::FeeRate,
-    },
-
-    ChecksumMismatch,
-    DifferentDescriptorStructure,
-
-    SpendingPolicyRequired,
-    InvalidPolicyPathError(crate::descriptor::policy::PolicyError),
-
-    Signer(crate::wallet::signer::SignerError),
-
-    // Blockchain interface errors
-    Uncapable(crate::blockchain::Capability),
-    OfflineClient,
-    InvalidProgressValue(f32),
-    ProgressUpdateError,
-    MissingCachedAddresses,
-    InvalidOutpoint(OutPoint),
-
-    Descriptor(crate::descriptor::error::Error),
-    AddressValidator(crate::wallet::address_validator::AddressValidatorError),
-
-    Encode(bitcoin::consensus::encode::Error),
-    Miniscript(miniscript::Error),
-    BIP32(bitcoin::util::bip32::Error),
-    Secp256k1(bitcoin::secp256k1::Error),
-    JSON(serde_json::Error),
-    Hex(bitcoin::hashes::hex::Error),
-    PSBT(bitcoin::util::psbt::Error),
-
-    #[cfg(feature = "electrum")]
-    Electrum(electrum_client::Error),
-    #[cfg(feature = "esplora")]
-    Esplora(crate::blockchain::esplora::EsploraError),
-    #[cfg(feature = "compact_filters")]
-    CompactFilters(crate::blockchain::compact_filters::CompactFiltersError),
-    #[cfg(feature = "key-value-db")]
-    Sled(sled::Error),
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}", self)
-    }
-}
-
-impl std::error::Error for Error {}
-
-macro_rules! impl_error {
-    ( $from:ty, $to:ident ) => {
-        impl std::convert::From<$from> for Error {
-            fn from(err: $from) -> Self {
-                Error::$to(err)
-            }
-        }
-    };
-}
-
-impl_error!(crate::descriptor::error::Error, Descriptor);
-impl_error!(
-    crate::wallet::address_validator::AddressValidatorError,
-    AddressValidator
-);
-impl_error!(
-    crate::descriptor::policy::PolicyError,
-    InvalidPolicyPathError
-);
-impl_error!(crate::wallet::signer::SignerError, Signer);
-
-impl_error!(bitcoin::consensus::encode::Error, Encode);
-impl_error!(miniscript::Error, Miniscript);
-impl_error!(bitcoin::util::bip32::Error, BIP32);
-impl_error!(bitcoin::secp256k1::Error, Secp256k1);
-impl_error!(serde_json::Error, JSON);
-impl_error!(bitcoin::hashes::hex::Error, Hex);
-impl_error!(bitcoin::util::psbt::Error, PSBT);
-
-#[cfg(feature = "electrum")]
-impl_error!(electrum_client::Error, Electrum);
-#[cfg(feature = "esplora")]
-impl_error!(crate::blockchain::esplora::EsploraError, Esplora);
-#[cfg(feature = "key-value-db")]
-impl_error!(sled::Error, Sled);
-
-#[cfg(feature = "compact_filters")]
-impl From<crate::blockchain::compact_filters::CompactFiltersError> for Error {
-    fn from(other: crate::blockchain::compact_filters::CompactFiltersError) -> Self {
-        match other {
-            crate::blockchain::compact_filters::CompactFiltersError::Global(e) => *e,
-            err @ _ => Error::CompactFilters(err),
-        }
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/lib.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/lib.rs.html deleted file mode 100644 index e5d15a85a5..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/lib.rs.html +++ /dev/null @@ -1,179 +0,0 @@ -lib.rs.html -- source
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-// only enables the `doc_cfg` feature when
-// the `docsrs` configuration attribute is defined
-#![cfg_attr(docsrs, feature(doc_cfg))]
-// only enables the nightly `external_doc` feature when
-// `test-md-docs` is enabled
-#![cfg_attr(feature = "test-md-docs", feature(external_doc))]
-
-pub extern crate bitcoin;
-extern crate log;
-pub extern crate miniscript;
-extern crate serde;
-#[macro_use]
-extern crate serde_json;
-
-#[cfg(any(target_arch = "wasm32", feature = "async-interface"))]
-#[macro_use]
-extern crate async_trait;
-#[macro_use]
-extern crate magical_macros;
-
-#[cfg(any(test, feature = "compact_filters"))]
-#[macro_use]
-extern crate lazy_static;
-
-#[cfg(feature = "electrum")]
-pub extern crate electrum_client;
-
-#[cfg(feature = "esplora")]
-pub extern crate reqwest;
-
-#[cfg(feature = "key-value-db")]
-pub extern crate sled;
-
-#[cfg(feature = "cli-utils")]
-pub mod cli;
-
-#[cfg(test)]
-#[macro_use]
-extern crate testutils;
-#[cfg(test)]
-#[macro_use]
-extern crate testutils_macros;
-#[cfg(test)]
-#[macro_use]
-extern crate serial_test;
-
-#[macro_use]
-pub(crate) mod error;
-pub mod blockchain;
-pub mod database;
-pub mod descriptor;
-#[cfg(feature = "test-md-docs")]
-mod doctest;
-pub(crate) mod psbt;
-pub(crate) mod types;
-pub mod wallet;
-
-pub use descriptor::HDKeyPaths;
-pub use error::Error;
-pub use types::*;
-pub use wallet::address_validator;
-pub use wallet::signer;
-pub use wallet::tx_builder::TxBuilder;
-pub use wallet::{OfflineWallet, Wallet};
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/psbt/mod.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/psbt/mod.rs.html deleted file mode 100644 index 9648a22f2b..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/psbt/mod.rs.html +++ /dev/null @@ -1,107 +0,0 @@ -mod.rs.html -- source
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
-use bitcoin::TxOut;
-
-pub trait PSBTUtils {
-    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut>;
-}
-
-impl PSBTUtils for PSBT {
-    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut> {
-        let tx = &self.global.unsigned_tx;
-
-        if input_index >= tx.input.len() {
-            return None;
-        }
-
-        if let Some(input) = self.inputs.get(input_index) {
-            if let Some(wit_utxo) = &input.witness_utxo {
-                Some(wit_utxo.clone())
-            } else if let Some(in_tx) = &input.non_witness_utxo {
-                Some(in_tx.output[tx.input[input_index].previous_output.vout as usize].clone())
-            } else {
-                None
-            }
-        } else {
-            None
-        }
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/types.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/types.rs.html deleted file mode 100644 index 228bd2f597..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/types.rs.html +++ /dev/null @@ -1,227 +0,0 @@ -types.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-use std::convert::AsRef;
-
-use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxOut};
-use bitcoin::hash_types::Txid;
-
-use serde::{Deserialize, Serialize};
-
-/// Types of script
-#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub enum ScriptType {
-    External = 0,
-    Internal = 1,
-}
-
-impl ScriptType {
-    pub fn as_byte(&self) -> u8 {
-        match self {
-            ScriptType::External => 'e' as u8,
-            ScriptType::Internal => 'i' as u8,
-        }
-    }
-
-    pub fn is_internal(&self) -> bool {
-        self == &ScriptType::Internal
-    }
-}
-
-impl AsRef<[u8]> for ScriptType {
-    fn as_ref(&self) -> &[u8] {
-        match self {
-            ScriptType::External => b"e",
-            ScriptType::Internal => b"i",
-        }
-    }
-}
-
-/// Fee rate
-#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
-// Internally stored as satoshi/vbyte
-pub struct FeeRate(f32);
-
-impl FeeRate {
-    /// Create a new instance of [`FeeRate`] given a float fee rate in btc/kvbytes
-    pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self {
-        FeeRate(btc_per_kvb * 1e5)
-    }
-
-    /// Create a new instance of [`FeeRate`] given a float fee rate in satoshi/vbyte
-    pub fn from_sat_per_vb(sat_per_vb: f32) -> Self {
-        FeeRate(sat_per_vb)
-    }
-
-    /// Create a new [`FeeRate`] with the default min relay fee value
-    pub fn default_min_relay_fee() -> Self {
-        FeeRate(1.0)
-    }
-
-    /// Return the value as satoshi/vbyte
-    pub fn as_sat_vb(&self) -> f32 {
-        self.0
-    }
-}
-
-impl std::default::Default for FeeRate {
-    fn default() -> Self {
-        FeeRate::default_min_relay_fee()
-    }
-}
-
-/// A wallet unspent output
-#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
-pub struct UTXO {
-    pub outpoint: OutPoint,
-    pub txout: TxOut,
-    pub is_internal: bool,
-}
-
-/// A wallet transaction
-#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
-pub struct TransactionDetails {
-    pub transaction: Option<Transaction>,
-    pub txid: Txid,
-    pub timestamp: u64,
-    pub received: u64,
-    pub sent: u64,
-    pub fees: u64,
-    pub height: Option<u32>,
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/address_validator.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/address_validator.rs.html deleted file mode 100644 index 107b832a95..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/address_validator.rs.html +++ /dev/null @@ -1,327 +0,0 @@ -address_validator.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Address validation callbacks
-//!
-//! The typical usage of those callbacks is for displaying the newly-generated address on a
-//! hardware wallet, so that the user can cross-check its correctness.
-//!
-//! More generally speaking though, these callbacks can also be used to "do something" every time
-//! an address is generated, without necessarily checking or validating it.
-//!
-//! An address validator can be attached to a [`Wallet`](super::Wallet) by using the
-//! [`Wallet::add_address_validator`](super::Wallet::add_address_validator) method, and
-//! whenever a new address is generated (either explicitly by the user with
-//! [`Wallet::get_new_address`](super::Wallet::get_new_address) or internally to create a change
-//! address) all the attached validators will be polled, in sequence. All of them must complete
-//! successfully to continue.
-//!
-//! ## Example
-//!
-//! ```
-//! # use std::sync::Arc;
-//! # use bitcoin::*;
-//! # use magical::address_validator::*;
-//! # use magical::database::*;
-//! # use magical::*;
-//! struct PrintAddressAndContinue;
-//!
-//! impl AddressValidator for PrintAddressAndContinue {
-//!     fn validate(
-//!         &self,
-//!         script_type: ScriptType,
-//!         hd_keypaths: &HDKeyPaths,
-//!         script: &Script
-//!     ) -> Result<(), AddressValidatorError> {
-//!         let address = Address::from_script(script, Network::Testnet)
-//!             .as_ref()
-//!             .map(Address::to_string)
-//!             .unwrap_or(script.to_string());
-//!         println!("New address of type {:?}: {}", script_type, address);
-//!         println!("HD keypaths: {:#?}", hd_keypaths);
-//!
-//!         Ok(())
-//!     }
-//! }
-//!
-//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-//! let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
-//! wallet.add_address_validator(Arc::new(Box::new(PrintAddressAndContinue)));
-//!
-//! let address = wallet.get_new_address()?;
-//! println!("Address: {}", address);
-//! # Ok::<(), magical::Error>(())
-//! ```
-
-use std::fmt;
-
-use bitcoin::Script;
-
-use crate::descriptor::HDKeyPaths;
-use crate::types::ScriptType;
-
-/// Errors that can be returned to fail the validation of an address
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum AddressValidatorError {
-    UserRejected,
-    ConnectionError,
-    TimeoutError,
-    InvalidScript,
-    Message(String),
-}
-
-impl fmt::Display for AddressValidatorError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}", self)
-    }
-}
-
-impl std::error::Error for AddressValidatorError {}
-
-/// Trait to build address validators
-///
-/// All the address validators attached to a wallet with [`Wallet::add_address_validator`](super::Wallet::add_address_validator) will be polled
-/// every time an address (external or internal) is generated by the wallet. Errors returned in the
-/// validator will be propagated up to the original caller that triggered the address generation.
-///
-/// For a usage example see [this module](crate::address_validator)'s documentation.
-pub trait AddressValidator {
-    /// Validate or inspect an address
-    fn validate(
-        &self,
-        script_type: ScriptType,
-        hd_keypaths: &HDKeyPaths,
-        script: &Script,
-    ) -> Result<(), AddressValidatorError>;
-}
-
-#[cfg(test)]
-mod test {
-    use std::sync::Arc;
-
-    use super::*;
-    use crate::wallet::test::{get_funded_wallet, get_test_wpkh};
-    use crate::wallet::TxBuilder;
-
-    struct TestValidator;
-    impl AddressValidator for TestValidator {
-        fn validate(
-            &self,
-            _script_type: ScriptType,
-            _hd_keypaths: &HDKeyPaths,
-            _script: &bitcoin::Script,
-        ) -> Result<(), AddressValidatorError> {
-            Err(AddressValidatorError::InvalidScript)
-        }
-    }
-
-    #[test]
-    #[should_panic(expected = "InvalidScript")]
-    fn test_address_validator_external() {
-        let (mut wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        wallet.add_address_validator(Arc::new(Box::new(TestValidator)));
-
-        wallet.get_new_address().unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "InvalidScript")]
-    fn test_address_validator_internal() {
-        let (mut wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
-        wallet.add_address_validator(Arc::new(Box::new(TestValidator)));
-
-        let addr = testutils!(@external descriptors, 10);
-        wallet
-            .create_tx(TxBuilder::with_recipients(vec![(
-                addr.script_pubkey(),
-                25_000,
-            )]))
-            .unwrap();
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/coin_selection.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/coin_selection.rs.html deleted file mode 100644 index bc7cf8bfe9..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/coin_selection.rs.html +++ /dev/null @@ -1,701 +0,0 @@ -coin_selection.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Coin selection
-//!
-//! This module provides the trait [`CoinSelectionAlgorithm`] that can be implemented to
-//! define custom coin selection algorithms.
-//!
-//! The coin selection algorithm is not globally part of a [`Wallet`](super::Wallet), instead it
-//! is selected whenever a [`Wallet::create_tx`](super::Wallet::create_tx) call is made, through
-//! the use of the [`TxBuilder`] structure, specifically with
-//! [`TxBuilder::coin_selection`](super::tx_builder::TxBuilder::coin_selection) method.
-//!
-//! The [`DefaultCoinSelectionAlgorithm`] selects the default coin selection algorithm that
-//! [`TxBuilder`] uses, if it's not explicitly overridden.
-//!
-//! [`TxBuilder`]: super::tx_builder::TxBuilder
-//!
-//! ## Example
-//!
-//! ```no_run
-//! # use std::str::FromStr;
-//! # use bitcoin::*;
-//! # use bitcoin::consensus::serialize;
-//! # use magical::wallet::coin_selection::*;
-//! # use magical::*;
-//! #[derive(Debug)]
-//! struct AlwaysSpendEverything;
-//!
-//! impl CoinSelectionAlgorithm for AlwaysSpendEverything {
-//!     fn coin_select(
-//!         &self,
-//!         utxos: Vec<UTXO>,
-//!         _use_all_utxos: bool,
-//!         fee_rate: FeeRate,
-//!         amount_needed: u64,
-//!         input_witness_weight: usize,
-//!         fee_amount: f32,
-//!     ) -> Result<CoinSelectionResult, magical::Error> {
-//!         let selected_amount = utxos.iter().fold(0, |acc, utxo| acc + utxo.txout.value);
-//!         let all_utxos_selected = utxos
-//!             .into_iter()
-//!             .map(|utxo| {
-//!                 (
-//!                     TxIn {
-//!                         previous_output: utxo.outpoint,
-//!                         ..Default::default()
-//!                     },
-//!                     utxo.txout.script_pubkey,
-//!                 )
-//!             })
-//!             .collect::<Vec<_>>();
-//!         let additional_weight = all_utxos_selected.iter().fold(0, |acc, (txin, _)| {
-//!             acc + serialize(txin).len() * 4 + input_witness_weight
-//!         });
-//!         let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
-//!
-//!         if (fee_amount + additional_fees).ceil() as u64 + amount_needed > selected_amount {
-//!             return Err(magical::Error::InsufficientFunds);
-//!         }
-//!
-//!         Ok(CoinSelectionResult {
-//!             txin: all_utxos_selected,
-//!             selected_amount,
-//!             fee_amount: fee_amount + additional_fees,
-//!         })
-//!     }
-//! }
-//!
-//! # let wallet: OfflineWallet<_> = Wallet::new_offline("", None, Network::Testnet, magical::database::MemoryDatabase::default())?;
-//! // create wallet, sync, ...
-//!
-//! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
-//! let (psbt, details) = wallet.create_tx(
-//!     TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
-//!         .coin_selection(AlwaysSpendEverything),
-//! )?;
-//!
-//! // inspect, sign, broadcast, ...
-//!
-//! # Ok::<(), magical::Error>(())
-//! ```
-
-use bitcoin::consensus::encode::serialize;
-use bitcoin::{Script, TxIn};
-
-use crate::error::Error;
-use crate::types::{FeeRate, UTXO};
-
-/// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
-/// overridden
-pub type DefaultCoinSelectionAlgorithm = DumbCoinSelection;
-
-/// Result of a successful coin selection
-#[derive(Debug)]
-pub struct CoinSelectionResult {
-    /// List of inputs to use, with the respective previous script_pubkey
-    pub txin: Vec<(TxIn, Script)>,
-    /// Sum of the selected inputs' value
-    pub selected_amount: u64,
-    /// Total fee amount in satoshi
-    pub fee_amount: f32,
-}
-
-/// Trait for generalized coin selection algorithms
-///
-/// This trait can be implemented to make the [`Wallet`](super::Wallet) use a customized coin
-/// selection algorithm when it creates transactions.
-///
-/// For an example see [this module](crate::wallet::coin_selection)'s documentation.
-pub trait CoinSelectionAlgorithm: std::fmt::Debug {
-    /// Perform the coin selection
-    ///
-    /// - `utxos`: the list of spendable UTXOs
-    /// - `use_all_utxos`: if true all utxos should be spent unconditionally
-    /// - `fee_rate`: fee rate to use
-    /// - `amount_needed`: the amount in satoshi to select
-    /// - `input_witness_weight`: the weight of an input's witness to keep into account for the fees
-    /// - `fee_amount`: the amount of fees in satoshi already accumulated from adding outputs
-    fn coin_select(
-        &self,
-        utxos: Vec<UTXO>,
-        use_all_utxos: bool,
-        fee_rate: FeeRate,
-        amount_needed: u64,
-        input_witness_weight: usize,
-        fee_amount: f32,
-    ) -> Result<CoinSelectionResult, Error>;
-}
-
-/// Simple and dumb coin selection
-///
-/// This coin selection algorithm sorts the available UTXOs by value and then picks them starting
-/// from the largest ones until the required amount is reached.
-#[derive(Debug, Default)]
-pub struct DumbCoinSelection;
-
-impl CoinSelectionAlgorithm for DumbCoinSelection {
-    fn coin_select(
-        &self,
-        mut utxos: Vec<UTXO>,
-        use_all_utxos: bool,
-        fee_rate: FeeRate,
-        outgoing_amount: u64,
-        input_witness_weight: usize,
-        mut fee_amount: f32,
-    ) -> Result<CoinSelectionResult, Error> {
-        let mut txin = Vec::new();
-        let calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
-
-        log::debug!(
-            "outgoing_amount = `{}`, fee_amount = `{}`, fee_rate = `{:?}`",
-            outgoing_amount,
-            fee_amount,
-            fee_rate
-        );
-
-        // sort so that we pick them starting from the larger.
-        utxos.sort_by(|a, b| a.txout.value.partial_cmp(&b.txout.value).unwrap());
-
-        let mut selected_amount: u64 = 0;
-        while use_all_utxos || selected_amount < outgoing_amount + (fee_amount.ceil() as u64) {
-            let utxo = match utxos.pop() {
-                Some(utxo) => utxo,
-                None if selected_amount < outgoing_amount + (fee_amount.ceil() as u64) => {
-                    return Err(Error::InsufficientFunds)
-                }
-                None if use_all_utxos => break,
-                None => return Err(Error::InsufficientFunds),
-            };
-
-            let new_in = TxIn {
-                previous_output: utxo.outpoint,
-                script_sig: Script::default(),
-                sequence: 0, // Let the caller choose the right nSequence
-                witness: vec![],
-            };
-            fee_amount += calc_fee_bytes(serialize(&new_in).len() * 4 + input_witness_weight);
-            log::debug!(
-                "Selected {}, updated fee_amount = `{}`",
-                new_in.previous_output,
-                fee_amount
-            );
-
-            txin.push((new_in, utxo.txout.script_pubkey));
-            selected_amount += utxo.txout.value;
-        }
-
-        Ok(CoinSelectionResult {
-            txin,
-            fee_amount,
-            selected_amount,
-        })
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use std::str::FromStr;
-
-    use bitcoin::{OutPoint, Script, TxOut};
-
-    use super::*;
-    use crate::types::*;
-
-    const P2WPKH_WITNESS_SIZE: usize = 73 + 33 + 2;
-
-    fn get_test_utxos() -> Vec<UTXO> {
-        vec![
-            UTXO {
-                outpoint: OutPoint::from_str(
-                    "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0",
-                )
-                .unwrap(),
-                txout: TxOut {
-                    value: 100_000,
-                    script_pubkey: Script::new(),
-                },
-                is_internal: false,
-            },
-            UTXO {
-                outpoint: OutPoint::from_str(
-                    "65d92ddff6b6dc72c89624a6491997714b90f6004f928d875bc0fd53f264fa85:0",
-                )
-                .unwrap(),
-                txout: TxOut {
-                    value: 200_000,
-                    script_pubkey: Script::new(),
-                },
-                is_internal: true,
-            },
-        ]
-    }
-
-    #[test]
-    fn test_dumb_coin_selection_success() {
-        let utxos = get_test_utxos();
-
-        let result = DumbCoinSelection
-            .coin_select(
-                utxos,
-                false,
-                FeeRate::from_sat_per_vb(1.0),
-                250_000,
-                P2WPKH_WITNESS_SIZE,
-                50.0,
-            )
-            .unwrap();
-
-        assert_eq!(result.txin.len(), 2);
-        assert_eq!(result.selected_amount, 300_000);
-        assert_eq!(result.fee_amount, 186.0);
-    }
-
-    #[test]
-    fn test_dumb_coin_selection_use_all() {
-        let utxos = get_test_utxos();
-
-        let result = DumbCoinSelection
-            .coin_select(
-                utxos,
-                true,
-                FeeRate::from_sat_per_vb(1.0),
-                20_000,
-                P2WPKH_WITNESS_SIZE,
-                50.0,
-            )
-            .unwrap();
-
-        assert_eq!(result.txin.len(), 2);
-        assert_eq!(result.selected_amount, 300_000);
-        assert_eq!(result.fee_amount, 186.0);
-    }
-
-    #[test]
-    fn test_dumb_coin_selection_use_only_necessary() {
-        let utxos = get_test_utxos();
-
-        let result = DumbCoinSelection
-            .coin_select(
-                utxos,
-                false,
-                FeeRate::from_sat_per_vb(1.0),
-                20_000,
-                P2WPKH_WITNESS_SIZE,
-                50.0,
-            )
-            .unwrap();
-
-        assert_eq!(result.txin.len(), 1);
-        assert_eq!(result.selected_amount, 200_000);
-        assert_eq!(result.fee_amount, 118.0);
-    }
-
-    #[test]
-    #[should_panic(expected = "InsufficientFunds")]
-    fn test_dumb_coin_selection_insufficient_funds() {
-        let utxos = get_test_utxos();
-
-        DumbCoinSelection
-            .coin_select(
-                utxos,
-                false,
-                FeeRate::from_sat_per_vb(1.0),
-                500_000,
-                P2WPKH_WITNESS_SIZE,
-                50.0,
-            )
-            .unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "InsufficientFunds")]
-    fn test_dumb_coin_selection_insufficient_funds_high_fees() {
-        let utxos = get_test_utxos();
-
-        DumbCoinSelection
-            .coin_select(
-                utxos,
-                false,
-                FeeRate::from_sat_per_vb(1000.0),
-                250_000,
-                P2WPKH_WITNESS_SIZE,
-                50.0,
-            )
-            .unwrap();
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/export.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/export.rs.html deleted file mode 100644 index 7fbdfced5a..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/export.rs.html +++ /dev/null @@ -1,683 +0,0 @@ -export.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Wallet export
-//!
-//! This modules implements the wallet export format used by [FullyNoded](https://github.com/Fonta1n3/FullyNoded/blob/10b7808c8b929b171cca537fb50522d015168ac9/Docs/Wallets/Wallet-Export-Spec.md).
-//!
-//! ## Examples
-//!
-//! ### Import from JSON
-//!
-//! ```
-//! # use std::str::FromStr;
-//! # use bitcoin::*;
-//! # use magical::database::*;
-//! # use magical::wallet::export::*;
-//! # use magical::*;
-//! let import = r#"{
-//!     "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
-//!     "blockheight":1782088,
-//!     "label":"testnet"
-//! }"#;
-//!
-//! let import = WalletExport::from_str(import)?;
-//! let wallet: OfflineWallet<_> = Wallet::new_offline(&import.descriptor(), import.change_descriptor().as_deref(), Network::Testnet, MemoryDatabase::default())?;
-//! # Ok::<_, magical::Error>(())
-//! ```
-//!
-//! ### Export a `Wallet`
-//! ```
-//! # use bitcoin::*;
-//! # use magical::database::*;
-//! # use magical::wallet::export::*;
-//! # use magical::*;
-//! let wallet: OfflineWallet<_> = Wallet::new_offline(
-//!     "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
-//!     Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
-//!     Network::Testnet,
-//!     MemoryDatabase::default()
-//! )?;
-//! let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
-//!     .map_err(ToString::to_string)
-//!     .map_err(magical::Error::Generic)?;
-//!
-//! println!("Exported: {}", export.to_string());
-//! # Ok::<_, magical::Error>(())
-//! ```
-
-use std::str::FromStr;
-
-use serde::{Deserialize, Serialize};
-
-use miniscript::{Descriptor, ScriptContext, Terminal};
-
-use crate::blockchain::Blockchain;
-use crate::database::BatchDatabase;
-use crate::wallet::Wallet;
-
-/// Structure that contains the export of a wallet
-///
-/// For a usage example see [this module](crate::wallet::export)'s documentation.
-#[derive(Debug, Serialize, Deserialize)]
-pub struct WalletExport {
-    descriptor: String,
-    /// Earliest block to rescan when looking for the wallet's transactions
-    pub blockheight: u32,
-    /// Arbitrary label for the wallet
-    pub label: String,
-}
-
-impl ToString for WalletExport {
-    fn to_string(&self) -> String {
-        serde_json::to_string(self).unwrap()
-    }
-}
-
-impl FromStr for WalletExport {
-    type Err = serde_json::Error;
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        serde_json::from_str(s)
-    }
-}
-
-impl WalletExport {
-    /// Export a wallet
-    ///
-    /// This function returns an error if it determines that the `wallet`'s descriptor(s) are not
-    /// supported by Bitcoin Core or don't follow the standard derivation paths defined by BIP44
-    /// and others.
-    ///
-    /// If `include_blockheight` is `true`, this function will look into the `wallet`'s database
-    /// for the oldest transaction it knows and use that as the earliest block to rescan.
-    ///
-    /// If the database is empty or `include_blockheight` is false, the `blockheight` field
-    /// returned will be `0`.
-    pub fn export_wallet<B: Blockchain, D: BatchDatabase>(
-        wallet: &Wallet<B, D>,
-        label: &str,
-        include_blockheight: bool,
-    ) -> Result<Self, &'static str> {
-        let descriptor = wallet
-            .descriptor
-            .to_string_with_secret(&wallet.signers.as_key_map());
-        Self::is_compatible_with_core(&descriptor)?;
-
-        let blockheight = match wallet.database.borrow().iter_txs(false) {
-            _ if !include_blockheight => 0,
-            Err(_) => 0,
-            Ok(txs) => {
-                let mut heights = txs
-                    .into_iter()
-                    .map(|tx| tx.height.unwrap_or(0))
-                    .collect::<Vec<_>>();
-                heights.sort();
-
-                *heights.last().unwrap_or(&0)
-            }
-        };
-
-        let export = WalletExport {
-            descriptor,
-            label: label.into(),
-            blockheight,
-        };
-
-        if export.change_descriptor()
-            != wallet
-                .change_descriptor
-                .as_ref()
-                .map(|d| d.to_string_with_secret(&wallet.change_signers.as_key_map()))
-        {
-            return Err("Incompatible change descriptor");
-        }
-
-        Ok(export)
-    }
-
-    fn is_compatible_with_core(descriptor: &str) -> Result<(), &'static str> {
-        fn check_ms<Ctx: ScriptContext>(
-            terminal: Terminal<String, Ctx>,
-        ) -> Result<(), &'static str> {
-            if let Terminal::Multi(_, _) = terminal {
-                Ok(())
-            } else {
-                Err("The descriptor contains operators not supported by Bitcoin Core")
-            }
-        }
-
-        match Descriptor::<String>::from_str(descriptor).map_err(|_| "Invalid descriptor")? {
-            Descriptor::Pk(_)
-            | Descriptor::Pkh(_)
-            | Descriptor::Wpkh(_)
-            | Descriptor::ShWpkh(_) => Ok(()),
-            Descriptor::Sh(ms) => check_ms(ms.node),
-            Descriptor::Wsh(ms) | Descriptor::ShWsh(ms) => check_ms(ms.node),
-            _ => Err("The descriptor is not compatible with Bitcoin Core"),
-        }
-    }
-
-    /// Return the external descriptor
-    pub fn descriptor(&self) -> String {
-        self.descriptor.clone()
-    }
-
-    /// Return the internal descriptor, if present
-    pub fn change_descriptor(&self) -> Option<String> {
-        let replaced = self.descriptor.replace("/0/*", "/1/*");
-
-        if replaced != self.descriptor {
-            Some(replaced)
-        } else {
-            None
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use std::str::FromStr;
-
-    use bitcoin::{Network, Txid};
-
-    use super::*;
-    use crate::database::{memory::MemoryDatabase, BatchOperations};
-    use crate::types::TransactionDetails;
-    use crate::wallet::{OfflineWallet, Wallet};
-
-    fn get_test_db() -> MemoryDatabase {
-        let mut db = MemoryDatabase::new();
-        db.set_tx(&TransactionDetails {
-            transaction: None,
-            txid: Txid::from_str(
-                "4ddff1fa33af17f377f62b72357b43107c19110a8009b36fb832af505efed98a",
-            )
-            .unwrap(),
-            timestamp: 12345678,
-            received: 100_000,
-            sent: 0,
-            fees: 500,
-            height: Some(5000),
-        })
-        .unwrap();
-
-        db
-    }
-
-    #[test]
-    fn test_export_bip44() {
-        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
-        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
-
-        let wallet: OfflineWallet<_> = Wallet::new_offline(
-            descriptor,
-            Some(change_descriptor),
-            Network::Testnet,
-            get_test_db(),
-        )
-        .unwrap();
-        let export = WalletExport::export_wallet(&wallet, "Test Label", true).unwrap();
-
-        assert_eq!(export.descriptor(), descriptor);
-        assert_eq!(export.change_descriptor(), Some(change_descriptor.into()));
-        assert_eq!(export.blockheight, 5000);
-        assert_eq!(export.label, "Test Label");
-    }
-
-    #[test]
-    #[should_panic(expected = "Incompatible change descriptor")]
-    fn test_export_no_change() {
-        // This wallet explicitly doesn't have a change descriptor. It should be impossible to
-        // export, because exporting this kind of external descriptor normally implies the
-        // existence of an internal descriptor
-
-        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
-
-        let wallet: OfflineWallet<_> =
-            Wallet::new_offline(descriptor, None, Network::Testnet, get_test_db()).unwrap();
-        WalletExport::export_wallet(&wallet, "Test Label", true).unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "Incompatible change descriptor")]
-    fn test_export_incompatible_change() {
-        // This wallet has a change descriptor, but the derivation path is not in the "standard"
-        // bip44/49/etc format
-
-        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
-        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/50'/0'/1/*)";
-
-        let wallet: OfflineWallet<_> = Wallet::new_offline(
-            descriptor,
-            Some(change_descriptor),
-            Network::Testnet,
-            get_test_db(),
-        )
-        .unwrap();
-        WalletExport::export_wallet(&wallet, "Test Label", true).unwrap();
-    }
-
-    #[test]
-    fn test_export_multi() {
-        let descriptor = "wsh(multi(2,\
-                                [73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*,\
-                                [f9f62194/48'/0'/0'/2']tpubDDp3ZSH1yCwusRppH7zgSxq2t1VEUyXSeEp8E5aFS8m43MknUjiF1bSLo3CGWAxbDyhF1XowA5ukPzyJZjznYk3kYi6oe7QxtX2euvKWsk4/0/*,\
-                                [c98b1535/48'/0'/0'/2']tpubDCDi5W4sP6zSnzJeowy8rQDVhBdRARaPhK1axABi8V1661wEPeanpEXj4ZLAUEoikVtoWcyK26TKKJSecSfeKxwHCcRrge9k1ybuiL71z4a/0/*\
-                          ))";
-        let change_descriptor = "wsh(multi(2,\
-                                       [73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/1/*,\
-                                       [f9f62194/48'/0'/0'/2']tpubDDp3ZSH1yCwusRppH7zgSxq2t1VEUyXSeEp8E5aFS8m43MknUjiF1bSLo3CGWAxbDyhF1XowA5ukPzyJZjznYk3kYi6oe7QxtX2euvKWsk4/1/*,\
-                                       [c98b1535/48'/0'/0'/2']tpubDCDi5W4sP6zSnzJeowy8rQDVhBdRARaPhK1axABi8V1661wEPeanpEXj4ZLAUEoikVtoWcyK26TKKJSecSfeKxwHCcRrge9k1ybuiL71z4a/1/*\
-                                 ))";
-
-        let wallet: OfflineWallet<_> = Wallet::new_offline(
-            descriptor,
-            Some(change_descriptor),
-            Network::Testnet,
-            get_test_db(),
-        )
-        .unwrap();
-        let export = WalletExport::export_wallet(&wallet, "Test Label", true).unwrap();
-
-        assert_eq!(export.descriptor(), descriptor);
-        assert_eq!(export.change_descriptor(), Some(change_descriptor.into()));
-        assert_eq!(export.blockheight, 5000);
-        assert_eq!(export.label, "Test Label");
-    }
-
-    #[test]
-    fn test_export_to_json() {
-        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
-        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
-
-        let wallet: OfflineWallet<_> = Wallet::new_offline(
-            descriptor,
-            Some(change_descriptor),
-            Network::Testnet,
-            get_test_db(),
-        )
-        .unwrap();
-        let export = WalletExport::export_wallet(&wallet, "Test Label", true).unwrap();
-
-        assert_eq!(export.to_string(), "{\"descriptor\":\"wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44\'/0\'/0\'/0/*)\",\"blockheight\":5000,\"label\":\"Test Label\"}");
-    }
-
-    #[test]
-    fn test_export_from_json() {
-        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
-        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
-
-        let import_str = "{\"descriptor\":\"wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44\'/0\'/0\'/0/*)\",\"blockheight\":5000,\"label\":\"Test Label\"}";
-        let export = WalletExport::from_str(import_str).unwrap();
-
-        assert_eq!(export.descriptor(), descriptor);
-        assert_eq!(export.change_descriptor(), Some(change_descriptor.into()));
-        assert_eq!(export.blockheight, 5000);
-        assert_eq!(export.label, "Test Label");
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/mod.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/mod.rs.html deleted file mode 100644 index fdf1247850..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/mod.rs.html +++ /dev/null @@ -1,4873 +0,0 @@ -mod.rs.html -- source
   1
-   2
-   3
-   4
-   5
-   6
-   7
-   8
-   9
-  10
-  11
-  12
-  13
-  14
-  15
-  16
-  17
-  18
-  19
-  20
-  21
-  22
-  23
-  24
-  25
-  26
-  27
-  28
-  29
-  30
-  31
-  32
-  33
-  34
-  35
-  36
-  37
-  38
-  39
-  40
-  41
-  42
-  43
-  44
-  45
-  46
-  47
-  48
-  49
-  50
-  51
-  52
-  53
-  54
-  55
-  56
-  57
-  58
-  59
-  60
-  61
-  62
-  63
-  64
-  65
-  66
-  67
-  68
-  69
-  70
-  71
-  72
-  73
-  74
-  75
-  76
-  77
-  78
-  79
-  80
-  81
-  82
-  83
-  84
-  85
-  86
-  87
-  88
-  89
-  90
-  91
-  92
-  93
-  94
-  95
-  96
-  97
-  98
-  99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382
- 383
- 384
- 385
- 386
- 387
- 388
- 389
- 390
- 391
- 392
- 393
- 394
- 395
- 396
- 397
- 398
- 399
- 400
- 401
- 402
- 403
- 404
- 405
- 406
- 407
- 408
- 409
- 410
- 411
- 412
- 413
- 414
- 415
- 416
- 417
- 418
- 419
- 420
- 421
- 422
- 423
- 424
- 425
- 426
- 427
- 428
- 429
- 430
- 431
- 432
- 433
- 434
- 435
- 436
- 437
- 438
- 439
- 440
- 441
- 442
- 443
- 444
- 445
- 446
- 447
- 448
- 449
- 450
- 451
- 452
- 453
- 454
- 455
- 456
- 457
- 458
- 459
- 460
- 461
- 462
- 463
- 464
- 465
- 466
- 467
- 468
- 469
- 470
- 471
- 472
- 473
- 474
- 475
- 476
- 477
- 478
- 479
- 480
- 481
- 482
- 483
- 484
- 485
- 486
- 487
- 488
- 489
- 490
- 491
- 492
- 493
- 494
- 495
- 496
- 497
- 498
- 499
- 500
- 501
- 502
- 503
- 504
- 505
- 506
- 507
- 508
- 509
- 510
- 511
- 512
- 513
- 514
- 515
- 516
- 517
- 518
- 519
- 520
- 521
- 522
- 523
- 524
- 525
- 526
- 527
- 528
- 529
- 530
- 531
- 532
- 533
- 534
- 535
- 536
- 537
- 538
- 539
- 540
- 541
- 542
- 543
- 544
- 545
- 546
- 547
- 548
- 549
- 550
- 551
- 552
- 553
- 554
- 555
- 556
- 557
- 558
- 559
- 560
- 561
- 562
- 563
- 564
- 565
- 566
- 567
- 568
- 569
- 570
- 571
- 572
- 573
- 574
- 575
- 576
- 577
- 578
- 579
- 580
- 581
- 582
- 583
- 584
- 585
- 586
- 587
- 588
- 589
- 590
- 591
- 592
- 593
- 594
- 595
- 596
- 597
- 598
- 599
- 600
- 601
- 602
- 603
- 604
- 605
- 606
- 607
- 608
- 609
- 610
- 611
- 612
- 613
- 614
- 615
- 616
- 617
- 618
- 619
- 620
- 621
- 622
- 623
- 624
- 625
- 626
- 627
- 628
- 629
- 630
- 631
- 632
- 633
- 634
- 635
- 636
- 637
- 638
- 639
- 640
- 641
- 642
- 643
- 644
- 645
- 646
- 647
- 648
- 649
- 650
- 651
- 652
- 653
- 654
- 655
- 656
- 657
- 658
- 659
- 660
- 661
- 662
- 663
- 664
- 665
- 666
- 667
- 668
- 669
- 670
- 671
- 672
- 673
- 674
- 675
- 676
- 677
- 678
- 679
- 680
- 681
- 682
- 683
- 684
- 685
- 686
- 687
- 688
- 689
- 690
- 691
- 692
- 693
- 694
- 695
- 696
- 697
- 698
- 699
- 700
- 701
- 702
- 703
- 704
- 705
- 706
- 707
- 708
- 709
- 710
- 711
- 712
- 713
- 714
- 715
- 716
- 717
- 718
- 719
- 720
- 721
- 722
- 723
- 724
- 725
- 726
- 727
- 728
- 729
- 730
- 731
- 732
- 733
- 734
- 735
- 736
- 737
- 738
- 739
- 740
- 741
- 742
- 743
- 744
- 745
- 746
- 747
- 748
- 749
- 750
- 751
- 752
- 753
- 754
- 755
- 756
- 757
- 758
- 759
- 760
- 761
- 762
- 763
- 764
- 765
- 766
- 767
- 768
- 769
- 770
- 771
- 772
- 773
- 774
- 775
- 776
- 777
- 778
- 779
- 780
- 781
- 782
- 783
- 784
- 785
- 786
- 787
- 788
- 789
- 790
- 791
- 792
- 793
- 794
- 795
- 796
- 797
- 798
- 799
- 800
- 801
- 802
- 803
- 804
- 805
- 806
- 807
- 808
- 809
- 810
- 811
- 812
- 813
- 814
- 815
- 816
- 817
- 818
- 819
- 820
- 821
- 822
- 823
- 824
- 825
- 826
- 827
- 828
- 829
- 830
- 831
- 832
- 833
- 834
- 835
- 836
- 837
- 838
- 839
- 840
- 841
- 842
- 843
- 844
- 845
- 846
- 847
- 848
- 849
- 850
- 851
- 852
- 853
- 854
- 855
- 856
- 857
- 858
- 859
- 860
- 861
- 862
- 863
- 864
- 865
- 866
- 867
- 868
- 869
- 870
- 871
- 872
- 873
- 874
- 875
- 876
- 877
- 878
- 879
- 880
- 881
- 882
- 883
- 884
- 885
- 886
- 887
- 888
- 889
- 890
- 891
- 892
- 893
- 894
- 895
- 896
- 897
- 898
- 899
- 900
- 901
- 902
- 903
- 904
- 905
- 906
- 907
- 908
- 909
- 910
- 911
- 912
- 913
- 914
- 915
- 916
- 917
- 918
- 919
- 920
- 921
- 922
- 923
- 924
- 925
- 926
- 927
- 928
- 929
- 930
- 931
- 932
- 933
- 934
- 935
- 936
- 937
- 938
- 939
- 940
- 941
- 942
- 943
- 944
- 945
- 946
- 947
- 948
- 949
- 950
- 951
- 952
- 953
- 954
- 955
- 956
- 957
- 958
- 959
- 960
- 961
- 962
- 963
- 964
- 965
- 966
- 967
- 968
- 969
- 970
- 971
- 972
- 973
- 974
- 975
- 976
- 977
- 978
- 979
- 980
- 981
- 982
- 983
- 984
- 985
- 986
- 987
- 988
- 989
- 990
- 991
- 992
- 993
- 994
- 995
- 996
- 997
- 998
- 999
-1000
-1001
-1002
-1003
-1004
-1005
-1006
-1007
-1008
-1009
-1010
-1011
-1012
-1013
-1014
-1015
-1016
-1017
-1018
-1019
-1020
-1021
-1022
-1023
-1024
-1025
-1026
-1027
-1028
-1029
-1030
-1031
-1032
-1033
-1034
-1035
-1036
-1037
-1038
-1039
-1040
-1041
-1042
-1043
-1044
-1045
-1046
-1047
-1048
-1049
-1050
-1051
-1052
-1053
-1054
-1055
-1056
-1057
-1058
-1059
-1060
-1061
-1062
-1063
-1064
-1065
-1066
-1067
-1068
-1069
-1070
-1071
-1072
-1073
-1074
-1075
-1076
-1077
-1078
-1079
-1080
-1081
-1082
-1083
-1084
-1085
-1086
-1087
-1088
-1089
-1090
-1091
-1092
-1093
-1094
-1095
-1096
-1097
-1098
-1099
-1100
-1101
-1102
-1103
-1104
-1105
-1106
-1107
-1108
-1109
-1110
-1111
-1112
-1113
-1114
-1115
-1116
-1117
-1118
-1119
-1120
-1121
-1122
-1123
-1124
-1125
-1126
-1127
-1128
-1129
-1130
-1131
-1132
-1133
-1134
-1135
-1136
-1137
-1138
-1139
-1140
-1141
-1142
-1143
-1144
-1145
-1146
-1147
-1148
-1149
-1150
-1151
-1152
-1153
-1154
-1155
-1156
-1157
-1158
-1159
-1160
-1161
-1162
-1163
-1164
-1165
-1166
-1167
-1168
-1169
-1170
-1171
-1172
-1173
-1174
-1175
-1176
-1177
-1178
-1179
-1180
-1181
-1182
-1183
-1184
-1185
-1186
-1187
-1188
-1189
-1190
-1191
-1192
-1193
-1194
-1195
-1196
-1197
-1198
-1199
-1200
-1201
-1202
-1203
-1204
-1205
-1206
-1207
-1208
-1209
-1210
-1211
-1212
-1213
-1214
-1215
-1216
-1217
-1218
-1219
-1220
-1221
-1222
-1223
-1224
-1225
-1226
-1227
-1228
-1229
-1230
-1231
-1232
-1233
-1234
-1235
-1236
-1237
-1238
-1239
-1240
-1241
-1242
-1243
-1244
-1245
-1246
-1247
-1248
-1249
-1250
-1251
-1252
-1253
-1254
-1255
-1256
-1257
-1258
-1259
-1260
-1261
-1262
-1263
-1264
-1265
-1266
-1267
-1268
-1269
-1270
-1271
-1272
-1273
-1274
-1275
-1276
-1277
-1278
-1279
-1280
-1281
-1282
-1283
-1284
-1285
-1286
-1287
-1288
-1289
-1290
-1291
-1292
-1293
-1294
-1295
-1296
-1297
-1298
-1299
-1300
-1301
-1302
-1303
-1304
-1305
-1306
-1307
-1308
-1309
-1310
-1311
-1312
-1313
-1314
-1315
-1316
-1317
-1318
-1319
-1320
-1321
-1322
-1323
-1324
-1325
-1326
-1327
-1328
-1329
-1330
-1331
-1332
-1333
-1334
-1335
-1336
-1337
-1338
-1339
-1340
-1341
-1342
-1343
-1344
-1345
-1346
-1347
-1348
-1349
-1350
-1351
-1352
-1353
-1354
-1355
-1356
-1357
-1358
-1359
-1360
-1361
-1362
-1363
-1364
-1365
-1366
-1367
-1368
-1369
-1370
-1371
-1372
-1373
-1374
-1375
-1376
-1377
-1378
-1379
-1380
-1381
-1382
-1383
-1384
-1385
-1386
-1387
-1388
-1389
-1390
-1391
-1392
-1393
-1394
-1395
-1396
-1397
-1398
-1399
-1400
-1401
-1402
-1403
-1404
-1405
-1406
-1407
-1408
-1409
-1410
-1411
-1412
-1413
-1414
-1415
-1416
-1417
-1418
-1419
-1420
-1421
-1422
-1423
-1424
-1425
-1426
-1427
-1428
-1429
-1430
-1431
-1432
-1433
-1434
-1435
-1436
-1437
-1438
-1439
-1440
-1441
-1442
-1443
-1444
-1445
-1446
-1447
-1448
-1449
-1450
-1451
-1452
-1453
-1454
-1455
-1456
-1457
-1458
-1459
-1460
-1461
-1462
-1463
-1464
-1465
-1466
-1467
-1468
-1469
-1470
-1471
-1472
-1473
-1474
-1475
-1476
-1477
-1478
-1479
-1480
-1481
-1482
-1483
-1484
-1485
-1486
-1487
-1488
-1489
-1490
-1491
-1492
-1493
-1494
-1495
-1496
-1497
-1498
-1499
-1500
-1501
-1502
-1503
-1504
-1505
-1506
-1507
-1508
-1509
-1510
-1511
-1512
-1513
-1514
-1515
-1516
-1517
-1518
-1519
-1520
-1521
-1522
-1523
-1524
-1525
-1526
-1527
-1528
-1529
-1530
-1531
-1532
-1533
-1534
-1535
-1536
-1537
-1538
-1539
-1540
-1541
-1542
-1543
-1544
-1545
-1546
-1547
-1548
-1549
-1550
-1551
-1552
-1553
-1554
-1555
-1556
-1557
-1558
-1559
-1560
-1561
-1562
-1563
-1564
-1565
-1566
-1567
-1568
-1569
-1570
-1571
-1572
-1573
-1574
-1575
-1576
-1577
-1578
-1579
-1580
-1581
-1582
-1583
-1584
-1585
-1586
-1587
-1588
-1589
-1590
-1591
-1592
-1593
-1594
-1595
-1596
-1597
-1598
-1599
-1600
-1601
-1602
-1603
-1604
-1605
-1606
-1607
-1608
-1609
-1610
-1611
-1612
-1613
-1614
-1615
-1616
-1617
-1618
-1619
-1620
-1621
-1622
-1623
-1624
-1625
-1626
-1627
-1628
-1629
-1630
-1631
-1632
-1633
-1634
-1635
-1636
-1637
-1638
-1639
-1640
-1641
-1642
-1643
-1644
-1645
-1646
-1647
-1648
-1649
-1650
-1651
-1652
-1653
-1654
-1655
-1656
-1657
-1658
-1659
-1660
-1661
-1662
-1663
-1664
-1665
-1666
-1667
-1668
-1669
-1670
-1671
-1672
-1673
-1674
-1675
-1676
-1677
-1678
-1679
-1680
-1681
-1682
-1683
-1684
-1685
-1686
-1687
-1688
-1689
-1690
-1691
-1692
-1693
-1694
-1695
-1696
-1697
-1698
-1699
-1700
-1701
-1702
-1703
-1704
-1705
-1706
-1707
-1708
-1709
-1710
-1711
-1712
-1713
-1714
-1715
-1716
-1717
-1718
-1719
-1720
-1721
-1722
-1723
-1724
-1725
-1726
-1727
-1728
-1729
-1730
-1731
-1732
-1733
-1734
-1735
-1736
-1737
-1738
-1739
-1740
-1741
-1742
-1743
-1744
-1745
-1746
-1747
-1748
-1749
-1750
-1751
-1752
-1753
-1754
-1755
-1756
-1757
-1758
-1759
-1760
-1761
-1762
-1763
-1764
-1765
-1766
-1767
-1768
-1769
-1770
-1771
-1772
-1773
-1774
-1775
-1776
-1777
-1778
-1779
-1780
-1781
-1782
-1783
-1784
-1785
-1786
-1787
-1788
-1789
-1790
-1791
-1792
-1793
-1794
-1795
-1796
-1797
-1798
-1799
-1800
-1801
-1802
-1803
-1804
-1805
-1806
-1807
-1808
-1809
-1810
-1811
-1812
-1813
-1814
-1815
-1816
-1817
-1818
-1819
-1820
-1821
-1822
-1823
-1824
-1825
-1826
-1827
-1828
-1829
-1830
-1831
-1832
-1833
-1834
-1835
-1836
-1837
-1838
-1839
-1840
-1841
-1842
-1843
-1844
-1845
-1846
-1847
-1848
-1849
-1850
-1851
-1852
-1853
-1854
-1855
-1856
-1857
-1858
-1859
-1860
-1861
-1862
-1863
-1864
-1865
-1866
-1867
-1868
-1869
-1870
-1871
-1872
-1873
-1874
-1875
-1876
-1877
-1878
-1879
-1880
-1881
-1882
-1883
-1884
-1885
-1886
-1887
-1888
-1889
-1890
-1891
-1892
-1893
-1894
-1895
-1896
-1897
-1898
-1899
-1900
-1901
-1902
-1903
-1904
-1905
-1906
-1907
-1908
-1909
-1910
-1911
-1912
-1913
-1914
-1915
-1916
-1917
-1918
-1919
-1920
-1921
-1922
-1923
-1924
-1925
-1926
-1927
-1928
-1929
-1930
-1931
-1932
-1933
-1934
-1935
-1936
-1937
-1938
-1939
-1940
-1941
-1942
-1943
-1944
-1945
-1946
-1947
-1948
-1949
-1950
-1951
-1952
-1953
-1954
-1955
-1956
-1957
-1958
-1959
-1960
-1961
-1962
-1963
-1964
-1965
-1966
-1967
-1968
-1969
-1970
-1971
-1972
-1973
-1974
-1975
-1976
-1977
-1978
-1979
-1980
-1981
-1982
-1983
-1984
-1985
-1986
-1987
-1988
-1989
-1990
-1991
-1992
-1993
-1994
-1995
-1996
-1997
-1998
-1999
-2000
-2001
-2002
-2003
-2004
-2005
-2006
-2007
-2008
-2009
-2010
-2011
-2012
-2013
-2014
-2015
-2016
-2017
-2018
-2019
-2020
-2021
-2022
-2023
-2024
-2025
-2026
-2027
-2028
-2029
-2030
-2031
-2032
-2033
-2034
-2035
-2036
-2037
-2038
-2039
-2040
-2041
-2042
-2043
-2044
-2045
-2046
-2047
-2048
-2049
-2050
-2051
-2052
-2053
-2054
-2055
-2056
-2057
-2058
-2059
-2060
-2061
-2062
-2063
-2064
-2065
-2066
-2067
-2068
-2069
-2070
-2071
-2072
-2073
-2074
-2075
-2076
-2077
-2078
-2079
-2080
-2081
-2082
-2083
-2084
-2085
-2086
-2087
-2088
-2089
-2090
-2091
-2092
-2093
-2094
-2095
-2096
-2097
-2098
-2099
-2100
-2101
-2102
-2103
-2104
-2105
-2106
-2107
-2108
-2109
-2110
-2111
-2112
-2113
-2114
-2115
-2116
-2117
-2118
-2119
-2120
-2121
-2122
-2123
-2124
-2125
-2126
-2127
-2128
-2129
-2130
-2131
-2132
-2133
-2134
-2135
-2136
-2137
-2138
-2139
-2140
-2141
-2142
-2143
-2144
-2145
-2146
-2147
-2148
-2149
-2150
-2151
-2152
-2153
-2154
-2155
-2156
-2157
-2158
-2159
-2160
-2161
-2162
-2163
-2164
-2165
-2166
-2167
-2168
-2169
-2170
-2171
-2172
-2173
-2174
-2175
-2176
-2177
-2178
-2179
-2180
-2181
-2182
-2183
-2184
-2185
-2186
-2187
-2188
-2189
-2190
-2191
-2192
-2193
-2194
-2195
-2196
-2197
-2198
-2199
-2200
-2201
-2202
-2203
-2204
-2205
-2206
-2207
-2208
-2209
-2210
-2211
-2212
-2213
-2214
-2215
-2216
-2217
-2218
-2219
-2220
-2221
-2222
-2223
-2224
-2225
-2226
-2227
-2228
-2229
-2230
-2231
-2232
-2233
-2234
-2235
-2236
-2237
-2238
-2239
-2240
-2241
-2242
-2243
-2244
-2245
-2246
-2247
-2248
-2249
-2250
-2251
-2252
-2253
-2254
-2255
-2256
-2257
-2258
-2259
-2260
-2261
-2262
-2263
-2264
-2265
-2266
-2267
-2268
-2269
-2270
-2271
-2272
-2273
-2274
-2275
-2276
-2277
-2278
-2279
-2280
-2281
-2282
-2283
-2284
-2285
-2286
-2287
-2288
-2289
-2290
-2291
-2292
-2293
-2294
-2295
-2296
-2297
-2298
-2299
-2300
-2301
-2302
-2303
-2304
-2305
-2306
-2307
-2308
-2309
-2310
-2311
-2312
-2313
-2314
-2315
-2316
-2317
-2318
-2319
-2320
-2321
-2322
-2323
-2324
-2325
-2326
-2327
-2328
-2329
-2330
-2331
-2332
-2333
-2334
-2335
-2336
-2337
-2338
-2339
-2340
-2341
-2342
-2343
-2344
-2345
-2346
-2347
-2348
-2349
-2350
-2351
-2352
-2353
-2354
-2355
-2356
-2357
-2358
-2359
-2360
-2361
-2362
-2363
-2364
-2365
-2366
-2367
-2368
-2369
-2370
-2371
-2372
-2373
-2374
-2375
-2376
-2377
-2378
-2379
-2380
-2381
-2382
-2383
-2384
-2385
-2386
-2387
-2388
-2389
-2390
-2391
-2392
-2393
-2394
-2395
-2396
-2397
-2398
-2399
-2400
-2401
-2402
-2403
-2404
-2405
-2406
-2407
-2408
-2409
-2410
-2411
-2412
-2413
-2414
-2415
-2416
-2417
-2418
-2419
-2420
-2421
-2422
-2423
-2424
-2425
-2426
-2427
-2428
-2429
-2430
-2431
-2432
-2433
-2434
-2435
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Wallet
-//!
-//! This module defines the [`Wallet`] structure.
-
-use std::cell::RefCell;
-use std::collections::HashMap;
-use std::collections::{BTreeMap, HashSet};
-use std::ops::{Deref, DerefMut};
-use std::sync::Arc;
-
-use bitcoin::consensus::encode::serialize;
-use bitcoin::util::bip32::ChildNumber;
-use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
-use bitcoin::{Address, Network, OutPoint, Script, SigHashType, Transaction, TxOut, Txid};
-
-use miniscript::descriptor::DescriptorPublicKey;
-
-#[allow(unused_imports)]
-use log::{debug, error, info, trace};
-
-pub mod address_validator;
-pub mod coin_selection;
-pub mod export;
-mod rbf;
-pub mod signer;
-pub mod time;
-pub mod tx_builder;
-pub(crate) mod utils;
-
-pub use utils::IsDust;
-
-use address_validator::AddressValidator;
-use signer::{Signer, SignerId, SignerOrdering, SignersContainer};
-use tx_builder::TxBuilder;
-use utils::{After, Older};
-
-use crate::blockchain::{Blockchain, OfflineBlockchain, OnlineBlockchain, Progress};
-use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
-use crate::descriptor::{
-    get_checksum, DescriptorMeta, DescriptorScripts, ExtendedDescriptor, ExtractPolicy, Policy,
-};
-use crate::error::Error;
-use crate::psbt::PSBTUtils;
-use crate::types::*;
-
-const CACHE_ADDR_BATCH_SIZE: u32 = 100;
-
-/// Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]
-pub type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;
-
-/// A Bitcoin wallet
-///
-/// A wallet takes descriptors, a [`database`](crate::database) and a
-/// [`blockchain`](crate::blockchain) and implements the basic functions that a Bitcoin wallets
-/// needs to operate, like [generating addresses](Wallet::get_new_address), [returning the balance](Wallet::get_balance),
-/// [creating transactions](Wallet::create_tx), etc.
-///
-/// A wallet can be either "online" if the [`blockchain`](crate::blockchain) type provided
-/// implements [`OnlineBlockchain`], or "offline" if it doesn't. Offline wallets only expose
-/// methods that don't need any interaction with the blockchain to work.
-pub struct Wallet<B: Blockchain, D: BatchDatabase> {
-    descriptor: ExtendedDescriptor,
-    change_descriptor: Option<ExtendedDescriptor>,
-
-    signers: Arc<SignersContainer<DescriptorPublicKey>>,
-    change_signers: Arc<SignersContainer<DescriptorPublicKey>>,
-
-    address_validators: Vec<Arc<Box<dyn AddressValidator>>>,
-
-    network: Network,
-
-    current_height: Option<u32>,
-
-    client: B,
-    database: RefCell<D>,
-}
-
-// offline actions, always available
-impl<B, D> Wallet<B, D>
-where
-    B: Blockchain,
-    D: BatchDatabase,
-{
-    /// Create a new "offline" wallet
-    pub fn new_offline(
-        descriptor: &str,
-        change_descriptor: Option<&str>,
-        network: Network,
-        mut database: D,
-    ) -> Result<Self, Error> {
-        database.check_descriptor_checksum(
-            ScriptType::External,
-            get_checksum(descriptor)?.as_bytes(),
-        )?;
-        let (descriptor, keymap) = ExtendedDescriptor::parse_secret(descriptor)?;
-        let signers = Arc::new(SignersContainer::from(keymap));
-        let (change_descriptor, change_signers) = match change_descriptor {
-            Some(desc) => {
-                database.check_descriptor_checksum(
-                    ScriptType::Internal,
-                    get_checksum(desc)?.as_bytes(),
-                )?;
-
-                let (change_descriptor, change_keymap) = ExtendedDescriptor::parse_secret(desc)?;
-                let change_signers = Arc::new(SignersContainer::from(change_keymap));
-                // if !parsed.same_structure(descriptor.as_ref()) {
-                //     return Err(Error::DifferentDescriptorStructure);
-                // }
-
-                (Some(change_descriptor), change_signers)
-            }
-            None => (None, Arc::new(SignersContainer::new())),
-        };
-
-        Ok(Wallet {
-            descriptor,
-            change_descriptor,
-            signers,
-            change_signers,
-            address_validators: Vec::new(),
-
-            network,
-
-            current_height: None,
-
-            client: B::offline(),
-            database: RefCell::new(database),
-        })
-    }
-
-    /// Return a newly generated address using the external descriptor
-    pub fn get_new_address(&self) -> Result<Address, Error> {
-        let index = self.fetch_and_increment_index(ScriptType::External)?;
-
-        self.descriptor
-            .derive(&[ChildNumber::from_normal_idx(index).unwrap()])
-            .address(self.network)
-            .ok_or(Error::ScriptDoesntHaveAddressForm)
-    }
-
-    /// Return whether or not a `script` is part of this wallet (either internal or external)
-    pub fn is_mine(&self, script: &Script) -> Result<bool, Error> {
-        self.database.borrow().is_mine(script)
-    }
-
-    /// Return the list of unspent outputs of this wallet
-    ///
-    /// Note that this methods only operate on the internal database, which first needs to be
-    /// [`Wallet::sync`] manually.
-    pub fn list_unspent(&self) -> Result<Vec<UTXO>, Error> {
-        self.database.borrow().iter_utxos()
-    }
-
-    /// Return the list of transactions made and received by the wallet
-    ///
-    /// Optionally fill the [`TransactionDetails::transaction`] field with the raw transaction if
-    /// `include_raw` is `true`.
-    ///
-    /// Note that this methods only operate on the internal database, which first needs to be
-    /// [`Wallet::sync`] manually.
-    pub fn list_transactions(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
-        self.database.borrow().iter_txs(include_raw)
-    }
-
-    /// Return the balance, meaning the sum of this wallet's unspent outputs' values
-    ///
-    /// Note that this methods only operate on the internal database, which first needs to be
-    /// [`Wallet::sync`] manually.
-    pub fn get_balance(&self) -> Result<u64, Error> {
-        Ok(self
-            .list_unspent()?
-            .iter()
-            .fold(0, |sum, i| sum + i.txout.value))
-    }
-
-    /// Add an external signer
-    ///
-    /// See [the `signer` module](signer) for an example.
-    pub fn add_signer(
-        &mut self,
-        script_type: ScriptType,
-        id: SignerId<DescriptorPublicKey>,
-        ordering: SignerOrdering,
-        signer: Arc<Box<dyn Signer>>,
-    ) {
-        let signers = match script_type {
-            ScriptType::External => Arc::make_mut(&mut self.signers),
-            ScriptType::Internal => Arc::make_mut(&mut self.change_signers),
-        };
-
-        signers.add_external(id, ordering, signer);
-    }
-
-    /// Add an address validator
-    ///
-    /// See [the `address_validator` module](address_validator) for an example.
-    pub fn add_address_validator(&mut self, validator: Arc<Box<dyn AddressValidator>>) {
-        self.address_validators.push(validator);
-    }
-
-    /// Create a new transaction following the options specified in the `builder`
-    ///
-    /// ## Example
-    ///
-    /// ```no_run
-    /// # use std::str::FromStr;
-    /// # use bitcoin::*;
-    /// # use magical::*;
-    /// # use magical::database::*;
-    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
-    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
-    /// let (psbt, details) = wallet.create_tx(
-    ///     TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
-    /// )?;
-    /// // sign and broadcast ...
-    /// # Ok::<(), magical::Error>(())
-    /// ```
-    pub fn create_tx<Cs: coin_selection::CoinSelectionAlgorithm>(
-        &self,
-        builder: TxBuilder<Cs>,
-    ) -> Result<(PSBT, TransactionDetails), Error> {
-        if builder.recipients.is_empty() {
-            return Err(Error::NoAddressees);
-        }
-
-        // TODO: fetch both internal and external policies
-        let policy = self
-            .descriptor
-            .extract_policy(Arc::clone(&self.signers))?
-            .unwrap();
-        if policy.requires_path() && builder.policy_path.is_none() {
-            return Err(Error::SpendingPolicyRequired);
-        }
-        let requirements =
-            policy.get_condition(builder.policy_path.as_ref().unwrap_or(&BTreeMap::new()))?;
-        debug!("requirements: {:?}", requirements);
-
-        let version = match builder.version {
-            Some(tx_builder::Version(0)) => {
-                return Err(Error::Generic("Invalid version `0`".into()))
-            }
-            Some(tx_builder::Version(1)) if requirements.csv.is_some() => {
-                return Err(Error::Generic(
-                    "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
-                        .into(),
-                ))
-            }
-            Some(tx_builder::Version(x)) => x,
-            None if requirements.csv.is_some() => 2,
-            _ => 1,
-        };
-
-        let lock_time = match builder.locktime {
-            None => requirements.timelock.unwrap_or(0),
-            Some(x) if requirements.timelock.is_none() => x,
-            Some(x) if requirements.timelock.unwrap() <= x => x,
-            Some(x) => return Err(Error::Generic(format!("TxBuilder requested timelock of `{}`, but at least `{}` is required to spend from this script", x, requirements.timelock.unwrap())))
-        };
-
-        let n_sequence = match (builder.rbf, requirements.csv) {
-            (None, Some(csv)) => csv,
-            (Some(rbf), Some(csv)) if rbf < csv => return Err(Error::Generic(format!("Cannot enable RBF with nSequence `{}`, since at least `{}` is required to spend with OP_CSV", rbf, csv))),
-            (None, _) if requirements.timelock.is_some() => 0xFFFFFFFE,
-            (Some(rbf), _) if rbf >= 0xFFFFFFFE => return Err(Error::Generic("Cannot enable RBF with a nSequence >= 0xFFFFFFFE".into())),
-            (Some(rbf), _) => rbf,
-            (None, _) => 0xFFFFFFFF,
-        };
-
-        let mut tx = Transaction {
-            version,
-            lock_time,
-            input: vec![],
-            output: vec![],
-        };
-
-        let fee_rate = builder.fee_rate.unwrap_or_default();
-        if builder.send_all && builder.recipients.len() != 1 {
-            return Err(Error::SendAllMultipleOutputs);
-        }
-
-        // we keep it as a float while we accumulate it, and only round it at the end
-        let mut fee_amount: f32 = 0.0;
-        let mut outgoing: u64 = 0;
-        let mut received: u64 = 0;
-
-        let calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
-        fee_amount += calc_fee_bytes(tx.get_weight());
-
-        for (index, (script_pubkey, satoshi)) in builder.recipients.iter().enumerate() {
-            let value = match builder.send_all {
-                true => 0,
-                false if satoshi.is_dust() => return Err(Error::OutputBelowDustLimit(index)),
-                false => *satoshi,
-            };
-
-            if self.is_mine(script_pubkey)? {
-                received += value;
-            }
-
-            let new_out = TxOut {
-                script_pubkey: script_pubkey.clone(),
-                value,
-            };
-            fee_amount += calc_fee_bytes(serialize(&new_out).len() * 4);
-
-            tx.output.push(new_out);
-
-            outgoing += value;
-        }
-
-        // TODO: use the right weight instead of the maximum, and only fall-back to it if the
-        // script is unknown in the database
-        let input_witness_weight = std::cmp::max(
-            self.get_descriptor_for_script_type(ScriptType::Internal)
-                .0
-                .max_satisfaction_weight(),
-            self.get_descriptor_for_script_type(ScriptType::External)
-                .0
-                .max_satisfaction_weight(),
-        );
-
-        if builder.change_policy != tx_builder::ChangeSpendPolicy::ChangeAllowed
-            && self.change_descriptor.is_none()
-        {
-            return Err(Error::Generic(
-                "The `change_policy` can be set only if the wallet has a change_descriptor".into(),
-            ));
-        }
-
-        let (available_utxos, use_all_utxos) = self.get_available_utxos(
-            builder.change_policy,
-            &builder.utxos,
-            &builder.unspendable,
-            builder.send_all,
-        )?;
-        let coin_selection::CoinSelectionResult {
-            txin,
-            selected_amount,
-            mut fee_amount,
-        } = builder.coin_selection.coin_select(
-            available_utxos,
-            use_all_utxos,
-            fee_rate,
-            outgoing,
-            input_witness_weight,
-            fee_amount,
-        )?;
-        let (mut txin, prev_script_pubkeys): (Vec<_>, Vec<_>) = txin.into_iter().unzip();
-        // map that allows us to lookup the prev_script_pubkey for a given previous_output
-        let prev_script_pubkeys = txin
-            .iter()
-            .zip(prev_script_pubkeys.into_iter())
-            .map(|(txin, script)| (txin.previous_output, script))
-            .collect::<HashMap<_, _>>();
-
-        txin.iter_mut().for_each(|i| i.sequence = n_sequence);
-        tx.input = txin;
-
-        // prepare the change output
-        let change_output = match builder.send_all {
-            true => None,
-            false => {
-                let change_script = self.get_change_address()?;
-                let change_output = TxOut {
-                    script_pubkey: change_script,
-                    value: 0,
-                };
-
-                // take the change into account for fees
-                fee_amount += calc_fee_bytes(serialize(&change_output).len() * 4);
-                Some(change_output)
-            }
-        };
-
-        let mut fee_amount = fee_amount.ceil() as u64;
-        let change_val = selected_amount - outgoing - fee_amount;
-        if !builder.send_all && !change_val.is_dust() {
-            let mut change_output = change_output.unwrap();
-            change_output.value = change_val;
-            received += change_val;
-
-            tx.output.push(change_output);
-        } else if builder.send_all && !change_val.is_dust() {
-            // there's only one output, send everything to it
-            tx.output[0].value = change_val;
-
-            // send_all to our address
-            if self.is_mine(&tx.output[0].script_pubkey)? {
-                received = change_val;
-            }
-        } else if !builder.send_all && change_val.is_dust() {
-            // skip the change output because it's dust, this adds up to the fees
-            fee_amount += change_val;
-        } else if builder.send_all {
-            // send_all but the only output would be below dust limit
-            return Err(Error::InsufficientFunds); // TODO: or OutputBelowDustLimit?
-        }
-
-        // sort input/outputs according to the chosen algorithm
-        builder.ordering.sort_tx(&mut tx);
-
-        let txid = tx.txid();
-        let psbt = self.complete_transaction(tx, prev_script_pubkeys, builder)?;
-
-        let transaction_details = TransactionDetails {
-            transaction: None,
-            txid,
-            timestamp: time::get_timestamp(),
-            received,
-            sent: selected_amount,
-            fees: fee_amount,
-            height: None,
-        };
-
-        Ok((psbt, transaction_details))
-    }
-
-    /// Bump the fee of a transaction following the options specified in the `builder`
-    ///
-    /// Return an error if the transaction is already confirmed or doesn't explicitly signal RBF.
-    ///
-    /// **NOTE**: if the original transaction was made with [`TxBuilder::send_all`], the same
-    /// option must be enabled when bumping its fees to correctly reduce the only output's value to
-    /// increase the fees.
-    ///
-    /// ## Example
-    ///
-    /// ```no_run
-    /// # use std::str::FromStr;
-    /// # use bitcoin::*;
-    /// # use magical::*;
-    /// # use magical::database::*;
-    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
-    /// let txid = Txid::from_str("faff0a466b70f5d5f92bd757a92c1371d4838bdd5bc53a06764e2488e51ce8f8").unwrap();
-    /// let (psbt, details) = wallet.bump_fee(
-    ///     &txid,
-    ///     TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(5.0)),
-    /// )?;
-    /// // sign and broadcast ...
-    /// # Ok::<(), magical::Error>(())
-    /// ```
-    // TODO: support for merging multiple transactions while bumping the fees
-    // TODO: option to force addition of an extra output? seems bad for privacy to update the
-    // change
-    pub fn bump_fee<Cs: coin_selection::CoinSelectionAlgorithm>(
-        &self,
-        txid: &Txid,
-        builder: TxBuilder<Cs>,
-    ) -> Result<(PSBT, TransactionDetails), Error> {
-        let mut details = match self.database.borrow().get_tx(&txid, true)? {
-            None => return Err(Error::TransactionNotFound),
-            Some(tx) if tx.transaction.is_none() => return Err(Error::TransactionNotFound),
-            Some(tx) if tx.height.is_some() => return Err(Error::TransactionConfirmed),
-            Some(tx) => tx,
-        };
-        let mut tx = details.transaction.take().unwrap();
-        if !tx.input.iter().any(|txin| txin.sequence <= 0xFFFFFFFD) {
-            return Err(Error::IrreplaceableTransaction);
-        }
-
-        // the new tx must "pay for its bandwidth"
-        let vbytes = tx.get_weight() as f32 / 4.0;
-        let required_feerate = FeeRate::from_sat_per_vb(details.fees as f32 / vbytes + 1.0);
-        let new_feerate = builder.fee_rate.unwrap_or_default();
-
-        if new_feerate < required_feerate {
-            return Err(Error::FeeRateTooLow {
-                required: required_feerate,
-            });
-        }
-        let mut fee_difference =
-            (new_feerate.as_sat_vb() * tx.get_weight() as f32 / 4.0).ceil() as u64 - details.fees;
-
-        if builder.send_all && tx.output.len() > 1 {
-            return Err(Error::SendAllMultipleOutputs);
-        }
-
-        // find the index of the output that we can update. either the change or the only one if
-        // it's `send_all`
-        let updatable_output = if builder.send_all {
-            0
-        } else {
-            let mut change_output = None;
-            for (index, txout) in tx.output.iter().enumerate() {
-                // look for an output that we know and that has the right ScriptType. We use
-                // `get_deget_descriptor_for` to find what's the ScriptType for `Internal`
-                // addresses really is, because if there's no change_descriptor it's actually equal
-                // to "External"
-                let (_, change_type) = self.get_descriptor_for_script_type(ScriptType::Internal);
-                match self
-                    .database
-                    .borrow()
-                    .get_path_from_script_pubkey(&txout.script_pubkey)?
-                {
-                    Some((script_type, _)) if script_type == change_type => {
-                        change_output = Some(index);
-                        break;
-                    }
-                    _ => {}
-                }
-            }
-
-            // we need a change output, add one here and take into account the extra fees for it
-            if change_output.is_none() {
-                let change_script = self.get_change_address()?;
-                let change_txout = TxOut {
-                    script_pubkey: change_script,
-                    value: 0,
-                };
-                fee_difference +=
-                    (serialize(&change_txout).len() as f32 * new_feerate.as_sat_vb()).ceil() as u64;
-                tx.output.push(change_txout);
-
-                change_output = Some(tx.output.len() - 1);
-            }
-
-            change_output.unwrap()
-        };
-
-        // if `builder.utxos` is Some(_) we have to add inputs and we skip down to the last branch
-        match tx.output[updatable_output]
-            .value
-            .checked_sub(fee_difference)
-        {
-            Some(new_value) if !new_value.is_dust() && builder.utxos.is_none() => {
-                // try to reduce the "updatable output" amount
-                tx.output[updatable_output].value = new_value;
-                if self.is_mine(&tx.output[updatable_output].script_pubkey)? {
-                    details.received -= fee_difference;
-                }
-
-                details.fees += fee_difference;
-            }
-            _ if builder.send_all && builder.utxos.is_none() => {
-                // if the tx is "send_all" it doesn't make sense to either remove the only output
-                // or add more inputs
-                return Err(Error::InsufficientFunds);
-            }
-            _ => {
-                // initially always remove the change output
-                let mut removed_change_output = tx.output.remove(updatable_output);
-                if self.is_mine(&removed_change_output.script_pubkey)? {
-                    details.received -= removed_change_output.value;
-                }
-
-                // we want to add more inputs if:
-                // - builder.utxos tells us to do so
-                // - the removed change value is lower than the fee_difference we want to add
-                let needs_more_inputs =
-                    builder.utxos.is_some() || removed_change_output.value <= fee_difference;
-                let added_amount = if needs_more_inputs {
-                    // TODO: use the right weight instead of the maximum, and only fall-back to it if the
-                    // script is unknown in the database
-                    let input_witness_weight = std::cmp::max(
-                        self.get_descriptor_for_script_type(ScriptType::Internal)
-                            .0
-                            .max_satisfaction_weight(),
-                        self.get_descriptor_for_script_type(ScriptType::External)
-                            .0
-                            .max_satisfaction_weight(),
-                    );
-
-                    let (available_utxos, use_all_utxos) = self.get_available_utxos(
-                        builder.change_policy,
-                        &builder.utxos,
-                        &builder.unspendable,
-                        false,
-                    )?;
-                    let available_utxos = rbf::filter_available(
-                        self.database.borrow().deref(),
-                        available_utxos.into_iter(),
-                    )?;
-                    let coin_selection::CoinSelectionResult {
-                        txin,
-                        selected_amount,
-                        fee_amount,
-                    } = builder.coin_selection.coin_select(
-                        available_utxos,
-                        use_all_utxos,
-                        new_feerate,
-                        fee_difference
-                            .checked_sub(removed_change_output.value)
-                            .unwrap_or(0),
-                        input_witness_weight,
-                        0.0,
-                    )?;
-                    fee_difference += fee_amount.ceil() as u64;
-
-                    // add the new inputs
-                    let (mut txin, _): (Vec<_>, Vec<_>) = txin.into_iter().unzip();
-
-                    // TODO: use tx_builder.sequence ??
-                    // copy the n_sequence from the inputs that were already in the transaction
-                    txin.iter_mut()
-                        .for_each(|i| i.sequence = tx.input[0].sequence);
-                    tx.input.extend_from_slice(&mut txin);
-
-                    details.sent += selected_amount;
-                    selected_amount
-                } else {
-                    // otherwise just remove the output and add 0 new coins
-                    0
-                };
-
-                match (removed_change_output.value + added_amount).checked_sub(fee_difference) {
-                    None => return Err(Error::InsufficientFunds),
-                    Some(new_value) if new_value.is_dust() => {
-                        // the change would be dust, add that to fees
-                        details.fees += fee_difference + new_value;
-                    }
-                    Some(new_value) => {
-                        // add the change back
-                        removed_change_output.value = new_value;
-                        tx.output.push(removed_change_output);
-
-                        details.received += new_value;
-                        details.fees += fee_difference;
-                    }
-                }
-            }
-        };
-
-        // clear witnesses
-        for input in &mut tx.input {
-            input.script_sig = Script::default();
-            input.witness = vec![];
-        }
-
-        // sort input/outputs according to the chosen algorithm
-        builder.ordering.sort_tx(&mut tx);
-
-        // TODO: check that we are not replacing more than 100 txs from mempool
-
-        details.txid = tx.txid();
-        details.timestamp = time::get_timestamp();
-
-        let prev_script_pubkeys = tx
-            .input
-            .iter()
-            .map(|txin| {
-                Ok((
-                    txin.previous_output.clone(),
-                    self.database
-                        .borrow()
-                        .get_previous_output(&txin.previous_output)?,
-                ))
-            })
-            .collect::<Result<Vec<_>, Error>>()?
-            .into_iter()
-            .filter_map(|(outpoint, txout)| match txout {
-                Some(txout) => Some((outpoint, txout.script_pubkey)),
-                None => None,
-            })
-            .collect();
-        let psbt = self.complete_transaction(tx, prev_script_pubkeys, builder)?;
-
-        Ok((psbt, details))
-    }
-
-    /// Sign a transaction with all the wallet's signers, in the order specified by every signer's
-    /// [`SignerOrdering`]
-    ///
-    /// ## Example
-    ///
-    /// ```no_run
-    /// # use std::str::FromStr;
-    /// # use bitcoin::*;
-    /// # use magical::*;
-    /// # use magical::database::*;
-    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
-    /// # let (psbt, _) = wallet.create_tx(TxBuilder::new())?;
-    /// let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
-    /// # Ok::<(), magical::Error>(())
-    pub fn sign(&self, mut psbt: PSBT, assume_height: Option<u32>) -> Result<(PSBT, bool), Error> {
-        // this helps us doing our job later
-        self.add_input_hd_keypaths(&mut psbt)?;
-
-        for signer in self
-            .signers
-            .signers()
-            .iter()
-            .chain(self.change_signers.signers().iter())
-        {
-            if signer.sign_whole_tx() {
-                signer.sign(&mut psbt, None)?;
-            } else {
-                for index in 0..psbt.inputs.len() {
-                    signer.sign(&mut psbt, Some(index))?;
-                }
-            }
-        }
-
-        // attempt to finalize
-        self.finalize_psbt(psbt, assume_height)
-    }
-
-    /// Return the spending policies for the wallet's descriptor
-    pub fn policies(&self, script_type: ScriptType) -> Result<Option<Policy>, Error> {
-        match (script_type, self.change_descriptor.as_ref()) {
-            (ScriptType::External, _) => {
-                Ok(self.descriptor.extract_policy(Arc::clone(&self.signers))?)
-            }
-            (ScriptType::Internal, None) => Ok(None),
-            (ScriptType::Internal, Some(desc)) => {
-                Ok(desc.extract_policy(Arc::clone(&self.change_signers))?)
-            }
-        }
-    }
-
-    /// Return the "public" version of the wallet's descriptor, meaning a new descriptor that has
-    /// the same structure but with every secret key removed
-    ///
-    /// This can be used to build a watch-only version of a wallet
-    pub fn public_descriptor(
-        &self,
-        script_type: ScriptType,
-    ) -> Result<Option<ExtendedDescriptor>, Error> {
-        match (script_type, self.change_descriptor.as_ref()) {
-            (ScriptType::External, _) => Ok(Some(self.descriptor.clone())),
-            (ScriptType::Internal, None) => Ok(None),
-            (ScriptType::Internal, Some(desc)) => Ok(Some(desc.clone())),
-        }
-    }
-
-    /// Try to finalize a PSBT
-    pub fn finalize_psbt(
-        &self,
-        mut psbt: PSBT,
-        assume_height: Option<u32>,
-    ) -> Result<(PSBT, bool), Error> {
-        let mut tx = psbt.global.unsigned_tx.clone();
-
-        for (n, (input, psbt_input)) in tx.input.iter_mut().zip(psbt.inputs.iter()).enumerate() {
-            // if the height is None in the database it means it's still unconfirmed, so consider
-            // that as a very high value
-            let create_height = self
-                .database
-                .borrow()
-                .get_tx(&input.previous_output.txid, false)?
-                .and_then(|tx| Some(tx.height.unwrap_or(std::u32::MAX)));
-            let current_height = assume_height.or(self.current_height);
-
-            debug!(
-                "Input #{} - {}, using `create_height` = {:?}, `current_height` = {:?}",
-                n, input.previous_output, create_height, current_height
-            );
-
-            // - Try to derive the descriptor by looking at the txout. If it's in our database, we
-            //   know exactly which `script_type` to use, and which derivation index it is
-            // - If that fails, try to derive it by looking at the psbt input: the complete logic
-            //   is in `src/descriptor/mod.rs`, but it will basically look at `hd_keypaths`,
-            //   `redeem_script` and `witness_script` to determine the right derivation
-            // - If that also fails, it will try it on the internal descriptor, if present
-            let desc = if let Some(desc) = psbt
-                .get_utxo_for(n)
-                .map(|txout| self.get_descriptor_for_txout(&txout))
-                .transpose()?
-                .flatten()
-            {
-                desc
-            } else if let Some(desc) = self
-                .descriptor
-                .derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n))
-            {
-                desc
-            } else if let Some(desc) = self
-                .change_descriptor
-                .as_ref()
-                .and_then(|desc| desc.derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n)))
-            {
-                desc
-            } else {
-                debug!("Couldn't find the right derived descriptor for input {}", n);
-                return Ok((psbt, false));
-            };
-
-            match desc.satisfy(
-                input,
-                (
-                    psbt_input.clone(),
-                    After::new(current_height, false),
-                    Older::new(current_height, create_height, false),
-                ),
-            ) {
-                Ok(_) => continue,
-                Err(e) => {
-                    debug!("satisfy error {:?} for input {}", e, n);
-                    return Ok((psbt, false));
-                }
-            }
-        }
-
-        // consume tx to extract its input's script_sig and witnesses and move them into the psbt
-        for (input, psbt_input) in tx.input.into_iter().zip(psbt.inputs.iter_mut()) {
-            psbt_input.final_script_sig = Some(input.script_sig);
-            psbt_input.final_script_witness = Some(input.witness);
-        }
-
-        Ok((psbt, true))
-    }
-
-    // Internals
-
-    fn get_descriptor_for_script_type(
-        &self,
-        script_type: ScriptType,
-    ) -> (&ExtendedDescriptor, ScriptType) {
-        let desc = match script_type {
-            ScriptType::Internal if self.change_descriptor.is_some() => (
-                self.change_descriptor.as_ref().unwrap(),
-                ScriptType::Internal,
-            ),
-            _ => (&self.descriptor, ScriptType::External),
-        };
-
-        desc
-    }
-
-    fn get_descriptor_for_txout(&self, txout: &TxOut) -> Result<Option<ExtendedDescriptor>, Error> {
-        Ok(self
-            .database
-            .borrow()
-            .get_path_from_script_pubkey(&txout.script_pubkey)?
-            .map(|(script_type, child)| (self.get_descriptor_for_script_type(script_type).0, child))
-            .map(|(desc, child)| desc.derive(&[ChildNumber::from_normal_idx(child).unwrap()])))
-    }
-
-    fn get_change_address(&self) -> Result<Script, Error> {
-        let (desc, script_type) = self.get_descriptor_for_script_type(ScriptType::Internal);
-        let index = self.fetch_and_increment_index(script_type)?;
-
-        Ok(desc
-            .derive(&[ChildNumber::from_normal_idx(index).unwrap()])
-            .script_pubkey())
-    }
-
-    fn fetch_and_increment_index(&self, script_type: ScriptType) -> Result<u32, Error> {
-        let (descriptor, script_type) = self.get_descriptor_for_script_type(script_type);
-        let index = match descriptor.is_fixed() {
-            true => 0,
-            false => self
-                .database
-                .borrow_mut()
-                .increment_last_index(script_type)?,
-        };
-
-        if self
-            .database
-            .borrow()
-            .get_script_pubkey_from_path(script_type, index)?
-            .is_none()
-        {
-            self.cache_addresses(script_type, index, CACHE_ADDR_BATCH_SIZE)?;
-        }
-
-        let hd_keypaths = descriptor.get_hd_keypaths(index)?;
-        let script = descriptor
-            .derive(&[ChildNumber::from_normal_idx(index).unwrap()])
-            .script_pubkey();
-        for validator in &self.address_validators {
-            validator.validate(script_type, &hd_keypaths, &script)?;
-        }
-
-        Ok(index)
-    }
-
-    fn cache_addresses(
-        &self,
-        script_type: ScriptType,
-        from: u32,
-        mut count: u32,
-    ) -> Result<(), Error> {
-        let (descriptor, script_type) = self.get_descriptor_for_script_type(script_type);
-        if descriptor.is_fixed() {
-            if from > 0 {
-                return Ok(());
-            }
-
-            count = 1;
-        }
-
-        let mut address_batch = self.database.borrow().begin_batch();
-
-        let start_time = time::Instant::new();
-        for i in from..(from + count) {
-            address_batch.set_script_pubkey(
-                &descriptor
-                    .derive(&[ChildNumber::from_normal_idx(i).unwrap()])
-                    .script_pubkey(),
-                script_type,
-                i,
-            )?;
-        }
-
-        info!(
-            "Derivation of {} addresses from {} took {} ms",
-            count,
-            from,
-            start_time.elapsed().as_millis()
-        );
-
-        self.database.borrow_mut().commit_batch(address_batch)?;
-
-        Ok(())
-    }
-
-    fn get_available_utxos(
-        &self,
-        change_policy: tx_builder::ChangeSpendPolicy,
-        utxo: &Option<Vec<OutPoint>>,
-        unspendable: &Option<Vec<OutPoint>>,
-        send_all: bool,
-    ) -> Result<(Vec<UTXO>, bool), Error> {
-        let unspendable_set = match unspendable {
-            None => HashSet::new(),
-            Some(vec) => vec.into_iter().collect(),
-        };
-
-        match utxo {
-            // with manual coin selection we always want to spend all the selected utxos, no matter
-            // what (even if they are marked as unspendable)
-            Some(raw_utxos) => {
-                let full_utxos = raw_utxos
-                    .iter()
-                    .map(|u| self.database.borrow().get_utxo(&u))
-                    .collect::<Result<Vec<_>, _>>()?;
-                if !full_utxos.iter().all(|u| u.is_some()) {
-                    return Err(Error::UnknownUTXO);
-                }
-
-                Ok((full_utxos.into_iter().map(|x| x.unwrap()).collect(), true))
-            }
-            // otherwise limit ourselves to the spendable utxos for the selected policy, and the `send_all` setting
-            None => {
-                let utxos = self.list_unspent()?.into_iter();
-                let utxos = change_policy.filter_utxos(utxos).into_iter();
-
-                Ok((
-                    utxos
-                        .filter(|u| !unspendable_set.contains(&u.outpoint))
-                        .collect(),
-                    send_all,
-                ))
-            }
-        }
-    }
-
-    fn complete_transaction<Cs: coin_selection::CoinSelectionAlgorithm>(
-        &self,
-        tx: Transaction,
-        prev_script_pubkeys: HashMap<OutPoint, Script>,
-        builder: TxBuilder<Cs>,
-    ) -> Result<PSBT, Error> {
-        let mut psbt = PSBT::from_unsigned_tx(tx)?;
-
-        // add metadata for the inputs
-        for (psbt_input, input) in psbt
-            .inputs
-            .iter_mut()
-            .zip(psbt.global.unsigned_tx.input.iter())
-        {
-            let prev_script = match prev_script_pubkeys.get(&input.previous_output) {
-                Some(prev_script) => prev_script,
-                None => continue,
-            };
-
-            // Add sighash, default is obviously "ALL"
-            psbt_input.sighash_type = builder.sighash.or(Some(SigHashType::All));
-
-            // Try to find the prev_script in our db to figure out if this is internal or external,
-            // and the derivation index
-            let (script_type, child) = match self
-                .database
-                .borrow()
-                .get_path_from_script_pubkey(&prev_script)?
-            {
-                Some(x) => x,
-                None => continue,
-            };
-
-            let (desc, _) = self.get_descriptor_for_script_type(script_type);
-            psbt_input.hd_keypaths = desc.get_hd_keypaths(child)?;
-            let derived_descriptor = desc.derive(&[ChildNumber::from_normal_idx(child).unwrap()]);
-
-            psbt_input.redeem_script = derived_descriptor.psbt_redeem_script();
-            psbt_input.witness_script = derived_descriptor.psbt_witness_script();
-
-            let prev_output = input.previous_output;
-            if let Some(prev_tx) = self.database.borrow().get_raw_tx(&prev_output.txid)? {
-                if derived_descriptor.is_witness() {
-                    psbt_input.witness_utxo =
-                        Some(prev_tx.output[prev_output.vout as usize].clone());
-                }
-                if !derived_descriptor.is_witness() || builder.force_non_witness_utxo {
-                    psbt_input.non_witness_utxo = Some(prev_tx);
-                }
-            }
-        }
-
-        // probably redundant but it doesn't hurt...
-        self.add_input_hd_keypaths(&mut psbt)?;
-
-        // add metadata for the outputs
-        for (psbt_output, tx_output) in psbt
-            .outputs
-            .iter_mut()
-            .zip(psbt.global.unsigned_tx.output.iter())
-        {
-            if let Some((script_type, child)) = self
-                .database
-                .borrow()
-                .get_path_from_script_pubkey(&tx_output.script_pubkey)?
-            {
-                let (desc, _) = self.get_descriptor_for_script_type(script_type);
-                psbt_output.hd_keypaths = desc.get_hd_keypaths(child)?;
-            }
-        }
-
-        Ok(psbt)
-    }
-
-    fn add_input_hd_keypaths(&self, psbt: &mut PSBT) -> Result<(), Error> {
-        let mut input_utxos = Vec::with_capacity(psbt.inputs.len());
-        for n in 0..psbt.inputs.len() {
-            input_utxos.push(psbt.get_utxo_for(n).clone());
-        }
-
-        // try to add hd_keypaths if we've already seen the output
-        for (psbt_input, out) in psbt.inputs.iter_mut().zip(input_utxos.iter()) {
-            if let Some(out) = out {
-                if let Some((script_type, child)) = self
-                    .database
-                    .borrow()
-                    .get_path_from_script_pubkey(&out.script_pubkey)?
-                {
-                    debug!("Found descriptor {:?}/{}", script_type, child);
-
-                    // merge hd_keypaths
-                    let (desc, _) = self.get_descriptor_for_script_type(script_type);
-                    let mut hd_keypaths = desc.get_hd_keypaths(child)?;
-                    psbt_input.hd_keypaths.append(&mut hd_keypaths);
-                }
-            }
-        }
-
-        Ok(())
-    }
-}
-
-impl<B, D> Wallet<B, D>
-where
-    B: OnlineBlockchain,
-    D: BatchDatabase,
-{
-    /// Create a new "online" wallet
-    #[maybe_async]
-    pub fn new(
-        descriptor: &str,
-        change_descriptor: Option<&str>,
-        network: Network,
-        database: D,
-        client: B,
-    ) -> Result<Self, Error> {
-        let mut wallet = Self::new_offline(descriptor, change_descriptor, network, database)?;
-
-        wallet.current_height = Some(maybe_await!(client.get_height())? as u32);
-        wallet.client = client;
-
-        Ok(wallet)
-    }
-
-    /// Sync the internal database with the blockchain
-    #[maybe_async]
-    pub fn sync<P: 'static + Progress>(
-        &self,
-        progress_update: P,
-        max_address_param: Option<u32>,
-    ) -> Result<(), Error> {
-        debug!("Begin sync...");
-
-        let mut run_setup = false;
-
-        let max_address = match self.descriptor.is_fixed() {
-            true => 0,
-            false => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
-        };
-        if self
-            .database
-            .borrow()
-            .get_script_pubkey_from_path(ScriptType::External, max_address)?
-            .is_none()
-        {
-            run_setup = true;
-            self.cache_addresses(ScriptType::External, 0, max_address)?;
-        }
-
-        if let Some(change_descriptor) = &self.change_descriptor {
-            let max_address = match change_descriptor.is_fixed() {
-                true => 0,
-                false => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
-            };
-
-            if self
-                .database
-                .borrow()
-                .get_script_pubkey_from_path(
-                    ScriptType::Internal,
-                    max_address.checked_sub(1).unwrap_or(0),
-                )?
-                .is_none()
-            {
-                run_setup = true;
-                self.cache_addresses(ScriptType::Internal, 0, max_address)?;
-            }
-        }
-
-        // TODO: what if i generate an address first and cache some addresses?
-        // TODO: we should sync if generating an address triggers a new batch to be stored
-        if run_setup {
-            maybe_await!(self.client.setup(
-                None,
-                self.database.borrow_mut().deref_mut(),
-                progress_update,
-            ))
-        } else {
-            maybe_await!(self.client.sync(
-                None,
-                self.database.borrow_mut().deref_mut(),
-                progress_update,
-            ))
-        }
-    }
-
-    /// Return a reference to the internal blockchain client
-    pub fn client(&self) -> &B {
-        &self.client
-    }
-
-    /// Broadcast a transaction to the network
-    #[maybe_async]
-    pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error> {
-        maybe_await!(self.client.broadcast(&tx))?;
-
-        Ok(tx.txid())
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use std::str::FromStr;
-
-    use bitcoin::Network;
-
-    use crate::database::memory::MemoryDatabase;
-    use crate::database::Database;
-    use crate::types::ScriptType;
-
-    use super::*;
-
-    #[test]
-    fn test_cache_addresses_fixed() {
-        let db = MemoryDatabase::new();
-        let wallet: OfflineWallet<_> = Wallet::new_offline(
-            "wpkh(L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6)",
-            None,
-            Network::Testnet,
-            db,
-        )
-        .unwrap();
-
-        assert_eq!(
-            wallet.get_new_address().unwrap().to_string(),
-            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
-        );
-        assert_eq!(
-            wallet.get_new_address().unwrap().to_string(),
-            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
-        );
-
-        assert!(wallet
-            .database
-            .borrow_mut()
-            .get_script_pubkey_from_path(ScriptType::External, 0)
-            .unwrap()
-            .is_some());
-        assert!(wallet
-            .database
-            .borrow_mut()
-            .get_script_pubkey_from_path(ScriptType::Internal, 0)
-            .unwrap()
-            .is_none());
-    }
-
-    #[test]
-    fn test_cache_addresses() {
-        let db = MemoryDatabase::new();
-        let wallet: OfflineWallet<_> = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
-
-        assert_eq!(
-            wallet.get_new_address().unwrap().to_string(),
-            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
-        );
-        assert_eq!(
-            wallet.get_new_address().unwrap().to_string(),
-            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
-        );
-
-        assert!(wallet
-            .database
-            .borrow_mut()
-            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE - 1)
-            .unwrap()
-            .is_some());
-        assert!(wallet
-            .database
-            .borrow_mut()
-            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE)
-            .unwrap()
-            .is_none());
-    }
-
-    #[test]
-    fn test_cache_addresses_refill() {
-        let db = MemoryDatabase::new();
-        let wallet: OfflineWallet<_> = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
-
-        assert_eq!(
-            wallet.get_new_address().unwrap().to_string(),
-            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
-        );
-        assert!(wallet
-            .database
-            .borrow_mut()
-            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE - 1)
-            .unwrap()
-            .is_some());
-
-        for _ in 0..CACHE_ADDR_BATCH_SIZE {
-            wallet.get_new_address().unwrap();
-        }
-
-        assert!(wallet
-            .database
-            .borrow_mut()
-            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE * 2 - 1)
-            .unwrap()
-            .is_some());
-    }
-
-    pub(crate) fn get_test_wpkh() -> &'static str {
-        "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)"
-    }
-
-    pub(crate) fn get_test_single_sig_csv() -> &'static str {
-        // and(pk(Alice),older(6))
-        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),older(6)))"
-    }
-
-    pub(crate) fn get_test_single_sig_cltv() -> &'static str {
-        // and(pk(Alice),after(100000))
-        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100000)))"
-    }
-
-    pub(crate) fn get_funded_wallet(
-        descriptor: &str,
-    ) -> (
-        OfflineWallet<MemoryDatabase>,
-        (String, Option<String>),
-        bitcoin::Txid,
-    ) {
-        let descriptors = testutils!(@descriptors (descriptor));
-        let wallet: OfflineWallet<_> = Wallet::new_offline(
-            &descriptors.0,
-            None,
-            Network::Regtest,
-            MemoryDatabase::new(),
-        )
-        .unwrap();
-
-        let txid = wallet.database.borrow_mut().received_tx(
-            testutils! {
-                @tx ( (@external descriptors, 0) => 50_000 ) (@confirmations 1)
-            },
-            Some(100),
-        );
-
-        (wallet, descriptors, txid)
-    }
-
-    macro_rules! assert_fee_rate {
-        ($tx:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({
-            let mut tx = $tx.clone();
-            $(
-                $( $add_signature )*
-                for txin in &mut tx.input {
-                    txin.witness.push([0x00; 108].to_vec()); // fake signature
-                }
-            )*
-
-            #[allow(unused_mut)]
-            #[allow(unused_assignments)]
-            let mut dust_change = false;
-            $(
-                $( $dust_change )*
-                dust_change = true;
-            )*
-
-            let tx_fee_rate = $fees as f32 / (tx.get_weight() as f32 / 4.0);
-            let fee_rate = $fee_rate.as_sat_vb();
-
-            if !dust_change {
-                assert!((tx_fee_rate - fee_rate).abs() < 0.5, format!("Expected fee rate of {}, the tx has {}", fee_rate, tx_fee_rate));
-            } else {
-                assert!(tx_fee_rate >= fee_rate, format!("Expected fee rate of at least {}, the tx has {}", fee_rate, tx_fee_rate));
-            }
-        });
-    }
-
-    #[test]
-    #[should_panic(expected = "NoAddressees")]
-    fn test_create_tx_empty_recipients() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        wallet
-            .create_tx(TxBuilder::with_recipients(vec![]).version(0))
-            .unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "Invalid version `0`")]
-    fn test_create_tx_version_0() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(0))
-            .unwrap();
-    }
-
-    #[test]
-    #[should_panic(
-        expected = "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
-    )]
-    fn test_create_tx_version_1_csv() {
-        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
-        let addr = wallet.get_new_address().unwrap();
-        wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(1))
-            .unwrap();
-    }
-
-    #[test]
-    fn test_create_tx_custom_version() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(42))
-            .unwrap();
-
-        assert_eq!(psbt.global.unsigned_tx.version, 42);
-    }
-
-    #[test]
-    fn test_create_tx_default_locktime() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(
-                addr.script_pubkey(),
-                25_000,
-            )]))
-            .unwrap();
-
-        assert_eq!(psbt.global.unsigned_tx.lock_time, 0);
-    }
-
-    #[test]
-    fn test_create_tx_default_locktime_cltv() {
-        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(
-                addr.script_pubkey(),
-                25_000,
-            )]))
-            .unwrap();
-
-        assert_eq!(psbt.global.unsigned_tx.lock_time, 100_000);
-    }
-
-    #[test]
-    fn test_create_tx_custom_locktime() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(630_000),
-            )
-            .unwrap();
-
-        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
-    }
-
-    #[test]
-    fn test_create_tx_custom_locktime_compatible_with_cltv() {
-        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(630_000),
-            )
-            .unwrap();
-
-        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
-    }
-
-    #[test]
-    #[should_panic(
-        expected = "TxBuilder requested timelock of `50000`, but at least `100000` is required to spend from this script"
-    )]
-    fn test_create_tx_custom_locktime_incompatible_with_cltv() {
-        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
-        let addr = wallet.get_new_address().unwrap();
-        wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(50000),
-            )
-            .unwrap();
-    }
-
-    #[test]
-    fn test_create_tx_no_rbf_csv() {
-        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(
-                addr.script_pubkey(),
-                25_000,
-            )]))
-            .unwrap();
-
-        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
-    }
-
-    #[test]
-    fn test_create_tx_with_default_rbf_csv() {
-        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
-            )
-            .unwrap();
-
-        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFD);
-    }
-
-    #[test]
-    #[should_panic(
-        expected = "Cannot enable RBF with nSequence `3`, since at least `6` is required to spend with OP_CSV"
-    )]
-    fn test_create_tx_with_custom_rbf_csv() {
-        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
-        let addr = wallet.get_new_address().unwrap();
-        wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
-                    .enable_rbf_with_sequence(3),
-            )
-            .unwrap();
-    }
-
-    #[test]
-    fn test_create_tx_no_rbf_cltv() {
-        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(
-                addr.script_pubkey(),
-                25_000,
-            )]))
-            .unwrap();
-
-        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFE);
-    }
-
-    #[test]
-    #[should_panic(expected = "Cannot enable RBF with a nSequence >= 0xFFFFFFFE")]
-    fn test_create_tx_invalid_rbf_sequence() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
-                    .enable_rbf_with_sequence(0xFFFFFFFE),
-            )
-            .unwrap();
-    }
-
-    #[test]
-    fn test_create_tx_custom_rbf_sequence() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
-                    .enable_rbf_with_sequence(0xDEADBEEF),
-            )
-            .unwrap();
-
-        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xDEADBEEF);
-    }
-
-    #[test]
-    fn test_create_tx_default_sequence() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(
-                addr.script_pubkey(),
-                25_000,
-            )]))
-            .unwrap();
-
-        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
-    }
-
-    #[test]
-    #[should_panic(
-        expected = "The `change_policy` can be set only if the wallet has a change_descriptor"
-    )]
-    fn test_create_tx_change_policy_no_internal() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
-                    .do_not_spend_change(),
-            )
-            .unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "SendAllMultipleOutputs")]
-    fn test_create_tx_send_all_multiple_outputs() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![
-                    (addr.script_pubkey(), 25_000),
-                    (addr.script_pubkey(), 10_000),
-                ])
-                .send_all(),
-            )
-            .unwrap();
-    }
-
-    #[test]
-    fn test_create_tx_send_all() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, details) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
-            .unwrap();
-
-        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
-        assert_eq!(
-            psbt.global.unsigned_tx.output[0].value,
-            50_000 - details.fees
-        );
-    }
-
-    #[test]
-    fn test_create_tx_default_fee_rate() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, details) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
-            .unwrap();
-
-        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::default(), @add_signature);
-    }
-
-    #[test]
-    fn test_create_tx_custom_fee_rate() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, details) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
-                    .fee_rate(FeeRate::from_sat_per_vb(5.0))
-                    .send_all(),
-            )
-            .unwrap();
-
-        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
-    }
-
-    #[test]
-    fn test_create_tx_add_change() {
-        use super::tx_builder::TxOrdering;
-
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, details) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
-                    .ordering(TxOrdering::Untouched),
-            )
-            .unwrap();
-
-        assert_eq!(psbt.global.unsigned_tx.output.len(), 2);
-        assert_eq!(psbt.global.unsigned_tx.output[0].value, 25_000);
-        assert_eq!(
-            psbt.global.unsigned_tx.output[1].value,
-            25_000 - details.fees
-        );
-    }
-
-    #[test]
-    fn test_create_tx_skip_change_dust() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(
-                addr.script_pubkey(),
-                49_800,
-            )]))
-            .unwrap();
-
-        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
-        assert_eq!(psbt.global.unsigned_tx.output[0].value, 49_800);
-    }
-
-    #[test]
-    #[should_panic(expected = "InsufficientFunds")]
-    fn test_create_tx_send_all_dust_amount() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        // very high fee rate, so that the only output would be below dust
-        wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
-                    .send_all()
-                    .fee_rate(crate::FeeRate::from_sat_per_vb(453.0)),
-            )
-            .unwrap();
-    }
-
-    #[test]
-    fn test_create_tx_ordering_respected() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, details) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![
-                    (addr.script_pubkey(), 30_000),
-                    (addr.script_pubkey(), 10_000),
-                ])
-                .ordering(super::tx_builder::TxOrdering::BIP69Lexicographic),
-            )
-            .unwrap();
-
-        assert_eq!(psbt.global.unsigned_tx.output.len(), 3);
-        assert_eq!(
-            psbt.global.unsigned_tx.output[0].value,
-            10_000 - details.fees
-        );
-        assert_eq!(psbt.global.unsigned_tx.output[1].value, 10_000);
-        assert_eq!(psbt.global.unsigned_tx.output[2].value, 30_000);
-    }
-
-    #[test]
-    fn test_create_tx_default_sighash() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(
-                addr.script_pubkey(),
-                30_000,
-            )]))
-            .unwrap();
-
-        assert_eq!(psbt.inputs[0].sighash_type, Some(bitcoin::SigHashType::All));
-    }
-
-    #[test]
-    fn test_create_tx_custom_sighash() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 30_000)])
-                    .sighash(bitcoin::SigHashType::Single),
-            )
-            .unwrap();
-
-        assert_eq!(
-            psbt.inputs[0].sighash_type,
-            Some(bitcoin::SigHashType::Single)
-        );
-    }
-
-    #[test]
-    fn test_create_tx_input_hd_keypaths() {
-        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
-        use std::str::FromStr;
-
-        let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*)");
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
-            .unwrap();
-
-        assert_eq!(psbt.inputs[0].hd_keypaths.len(), 1);
-        assert_eq!(
-            psbt.inputs[0].hd_keypaths.values().nth(0).unwrap(),
-            &(
-                Fingerprint::from_str("d34db33f").unwrap(),
-                DerivationPath::from_str("m/44'/0'/0'/0/0").unwrap()
-            )
-        );
-    }
-
-    #[test]
-    fn test_create_tx_output_hd_keypaths() {
-        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
-        use std::str::FromStr;
-
-        let (wallet, descriptors, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*)");
-        // cache some addresses
-        wallet.get_new_address().unwrap();
-
-        let addr = testutils!(@external descriptors, 5);
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
-            .unwrap();
-
-        assert_eq!(psbt.outputs[0].hd_keypaths.len(), 1);
-        assert_eq!(
-            psbt.outputs[0].hd_keypaths.values().nth(0).unwrap(),
-            &(
-                Fingerprint::from_str("d34db33f").unwrap(),
-                DerivationPath::from_str("m/44'/0'/0'/0/5").unwrap()
-            )
-        );
-    }
-
-    #[test]
-    fn test_create_tx_set_redeem_script_p2sh() {
-        use bitcoin::hashes::hex::FromHex;
-
-        let (wallet, _, _) =
-            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
-            .unwrap();
-
-        assert_eq!(
-            psbt.inputs[0].redeem_script,
-            Some(Script::from(
-                Vec::<u8>::from_hex(
-                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
-                )
-                .unwrap()
-            ))
-        );
-        assert_eq!(psbt.inputs[0].witness_script, None);
-    }
-
-    #[test]
-    fn test_create_tx_set_witness_script_p2wsh() {
-        use bitcoin::hashes::hex::FromHex;
-
-        let (wallet, _, _) =
-            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
-            .unwrap();
-
-        assert_eq!(psbt.inputs[0].redeem_script, None);
-        assert_eq!(
-            psbt.inputs[0].witness_script,
-            Some(Script::from(
-                Vec::<u8>::from_hex(
-                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
-                )
-                .unwrap()
-            ))
-        );
-    }
-
-    #[test]
-    fn test_create_tx_set_redeem_witness_script_p2wsh_p2sh() {
-        use bitcoin::hashes::hex::FromHex;
-
-        let (wallet, _, _) =
-            get_funded_wallet("sh(wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)))");
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
-            .unwrap();
-
-        let script = Script::from(
-            Vec::<u8>::from_hex(
-                "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac",
-            )
-            .unwrap(),
-        );
-
-        assert_eq!(psbt.inputs[0].redeem_script, Some(script.to_v0_p2wsh()));
-        assert_eq!(psbt.inputs[0].witness_script, Some(script));
-    }
-
-    #[test]
-    fn test_create_tx_non_witness_utxo() {
-        let (wallet, _, _) =
-            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
-            .unwrap();
-
-        assert!(psbt.inputs[0].non_witness_utxo.is_some());
-        assert!(psbt.inputs[0].witness_utxo.is_none());
-    }
-
-    #[test]
-    fn test_create_tx_only_witness_utxo() {
-        let (wallet, _, _) =
-            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
-            .unwrap();
-
-        assert!(psbt.inputs[0].non_witness_utxo.is_none());
-        assert!(psbt.inputs[0].witness_utxo.is_some());
-    }
-
-    #[test]
-    fn test_create_tx_both_non_witness_utxo_and_witness_utxo() {
-        let (wallet, _, _) =
-            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
-                    .force_non_witness_utxo()
-                    .send_all(),
-            )
-            .unwrap();
-
-        assert!(psbt.inputs[0].non_witness_utxo.is_some());
-        assert!(psbt.inputs[0].witness_utxo.is_some());
-    }
-
-    #[test]
-    #[should_panic(expected = "IrreplaceableTransaction")]
-    fn test_bump_fee_irreplaceable_tx() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, mut details) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(
-                addr.script_pubkey(),
-                25_000,
-            )]))
-            .unwrap();
-        let tx = psbt.extract_tx();
-        let txid = tx.txid();
-        // skip saving the utxos, we know they can't be used anyways
-        details.transaction = Some(tx);
-        wallet.database.borrow_mut().set_tx(&details).unwrap();
-
-        wallet.bump_fee(&txid, TxBuilder::new()).unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "TransactionConfirmed")]
-    fn test_bump_fee_confirmed_tx() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, mut details) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(
-                addr.script_pubkey(),
-                25_000,
-            )]))
-            .unwrap();
-        let tx = psbt.extract_tx();
-        let txid = tx.txid();
-        // skip saving the utxos, we know they can't be used anyways
-        details.transaction = Some(tx);
-        details.height = Some(42);
-        wallet.database.borrow_mut().set_tx(&details).unwrap();
-
-        wallet.bump_fee(&txid, TxBuilder::new()).unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "FeeRateTooLow")]
-    fn test_bump_fee_low_fee_rate() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, mut details) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
-            )
-            .unwrap();
-        let tx = psbt.extract_tx();
-        let txid = tx.txid();
-        // skip saving the utxos, we know they can't be used anyways
-        details.transaction = Some(tx);
-        wallet.database.borrow_mut().set_tx(&details).unwrap();
-
-        wallet
-            .bump_fee(
-                &txid,
-                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(1.0)),
-            )
-            .unwrap();
-    }
-
-    #[test]
-    fn test_bump_fee_reduce_change() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
-            )
-            .unwrap();
-        let mut tx = psbt.extract_tx();
-        let txid = tx.txid();
-        // skip saving the new utxos, we know they can't be used anyways
-        for txin in &mut tx.input {
-            txin.witness.push([0x00; 108].to_vec()); // fake signature
-            wallet
-                .database
-                .borrow_mut()
-                .del_utxo(&txin.previous_output)
-                .unwrap();
-        }
-        original_details.transaction = Some(tx);
-        wallet
-            .database
-            .borrow_mut()
-            .set_tx(&original_details)
-            .unwrap();
-
-        let (psbt, details) = wallet
-            .bump_fee(
-                &txid,
-                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(2.5)),
-            )
-            .unwrap();
-
-        assert_eq!(details.sent, original_details.sent);
-        assert_eq!(
-            details.received + details.fees,
-            original_details.received + original_details.fees
-        );
-        assert!(details.fees > original_details.fees);
-
-        let tx = &psbt.global.unsigned_tx;
-        assert_eq!(tx.output.len(), 2);
-        assert_eq!(
-            tx.output
-                .iter()
-                .find(|txout| txout.script_pubkey == addr.script_pubkey())
-                .unwrap()
-                .value,
-            25_000
-        );
-        assert_eq!(
-            tx.output
-                .iter()
-                .find(|txout| txout.script_pubkey != addr.script_pubkey())
-                .unwrap()
-                .value,
-            details.received
-        );
-
-        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(2.5), @add_signature);
-    }
-
-    #[test]
-    fn test_bump_fee_reduce_send_all() {
-        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
-        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
-                    .send_all()
-                    .enable_rbf(),
-            )
-            .unwrap();
-        let mut tx = psbt.extract_tx();
-        let txid = tx.txid();
-        for txin in &mut tx.input {
-            txin.witness.push([0x00; 108].to_vec()); // fake signature
-            wallet
-                .database
-                .borrow_mut()
-                .del_utxo(&txin.previous_output)
-                .unwrap();
-        }
-        original_details.transaction = Some(tx);
-        wallet
-            .database
-            .borrow_mut()
-            .set_tx(&original_details)
-            .unwrap();
-
-        let (psbt, details) = wallet
-            .bump_fee(
-                &txid,
-                TxBuilder::new()
-                    .send_all()
-                    .fee_rate(FeeRate::from_sat_per_vb(2.5)),
-            )
-            .unwrap();
-
-        assert_eq!(details.sent, original_details.sent);
-        assert!(details.fees > original_details.fees);
-
-        let tx = &psbt.global.unsigned_tx;
-        assert_eq!(tx.output.len(), 1);
-        assert_eq!(tx.output[0].value + details.fees, details.sent);
-
-        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(2.5), @add_signature);
-    }
-
-    #[test]
-    #[should_panic(expected = "InsufficientFunds")]
-    fn test_bump_fee_remove_send_all_output() {
-        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
-        // receive an extra tx, to make sure that in case of "send_all" we get an error and it
-        // doesn't try to pick more inputs
-        let incoming_txid = wallet.database.borrow_mut().received_tx(
-            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
-            Some(100),
-        );
-        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
-                    .utxos(vec![OutPoint {
-                        txid: incoming_txid,
-                        vout: 0,
-                    }])
-                    .send_all()
-                    .enable_rbf(),
-            )
-            .unwrap();
-        let mut tx = psbt.extract_tx();
-        let txid = tx.txid();
-        for txin in &mut tx.input {
-            txin.witness.push([0x00; 108].to_vec()); // fake signature
-            wallet
-                .database
-                .borrow_mut()
-                .del_utxo(&txin.previous_output)
-                .unwrap();
-        }
-        original_details.transaction = Some(tx);
-        wallet
-            .database
-            .borrow_mut()
-            .set_tx(&original_details)
-            .unwrap();
-        assert_eq!(original_details.sent, 25_000);
-
-        wallet
-            .bump_fee(
-                &txid,
-                TxBuilder::new()
-                    .send_all()
-                    .fee_rate(FeeRate::from_sat_per_vb(225.0)),
-            )
-            .unwrap();
-    }
-
-    #[test]
-    fn test_bump_fee_add_input() {
-        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
-        wallet.database.borrow_mut().received_tx(
-            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
-            Some(100),
-        );
-
-        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
-            )
-            .unwrap();
-        let mut tx = psbt.extract_tx();
-        let txid = tx.txid();
-        // skip saving the new utxos, we know they can't be used anyways
-        for txin in &mut tx.input {
-            txin.witness.push([0x00; 108].to_vec()); // fake signature
-            wallet
-                .database
-                .borrow_mut()
-                .del_utxo(&txin.previous_output)
-                .unwrap();
-        }
-        original_details.transaction = Some(tx);
-        wallet
-            .database
-            .borrow_mut()
-            .set_tx(&original_details)
-            .unwrap();
-
-        let (psbt, details) = wallet
-            .bump_fee(
-                &txid,
-                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(50.0)),
-            )
-            .unwrap();
-
-        assert_eq!(details.sent, original_details.sent + 25_000);
-        assert_eq!(details.fees + details.received, 30_000);
-
-        let tx = &psbt.global.unsigned_tx;
-        assert_eq!(tx.input.len(), 2);
-        assert_eq!(tx.output.len(), 2);
-        assert_eq!(
-            tx.output
-                .iter()
-                .find(|txout| txout.script_pubkey == addr.script_pubkey())
-                .unwrap()
-                .value,
-            45_000
-        );
-        assert_eq!(
-            tx.output
-                .iter()
-                .find(|txout| txout.script_pubkey != addr.script_pubkey())
-                .unwrap()
-                .value,
-            details.received
-        );
-
-        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(50.0), @add_signature);
-    }
-
-    #[test]
-    fn test_bump_fee_no_change_add_input_and_change() {
-        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
-        let incoming_txid = wallet.database.borrow_mut().received_tx(
-            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
-            Some(100),
-        );
-
-        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
-                    .send_all()
-                    .add_utxo(OutPoint {
-                        txid: incoming_txid,
-                        vout: 0,
-                    })
-                    .enable_rbf(),
-            )
-            .unwrap();
-        let mut tx = psbt.extract_tx();
-        let txid = tx.txid();
-        // skip saving the new utxos, we know they can't be used anyways
-        for txin in &mut tx.input {
-            txin.witness.push([0x00; 108].to_vec()); // fake signature
-            wallet
-                .database
-                .borrow_mut()
-                .del_utxo(&txin.previous_output)
-                .unwrap();
-        }
-        original_details.transaction = Some(tx);
-        wallet
-            .database
-            .borrow_mut()
-            .set_tx(&original_details)
-            .unwrap();
-
-        // NOTE: we don't set "send_all" here. so we have a transaction with only one input, but
-        // here we are allowed to add more, and we will also have to add a change
-        let (psbt, details) = wallet
-            .bump_fee(
-                &txid,
-                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(50.0)),
-            )
-            .unwrap();
-
-        let original_send_all_amount = original_details.sent - original_details.fees;
-        assert_eq!(details.sent, original_details.sent + 50_000);
-        assert_eq!(
-            details.received,
-            75_000 - original_send_all_amount - details.fees
-        );
-
-        let tx = &psbt.global.unsigned_tx;
-        assert_eq!(tx.input.len(), 2);
-        assert_eq!(tx.output.len(), 2);
-        assert_eq!(
-            tx.output
-                .iter()
-                .find(|txout| txout.script_pubkey == addr.script_pubkey())
-                .unwrap()
-                .value,
-            original_send_all_amount
-        );
-        assert_eq!(
-            tx.output
-                .iter()
-                .find(|txout| txout.script_pubkey != addr.script_pubkey())
-                .unwrap()
-                .value,
-            75_000 - original_send_all_amount - details.fees
-        );
-
-        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(50.0), @add_signature);
-    }
-
-    #[test]
-    fn test_bump_fee_add_input_change_dust() {
-        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
-        wallet.database.borrow_mut().received_tx(
-            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
-            Some(100),
-        );
-
-        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
-            )
-            .unwrap();
-        let mut tx = psbt.extract_tx();
-        assert_eq!(tx.input.len(), 1);
-        assert_eq!(tx.output.len(), 2);
-        let txid = tx.txid();
-        // skip saving the new utxos, we know they can't be used anyways
-        for txin in &mut tx.input {
-            txin.witness.push([0x00; 108].to_vec()); // fake signature
-            wallet
-                .database
-                .borrow_mut()
-                .del_utxo(&txin.previous_output)
-                .unwrap();
-        }
-        original_details.transaction = Some(tx);
-        wallet
-            .database
-            .borrow_mut()
-            .set_tx(&original_details)
-            .unwrap();
-
-        let (psbt, details) = wallet
-            .bump_fee(
-                &txid,
-                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(140.0)),
-            )
-            .unwrap();
-
-        assert_eq!(original_details.received, 5_000 - original_details.fees);
-
-        assert_eq!(details.sent, original_details.sent + 25_000);
-        assert_eq!(details.fees, 30_000);
-        assert_eq!(details.received, 0);
-
-        let tx = &psbt.global.unsigned_tx;
-        assert_eq!(tx.input.len(), 2);
-        assert_eq!(tx.output.len(), 1);
-        assert_eq!(
-            tx.output
-                .iter()
-                .find(|txout| txout.script_pubkey == addr.script_pubkey())
-                .unwrap()
-                .value,
-            45_000
-        );
-
-        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(140.0), @dust_change, @add_signature);
-    }
-
-    #[test]
-    fn test_bump_fee_force_add_input() {
-        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
-        let incoming_txid = wallet.database.borrow_mut().received_tx(
-            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
-            Some(100),
-        );
-
-        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .create_tx(
-                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
-            )
-            .unwrap();
-        let mut tx = psbt.extract_tx();
-        let txid = tx.txid();
-        // skip saving the new utxos, we know they can't be used anyways
-        for txin in &mut tx.input {
-            txin.witness.push([0x00; 108].to_vec()); // fake signature
-            wallet
-                .database
-                .borrow_mut()
-                .del_utxo(&txin.previous_output)
-                .unwrap();
-        }
-        original_details.transaction = Some(tx);
-        wallet
-            .database
-            .borrow_mut()
-            .set_tx(&original_details)
-            .unwrap();
-
-        // the new fee_rate is low enough that just reducing the change would be fine, but we force
-        // the addition of an extra input with `add_utxo()`
-        let (psbt, details) = wallet
-            .bump_fee(
-                &txid,
-                TxBuilder::new()
-                    .add_utxo(OutPoint {
-                        txid: incoming_txid,
-                        vout: 0,
-                    })
-                    .fee_rate(FeeRate::from_sat_per_vb(5.0)),
-            )
-            .unwrap();
-
-        assert_eq!(details.sent, original_details.sent + 25_000);
-        assert_eq!(details.fees + details.received, 30_000);
-
-        let tx = &psbt.global.unsigned_tx;
-        assert_eq!(tx.input.len(), 2);
-        assert_eq!(tx.output.len(), 2);
-        assert_eq!(
-            tx.output
-                .iter()
-                .find(|txout| txout.script_pubkey == addr.script_pubkey())
-                .unwrap()
-                .value,
-            45_000
-        );
-        assert_eq!(
-            tx.output
-                .iter()
-                .find(|txout| txout.script_pubkey != addr.script_pubkey())
-                .unwrap()
-                .value,
-            details.received
-        );
-
-        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
-    }
-
-    #[test]
-    fn test_sign_single_xprv() {
-        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
-            .unwrap();
-
-        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
-        assert_eq!(finalized, true);
-
-        let extracted = signed_psbt.extract_tx();
-        assert_eq!(extracted.input[0].witness.len(), 2);
-    }
-
-    #[test]
-    fn test_sign_single_wif() {
-        let (wallet, _, _) =
-            get_funded_wallet("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)");
-        let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
-            .unwrap();
-
-        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
-        assert_eq!(finalized, true);
-
-        let extracted = signed_psbt.extract_tx();
-        assert_eq!(extracted.input[0].witness.len(), 2);
-    }
-
-    #[test]
-    fn test_sign_single_xprv_no_hd_keypaths() {
-        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
-        let addr = wallet.get_new_address().unwrap();
-        let (mut psbt, _) = wallet
-            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
-            .unwrap();
-
-        psbt.inputs[0].hd_keypaths.clear();
-        assert_eq!(psbt.inputs[0].hd_keypaths.len(), 0);
-
-        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
-        assert_eq!(finalized, true);
-
-        let extracted = signed_psbt.extract_tx();
-        assert_eq!(extracted.input[0].witness.len(), 2);
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/rbf.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/rbf.rs.html deleted file mode 100644 index 4110d670cf..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/rbf.rs.html +++ /dev/null @@ -1,257 +0,0 @@ -rbf.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-use crate::database::Database;
-use crate::error::Error;
-use crate::types::*;
-
-/// Filters unspent utxos
-pub(super) fn filter_available<I: Iterator<Item = UTXO>, D: Database>(
-    database: &D,
-    iter: I,
-) -> Result<Vec<UTXO>, Error> {
-    Ok(iter
-        .map(|utxo| {
-            Ok(match database.get_tx(&utxo.outpoint.txid, true)? {
-                None => None,
-                Some(tx) if tx.height.is_none() => None,
-                Some(_) => Some(utxo),
-            })
-        })
-        .collect::<Result<Vec<_>, Error>>()?
-        .into_iter()
-        .filter_map(|x| x)
-        .collect())
-}
-
-#[cfg(test)]
-mod test {
-    use std::str::FromStr;
-
-    use bitcoin::{OutPoint, Transaction, TxIn, TxOut, Txid};
-
-    use super::*;
-    use crate::database::{BatchOperations, MemoryDatabase};
-
-    fn add_transaction(
-        database: &mut MemoryDatabase,
-        spend: Vec<OutPoint>,
-        outputs: Vec<u64>,
-    ) -> Txid {
-        let tx = Transaction {
-            version: 1,
-            lock_time: 0,
-            input: spend
-                .iter()
-                .cloned()
-                .map(|previous_output| TxIn {
-                    previous_output,
-                    ..Default::default()
-                })
-                .collect(),
-            output: outputs
-                .iter()
-                .cloned()
-                .map(|value| TxOut {
-                    value,
-                    ..Default::default()
-                })
-                .collect(),
-        };
-        let txid = tx.txid();
-
-        for input in &spend {
-            database.del_utxo(input).unwrap();
-        }
-        for vout in 0..outputs.len() {
-            database
-                .set_utxo(&UTXO {
-                    txout: tx.output[vout].clone(),
-                    outpoint: OutPoint {
-                        txid,
-                        vout: vout as u32,
-                    },
-                    is_internal: true,
-                })
-                .unwrap();
-        }
-        database
-            .set_tx(&TransactionDetails {
-                txid,
-                transaction: Some(tx),
-                height: None,
-                ..Default::default()
-            })
-            .unwrap();
-
-        txid
-    }
-
-    #[test]
-    fn test_filter_available() {
-        let mut database = MemoryDatabase::new();
-        add_transaction(
-            &mut database,
-            vec![OutPoint::from_str(
-                "aad194c72fd5cfd16d23da9462930ca91e35df1cfee05242b62f4034f50c3d41:5",
-            )
-            .unwrap()],
-            vec![50_000],
-        );
-
-        let filtered =
-            filter_available(&database, database.iter_utxos().unwrap().into_iter()).unwrap();
-        assert_eq!(filtered, &[]);
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/signer.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/signer.rs.html deleted file mode 100644 index 7461c0ac23..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/signer.rs.html +++ /dev/null @@ -1,1029 +0,0 @@ -signer.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-397
-398
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-409
-410
-411
-412
-413
-414
-415
-416
-417
-418
-419
-420
-421
-422
-423
-424
-425
-426
-427
-428
-429
-430
-431
-432
-433
-434
-435
-436
-437
-438
-439
-440
-441
-442
-443
-444
-445
-446
-447
-448
-449
-450
-451
-452
-453
-454
-455
-456
-457
-458
-459
-460
-461
-462
-463
-464
-465
-466
-467
-468
-469
-470
-471
-472
-473
-474
-475
-476
-477
-478
-479
-480
-481
-482
-483
-484
-485
-486
-487
-488
-489
-490
-491
-492
-493
-494
-495
-496
-497
-498
-499
-500
-501
-502
-503
-504
-505
-506
-507
-508
-509
-510
-511
-512
-513
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Generalized signers
-//!
-//! This module provides the ability to add customized signers to a [`Wallet`](super::Wallet)
-//! through the [`Wallet::add_signer`](super::Wallet::add_signer) function.
-//!
-//! ```
-//! # use std::sync::Arc;
-//! # use std::str::FromStr;
-//! # use bitcoin::*;
-//! # use bitcoin::util::psbt;
-//! # use bitcoin::util::bip32::Fingerprint;
-//! # use magical::signer::*;
-//! # use magical::database::*;
-//! # use magical::*;
-//! # #[derive(Debug)]
-//! # struct CustomHSM;
-//! # impl CustomHSM {
-//! #     fn sign_input(&self, _psbt: &mut psbt::PartiallySignedTransaction, _input: usize) -> Result<(), SignerError> {
-//! #         Ok(())
-//! #     }
-//! #     fn connect() -> Self {
-//! #         CustomHSM
-//! #     }
-//! # }
-//! #[derive(Debug)]
-//! struct CustomSigner {
-//!     device: CustomHSM,
-//! }
-//!
-//! impl CustomSigner {
-//!     fn connect() -> Self {
-//!         CustomSigner { device: CustomHSM::connect() }
-//!     }
-//! }
-//!
-//! impl Signer for CustomSigner {
-//!     fn sign(
-//!         &self,
-//!         psbt: &mut psbt::PartiallySignedTransaction,
-//!         input_index: Option<usize>,
-//!     ) -> Result<(), SignerError> {
-//!         let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
-//!         self.device.sign_input(psbt, input_index)?;
-//!
-//!         Ok(())
-//!     }
-//!
-//!     fn sign_whole_tx(&self) -> bool {
-//!         false
-//!     }
-//! }
-//!
-//! let custom_signer = CustomSigner::connect();
-//!
-//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-//! let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
-//! wallet.add_signer(
-//!     ScriptType::External,
-//!     Fingerprint::from_str("e30f11b8").unwrap().into(),
-//!     SignerOrdering(200),
-//!     Arc::new(Box::new(custom_signer))
-//! );
-//!
-//! # Ok::<_, magical::Error>(())
-//! ```
-
-use std::cmp::Ordering;
-use std::collections::BTreeMap;
-use std::fmt;
-use std::ops::Bound::Included;
-use std::sync::Arc;
-
-use bitcoin::blockdata::opcodes;
-use bitcoin::blockdata::script::Builder as ScriptBuilder;
-use bitcoin::hashes::{hash160, Hash};
-use bitcoin::secp256k1::{Message, Secp256k1};
-use bitcoin::util::bip32::{ExtendedPrivKey, Fingerprint};
-use bitcoin::util::{bip143, psbt};
-use bitcoin::{PrivateKey, SigHash, SigHashType};
-
-use miniscript::descriptor::{DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey, KeyMap};
-use miniscript::{Legacy, MiniscriptKey, Segwitv0};
-
-use crate::descriptor::XKeyUtils;
-
-/// Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among
-/// multiple of them
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum SignerId<Pk: MiniscriptKey> {
-    PkHash(<Pk as MiniscriptKey>::Hash),
-    Fingerprint(Fingerprint),
-}
-
-impl From<hash160::Hash> for SignerId<DescriptorPublicKey> {
-    fn from(hash: hash160::Hash) -> SignerId<DescriptorPublicKey> {
-        SignerId::PkHash(hash)
-    }
-}
-
-impl From<Fingerprint> for SignerId<DescriptorPublicKey> {
-    fn from(fing: Fingerprint) -> SignerId<DescriptorPublicKey> {
-        SignerId::Fingerprint(fing)
-    }
-}
-
-/// Signing error
-#[derive(Debug, PartialEq, Eq, Clone)]
-pub enum SignerError {
-    /// The private key is missing for the required public key
-    MissingKey,
-    /// The user canceled the operation
-    UserCanceled,
-    /// The sighash is missing in the PSBT input
-    MissingSighash,
-    /// Input index is out of range
-    InputIndexOutOfRange,
-    /// The `non_witness_utxo` field of the transaction is required to sign this input
-    MissingNonWitnessUtxo,
-    /// The `non_witness_utxo` specified is invalid
-    InvalidNonWitnessUtxo,
-    /// The `witness_utxo` field of the transaction is required to sign this input
-    MissingWitnessUtxo,
-    /// The `witness_script` field of the transaction is requied to sign this input
-    MissingWitnessScript,
-    /// The fingerprint and derivation path are missing from the psbt input
-    MissingHDKeypath,
-}
-
-impl fmt::Display for SignerError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}", self)
-    }
-}
-
-impl std::error::Error for SignerError {}
-
-/// Trait for signers
-///
-/// This trait can be implemented to provide customized signers to the wallet. For an example see
-/// [`this module`](crate::wallet::signer)'s documentation.
-pub trait Signer: fmt::Debug {
-    /// Sign a PSBT
-    ///
-    /// The `input_index` argument is only provided if the wallet doesn't declare to sign the whole
-    /// transaction in one go (see [`Signer::sign_whole_tx`]). Otherwise its value is `None` and
-    /// can be ignored.
-    fn sign(
-        &self,
-        psbt: &mut psbt::PartiallySignedTransaction,
-        input_index: Option<usize>,
-    ) -> Result<(), SignerError>;
-
-    /// Return whether or not the signer signs the whole transaction in one go instead of every
-    /// input individually
-    fn sign_whole_tx(&self) -> bool;
-
-    /// Return the secret key for the signer
-    ///
-    /// This is used internally to reconstruct the original descriptor that may contain secrets.
-    /// External signers that are meant to keep key isolated should just return `None` here (which
-    /// is the default for this method, if not overridden).
-    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
-        None
-    }
-}
-
-impl Signer for DescriptorXKey<ExtendedPrivKey> {
-    fn sign(
-        &self,
-        psbt: &mut psbt::PartiallySignedTransaction,
-        input_index: Option<usize>,
-    ) -> Result<(), SignerError> {
-        let input_index = input_index.unwrap();
-        if input_index >= psbt.inputs.len() {
-            return Err(SignerError::InputIndexOutOfRange);
-        }
-
-        let deriv_path = match psbt.inputs[input_index]
-            .hd_keypaths
-            .iter()
-            .filter_map(|(_, &(fingerprint, ref path))| self.matches(fingerprint.clone(), &path))
-            .next()
-        {
-            Some(deriv_path) => deriv_path,
-            None => return Ok(()), // TODO: should report an error maybe?
-        };
-
-        let ctx = Secp256k1::signing_only();
-
-        let derived_key = self.xkey.derive_priv(&ctx, &deriv_path).unwrap();
-        derived_key.private_key.sign(psbt, Some(input_index))
-    }
-
-    fn sign_whole_tx(&self) -> bool {
-        false
-    }
-
-    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
-        Some(DescriptorSecretKey::XPrv(self.clone()))
-    }
-}
-
-impl Signer for PrivateKey {
-    fn sign(
-        &self,
-        psbt: &mut psbt::PartiallySignedTransaction,
-        input_index: Option<usize>,
-    ) -> Result<(), SignerError> {
-        let input_index = input_index.unwrap();
-        if input_index >= psbt.inputs.len() {
-            return Err(SignerError::InputIndexOutOfRange);
-        }
-
-        let ctx = Secp256k1::signing_only();
-
-        let pubkey = self.public_key(&ctx);
-        if psbt.inputs[input_index].partial_sigs.contains_key(&pubkey) {
-            return Ok(());
-        }
-
-        // FIXME: use the presence of `witness_utxo` as an indication that we should make a bip143
-        // sig. Does this make sense? Should we add an extra argument to explicitly swith between
-        // these? The original idea was to declare sign() as sign<Ctx: ScriptContex>() and use Ctx,
-        // but that violates the rules for trait-objects, so we can't do it.
-        let (hash, sighash) = match psbt.inputs[input_index].witness_utxo {
-            Some(_) => Segwitv0::sighash(psbt, input_index)?,
-            None => Legacy::sighash(psbt, input_index)?,
-        };
-
-        let signature = ctx.sign(
-            &Message::from_slice(&hash.into_inner()[..]).unwrap(),
-            &self.key,
-        );
-
-        let mut final_signature = Vec::with_capacity(75);
-        final_signature.extend_from_slice(&signature.serialize_der());
-        final_signature.push(sighash.as_u32() as u8);
-
-        psbt.inputs[input_index]
-            .partial_sigs
-            .insert(pubkey, final_signature);
-
-        Ok(())
-    }
-
-    fn sign_whole_tx(&self) -> bool {
-        false
-    }
-
-    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
-        Some(DescriptorSecretKey::PrivKey(self.clone()))
-    }
-}
-
-/// Defines the order in which signers are called
-///
-/// The default value is `100`. Signers with an ordering above that will be called later,
-/// and they will thus see the partial signatures added to the transaction once they get to sign
-/// themselves.
-#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)]
-pub struct SignerOrdering(pub usize);
-
-impl std::default::Default for SignerOrdering {
-    fn default() -> Self {
-        SignerOrdering(100)
-    }
-}
-
-#[derive(Debug, Clone)]
-struct SignersContainerKey<Pk: MiniscriptKey> {
-    id: SignerId<Pk>,
-    ordering: SignerOrdering,
-}
-
-impl<Pk: MiniscriptKey> From<(SignerId<Pk>, SignerOrdering)> for SignersContainerKey<Pk> {
-    fn from(tuple: (SignerId<Pk>, SignerOrdering)) -> Self {
-        SignersContainerKey {
-            id: tuple.0,
-            ordering: tuple.1,
-        }
-    }
-}
-
-/// Container for multiple signers
-#[derive(Debug, Default, Clone)]
-pub struct SignersContainer<Pk: MiniscriptKey>(
-    BTreeMap<SignersContainerKey<Pk>, Arc<Box<dyn Signer>>>,
-);
-
-impl SignersContainer<DescriptorPublicKey> {
-    pub fn as_key_map(&self) -> KeyMap {
-        self.0
-            .values()
-            .filter_map(|signer| signer.descriptor_secret_key())
-            .filter_map(|secret| secret.as_public().ok().map(|public| (public, secret)))
-            .collect()
-    }
-}
-
-impl From<KeyMap> for SignersContainer<DescriptorPublicKey> {
-    fn from(keymap: KeyMap) -> SignersContainer<DescriptorPublicKey> {
-        let mut container = SignersContainer::new();
-
-        for (_, secret) in keymap {
-            match secret {
-                DescriptorSecretKey::PrivKey(private_key) => container.add_external(
-                    SignerId::from(
-                        private_key
-                            .public_key(&Secp256k1::signing_only())
-                            .to_pubkeyhash(),
-                    ),
-                    SignerOrdering::default(),
-                    Arc::new(Box::new(private_key)),
-                ),
-                DescriptorSecretKey::XPrv(xprv) => container.add_external(
-                    SignerId::from(xprv.root_fingerprint()),
-                    SignerOrdering::default(),
-                    Arc::new(Box::new(xprv)),
-                ),
-            };
-        }
-
-        container
-    }
-}
-
-impl<Pk: MiniscriptKey> SignersContainer<Pk> {
-    /// Default constructor
-    pub fn new() -> Self {
-        SignersContainer(Default::default())
-    }
-
-    /// Adds an external signer to the container for the specified id. Optionally returns the
-    /// signer that was previosuly in the container, if any
-    pub fn add_external(
-        &mut self,
-        id: SignerId<Pk>,
-        ordering: SignerOrdering,
-        signer: Arc<Box<dyn Signer>>,
-    ) -> Option<Arc<Box<dyn Signer>>> {
-        self.0.insert((id, ordering).into(), signer)
-    }
-
-    /// Removes a signer from the container and returns it
-    pub fn remove(
-        &mut self,
-        id: SignerId<Pk>,
-        ordering: SignerOrdering,
-    ) -> Option<Arc<Box<dyn Signer>>> {
-        self.0.remove(&(id, ordering).into())
-    }
-
-    /// Returns the list of identifiers of all the signers in the container
-    pub fn ids(&self) -> Vec<&SignerId<Pk>> {
-        self.0
-            .keys()
-            .map(|SignersContainerKey { id, .. }| id)
-            .collect()
-    }
-
-    /// Returns the list of signers in the container, sorted by lowest to highest `ordering`
-    pub fn signers(&self) -> Vec<&Arc<Box<dyn Signer>>> {
-        self.0.values().collect()
-    }
-
-    /// Finds the signer with lowest ordering for a given id in the container.
-    pub fn find(&self, id: SignerId<Pk>) -> Option<&Arc<Box<dyn Signer>>> {
-        self.0
-            .range((
-                Included(&(id.clone(), SignerOrdering(0)).into()),
-                Included(&(id, SignerOrdering(usize::MAX)).into()),
-            ))
-            .map(|(_, v)| v)
-            .nth(0)
-    }
-}
-
-pub(crate) trait ComputeSighash {
-    fn sighash(
-        psbt: &psbt::PartiallySignedTransaction,
-        input_index: usize,
-    ) -> Result<(SigHash, SigHashType), SignerError>;
-}
-
-impl ComputeSighash for Legacy {
-    fn sighash(
-        psbt: &psbt::PartiallySignedTransaction,
-        input_index: usize,
-    ) -> Result<(SigHash, SigHashType), SignerError> {
-        if input_index >= psbt.inputs.len() {
-            return Err(SignerError::InputIndexOutOfRange);
-        }
-
-        let psbt_input = &psbt.inputs[input_index];
-        let tx_input = &psbt.global.unsigned_tx.input[input_index];
-
-        let sighash = psbt_input.sighash_type.ok_or(SignerError::MissingSighash)?;
-        let script = match &psbt_input.redeem_script {
-            &Some(ref redeem_script) => redeem_script.clone(),
-            &None => {
-                let non_witness_utxo = psbt_input
-                    .non_witness_utxo
-                    .as_ref()
-                    .ok_or(SignerError::MissingNonWitnessUtxo)?;
-                let prev_out = non_witness_utxo
-                    .output
-                    .get(tx_input.previous_output.vout as usize)
-                    .ok_or(SignerError::InvalidNonWitnessUtxo)?;
-
-                prev_out.script_pubkey.clone()
-            }
-        };
-
-        Ok((
-            psbt.global
-                .unsigned_tx
-                .signature_hash(input_index, &script, sighash.as_u32()),
-            sighash,
-        ))
-    }
-}
-
-impl ComputeSighash for Segwitv0 {
-    fn sighash(
-        psbt: &psbt::PartiallySignedTransaction,
-        input_index: usize,
-    ) -> Result<(SigHash, SigHashType), SignerError> {
-        if input_index >= psbt.inputs.len() {
-            return Err(SignerError::InputIndexOutOfRange);
-        }
-
-        let psbt_input = &psbt.inputs[input_index];
-
-        let sighash = psbt_input.sighash_type.ok_or(SignerError::MissingSighash)?;
-
-        let witness_utxo = psbt_input
-            .witness_utxo
-            .as_ref()
-            .ok_or(SignerError::MissingNonWitnessUtxo)?;
-        let value = witness_utxo.value;
-
-        let script = match &psbt_input.witness_script {
-            &Some(ref witness_script) => witness_script.clone(),
-            &None => {
-                if witness_utxo.script_pubkey.is_v0_p2wpkh() {
-                    ScriptBuilder::new()
-                        .push_opcode(opcodes::all::OP_DUP)
-                        .push_opcode(opcodes::all::OP_HASH160)
-                        .push_slice(&witness_utxo.script_pubkey[2..])
-                        .push_opcode(opcodes::all::OP_EQUALVERIFY)
-                        .push_opcode(opcodes::all::OP_CHECKSIG)
-                        .into_script()
-                } else {
-                    return Err(SignerError::MissingWitnessScript);
-                }
-            }
-        };
-
-        Ok((
-            bip143::SigHashCache::new(&psbt.global.unsigned_tx).signature_hash(
-                input_index,
-                &script,
-                value,
-                sighash,
-            ),
-            sighash,
-        ))
-    }
-}
-
-impl<Pk: MiniscriptKey> PartialOrd for SignersContainerKey<Pk> {
-    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
-impl<Pk: MiniscriptKey> Ord for SignersContainerKey<Pk> {
-    fn cmp(&self, other: &Self) -> Ordering {
-        self.ordering.cmp(&other.ordering)
-    }
-}
-
-impl<Pk: MiniscriptKey> PartialEq for SignersContainerKey<Pk> {
-    fn eq(&self, other: &Self) -> bool {
-        self.ordering == other.ordering
-    }
-}
-
-impl<Pk: MiniscriptKey> Eq for SignersContainerKey<Pk> {}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/time.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/time.rs.html deleted file mode 100644 index b0b4a16f70..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/time.rs.html +++ /dev/null @@ -1,175 +0,0 @@ -time.rs.html -- source
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Cross-platform time
-//!
-//! This module provides a function to get the current timestamp that works on all the platforms
-//! supported by the library.
-//!
-//! It can be useful to compare it with the timestamps found in
-//! [`TransactionDetails`](crate::types::TransactionDetails).
-
-use std::time::Duration;
-
-#[cfg(target_arch = "wasm32")]
-use js_sys::Date;
-#[cfg(not(target_arch = "wasm32"))]
-use std::time::{Instant as SystemInstant, SystemTime, UNIX_EPOCH};
-
-/// Return the current timestamp in seconds
-#[cfg(not(target_arch = "wasm32"))]
-pub fn get_timestamp() -> u64 {
-    SystemTime::now()
-        .duration_since(UNIX_EPOCH)
-        .unwrap()
-        .as_secs()
-}
-/// Return the current timestamp in seconds
-#[cfg(target_arch = "wasm32")]
-pub fn get_timestamp() -> u64 {
-    let millis = Date::now();
-
-    (millis / 1000.0) as u64
-}
-
-#[cfg(not(target_arch = "wasm32"))]
-pub(crate) struct Instant(SystemInstant);
-#[cfg(target_arch = "wasm32")]
-pub(crate) struct Instant(Duration);
-
-impl Instant {
-    #[cfg(not(target_arch = "wasm32"))]
-    pub fn new() -> Self {
-        Instant(SystemInstant::now())
-    }
-    #[cfg(target_arch = "wasm32")]
-    pub fn new() -> Self {
-        let millis = Date::now();
-
-        let secs = millis / 1000.0;
-        let nanos = (millis % 1000.0) * 1e6;
-
-        Instant(Duration::new(secs as u64, nanos as u32))
-    }
-
-    #[cfg(not(target_arch = "wasm32"))]
-    pub fn elapsed(&self) -> Duration {
-        self.0.elapsed()
-    }
-    #[cfg(target_arch = "wasm32")]
-    pub fn elapsed(&self) -> Duration {
-        let now = Instant::new();
-
-        now.0.checked_sub(self.0).unwrap_or(Duration::new(0, 0))
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/tx_builder.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/tx_builder.rs.html deleted file mode 100644 index d11de5e748..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/tx_builder.rs.html +++ /dev/null @@ -1,979 +0,0 @@ -tx_builder.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-397
-398
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-409
-410
-411
-412
-413
-414
-415
-416
-417
-418
-419
-420
-421
-422
-423
-424
-425
-426
-427
-428
-429
-430
-431
-432
-433
-434
-435
-436
-437
-438
-439
-440
-441
-442
-443
-444
-445
-446
-447
-448
-449
-450
-451
-452
-453
-454
-455
-456
-457
-458
-459
-460
-461
-462
-463
-464
-465
-466
-467
-468
-469
-470
-471
-472
-473
-474
-475
-476
-477
-478
-479
-480
-481
-482
-483
-484
-485
-486
-487
-488
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! Transaction builder
-//!
-//! ## Example
-//!
-//! ```
-//! # use std::str::FromStr;
-//! # use bitcoin::*;
-//! # use magical::*;
-//! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
-//! // Create a transaction with one output to `to_address` of 50_000 satoshi, with a custom fee rate
-//! // of 5.0 satoshi/vbyte, only spending non-change outputs and with RBF signaling
-//! // enabled
-//! let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
-//!     .fee_rate(FeeRate::from_sat_per_vb(5.0))
-//!     .do_not_spend_change()
-//!     .enable_rbf();
-//! ```
-
-use std::collections::BTreeMap;
-use std::default::Default;
-
-use bitcoin::{OutPoint, Script, SigHashType, Transaction};
-
-use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm};
-use crate::types::{FeeRate, UTXO};
-
-/// A transaction builder
-///
-/// This structure contains the configuration that the wallet must follow to build a transaction.
-///
-/// For an example see [this module](super::tx_builder)'s documentation;
-#[derive(Debug, Default)]
-pub struct TxBuilder<Cs: CoinSelectionAlgorithm> {
-    pub(crate) recipients: Vec<(Script, u64)>,
-    pub(crate) send_all: bool,
-    pub(crate) fee_rate: Option<FeeRate>,
-    pub(crate) policy_path: Option<BTreeMap<String, Vec<usize>>>,
-    pub(crate) utxos: Option<Vec<OutPoint>>,
-    pub(crate) unspendable: Option<Vec<OutPoint>>,
-    pub(crate) sighash: Option<SigHashType>,
-    pub(crate) ordering: TxOrdering,
-    pub(crate) locktime: Option<u32>,
-    pub(crate) rbf: Option<u32>,
-    pub(crate) version: Option<Version>,
-    pub(crate) change_policy: ChangeSpendPolicy,
-    pub(crate) force_non_witness_utxo: bool,
-    pub(crate) coin_selection: Cs,
-}
-
-impl TxBuilder<DefaultCoinSelectionAlgorithm> {
-    /// Create an empty builder
-    pub fn new() -> Self {
-        Self::default()
-    }
-
-    /// Create a builder starting from a list of recipients
-    pub fn with_recipients(recipients: Vec<(Script, u64)>) -> Self {
-        Self::default().set_recipients(recipients)
-    }
-}
-
-impl<Cs: CoinSelectionAlgorithm> TxBuilder<Cs> {
-    /// Replace the recipients already added with a new list
-    pub fn set_recipients(mut self, recipients: Vec<(Script, u64)>) -> Self {
-        self.recipients = recipients;
-        self
-    }
-
-    /// Add a recipient to the internal list
-    pub fn add_recipient(mut self, script_pubkey: Script, amount: u64) -> Self {
-        self.recipients.push((script_pubkey, amount));
-        self
-    }
-
-    /// Send all the selected utxos to a single output
-    ///
-    /// Adding more than one recipients with this option enabled will result in an error.
-    ///
-    /// The value associated with the only recipient is irrelevant and will be replaced by the wallet.
-    pub fn send_all(mut self) -> Self {
-        self.send_all = true;
-        self
-    }
-
-    /// Set a custom fee rate
-    pub fn fee_rate(mut self, fee_rate: FeeRate) -> Self {
-        self.fee_rate = Some(fee_rate);
-        self
-    }
-
-    /// Set the policy path to use while creating the transaction
-    ///
-    /// This method accepts a map where the key is the policy node id (see
-    /// [`Policy::id`](crate::descriptor::Policy::id)) and the value is the list of the indexes of
-    /// the items that are intended to be satisfied from the policy node (see
-    /// [`SatisfiableItem::Thresh::items`](crate::descriptor::policy::SatisfiableItem::Thresh::items)).
-    pub fn policy_path(mut self, policy_path: BTreeMap<String, Vec<usize>>) -> Self {
-        self.policy_path = Some(policy_path);
-        self
-    }
-
-    /// Replace the internal list of utxos that **must** be spent with a new list
-    ///
-    /// These have priority over the "unspendable" utxos, meaning that if a utxo is present both in
-    /// the "utxos" and the "unspendable" list, it will be spent.
-    pub fn utxos(mut self, utxos: Vec<OutPoint>) -> Self {
-        self.utxos = Some(utxos);
-        self
-    }
-
-    /// Add a utxo to the internal list of utxos that **must** be spent
-    ///
-    /// These have priority over the "unspendable" utxos, meaning that if a utxo is present both in
-    /// the "utxos" and the "unspendable" list, it will be spent.
-    pub fn add_utxo(mut self, utxo: OutPoint) -> Self {
-        self.utxos.get_or_insert(vec![]).push(utxo);
-        self
-    }
-
-    /// Replace the internal list of unspendable utxos with a new list
-    ///
-    /// It's important to note that the "must-be-spent" utxos added with [`TxBuilder::utxos`] and
-    /// [`TxBuilder::add_utxo`] have priority over these. See the docs of the two linked methods
-    /// for more details.
-    pub fn unspendable(mut self, unspendable: Vec<OutPoint>) -> Self {
-        self.unspendable = Some(unspendable);
-        self
-    }
-
-    /// Add a utxo to the internal list of unspendable utxos
-    ///
-    /// It's important to note that the "must-be-spent" utxos added with [`TxBuilder::utxos`] and
-    /// [`TxBuilder::add_utxo`] have priority over this. See the docs of the two linked methods
-    /// for more details.
-    pub fn add_unspendable(mut self, unspendable: OutPoint) -> Self {
-        self.unspendable.get_or_insert(vec![]).push(unspendable);
-        self
-    }
-
-    /// Sign with a specific sig hash
-    ///
-    /// **Use this option very carefully**
-    pub fn sighash(mut self, sighash: SigHashType) -> Self {
-        self.sighash = Some(sighash);
-        self
-    }
-
-    /// Choose the ordering for inputs and outputs of the transaction
-    pub fn ordering(mut self, ordering: TxOrdering) -> Self {
-        self.ordering = ordering;
-        self
-    }
-
-    /// Use a specific nLockTime while creating the transaction
-    ///
-    /// This can cause conflicts if the wallet's descriptors contain an "after" (OP_CLTV) operator.
-    pub fn nlocktime(mut self, locktime: u32) -> Self {
-        self.locktime = Some(locktime);
-        self
-    }
-
-    /// Enable signaling RBF
-    ///
-    /// This will use the default nSequence value of `0xFFFFFFFD`.
-    pub fn enable_rbf(self) -> Self {
-        self.enable_rbf_with_sequence(0xFFFFFFFD)
-    }
-
-    /// Enable signaling RBF with a specific nSequence value
-    ///
-    /// This can cause conflicts if the wallet's descriptors contain an "older" (OP_CSV) operator
-    /// and the given `nsequence` is lower than the CSV value.
-    ///
-    /// If the `nsequence` is higher than `0xFFFFFFFD` an error will be thrown, since it would not
-    /// be a valid nSequence to signal RBF.
-    pub fn enable_rbf_with_sequence(mut self, nsequence: u32) -> Self {
-        self.rbf = Some(nsequence);
-        self
-    }
-
-    /// Build a transaction with a specific version
-    ///
-    /// The `version` should always be greater than `0` and greater than `1` if the wallet's
-    /// descriptors contain an "older" (OP_CSV) operator.
-    pub fn version(mut self, version: u32) -> Self {
-        self.version = Some(Version(version));
-        self
-    }
-
-    /// Do not spend change outputs
-    ///
-    /// This effectively adds all the change outputs to the "unspendable" list. See
-    /// [`TxBuilder::unspendable`].
-    pub fn do_not_spend_change(mut self) -> Self {
-        self.change_policy = ChangeSpendPolicy::ChangeForbidden;
-        self
-    }
-
-    /// Only spend change outputs
-    ///
-    /// This effectively adds all the non-change outputs to the "unspendable" list. See
-    /// [`TxBuilder::unspendable`].
-    pub fn only_spend_change(mut self) -> Self {
-        self.change_policy = ChangeSpendPolicy::OnlyChange;
-        self
-    }
-
-    /// Set a specific [`ChangeSpendPolicy`]. See [`TxBuilder::do_not_spend_change`] and
-    /// [`TxBuilder::only_spend_change`] for some shortcuts.
-    pub fn change_policy(mut self, change_policy: ChangeSpendPolicy) -> Self {
-        self.change_policy = change_policy;
-        self
-    }
-
-    /// Fill-in the [`psbt::Input::non_witness_utxo`](bitcoin::util::psbt::Input::non_witness_utxo) field even if the wallet only has SegWit
-    /// descriptors.
-    ///
-    /// This is useful for signers which always require it, like Trezor hardware wallets.
-    pub fn force_non_witness_utxo(mut self) -> Self {
-        self.force_non_witness_utxo = true;
-        self
-    }
-
-    /// Choose the coin selection algorithm
-    ///
-    /// Overrides the [`DefaultCoinSelectionAlgorithm`](super::coin_selection::DefaultCoinSelectionAlgorithm).
-    pub fn coin_selection<P: CoinSelectionAlgorithm>(self, coin_selection: P) -> TxBuilder<P> {
-        TxBuilder {
-            recipients: self.recipients,
-            send_all: self.send_all,
-            fee_rate: self.fee_rate,
-            policy_path: self.policy_path,
-            utxos: self.utxos,
-            unspendable: self.unspendable,
-            sighash: self.sighash,
-            ordering: self.ordering,
-            locktime: self.locktime,
-            rbf: self.rbf,
-            version: self.version,
-            change_policy: self.change_policy,
-            force_non_witness_utxo: self.force_non_witness_utxo,
-            coin_selection,
-        }
-    }
-}
-
-/// Ordering of the transaction's inputs and outputs
-#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
-pub enum TxOrdering {
-    /// Randomized (default)
-    Shuffle,
-    /// Unchanged
-    Untouched,
-    /// BIP69 / Lexicographic
-    BIP69Lexicographic,
-}
-
-impl Default for TxOrdering {
-    fn default() -> Self {
-        TxOrdering::Shuffle
-    }
-}
-
-impl TxOrdering {
-    pub fn sort_tx(&self, tx: &mut Transaction) {
-        match self {
-            TxOrdering::Untouched => {}
-            TxOrdering::Shuffle => {
-                use rand::seq::SliceRandom;
-                #[cfg(test)]
-                use rand::SeedableRng;
-
-                #[cfg(not(test))]
-                let mut rng = rand::thread_rng();
-                #[cfg(test)]
-                let mut rng = rand::rngs::StdRng::seed_from_u64(0);
-
-                tx.output.shuffle(&mut rng);
-            }
-            TxOrdering::BIP69Lexicographic => {
-                tx.input.sort_unstable_by_key(|txin| {
-                    (txin.previous_output.txid, txin.previous_output.vout)
-                });
-                tx.output
-                    .sort_unstable_by_key(|txout| (txout.value, txout.script_pubkey.clone()));
-            }
-        }
-    }
-}
-
-/// Transaction version
-///
-/// Has a default value of `1`
-#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
-pub(crate) struct Version(pub(crate) u32);
-
-impl Default for Version {
-    fn default() -> Self {
-        Version(1)
-    }
-}
-
-/// Policy regarding the use of change outputs when creating a transaction
-#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
-pub enum ChangeSpendPolicy {
-    /// Use both change and non-change outputs (default)
-    ChangeAllowed,
-    /// Only use change outputs (see [`TxBuilder::only_spend_change`])
-    OnlyChange,
-    /// Only use non-change outputs (see [`TxBuilder::do_not_spend_change`])
-    ChangeForbidden,
-}
-
-impl Default for ChangeSpendPolicy {
-    fn default() -> Self {
-        ChangeSpendPolicy::ChangeAllowed
-    }
-}
-
-impl ChangeSpendPolicy {
-    pub(crate) fn filter_utxos<I: Iterator<Item = UTXO>>(&self, iter: I) -> Vec<UTXO> {
-        match self {
-            ChangeSpendPolicy::ChangeAllowed => iter.collect(),
-            ChangeSpendPolicy::OnlyChange => iter.filter(|utxo| utxo.is_internal).collect(),
-            ChangeSpendPolicy::ChangeForbidden => iter.filter(|utxo| !utxo.is_internal).collect(),
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    const ORDERING_TEST_TX: &'static str = "0200000003c26f3eb7932f7acddc5ddd26602b77e7516079b03090a16e2c2f54\
-                                            85d1fd600f0100000000ffffffffc26f3eb7932f7acddc5ddd26602b77e75160\
-                                            79b03090a16e2c2f5485d1fd600f0000000000ffffffff571fb3e02278217852\
-                                            dd5d299947e2b7354a639adc32ec1fa7b82cfb5dec530e0500000000ffffffff\
-                                            03e80300000000000002aaeee80300000000000001aa200300000000000001ff\
-                                            00000000";
-    macro_rules! ordering_test_tx {
-        () => {
-            deserialize::<bitcoin::Transaction>(&Vec::<u8>::from_hex(ORDERING_TEST_TX).unwrap())
-                .unwrap()
-        };
-    }
-
-    use bitcoin::consensus::deserialize;
-    use bitcoin::hashes::hex::FromHex;
-
-    use super::*;
-
-    #[test]
-    fn test_output_ordering_default_shuffle() {
-        assert_eq!(TxOrdering::default(), TxOrdering::Shuffle);
-    }
-
-    #[test]
-    fn test_output_ordering_untouched() {
-        let original_tx = ordering_test_tx!();
-        let mut tx = original_tx.clone();
-
-        TxOrdering::Untouched.sort_tx(&mut tx);
-
-        assert_eq!(original_tx, tx);
-    }
-
-    #[test]
-    fn test_output_ordering_shuffle() {
-        let original_tx = ordering_test_tx!();
-        let mut tx = original_tx.clone();
-
-        TxOrdering::Shuffle.sort_tx(&mut tx);
-
-        assert_eq!(original_tx.input, tx.input);
-        assert_ne!(original_tx.output, tx.output);
-    }
-
-    #[test]
-    fn test_output_ordering_bip69() {
-        use std::str::FromStr;
-
-        let original_tx = ordering_test_tx!();
-        let mut tx = original_tx.clone();
-
-        TxOrdering::BIP69Lexicographic.sort_tx(&mut tx);
-
-        assert_eq!(
-            tx.input[0].previous_output,
-            bitcoin::OutPoint::from_str(
-                "0e53ec5dfb2cb8a71fec32dc9a634a35b7e24799295ddd5278217822e0b31f57:5"
-            )
-            .unwrap()
-        );
-        assert_eq!(
-            tx.input[1].previous_output,
-            bitcoin::OutPoint::from_str(
-                "0f60fdd185542f2c6ea19030b0796051e7772b6026dd5ddccd7a2f93b73e6fc2:0"
-            )
-            .unwrap()
-        );
-        assert_eq!(
-            tx.input[2].previous_output,
-            bitcoin::OutPoint::from_str(
-                "0f60fdd185542f2c6ea19030b0796051e7772b6026dd5ddccd7a2f93b73e6fc2:1"
-            )
-            .unwrap()
-        );
-
-        assert_eq!(tx.output[0].value, 800);
-        assert_eq!(tx.output[1].script_pubkey, From::from(vec![0xAA]));
-        assert_eq!(tx.output[2].script_pubkey, From::from(vec![0xAA, 0xEE]));
-    }
-
-    fn get_test_utxos() -> Vec<UTXO> {
-        vec![
-            UTXO {
-                outpoint: OutPoint {
-                    txid: Default::default(),
-                    vout: 0,
-                },
-                txout: Default::default(),
-                is_internal: false,
-            },
-            UTXO {
-                outpoint: OutPoint {
-                    txid: Default::default(),
-                    vout: 1,
-                },
-                txout: Default::default(),
-                is_internal: true,
-            },
-        ]
-    }
-
-    #[test]
-    fn test_change_spend_policy_default() {
-        let change_spend_policy = ChangeSpendPolicy::default();
-        let filtered = change_spend_policy.filter_utxos(get_test_utxos().into_iter());
-
-        assert_eq!(filtered.len(), 2);
-    }
-
-    #[test]
-    fn test_change_spend_policy_no_internal() {
-        let change_spend_policy = ChangeSpendPolicy::ChangeForbidden;
-        let filtered = change_spend_policy.filter_utxos(get_test_utxos().into_iter());
-
-        assert_eq!(filtered.len(), 1);
-        assert_eq!(filtered[0].is_internal, false);
-    }
-
-    #[test]
-    fn test_change_spend_policy_only_internal() {
-        let change_spend_policy = ChangeSpendPolicy::OnlyChange;
-        let filtered = change_spend_policy.filter_utxos(get_test_utxos().into_iter());
-
-        assert_eq!(filtered.len(), 1);
-        assert_eq!(filtered[0].is_internal, true);
-    }
-
-    #[test]
-    fn test_default_tx_version_1() {
-        let version = Version::default();
-        assert_eq!(version.0, 1);
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/utils.rs.html b/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/utils.rs.html deleted file mode 100644 index 2c3afbe8a7..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/src/magical/wallet/utils.rs.html +++ /dev/null @@ -1,311 +0,0 @@ -utils.rs.html -- source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-
-// Magical Bitcoin Library
-// Written in 2020 by
-//     Alekos Filini <alekos.filini@gmail.com>
-//
-// Copyright (c) 2020 Magical Bitcoin
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-use miniscript::{MiniscriptKey, Satisfier};
-
-// De-facto standard "dust limit" (even though it should change based on the output type)
-const DUST_LIMIT_SATOSHI: u64 = 546;
-
-/// Trait to check if a value is below the dust limit
-// we implement this trait to make sure we don't mess up the comparison with off-by-one like a <
-// instead of a <= etc. The constant value for the dust limit is not public on purpose, to
-// encourage the usage of this trait.
-pub trait IsDust {
-    /// Check whether or not a value is below dust limit
-    fn is_dust(&self) -> bool;
-}
-
-impl IsDust for u64 {
-    fn is_dust(&self) -> bool {
-        *self <= DUST_LIMIT_SATOSHI
-    }
-}
-
-pub struct After {
-    pub current_height: Option<u32>,
-    pub assume_height_reached: bool,
-}
-
-impl After {
-    pub(crate) fn new(current_height: Option<u32>, assume_height_reached: bool) -> After {
-        After {
-            current_height,
-            assume_height_reached,
-        }
-    }
-}
-
-impl<Pk: MiniscriptKey> Satisfier<Pk> for After {
-    fn check_after(&self, n: u32) -> bool {
-        if let Some(current_height) = self.current_height {
-            current_height >= n
-        } else {
-            self.assume_height_reached
-        }
-    }
-}
-
-pub struct Older {
-    pub current_height: Option<u32>,
-    pub create_height: Option<u32>,
-    pub assume_height_reached: bool,
-}
-
-impl Older {
-    pub(crate) fn new(
-        current_height: Option<u32>,
-        create_height: Option<u32>,
-        assume_height_reached: bool,
-    ) -> Older {
-        Older {
-            current_height,
-            create_height,
-            assume_height_reached,
-        }
-    }
-}
-
-impl<Pk: MiniscriptKey> Satisfier<Pk> for Older {
-    fn check_older(&self, n: u32) -> bool {
-        if let Some(current_height) = self.current_height {
-            // TODO: test >= / >
-            current_height as u64 >= self.create_height.unwrap_or(0) as u64 + n as u64
-        } else {
-            self.assume_height_reached
-        }
-    }
-}
-
-pub struct ChunksIterator<I: Iterator> {
-    iter: I,
-    size: usize,
-}
-
-impl<I: Iterator> ChunksIterator<I> {
-    pub fn new(iter: I, size: usize) -> Self {
-        ChunksIterator { iter, size }
-    }
-}
-
-impl<I: Iterator> Iterator for ChunksIterator<I> {
-    type Item = Vec<<I as std::iter::Iterator>::Item>;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        let mut v = Vec::new();
-        for _ in 0..self.size {
-            let e = self.iter.next();
-
-            match e {
-                None => break,
-                Some(val) => v.push(val),
-            }
-        }
-
-        if v.is_empty() {
-            return None;
-        }
-
-        Some(v)
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use crate::types::FeeRate;
-
-    #[test]
-    fn test_fee_from_btc_per_kb() {
-        let fee = FeeRate::from_btc_per_kvb(1e-5);
-        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
-    }
-
-    #[test]
-    fn test_fee_from_sats_vbyte() {
-        let fee = FeeRate::from_sat_per_vb(1.0);
-        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
-    }
-
-    #[test]
-    fn test_fee_default_min_relay_fee() {
-        let fee = FeeRate::default_min_relay_fee();
-        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
-    }
-}
-
-
\ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/storage.js b/static/docs-rs/magical/0.1.0-beta.1/storage.js deleted file mode 100644 index 1b5225126f..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/storage.js +++ /dev/null @@ -1 +0,0 @@ -var resourcesSuffix="";var currentTheme=document.getElementById("themeStyle");var mainTheme=document.getElementById("mainThemeStyle");var savedHref=[];function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(!elem||!elem.classList){return}elem.classList.add(className)}function removeClass(elem,className){if(!elem||!elem.classList){return}elem.classList.remove(className)}function onEach(arr,func,reversed){if(arr&&arr.length>0&&func){var length=arr.length;var i;if(reversed!==true){for(i=0;i=0;--i){if(func(arr[i])===true){return true}}}}return false}function onEachLazy(lazyArray,func,reversed){return onEach(Array.prototype.slice.call(lazyArray),func,reversed)}function hasOwnProperty(obj,property){return Object.prototype.hasOwnProperty.call(obj,property)}function usableLocalStorage(){if(typeof Storage==="undefined"){return false}try{return window.localStorage!==null&&window.localStorage!==undefined}catch(err){return false}}function updateLocalStorage(name,value){if(usableLocalStorage()){localStorage[name]=value}else{}}function getCurrentValue(name){if(usableLocalStorage()&&localStorage[name]!==undefined){return localStorage[name]}return null}function switchTheme(styleElem,mainStyleElem,newTheme,saveTheme){var fullBasicCss="rustdoc"+resourcesSuffix+".css";var fullNewTheme=newTheme+resourcesSuffix+".css";var newHref=mainStyleElem.href.replace(fullBasicCss,fullNewTheme);if(styleElem.href===newHref){return}var found=false;if(savedHref.length===0){onEachLazy(document.getElementsByTagName("link"),function(el){savedHref.push(el.href)})}onEach(savedHref,function(el){if(el===newHref){found=true;return true}});if(found===true){styleElem.href=newHref;if(saveTheme===true){updateLocalStorage("rustdoc-theme",newTheme)}}}function getSystemValue(){var property=getComputedStyle(document.documentElement).getPropertyValue('content');return property.replace(/[\"\']/g,"")}switchTheme(currentTheme,mainTheme,getCurrentValue("rustdoc-theme")||getSystemValue()||"light",false) \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/theme.js b/static/docs-rs/magical/0.1.0-beta.1/theme.js deleted file mode 100644 index ebd1a87271..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/theme.js +++ /dev/null @@ -1 +0,0 @@ -var themes=document.getElementById("theme-choices");var themePicker=document.getElementById("theme-picker");function showThemeButtonState(){themes.style.display="block";themePicker.style.borderBottomRightRadius="0";themePicker.style.borderBottomLeftRadius="0"}function hideThemeButtonState(){themes.style.display="none";themePicker.style.borderBottomRightRadius="3px";themePicker.style.borderBottomLeftRadius="3px"}function switchThemeButtonState(){if(themes.style.display==="block"){hideThemeButtonState()}else{showThemeButtonState()}};function handleThemeButtonsBlur(e){var active=document.activeElement;var related=e.relatedTarget;if(active.id!=="themePicker"&&(!active.parentNode||active.parentNode.id!=="theme-choices")&&(!related||(related.id!=="themePicker"&&(!related.parentNode||related.parentNode.id!=="theme-choices")))){hideThemeButtonState()}}themePicker.onclick=switchThemeButtonState;themePicker.onblur=handleThemeButtonsBlur;["dark","light"].forEach(function(item){var but=document.createElement('button');but.textContent=item;but.onclick=function(el){switchTheme(currentTheme,mainTheme,item,true)};but.onblur=handleThemeButtonsBlur;themes.appendChild(but)}) \ No newline at end of file diff --git a/static/docs-rs/magical/0.1.0-beta.1/wheel.svg b/static/docs-rs/magical/0.1.0-beta.1/wheel.svg deleted file mode 100644 index 01da3b24c7..0000000000 --- a/static/docs-rs/magical/0.1.0-beta.1/wheel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/static/docs-rs/magical/index.html b/static/docs-rs/magical/index.html deleted file mode 100644 index 23b78f3bfa..0000000000 --- a/static/docs-rs/magical/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - Redirect - - - -

- You are being re-directed to the latest version.
- If that doesn't happen click here. -

- -