summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/github-action-checks.yml9
-rw-r--r--.gitignore6
-rw-r--r--README.mediawiki38
-rw-r--r--bip-0009/states.gv22
-rw-r--r--bip-0009/states.pngbin30632 -> 50153 bytes
-rw-r--r--bip-0014.mediawiki2
-rw-r--r--bip-0015.mediawiki4
-rw-r--r--bip-0021.mediawiki11
-rw-r--r--bip-0035.mediawiki2
-rw-r--r--bip-0038.mediawiki8
-rw-r--r--bip-0039.mediawiki69
-rw-r--r--bip-0039/bip-0039-wordlists.md14
-rw-r--r--bip-0042.mediawiki2
-rw-r--r--bip-0061.mediawiki2
-rw-r--r--bip-0067.mediawiki6
-rw-r--r--bip-0078.mediawiki14
-rw-r--r--bip-0080.mediawiki2
-rw-r--r--bip-0081.mediawiki2
-rw-r--r--bip-0083.mediawiki2
-rw-r--r--bip-0085.mediawiki2
-rw-r--r--bip-0099.mediawiki2
-rw-r--r--bip-0109.mediawiki2
-rw-r--r--bip-0112.mediawiki2
-rw-r--r--bip-0114.mediawiki2
-rw-r--r--bip-0126.mediawiki16
-rw-r--r--bip-0127.mediawiki2
-rw-r--r--bip-0129.mediawiki7
-rw-r--r--bip-0132.mediawiki2
-rw-r--r--bip-0133.mediawiki2
-rw-r--r--bip-0137.mediawiki2
-rw-r--r--bip-0141.mediawiki10
-rw-r--r--bip-0143.mediawiki4
-rw-r--r--bip-0151.mediawiki2
-rw-r--r--bip-0155.mediawiki9
-rw-r--r--bip-0158.mediawiki7
-rw-r--r--bip-0158/gentestvectors.go2
-rw-r--r--bip-0173.mediawiki10
-rw-r--r--bip-0174.mediawiki4
-rwxr-xr-xbip-0174/build.sh9
-rw-r--r--bip-0174/coinjoin-workflow.svg1460
-rw-r--r--bip-0174/coinjoin-workflow.tex12
-rw-r--r--bip-0174/multisig-workflow.svg2957
-rw-r--r--bip-0174/multisig-workflow.tex19
-rw-r--r--bip-0197.mediawiki2
-rw-r--r--bip-0310.mediawiki4
-rw-r--r--bip-0322.mediawiki2
-rw-r--r--bip-0324/test_sage_decoding.py2
-rw-r--r--bip-0324/xswiftec_test_vectors.csv33
-rw-r--r--bip-0327.mediawiki2
-rw-r--r--bip-0327/vectors/sign_verify_vectors.json8
-rwxr-xr-xbip-0330/minisketch.py2
-rw-r--r--bip-0340.mediawiki11
-rw-r--r--bip-0347.mediawiki113
-rw-r--r--bip-0352.mediawiki493
-rw-r--r--bip-0352/bech32m.py135
-rw-r--r--bip-0352/bitcoin_utils.py158
-rwxr-xr-xbip-0352/reference.py335
-rw-r--r--bip-0352/scan_data_downloader_per_month.pngbin0 -> 54276 bytes
-rw-r--r--bip-0352/secp256k1.py696
-rw-r--r--bip-0352/send_and_receive_test_vectors.json2673
-rw-r--r--bip-0370.mediawiki2
-rw-r--r--bip-0387.mediawiki101
-rw-r--r--bip-0388.mediawiki306
-rwxr-xr-xbip-0388/wallet_policies.py202
-rwxr-xr-xscripts/buildtable.pl3
-rwxr-xr-xscripts/diffcheck.sh3
-rwxr-xr-xscripts/link-format-chk.sh16
67 files changed, 9005 insertions, 1058 deletions
diff --git a/.github/workflows/github-action-checks.yml b/.github/workflows/github-action-checks.yml
index bfc014b..8a7d2ac 100644
--- a/.github/workflows/github-action-checks.yml
+++ b/.github/workflows/github-action-checks.yml
@@ -5,15 +5,18 @@ jobs:
Link-Format-Checks:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- run: scripts/link-format-chk.sh
Build-Table-Checks:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- run: scripts/buildtable.pl >/tmp/table.mediawiki || exit 1
Diff-Checks:
+ name: "Diff Checks (fails until number assignment)"
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 2
- run: scripts/diffcheck.sh
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d939d2a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+bip-0174/coinjoin-workflow.aux
+bip-0174/coinjoin-workflow.log
+bip-0174/coinjoin-workflow.pdf
+bip-0174/multisig-workflow.aux
+bip-0174/multisig-workflow.log
+bip-0174/multisig-workflow.pdf
diff --git a/README.mediawiki b/README.mediawiki
index b5ae7bb..710e128 100644
--- a/README.mediawiki
+++ b/README.mediawiki
@@ -237,7 +237,7 @@ Those proposing changes should consider that ultimately consent may rest with th
| Marek Palatinus, Pavol Rusnak
| Standard
| Final
-|- style="background-color: #ffffcf"
+|- style="background-color: #cfffcf"
| [[bip-0044.mediawiki|44]]
| Applications
| Multi-Account Hierarchy for Deterministic Wallets
@@ -251,13 +251,13 @@ Those proposing changes should consider that ultimately consent may rest with th
| Manuel Araoz, Ryan X. Charles, Matias Alejo Garcia
| Standard
| Proposed
-|-
+|- style="background-color: #cfffcf"
| [[bip-0047.mediawiki|47]]
| Applications
| Reusable Payment Codes for Hierarchical Deterministic Wallets
| Justus Ranvier
| Informational
-| Draft
+| Final
|- style="background-color: #ffffcf"
| [[bip-0048.mediawiki|48]]
| Applications
@@ -714,13 +714,13 @@ Those proposing changes should consider that ultimately consent may rest with th
| Andy Chase
| Process
| Withdrawn
-|-
+|- style="background-color: #cfffcf"
| [[bip-0133.mediawiki|133]]
| Peer Services
| feefilter message
| Alex Morcos
| Standard
-| Draft
+| Final
|- style="background-color: #ffcfcf"
| [[bip-0134.mediawiki|134]]
| Consensus (hard fork)
@@ -1085,6 +1085,13 @@ Those proposing changes should consider that ultimately consent may rest with th
| James O'Beirne, Greg Sanders, Anthony Towns
| Standard
| Draft
+|-
+| [[bip-0347.mediawiki|347]]
+| Consensus (soft fork)
+| OP_CAT in Tapscript
+| Ethan Heilman, Armin Sabouri
+| Standard
+| Draft
|- style="background-color: #cfffcf"
| [[bip-0350.mediawiki|350]]
| Applications
@@ -1099,6 +1106,13 @@ Those proposing changes should consider that ultimately consent may rest with th
| Alfred Hodler, Clark Moody
| Informational
| Draft
+|- style="background-color: #ffffcf"
+| [[bip-0352.mediawiki|352]]
+| Applications
+| Silent Payments
+| josibake, Ruben Somsen
+| Standard
+| Proposed
|-
| [[bip-0370.mediawiki|370]]
| Applications
@@ -1170,6 +1184,20 @@ Those proposing changes should consider that ultimately consent may rest with th
| Informational
| Draft
|-
+| [[bip-0387.mediawiki|387]]
+| Applications
+| Tapscript Multisig Output Script Descriptors
+| Pieter Wuille, Ava Chow
+| Informational
+| Draft
+|- style="background-color: #ffffcf"
+| [[bip-0388.mediawiki|388]]
+| Applications
+| Wallet Policies for Descriptor Wallets
+| Salvatore Ingala
+| Standard
+| Proposed
+|-
| [[bip-0389.mediawiki|389]]
| Applications
| Multipath Descriptor Key Expressions
diff --git a/bip-0009/states.gv b/bip-0009/states.gv
new file mode 100644
index 0000000..9dc95c5
--- /dev/null
+++ b/bip-0009/states.gv
@@ -0,0 +1,22 @@
+/* There are many ways to compile this, but one of them is:
+ *
+ * $ dot -Tpng states.gv -o states.png
+ */
+digraph {
+ /* States. */
+ DEFINED; FAILED; STARTED; LOCKED_IN; ACTIVE;
+
+ /* Relationships between states, labeled where applicable. */
+ DEFINED -> DEFINED;
+ DEFINED -> FAILED [label = "timeout ≤ MTP"];
+ DEFINED -> STARTED [label = "starttime ≤ MTP < timeout"];
+ FAILED -> FAILED;
+ STARTED -> STARTED;
+ STARTED -> FAILED [label = "timeout ≤ MTP"];
+ STARTED -> LOCKED_IN [label = "(MTP < timeout) AND (threshold reached)"];
+ LOCKED_IN -> ACTIVE [label = "Always"];
+ ACTIVE -> ACTIVE;
+
+ /* Visualization hack to unclutter output. */
+ nodesep = 1.2;
+}
diff --git a/bip-0009/states.png b/bip-0009/states.png
index 09312a1..2048ed8 100644
--- a/bip-0009/states.png
+++ b/bip-0009/states.png
Binary files differ
diff --git a/bip-0014.mediawiki b/bip-0014.mediawiki
index abd575c..fded420 100644
--- a/bip-0014.mediawiki
+++ b/bip-0014.mediawiki
@@ -28,7 +28,7 @@ Version bumping can also introduce incompatibilities and fracture the network. I
By using a protocol version, we set all implementations on the network to a common standard. Everybody is able to agree within their confines what is protocol and what is implementation-dependent. A user agent string is offered as a 'vanity-plate' for clients to distinguish themselves in the network.
-Separation of the network protocol from the implemention, and forming development of said protocol by means of a mutual consensus among participants, has the democratic disadvantage when agreement is hard to reach on contentious issues. To mitigate this issue, strong communication channels and fast release schedules are needed, and are outside the scope of this document (concerning a process-BIP type).
+Separation of the network protocol from the implementation, and forming development of said protocol by means of a mutual consensus among participants, has the democratic disadvantage when agreement is hard to reach on contentious issues. To mitigate this issue, strong communication channels and fast release schedules are needed, and are outside the scope of this document (concerning a process-BIP type).
User agents provide extra tracking information that is useful for keeping tabs on network data such as client implementations used or common architectures/operating-systems. In the rare case they may even provide an emergency method of shunning faulty clients that threaten network health- although this is strongly unrecommended and extremely bad form. The user agent does not provide a method for clients to work around and behave differently to different implementations, as this will lead to protocol fracturing.
diff --git a/bip-0015.mediawiki b/bip-0015.mediawiki
index a6e4426..52a698f 100644
--- a/bip-0015.mediawiki
+++ b/bip-0015.mediawiki
@@ -348,7 +348,7 @@ By using DNS lookups, the MITM problem with IP transactions could be mitigated b
=== Namecoin ID ===
-This proposal uses the Namecoin blockchain to associate an alias with a bitcoin address. Bitcoin queries a namecoin node. This retreives the structured data containing the bitcoin address(es) associated with this alias.
+This proposal uses the Namecoin blockchain to associate an alias with a bitcoin address. Bitcoin queries a namecoin node. This retrieves the structured data containing the bitcoin address(es) associated with this alias.
Using a decentralised domain name system like Namecoin, means no external server or entity needs to be trusted unlike the other proposals listed here. This indicates a system with the advantage of having a high availability and ease of entry (no restrictions for users to create aliases).
@@ -401,4 +401,4 @@ Any text can be put into the brackets, allowing merchants to adapt it to all the
New features can be added later to support uncovered cases.
-See the specification of [http://dot-bit.org/Namespace:Identity Namecoin ID] for more informations.
+See the specification of [http://dot-bit.org/Namespace:Identity Namecoin ID] for more information.
diff --git a/bip-0021.mediawiki b/bip-0021.mediawiki
index cdc37ba..9fa4823 100644
--- a/bip-0021.mediawiki
+++ b/bip-0021.mediawiki
@@ -120,11 +120,6 @@ Some future version that has variables which are (currently) not understood but
Characters must be URI encoded properly.
-== Reference Implementations ==
-=== Bitcoin clients ===
-* Bitcoin-Qt supports the old version of Bitcoin URIs (ie without the req- prefix), with Windows and KDE integration as of commit 70f55355e29c8e45b607e782c5d76609d23cc858.
-
-=== Libraries ===
-* Javascript - https://github.com/bitcoinjs/bip21
-* Java - https://github.com/SandroMachado/BitcoinPaymentURI
-* Swift - https://github.com/SandroMachado/BitcoinPaymentURISwift
+== Reference Implementation ==
+
+Bitcoin-Qt supports the old version of Bitcoin URIs (ie without the req- prefix), with Windows and KDE integration as of commit 70f55355e29c8e45b607e782c5d76609d23cc858.
diff --git a/bip-0035.mediawiki b/bip-0035.mediawiki
index 64edaf5..eccd381 100644
--- a/bip-0035.mediawiki
+++ b/bip-0035.mediawiki
@@ -16,7 +16,7 @@ Make a network node's transaction memory pool accessible via a new "mempool" mes
==Motivation==
-Several use cases make it desireable to expose a network node's transaction memory pool:
+Several use cases make it desirable to expose a network node's transaction memory pool:
# SPV clients, wishing to obtain zero-confirmation transactions sent or received.
# Miners, to avoid missing lucrative fees, downloading existing network transactions after a restart.
# Remote network diagnostics.
diff --git a/bip-0038.mediawiki b/bip-0038.mediawiki
index 7f99b1a..ffae832 100644
--- a/bip-0038.mediawiki
+++ b/bip-0038.mediawiki
@@ -36,10 +36,10 @@ Password and passphrase-protected private keys enable new practical use cases fo
This proposal is hereby placed in the public domain.
==Rationale==
-:'''''User story:''' As a Bitcoin user who uses paper wallets, I would like the ability to add encryption, so that my Bitcoin paper storage can be two factor: something I have plus something I know.''
-:'''''User story:''' As a Bitcoin user who would like to pay a person or a company with a private key, I do not want to worry that any part of the communication path may result in the interception of the key and theft of my funds. I would prefer to offer an encrypted private key, and then follow it up with the password using a different communication channel (e.g. a phone call or SMS).''
-:'''''User story:''' (EC-multiplied keys) As a user of physical bitcoins, I would like a third party to be able to create password-protected Bitcoin private keys for me, without them knowing the password, so I can benefit from the physical bitcoin without the issuer having access to the private key. I would like to be able to choose a password whose minimum length and required format does not preclude me from memorizing it or engraving it on my physical bitcoin, without exposing me to an undue risk of password cracking and/or theft by the manufacturer of the item.''
-:'''''User story:''' (EC multiplied keys) As a user of paper wallets, I would like the ability to generate a large number of Bitcoin addresses protected by the same password, while enjoying a high degree of security (highly expensive scrypt parameters), but without having to incur the scrypt delay for each address I generate.
+:'' '''User story:''' As a Bitcoin user who uses paper wallets, I would like the ability to add encryption, so that my Bitcoin paper storage can be two factor: something I have plus something I know.''
+:'' '''User story:''' As a Bitcoin user who would like to pay a person or a company with a private key, I do not want to worry that any part of the communication path may result in the interception of the key and theft of my funds. I would prefer to offer an encrypted private key, and then follow it up with the password using a different communication channel (e.g. a phone call or SMS).''
+:'' '''User story:''' (EC-multiplied keys) As a user of physical bitcoins, I would like a third party to be able to create password-protected Bitcoin private keys for me, without them knowing the password, so I can benefit from the physical bitcoin without the issuer having access to the private key. I would like to be able to choose a password whose minimum length and required format does not preclude me from memorizing it or engraving it on my physical bitcoin, without exposing me to an undue risk of password cracking and/or theft by the manufacturer of the item.''
+:'' '''User story:''' (EC-multiplied keys) As a user of paper wallets, I would like the ability to generate a large number of Bitcoin addresses protected by the same password, while enjoying a high degree of security (highly expensive scrypt parameters), but without having to incur the scrypt delay for each address I generate.''
==Specification==
This proposal makes use of the following functions and definitions:
diff --git a/bip-0039.mediawiki b/bip-0039.mediawiki
index 1c4845e..51fe33d 100644
--- a/bip-0039.mediawiki
+++ b/bip-0039.mediawiki
@@ -138,72 +138,3 @@ Also see https://github.com/bip32JP/bip32JP.github.io/blob/master/test_JP_BIP39.
Reference implementation including wordlists is available from
http://github.com/trezor/python-mnemonic
-
-==Other Implementations==
-
-Go:
-* https://github.com/tyler-smith/go-bip39
-
-Python:
-* https://github.com/meherett/python-hdwallet
-
-Elixir:
-* https://github.com/aerosol/mnemo
-
-Objective-C:
-* https://github.com/nybex/NYMnemonic
-
-Haskell:
-* https://github.com/haskoin/haskoin
-
-.NET (Standard):
-* https://www.nuget.org/packages/dotnetstandard-bip39/
-
-.NET C# (PCL):
-* https://github.com/Thashiznets/BIP39.NET
-
-.NET C# (PCL):
-* https://github.com/NicolasDorier/NBitcoin
-
-JavaScript:
-* https://github.com/bitpay/bitcore/tree/master/packages/bitcore-mnemonic
-* https://github.com/bitcoinjs/bip39 (used by [[https://github.com/blockchain/My-Wallet-V3/blob/v3.8.0/src/hd-wallet.js#L121-L146|blockchain.info]])
-* https://github.com/dashhive/DashPhrase.js
-* https://github.com/hujiulong/web-bip39
-
-TypeScript:
-* https://github.com/bitauth/libauth
-
-Java:
-* https://github.com/bitcoinj/bitcoinj/blob/master/core/src/main/java/org/bitcoinj/crypto/MnemonicCode.java
-
-Ruby:
-* https://github.com/sreekanthgs/bip_mnemonic
-
-Rust:
-* https://github.com/maciejhirsz/tiny-bip39/
-* https://github.com/koushiro/bip0039-rs
-
-Smalltalk:
-* https://github.com/eMaringolo/pharo-bip39mnemonic
-
-Swift:
-* https://github.com/CikeQiu/CKMnemonic
-* https://github.com/yuzushioh/WalletKit
-* https://github.com/pengpengliu/BIP39
-* https://github.com/matter-labs/web3swift/blob/develop/Sources/web3swift/KeystoreManager/BIP39.swift
-* https://github.com/zcash-hackworks/MnemonicSwift
-* https://github.com/ShenghaiWang/BIP39
-* https://github.com/anquii/BIP39
-
-C++:
-* https://github.com/libbitcoin/libbitcoin-system/blob/master/include/bitcoin/system/wallet/mnemonic.hpp
-
-C (with Python/Java/Javascript bindings):
-* https://github.com/ElementsProject/libwally-core
-
-Python:
-* https://github.com/scgbckbone/btc-hd-wallet
-
-Dart:
-* https://github.com/dart-bitcoin/bip39
diff --git a/bip-0039/bip-0039-wordlists.md b/bip-0039/bip-0039-wordlists.md
index f2c173c..5acf87d 100644
--- a/bip-0039/bip-0039-wordlists.md
+++ b/bip-0039/bip-0039-wordlists.md
@@ -53,7 +53,7 @@ Credits: @Kirvx @NicolasDorier @ecdsa @EricLarch
7. No words in the plural (except invariable words like "univers", or same spelling than singular like "heureux").
8. No female adjectives (except words with same spelling for male and female adjectives like "magique").
9. No words with several senses AND different spelling in speaking like "verre-vert", unless a word has a meaning much more popular than another like "perle" and "pairle".
-10. No very similar words with 1 letter of difference.
+10. No very similar words with only 1 letter of difference.
11. No essentially reflexive verbs (unless a verb is also a noun like "souvenir").
12. No words with "ô;â;ç;ê;œ;æ;î;ï;û;ù;à;ë;ÿ".
13. No words ending by "é;ée;è;et;ai;ait".
@@ -93,12 +93,12 @@ Words chosen using the following rules:
1. Words are 4-8 letters long.
2. Words can be uniquely determined typing the first 4 letters.
-3. Only words containing all letters without diacritical marks. (It was the hardest task, because in one third of all Czech letters has diacritical marks.)
+3. Only words containing all letters without diacritical marks. (It was the hardest task, because one third of all Czech letters has diacritical marks.)
4. Only nouns, verbs and adverbs, no other word types. All words are in basic form.
5. No personal names or geographical names.
6. No very similar words with 1 letter of difference.
-7. Words are sorting according English alphabet (Czech sorting has difference in "ch").
-8. No words already used in other language mnemonic sets (english, italian, french, spanish). Letters with diacritical marks from these sets are counted as analogous letters without diacritical marks.
+7. Words are sorted according to English alphabet (Czech sorting has difference in "ch").
+8. No words already used in other language mnemonic sets (english, italian, french, spanish). Letters with diacritical marks from these sets are counted as analogous letters without diacritical marks.
### Portuguese
@@ -109,9 +109,9 @@ Credits: @alegotardo @bitmover-studio @brenorb @kuthullu @ninjastic @sabotag3x @
3. No complex verb forms.
4. No plural words, unless there's no singular form.
5. No words with double spelling.
-6. No words with the exact sound of another word with different spelling.
+6. No words with the exact sound as another word with different spelling.
7. No offensive words.
8. No words already used in other language mnemonic sets.
9. The words which have not the same spelling in Brazil and in Portugal are excluded.
-10. No words that remind negative/sad/bad things.
-11. No very similar words with 1 letter of difference.
+10. No words that remind one of negative/sad/bad things.
+11. No very similar words with only 1 letter of difference.
diff --git a/bip-0042.mediawiki b/bip-0042.mediawiki
index 223076f..2c5de6d 100644
--- a/bip-0042.mediawiki
+++ b/bip-0042.mediawiki
@@ -15,7 +15,7 @@
Although it is widely believed that Satoshi was an inflation-hating goldbug he never said this, and in fact programmed Bitcoin's money supply to grow indefinitely, forever. He modeled the monetary supply as 4 gold mines being discovered per mibillenium (1024 years), with equal intervals between them, each one being depleted over the course of 140 years.
-This poses obvious problems, however. Prominent among them is the discussion on what to call 1 billion Bitcoin, which symbol color to use for it, and when wallet clients should switch to it by default.
+This poses obvious problems, however. Prominent among them is the discussion on what to call 1 billion bitcoin, which symbol color to use for it, and when wallet clients should switch to it by default.
To combat this, this document proposes a controversial change: making Bitcoin's monetary supply finite.
diff --git a/bip-0061.mediawiki b/bip-0061.mediawiki
index b08739d..384c0ff 100644
--- a/bip-0061.mediawiki
+++ b/bip-0061.mediawiki
@@ -57,7 +57,7 @@ Every reject message begins with the following fields. Some messages append extr
|}
The human-readable string is intended only for debugging purposes; in particular, different implementations may
-use different strings. The string should not be shown to users or used for anthing besides diagnosing
+use different strings. The string should not be shown to users or used for anything besides diagnosing
interoperability problems.
The following reject code categories are used; in the descriptions below, "server" is the peer generating
diff --git a/bip-0067.mediawiki b/bip-0067.mediawiki
index 793039d..a31cc3d 100644
--- a/bip-0067.mediawiki
+++ b/bip-0067.mediawiki
@@ -53,10 +53,10 @@ Hash the redeem script according to BIP-0016 to get the P2SH address.
3Q4sF6tv9wsdqu2NtARzNCpQgwifm2rAba
==Compatibility==
-* Uncompressed keys are incompatible with this specificiation. A compatible implementation should not automatically compress keys. Receiving an uncompressed key from a multisig participant should be interpreted as a sign that the user has an incompatible implementation.
-* P2SH addressses do not reveal information about the script that is receiving the funds. For this reason it is not technically possible to enforce this BIP as a rule on the network. Also, it would cause a hard fork.
+* Uncompressed keys are incompatible with this specification. A compatible implementation should not automatically compress keys. Receiving an uncompressed key from a multisig participant should be interpreted as a sign that the user has an incompatible implementation.
+* P2SH addresses do not reveal information about the script that is receiving the funds. For this reason it is not technically possible to enforce this BIP as a rule on the network. Also, it would cause a hard fork.
* Implementations that do not conform with this BIP will have compatibility issues with strictly-compliant wallets.
-* Implementations which do adopt this standard will be cross-compatible when choosing multisig addressses.
+* Implementations which do adopt this standard will be cross-compatible when choosing multisig addresses.
* If a group of users were not entirely compliant, there is the possibility that a participant will derive an address that the others will not recognize as part of the common multisig account.
==Test vectors==
diff --git a/bip-0078.mediawiki b/bip-0078.mediawiki
index 1893f0e..3528725 100644
--- a/bip-0078.mediawiki
+++ b/bip-0078.mediawiki
@@ -143,7 +143,7 @@ If the receiver does not support the version of the sender, they should send an
}
</pre>
-* <code>additionalfeeoutputindex=</code>, if the sender is willing to pay for increased fee, this indicate output can have its value substracted to pay for it.
+* <code>additionalfeeoutputindex=</code>, if the sender is willing to pay for increased fee, this indicate output can have its value subtracted to pay for it.
If the <code>additionalfeeoutputindex</code> is out of bounds or pointing to the payment output meant for the receiver, the receiver should ignore the parameter. See [[#fee-output|fee output]] for more information.
@@ -198,7 +198,7 @@ It is advised to hard code the description of the well known error codes into th
===<span id="fee-output"></span>Fee output===
In some situation, the sender might want to pay some additional fee in the payjoin proposal.
-If such is the case, the sender must use both [[#optional-params|optional parameters]] <code>additionalfeeoutputindex=</code> and <code>maxadditionalfeecontribution=</code> to indicate which output and how much the receiver can substract fee.
+If such is the case, the sender must use both [[#optional-params|optional parameters]] <code>additionalfeeoutputindex=</code> and <code>maxadditionalfeecontribution=</code> to indicate which output and how much the receiver can subtract fee.
There is several cases where a fee output is useful:
@@ -273,7 +273,7 @@ The sender should check the payjoin proposal before signing it to prevent a mali
* For each outputs in the proposal:
** Verify that no keypaths is in the PSBT output
** If the output is the [[#fee-output|fee output]]:
-*** The amount that was substracted from the output's value is less than or equal to <code>maxadditionalfeecontribution</code>. Let's call this amount <code>actual contribution</code>.
+*** The amount that was subtracted from the output's value is less than or equal to <code>maxadditionalfeecontribution</code>. Let's call this amount <code>actual contribution</code>.
*** Make sure the actual contribution is only paying fee: The <code>actual contribution</code> is less than or equals to the difference of absolute fee between the payjoin proposal and the original PSBT.
*** Make sure the actual contribution is only paying for fee incurred by additional inputs: <code>actual contribution</code> is less than or equals to <code>originalPSBTFeeRate * vsize(sender_input_type) * (count(payjoin_proposal_inputs) - count(original_psbt_inputs))</code>. (see [[#fee-output|Fee output]] section)
** If the output is the payment output and payment output substitution is allowed.
@@ -344,7 +344,7 @@ On top of this the receiver can poison analysis by randomly faking a round amoun
===<span id="output-substitution"></span>Payment output substitution===
-Unless disallowed by sender explicitely via `disableoutputsubstitution=true` or by the BIP21 url via query parameter the `pjos=0`, the receiver is free to decrease the amount, remove, or change the scriptPubKey output paying to himself.
+Unless disallowed by sender explicitly via `disableoutputsubstitution=true` or by the BIP21 url via query parameter the `pjos=0`, the receiver is free to decrease the amount, remove, or change the scriptPubKey output paying to himself.
Note that if payment output substitution is disallowed, the reveiver can still increase the amount of the output. (See [[#reference-impl|the reference implementation]])
For example, if the sender's scriptPubKey type is P2WPKH while the receiver's payment output in the original PSBT is P2SH, then the receiver can substitute the payment output to be P2WPKH to match the sender's scriptPubKey type.
@@ -413,7 +413,7 @@ Here is pseudo code of a sender implementation.
The <code>signedPSBT</code> represents a PSBT which has been fully signed, but not yet finalized.
We then prepare <code>originalPSBT</code> from the <code>signedPSBT</code> via the <code>CreateOriginalPSBT</code> function and get back the <code>proposal</code>.
-While we verify the <code>proposal</code>, we also import into it informations about our own inputs and outputs from the <code>signedPSBT</code>.
+While we verify the <code>proposal</code>, we also import into it information about our own inputs and outputs from the <code>signedPSBT</code>.
At the end of this <code>RequestPayjoin</code>, the proposal is verified and ready to be signed.
We logged the different PSBT involved, and show the result in our [[#test-vectors|test vectors]].
@@ -557,7 +557,7 @@ public async Task<PSBT> RequestPayjoin(
if (output.OriginalTxOut == feeOutput)
{
var actualContribution = feeOutput.Value - proposedPSBTOutput.Value;
- // The amount that was substracted from the output's value is less than or equal to maxadditionalfeecontribution
+ // The amount that was subtracted from the output's value is less than or equal to maxadditionalfeecontribution
if (actualContribution > optionalParameters.MaxAdditionalFeeContribution)
throw new PayjoinSenderException("The actual contribution is more than maxadditionalfeecontribution");
// Make sure the actual contribution is only paying fee
@@ -642,7 +642,7 @@ A successful exchange with:
{| class="wikitable"
!InputScriptType
-!Orginal PSBT Fee rate
+!Original PSBT Fee rate
!maxadditionalfeecontribution
!additionalfeeoutputindex
|-
diff --git a/bip-0080.mediawiki b/bip-0080.mediawiki
index 0cade19..f367c71 100644
--- a/bip-0080.mediawiki
+++ b/bip-0080.mediawiki
@@ -35,7 +35,7 @@ Each level has a special meaning, described in the chapters below.
===Purpose===
-Purpose is a constant set following the BIP43 recommendation to: the ASCII value of "80" with the most signifigant bit set to indicate hardened derivation (0x80000050). It indicates that the subtree of this node is used according to this specification.
+Purpose is a constant set following the BIP43 recommendation to: the ASCII value of "80" with the most significant bit set to indicate hardened derivation (0x80000050). It indicates that the subtree of this node is used according to this specification.
Hardened derivation is used at this level.
diff --git a/bip-0081.mediawiki b/bip-0081.mediawiki
index 96ac8d1..923917c 100644
--- a/bip-0081.mediawiki
+++ b/bip-0081.mediawiki
@@ -35,7 +35,7 @@ Each level has a special meaning, described in the chapters below.
===Purpose===
-Purpose is a constant set following the BIP43 recommendation to: the ASCII value of "81" with the most signifigant bit set to indicate hardened derivation (0x80000051). It indicates that the subtree of this node is used according to this specification.
+Purpose is a constant set following the BIP43 recommendation to: the ASCII value of "81" with the most significant bit set to indicate hardened derivation (0x80000051). It indicates that the subtree of this node is used according to this specification.
Hardened derivation is used at this level.
diff --git a/bip-0083.mediawiki b/bip-0083.mediawiki
index d7bbe8e..c669001 100644
--- a/bip-0083.mediawiki
+++ b/bip-0083.mediawiki
@@ -53,7 +53,7 @@ p //' n instead of p / 0' / n
Rather than specifying upfront which path is to be used for a specific purpose (i.e. external invoicing vs. internal change), different applications can specify arbitrary parent nodes and derivation paths. This allows for nesting of sublevels to arbitrary depth with application-specified semantics. Rather than trying to specify use cases upfront, we leave the design completely open-ended. Different applications can exchange these mappings for interoperability. Eventually, if certain mappings become popular, application user interfaces can provide convenient shortcuts or use them as defaults.
-Note that BIP32 suggests reserving child 0 for the derivation of signing keys rather than sublevels. It is not really necessary to reserve signing key parents, however, as each key's parent's path can be explicitly stated. But unless we reserve a child for sublevel derivation, we lose the ability to nest deeper levels into the hierarchy. While we could reserve any arbitrary index for nesting sublevels, reserving child 0 seems simplest to implement, leaving all indices > 0 for contiguously indexed signing keys. We could also use MAX_INDEX (2<sup>31</sup> - 1) for this purpose. However, we believe doing so introduces more ideosyncracies into the semantics and will present a problem if we ever decide to extend the scheme to use indices larger than 31 bits.
+Note that BIP32 suggests reserving child 0 for the derivation of signing keys rather than sublevels. It is not really necessary to reserve signing key parents, however, as each key's parent's path can be explicitly stated. But unless we reserve a child for sublevel derivation, we lose the ability to nest deeper levels into the hierarchy. While we could reserve any arbitrary index for nesting sublevels, reserving child 0 seems simplest to implement, leaving all indices > 0 for contiguously indexed signing keys. We could also use MAX_INDEX (2<sup>31</sup> - 1) for this purpose. However, we believe doing so introduces more idiosyncrasies into the semantics and will present a problem if we ever decide to extend the scheme to use indices larger than 31 bits.
==Use Cases==
diff --git a/bip-0085.mediawiki b/bip-0085.mediawiki
index 738227a..7311d8a 100644
--- a/bip-0085.mediawiki
+++ b/bip-0085.mediawiki
@@ -315,7 +315,7 @@ Entropy = log2(R ** L)<br>
|-
| 30 || 192.0
|-
-| 20 || 512.0
+| 80 || 512.0
|}
INPUT:
diff --git a/bip-0099.mediawiki b/bip-0099.mediawiki
index 8882e00..156eec0 100644
--- a/bip-0099.mediawiki
+++ b/bip-0099.mediawiki
@@ -56,7 +56,7 @@ development, diversity, etc) to fork the Bitcoin Core software and it's good
that there's many alternative implementations of the protocol (forks
of Bitcoin Core or written from scratch).
-But sometimes a bug in the reimplementaion of the consensus
+But sometimes a bug in the reimplementation of the consensus
validation rules can prevent users of alternative implementation from
following the longest (most work) valid chain. This can result in
those users losing coins or being defrauded, making reimplementations
diff --git a/bip-0109.mediawiki b/bip-0109.mediawiki
index 69b265b..4822d4a 100644
--- a/bip-0109.mediawiki
+++ b/bip-0109.mediawiki
@@ -37,7 +37,7 @@ In particular:
* The coinbase scriptSig is not counted
* Signature operations in un-executed branches of a Script are not counted
-* OP_CHECKMULTISIG evaluations are counted accurately; if the signature for a 1-of-20 OP_CHECKMULTISIG is satisified by the public key nearest the top of the execution stack, it is counted as one signature operation. If it is satisfied by the public key nearest the bottom of the execution stack, it is counted as twenty signature operations.
+* OP_CHECKMULTISIG evaluations are counted accurately; if the signature for a 1-of-20 OP_CHECKMULTISIG is satisfied by the public key nearest the top of the execution stack, it is counted as one signature operation. If it is satisfied by the public key nearest the bottom of the execution stack, it is counted as twenty signature operations.
* Signature operations involving invalidly encoded signatures or public keys are not counted towards the limit
=== Add a new limit of 1,300,000,000 bytes hashed to compute transaction signatures per block ===
diff --git a/bip-0112.mediawiki b/bip-0112.mediawiki
index 63a7797..d6ed546 100644
--- a/bip-0112.mediawiki
+++ b/bip-0112.mediawiki
@@ -36,7 +36,7 @@ When executed, if any of the following conditions are true, the script interpret
Otherwise, script execution will continue as if a NOP had been executed.
-BIP 68 prevents a non-final transaction from being selected for inclusion in a block until the corresponding input has reached the specified age, as measured in block-height or block-time. By comparing the argument to CHECKSEQUENCEVERIFY against the nSequence field, we indirectly verify a desired minimum age of the
+BIP 68 prevents a non-final transaction from being selected for inclusion in a block until the corresponding input has reached the specified age, as measured in block-height or block-time. By comparing the argument to CHECKSEQUENCEVERIFY against the nSequence field, we indirectly verify a desired minimum age of
the output being spent; until that relative age has been reached any script execution pathway including the CHECKSEQUENCEVERIFY will fail to validate, causing the transaction not to be selected for inclusion in a block.
diff --git a/bip-0114.mediawiki b/bip-0114.mediawiki
index 410e84c..5b07137 100644
--- a/bip-0114.mediawiki
+++ b/bip-0114.mediawiki
@@ -111,7 +111,7 @@ The advantages of the current proposal are:
* If different parties in a contract do not want to expose their scripts to each other, they may provide only <code>H(Subscript)</code> and keep the <code>Subscript</code> private until redemption.
* If they are willing to share the actual scripts, they may combine them into one <code>Subscript</code> for each branch, saving some <code>nOpCount</code> and a few bytes of witness space.
-The are some disadvantages, but only when the redemption condition is very complicated:
+There are some disadvantages, but only when the redemption condition is very complicated:
* It may require more branches than a general MAST design (as shown in the previous example) and take more witness space in redemption
* Creation and storage of the MAST structure may take more time and space. However, such additional costs affect only the related parties in the contract but not any other Bitcoin users.
diff --git a/bip-0126.mediawiki b/bip-0126.mediawiki
index 4cfa292..2c04eb4 100644
--- a/bip-0126.mediawiki
+++ b/bip-0126.mediawiki
@@ -14,7 +14,7 @@
When a Bitcoin transaction contains inputs that reference previous transaction outputs sent to different Bitcoin addresses, personally identifiable information of the user will leak into the blockchain in an uncontrolled manner. While undesirable, these transactions are frequently unavoidable due to the natural fragmentation of wallet balances over time.
-This document proposes a set of best practice guidelines which minimize the uncontrolled disclosure of personally identifiable information by defining standard forms for transactions containing heterogenous input scripts.
+This document proposes a set of best practice guidelines which minimize the uncontrolled disclosure of personally identifiable information by defining standard forms for transactions containing heterogeneous input scripts.
==Copyright==
@@ -23,8 +23,8 @@ This BIP is in the public domain.
==Definitions==
* '''Heterogenous input script transaction (HIT)''': A transaction containing multiple inputs where the scripts of the previous transaction outputs being consumed are not identical (e.g. a transaction spending outputs which were sent to more than one Bitcoin address)
-* '''Unavoidable heterogenous input script transaction''': A HIT created as a result of a user’s desire to create a new output with a value larger than the value of his wallet's largest existing unspent output
-* '''Intentional heterogenous input script transaction''': A HIT created as part of a user protection protocol for reducing uncontrolled disclosure of personally-identifying information (PII)
+* '''Unavoidable heterogeneous input script transaction''': A HIT created as a result of a user’s desire to create a new output with a value larger than the value of his wallet's largest existing unspent output
+* '''Intentional heterogeneous input script transaction''': A HIT created as part of a user protection protocol for reducing uncontrolled disclosure of personally-identifying information (PII)
Throughout this procedure, when input scripts are evaluated for uniqueness, "input script" should be interpreted to mean, "the script of the previous output referenced by an input to a transaction".
@@ -33,10 +33,10 @@ Throughout this procedure, when input scripts are evaluated for uniqueness, "inp
The recommendations in this document are designed to accomplish three goals:
# Maximise the effectiveness of user-protecting protocols: Users may find that protection protocols are counterproductive if such transactions have a distinctive fingerprint which renders them ineffective.
-# Minimise the adverse consequences of unavoidable heterogenous input transactions: If unavoidable HITs are indistinguishable from intentional HITs, a user creating an unavoidable HIT benefits from ambiguity with respect to graph analysis.
+# Minimise the adverse consequences of unavoidable heterogeneous input transactions: If unavoidable HITs are indistinguishable from intentional HITs, a user creating an unavoidable HIT benefits from ambiguity with respect to graph analysis.
# Limiting the effect on UTXO set growth: To date, non-standardized intentional HITs tend to increase the network's UTXO set with each transaction; this standard attempts to minimize this effect by standardizing unavoidable and intentional HITs to limit UTXO set growth.
-In order to achieve these goals, this specification proposes a set of best practices for heterogenous input script transaction creation. These practices accommodate all applicable requirements of both intentional and unavoidable HITs while maximising the effectiveness of both in terms of preventing uncontrolled disclosure of PII.
+In order to achieve these goals, this specification proposes a set of best practices for heterogeneous input script transaction creation. These practices accommodate all applicable requirements of both intentional and unavoidable HITs while maximising the effectiveness of both in terms of preventing uncontrolled disclosure of PII.
In order to achieve this, two forms of HIT are proposed: Standard form and alternate form.
@@ -44,7 +44,7 @@ In order to achieve this, two forms of HIT are proposed: Standard form and alter
Applications which wish to comply both with this procedure and BIP69 should apply this procedure prior to applying BIP69.
-==Standard form heterogenous input script transaction==
+==Standard form heterogeneous input script transaction==
===Rules===
@@ -63,7 +63,7 @@ The requirement that all output scripts are unique prevents address reuse. Restr
The requirement for at least one pair of outputs in an intentional HIT to be of equal value results in optimal behavior, and causes intentional HITs to resemble unavoidable HITs.
-==Alternate form heterogenous input script transactions==
+==Alternate form heterogeneous input script transactions==
The formation of a standard form HIT is not possible in the following cases:
@@ -100,7 +100,7 @@ An HIT formed via the preceding procedure will adhere to the following condition
## The sum of the inputs in the set minus the value of the change output is equal to the standard value with a tolerance equal to the transaction fee.
## Change outputs with a value of zero (virtual change outputs) are permitted. The are defined for the purpose of testing whether or not a HIT adheres to this specification but are not present in the version of the transaction which is broadcast to the network.
-==Non-compliant heterogenous input script transactions==
+==Non-compliant heterogeneous input script transactions==
If a user wishes to create an output that is larger than half the total size of their spendable outputs, or if their inputs are not distributed in a manner in which the alternate form procedure can be completed, then the user can not create a transaction which is compliant with this procedure.
diff --git a/bip-0127.mediawiki b/bip-0127.mediawiki
index 44a90d7..87071d8 100644
--- a/bip-0127.mediawiki
+++ b/bip-0127.mediawiki
@@ -124,7 +124,7 @@ message FinalProof {
// Bitcoin transaction.
bytes proof_tx = 1;
- // The metadata of the ouputs used in the proof transaction.
+ // The metadata of the outputs used in the proof transaction.
repeated OutputMeta output_metadata = 2;
}
diff --git a/bip-0129.mediawiki b/bip-0129.mediawiki
index 608c724..b5dfae8 100644
--- a/bip-0129.mediawiki
+++ b/bip-0129.mediawiki
@@ -47,11 +47,14 @@ Concerns #4 and #5 should be handled by Signers and are out of scope of this pro
==Specification==
===Prerequisites===
-This proposal assumes the parties in the multisig support [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP-0032], [https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki BIP-0322], [https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md the descriptor language] and [https://tools.ietf.org/html/rfc3686 AES encryption].
+This proposal assumes the parties in the multisig support [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP-0032], [https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki BIP-0322], [https://github.com/bitcoin/bips/blob/master/bip-0380.mediawiki BIP-0380 Output Script Descriptors] ([https://github.com/bitcoin/bips/blob/master/bip-0381.mediawiki BIP-0381],[https://github.com/bitcoin/bips/blob/master/bip-0382.mediawiki BIP-0382],[https://github.com/bitcoin/bips/blob/master/bip-0383.mediawiki BIP-0383]) and [https://tools.ietf.org/html/rfc3686 AES encryption].
===File Extensions===
All descriptor and key records should have a <tt>.bsms</tt> file extension. Encrypted data should have a <tt>.dat</tt> extension.
+===Newline===
+This specification uses line feed (LF) control character <tt>\n</tt>.
+
===Roles===
====Coordinator====
@@ -141,7 +144,7 @@ Whereas:
* Password = "No SPOF"
* Salt = <tt>TOKEN</tt>
* c = 2048
-* dkLen = 256
+* dkLen = 256 bits (32 bytes)
* DKey = Derived <tt>ENCRYPTION_KEY</tt>
====Encryption Scheme====
diff --git a/bip-0132.mediawiki b/bip-0132.mediawiki
index e7aed29..173c919 100644
--- a/bip-0132.mediawiki
+++ b/bip-0132.mediawiki
@@ -48,7 +48,7 @@ The author doesn't believe this is a problem because a BIP cannot be forced on c
== Process ==
-* '''Submit for Comments.''' The first BIP champion named in the proposal can call a &quot;submit for comments&quot; at any time by posting to the [https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev Dev Mailing List] mailling with the BIP number and a statement that the champion intends to immediately submit the BIP for comments.
+* '''Submit for Comments.''' The first BIP champion named in the proposal can call a &quot;submit for comments&quot; at any time by posting to the [https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev Dev Mailing List] mailing with the BIP number and a statement that the champion intends to immediately submit the BIP for comments.
** The BIP must have been assigned BIP-number (i.e. been approved by the BIP editor) to be submitted for comments.
* '''Comments.'''
** After a BIP has been submitted for comments, a two-week waiting period begins in which the community should transition from making suggestions about a proposal to publishing their opinions or concerns on the proposal.
diff --git a/bip-0133.mediawiki b/bip-0133.mediawiki
index c109f12..b37370d 100644
--- a/bip-0133.mediawiki
+++ b/bip-0133.mediawiki
@@ -5,7 +5,7 @@
Author: Alex Morcos <morcos@chaincode.com>
Comments-Summary: No comments yet.
Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0133
- Status: Draft
+ Status: Final
Type: Standards Track
Created: 2016-02-13
License: PD
diff --git a/bip-0137.mediawiki b/bip-0137.mediawiki
index 43addba..575440b 100644
--- a/bip-0137.mediawiki
+++ b/bip-0137.mediawiki
@@ -116,7 +116,7 @@ Since this format includes P2PKH keys, it is backwards compatible, but keep in m
==Implications==
-Message signing is an important use case and potentially underused due to the fact that, up until now, there has not been a formal specification for how wallets can sign messages using Bitcoin private keys. Bitcoin wallets should be interoperable and use the same conventions for determing a signature's validity. This BIP can also be updated as new signature formats emerge.
+Message signing is an important use case and potentially underused due to the fact that, up until now, there has not been a formal specification for how wallets can sign messages using Bitcoin private keys. Bitcoin wallets should be interoperable and use the same conventions for determining a signature's validity. This BIP can also be updated as new signature formats emerge.
==Acknowledgements==
diff --git a/bip-0141.mediawiki b/bip-0141.mediawiki
index eb2fc74..117ca59 100644
--- a/bip-0141.mediawiki
+++ b/bip-0141.mediawiki
@@ -83,19 +83,23 @@ If all transactions in a block do not have witness data, the commitment is optio
=== Witness program ===
-A <code>scriptPubKey</code> (or <code>redeemScript</code> as defined in BIP16/P2SH) that consists of a select subset of opcodes (<code>OP_0,OP_1,OP_2,...,OP_16</code>) followed by a data push between 2 and 40 bytes gets a new special meaning. The value of the first push is called the "version byte". The following byte vector pushed is called the "witness program".
+A <code>scriptPubKey</code> (or <code>redeemScript</code> as defined in BIP16/P2SH) that consists of a 1-byte push opcode (one of <code>OP_0,OP_1,OP_2,...,OP_16</code>) followed by a direct data push between 2 and 40 bytes gets a new special meaning. The value of the first push is called the "version byte". The following byte vector pushed is called the "witness program".
+In more detail, this means a <code>scriptPubKey</code> or <code>redeemScript</code> which consists of (in order):
+* First, byte 0x00 (<code>OP_0</code>) or any byte between 0x51 (<code>OP_1</code>) and 0x60 (<code>OP_16</code>) inclusive (the version byte).
+* Then, a byte ''L'' between 0x02 (push of 2 bytes) and 0x28 (push of 40 bytes) inclusive.
+* Finally, ''L'' arbitrary bytes (the witness program).
There are two cases in which witness validation logic are triggered. Each case determines the location of the witness version byte and program, as well as the form of the scriptSig:
# Triggered by a <code>scriptPubKey</code> that is exactly a push of a version byte, plus a push of a witness program. The scriptSig must be exactly empty or validation fails. (''"native witness program"'')
# Triggered when a <code>scriptPubKey</code> is a P2SH script, and the BIP16 <code>redeemScript</code> pushed in the <code>scriptSig</code> is exactly a push of a version byte plus a push of a witness program. The <code>scriptSig</code> must be exactly a push of the BIP16 <code>redeemScript</code> or validation fails. (''"P2SH witness program"'')
-If the version byte is 0, and the witness program is 20 bytes:
+If the version byte is 0, and the witness program is 20 bytes (''L = 20''):
* It is interpreted as a pay-to-witness-public-key-hash (P2WPKH) program.
* The witness must consist of exactly 2 items (≤ 520 bytes each). The first one a signature, and the second one a public key.
* The HASH160 of the public key must match the 20-byte witness program.
* After normal script evaluation, the signature is verified against the public key with CHECKSIG operation. The verification must result in a single TRUE on the stack.
-If the version byte is 0, and the witness program is 32 bytes:
+If the version byte is 0, and the witness program is 32 bytes (''L = 32''):
* It is interpreted as a pay-to-witness-script-hash (P2WSH) program.
* The witness must consist of an input stack to feed to the script, followed by a serialized script (<code>witnessScript</code>).
* The <code>witnessScript</code> (≤ 10,000 bytes) is popped off the initial witness stack. SHA256 of the <code>witnessScript</code> must match the 32-byte witness program.
diff --git a/bip-0143.mediawiki b/bip-0143.mediawiki
index ebf0d7c..9935eaa 100644
--- a/bip-0143.mediawiki
+++ b/bip-0143.mediawiki
@@ -39,12 +39,12 @@ A new transaction digest algorithm is defined, but only applicable to sigops in
9. nLocktime of the transaction (4-byte little endian)
10. sighash type of the signature (4-byte little endian)
-Semantics of the original sighash types remain unchanged, except the followings:
+Semantics of the original sighash types remain unchanged, except the following:
# The way of serialization is changed;
# All sighash types commit to the amount being spent by the signed input;
# <code>FindAndDelete</code> of the signature is not applied to the <code>scriptCode</code>;
# <code>OP_CODESEPARATOR</code>(s) after the last executed <code>OP_CODESEPARATOR</code> are not removed from the <code>scriptCode</code> (the last executed <code>OP_CODESEPARATOR</code> and any script before it are always removed);
-# <code>SINGLE</code> does not commit to the input index. When <code>ANYONECANPAY</code> is not set, the semantics are unchanged since <code>hashPrevouts</code> and <code>outpoint</code> together implictly commit to the input index. When <code>SINGLE</code> is used with <code>ANYONECANPAY</code>, omission of the index commitment allows permutation of the input-output pairs, as long as each pair is located at an equivalent index.
+# <code>SINGLE</code> does not commit to the input index. When <code>ANYONECANPAY</code> is not set, the semantics are unchanged since <code>hashPrevouts</code> and <code>outpoint</code> together implicitly commit to the input index. When <code>SINGLE</code> is used with <code>ANYONECANPAY</code>, omission of the index commitment allows permutation of the input-output pairs, as long as each pair is located at an equivalent index.
The items 1, 4, 7, 9, 10 have the same meaning as the original algorithm. <ref name=wiki></ref>
diff --git a/bip-0151.mediawiki b/bip-0151.mediawiki
index 793c244..8bc1197 100644
--- a/bip-0151.mediawiki
+++ b/bip-0151.mediawiki
@@ -85,7 +85,7 @@ a 64 bit nonce and a 64 bit counter into 64 bytes of output. This output is used
Poly1305, also by Daniel Bernstein [4], is a one-time Carter-Wegman MAC that computes a 128 bit integrity tag given a message and a single-use
256 bit secret key.
-The chacha20-poly1305@openssh.com specified and defined by openssh [5] combines these two primitives into an authenticated encryption mode. The construction used is based on that proposed for TLS by Adam Langley [6], but differs in the layout of data passed to the MAC and in the addition of encyption of the packet lengths.
+The chacha20-poly1305@openssh.com specified and defined by openssh [5] combines these two primitives into an authenticated encryption mode. The construction used is based on that proposed for TLS by Adam Langley [6], but differs in the layout of data passed to the MAC and in the addition of encryption of the packet lengths.
<code>K_1</code> must be used to only encrypt the payload size of the encrypted message to avoid leaking information by revealing the message size.
diff --git a/bip-0155.mediawiki b/bip-0155.mediawiki
index 3e7b0d8..0ec6801 100644
--- a/bip-0155.mediawiki
+++ b/bip-0155.mediawiki
@@ -117,6 +117,11 @@ The list of reserved network IDs is as follows:
| <code>CJDNS</code>
| 16
| Cjdns overlay network address
+|-
+| <code>0x07</code>
+| <code>YGGDRASIL</code>
+| 16
+| Yggdrasil overlay network address
|}
Clients are RECOMMENDED to gossip addresses from all known networks even if they are currently not connected to some of them. That could help multi-homed nodes and make it more difficult for an observer to tell which networks a node is connected to.
@@ -184,6 +189,10 @@ I2P addresses MUST be sent with the <code>I2P</code> network ID, with the decode
Cjdns addresses are simply IPv6 addresses in the <code>fc00::/8</code> range<ref>[https://github.com/cjdelisle/cjdns/blob/6e46fa41f5647d6b414612d9d63626b0b952746b/doc/Whitepaper.md#pulling-it-all-together Cjdns whitepaper: Pulling It All Together]</ref>. They MUST be sent with the <code>CJDNS</code> network ID.
+==Appendix E: Yggdrasil address encoding==
+
+Yggdrasil addresses are simply IPv6 addresses in the <code>0200::/7</code> range<ref>[https://yggdrasil-network.github.io/faq.html#will-yggdrasil-conflict-with-my-network-routing Yggdrasil FAQ]</ref>. They MUST be sent with the <code>YGGDRASIL</code> network ID.
+
==References==
<references/>
diff --git a/bip-0158.mediawiki b/bip-0158.mediawiki
index 054aa1f..1fadcc7 100644
--- a/bip-0158.mediawiki
+++ b/bip-0158.mediawiki
@@ -39,9 +39,6 @@ that is designed to reduce the filter size for regular wallets.
''CompactSize'' is a compact encoding of unsigned integers used in the Bitcoin
P2P protocol.
-''Data pushes'' are byte vectors pushed to the stack according to the rules of
-Bitcoin script.
-
''Bit streams'' are readable and writable streams of individual bits. The
following functions are used in the pseudocode in this document:
* <code>new_bit_stream</code> instantiates a new writable bit stream
@@ -85,7 +82,7 @@ one is able to select both Parameters independently, then more optimal values
can be
selected<ref>https://gist.github.com/sipa/576d5f09c3b86c3b1b75598d799fc845</ref>.
Set membership queries against the hash outputs will have a false positive rate
-of <code>M</code>. To avoid integer overflow, the number of items <code>N</code>
+of <code>1 / M</code>. To avoid integer overflow, the number of items <code>N</code>
MUST be <2^32 and <code>M</code> MUST be <2^32.
The items are first passed through the pseudorandom function ''SipHash'', which
@@ -189,7 +186,7 @@ golomb_decode(stream, P: uint) -> uint64:
A GCS is constructed from four parameters:
* <code>L</code>, a vector of <code>N</code> raw items
* <code>P</code>, the bit parameter of the Golomb-Rice coding
-* <code>M</code>, the target false positive rate
+* <code>M</code>, the inverse of the target false positive rate
* <code>k</code>, the 128-bit key used to randomize the SipHash outputs
The result is a byte vector with a minimum size of <code>N * (P + 1)</code>
diff --git a/bip-0158/gentestvectors.go b/bip-0158/gentestvectors.go
index 3435eb3..e51b984 100644
--- a/bip-0158/gentestvectors.go
+++ b/bip-0158/gentestvectors.go
@@ -207,7 +207,7 @@ func main() {
prevOutputScripts, err := fetchPrevOutputScripts(client, block)
if err != nil {
- fmt.Println("Couldn't fetch prev output scipts: ", err)
+ fmt.Println("Couldn't fetch prev output scripts: ", err)
return
}
diff --git a/bip-0173.mediawiki b/bip-0173.mediawiki
index 1fdd8be..7087fff 100644
--- a/bip-0173.mediawiki
+++ b/bip-0173.mediawiki
@@ -11,6 +11,7 @@
Created: 2017-03-20
License: BSD-2-Clause
Replaces: 142
+ Superseded-By: 350
</pre>
==Introduction==
@@ -403,3 +404,12 @@ separator).
This document is inspired by the [https://rusty.ozlabs.org/?p=578 address proposal] by Rusty Russell, the
[https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2014-February/004402.html base32] proposal by Mark Friedenbach, and had input from Luke Dashjr,
Johnson Lau, Eric Lombrozo, Peter Todd, and various other reviewers.
+
+==Disclosures (added 2024)==
+
+Due to an oversight in the design of bech32, this checksum scheme is not always
+robust against
+[[https://gist.github.com/sipa/a9845b37c1b298a7301c33a04090b2eb|the insertion
+and deletion of fewer than 5 consecutive characters]]. Due to this weakness,
+[[bip-0350.mediawiki|BIP-350]] proposes using the scheme described in this BIP
+only for Native Segwit v0 outputs.
diff --git a/bip-0174.mediawiki b/bip-0174.mediawiki
index 5e70a11..95a5573 100644
--- a/bip-0174.mediawiki
+++ b/bip-0174.mediawiki
@@ -633,7 +633,7 @@ values are valid, then it does not matter which is chosen as either way the tran
===Proprietary Use Type===
For all global, per-input, and per-output maps, the type <tt>0xFC</tt> is reserved for proprietary use.
-The proprietary use type requires keys that follow the type with a compact size unsigned integer representing the length of the string identifer, followed by the string identifier, then a subtype, and finally any key data.
+The proprietary use type requires keys that follow the type with a compact size unsigned integer representing the length of the string identifier, followed by the string identifier, then a subtype, and finally any key data.
The identifier can be any variable length string that software can use to identify whether the particular data in the proprietary type can be used by it.
It can also be the empty string although this is not recommended.
@@ -800,7 +800,7 @@ A MIME type name will be added to this document once one has been registered.
==Extensibility==
The Partially Signed Transaction format can be extended in the future by adding
-new types for key-value pairs. Backwards compatibilty will still be maintained as those new
+new types for key-value pairs. Backwards compatibility will still be maintained as those new
types will be ignored and passed-through by signers which do not know about them.
===Version Numbers===
diff --git a/bip-0174/build.sh b/bip-0174/build.sh
new file mode 100755
index 0000000..2de1e56
--- /dev/null
+++ b/bip-0174/build.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+pdflatex -output-format=pdf coinjoin-workflow.tex && \
+inkscape --with-gui --export-text-to-path \
+ --export-plain-svg=coinjoin-workflow.svg coinjoin-workflow.pdf && \
+pdflatex -output-format=pdf multisig-workflow.tex && \
+inkscape --with-gui --export-text-to-path \
+ --export-plain-svg=multisig-workflow.svg multisig-workflow.pdf && \
+echo '"success"'
diff --git a/bip-0174/coinjoin-workflow.svg b/bip-0174/coinjoin-workflow.svg
index 4c2a041..3b6b952 100644
--- a/bip-0174/coinjoin-workflow.svg
+++ b/bip-0174/coinjoin-workflow.svg
@@ -1,8 +1,54 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="420.819pt" height="118.266pt"
- viewBox="0 0 420.819 118.266" style="background-color:white" version="1.1">
-<defs>
-<g>
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="420.819pt"
+ height="122.694pt"
+ viewBox="0 0 420.819 122.694"
+ version="1.2"
+ id="svg1044"
+ sodipodi:docname="coinjoin-workflow.svg"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
+ <metadata
+ id="metadata1048">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview1046"
+ showgrid="false"
+ inkscape:zoom="0.50080914"
+ inkscape:cx="280.546"
+ inkscape:cy="81.796"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg1044" />
+<defs id="defs109">
+<g id="g104">
<symbol overflow="visible" id="glyph0-0">
<path style="stroke:none;" d=""/>
</symbol>
@@ -107,7 +153,7 @@
</symbol>
</g>
<clipPath id="clip1">
- <path d="M 19 53 L 128 53 L 128 118.265625 L 19 118.265625 Z M 19 53 "/>
+ <path d="M 19 57 L 128 57 L 128 122.695312 L 19 122.695312 Z M 19 57 "/>
</clipPath>
</defs>
<g id="surface1">
@@ -376,281 +422,1133 @@
<use xlink:href="#glyph0-9" x="387.534513" y="49.823"/>
<use xlink:href="#glyph0-26" x="391.353178" y="49.823"/>
</g>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 112.644531 64.734375 L 34.269531 64.734375 C 32.070312 64.734375 30.285156 66.515625 30.285156 68.71875 L 30.285156 110.5625 C 30.285156 112.761719 32.070312 114.546875 34.269531 114.546875 L 112.644531 114.546875 C 114.84375 114.546875 116.628906 112.761719 116.628906 110.5625 L 116.628906 68.71875 C 116.628906 66.515625 114.84375 64.734375 112.644531 64.734375 Z M 112.644531 64.734375 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 112.644531 69.160156 L 34.269531 69.160156 C 32.070312 69.160156 30.285156 70.945312 30.285156 73.144531 L 30.285156 114.988281 C 30.285156 117.191406 32.070312 118.976562 34.269531 118.976562 L 112.644531 118.976562 C 114.84375 118.976562 116.628906 117.191406 116.628906 114.988281 L 116.628906 73.144531 C 116.628906 70.945312 114.84375 69.160156 112.644531 69.160156 Z M 112.644531 69.160156 "/>
<g clip-path="url(#clip1)" clip-rule="nonzero">
-<path style="fill:none;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 39.187531 24.905625 L -39.187469 24.905625 C -41.386687 24.905625 -43.171844 23.124375 -43.171844 20.92125 L -43.171844 -20.9225 C -43.171844 -23.121719 -41.386687 -24.906875 -39.187469 -24.906875 L 39.187531 -24.906875 C 41.38675 -24.906875 43.171906 -23.121719 43.171906 -20.9225 L 43.171906 20.92125 C 43.171906 23.124375 41.38675 24.905625 39.187531 24.905625 Z M 39.187531 24.905625 " transform="matrix(1,0,0,-1,73.457,89.64)"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-1" x="37.094" y="75.167"/>
- <use xlink:href="#glyph0-2" x="43.736065" y="75.167"/>
- <use xlink:href="#glyph0-3" x="46.116131" y="75.167"/>
- <use xlink:href="#glyph0-4" x="48.496196" y="75.167"/>
- <use xlink:href="#glyph0-5" x="52.924571" y="75.167"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-5" x="60.670493" y="75.167"/>
- <use xlink:href="#glyph0-32" x="65.098869" y="75.167"/>
- <use xlink:href="#glyph0-8" x="69.692623" y="75.167"/>
- <use xlink:href="#glyph0-6" x="73.290118" y="75.167"/>
- <use xlink:href="#glyph0-7" x="76.694339" y="75.167"/>
- <use xlink:href="#glyph0-4" x="81.482364" y="75.167"/>
- <use xlink:href="#glyph0-8" x="85.91074" y="75.167"/>
- <use xlink:href="#glyph0-9" x="89.508235" y="75.167"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-8" x="96.644445" y="75.167"/>
- <use xlink:href="#glyph0-15" x="100.24194" y="75.167"/>
- <use xlink:href="#glyph0-5" x="105.389616" y="75.167"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-17" x="36.852" y="87.122"/>
- <use xlink:href="#glyph0-5" x="41.999675" y="87.122"/>
- <use xlink:href="#glyph0-8" x="46.428051" y="87.122"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-14" x="49.746593" y="87.122"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-16" x="56.275085" y="87.122"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-6" x="60.987395" y="87.122"/>
- <use xlink:href="#glyph0-33" x="64.391615" y="87.122"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-9" x="72.579876" y="87.122"/>
- <use xlink:href="#glyph0-5" x="76.398541" y="87.122"/>
- <use xlink:href="#glyph0-6" x="80.826916" y="87.122"/>
- <use xlink:href="#glyph0-3" x="84.231137" y="87.122"/>
- <use xlink:href="#glyph0-7" x="86.611202" y="87.122"/>
- <use xlink:href="#glyph0-2" x="91.399228" y="87.122"/>
- <use xlink:href="#glyph0-3" x="93.779293" y="87.122"/>
- <use xlink:href="#glyph0-31" x="96.159358" y="87.122"/>
- <use xlink:href="#glyph0-5" x="100.4901" y="87.122"/>
- <use xlink:href="#glyph0-25" x="104.918476" y="87.122"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-8" x="41.217" y="99.077"/>
- <use xlink:href="#glyph0-6" x="44.814495" y="99.077"/>
- <use xlink:href="#glyph0-7" x="48.218715" y="99.077"/>
- <use xlink:href="#glyph0-17" x="53.006741" y="99.077"/>
- <use xlink:href="#glyph0-9" x="58.154416" y="99.077"/>
- <use xlink:href="#glyph0-7" x="61.973081" y="99.077"/>
- <use xlink:href="#glyph0-4" x="66.761106" y="99.077"/>
- <use xlink:href="#glyph0-8" x="71.189482" y="99.077"/>
- <use xlink:href="#glyph0-3" x="74.786977" y="99.077"/>
- <use xlink:href="#glyph0-16" x="77.167042" y="99.077"/>
- <use xlink:href="#glyph0-17" x="82.148342" y="99.077"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-7" x="90.613563" y="99.077"/>
- <use xlink:href="#glyph0-17" x="95.401589" y="99.077"/>
- <use xlink:href="#glyph0-25" x="100.549264" y="99.077"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-27" x="45.604" y="111.032"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-6" x="50.472723" y="111.032"/>
- <use xlink:href="#glyph0-16" x="53.876943" y="111.032"/>
- <use xlink:href="#glyph0-7" x="58.858243" y="111.032"/>
- <use xlink:href="#glyph0-25" x="63.646269" y="111.032"/>
- <use xlink:href="#glyph0-4" x="68.793944" y="111.032"/>
- <use xlink:href="#glyph0-7" x="73.22232" y="111.032"/>
- <use xlink:href="#glyph0-9" x="78.010345" y="111.032"/>
- <use xlink:href="#glyph0-8" x="81.82901" y="111.032"/>
- <use xlink:href="#glyph0-9" x="85.426505" y="111.032"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-3" x="92.562715" y="111.032"/>
- <use xlink:href="#glyph0-8" x="94.94278" y="111.032"/>
- <use xlink:href="#glyph0-26" x="98.540275" y="111.032"/>
-</g>
-<path style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -63.098187 -24.906875 L 63.097125 -24.906875 L 63.097125 24.905625 L -63.098187 24.905625 Z M -63.098187 -24.906875 " transform="matrix(1,0,0,-1,213.731,89.64)"/>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-1" x="157.539" y="80.176"/>
- <use xlink:href="#glyph0-2" x="164.181065" y="80.176"/>
- <use xlink:href="#glyph0-3" x="166.561131" y="80.176"/>
- <use xlink:href="#glyph0-4" x="168.941196" y="80.176"/>
- <use xlink:href="#glyph0-5" x="173.369571" y="80.176"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-9" x="181.115493" y="80.176"/>
- <use xlink:href="#glyph0-3" x="184.934157" y="80.176"/>
- <use xlink:href="#glyph0-30" x="187.314223" y="80.176"/>
- <use xlink:href="#glyph0-17" x="192.295523" y="80.176"/>
- <use xlink:href="#glyph0-9" x="197.443198" y="80.176"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-8" x="204.589371" y="80.176"/>
- <use xlink:href="#glyph0-15" x="208.186866" y="80.176"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-5" x="213.324579" y="80.176"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-8" x="221.080463" y="80.176"/>
- <use xlink:href="#glyph0-6" x="224.677958" y="80.176"/>
- <use xlink:href="#glyph0-7" x="228.082178" y="80.176"/>
- <use xlink:href="#glyph0-17" x="232.870204" y="80.176"/>
- <use xlink:href="#glyph0-9" x="238.017879" y="80.176"/>
- <use xlink:href="#glyph0-7" x="241.836544" y="80.176"/>
- <use xlink:href="#glyph0-4" x="246.624569" y="80.176"/>
- <use xlink:href="#glyph0-8" x="251.052945" y="80.176"/>
- <use xlink:href="#glyph0-3" x="254.65044" y="80.176"/>
- <use xlink:href="#glyph0-16" x="257.030505" y="80.176"/>
- <use xlink:href="#glyph0-17" x="262.011805" y="80.176"/>
- <use xlink:href="#glyph0-29" x="267.15948" y="80.176"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-7" x="172.331" y="92.131"/>
- <use xlink:href="#glyph0-25" x="177.119026" y="92.131"/>
- <use xlink:href="#glyph0-25" x="182.266701" y="92.131"/>
- <use xlink:href="#glyph0-9" x="187.414376" y="92.131"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-15" x="194.550587" y="92.131"/>
- <use xlink:href="#glyph0-5" x="199.698262" y="92.131"/>
- <use xlink:href="#glyph0-6" x="204.126638" y="92.131"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-9" x="210.848404" y="92.131"/>
- <use xlink:href="#glyph0-3" x="214.667069" y="92.131"/>
- <use xlink:href="#glyph0-30" x="217.047134" y="92.131"/>
- <use xlink:href="#glyph0-17" x="222.028434" y="92.131"/>
- <use xlink:href="#glyph0-7" x="227.176109" y="92.131"/>
- <use xlink:href="#glyph0-8" x="231.964135" y="92.131"/>
- <use xlink:href="#glyph0-20" x="235.56163" y="92.131"/>
- <use xlink:href="#glyph0-6" x="240.709305" y="92.131"/>
- <use xlink:href="#glyph0-5" x="244.113526" y="92.131"/>
- <use xlink:href="#glyph0-9" x="248.541901" y="92.131"/>
- <use xlink:href="#glyph0-29" x="252.360566" y="92.131"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-7" x="164.409" y="104.086"/>
- <use xlink:href="#glyph0-17" x="169.197026" y="104.086"/>
- <use xlink:href="#glyph0-25" x="174.344701" y="104.086"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-24" x="182.809922" y="104.086"/>
- <use xlink:href="#glyph0-17" x="188.150872" y="104.086"/>
- <use xlink:href="#glyph0-7" x="193.298547" y="104.086"/>
- <use xlink:href="#glyph0-2" x="198.086573" y="104.086"/>
- <use xlink:href="#glyph0-3" x="200.466638" y="104.086"/>
- <use xlink:href="#glyph0-31" x="202.846703" y="104.086"/>
- <use xlink:href="#glyph0-5" x="207.177446" y="104.086"/>
- <use xlink:href="#glyph0-9" x="211.605821" y="104.086"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-15" x="218.742032" y="104.086"/>
- <use xlink:href="#glyph0-5" x="223.889707" y="104.086"/>
- <use xlink:href="#glyph0-6" x="228.318083" y="104.086"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-3" x="235.049812" y="104.086"/>
- <use xlink:href="#glyph0-17" x="237.429877" y="104.086"/>
- <use xlink:href="#glyph0-19" x="242.577552" y="104.086"/>
- <use xlink:href="#glyph0-20" x="247.725228" y="104.086"/>
- <use xlink:href="#glyph0-8" x="252.872903" y="104.086"/>
- <use xlink:href="#glyph0-9" x="256.470398" y="104.086"/>
- <use xlink:href="#glyph0-26" x="260.289062" y="104.086"/>
-</g>
-<path style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -63.09775 -24.906875 L 63.097563 -24.906875 L 63.097563 24.905625 L -63.09775 24.905625 Z M -63.09775 -24.906875 " transform="matrix(1,0,0,-1,354.004,89.64)"/>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-12" x="299.556" y="80.176"/>
- <use xlink:href="#glyph0-16" x="306.198065" y="80.176"/>
- <use xlink:href="#glyph0-27" x="311.179365" y="80.176"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-9" x="319.644587" y="80.176"/>
- <use xlink:href="#glyph0-3" x="323.463251" y="80.176"/>
- <use xlink:href="#glyph0-30" x="325.843316" y="80.176"/>
- <use xlink:href="#glyph0-17" x="330.824616" y="80.176"/>
- <use xlink:href="#glyph0-9" x="335.972292" y="80.176"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-8" x="343.118465" y="80.176"/>
- <use xlink:href="#glyph0-15" x="346.71596" y="80.176"/>
- <use xlink:href="#glyph0-5" x="351.863635" y="80.176"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-8" x="359.609557" y="80.176"/>
- <use xlink:href="#glyph0-6" x="363.207051" y="80.176"/>
- <use xlink:href="#glyph0-7" x="366.611272" y="80.176"/>
- <use xlink:href="#glyph0-17" x="371.399297" y="80.176"/>
- <use xlink:href="#glyph0-9" x="376.546973" y="80.176"/>
- <use xlink:href="#glyph0-7" x="380.365637" y="80.176"/>
- <use xlink:href="#glyph0-4" x="385.153663" y="80.176"/>
- <use xlink:href="#glyph0-8" x="389.582039" y="80.176"/>
- <use xlink:href="#glyph0-3" x="393.179533" y="80.176"/>
- <use xlink:href="#glyph0-16" x="395.559599" y="80.176"/>
- <use xlink:href="#glyph0-17" x="400.540899" y="80.176"/>
- <use xlink:href="#glyph0-29" x="405.688574" y="80.176"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-7" x="313.42" y="92.131"/>
- <use xlink:href="#glyph0-25" x="318.208026" y="92.131"/>
- <use xlink:href="#glyph0-25" x="323.355701" y="92.131"/>
- <use xlink:href="#glyph0-9" x="328.503376" y="92.131"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-15" x="335.639587" y="92.131"/>
- <use xlink:href="#glyph0-3" x="340.787262" y="92.131"/>
- <use xlink:href="#glyph0-9" x="343.167327" y="92.131"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-9" x="350.3135" y="92.131"/>
- <use xlink:href="#glyph0-3" x="354.132165" y="92.131"/>
- <use xlink:href="#glyph0-30" x="356.51223" y="92.131"/>
- <use xlink:href="#glyph0-17" x="361.49353" y="92.131"/>
- <use xlink:href="#glyph0-7" x="366.641205" y="92.131"/>
- <use xlink:href="#glyph0-8" x="371.429231" y="92.131"/>
- <use xlink:href="#glyph0-20" x="375.026726" y="92.131"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-6" x="380.164439" y="92.131"/>
- <use xlink:href="#glyph0-5" x="383.568659" y="92.131"/>
- <use xlink:href="#glyph0-9" x="387.997035" y="92.131"/>
- <use xlink:href="#glyph0-29" x="391.815699" y="92.131"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-7" x="305.499" y="104.086"/>
- <use xlink:href="#glyph0-17" x="310.287026" y="104.086"/>
- <use xlink:href="#glyph0-25" x="315.434701" y="104.086"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-24" x="323.899922" y="104.086"/>
- <use xlink:href="#glyph0-17" x="329.240872" y="104.086"/>
- <use xlink:href="#glyph0-7" x="334.388547" y="104.086"/>
- <use xlink:href="#glyph0-2" x="339.176573" y="104.086"/>
- <use xlink:href="#glyph0-3" x="341.556638" y="104.086"/>
- <use xlink:href="#glyph0-31" x="343.936703" y="104.086"/>
- <use xlink:href="#glyph0-5" x="348.267446" y="104.086"/>
- <use xlink:href="#glyph0-9" x="352.695821" y="104.086"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-15" x="359.832032" y="104.086"/>
- <use xlink:href="#glyph0-3" x="364.979707" y="104.086"/>
- <use xlink:href="#glyph0-9" x="367.359772" y="104.086"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-3" x="374.505945" y="104.086"/>
- <use xlink:href="#glyph0-17" x="376.88601" y="104.086"/>
- <use xlink:href="#glyph0-19" x="382.033686" y="104.086"/>
- <use xlink:href="#glyph0-20" x="387.181361" y="104.086"/>
- <use xlink:href="#glyph0-8" x="392.329037" y="104.086"/>
- <use xlink:href="#glyph0-9" x="395.926531" y="104.086"/>
- <use xlink:href="#glyph0-26" x="399.745196" y="104.086"/>
-</g>
-<path style="fill:none;stroke-width:0.99628;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -76.777875 29.734563 L -68.695844 29.734563 " transform="matrix(1,0,0,-1,213.731,59.133)"/>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 150.234375 29.398438 C 148.695312 29.109375 146.191406 28.242188 144.457031 27.234375 L 144.457031 31.566406 C 146.191406 30.554688 148.695312 29.6875 150.234375 29.398438 "/>
-<path style="fill:none;stroke-width:0.99628;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 63.495563 29.734563 L 71.577594 29.734563 " transform="matrix(1,0,0,-1,213.731,59.133)"/>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 290.511719 29.398438 C 288.96875 29.109375 286.464844 28.242188 284.730469 27.234375 L 284.730469 31.566406 C 286.464844 30.554688 288.96875 29.6875 290.511719 29.398438 "/>
-<path style="fill:none;stroke-width:0.99628;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 140.276813 3.652531 L 140.276813 -0.00371875 " transform="matrix(1,0,0,-1,213.731,59.133)"/>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 354.007812 64.335938 C 354.296875 62.792969 355.160156 60.289062 356.171875 58.558594 L 351.839844 58.558594 C 352.851562 60.289062 353.71875 62.792969 354.007812 64.335938 "/>
-<path style="fill:none;stroke-width:0.99628;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 76.780719 -30.507625 L 68.694781 -30.507625 " transform="matrix(1,0,0,-1,213.731,59.133)"/>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 277.226562 89.640625 C 278.769531 89.929688 281.273438 90.796875 283.003906 91.808594 L 283.003906 87.472656 C 281.273438 88.484375 278.769531 89.351562 277.226562 89.640625 "/>
-<path style="fill:none;stroke-width:0.99628;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -63.496625 -30.507625 L -91.504437 -30.507625 " transform="matrix(1,0,0,-1,213.731,59.133)"/>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 117.027344 89.640625 C 118.566406 89.929688 121.070312 90.796875 122.804688 91.808594 L 122.804688 87.472656 C 121.070312 88.484375 118.566406 89.351562 117.027344 89.640625 "/>
+<path style="fill:none;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 39.187531 24.907844 L -39.187469 24.907844 C -41.386687 24.907844 -43.171844 23.122688 -43.171844 20.923469 L -43.171844 -20.920281 C -43.171844 -23.123406 -41.386687 -24.908562 -39.187469 -24.908562 L 39.187531 -24.908562 C 41.38675 -24.908562 43.171906 -23.123406 43.171906 -20.920281 L 43.171906 20.923469 C 43.171906 23.122688 41.38675 24.907844 39.187531 24.907844 Z M 39.187531 24.907844 " transform="matrix(1,0,0,-1,73.457,94.068)"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="37.094" y="79.595"/>
+ <use xlink:href="#glyph0-2" x="43.736065" y="79.595"/>
+ <use xlink:href="#glyph0-3" x="46.116131" y="79.595"/>
+ <use xlink:href="#glyph0-4" x="48.496196" y="79.595"/>
+ <use xlink:href="#glyph0-5" x="52.924571" y="79.595"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph0-5" x="60.670493" y="79.595"/>
+ <use xlink:href="#glyph0-32" x="65.098869" y="79.595"/>
+ <use xlink:href="#glyph0-8" x="69.692623" y="79.595"/>
+ <use xlink:href="#glyph0-6" x="73.290118" y="79.595"/>
+ <use xlink:href="#glyph0-7" x="76.694339" y="79.595"/>
+ <use xlink:href="#glyph0-4" x="81.482364" y="79.595"/>
+ <use xlink:href="#glyph0-8" x="85.91074" y="79.595"/>
+ <use xlink:href="#glyph0-9" x="89.508235" y="79.595"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use
+ xlink:href="#glyph0-8"
+ x="96.644445"
+ y="79.595"
+ id="use583" />
+ <use
+ xlink:href="#glyph0-15"
+ x="100.24194"
+ y="79.595"
+ id="use585" />
+ <use
+ xlink:href="#glyph0-5"
+ x="105.389616"
+ y="79.595"
+ id="use587" />
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use
+ xlink:href="#glyph0-17"
+ x="36.852"
+ y="91.55"
+ id="use591" />
+ <use
+ xlink:href="#glyph0-5"
+ x="41.999675"
+ y="91.55"
+ id="use593" />
+ <use
+ xlink:href="#glyph0-8"
+ x="46.428051"
+ y="91.55"
+ id="use595" />
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use
+ xlink:href="#glyph0-14"
+ x="49.746593"
+ y="91.55"
+ id="use599" />
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use
+ xlink:href="#glyph0-16"
+ x="56.275085"
+ y="91.55"
+ id="use603" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g611">
+ <use
+ xlink:href="#glyph0-6"
+ x="60.987395"
+ y="91.55"
+ id="use607" />
+ <use
+ xlink:href="#glyph0-33"
+ x="64.391615"
+ y="91.55"
+ id="use609" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g633">
+ <use
+ xlink:href="#glyph0-9"
+ x="72.579876"
+ y="91.55"
+ id="use613" />
+ <use
+ xlink:href="#glyph0-5"
+ x="76.398541"
+ y="91.55"
+ id="use615" />
+ <use
+ xlink:href="#glyph0-6"
+ x="80.826916"
+ y="91.55"
+ id="use617" />
+ <use
+ xlink:href="#glyph0-3"
+ x="84.231137"
+ y="91.55"
+ id="use619" />
+ <use
+ xlink:href="#glyph0-7"
+ x="86.611202"
+ y="91.55"
+ id="use621" />
+ <use
+ xlink:href="#glyph0-2"
+ x="91.399228"
+ y="91.55"
+ id="use623" />
+ <use
+ xlink:href="#glyph0-3"
+ x="93.779293"
+ y="91.55"
+ id="use625" />
+ <use
+ xlink:href="#glyph0-31"
+ x="96.159358"
+ y="91.55"
+ id="use627" />
+ <use
+ xlink:href="#glyph0-5"
+ x="100.4901"
+ y="91.55"
+ id="use629" />
+ <use
+ xlink:href="#glyph0-25"
+ x="104.918476"
+ y="91.55"
+ id="use631" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g657">
+ <use
+ xlink:href="#glyph0-8"
+ x="41.217"
+ y="103.505"
+ id="use635" />
+ <use
+ xlink:href="#glyph0-6"
+ x="44.814495"
+ y="103.505"
+ id="use637" />
+ <use
+ xlink:href="#glyph0-7"
+ x="48.218715"
+ y="103.505"
+ id="use639" />
+ <use
+ xlink:href="#glyph0-17"
+ x="53.006741"
+ y="103.505"
+ id="use641" />
+ <use
+ xlink:href="#glyph0-9"
+ x="58.154416"
+ y="103.505"
+ id="use643" />
+ <use
+ xlink:href="#glyph0-7"
+ x="61.973081"
+ y="103.505"
+ id="use645" />
+ <use
+ xlink:href="#glyph0-4"
+ x="66.761106"
+ y="103.505"
+ id="use647" />
+ <use
+ xlink:href="#glyph0-8"
+ x="71.189482"
+ y="103.505"
+ id="use649" />
+ <use
+ xlink:href="#glyph0-3"
+ x="74.786977"
+ y="103.505"
+ id="use651" />
+ <use
+ xlink:href="#glyph0-16"
+ x="77.167042"
+ y="103.505"
+ id="use653" />
+ <use
+ xlink:href="#glyph0-17"
+ x="82.148342"
+ y="103.505"
+ id="use655" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g665">
+ <use
+ xlink:href="#glyph0-7"
+ x="90.613563"
+ y="103.505"
+ id="use659" />
+ <use
+ xlink:href="#glyph0-17"
+ x="95.401589"
+ y="103.505"
+ id="use661" />
+ <use
+ xlink:href="#glyph0-25"
+ x="100.549264"
+ y="103.505"
+ id="use663" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g669">
+ <use
+ xlink:href="#glyph0-27"
+ x="45.604"
+ y="115.46"
+ id="use667" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g689">
+ <use
+ xlink:href="#glyph0-6"
+ x="50.472723"
+ y="115.46"
+ id="use671" />
+ <use
+ xlink:href="#glyph0-16"
+ x="53.876943"
+ y="115.46"
+ id="use673" />
+ <use
+ xlink:href="#glyph0-7"
+ x="58.858243"
+ y="115.46"
+ id="use675" />
+ <use
+ xlink:href="#glyph0-25"
+ x="63.646269"
+ y="115.46"
+ id="use677" />
+ <use
+ xlink:href="#glyph0-4"
+ x="68.793944"
+ y="115.46"
+ id="use679" />
+ <use
+ xlink:href="#glyph0-7"
+ x="73.22232"
+ y="115.46"
+ id="use681" />
+ <use
+ xlink:href="#glyph0-9"
+ x="78.010345"
+ y="115.46"
+ id="use683" />
+ <use
+ xlink:href="#glyph0-8"
+ x="81.82901"
+ y="115.46"
+ id="use685" />
+ <use
+ xlink:href="#glyph0-9"
+ x="85.426505"
+ y="115.46"
+ id="use687" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g697">
+ <use
+ xlink:href="#glyph0-3"
+ x="92.562715"
+ y="115.46"
+ id="use691" />
+ <use
+ xlink:href="#glyph0-8"
+ x="94.94278"
+ y="115.46"
+ id="use693" />
+ <use
+ xlink:href="#glyph0-26"
+ x="98.540275"
+ y="115.46"
+ id="use695" />
+</g>
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M -63.098187 -24.908562 L 63.097125 -24.908562 L 63.097125 24.907844 L -63.098187 24.907844 Z M -63.098187 -24.908562 "
+ transform="matrix(1,0,0,-1,213.731,94.068)"
+ id="path699" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g711">
+ <use
+ xlink:href="#glyph0-1"
+ x="157.539"
+ y="84.604"
+ id="use701" />
+ <use
+ xlink:href="#glyph0-2"
+ x="164.181065"
+ y="84.604"
+ id="use703" />
+ <use
+ xlink:href="#glyph0-3"
+ x="166.561131"
+ y="84.604"
+ id="use705" />
+ <use
+ xlink:href="#glyph0-4"
+ x="168.941196"
+ y="84.604"
+ id="use707" />
+ <use
+ xlink:href="#glyph0-5"
+ x="173.369571"
+ y="84.604"
+ id="use709" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g723">
+ <use
+ xlink:href="#glyph0-9"
+ x="181.115493"
+ y="84.604"
+ id="use713" />
+ <use
+ xlink:href="#glyph0-3"
+ x="184.934157"
+ y="84.604"
+ id="use715" />
+ <use
+ xlink:href="#glyph0-30"
+ x="187.314223"
+ y="84.604"
+ id="use717" />
+ <use
+ xlink:href="#glyph0-17"
+ x="192.295523"
+ y="84.604"
+ id="use719" />
+ <use
+ xlink:href="#glyph0-9"
+ x="197.443198"
+ y="84.604"
+ id="use721" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g729">
+ <use
+ xlink:href="#glyph0-8"
+ x="204.589371"
+ y="84.604"
+ id="use725" />
+ <use
+ xlink:href="#glyph0-15"
+ x="208.186866"
+ y="84.604"
+ id="use727" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g733">
+ <use
+ xlink:href="#glyph0-5"
+ x="213.324579"
+ y="84.604"
+ id="use731" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g759">
+ <use
+ xlink:href="#glyph0-8"
+ x="221.080463"
+ y="84.604"
+ id="use735" />
+ <use
+ xlink:href="#glyph0-6"
+ x="224.677958"
+ y="84.604"
+ id="use737" />
+ <use
+ xlink:href="#glyph0-7"
+ x="228.082178"
+ y="84.604"
+ id="use739" />
+ <use
+ xlink:href="#glyph0-17"
+ x="232.870204"
+ y="84.604"
+ id="use741" />
+ <use
+ xlink:href="#glyph0-9"
+ x="238.017879"
+ y="84.604"
+ id="use743" />
+ <use
+ xlink:href="#glyph0-7"
+ x="241.836544"
+ y="84.604"
+ id="use745" />
+ <use
+ xlink:href="#glyph0-4"
+ x="246.624569"
+ y="84.604"
+ id="use747" />
+ <use
+ xlink:href="#glyph0-8"
+ x="251.052945"
+ y="84.604"
+ id="use749" />
+ <use
+ xlink:href="#glyph0-3"
+ x="254.65044"
+ y="84.604"
+ id="use751" />
+ <use
+ xlink:href="#glyph0-16"
+ x="257.030505"
+ y="84.604"
+ id="use753" />
+ <use
+ xlink:href="#glyph0-17"
+ x="262.011805"
+ y="84.604"
+ id="use755" />
+ <use
+ xlink:href="#glyph0-29"
+ x="267.15948"
+ y="84.604"
+ id="use757" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g769">
+ <use
+ xlink:href="#glyph0-7"
+ x="172.331"
+ y="96.559"
+ id="use761" />
+ <use
+ xlink:href="#glyph0-25"
+ x="177.119026"
+ y="96.559"
+ id="use763" />
+ <use
+ xlink:href="#glyph0-25"
+ x="182.266701"
+ y="96.559"
+ id="use765" />
+ <use
+ xlink:href="#glyph0-9"
+ x="187.414376"
+ y="96.559"
+ id="use767" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g777">
+ <use
+ xlink:href="#glyph0-15"
+ x="194.550587"
+ y="96.559"
+ id="use771" />
+ <use
+ xlink:href="#glyph0-5"
+ x="199.698262"
+ y="96.559"
+ id="use773" />
+ <use
+ xlink:href="#glyph0-6"
+ x="204.126638"
+ y="96.559"
+ id="use775" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g801">
+ <use
+ xlink:href="#glyph0-9"
+ x="210.848404"
+ y="96.559"
+ id="use779" />
+ <use
+ xlink:href="#glyph0-3"
+ x="214.667069"
+ y="96.559"
+ id="use781" />
+ <use
+ xlink:href="#glyph0-30"
+ x="217.047134"
+ y="96.559"
+ id="use783" />
+ <use
+ xlink:href="#glyph0-17"
+ x="222.028434"
+ y="96.559"
+ id="use785" />
+ <use
+ xlink:href="#glyph0-7"
+ x="227.176109"
+ y="96.559"
+ id="use787" />
+ <use
+ xlink:href="#glyph0-8"
+ x="231.964135"
+ y="96.559"
+ id="use789" />
+ <use
+ xlink:href="#glyph0-20"
+ x="235.56163"
+ y="96.559"
+ id="use791" />
+ <use
+ xlink:href="#glyph0-6"
+ x="240.709305"
+ y="96.559"
+ id="use793" />
+ <use
+ xlink:href="#glyph0-5"
+ x="244.113526"
+ y="96.559"
+ id="use795" />
+ <use
+ xlink:href="#glyph0-9"
+ x="248.541901"
+ y="96.559"
+ id="use797" />
+ <use
+ xlink:href="#glyph0-29"
+ x="252.360566"
+ y="96.559"
+ id="use799" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g809">
+ <use
+ xlink:href="#glyph0-7"
+ x="164.409"
+ y="108.514"
+ id="use803" />
+ <use
+ xlink:href="#glyph0-17"
+ x="169.197026"
+ y="108.514"
+ id="use805" />
+ <use
+ xlink:href="#glyph0-25"
+ x="174.344701"
+ y="108.514"
+ id="use807" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g827">
+ <use
+ xlink:href="#glyph0-24"
+ x="182.809922"
+ y="108.514"
+ id="use811" />
+ <use
+ xlink:href="#glyph0-17"
+ x="188.150872"
+ y="108.514"
+ id="use813" />
+ <use
+ xlink:href="#glyph0-7"
+ x="193.298547"
+ y="108.514"
+ id="use815" />
+ <use
+ xlink:href="#glyph0-2"
+ x="198.086573"
+ y="108.514"
+ id="use817" />
+ <use
+ xlink:href="#glyph0-3"
+ x="200.466638"
+ y="108.514"
+ id="use819" />
+ <use
+ xlink:href="#glyph0-31"
+ x="202.846703"
+ y="108.514"
+ id="use821" />
+ <use
+ xlink:href="#glyph0-5"
+ x="207.177446"
+ y="108.514"
+ id="use823" />
+ <use
+ xlink:href="#glyph0-9"
+ x="211.605821"
+ y="108.514"
+ id="use825" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g835">
+ <use
+ xlink:href="#glyph0-15"
+ x="218.742032"
+ y="108.514"
+ id="use829" />
+ <use
+ xlink:href="#glyph0-5"
+ x="223.889707"
+ y="108.514"
+ id="use831" />
+ <use
+ xlink:href="#glyph0-6"
+ x="228.318083"
+ y="108.514"
+ id="use833" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g851">
+ <use
+ xlink:href="#glyph0-3"
+ x="235.049812"
+ y="108.514"
+ id="use837" />
+ <use
+ xlink:href="#glyph0-17"
+ x="237.429877"
+ y="108.514"
+ id="use839" />
+ <use
+ xlink:href="#glyph0-19"
+ x="242.577552"
+ y="108.514"
+ id="use841" />
+ <use
+ xlink:href="#glyph0-20"
+ x="247.725228"
+ y="108.514"
+ id="use843" />
+ <use
+ xlink:href="#glyph0-8"
+ x="252.872903"
+ y="108.514"
+ id="use845" />
+ <use
+ xlink:href="#glyph0-9"
+ x="256.470398"
+ y="108.514"
+ id="use847" />
+ <use
+ xlink:href="#glyph0-26"
+ x="260.289062"
+ y="108.514"
+ id="use849" />
+</g>
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M -63.09775 -24.908562 L 63.097563 -24.908562 L 63.097563 24.907844 L -63.09775 24.907844 Z M -63.09775 -24.908562 "
+ transform="matrix(1,0,0,-1,354.004,94.068)"
+ id="path853" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g861">
+ <use
+ xlink:href="#glyph0-12"
+ x="299.556"
+ y="84.604"
+ id="use855" />
+ <use
+ xlink:href="#glyph0-16"
+ x="306.198065"
+ y="84.604"
+ id="use857" />
+ <use
+ xlink:href="#glyph0-27"
+ x="311.179365"
+ y="84.604"
+ id="use859" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g873">
+ <use
+ xlink:href="#glyph0-9"
+ x="319.644587"
+ y="84.604"
+ id="use863" />
+ <use
+ xlink:href="#glyph0-3"
+ x="323.463251"
+ y="84.604"
+ id="use865" />
+ <use
+ xlink:href="#glyph0-30"
+ x="325.843316"
+ y="84.604"
+ id="use867" />
+ <use
+ xlink:href="#glyph0-17"
+ x="330.824616"
+ y="84.604"
+ id="use869" />
+ <use
+ xlink:href="#glyph0-9"
+ x="335.972292"
+ y="84.604"
+ id="use871" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g881">
+ <use
+ xlink:href="#glyph0-8"
+ x="343.118465"
+ y="84.604"
+ id="use875" />
+ <use
+ xlink:href="#glyph0-15"
+ x="346.71596"
+ y="84.604"
+ id="use877" />
+ <use
+ xlink:href="#glyph0-5"
+ x="351.863635"
+ y="84.604"
+ id="use879" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g907">
+ <use
+ xlink:href="#glyph0-8"
+ x="359.609557"
+ y="84.604"
+ id="use883" />
+ <use
+ xlink:href="#glyph0-6"
+ x="363.207051"
+ y="84.604"
+ id="use885" />
+ <use
+ xlink:href="#glyph0-7"
+ x="366.611272"
+ y="84.604"
+ id="use887" />
+ <use
+ xlink:href="#glyph0-17"
+ x="371.399297"
+ y="84.604"
+ id="use889" />
+ <use
+ xlink:href="#glyph0-9"
+ x="376.546973"
+ y="84.604"
+ id="use891" />
+ <use
+ xlink:href="#glyph0-7"
+ x="380.365637"
+ y="84.604"
+ id="use893" />
+ <use
+ xlink:href="#glyph0-4"
+ x="385.153663"
+ y="84.604"
+ id="use895" />
+ <use
+ xlink:href="#glyph0-8"
+ x="389.582039"
+ y="84.604"
+ id="use897" />
+ <use
+ xlink:href="#glyph0-3"
+ x="393.179533"
+ y="84.604"
+ id="use899" />
+ <use
+ xlink:href="#glyph0-16"
+ x="395.559599"
+ y="84.604"
+ id="use901" />
+ <use
+ xlink:href="#glyph0-17"
+ x="400.540899"
+ y="84.604"
+ id="use903" />
+ <use
+ xlink:href="#glyph0-29"
+ x="405.688574"
+ y="84.604"
+ id="use905" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g917">
+ <use
+ xlink:href="#glyph0-7"
+ x="313.42"
+ y="96.559"
+ id="use909" />
+ <use
+ xlink:href="#glyph0-25"
+ x="318.208026"
+ y="96.559"
+ id="use911" />
+ <use
+ xlink:href="#glyph0-25"
+ x="323.355701"
+ y="96.559"
+ id="use913" />
+ <use
+ xlink:href="#glyph0-9"
+ x="328.503376"
+ y="96.559"
+ id="use915" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g925">
+ <use
+ xlink:href="#glyph0-15"
+ x="335.639587"
+ y="96.559"
+ id="use919" />
+ <use
+ xlink:href="#glyph0-3"
+ x="340.787262"
+ y="96.559"
+ id="use921" />
+ <use
+ xlink:href="#glyph0-9"
+ x="343.167327"
+ y="96.559"
+ id="use923" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g941">
+ <use
+ xlink:href="#glyph0-9"
+ x="350.3135"
+ y="96.559"
+ id="use927" />
+ <use
+ xlink:href="#glyph0-3"
+ x="354.132165"
+ y="96.559"
+ id="use929" />
+ <use
+ xlink:href="#glyph0-30"
+ x="356.51223"
+ y="96.559"
+ id="use931" />
+ <use
+ xlink:href="#glyph0-17"
+ x="361.49353"
+ y="96.559"
+ id="use933" />
+ <use
+ xlink:href="#glyph0-7"
+ x="366.641205"
+ y="96.559"
+ id="use935" />
+ <use
+ xlink:href="#glyph0-8"
+ x="371.429231"
+ y="96.559"
+ id="use937" />
+ <use
+ xlink:href="#glyph0-20"
+ x="375.026726"
+ y="96.559"
+ id="use939" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g951">
+ <use
+ xlink:href="#glyph0-6"
+ x="380.164439"
+ y="96.559"
+ id="use943" />
+ <use
+ xlink:href="#glyph0-5"
+ x="383.568659"
+ y="96.559"
+ id="use945" />
+ <use
+ xlink:href="#glyph0-9"
+ x="387.997035"
+ y="96.559"
+ id="use947" />
+ <use
+ xlink:href="#glyph0-29"
+ x="391.815699"
+ y="96.559"
+ id="use949" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g959">
+ <use
+ xlink:href="#glyph0-7"
+ x="305.499"
+ y="108.514"
+ id="use953" />
+ <use
+ xlink:href="#glyph0-17"
+ x="310.287026"
+ y="108.514"
+ id="use955" />
+ <use
+ xlink:href="#glyph0-25"
+ x="315.434701"
+ y="108.514"
+ id="use957" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g977">
+ <use
+ xlink:href="#glyph0-24"
+ x="323.899922"
+ y="108.514"
+ id="use961" />
+ <use
+ xlink:href="#glyph0-17"
+ x="329.240872"
+ y="108.514"
+ id="use963" />
+ <use
+ xlink:href="#glyph0-7"
+ x="334.388547"
+ y="108.514"
+ id="use965" />
+ <use
+ xlink:href="#glyph0-2"
+ x="339.176573"
+ y="108.514"
+ id="use967" />
+ <use
+ xlink:href="#glyph0-3"
+ x="341.556638"
+ y="108.514"
+ id="use969" />
+ <use
+ xlink:href="#glyph0-31"
+ x="343.936703"
+ y="108.514"
+ id="use971" />
+ <use
+ xlink:href="#glyph0-5"
+ x="348.267446"
+ y="108.514"
+ id="use973" />
+ <use
+ xlink:href="#glyph0-9"
+ x="352.695821"
+ y="108.514"
+ id="use975" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g985">
+ <use
+ xlink:href="#glyph0-15"
+ x="359.832032"
+ y="108.514"
+ id="use979" />
+ <use
+ xlink:href="#glyph0-3"
+ x="364.979707"
+ y="108.514"
+ id="use981" />
+ <use
+ xlink:href="#glyph0-9"
+ x="367.359772"
+ y="108.514"
+ id="use983" />
+</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1001">
+ <use
+ xlink:href="#glyph0-3"
+ x="374.505945"
+ y="108.514"
+ id="use987" />
+ <use
+ xlink:href="#glyph0-17"
+ x="376.88601"
+ y="108.514"
+ id="use989" />
+ <use
+ xlink:href="#glyph0-19"
+ x="382.033686"
+ y="108.514"
+ id="use991" />
+ <use
+ xlink:href="#glyph0-20"
+ x="387.181361"
+ y="108.514"
+ id="use993" />
+ <use
+ xlink:href="#glyph0-8"
+ x="392.329037"
+ y="108.514"
+ id="use995" />
+ <use
+ xlink:href="#glyph0-9"
+ x="395.926531"
+ y="108.514"
+ id="use997" />
+ <use
+ xlink:href="#glyph0-26"
+ x="399.745196"
+ y="108.514"
+ id="use999" />
+</g>
+ <path
+ style="fill:none;stroke-width:1.59404;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M -76.777875 31.948563 L -68.320844 31.948563 "
+ transform="matrix(1,0,0,-1,213.731,61.347)"
+ id="path1003" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.34497;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 6.055213 0.0012025 L 2.1724 1.477765 L 3.480994 0.0012025 L 2.1724 -1.479266 Z M 6.055213 0.0012025 "
+ transform="matrix(1,0,0,-1,142.2651,29.39964)"
+ id="path1005" />
+ <path
+ style="fill:none;stroke-width:1.59404;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 63.495563 31.948563 L 71.952594 31.948563 "
+ transform="matrix(1,0,0,-1,213.731,61.347)"
+ id="path1007" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.34497;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 6.05342 0.0012025 L 2.170608 1.477765 L 3.479201 0.0012025 L 2.170608 -1.479266 Z M 6.05342 0.0012025 "
+ transform="matrix(1,0,0,-1,282.54033,29.39964)"
+ id="path1009" />
+ <path
+ style="fill:none;stroke-width:1.59404;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 140.276813 5.866531 L 140.276813 -2.5905 "
+ transform="matrix(1,0,0,-1,213.731,61.347)"
+ id="path1011" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.34497;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 6.054396 0.0015925 L 2.171584 1.478155 L 3.480177 0.0015925 L 2.171584 -1.478876 Z M 6.054396 0.0015925 "
+ transform="matrix(0,1,1,0,354.00622,60.79326)"
+ id="path1013" />
+ <path
+ style="fill:none;stroke-width:1.59404;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 76.780719 -32.723312 L 68.323688 -32.723312 "
+ transform="matrix(1,0,0,-1,213.731,61.347)"
+ id="path1015" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.34497;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 6.056275 0.0014125 L 2.173463 1.477975 L 3.482056 0.0014125 L 2.173463 -1.479056 Z M 6.056275 0.0014125 "
+ transform="matrix(-1,0,0,1,285.1969,94.0689)"
+ id="path1017" />
+ <path
+ style="fill:none;stroke-width:1.59404;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M -63.496625 -32.723312 L -91.879437 -32.723312 "
+ transform="matrix(1,0,0,-1,213.731,61.347)"
+ id="path1019" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.34497;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 6.054734 0.0014125 L 2.171921 1.477975 L 3.480515 0.0014125 L 2.171921 -1.479056 Z M 6.054734 0.0014125 "
+ transform="matrix(-1,0,0,1,124.99614,94.0689)"
+ id="path1021" />
+ <path
+ style="fill:none;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M -76.777875 31.948563 L -68.711469 31.948563 "
+ transform="matrix(1,0,0,-1,213.731,61.347)"
+ id="path1023" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 7.402869 0.0012025 L 0.645056 2.540265 L 2.852088 0.0012025 L 0.645056 -2.541766 Z M 7.402869 0.0012025 "
+ transform="matrix(1,0,0,-1,142.2651,29.39964)"
+ id="path1025" />
+ <path
+ style="fill:none;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 63.495563 31.948563 L 71.561969 31.948563 "
+ transform="matrix(1,0,0,-1,213.731,61.347)"
+ id="path1027" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 7.401076 0.0012025 L 0.643264 2.540265 L 2.854201 0.0012025 L 0.643264 -2.541766 Z M 7.401076 0.0012025 "
+ transform="matrix(1,0,0,-1,282.54033,29.39964)"
+ id="path1029" />
+ <path
+ style="fill:none;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 140.276813 5.866531 L 140.276813 -2.199875 "
+ transform="matrix(1,0,0,-1,213.731,61.347)"
+ id="path1031" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 7.402052 0.0015925 L 0.64424 2.540655 L 2.855177 0.0015925 L 0.64424 -2.541376 Z M 7.402052 0.0015925 "
+ transform="matrix(0,1,1,0,354.00622,60.79326)"
+ id="path1033" />
+ <path
+ style="fill:none;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 76.780719 -32.723312 L 68.710406 -32.723312 "
+ transform="matrix(1,0,0,-1,213.731,61.347)"
+ id="path1035" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 7.403931 0.0014125 L 0.642213 2.540475 L 2.85315 0.0014125 L 0.642213 -2.541556 Z M 7.403931 0.0014125 "
+ transform="matrix(-1,0,0,1,285.1969,94.0689)"
+ id="path1037" />
+ <path
+ style="fill:none;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M -63.496625 -32.723312 L -91.488812 -32.723312 "
+ transform="matrix(1,0,0,-1,213.731,61.347)"
+ id="path1039" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 7.40239 0.0014125 L 0.644577 2.540475 L 2.855515 0.0014125 L 0.644577 -2.541556 Z M 7.40239 0.0014125 "
+ transform="matrix(-1,0,0,1,124.99614,94.0689)"
+ id="path1041" />
</g>
</svg>
diff --git a/bip-0174/coinjoin-workflow.tex b/bip-0174/coinjoin-workflow.tex
index e0516ff..a325321 100644
--- a/bip-0174/coinjoin-workflow.tex
+++ b/bip-0174/coinjoin-workflow.tex
@@ -7,7 +7,7 @@
\usepackage{lmodern}
\renewcommand*\familydefault{\sfdefault}
\usepackage{tikz}
-\usetikzlibrary{shapes,arrows}
+\usetikzlibrary{shapes,arrows.meta}
\tikzset{>=latex}
\begin{document}
% \sffamily{}
@@ -22,7 +22,7 @@
rounded corners]
\begin{tikzpicture}[auto]
% outlining the flowchart on a grid
- \matrix[column sep=3ex,row sep=2ex]{
+ \matrix[column sep=3ex,row sep=3ex]{
\node [block_center] (0alice1)
{Alice creates a PSBT with only her inputs
with UTXOs filled in.\\Sends it to Bob.};
@@ -49,7 +49,13 @@
\\
};% end matrix
% connecting nodes with paths
- \draw[line width = 1pt, ->]
+ \draw [ultra thick, draw=black, -{Stealth[length=8pt]}]
+ (0alice1) edge (1bob1)
+ (1bob1) edge (2carol1)
+ (2carol1) edge (3bob2)
+ (3bob2) edge (4alice1)
+ (4alice1) edge (5alice2);
+ \draw [thin, white, -{Stealth[color=black, fill=white, length=8pt]}]
(0alice1) edge (1bob1)
(1bob1) edge (2carol1)
(2carol1) edge (3bob2)
diff --git a/bip-0174/multisig-workflow.svg b/bip-0174/multisig-workflow.svg
index 8abe4c5..2d873b0 100644
--- a/bip-0174/multisig-workflow.svg
+++ b/bip-0174/multisig-workflow.svg
@@ -1,6 +1,47 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="375.988pt" height="411.906pt"
- viewBox="0 0 375.988 411.906" style="background-color:white" version="1.1">
+ viewBox="0 0 375.988 411.906" version="1.2"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1424"
+ sodipodi:docname="multisig-workflow.svg"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
+ <metadata
+ id="metadata1428">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview1426"
+ showgrid="false"
+ inkscape:zoom="0.42970968"
+ inkscape:cx="250.65867"
+ inkscape:cy="274.604"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg1424" />
<defs>
<g>
<symbol overflow="visible" id="glyph0-0">
@@ -192,277 +233,931 @@
<use xlink:href="#glyph0-20" x="211.977264" y="25.914"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-14" x="215.011872" y="25.914"/>
- <use xlink:href="#glyph0-8" x="218.416092" y="25.914"/>
- <use xlink:href="#glyph0-21" x="223.397392" y="25.914"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-10" x="155.2" y="37.869"/>
-</g>
+ <use
+ xlink:href="#glyph0-14"
+ x="215.011872"
+ y="25.914"
+ id="use221" />
+ <use
+ xlink:href="#glyph0-8"
+ x="218.416092"
+ y="25.914"
+ id="use223" />
+ <use
+ xlink:href="#glyph0-21"
+ x="223.397392"
+ y="25.914"
+ id="use225" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g231">
+ <use
+ xlink:href="#glyph0-10"
+ x="155.2"
+ y="37.869"
+ id="use229" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-22" x="163.305571" y="37.869"/>
- <use xlink:href="#glyph0-23" x="168.286871" y="37.869"/>
- <use xlink:href="#glyph0-8" x="171.607406" y="37.869"/>
- <use xlink:href="#glyph0-20" x="176.588706" y="37.869"/>
- <use xlink:href="#glyph0-23" x="179.633277" y="37.869"/>
- <use xlink:href="#glyph0-24" x="182.953811" y="37.869"/>
-</g>
+ <use
+ xlink:href="#glyph0-23"
+ x="168.286871"
+ y="37.869"
+ id="use235" />
+ <use
+ xlink:href="#glyph0-8"
+ x="171.607406"
+ y="37.869"
+ id="use237" />
+ <use
+ xlink:href="#glyph0-20"
+ x="176.588706"
+ y="37.869"
+ id="use239" />
+ <use
+ xlink:href="#glyph0-23"
+ x="179.633277"
+ y="37.869"
+ id="use241" />
+ <use
+ xlink:href="#glyph0-24"
+ x="182.953811"
+ y="37.869"
+ id="use243" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-25" x="191.262619" y="37.869"/>
- <use xlink:href="#glyph0-26" x="199.979894" y="37.869"/>
- <use xlink:href="#glyph0-2" x="205.12757" y="37.869"/>
- <use xlink:href="#glyph0-18" x="207.507635" y="37.869"/>
- <use xlink:href="#glyph0-3" x="211.10513" y="37.869"/>
- <use xlink:href="#glyph0-16" x="213.485195" y="37.869"/>
- <use xlink:href="#glyph0-3" x="217.30386" y="37.869"/>
- <use xlink:href="#glyph0-27" x="219.683925" y="37.869"/>
- <use xlink:href="#glyph0-28" x="224.665225" y="37.869"/>
-</g>
-<path style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -55.623594 -19.705344 L 55.626406 -19.705344 L 55.626406 19.704812 L -55.623594 19.704812 Z M -55.623594 -19.705344 " transform="matrix(1,0,0,-1,191.315,74.697)"/>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-1" x="141.128" y="65.232"/>
- <use xlink:href="#glyph0-2" x="147.770065" y="65.232"/>
- <use xlink:href="#glyph0-3" x="150.150131" y="65.232"/>
- <use xlink:href="#glyph0-4" x="152.530196" y="65.232"/>
+ <use
+ xlink:href="#glyph0-26"
+ x="199.979894"
+ y="37.869"
+ id="use249" />
+ <use
+ xlink:href="#glyph0-2"
+ x="205.12757"
+ y="37.869"
+ id="use251" />
+ <use
+ xlink:href="#glyph0-18"
+ x="207.507635"
+ y="37.869"
+ id="use253" />
+ <use
+ xlink:href="#glyph0-3"
+ x="211.10513"
+ y="37.869"
+ id="use255" />
+ <use
+ xlink:href="#glyph0-16"
+ x="213.485195"
+ y="37.869"
+ id="use257" />
+ <use
+ xlink:href="#glyph0-3"
+ x="217.30386"
+ y="37.869"
+ id="use259" />
+ <use
+ xlink:href="#glyph0-27"
+ x="219.683925"
+ y="37.869"
+ id="use261" />
+ <use
+ xlink:href="#glyph0-28"
+ x="224.665225"
+ y="37.869"
+ id="use263" />
+ </g>
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M -55.623594 -19.705344 L 55.626406 -19.705344 L 55.626406 19.704812 L -55.623594 19.704812 Z M -55.623594 -19.705344 "
+ transform="matrix(1,0,0,-1,191.315,74.697)"
+ id="path267" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g279">
+ <use
+ xlink:href="#glyph0-1"
+ x="141.128"
+ y="65.232"
+ id="use269" />
+ <use
+ xlink:href="#glyph0-2"
+ x="147.770065"
+ y="65.232"
+ id="use271" />
+ <use
+ xlink:href="#glyph0-3"
+ x="150.150131"
+ y="65.232"
+ id="use273" />
+ <use
+ xlink:href="#glyph0-4"
+ x="152.530196"
+ y="65.232"
+ id="use275" />
<use xlink:href="#glyph0-5" x="156.958571" y="65.232"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-26" x="164.704493" y="65.232"/>
- <use xlink:href="#glyph0-16" x="169.852168" y="65.232"/>
- <use xlink:href="#glyph0-5" x="173.670833" y="65.232"/>
- <use xlink:href="#glyph0-16" x="178.099209" y="65.232"/>
-</g>
+ <use
+ xlink:href="#glyph0-26"
+ x="164.704493"
+ y="65.232"
+ id="use281" />
+ <use
+ xlink:href="#glyph0-16"
+ x="169.852168"
+ y="65.232"
+ id="use283" />
+ <use
+ xlink:href="#glyph0-5"
+ x="173.670833"
+ y="65.232"
+ id="use285" />
+ <use
+ xlink:href="#glyph0-16"
+ x="178.099209"
+ y="65.232"
+ id="use287" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-10" x="185.245382" y="65.232"/>
</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-20" x="193.350953" y="65.232"/>
- <use xlink:href="#glyph0-26" x="196.395523" y="65.232"/>
- <use xlink:href="#glyph0-2" x="201.543199" y="65.232"/>
- <use xlink:href="#glyph0-2" x="203.923264" y="65.232"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-11" x="209.620875" y="65.232"/>
- <use xlink:href="#glyph0-8" x="214.76855" y="65.232"/>
-</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g303">
+ <use
+ xlink:href="#glyph0-20"
+ x="193.350953"
+ y="65.232"
+ id="use295" />
+ <use
+ xlink:href="#glyph0-26"
+ x="196.395524"
+ y="65.232"
+ id="use297" />
+ <use
+ xlink:href="#glyph0-2"
+ x="201.543199"
+ y="65.232"
+ id="use299" />
+ <use
+ xlink:href="#glyph0-2"
+ x="203.923264"
+ y="65.232"
+ id="use301" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g309">
+ <use
+ xlink:href="#glyph0-11"
+ x="209.620875"
+ y="65.232"
+ id="use305" />
+ <use
+ xlink:href="#glyph0-8"
+ x="214.76855"
+ y="65.232"
+ id="use307" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-12" x="220.028803" y="65.232"/>
- <use xlink:href="#glyph0-5" x="225.176479" y="65.232"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-18" x="232.9224" y="65.232"/>
- <use xlink:href="#glyph0-8" x="236.519895" y="65.232"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-4" x="143.342" y="77.187"/>
- <use xlink:href="#glyph0-14" x="147.770376" y="77.187"/>
- <use xlink:href="#glyph0-5" x="151.174596" y="77.187"/>
- <use xlink:href="#glyph0-10" x="155.602972" y="77.187"/>
- <use xlink:href="#glyph0-18" x="160.390997" y="77.187"/>
- <use xlink:href="#glyph0-5" x="163.988492" y="77.187"/>
-</g>
+ <use
+ xlink:href="#glyph0-5"
+ x="225.176479"
+ y="65.232"
+ id="use313" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g321">
+ <use
+ xlink:href="#glyph0-18"
+ x="232.9224"
+ y="65.232"
+ id="use317" />
+ <use
+ xlink:href="#glyph0-8"
+ x="236.519895"
+ y="65.232"
+ id="use319" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g335">
+ <use
+ xlink:href="#glyph0-4"
+ x="143.342"
+ y="77.187"
+ id="use323" />
+ <use
+ xlink:href="#glyph0-14"
+ x="147.770376"
+ y="77.187"
+ id="use325" />
+ <use
+ xlink:href="#glyph0-5"
+ x="151.174596"
+ y="77.187"
+ id="use327" />
+ <use
+ xlink:href="#glyph0-10"
+ x="155.602972"
+ y="77.187"
+ id="use329" />
+ <use
+ xlink:href="#glyph0-18"
+ x="160.390997"
+ y="77.187"
+ id="use331" />
+ <use
+ xlink:href="#glyph0-5"
+ x="163.988492"
+ y="77.187"
+ id="use333" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-10" x="171.734414" y="77.187"/>
</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-29" x="179.839985" y="77.187"/>
- <use xlink:href="#glyph0-30" x="186.20509" y="77.187"/>
- <use xlink:href="#glyph0-7" x="191.740311" y="77.187"/>
- <use xlink:href="#glyph0-31" x="198.382376" y="77.187"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-15" x="208.49043" y="77.187"/>
- <use xlink:href="#glyph0-3" x="215.297875" y="77.187"/>
- <use xlink:href="#glyph0-18" x="217.67794" y="77.187"/>
- <use xlink:href="#glyph0-17" x="221.275435" y="77.187"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-10" x="229.740656" y="77.187"/>
- <use xlink:href="#glyph0-2" x="234.528682" y="77.187"/>
- <use xlink:href="#glyph0-2" x="236.908747" y="77.187"/>
-</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g349">
+ <use
+ xlink:href="#glyph0-29"
+ x="179.839985"
+ y="77.187"
+ id="use341" />
+ <use
+ xlink:href="#glyph0-30"
+ x="186.20509"
+ y="77.187"
+ id="use343" />
+ <use
+ xlink:href="#glyph0-7"
+ x="191.740311"
+ y="77.187"
+ id="use345" />
+ <use
+ xlink:href="#glyph0-31"
+ x="198.382376"
+ y="77.187"
+ id="use347" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g359">
+ <use
+ xlink:href="#glyph0-15"
+ x="208.49043"
+ y="77.187"
+ id="use351" />
+ <use
+ xlink:href="#glyph0-3"
+ x="215.297875"
+ y="77.187"
+ id="use353" />
+ <use
+ xlink:href="#glyph0-18"
+ x="217.67794"
+ y="77.187"
+ id="use355" />
+ <use
+ xlink:href="#glyph0-17"
+ x="221.275435"
+ y="77.187"
+ id="use357" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g367">
+ <use
+ xlink:href="#glyph0-10"
+ x="229.740656"
+ y="77.187"
+ id="use361" />
+ <use
+ xlink:href="#glyph0-2"
+ x="234.528682"
+ y="77.187"
+ id="use363" />
+ <use
+ xlink:href="#glyph0-2"
+ x="236.908747"
+ y="77.187"
+ id="use365" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-3" x="145.065" y="89.143"/>
<use xlink:href="#glyph0-11" x="147.445065" y="89.143"/>
<use xlink:href="#glyph0-19" x="152.592741" y="89.143"/>
<use xlink:href="#glyph0-26" x="157.740416" y="89.143"/>
- <use xlink:href="#glyph0-18" x="162.888091" y="89.143"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-32" x="169.803132" y="89.143"/>
- <use xlink:href="#glyph0-31" x="176.65242" y="89.143"/>
- <use xlink:href="#glyph0-33" x="183.432965" y="89.143"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-34" x="189.796078" y="89.143"/>
- <use xlink:href="#glyph0-16" x="197.129548" y="89.143"/>
-</g>
+ <use
+ xlink:href="#glyph0-18"
+ x="162.888091"
+ y="89.143"
+ id="use377" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g387">
+ <use
+ xlink:href="#glyph0-32"
+ x="169.803132"
+ y="89.143"
+ id="use381" />
+ <use
+ xlink:href="#glyph0-31"
+ x="176.65242"
+ y="89.143"
+ id="use383" />
+ <use
+ xlink:href="#glyph0-33"
+ x="183.432965"
+ y="89.143"
+ id="use385" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g393">
+ <use
+ xlink:href="#glyph0-34"
+ x="189.796078"
+ y="89.143"
+ id="use389" />
+ <use
+ xlink:href="#glyph0-16"
+ x="197.129548"
+ y="89.143"
+ id="use391" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-35" x="204.275721" y="89.143"/>
- <use xlink:href="#glyph0-2" x="209.61667" y="89.143"/>
- <use xlink:href="#glyph0-2" x="211.996736" y="89.143"/>
- <use xlink:href="#glyph0-5" x="214.376801" y="89.143"/>
- <use xlink:href="#glyph0-12" x="218.805176" y="89.143"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-3" x="227.270398" y="89.143"/>
+ <use
+ xlink:href="#glyph0-2"
+ x="209.61667"
+ y="89.143"
+ id="use397" />
+ <use
+ xlink:href="#glyph0-2"
+ x="211.996736"
+ y="89.143"
+ id="use399" />
+ <use
+ xlink:href="#glyph0-5"
+ x="214.376801"
+ y="89.143"
+ id="use401" />
+ <use
+ xlink:href="#glyph0-12"
+ x="218.805176"
+ y="89.143"
+ id="use403" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g413">
+ <use
+ xlink:href="#glyph0-3"
+ x="227.270398"
+ y="89.143"
+ id="use407" />
<use xlink:href="#glyph0-11" x="229.650463" y="89.143"/>
<use xlink:href="#glyph0-28" x="234.798138" y="89.143"/>
</g>
<path style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -55.623594 -6.781125 L 55.626406 -6.781125 L 55.626406 6.781375 L -55.623594 6.781375 Z M -55.623594 -6.781125 " transform="matrix(1,0,0,-1,191.315,113.047)"/>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-29" x="153.512" y="116.506"/>
- <use xlink:href="#glyph0-30" x="159.877105" y="116.506"/>
- <use xlink:href="#glyph0-7" x="165.412326" y="116.506"/>
- <use xlink:href="#glyph0-31" x="172.054391" y="116.506"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-12" x="182.152482" y="116.506"/>
- <use xlink:href="#glyph0-3" x="187.300158" y="116.506"/>
- <use xlink:href="#glyph0-16" x="189.680223" y="116.506"/>
- <use xlink:href="#glyph0-18" x="193.498888" y="116.506"/>
- <use xlink:href="#glyph0-14" x="197.096382" y="116.506"/>
- <use xlink:href="#glyph0-3" x="200.500603" y="116.506"/>
- <use xlink:href="#glyph0-9" x="202.880668" y="116.506"/>
- <use xlink:href="#glyph0-26" x="208.028343" y="116.506"/>
- <use xlink:href="#glyph0-18" x="213.176019" y="116.506"/>
- <use xlink:href="#glyph0-5" x="216.773514" y="116.506"/>
- <use xlink:href="#glyph0-12" x="221.201889" y="116.506"/>
- <use xlink:href="#glyph0-28" x="226.349565" y="116.506"/>
+ <use
+ xlink:href="#glyph0-29"
+ x="153.512"
+ y="116.506"
+ id="use417" />
+ <use
+ xlink:href="#glyph0-30"
+ x="159.877105"
+ y="116.506"
+ id="use419" />
+ <use
+ xlink:href="#glyph0-7"
+ x="165.412326"
+ y="116.506"
+ id="use421" />
+ <use
+ xlink:href="#glyph0-31"
+ x="172.054391"
+ y="116.506"
+ id="use423" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g451">
+ <use
+ xlink:href="#glyph0-12"
+ x="182.152482"
+ y="116.506"
+ id="use427" />
+ <use
+ xlink:href="#glyph0-3"
+ x="187.300158"
+ y="116.506"
+ id="use429" />
+ <use
+ xlink:href="#glyph0-16"
+ x="189.680223"
+ y="116.506"
+ id="use431" />
+ <use
+ xlink:href="#glyph0-18"
+ x="193.498888"
+ y="116.506"
+ id="use433" />
+ <use
+ xlink:href="#glyph0-14"
+ x="197.096382"
+ y="116.506"
+ id="use435" />
+ <use
+ xlink:href="#glyph0-3"
+ x="200.500603"
+ y="116.506"
+ id="use437" />
+ <use
+ xlink:href="#glyph0-9"
+ x="202.880668"
+ y="116.506"
+ id="use439" />
+ <use
+ xlink:href="#glyph0-26"
+ x="208.028343"
+ y="116.506"
+ id="use441" />
+ <use
+ xlink:href="#glyph0-18"
+ x="213.176019"
+ y="116.506"
+ id="use443" />
+ <use
+ xlink:href="#glyph0-5"
+ x="216.773514"
+ y="116.506"
+ id="use445" />
+ <use
+ xlink:href="#glyph0-12"
+ x="221.201889"
+ y="116.506"
+ id="use447" />
+ <use
+ xlink:href="#glyph0-28"
+ x="226.349565"
+ y="116.506"
+ id="use449" />
</g>
<path style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -55.625625 -12.75925 L 55.624375 -12.75925 L 55.624375 12.756375 L -55.625625 12.756375 Z M -55.625625 -12.75925 " transform="matrix(1,0,0,-1,65.985,151.397)"/>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-1" x="21.555" y="148.879"/>
- <use xlink:href="#glyph0-2" x="28.197065" y="148.879"/>
- <use xlink:href="#glyph0-3" x="30.577131" y="148.879"/>
- <use xlink:href="#glyph0-4" x="32.957196" y="148.879"/>
- <use xlink:href="#glyph0-5" x="37.385571" y="148.879"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-16" x="45.131493" y="148.879"/>
- <use xlink:href="#glyph0-3" x="48.950157" y="148.879"/>
- <use xlink:href="#glyph0-27" x="51.330223" y="148.879"/>
- <use xlink:href="#glyph0-11" x="56.311523" y="148.879"/>
- <use xlink:href="#glyph0-16" x="61.459198" y="148.879"/>
-</g>
+ <use
+ xlink:href="#glyph0-2"
+ x="28.197065"
+ y="148.879"
+ id="use457" />
+ <use
+ xlink:href="#glyph0-3"
+ x="30.577131"
+ y="148.879"
+ id="use459" />
+ <use
+ xlink:href="#glyph0-4"
+ x="32.957196"
+ y="148.879"
+ id="use461" />
+ <use
+ xlink:href="#glyph0-5"
+ x="37.385571"
+ y="148.879"
+ id="use463" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g477">
+ <use
+ xlink:href="#glyph0-16"
+ x="45.131493"
+ y="148.879"
+ id="use467" />
+ <use
+ xlink:href="#glyph0-3"
+ x="48.950157"
+ y="148.879"
+ id="use469" />
+ <use
+ xlink:href="#glyph0-27"
+ x="51.330223"
+ y="148.879"
+ id="use471" />
+ <use
+ xlink:href="#glyph0-11"
+ x="56.311523"
+ y="148.879"
+ id="use473" />
+ <use
+ xlink:href="#glyph0-16"
+ x="61.459198"
+ y="148.879"
+ id="use475" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-18" x="68.595408" y="148.879"/>
- <use xlink:href="#glyph0-17" x="72.192903" y="148.879"/>
- <use xlink:href="#glyph0-5" x="77.340579" y="148.879"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-29" x="85.096463" y="148.879"/>
- <use xlink:href="#glyph0-30" x="91.461568" y="148.879"/>
- <use xlink:href="#glyph0-7" x="96.996789" y="148.879"/>
- <use xlink:href="#glyph0-31" x="103.638854" y="148.879"/>
-</g>
+ <use
+ xlink:href="#glyph0-17"
+ x="72.192903"
+ y="148.879"
+ id="use481" />
+ <use
+ xlink:href="#glyph0-5"
+ x="77.340579"
+ y="148.879"
+ id="use483" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g495">
+ <use
+ xlink:href="#glyph0-29"
+ x="85.096463"
+ y="148.879"
+ id="use487" />
+ <use
+ xlink:href="#glyph0-30"
+ x="91.461568"
+ y="148.879"
+ id="use489" />
+ <use
+ xlink:href="#glyph0-7"
+ x="96.996789"
+ y="148.879"
+ id="use491" />
+ <use
+ xlink:href="#glyph0-31"
+ x="103.638854"
+ y="148.879"
+ id="use493" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-15" x="33.773" y="160.834"/>
- <use xlink:href="#glyph0-3" x="40.580445" y="160.834"/>
- <use xlink:href="#glyph0-18" x="42.96051" y="160.834"/>
- <use xlink:href="#glyph0-17" x="46.558005" y="160.834"/>
-</g>
+ <use
+ xlink:href="#glyph0-3"
+ x="40.580445"
+ y="160.834"
+ id="use499" />
+ <use
+ xlink:href="#glyph0-18"
+ x="42.96051"
+ y="160.834"
+ id="use501" />
+ <use
+ xlink:href="#glyph0-17"
+ x="46.558005"
+ y="160.834"
+ id="use503" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-17" x="55.023226" y="160.834"/>
<use xlink:href="#glyph0-5" x="60.170901" y="160.834"/>
<use xlink:href="#glyph0-14" x="64.599277" y="160.834"/>
</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-15" x="71.321043" y="160.834"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-10" x="77.859498" y="160.834"/>
- <use xlink:href="#glyph0-2" x="82.647523" y="160.834"/>
- <use xlink:href="#glyph0-2" x="85.027588" y="160.834"/>
- <use xlink:href="#glyph0-5" x="87.407653" y="160.834"/>
- <use xlink:href="#glyph0-18" x="91.836029" y="160.834"/>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g517">
+ <use
+ xlink:href="#glyph0-15"
+ x="71.321043"
+ y="160.834"
+ id="use515" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g531">
+ <use
+ xlink:href="#glyph0-10"
+ x="77.859498"
+ y="160.834"
+ id="use519" />
+ <use
+ xlink:href="#glyph0-2"
+ x="82.647523"
+ y="160.834"
+ id="use521" />
+ <use
+ xlink:href="#glyph0-2"
+ x="85.027588"
+ y="160.834"
+ id="use523" />
+ <use
+ xlink:href="#glyph0-5"
+ x="87.407653"
+ y="160.834"
+ id="use525" />
+ <use
+ xlink:href="#glyph0-18"
+ x="91.836029"
+ y="160.834"
+ id="use527" />
<use xlink:href="#glyph0-28" x="95.433524" y="160.834"/>
</g>
<path style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -55.623594 -12.75925 L 55.626406 -12.75925 L 55.626406 12.756375 L -55.623594 12.756375 Z M -55.623594 -12.75925 " transform="matrix(1,0,0,-1,191.315,151.397)"/>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-7" x="148.628" y="148.879"/>
- <use xlink:href="#glyph0-8" x="155.270065" y="148.879"/>
- <use xlink:href="#glyph0-9" x="160.251365" y="148.879"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-16" x="168.716587" y="148.879"/>
- <use xlink:href="#glyph0-3" x="172.535251" y="148.879"/>
- <use xlink:href="#glyph0-27" x="174.915316" y="148.879"/>
- <use xlink:href="#glyph0-11" x="179.896616" y="148.879"/>
- <use xlink:href="#glyph0-16" x="185.044292" y="148.879"/>
-</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g541">
+ <use
+ xlink:href="#glyph0-7"
+ x="148.628"
+ y="148.879"
+ id="use535" />
+ <use
+ xlink:href="#glyph0-8"
+ x="155.270065"
+ y="148.879"
+ id="use537" />
+ <use
+ xlink:href="#glyph0-9"
+ x="160.251365"
+ y="148.879"
+ id="use539" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g553">
+ <use
+ xlink:href="#glyph0-16"
+ x="168.716587"
+ y="148.879"
+ id="use543" />
+ <use
+ xlink:href="#glyph0-3"
+ x="172.535251"
+ y="148.879"
+ id="use545" />
+ <use
+ xlink:href="#glyph0-27"
+ x="174.915316"
+ y="148.879"
+ id="use547" />
+ <use
+ xlink:href="#glyph0-11"
+ x="179.896616"
+ y="148.879"
+ id="use549" />
+ <use
+ xlink:href="#glyph0-16"
+ x="185.044292"
+ y="148.879"
+ id="use551" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-18" x="192.190465" y="148.879"/>
- <use xlink:href="#glyph0-17" x="195.78796" y="148.879"/>
- <use xlink:href="#glyph0-5" x="200.935635" y="148.879"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-29" x="208.681557" y="148.879"/>
- <use xlink:href="#glyph0-30" x="215.046662" y="148.879"/>
- <use xlink:href="#glyph0-7" x="220.581882" y="148.879"/>
- <use xlink:href="#glyph0-31" x="227.223948" y="148.879"/>
-</g>
+ <use
+ xlink:href="#glyph0-17"
+ x="195.78796"
+ y="148.879"
+ id="use557" />
+ <use
+ xlink:href="#glyph0-5"
+ x="200.935635"
+ y="148.879"
+ id="use559" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g571">
+ <use
+ xlink:href="#glyph0-29"
+ x="208.681557"
+ y="148.879"
+ id="use563" />
+ <use
+ xlink:href="#glyph0-30"
+ x="215.046662"
+ y="148.879"
+ id="use565" />
+ <use
+ xlink:href="#glyph0-7"
+ x="220.581882"
+ y="148.879"
+ id="use567" />
+ <use
+ xlink:href="#glyph0-31"
+ x="227.223948"
+ y="148.879"
+ id="use569" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-15" x="148.988" y="160.834"/>
- <use xlink:href="#glyph0-3" x="155.795445" y="160.834"/>
- <use xlink:href="#glyph0-18" x="158.17551" y="160.834"/>
- <use xlink:href="#glyph0-17" x="161.773005" y="160.834"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-17" x="170.238226" y="160.834"/>
- <use xlink:href="#glyph0-3" x="175.385901" y="160.834"/>
- <use xlink:href="#glyph0-16" x="177.765966" y="160.834"/>
-</g>
+ <use
+ xlink:href="#glyph0-3"
+ x="155.795445"
+ y="160.834"
+ id="use575" />
+ <use
+ xlink:href="#glyph0-18"
+ x="158.17551"
+ y="160.834"
+ id="use577" />
+ <use
+ xlink:href="#glyph0-17"
+ x="161.773005"
+ y="160.834"
+ id="use579" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g589">
+ <use
+ xlink:href="#glyph0-17"
+ x="170.238226"
+ y="160.834"
+ id="use583" />
+ <use
+ xlink:href="#glyph0-3"
+ x="175.385901"
+ y="160.834"
+ id="use585" />
+ <use
+ xlink:href="#glyph0-16"
+ x="177.765966"
+ y="160.834"
+ id="use587" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-30" x="184.912139" y="160.834"/>
- <use xlink:href="#glyph0-29" x="190.44736" y="160.834"/>
- <use xlink:href="#glyph0-36" x="196.812465" y="160.834"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-15" x="206.772076" y="160.834"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-10" x="213.300568" y="160.834"/>
- <use xlink:href="#glyph0-2" x="218.088594" y="160.834"/>
- <use xlink:href="#glyph0-2" x="220.468659" y="160.834"/>
- <use xlink:href="#glyph0-5" x="222.848724" y="160.834"/>
+ <use
+ xlink:href="#glyph0-29"
+ x="190.44736"
+ y="160.834"
+ id="use593" />
+ <use
+ xlink:href="#glyph0-36"
+ x="196.812465"
+ y="160.834"
+ id="use595" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g601">
+ <use
+ xlink:href="#glyph0-15"
+ x="206.772076"
+ y="160.834"
+ id="use599" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g615">
+ <use
+ xlink:href="#glyph0-10"
+ x="213.300568"
+ y="160.834"
+ id="use603" />
+ <use
+ xlink:href="#glyph0-2"
+ x="218.088594"
+ y="160.834"
+ id="use605" />
+ <use
+ xlink:href="#glyph0-2"
+ x="220.468659"
+ y="160.834"
+ id="use607" />
+ <use
+ xlink:href="#glyph0-5"
+ x="222.848724"
+ y="160.834"
+ id="use609" />
<use xlink:href="#glyph0-18" x="227.2771" y="160.834"/>
<use xlink:href="#glyph0-28" x="230.874594" y="160.834"/>
</g>
-<path style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -55.624469 -19.704563 L 55.625531 -19.704563 L 55.625531 19.705594 L -55.624469 19.705594 Z M -55.624469 -19.704563 " transform="matrix(1,0,0,-1,316.644,151.397)"/>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-13" x="271.522" y="141.932"/>
- <use xlink:href="#glyph0-10" x="277.887105" y="141.932"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-14" x="282.396178" y="141.932"/>
- <use xlink:href="#glyph0-8" x="285.800398" y="141.932"/>
- <use xlink:href="#glyph0-2" x="290.781698" y="141.932"/>
-</g>
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M -55.624469 -19.704563 L 55.625531 -19.704563 L 55.625531 19.705594 L -55.624469 19.705594 Z M -55.624469 -19.704563 "
+ transform="matrix(1,0,0,-1,316.644,151.397)"
+ id="path617" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g623">
+ <use
+ xlink:href="#glyph0-13"
+ x="271.522"
+ y="141.932"
+ id="use619" />
+ <use
+ xlink:href="#glyph0-10"
+ x="277.887105"
+ y="141.932"
+ id="use621" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g631">
+ <use
+ xlink:href="#glyph0-14"
+ x="282.396178"
+ y="141.932"
+ id="use625" />
+ <use
+ xlink:href="#glyph0-8"
+ x="285.800398"
+ y="141.932"
+ id="use627" />
+ <use
+ xlink:href="#glyph0-2"
+ x="290.781698"
+ y="141.932"
+ id="use629" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-16" x="296.479309" y="141.932"/>
- <use xlink:href="#glyph0-3" x="300.297974" y="141.932"/>
- <use xlink:href="#glyph0-27" x="302.678039" y="141.932"/>
- <use xlink:href="#glyph0-11" x="307.659339" y="141.932"/>
- <use xlink:href="#glyph0-16" x="312.807014" y="141.932"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-18" x="319.953187" y="141.932"/>
- <use xlink:href="#glyph0-17" x="323.550682" y="141.932"/>
- <use xlink:href="#glyph0-5" x="328.698358" y="141.932"/>
-</g>
+ <use
+ xlink:href="#glyph0-3"
+ x="300.297974"
+ y="141.932"
+ id="use635" />
+ <use
+ xlink:href="#glyph0-27"
+ x="302.678039"
+ y="141.932"
+ id="use637" />
+ <use
+ xlink:href="#glyph0-11"
+ x="307.659339"
+ y="141.932"
+ id="use639" />
+ <use
+ xlink:href="#glyph0-16"
+ x="312.807014"
+ y="141.932"
+ id="use641" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g651">
+ <use
+ xlink:href="#glyph0-18"
+ x="319.953187"
+ y="141.932"
+ id="use645" />
+ <use
+ xlink:href="#glyph0-17"
+ x="323.550682"
+ y="141.932"
+ id="use647" />
+ <use
+ xlink:href="#glyph0-5"
+ x="328.698358"
+ y="141.932"
+ id="use649" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-29" x="336.444279" y="141.932"/>
- <use xlink:href="#glyph0-30" x="342.809384" y="141.932"/>
- <use xlink:href="#glyph0-7" x="348.344605" y="141.932"/>
- <use xlink:href="#glyph0-31" x="354.98667" y="141.932"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-15" x="279.824" y="153.888"/>
- <use xlink:href="#glyph0-3" x="286.631445" y="153.888"/>
- <use xlink:href="#glyph0-18" x="289.01151" y="153.888"/>
- <use xlink:href="#glyph0-17" x="292.609005" y="153.888"/>
-</g>
+ <use
+ xlink:href="#glyph0-30"
+ x="342.809384"
+ y="141.932"
+ id="use655" />
+ <use
+ xlink:href="#glyph0-7"
+ x="348.344605"
+ y="141.932"
+ id="use657" />
+ <use
+ xlink:href="#glyph0-31"
+ x="354.98667"
+ y="141.932"
+ id="use659" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g671">
+ <use
+ xlink:href="#glyph0-15"
+ x="279.824"
+ y="153.888"
+ id="use663" />
+ <use
+ xlink:href="#glyph0-3"
+ x="286.631445"
+ y="153.888"
+ id="use665" />
+ <use
+ xlink:href="#glyph0-18"
+ x="289.01151"
+ y="153.888"
+ id="use667" />
+ <use
+ xlink:href="#glyph0-17"
+ x="292.609005"
+ y="153.888"
+ id="use669" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-10" x="301.074226" y="153.888"/>
</g>
@@ -471,397 +1166,1381 @@
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-8" x="313.608173" y="153.888"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-21" x="318.599435" y="153.888"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph0-21" x="318.589473" y="153.888"/>
<use xlink:href="#glyph0-19" x="326.504759" y="153.888"/>
<use xlink:href="#glyph0-2" x="331.652434" y="153.888"/>
<use xlink:href="#glyph0-5" x="334.032499" y="153.888"/>
- <use xlink:href="#glyph0-18" x="338.460875" y="153.888"/>
- <use xlink:href="#glyph0-5" x="342.05837" y="153.888"/>
- <use xlink:href="#glyph0-2" x="346.486745" y="153.888"/>
- <use xlink:href="#glyph0-37" x="348.866811" y="153.888"/>
-</g>
+ <use
+ xlink:href="#glyph0-18"
+ x="338.460875"
+ y="153.888"
+ id="use691" />
+ <use
+ xlink:href="#glyph0-5"
+ x="342.05837"
+ y="153.888"
+ id="use693" />
+ <use
+ xlink:href="#glyph0-2"
+ x="346.486745"
+ y="153.888"
+ id="use695" />
+ <use
+ xlink:href="#glyph0-37"
+ x="348.866811"
+ y="153.888"
+ id="use697" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-8" x="267.882" y="165.843"/>
<use xlink:href="#glyph0-38" x="272.8633" y="165.843"/>
- <use xlink:href="#glyph0-3" x="280.97186" y="165.843"/>
- <use xlink:href="#glyph0-11" x="283.351925" y="165.843"/>
- <use xlink:href="#glyph0-5" x="288.499601" y="165.843"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-16" x="296.245522" y="165.843"/>
- <use xlink:href="#glyph0-3" x="300.064187" y="165.843"/>
- <use xlink:href="#glyph0-27" x="302.444252" y="165.843"/>
- <use xlink:href="#glyph0-11" x="307.425552" y="165.843"/>
+ <use
+ xlink:href="#glyph0-3"
+ x="280.97186"
+ y="165.843"
+ id="use705" />
+ <use
+ xlink:href="#glyph0-11"
+ x="283.351925"
+ y="165.843"
+ id="use707" />
+ <use
+ xlink:href="#glyph0-5"
+ x="288.499601"
+ y="165.843"
+ id="use709" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g727">
+ <use
+ xlink:href="#glyph0-16"
+ x="296.245522"
+ y="165.843"
+ id="use713" />
+ <use
+ xlink:href="#glyph0-3"
+ x="300.064187"
+ y="165.843"
+ id="use715" />
+ <use
+ xlink:href="#glyph0-27"
+ x="302.444252"
+ y="165.843"
+ id="use717" />
+ <use
+ xlink:href="#glyph0-11"
+ x="307.425552"
+ y="165.843"
+ id="use719" />
<use xlink:href="#glyph0-3" x="312.573227" y="165.843"/>
<use xlink:href="#glyph0-11" x="314.953292" y="165.843"/>
<use xlink:href="#glyph0-27" x="320.100968" y="165.843"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-21" x="328.409776" y="165.843"/>
- <use xlink:href="#glyph0-10" x="336.325062" y="165.843"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph0-10" x="336.315099" y="165.843"/>
<use xlink:href="#glyph0-4" x="341.103125" y="165.843"/>
- <use xlink:href="#glyph0-17" x="345.531501" y="165.843"/>
- <use xlink:href="#glyph0-3" x="350.679176" y="165.843"/>
- <use xlink:href="#glyph0-11" x="353.059241" y="165.843"/>
- <use xlink:href="#glyph0-5" x="358.206917" y="165.843"/>
+ <use
+ xlink:href="#glyph0-17"
+ x="345.531501"
+ y="165.843"
+ id="use737" />
+ <use
+ xlink:href="#glyph0-3"
+ x="350.679176"
+ y="165.843"
+ id="use739" />
+ <use
+ xlink:href="#glyph0-11"
+ x="353.059241"
+ y="165.843"
+ id="use741" />
+ <use
+ xlink:href="#glyph0-5"
+ x="358.206917"
+ y="165.843"
+ id="use743" />
<use xlink:href="#glyph0-28" x="362.635292" y="165.843"/>
</g>
<path style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -55.623594 -12.759375 L 55.626406 -12.759375 L 55.626406 12.75625 L -55.623594 12.75625 Z M -55.623594 -12.759375 " transform="matrix(1,0,0,-1,191.315,195.725)"/>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-29" x="169.328" y="193.206"/>
- <use xlink:href="#glyph0-30" x="175.693105" y="193.206"/>
- <use xlink:href="#glyph0-7" x="181.228326" y="193.206"/>
- <use xlink:href="#glyph0-31" x="187.870391" y="193.206"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-16" x="193.824041" y="193.206"/>
-</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g759">
+ <use
+ xlink:href="#glyph0-29"
+ x="169.328"
+ y="193.206"
+ id="use751" />
+ <use
+ xlink:href="#glyph0-30"
+ x="175.693105"
+ y="193.206"
+ id="use753" />
+ <use
+ xlink:href="#glyph0-7"
+ x="181.228326"
+ y="193.206"
+ id="use755" />
+ <use
+ xlink:href="#glyph0-31"
+ x="187.870391"
+ y="193.206"
+ id="use757" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g763">
+ <use
+ xlink:href="#glyph0-16"
+ x="193.824041"
+ y="193.206"
+ id="use761" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-10" x="200.960251" y="193.206"/>
</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-14" x="205.469324" y="193.206"/>
- <use xlink:href="#glyph0-5" x="208.873544" y="193.206"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-14" x="154.84" y="205.161"/>
- <use xlink:href="#glyph0-5" x="158.24422" y="205.161"/>
- <use xlink:href="#glyph0-18" x="162.672596" y="205.161"/>
- <use xlink:href="#glyph0-26" x="166.270091" y="205.161"/>
- <use xlink:href="#glyph0-14" x="171.417766" y="205.161"/>
- <use xlink:href="#glyph0-11" x="174.821987" y="205.161"/>
- <use xlink:href="#glyph0-5" x="179.969662" y="205.161"/>
- <use xlink:href="#glyph0-12" x="184.398038" y="205.161"/>
-</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g773">
+ <use
+ xlink:href="#glyph0-14"
+ x="205.469324"
+ y="193.206"
+ id="use769" />
+ <use
+ xlink:href="#glyph0-5"
+ x="208.873544"
+ y="193.206"
+ id="use771" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g791">
+ <use
+ xlink:href="#glyph0-14"
+ x="154.84"
+ y="205.161"
+ id="use775" />
+ <use
+ xlink:href="#glyph0-5"
+ x="158.24422"
+ y="205.161"
+ id="use777" />
+ <use
+ xlink:href="#glyph0-18"
+ x="162.672596"
+ y="205.161"
+ id="use779" />
+ <use
+ xlink:href="#glyph0-26"
+ x="166.270091"
+ y="205.161"
+ id="use781" />
+ <use
+ xlink:href="#glyph0-14"
+ x="171.417766"
+ y="205.161"
+ id="use783" />
+ <use
+ xlink:href="#glyph0-11"
+ x="174.821987"
+ y="205.161"
+ id="use785" />
+ <use
+ xlink:href="#glyph0-5"
+ x="179.969662"
+ y="205.161"
+ id="use787" />
+ <use
+ xlink:href="#glyph0-12"
+ x="184.398038"
+ y="205.161"
+ id="use789" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-18" x="192.863259" y="205.161"/>
- <use xlink:href="#glyph0-8" x="196.460754" y="205.161"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-1" x="204.7596" y="205.161"/>
- <use xlink:href="#glyph0-2" x="211.401665" y="205.161"/>
- <use xlink:href="#glyph0-3" x="213.78173" y="205.161"/>
- <use xlink:href="#glyph0-4" x="216.161796" y="205.161"/>
- <use xlink:href="#glyph0-5" x="220.590171" y="205.161"/>
- <use xlink:href="#glyph0-28" x="225.018547" y="205.161"/>
-</g>
+ <use
+ xlink:href="#glyph0-8"
+ x="196.460754"
+ y="205.161"
+ id="use795" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g811">
+ <use
+ xlink:href="#glyph0-1"
+ x="204.7596"
+ y="205.161"
+ id="use799" />
+ <use
+ xlink:href="#glyph0-2"
+ x="211.401665"
+ y="205.161"
+ id="use801" />
+ <use
+ xlink:href="#glyph0-3"
+ x="213.78173"
+ y="205.161"
+ id="use803" />
+ <use
+ xlink:href="#glyph0-4"
+ x="216.161796"
+ y="205.161"
+ id="use805" />
+ <use
+ xlink:href="#glyph0-5"
+ x="220.590171"
+ y="205.161"
+ id="use807" />
+ <use
+ xlink:href="#glyph0-28"
+ x="225.018547"
+ y="205.161"
+ id="use809" />
+ </g>
<path style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -55.623594 -19.701906 L 55.626406 -19.701906 L 55.626406 19.704344 L -55.623594 19.704344 Z M -55.623594 -19.701906 " transform="matrix(1,0,0,-1,191.315,240.052)"/>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-1" x="150.246" y="230.588"/>
- <use xlink:href="#glyph0-2" x="156.888065" y="230.588"/>
- <use xlink:href="#glyph0-3" x="159.268131" y="230.588"/>
- <use xlink:href="#glyph0-4" x="161.648196" y="230.588"/>
- <use xlink:href="#glyph0-5" x="166.076571" y="230.588"/>
- <use xlink:href="#glyph0-16" x="170.504947" y="230.588"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-4" x="177.641157" y="230.588"/>
- <use xlink:href="#glyph0-8" x="182.069533" y="230.588"/>
- <use xlink:href="#glyph0-21" x="187.050833" y="230.588"/>
- <use xlink:href="#glyph0-9" x="194.966119" y="230.588"/>
- <use xlink:href="#glyph0-3" x="200.113794" y="230.588"/>
- <use xlink:href="#glyph0-11" x="202.493859" y="230.588"/>
- <use xlink:href="#glyph0-5" x="207.641535" y="230.588"/>
- <use xlink:href="#glyph0-16" x="212.069911" y="230.588"/>
-</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g827">
+ <use
+ xlink:href="#glyph0-1"
+ x="150.246"
+ y="230.588"
+ id="use815" />
+ <use
+ xlink:href="#glyph0-2"
+ x="156.888065"
+ y="230.588"
+ id="use817" />
+ <use
+ xlink:href="#glyph0-3"
+ x="159.268131"
+ y="230.588"
+ id="use819" />
+ <use
+ xlink:href="#glyph0-4"
+ x="161.648196"
+ y="230.588"
+ id="use821" />
+ <use
+ xlink:href="#glyph0-5"
+ x="166.076571"
+ y="230.588"
+ id="use823" />
+ <use
+ xlink:href="#glyph0-16"
+ x="170.504947"
+ y="230.588"
+ id="use825" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g845">
+ <use
+ xlink:href="#glyph0-4"
+ x="177.641157"
+ y="230.588"
+ id="use829" />
+ <use
+ xlink:href="#glyph0-8"
+ x="182.069533"
+ y="230.588"
+ id="use831" />
+ <use
+ xlink:href="#glyph0-21"
+ x="187.050833"
+ y="230.588"
+ id="use833" />
+ <use
+ xlink:href="#glyph0-9"
+ x="194.966119"
+ y="230.588"
+ id="use835" />
+ <use
+ xlink:href="#glyph0-3"
+ x="200.113794"
+ y="230.588"
+ id="use837" />
+ <use
+ xlink:href="#glyph0-11"
+ x="202.493859"
+ y="230.588"
+ id="use839" />
+ <use
+ xlink:href="#glyph0-5"
+ x="207.641535"
+ y="230.588"
+ id="use841" />
+ <use
+ xlink:href="#glyph0-16"
+ x="212.069911"
+ y="230.588"
+ id="use843" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-18" x="219.206121" y="230.588"/>
- <use xlink:href="#glyph0-17" x="222.803616" y="230.588"/>
- <use xlink:href="#glyph0-5" x="227.951291" y="230.588"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-29" x="153.304" y="242.543"/>
- <use xlink:href="#glyph0-30" x="159.669105" y="242.543"/>
- <use xlink:href="#glyph0-7" x="165.204326" y="242.543"/>
- <use xlink:href="#glyph0-31" x="171.846391" y="242.543"/>
-</g>
+ <use
+ xlink:href="#glyph0-17"
+ x="222.803616"
+ y="230.588"
+ id="use849" />
+ <use
+ xlink:href="#glyph0-5"
+ x="227.951291"
+ y="230.588"
+ id="use851" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g863">
+ <use
+ xlink:href="#glyph0-29"
+ x="153.304"
+ y="242.543"
+ id="use855" />
+ <use
+ xlink:href="#glyph0-30"
+ x="159.669105"
+ y="242.543"
+ id="use857" />
+ <use
+ xlink:href="#glyph0-7"
+ x="165.204326"
+ y="242.543"
+ id="use859" />
+ <use
+ xlink:href="#glyph0-31"
+ x="171.846391"
+ y="242.543"
+ id="use861" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-16" x="177.800041" y="242.543"/>
- <use xlink:href="#glyph0-28" x="181.618705" y="242.543"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-1" x="189.367616" y="242.543"/>
- <use xlink:href="#glyph0-2" x="196.009681" y="242.543"/>
- <use xlink:href="#glyph0-2" x="198.389746" y="242.543"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-3" x="204.087357" y="242.543"/>
- <use xlink:href="#glyph0-11" x="206.467422" y="242.543"/>
+ <use
+ xlink:href="#glyph0-28"
+ x="181.618705"
+ y="242.543"
+ id="use867" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g877">
+ <use
+ xlink:href="#glyph0-1"
+ x="189.367616"
+ y="242.543"
+ id="use871" />
+ <use
+ xlink:href="#glyph0-2"
+ x="196.009681"
+ y="242.543"
+ id="use873" />
+ <use
+ xlink:href="#glyph0-2"
+ x="198.389746"
+ y="242.543"
+ id="use875" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g891">
+ <use
+ xlink:href="#glyph0-3"
+ x="204.087357"
+ y="242.543"
+ id="use879" />
+ <use
+ xlink:href="#glyph0-11"
+ x="206.467422"
+ y="242.543"
+ id="use881" />
<use xlink:href="#glyph0-19" x="211.615098" y="242.543"/>
<use xlink:href="#glyph0-26" x="216.762773" y="242.543"/>
- <use xlink:href="#glyph0-18" x="221.910449" y="242.543"/>
- <use xlink:href="#glyph0-16" x="225.507944" y="242.543"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-11" x="143.896" y="254.498"/>
- <use xlink:href="#glyph0-8" x="149.043675" y="254.498"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-15" x="153.746023" y="254.498"/>
-</g>
+ <use
+ xlink:href="#glyph0-18"
+ x="221.910449"
+ y="242.543"
+ id="use887" />
+ <use
+ xlink:href="#glyph0-16"
+ x="225.507944"
+ y="242.543"
+ id="use889" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g897">
+ <use
+ xlink:href="#glyph0-11"
+ x="143.896"
+ y="254.498"
+ id="use893" />
+ <use
+ xlink:href="#glyph0-8"
+ x="149.043675"
+ y="254.498"
+ id="use895" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g901">
+ <use
+ xlink:href="#glyph0-15"
+ x="153.746023"
+ y="254.498"
+ id="use899" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-17" x="163.871013" y="254.498"/>
<use xlink:href="#glyph0-10" x="169.018688" y="254.498"/>
- <use xlink:href="#glyph0-39" x="173.806714" y="254.498"/>
- <use xlink:href="#glyph0-5" x="178.400469" y="254.498"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-24" x="186.156353" y="254.498"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-16" x="194.455199" y="254.498"/>
- <use xlink:href="#glyph0-3" x="198.273863" y="254.498"/>
+ <use
+ xlink:href="#glyph0-39"
+ x="173.806714"
+ y="254.498"
+ id="use907" />
+ <use
+ xlink:href="#glyph0-5"
+ x="178.400469"
+ y="254.498"
+ id="use909" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g915">
+ <use
+ xlink:href="#glyph0-24"
+ x="186.156353"
+ y="254.498"
+ id="use913" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g939">
+ <use
+ xlink:href="#glyph0-16"
+ x="194.455199"
+ y="254.498"
+ id="use917" />
+ <use
+ xlink:href="#glyph0-3"
+ x="198.273863"
+ y="254.498"
+ id="use919" />
<use xlink:href="#glyph0-27" x="200.653928" y="254.498"/>
<use xlink:href="#glyph0-11" x="205.635228" y="254.498"/>
- <use xlink:href="#glyph0-10" x="210.782904" y="254.498"/>
- <use xlink:href="#glyph0-18" x="215.570929" y="254.498"/>
- <use xlink:href="#glyph0-26" x="219.168424" y="254.498"/>
- <use xlink:href="#glyph0-14" x="224.3161" y="254.498"/>
- <use xlink:href="#glyph0-5" x="227.72032" y="254.498"/>
- <use xlink:href="#glyph0-16" x="232.148696" y="254.498"/>
- <use xlink:href="#glyph0-28" x="235.96736" y="254.498"/>
-</g>
+ <use
+ xlink:href="#glyph0-10"
+ x="210.782904"
+ y="254.498"
+ id="use925" />
+ <use
+ xlink:href="#glyph0-18"
+ x="215.570929"
+ y="254.498"
+ id="use927" />
+ <use
+ xlink:href="#glyph0-26"
+ x="219.168424"
+ y="254.498"
+ id="use929" />
+ <use
+ xlink:href="#glyph0-14"
+ x="224.3161"
+ y="254.498"
+ id="use931" />
+ <use
+ xlink:href="#glyph0-5"
+ x="227.72032"
+ y="254.498"
+ id="use933" />
+ <use
+ xlink:href="#glyph0-16"
+ x="232.148696"
+ y="254.498"
+ id="use935" />
+ <use
+ xlink:href="#glyph0-28"
+ x="235.96736"
+ y="254.498"
+ id="use937" />
+ </g>
<path style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -55.623594 -31.660406 L 55.626406 -31.660406 L 55.626406 31.659906 L -55.623594 31.659906 Z M -55.623594 -31.660406 " transform="matrix(1,0,0,-1,191.315,303.281)"/>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-1" x="154.972" y="281.862"/>
- <use xlink:href="#glyph0-2" x="161.614065" y="281.862"/>
- <use xlink:href="#glyph0-3" x="163.994131" y="281.862"/>
- <use xlink:href="#glyph0-4" x="166.374196" y="281.862"/>
- <use xlink:href="#glyph0-5" x="170.802571" y="281.862"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-35" x="178.548493" y="281.862"/>
- <use xlink:href="#glyph0-11" x="183.889443" y="281.862"/>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g953">
+ <use
+ xlink:href="#glyph0-1"
+ x="154.972"
+ y="281.862"
+ id="use943" />
+ <use
+ xlink:href="#glyph0-2"
+ x="161.614065"
+ y="281.862"
+ id="use945" />
+ <use
+ xlink:href="#glyph0-3"
+ x="163.994131"
+ y="281.862"
+ id="use947" />
+ <use
+ xlink:href="#glyph0-4"
+ x="166.374196"
+ y="281.862"
+ id="use949" />
+ <use
+ xlink:href="#glyph0-5"
+ x="170.802571"
+ y="281.862"
+ id="use951" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g971">
+ <use
+ xlink:href="#glyph0-35"
+ x="178.548493"
+ y="281.862"
+ id="use955" />
+ <use
+ xlink:href="#glyph0-11"
+ x="183.889443"
+ y="281.862"
+ id="use957" />
<use xlink:href="#glyph0-10" x="189.037118" y="281.862"/>
<use xlink:href="#glyph0-2" x="193.825144" y="281.862"/>
- <use xlink:href="#glyph0-3" x="196.205209" y="281.862"/>
- <use xlink:href="#glyph0-40" x="198.585274" y="281.862"/>
- <use xlink:href="#glyph0-5" x="202.916016" y="281.862"/>
- <use xlink:href="#glyph0-16" x="207.344392" y="281.862"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-18" x="214.480602" y="281.862"/>
- <use xlink:href="#glyph0-17" x="218.078097" y="281.862"/>
- <use xlink:href="#glyph0-5" x="223.225773" y="281.862"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use
+ xlink:href="#glyph0-3"
+ x="196.205209"
+ y="281.862"
+ id="use963" />
+ <use
+ xlink:href="#glyph0-40"
+ x="198.585274"
+ y="281.862"
+ id="use965" />
+ <use
+ xlink:href="#glyph0-5"
+ x="202.916016"
+ y="281.862"
+ id="use967" />
+ <use
+ xlink:href="#glyph0-16"
+ x="207.344392"
+ y="281.862"
+ id="use969" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g979">
+ <use
+ xlink:href="#glyph0-18"
+ x="214.480602"
+ y="281.862"
+ id="use973" />
+ <use
+ xlink:href="#glyph0-17"
+ x="218.078097"
+ y="281.862"
+ id="use975" />
+ <use
+ xlink:href="#glyph0-5"
+ x="223.225773"
+ y="281.862"
+ id="use977" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g989">
<use xlink:href="#glyph0-29" x="142.969" y="293.817"/>
<use xlink:href="#glyph0-30" x="149.334105" y="293.817"/>
- <use xlink:href="#glyph0-7" x="154.869326" y="293.817"/>
- <use xlink:href="#glyph0-31" x="161.511391" y="293.817"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-9" x="171.609482" y="293.817"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-37" x="176.478205" y="293.817"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-4" x="184.399468" y="293.817"/>
- <use xlink:href="#glyph0-14" x="188.827844" y="293.817"/>
+ <use
+ xlink:href="#glyph0-7"
+ x="154.869326"
+ y="293.817"
+ id="use985" />
+ <use
+ xlink:href="#glyph0-31"
+ x="161.511391"
+ y="293.817"
+ id="use987" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g993">
+ <use
+ xlink:href="#glyph0-9"
+ x="171.609482"
+ y="293.817"
+ id="use991" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g997">
+ <use
+ xlink:href="#glyph0-37"
+ x="176.478205"
+ y="293.817"
+ id="use995" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1007">
+ <use
+ xlink:href="#glyph0-4"
+ x="184.399468"
+ y="293.817"
+ id="use999" />
+ <use
+ xlink:href="#glyph0-14"
+ x="188.827844"
+ y="293.817"
+ id="use1001" />
<use xlink:href="#glyph0-5" x="192.232064" y="293.817"/>
<use xlink:href="#glyph0-10" x="196.66044" y="293.817"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-18" x="201.438503" y="293.817"/>
- <use xlink:href="#glyph0-3" x="205.035998" y="293.817"/>
- <use xlink:href="#glyph0-11" x="207.416063" y="293.817"/>
- <use xlink:href="#glyph0-27" x="212.563739" y="293.817"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-5" x="220.872547" y="293.817"/>
- <use xlink:href="#glyph0-10" x="225.300923" y="293.817"/>
- <use xlink:href="#glyph0-4" x="230.088948" y="293.817"/>
- <use xlink:href="#glyph0-17" x="234.517324" y="293.817"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-3" x="145.944" y="305.772"/>
- <use xlink:href="#glyph0-11" x="148.324065" y="305.772"/>
- <use xlink:href="#glyph0-19" x="153.471741" y="305.772"/>
- <use xlink:href="#glyph0-26" x="158.619416" y="305.772"/>
- <use xlink:href="#glyph0-18" x="163.767091" y="305.772"/>
- <use xlink:href="#glyph0-41" x="167.364586" y="305.772"/>
- <use xlink:href="#glyph0-16" x="170.132197" y="305.772"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-35" x="177.268407" y="305.772"/>
- <use xlink:href="#glyph0-11" x="182.609357" y="305.772"/>
- <use xlink:href="#glyph0-10" x="187.757032" y="305.772"/>
- <use xlink:href="#glyph0-2" x="192.545058" y="305.772"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-16" x="198.242669" y="305.772"/>
- <use xlink:href="#glyph0-4" x="202.061333" y="305.772"/>
- <use xlink:href="#glyph0-14" x="206.489709" y="305.772"/>
- <use xlink:href="#glyph0-3" x="209.893929" y="305.772"/>
- <use xlink:href="#glyph0-19" x="212.273995" y="305.772"/>
- <use xlink:href="#glyph0-18" x="217.42167" y="305.772"/>
- <use xlink:href="#glyph0-30" x="221.019165" y="305.772"/>
- <use xlink:href="#glyph0-3" x="226.554385" y="305.772"/>
- <use xlink:href="#glyph0-27" x="228.934451" y="305.772"/>
- <use xlink:href="#glyph0-28" x="233.915751" y="305.772"/>
-</g>
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1017">
+ <use
+ xlink:href="#glyph0-18"
+ x="201.438503"
+ y="293.817"
+ id="use1009" />
+ <use
+ xlink:href="#glyph0-3"
+ x="205.035998"
+ y="293.817"
+ id="use1011" />
+ <use
+ xlink:href="#glyph0-11"
+ x="207.416063"
+ y="293.817"
+ id="use1013" />
+ <use
+ xlink:href="#glyph0-27"
+ x="212.563739"
+ y="293.817"
+ id="use1015" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1027">
+ <use
+ xlink:href="#glyph0-5"
+ x="220.872547"
+ y="293.817"
+ id="use1019" />
+ <use
+ xlink:href="#glyph0-10"
+ x="225.300923"
+ y="293.817"
+ id="use1021" />
+ <use
+ xlink:href="#glyph0-4"
+ x="230.088948"
+ y="293.817"
+ id="use1023" />
+ <use
+ xlink:href="#glyph0-17"
+ x="234.517324"
+ y="293.817"
+ id="use1025" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1043">
+ <use
+ xlink:href="#glyph0-3"
+ x="145.944"
+ y="305.772"
+ id="use1029" />
+ <use
+ xlink:href="#glyph0-11"
+ x="148.324065"
+ y="305.772"
+ id="use1031" />
+ <use
+ xlink:href="#glyph0-19"
+ x="153.471741"
+ y="305.772"
+ id="use1033" />
+ <use
+ xlink:href="#glyph0-26"
+ x="158.619416"
+ y="305.772"
+ id="use1035" />
+ <use
+ xlink:href="#glyph0-18"
+ x="163.767091"
+ y="305.772"
+ id="use1037" />
+ <use
+ xlink:href="#glyph0-41"
+ x="167.364586"
+ y="305.772"
+ id="use1039" />
+ <use
+ xlink:href="#glyph0-16"
+ x="170.132197"
+ y="305.772"
+ id="use1041" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1053">
+ <use
+ xlink:href="#glyph0-35"
+ x="177.268407"
+ y="305.772"
+ id="use1045" />
+ <use
+ xlink:href="#glyph0-11"
+ x="182.609357"
+ y="305.772"
+ id="use1047" />
+ <use
+ xlink:href="#glyph0-10"
+ x="187.757032"
+ y="305.772"
+ id="use1049" />
+ <use
+ xlink:href="#glyph0-2"
+ x="192.545058"
+ y="305.772"
+ id="use1051" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1075">
+ <use
+ xlink:href="#glyph0-16"
+ x="198.242669"
+ y="305.772"
+ id="use1055" />
+ <use
+ xlink:href="#glyph0-4"
+ x="202.061333"
+ y="305.772"
+ id="use1057" />
+ <use
+ xlink:href="#glyph0-14"
+ x="206.489709"
+ y="305.772"
+ id="use1059" />
+ <use
+ xlink:href="#glyph0-3"
+ x="209.893929"
+ y="305.772"
+ id="use1061" />
+ <use
+ xlink:href="#glyph0-19"
+ x="212.273995"
+ y="305.772"
+ id="use1063" />
+ <use
+ xlink:href="#glyph0-18"
+ x="217.42167"
+ y="305.772"
+ id="use1065" />
+ <use
+ xlink:href="#glyph0-30"
+ x="221.019165"
+ y="305.772"
+ id="use1067" />
+ <use
+ xlink:href="#glyph0-3"
+ x="226.554385"
+ y="305.772"
+ id="use1069" />
+ <use
+ xlink:href="#glyph0-27"
+ x="228.934451"
+ y="305.772"
+ id="use1071" />
+ <use
+ xlink:href="#glyph0-28"
+ x="233.915751"
+ y="305.772"
+ id="use1073" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-34" x="155.118" y="317.727"/>
<use xlink:href="#glyph0-11" x="162.45147" y="317.727"/>
<use xlink:href="#glyph0-5" x="167.599145" y="317.727"/>
</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-16" x="175.345067" y="317.727"/>
- <use xlink:href="#glyph0-3" x="179.163731" y="317.727"/>
- <use xlink:href="#glyph0-27" x="181.543797" y="317.727"/>
- <use xlink:href="#glyph0-11" x="186.525097" y="317.727"/>
- <use xlink:href="#glyph0-10" x="191.672772" y="317.727"/>
- <use xlink:href="#glyph0-18" x="196.460797" y="317.727"/>
- <use xlink:href="#glyph0-26" x="200.058292" y="317.727"/>
- <use xlink:href="#glyph0-14" x="205.205968" y="317.727"/>
- <use xlink:href="#glyph0-5" x="208.610188" y="317.727"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-20" x="216.35611" y="317.727"/>
- <use xlink:href="#glyph0-8" x="219.40068" y="317.727"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-14" x="224.103027" y="317.727"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-5" x="144.906" y="329.682"/>
- <use xlink:href="#glyph0-10" x="149.334376" y="329.682"/>
- <use xlink:href="#glyph0-4" x="154.122401" y="329.682"/>
- <use xlink:href="#glyph0-17" x="158.550777" y="329.682"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-3" x="167.015998" y="329.682"/>
- <use xlink:href="#glyph0-11" x="169.396063" y="329.682"/>
- <use xlink:href="#glyph0-19" x="174.543739" y="329.682"/>
- <use xlink:href="#glyph0-26" x="179.691414" y="329.682"/>
- <use xlink:href="#glyph0-18" x="184.83909" y="329.682"/>
-</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1103">
+ <use
+ xlink:href="#glyph0-16"
+ x="175.345067"
+ y="317.727"
+ id="use1085" />
+ <use
+ xlink:href="#glyph0-3"
+ x="179.163731"
+ y="317.727"
+ id="use1087" />
+ <use
+ xlink:href="#glyph0-27"
+ x="181.543797"
+ y="317.727"
+ id="use1089" />
+ <use
+ xlink:href="#glyph0-11"
+ x="186.525097"
+ y="317.727"
+ id="use1091" />
+ <use
+ xlink:href="#glyph0-10"
+ x="191.672772"
+ y="317.727"
+ id="use1093" />
+ <use
+ xlink:href="#glyph0-18"
+ x="196.460797"
+ y="317.727"
+ id="use1095" />
+ <use
+ xlink:href="#glyph0-26"
+ x="200.058292"
+ y="317.727"
+ id="use1097" />
+ <use
+ xlink:href="#glyph0-14"
+ x="205.205968"
+ y="317.727"
+ id="use1099" />
+ <use
+ xlink:href="#glyph0-5"
+ x="208.610188"
+ y="317.727"
+ id="use1101" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1109">
+ <use
+ xlink:href="#glyph0-20"
+ x="216.35611"
+ y="317.727"
+ id="use1105" />
+ <use
+ xlink:href="#glyph0-8"
+ x="219.40068"
+ y="317.727"
+ id="use1107" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1113">
+ <use
+ xlink:href="#glyph0-14"
+ x="224.103027"
+ y="317.727"
+ id="use1111" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1123">
+ <use
+ xlink:href="#glyph0-5"
+ x="144.906"
+ y="329.682"
+ id="use1115" />
+ <use
+ xlink:href="#glyph0-10"
+ x="149.334376"
+ y="329.682"
+ id="use1117" />
+ <use
+ xlink:href="#glyph0-4"
+ x="154.122401"
+ y="329.682"
+ id="use1119" />
+ <use
+ xlink:href="#glyph0-17"
+ x="158.550777"
+ y="329.682"
+ id="use1121" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1135">
+ <use
+ xlink:href="#glyph0-3"
+ x="167.015998"
+ y="329.682"
+ id="use1125" />
+ <use
+ xlink:href="#glyph0-11"
+ x="169.396063"
+ y="329.682"
+ id="use1127" />
+ <use
+ xlink:href="#glyph0-19"
+ x="174.543739"
+ y="329.682"
+ id="use1129" />
+ <use
+ xlink:href="#glyph0-26"
+ x="179.691414"
+ y="329.682"
+ id="use1131" />
+ <use
+ xlink:href="#glyph0-18"
+ x="184.83909"
+ y="329.682"
+ id="use1133" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-3" x="191.75413" y="329.682"/>
<use xlink:href="#glyph0-16" x="194.134195" y="329.682"/>
</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-12" x="201.280368" y="329.682"/>
- <use xlink:href="#glyph0-14" x="206.428044" y="329.682"/>
- <use xlink:href="#glyph0-8" x="209.832264" y="329.682"/>
- <use xlink:href="#glyph0-19" x="214.813564" y="329.682"/>
- <use xlink:href="#glyph0-19" x="219.96124" y="329.682"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-5" x="225.377905" y="329.682"/>
- <use xlink:href="#glyph0-12" x="229.806281" y="329.682"/>
- <use xlink:href="#glyph0-28" x="234.953956" y="329.682"/>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1153">
+ <use
+ xlink:href="#glyph0-12"
+ x="201.280368"
+ y="329.682"
+ id="use1143" />
+ <use
+ xlink:href="#glyph0-14"
+ x="206.428044"
+ y="329.682"
+ id="use1145" />
+ <use
+ xlink:href="#glyph0-8"
+ x="209.832264"
+ y="329.682"
+ id="use1147" />
+ <use
+ xlink:href="#glyph0-19"
+ x="214.813564"
+ y="329.682"
+ id="use1149" />
+ <use
+ xlink:href="#glyph0-19"
+ x="219.96124"
+ y="329.682"
+ id="use1151" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1161">
+ <use
+ xlink:href="#glyph0-5"
+ x="225.377905"
+ y="329.682"
+ id="use1155" />
+ <use
+ xlink:href="#glyph0-12"
+ x="229.806281"
+ y="329.682"
+ id="use1157" />
+ <use
+ xlink:href="#glyph0-28"
+ x="234.953956"
+ y="329.682"
+ id="use1159" />
</g>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 230.5 346.804688 L 152.128906 346.804688 C 149.925781 346.804688 148.144531 348.589844 148.144531 350.792969 L 148.144531 404.203125 C 148.144531 406.402344 149.925781 408.1875 152.128906 408.1875 L 230.5 408.1875 C 232.703125 408.1875 234.488281 406.402344 234.488281 404.203125 L 234.488281 350.792969 C 234.488281 348.589844 232.703125 346.804688 230.5 346.804688 Z M 230.5 346.804688 "/>
<g clip-path="url(#clip1)" clip-rule="nonzero">
<path style="fill:none;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 39.185 30.692312 L -39.186094 30.692312 C -41.389219 30.692312 -43.170469 28.907156 -43.170469 26.704031 L -43.170469 -26.706125 C -43.170469 -28.905344 -41.389219 -30.6905 -39.186094 -30.6905 L 39.185 -30.6905 C 41.388125 -30.6905 43.173281 -28.905344 43.173281 -26.706125 L 43.173281 26.704031 C 43.173281 28.907156 41.388125 30.692312 39.185 30.692312 Z M 39.185 30.692312 " transform="matrix(1,0,0,-1,191.315,377.497)"/>
</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-1" x="154.951" y="357.046"/>
- <use xlink:href="#glyph0-2" x="161.593065" y="357.046"/>
- <use xlink:href="#glyph0-3" x="163.973131" y="357.046"/>
- <use xlink:href="#glyph0-4" x="166.353196" y="357.046"/>
- <use xlink:href="#glyph0-5" x="170.781571" y="357.046"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-5" x="178.527493" y="357.046"/>
- <use xlink:href="#glyph0-42" x="182.955869" y="357.046"/>
- <use xlink:href="#glyph0-18" x="187.549623" y="357.046"/>
- <use xlink:href="#glyph0-14" x="191.147118" y="357.046"/>
- <use xlink:href="#glyph0-10" x="194.551339" y="357.046"/>
- <use xlink:href="#glyph0-4" x="199.339364" y="357.046"/>
- <use xlink:href="#glyph0-18" x="203.76774" y="357.046"/>
- <use xlink:href="#glyph0-16" x="207.365235" y="357.046"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-18" x="214.501445" y="357.046"/>
- <use xlink:href="#glyph0-17" x="218.09894" y="357.046"/>
- <use xlink:href="#glyph0-5" x="223.246616" y="357.046"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-11" x="154.709" y="369.001"/>
- <use xlink:href="#glyph0-5" x="159.856675" y="369.001"/>
- <use xlink:href="#glyph0-18" x="164.285051" y="369.001"/>
-</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1179">
+ <use
+ xlink:href="#glyph0-1"
+ x="154.951"
+ y="357.046"
+ id="use1169" />
+ <use
+ xlink:href="#glyph0-2"
+ x="161.593065"
+ y="357.046"
+ id="use1171" />
+ <use
+ xlink:href="#glyph0-3"
+ x="163.973131"
+ y="357.046"
+ id="use1173" />
+ <use
+ xlink:href="#glyph0-4"
+ x="166.353196"
+ y="357.046"
+ id="use1175" />
+ <use
+ xlink:href="#glyph0-5"
+ x="170.781571"
+ y="357.046"
+ id="use1177" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1197">
+ <use
+ xlink:href="#glyph0-5"
+ x="178.527493"
+ y="357.046"
+ id="use1181" />
+ <use
+ xlink:href="#glyph0-42"
+ x="182.955869"
+ y="357.046"
+ id="use1183" />
+ <use
+ xlink:href="#glyph0-18"
+ x="187.549623"
+ y="357.046"
+ id="use1185" />
+ <use
+ xlink:href="#glyph0-14"
+ x="191.147118"
+ y="357.046"
+ id="use1187" />
+ <use
+ xlink:href="#glyph0-10"
+ x="194.551339"
+ y="357.046"
+ id="use1189" />
+ <use
+ xlink:href="#glyph0-4"
+ x="199.339364"
+ y="357.046"
+ id="use1191" />
+ <use
+ xlink:href="#glyph0-18"
+ x="203.76774"
+ y="357.046"
+ id="use1193" />
+ <use
+ xlink:href="#glyph0-16"
+ x="207.365235"
+ y="357.046"
+ id="use1195" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1205">
+ <use
+ xlink:href="#glyph0-18"
+ x="214.501445"
+ y="357.046"
+ id="use1199" />
+ <use
+ xlink:href="#glyph0-17"
+ x="218.09894"
+ y="357.046"
+ id="use1201" />
+ <use
+ xlink:href="#glyph0-5"
+ x="223.246616"
+ y="357.046"
+ id="use1203" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1213">
+ <use
+ xlink:href="#glyph0-11"
+ x="154.709"
+ y="369.001"
+ id="use1207" />
+ <use
+ xlink:href="#glyph0-5"
+ x="159.856675"
+ y="369.001"
+ id="use1209" />
+ <use
+ xlink:href="#glyph0-18"
+ x="164.285051"
+ y="369.001"
+ id="use1211" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-15" x="167.603593" y="369.001"/>
</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-8" x="174.132085" y="369.001"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-14" x="178.844395" y="369.001"/>
- <use xlink:href="#glyph0-43" x="182.248615" y="369.001"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-16" x="190.436876" y="369.001"/>
- <use xlink:href="#glyph0-5" x="194.255541" y="369.001"/>
- <use xlink:href="#glyph0-14" x="198.683916" y="369.001"/>
- <use xlink:href="#glyph0-3" x="202.088137" y="369.001"/>
- <use xlink:href="#glyph0-10" x="204.468202" y="369.001"/>
- <use xlink:href="#glyph0-2" x="209.256228" y="369.001"/>
- <use xlink:href="#glyph0-3" x="211.636293" y="369.001"/>
- <use xlink:href="#glyph0-40" x="214.016358" y="369.001"/>
- <use xlink:href="#glyph0-5" x="218.3471" y="369.001"/>
- <use xlink:href="#glyph0-12" x="222.775476" y="369.001"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-18" x="159.075" y="380.956"/>
- <use xlink:href="#glyph0-14" x="162.672495" y="380.956"/>
- <use xlink:href="#glyph0-10" x="166.076715" y="380.956"/>
- <use xlink:href="#glyph0-11" x="170.864741" y="380.956"/>
- <use xlink:href="#glyph0-16" x="176.012416" y="380.956"/>
- <use xlink:href="#glyph0-10" x="179.831081" y="380.956"/>
- <use xlink:href="#glyph0-4" x="184.619106" y="380.956"/>
- <use xlink:href="#glyph0-18" x="189.047482" y="380.956"/>
- <use xlink:href="#glyph0-3" x="192.644977" y="380.956"/>
- <use xlink:href="#glyph0-8" x="195.025042" y="380.956"/>
- <use xlink:href="#glyph0-11" x="200.006342" y="380.956"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-10" x="208.471563" y="380.956"/>
- <use xlink:href="#glyph0-11" x="213.259589" y="380.956"/>
- <use xlink:href="#glyph0-12" x="218.407264" y="380.956"/>
-</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1221">
+ <use
+ xlink:href="#glyph0-8"
+ x="174.132085"
+ y="369.001"
+ id="use1219" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1227">
+ <use
+ xlink:href="#glyph0-14"
+ x="178.844395"
+ y="369.001"
+ id="use1223" />
+ <use
+ xlink:href="#glyph0-43"
+ x="182.248615"
+ y="369.001"
+ id="use1225" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1249">
+ <use
+ xlink:href="#glyph0-16"
+ x="190.436876"
+ y="369.001"
+ id="use1229" />
+ <use
+ xlink:href="#glyph0-5"
+ x="194.255541"
+ y="369.001"
+ id="use1231" />
+ <use
+ xlink:href="#glyph0-14"
+ x="198.683916"
+ y="369.001"
+ id="use1233" />
+ <use
+ xlink:href="#glyph0-3"
+ x="202.088137"
+ y="369.001"
+ id="use1235" />
+ <use
+ xlink:href="#glyph0-10"
+ x="204.468202"
+ y="369.001"
+ id="use1237" />
+ <use
+ xlink:href="#glyph0-2"
+ x="209.256228"
+ y="369.001"
+ id="use1239" />
+ <use
+ xlink:href="#glyph0-3"
+ x="211.636293"
+ y="369.001"
+ id="use1241" />
+ <use
+ xlink:href="#glyph0-40"
+ x="214.016358"
+ y="369.001"
+ id="use1243" />
+ <use
+ xlink:href="#glyph0-5"
+ x="218.3471"
+ y="369.001"
+ id="use1245" />
+ <use
+ xlink:href="#glyph0-12"
+ x="222.775476"
+ y="369.001"
+ id="use1247" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1273">
+ <use
+ xlink:href="#glyph0-18"
+ x="159.075"
+ y="380.956"
+ id="use1251" />
+ <use
+ xlink:href="#glyph0-14"
+ x="162.672495"
+ y="380.956"
+ id="use1253" />
+ <use
+ xlink:href="#glyph0-10"
+ x="166.076715"
+ y="380.956"
+ id="use1255" />
+ <use
+ xlink:href="#glyph0-11"
+ x="170.864741"
+ y="380.956"
+ id="use1257" />
+ <use
+ xlink:href="#glyph0-16"
+ x="176.012416"
+ y="380.956"
+ id="use1259" />
+ <use
+ xlink:href="#glyph0-10"
+ x="179.831081"
+ y="380.956"
+ id="use1261" />
+ <use
+ xlink:href="#glyph0-4"
+ x="184.619106"
+ y="380.956"
+ id="use1263" />
+ <use
+ xlink:href="#glyph0-18"
+ x="189.047482"
+ y="380.956"
+ id="use1265" />
+ <use
+ xlink:href="#glyph0-3"
+ x="192.644977"
+ y="380.956"
+ id="use1267" />
+ <use
+ xlink:href="#glyph0-8"
+ x="195.025042"
+ y="380.956"
+ id="use1269" />
+ <use
+ xlink:href="#glyph0-11"
+ x="200.006342"
+ y="380.956"
+ id="use1271" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1281">
+ <use
+ xlink:href="#glyph0-10"
+ x="208.471563"
+ y="380.956"
+ id="use1275" />
+ <use
+ xlink:href="#glyph0-11"
+ x="213.259589"
+ y="380.956"
+ id="use1277" />
+ <use
+ xlink:href="#glyph0-12"
+ x="218.407264"
+ y="380.956"
+ id="use1279" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-9" x="164.845" y="392.911"/>
</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-14" x="169.713723" y="392.911"/>
- <use xlink:href="#glyph0-8" x="173.117943" y="392.911"/>
- <use xlink:href="#glyph0-10" x="178.099243" y="392.911"/>
- <use xlink:href="#glyph0-12" x="182.887269" y="392.911"/>
- <use xlink:href="#glyph0-4" x="188.034944" y="392.911"/>
- <use xlink:href="#glyph0-10" x="192.46332" y="392.911"/>
- <use xlink:href="#glyph0-16" x="197.251345" y="392.911"/>
- <use xlink:href="#glyph0-18" x="201.07001" y="392.911"/>
- <use xlink:href="#glyph0-16" x="204.667505" y="392.911"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-3" x="211.803715" y="392.911"/>
- <use xlink:href="#glyph0-18" x="214.18378" y="392.911"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-18" x="159.532" y="404.866"/>
- <use xlink:href="#glyph0-8" x="163.129495" y="404.866"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-18" x="171.428341" y="404.866"/>
- <use xlink:href="#glyph0-17" x="175.025836" y="404.866"/>
- <use xlink:href="#glyph0-5" x="180.173511" y="404.866"/>
-</g>
-<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
- <use xlink:href="#glyph0-11" x="187.919432" y="404.866"/>
- <use xlink:href="#glyph0-5" x="193.067108" y="404.866"/>
- <use xlink:href="#glyph0-18" x="197.495484" y="404.866"/>
-</g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1305">
+ <use
+ xlink:href="#glyph0-14"
+ x="169.713723"
+ y="392.911"
+ id="use1287" />
+ <use
+ xlink:href="#glyph0-8"
+ x="173.117943"
+ y="392.911"
+ id="use1289" />
+ <use
+ xlink:href="#glyph0-10"
+ x="178.099243"
+ y="392.911"
+ id="use1291" />
+ <use
+ xlink:href="#glyph0-12"
+ x="182.887269"
+ y="392.911"
+ id="use1293" />
+ <use
+ xlink:href="#glyph0-4"
+ x="188.034944"
+ y="392.911"
+ id="use1295" />
+ <use
+ xlink:href="#glyph0-10"
+ x="192.46332"
+ y="392.911"
+ id="use1297" />
+ <use
+ xlink:href="#glyph0-16"
+ x="197.251345"
+ y="392.911"
+ id="use1299" />
+ <use
+ xlink:href="#glyph0-18"
+ x="201.07001"
+ y="392.911"
+ id="use1301" />
+ <use
+ xlink:href="#glyph0-16"
+ x="204.667505"
+ y="392.911"
+ id="use1303" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1311">
+ <use
+ xlink:href="#glyph0-3"
+ x="211.803715"
+ y="392.911"
+ id="use1307" />
+ <use
+ xlink:href="#glyph0-18"
+ x="214.18378"
+ y="392.911"
+ id="use1309" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1317">
+ <use
+ xlink:href="#glyph0-18"
+ x="159.532"
+ y="404.866"
+ id="use1313" />
+ <use
+ xlink:href="#glyph0-8"
+ x="163.129495"
+ y="404.866"
+ id="use1315" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1325">
+ <use
+ xlink:href="#glyph0-18"
+ x="171.428341"
+ y="404.866"
+ id="use1319" />
+ <use
+ xlink:href="#glyph0-17"
+ x="175.025836"
+ y="404.866"
+ id="use1321" />
+ <use
+ xlink:href="#glyph0-5"
+ x="180.173511"
+ y="404.866"
+ id="use1323" />
+ </g>
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1333">
+ <use
+ xlink:href="#glyph0-11"
+ x="187.919432"
+ y="404.866"
+ id="use1327" />
+ <use
+ xlink:href="#glyph0-5"
+ x="193.067108"
+ y="404.866"
+ id="use1329" />
+ <use
+ xlink:href="#glyph0-18"
+ x="197.495484"
+ y="404.866"
+ id="use1331" />
+ </g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-15" x="200.823988" y="404.866"/>
</g>
@@ -873,23 +2552,173 @@
<use xlink:href="#glyph0-43" x="215.459048" y="404.866"/>
<use xlink:href="#glyph0-28" x="220.329763" y="404.866"/>
</g>
-<path style="fill:none;stroke-width:0.99628;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -56.022031 92.906125 L -125.330625 92.906125 L -125.330625 72.913937 " transform="matrix(1,0,0,-1,191.315,205.953)"/>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 65.984375 138.238281 C 66.273438 136.699219 67.140625 134.195312 68.152344 132.460938 L 63.816406 132.460938 C 64.828125 134.195312 65.695312 136.699219 65.984375 138.238281 "/>
-<path style="fill:none;stroke-width:0.99628;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0.00140625 162.429562 L 0.00140625 156.562375 " transform="matrix(1,0,0,-1,191.315,205.953)"/>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 191.316406 54.59375 C 191.605469 53.050781 192.46875 50.546875 193.480469 48.8125 L 189.148438 48.8125 C 190.160156 50.546875 191.027344 53.050781 191.316406 54.59375 "/>
-<path style="fill:none;stroke-width:0.99628;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0.00140625 111.156125 L 0.00140625 105.285031 " transform="matrix(1,0,0,-1,191.315,205.953)"/>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 191.316406 105.867188 C 191.605469 104.324219 192.46875 101.820312 193.480469 100.089844 L 189.148438 100.089844 C 190.160156 101.820312 191.027344 104.324219 191.316406 105.867188 "/>
-<path style="fill:none;stroke-width:0.99628;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0.00140625 85.730344 L 0.00140625 72.913937 " transform="matrix(1,0,0,-1,191.315,205.953)"/>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 191.316406 138.238281 C 191.605469 136.699219 192.46875 134.195312 193.480469 132.460938 L 189.148438 132.460938 C 190.160156 134.195312 191.027344 136.699219 191.316406 138.238281 "/>
-<path style="fill:none;stroke-width:0.99628;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0.00140625 -2.925906 L 0.00140625 -8.797 " transform="matrix(1,0,0,-1,191.315,205.953)"/>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 191.316406 219.949219 C 191.605469 218.410156 192.46875 215.90625 193.480469 214.171875 L 189.148438 214.171875 C 190.160156 215.90625 191.027344 218.410156 191.316406 219.949219 "/>
-<path style="fill:none;stroke-width:0.99628;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0.00140625 -54.20325 L 0.00140625 -60.070438 " transform="matrix(1,0,0,-1,191.315,205.953)"/>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 191.316406 271.226562 C 191.605469 269.683594 192.46875 267.179688 193.480469 265.445312 L 189.148438 265.445312 C 190.160156 267.179688 191.027344 269.683594 191.316406 271.226562 "/>
-<path style="fill:none;stroke-width:0.99628;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0.00140625 -129.386844 L 0.00140625 -135.257938 " transform="matrix(1,0,0,-1,191.315,205.953)"/>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 191.316406 346.410156 C 191.605469 344.867188 192.46875 342.363281 193.480469 340.632812 L 189.148438 340.632812 C 190.160156 342.363281 191.027344 344.867188 191.316406 346.410156 "/>
-<path style="fill:none;stroke-width:0.99628;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -125.330625 41.402219 L -125.330625 32.6405 L 0.00140625 32.6405 L 0.00140625 23.386594 M 125.329531 34.453 L 125.329531 32.6405 L 0.00140625 32.6405 L 0.00140625 23.386594 M 56.024844 92.906125 L 125.329531 92.906125 L 125.329531 79.85925 " transform="matrix(1,0,0,-1,191.315,205.953)"/>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 316.644531 131.292969 C 316.933594 129.753906 317.800781 127.25 318.8125 125.515625 L 314.480469 125.515625 C 315.492188 127.25 316.355469 129.753906 316.644531 131.292969 "/>
-<path style="fill:none;stroke-width:0.99628;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0.00140625 41.402219 L 0.00140625 28.585812 " transform="matrix(1,0,0,-1,191.315,205.953)"/>
-<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 191.316406 182.566406 C 191.605469 181.027344 192.46875 178.523438 193.480469 176.789062 L 189.148438 176.789062 C 190.160156 178.523438 191.027344 181.027344 191.316406 182.566406 "/>
+<path style="fill:none;stroke-width:1.59404;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -56.022031 92.906125 L -125.330625 92.906125 L -125.330625 72.538937 " transform="matrix(1,0,0,-1,191.315,205.953)"/>
+<path style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.34497;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.054429 0.000445 L 2.171616 1.477007 L 3.48021 0.000445 L 2.171616 -1.480024 Z M 6.054429 0.000445 " transform="matrix(0,1,1,0,65.98393,130.26979)"/>
+<path style="fill:none;stroke-width:1.59404;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0.00140625 162.429562 L 0.00140625 156.187375 " transform="matrix(1,0,0,-1,191.315,205.953)"/>
+ <path
+ style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.34497;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 6.053411 0.00140625 L 2.170599 1.477969 L 3.479193 0.00140625 L 2.170599 -1.479062 Z M 6.053411 0.00140625 "
+ transform="matrix(0,1,1,0,191.315,46.62237)"
+ id="path1357" />
+ <path
+ style="fill:none;stroke-width:1.59404;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 0.00140625 111.156125 L 0.00140625 104.913937 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1359" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.34497;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 6.056245 0.00140625 L 2.173433 1.477969 L 3.482026 0.00140625 L 2.173433 -1.479062 Z M 6.056245 0.00140625 "
+ transform="matrix(0,1,1,0,191.315,97.89688)"
+ id="path1361" />
+ <path
+ style="fill:none;stroke-width:1.59404;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 0.00140625 85.730344 L 0.00140625 72.538937 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1363" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.34497;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 6.054429 0.00140625 L 2.171616 1.477969 L 3.48021 0.00140625 L 2.171616 -1.479062 Z M 6.054429 0.00140625 "
+ transform="matrix(0,1,1,0,191.315,130.26979)"
+ id="path1365" />
+ <path
+ style="fill:none;stroke-width:1.59404;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 0.00140625 -2.925906 L 0.00140625 -9.172 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1367" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.34497;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 6.055156 0.00140625 L 2.172344 1.477969 L 3.480938 0.00140625 L 2.172344 -1.479062 Z M 6.055156 0.00140625 "
+ transform="matrix(0,1,1,0,191.315,211.98)"
+ id="path1369" />
+ <path
+ style="fill:none;stroke-width:1.59404;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 0.00140625 -54.20325 L 0.00140625 -60.445438 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1371" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.34497;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 6.054094 0.00140625 L 2.171281 1.477969 L 3.479875 0.00140625 L 2.171281 -1.479062 Z M 6.054094 0.00140625 "
+ transform="matrix(0,1,1,0,191.315,263.2545)"
+ id="path1373" />
+ <path
+ style="fill:none;stroke-width:1.59404;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 0.00140625 -129.386844 L 0.00140625 -135.629031 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1375" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.34497;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 6.056464 0.00140625 L 2.173651 1.477969 L 3.478339 0.00140625 L 2.173651 -1.479062 Z M 6.056464 0.00140625 "
+ transform="matrix(0,1,1,0,191.315,338.43963)"
+ id="path1377" />
+ <path
+ style="fill:none;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M -56.022031 92.906125 L -125.330625 92.906125 L -125.330625 72.929562 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1379" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 7.402085 0.000445 L 0.644273 2.539507 L 2.85521 0.000445 L 0.644273 -2.542524 Z M 7.402085 0.000445 "
+ transform="matrix(0,1,1,0,65.98393,130.26979)"
+ id="path1381" />
+ <path
+ style="fill:none;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 0.00140625 162.429562 L 0.00140625 156.578 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1383" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 7.401068 0.00140625 L 0.643255 2.540469 L 2.854193 0.00140625 L 0.643255 -2.541562 Z M 7.401068 0.00140625 "
+ transform="matrix(0,1,1,0,191.315,46.62237)"
+ id="path1385" />
+ <path
+ style="fill:none;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 0.00140625 111.156125 L 0.00140625 105.300656 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1387" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 7.403901 0.00140625 L 0.642183 2.540469 L 2.85312 0.00140625 L 0.642183 -2.541562 Z M 7.403901 0.00140625 "
+ transform="matrix(0,1,1,0,191.315,97.89688)"
+ id="path1389" />
+ <path
+ style="fill:none;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 0.00140625 85.730344 L 0.00140625 72.929562 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1391" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 7.402085 0.00140625 L 0.644273 2.540469 L 2.85521 0.00140625 L 0.644273 -2.541562 Z M 7.402085 0.00140625 "
+ transform="matrix(0,1,1,0,191.315,130.26979)"
+ id="path1393" />
+ <path
+ style="fill:none;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 0.00140625 -2.925906 L 0.00140625 -8.781375 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1395" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 7.402813 0.00140625 L 0.645 2.540469 L 2.852031 0.00140625 L 0.645 -2.541562 Z M 7.402813 0.00140625 "
+ transform="matrix(0,1,1,0,191.315,211.98)"
+ id="path1397" />
+ <path
+ style="fill:none;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 0.00140625 -54.20325 L 0.00140625 -60.054813 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1399" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 7.40175 0.00140625 L 0.643938 2.540469 L 2.854875 0.00140625 L 0.643938 -2.541562 Z M 7.40175 0.00140625 "
+ transform="matrix(0,1,1,0,191.315,263.2545)"
+ id="path1401" />
+ <path
+ style="fill:none;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 0.00140625 -129.386844 L 0.00140625 -135.242313 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1403" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 7.40412 0.00140625 L 0.642401 2.540469 L 2.853339 0.00140625 L 0.642401 -2.541562 Z M 7.40412 0.00140625 "
+ transform="matrix(0,1,1,0,191.315,338.43963)"
+ id="path1405" />
+ <path
+ style="fill:none;stroke-width:1.59404;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M -125.330625 41.402219 L -125.330625 32.6405 L 0.00140625 32.6405 L 0.00140625 23.386594 M 125.329531 34.453 L 125.329531 32.6405 L 0.00140625 32.6405 L 0.00140625 23.386594 M 56.024844 92.906125 L 125.329531 92.906125 L 125.329531 79.48425 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1407" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.34497;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 6.055376 -0.00153875 L 2.172564 1.47893 L 3.481158 -0.00153875 L 2.172564 -1.478101 Z M 6.055376 -0.00153875 "
+ transform="matrix(0,1,1,0,316.64607,123.32353)"
+ id="path1409" />
+ <path
+ style="fill:none;stroke-width:1.59404;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 0.00140625 41.402219 L 0.00140625 28.210812 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1411" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.34497;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 6.054314 0.00140625 L 2.171501 1.477969 L 3.480095 0.00140625 L 2.171501 -1.479062 Z M 6.054314 0.00140625 "
+ transform="matrix(0,1,1,0,191.315,174.59803)"
+ id="path1413" />
+ <path
+ style="fill:none;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M -125.330625 41.402219 L -125.330625 32.6405 L 0.00140625 32.6405 L 0.00140625 23.386594 M 125.329531 34.453 L 125.329531 32.6405 L 0.00140625 32.6405 L 0.00140625 23.386594 M 56.024844 92.906125 L 125.329531 92.906125 L 125.329531 79.874875 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1415" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 7.403033 -0.00153875 L 0.64522 2.54143 L 2.852251 -0.00153875 L 0.64522 -2.540601 Z M 7.403033 -0.00153875 "
+ transform="matrix(0,1,1,0,316.64607,123.32353)"
+ id="path1417" />
+ <path
+ style="fill:none;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 0.00140625 41.402219 L 0.00140625 28.601437 "
+ transform="matrix(1,0,0,-1,191.315,205.953)"
+ id="path1419" />
+ <path
+ style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 7.40197 0.00140625 L 0.644158 2.540469 L 2.855095 0.00140625 L 0.644158 -2.541562 Z M 7.40197 0.00140625 "
+ transform="matrix(0,1,1,0,191.315,174.59803)"
+ id="path1421" />
</g>
</svg>
diff --git a/bip-0174/multisig-workflow.tex b/bip-0174/multisig-workflow.tex
index 2b8744d..d2250cf 100644
--- a/bip-0174/multisig-workflow.tex
+++ b/bip-0174/multisig-workflow.tex
@@ -7,7 +7,7 @@
\usepackage{lmodern}
\renewcommand*\familydefault{\sfdefault}
\usepackage{tikz}
-\usetikzlibrary{shapes,arrows}
+\usetikzlibrary{shapes,arrows.meta}
\tikzset{>=latex}
%\pgfdeclarelayer{bg} % declare background layer
%\pgfsetlayers{bg,main} % set order of layers
@@ -83,7 +83,15 @@
};% end matrix
% connecting nodes with paths
% \begin{pgfonlayer}{bg}
- \draw[line width = 1pt, ->]
+ \draw [ultra thick, draw=black, -{Stealth[length=8pt]}]
+ (R1) edge (R2)
+ (R2) edge (R3)
+ (R3) -| (R4C1)
+ (R3) edge (R4C2)
+ (R5) edge (R6)
+ (R6) edge (R7)
+ (R7) edge (stop);
+ \draw [thin, white, -{Stealth[color=black, fill=white, length=8pt]}]
(R1) edge (R2)
(R2) edge (R3)
(R3) -| (R4C1)
@@ -92,7 +100,12 @@
(R6) edge (R7)
(R7) edge (stop);
% circumvent missing arrow
- \draw[line width = 1pt, ->]
+ \draw [ultra thick, draw=black, -{Stealth[length=8pt]}]
+ (R4C1) |-+(0,-2.2em)-| (R5)
+ (R4C2) edge (R5)
+ (R4C3) |-+(0,-2.2em)-| (R5)
+ (R3) -| (R4C3);
+ \draw [thin, white, -{Stealth[color=black, fill=white, length=8pt]}]
(R4C1) |-+(0,-2.2em)-| (R5)
(R4C2) edge (R5)
(R4C3) |-+(0,-2.2em)-| (R5)
diff --git a/bip-0197.mediawiki b/bip-0197.mediawiki
index 427ff22..2cac042 100644
--- a/bip-0197.mediawiki
+++ b/bip-0197.mediawiki
@@ -79,7 +79,7 @@ The Seizable Collateral script takes the following form:
==Compatibility==
-BIP 197 is compatible with [ERC 1850](https://github.com/ethereum/EIPs/pull/1850) for [atomic loans](https://arxiv.org/pdf/1901.05117.pdf) with Ethereum. Can be extended in the future to be compatible with other HTLC and smart contract compatible chains.
+BIP 197 is compatible with [https://github.com/ethereum/EIPs/pull/1850 ERC 1850] for [https://arxiv.org/pdf/1901.05117.pdf atomic loans] with Ethereum. Can be extended in the future to be compatible with other HTLC and smart contract compatible chains.
==Motivation==
diff --git a/bip-0310.mediawiki b/bip-0310.mediawiki
index 257e92a..34522be 100644
--- a/bip-0310.mediawiki
+++ b/bip-0310.mediawiki
@@ -190,7 +190,7 @@ send the mask, in this case a default full mask is used.
* '''"version-rolling.mask"''' (REQUIRED, ''TMask'')
::- Bits set to 1 are allowed to be changed by the miner. If a miner changes bits with mask value 0, the server will reject the submit.
-::- The server SHOULD return the largest mask possible (as many bits set to 1 as possible). This can be useful in a mining proxy setup when a proxy needs to negotiate the best mask for its future clients. There is a [Draft BIP](https://github.com/bitcoin/bips/pull/661/files) describing available nVersion bits. The server SHOULD pick a mask that preferably covers all bits specified in the BIP.
+::- The server SHOULD return the largest mask possible (as many bits set to 1 as possible). This can be useful in a mining proxy setup when a proxy needs to negotiate the best mask for its future clients. There is a [https://github.com/bitcoin/bips/pull/661/files Draft BIP] describing available nVersion bits. The server SHOULD pick a mask that preferably covers all bits specified in the BIP.
* '''"version-rolling.min-bit-count"''' (REQUIRED, ''TMask'')
::- The miner also provides a minimum number of bits that it needs for efficient version rolling in hardware. Note that this parameter provides important diagnostic information to the pool server. If the requested bit count exceeds the limit of the pool server, the miner always has the chance to operate in a degraded mode without using full hashing power. The pool server SHOULD NOT terminate miner connection if this rare mismatch case occurs.
@@ -276,7 +276,7 @@ Miner provides additional text-based information.
Currently, there is a similar protocol feature '''mining.capabilities''' that
was intended for various protocol extensions. However, '''mining.configure'''
is incompatible with this feature as it requires a server response confirming
-all accepted/negotatied extensions. The reason why we made it incompatible is
+all accepted/negotiated extensions. The reason why we made it incompatible is
that '''mining.capabilities''' request has no associated response.
diff --git a/bip-0322.mediawiki b/bip-0322.mediawiki
index 55a751f..911d3c8 100644
--- a/bip-0322.mediawiki
+++ b/bip-0322.mediawiki
@@ -80,8 +80,6 @@ A full signature consists of the base64-encoding of the <code>to_sign</code> tra
A signer may construct a proof of funds, demonstrating control of a set of UTXOs, by constructing a full signature as above, with the following modifications.
-* <code>message_challenge</code> is unused and shall be set to <code>OP_TRUE</code>
-* Similarly, <code>message_signature</code> is then empty.
* All outputs that the signer wishes to demonstrate control of are included as additional inputs of <code>to_sign</code>, and their witness and scriptSig data should be set as though these outputs were actually being spent.
Unlike an ordinary signature, validators of a proof of funds need access to the current UTXO set, to learn that the claimed inputs exist on the blockchain, and to learn their scriptPubKeys.
diff --git a/bip-0324/test_sage_decoding.py b/bip-0324/test_sage_decoding.py
index c26c334..1ec5fdf 100644
--- a/bip-0324/test_sage_decoding.py
+++ b/bip-0324/test_sage_decoding.py
@@ -5,8 +5,8 @@ Instructions:
* Clone the SwiftEC repository, and enter the directory:
git clone https://github.com/Jchavezsaab/SwiftEC
- git checkout 5320a25035d91addde29d14164cce684b56a12ed
cd SwiftEC
+ git checkout 5320a25035d91addde29d14164cce684b56a12ed
* Generate parameters for the secp256k1 curve:
diff --git a/bip-0324/xswiftec_test_vectors.csv b/bip-0324/xswiftec_test_vectors.csv
deleted file mode 100644
index 985235f..0000000
--- a/bip-0324/xswiftec_test_vectors.csv
+++ /dev/null
@@ -1,33 +0,0 @@
-u,x,case0_t,case1_t,case2_t,case3_t,case4_t,case5_t,case6_t,case7_t
-08da7c45cb204377e7e42249cda5713fa865116ddbb4cb5a1949b2e5b438a6ab,e087b707dabf2796b03b2fb4f976c3f2f5abb36110d00ef656432117f2c93f0a,,,,,,,,
-0a6361b3a802f55cd5ae06101c88a1e216320fe11cc0cfe1d791eed08a1200fd,a0223bc98997647daf4d520129bdb66e4937a00d1533af1fa29645fb96fb5bb5,60a3ed14bd9df0bfb89ada9372a7b5790b123a66bf130f5788237e8cd5225de4,9c4ee4629f10220fda49532d0c859a539dec5148eefc78bf48d93d2828027a9c,fc5e72f042fd1792cbf88728a374a2cc1e03e1f9ec8813fa3692e497cfa7d5e6,cb39fac005f26dc0a383ea64cb9b3b0b26767f20232cae4486f32904df4f04e3,9f5c12eb42620f404765256c8d584a86f4edc59940ecf0a877dc81722add9e4b,63b11b9d60efddf025b6acd2f37a65ac6213aeb711038740b726c2d6d7fd8193,03a18d0fbd02e86d340778d75c8b5d33e1fc1e061377ec05c96d1b6730582649,34c6053ffa0d923f5c7c159b3464c4f4d98980dfdcd351bb790cd6fa20b0f74c
-102b51b9765a56a3e899f7cf0ee38e5251f9c503b357b330a49183eb7b155604,102b51b9765a56a3e899f7cf0ee38e5251f9c503b357b330a49183eb7b155604,bdb5bd58ca96eae36147a6c55bc2bef2cee55a757ee193cb619edc8d3590f90a,bda953c1da02059350e740b83f59149628e0be50c24ac8dc6908a2225931b4a0,,,424a42a73569151c9eb8593aa43d410d311aa58a811e6c349e612371ca6f0325,4256ac3e25fdfa6caf18bf47c0a6eb69d71f41af3db5372396f75ddca6ce478f,,
-2921a11f25dadaa24aa79a548e4e81508c2e5e56af2d833d65e2bcce448ce2f5,3a70c472406b83d9f1c4398b8ecef786499bc44a3b30c34ac30f2d8a418bffa3,b9c76c21d3fabb948fa0326bf9e999068e9eed56ee4e76cb81558aa26969c56c,ef7dd84338732a0cac3a8995f3bacf9b2896582b8d3317ed508e5d9a5a3447af,,,463893de2c05446b705fcd94061666f9716112a911b189347eaa755c969636c3,108227bcc78cd5f353c5766a0c453064d769a7d472cce812af71a264a5cbb480,,
-33b67cb5385ceddad93d0ee960679041613bed34b8b4a5e6362fe7539ba2d3ce,0105c74958a165e016502eeb87835195505d89714c95272b6fa88fe6c60b33ac,,,069e1b3b155c6da989b9b6a8735bba3c5c1049dcf01fe4474772244db89cf9ca,c77b10bca540e95ee66c1f57ab6297787849a89b2b883116e700593e3c0fe66d,,,f961e4c4eaa39256764649578ca445c3a3efb6230fe01bb8b88ddbb147630265,3884ef435abf16a11993e0a8549d688787b65764d477cee918ffa6c0c3f015c2
-3a898eecdae167231275338e9a79153cbe53f7bf99943eeb72ee64e57bb58699,41ffd7362aaa7b90fe03936deeebe9afafd9c18967122d8f972db2c050d4f07b,60abf7ed2a7ffd3d2ac242a782331ea663d55ca157af994e5e964e9c79a0db40,3c3c39dc37753ab9160dfbc2e0596c3a5114784690caa1836e12036814453da3,adcd3f100de60723f127278998c591fbf081af8e0a77f2a9090bed67d8aa2aa3,,9f540812d58002c2d53dbd587dcce1599c2aa35ea85066b1a169b162865f20ef,c3c3c623c88ac546e9f2043d1fa693c5aeeb87b96f355e7c91edfc96ebbabe8c,5232c0eff219f8dc0ed8d876673a6e040f7e5071f5880d56f6f412972755d18c,
-46e04d129d7b45d054469ce34e24069a1426b3e34f1b68a3d1bff1e070aee192,c6ce9611bd908c16eba5c599e5219de2d18d82c96aafb0180b23ee315513618f,,,,,,,,
-47dc540c94ceb704a23875c11273e16bb0b8a87aed84de911f2133568115f254,13964717dbc998964d7c19ec3d9981fe1d4a9a80845552a98fb9352898532844,,,,,,,,
-4cab73ce2a7e6220975001c8a354143267a3c1ce8bf7692313e654481e616a93,9114cf2edd3b53dbb6581290a5cca532db38b4e9ceeacc9b0437a0e49bf97211,903b600ed648d4ddc48f0f628829c8992c88fab44b692413fb8b3d783854f9a2,2952afe39557606d08c311345788a5071413580917207c86ea7cb829cf2f2c6d,05f414320d0c4004cff10f798c3fda6c4fc335b5a2db940993b3d78147a25c18,48e2531c7e3ec99f807210d6c5330114b4f04d7345535ca5a6e6abf478bdb723,6fc49ff129b72b223b70f09d77d63766d377054bb496dbec0474c286c7ab028d,d6ad501c6aa89f92f73ceecba8775af8ebeca7f6e8df8379158347d530d0cfc2,fa0bebcdf2f3bffb300ef08673c02593b03cca4a5d246bf66c4c287db85da017,b71dace381c136607f8def293accfeeb4b0fb28cbaaca35a5919540a8742450c
-5aeca385d8b781825b07bbec7c858b7170426c88088935850bc13dd6402368a5,a5135c7a27487e7da4f84413837a748e8fbd9377f776ca7af43ec228bfdc938a,8da4f71fb2700758f623d73c24ac91747da43f2302fce16c8d438a769c63495f,6b8f345fc0a25a76455541ddbf2791ff4b943c98b16db2b6eb6cea94a6b19afb,,,725b08e04d8ff8a709dc28c3db536e8b825bc0dcfd031e9372bc7588639cb2d0,9470cba03f5da589baaabe2240d86e00b46bc3674e924d491493156a594e6134,,
-707bf0b938f307b5c222e670598b865d5e1f8a8003df82c7abbf7c9f8fa4d720,8f840f46c70cf84a3ddd198fa67479a2a1e0757ffc207d385440835f705b250f,,,eab90fb459bace62d3ce8fbd69c9f1039f0627d0e93e2f42bffd87889cb236a4,157c26578b226c66daf8edfa56f7560f1131f41d1685175e6d76cc95b4f89f10,,,1546f04ba645319d2c31704296360efc60f9d82f16c1d0bd40027876634dc58b,ea83d9a874dd939925071205a908a9f0eece0be2e97ae8a1928933694b075d1f
-766caa663e1025b9accd7ededd24fbc8193180e028eedae2f41d6bb0b1d36468,22825ee826f8b76c27220e43c79c884a8518bc20f4978cc15f83f9c48346a314,,,8fe95c178da66d1dd249ea6a4dc614a6d46d79c83cbc4beafee518090263e48a,7b044cb756eb207226db302ba05e164781c2f5161dccd72607282cb9ad86a282,,,7016a3e8725992e22db61595b239eb592b928637c343b415011ae7f5fd9c17a5,84fbb348a914df8dd924cfd45fa1e9b87e3d0ae9e23328d9f8d7d345527959ad
-78a23af8da46b1b37e8767921a2d3f528fdc8eca37cea8aea775fd2b283d3776,73d5f35d96f3ce1ef5802ead8edc10787700c593b5e0ddcc3bfb2720b9d36de3,8465ad20bd0f2b4a2d37106769af46288a109bc10b527c3b033c930c0e4b1025,1b7f03bd2c915bb736622aec85601bcabec89268c98945e19a0de4126ed62524,,,7b9a52df42f0d4b5d2c8ef989650b9d775ef643ef4ad83c4fcc36cf2f1b4ec0a,e480fc42d36ea448c99dd5137a9fe43541376d973676ba1e65f21bec9129d70b,,
-78b4be1f9eeef9da65c393e4385f67edd142709b400ca7d900bd952e0c3cf727,089329e17a58a91e71ffe6ddd851e8a352e85a29fcc289b34a3bfdeaf958fe91,,,6008d703955b38da0166bd975ad3535af3b701b2efdf653fc5e7e6eb6afff0a3,,,,9ff728fc6aa4c725fe994268a52caca50c48fe4d10209ac03a18191395000b8c,
-7a2a7c0a81d1bd595dff09b918f8ecb5b5e8493654a4f83496956ed8eb017674,85d583f57e2e42a6a200f646e707134a4a17b6c9ab5b07cb696a912614fe85bb,,,,,,,,
-913da1f8df6f8fd47593840d533ba0458cc9873996bf310460abb495b34c232a,a7803f8e02b70718443a06db502c67925640e936b3fa46dd2ed6b8f7c80fa329,67d916ba2cc154464d87ff4e0cfe3bb816b22a961831c2daf62597a8b0681e87,a4b84520f8853e5482ee7689732ed7dd7da59945d26edeee0bf5f55d3507192f,,,9826e945d33eabb9b27800b1f301c447e94dd569e7ce3d2509da68564f97dda8,5b47badf077ac1ab7d1189768cd12822825a66ba2d912111f40a0aa1caf8e300,,
-96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7,7684ab3b1a43e20a97a7b5520e5b5347841a7d95984fd76b2478a2b710f1a2ce,,,,,,,,
-99be5efb88ca2013bd8e4eb035fd42d5245468fe9afa70d8ba9c1c419a48c4e8,08ee83ae5c7af0c9b2341e595fe347537272d94f2fe9f10b9a8f913279fc6230,,,,,,,,
-9b4fb24edd6d1d8830e272398263cdbf026b97392cc35387b991dc0248a628f9,80e81d40a50b53712a8dac5f468b0903c05219544a56af70aa152ebf17887701,,,6e94af5a32ac100c5230f1e119c538742b7051934b02f3850522cff26bd32d97,e9bd309fbf041342311be3d5bab0b9d16c9f80c6640eb47e311d3178c2adc75d,,,916b50a5cd53eff3adcf0e1ee63ac78bd48fae6cb4fd0c7afadd300c942cce98,1642cf6040fbecbdcee41c2a454f462e93607f399bf14b81cee2ce863d5234d2
-9def996cb1ea87e596b6cadccca3839a352e99d9ce07e635cdb239f38ca294f8,294850a665ab014a0e75eb4b52ee66dd8a8d2b5e453074e58afacb5e019ee90a,b1a29367b95e1996f7e393fb389e7ace812d4135f6ddcdcd77467fc000dfca8c,a340aabc95b4000e3043ba6139178c450046c985fbf09676c440bc6430ddaa5b,4c4cd400d0be335dd651370c5565c2b742a298016212a8605187b3c0751a811e,d90fa208bbb5f3f6e16c5a42b419188ec1951c1eb358f04741b7b48df9e55f79,4e5d6c9846a1e669081c6c04c76185317ed2beca0922323288b9803eff2031a3,5cbf55436a4bfff1cfbc459ec6e873baffb9367a040f69893bbf439acf2251d4,b3b32bff2f41cca229aec8f3aa9a3d48bd5d67fe9ded579fae784c3e8ae57b11,26f05df7444a0c091e93a5bd4be6e7713e6ae3e14ca70fb8be484b71061a9cb6
-a2c4aed1cf757cd9a509734a267ffc7b1166b55f4c8f9c3e3550c56e743328fc,a2c4aed1cf757cd9a509734a267ffc7b1166b55f4c8f9c3e3550c56e743328fc,,,,,,,,
-a8e437abf9c0e74dc6d51eabf2d261a00e785c7e21efeac1f322b610273ba066,5a64cce4be767964e7dba23e78e30149326c539353b647e0d5d7cc361943b13b,,,6f73bdd6b748790b5f788935ca02aee3b9e560c4ba6caf47d716fbde1dd6e92c,b1ff705694188e672f58c6a05eeecc379dd1b60fd3cb9f19fcb02b1d9cab4bc5,,,908c422948b786f4a08776ca35fd511c461a9f3b459350b828e90420e2291303,4e008fa96be77198d0a7395fa11133c8622e49f02c3460e6034fd4e16354b06a
-bf60e4349cace6bce0d552e8d783428db66d0d649bd9e430a3627e2ee14ac839,409f1bcb635319431f2aad17287cbd724992f29b64261bcf5c9d81d01eb533f6,,,,,,,,
-c0ba8a33ac67f44abff5984dfbb6f56c46b880ac2b86e1f23e7fa9c402c53ae7,4767c4cab0d08133980a8e66c3f93a055c8ae62f89a92f8dcfa47607cee0bc57,4c21052f5ffccadb4f707aa1cba828ef384d7861af1690c59d638dfee9f368e7,dbcc8fe22896478161452d44688a6b138050a4d0964470c175a521dcecc5519a,,,b3defad0a0033524b08f855e3457d710c7b2879e50e96f3a629c7200160c9348,2433701dd769b87e9ebad2bb977594ec7faf5b2f69bb8f3e8a5ade22133aaa95,,
-cbe2268747c9c8072c7f9926f2288f270637dc55bb9d14d3368361d5e47d25be,0e4e25736b614910c4984843e606b1e229def08bfd672ab61e2707cde8248c6d,,,c30567184201fac8e1cb9e776d921e17d28cdb7333223abd1c8f860a16393df1,,,,3cfa98e7bdfe05371e346188926de1e82d73248cccddc542e37079f4e9c6be3e,
-ceb827ad3d3884fd4d50ae6099d6d50c09a21e72ebd309708e8b69d93df19e55,a6a0c8c94462f16f1b92502c3d5f9d1618f12ffa756227d5b19b01b9373cd940,,,,,,,,
-d57e9d4f5842134f140032eaf38b5333638e8c4b145fcf86a23d48d3e9acc0f8,2a8162b0a7bdecb0ebffcd150c74accc9c7173b4eba030795dc2b72b16533b37,349a9a592d2c56e5378ae869d646043fc09ffb8fe5fd9debd83a11274da08892,9875f58028cc991cafab9fb1183b350bc1d8d5ce5723813cc2b8434ed1a2100f,,,cb6565a6d2d3a91ac875179629b9fbc03f6004701a02621427c5eed7b25f739d,678a0a7fd73366e35054604ee7c4caf43e272a31a8dc7ec33d47bcb02e5dec20,,
-d94e7f1e9bb1f8a9b90996ba12c461b84956f0e7f230145cc594c2f80b067aa0,b4f4632803cff65c013a566748cd3386d58cd3a28f5b4721056cbe9d278a67a4,,,fad51eda7d418ee2785df9f3788ac9152576312177fc0fd83c65036750581620,749259382784be63f86cc927a5defa6aa8cecb98e38d68f6b7a7e958303c94ad,,,052ae12582be711d87a2060c877536eada89cede8803f027c39afc97afa7e60f,8b6da6c7d87b419c079336d85a210595573134671c729709485816a6cfc36782
-e545d395bb3fd971f91bf9a2b6722831df704efae6c1aa9da0989ed0970b77bb,760486143a1d512da5219d3e5febc7c5c9990d21ca7a501ed23f86c91ddee4cf,,,090892960a84c69967fe5a5d014d3ca19173e4cb72a908586fbce9d1e531a265,42a47f65d00ff2004faa98865ee8ed4f8a9a5ddc9f75042d728de335664bb546,,,f6f76d69f57b39669801a5a2feb2c35e6e8c1b348d56f7a79043162d1ace59ca,bd5b809a2ff00dffb0556779a11712b07565a223608afbd28d721cc999b446e9
-e9f86cefcfd61558fe75da7d4ea48a6c82d93191c6d49579aab49f99e543dcad,5db7371325a7bb83b030691b2d87cd9f199f43d91e302568391ac48181b7cea6,,,,,,,,
-eec4121f2a07b61aba16414812aa9afc39ab0a136360a5ace2240dc19b0464eb,0b623c5296c13218a1eb24e79d00b04bf15788f6c2f7ec100a4a16f1473124a2,,,,,,,,
-f566cc6fccc657365c0197accf3a7d6f80f85209ff666ff774f4dcbc524aa842,0a9933903339a8c9a3fe685330c582907f07adf6009990088b0b2342adb553ed,3ab8dc4ecbc0441c685436ac0d76f16393769c353be6092bd6ec4ce094106bd8,3bd189b4ef3d1baa5610f2b14cb4a2b377eb171511e6f36ef6a05a2c7c52e368,1594764c6296402aadd123675d81f3505d35f2a52c52881568eadb7b675b53f0,c64fbf71138e66de8ce0abdf3b6f51d151ca8e1037ab5b979e62b2faa15be81c,c54723b1343fbbe397abc953f2890e9c6c8963cac419f6d42913b31e6bef9057,c42e764b10c2e455a9ef0d4eb34b5d4c8814e8eaee190c91095fa5d283ad18c7,ea6b89b39d69bfd5522edc98a27e0cafa2ca0d5ad3ad77ea9715248398a4a83f,39b0408eec719921731f5420c490ae2eae3571efc854a468619d4d045ea41413
diff --git a/bip-0327.mediawiki b/bip-0327.mediawiki
index b5600ab..4815f40 100644
--- a/bip-0327.mediawiki
+++ b/bip-0327.mediawiki
@@ -785,6 +785,8 @@ An exception to this rule is <code>MAJOR</code> version zero (0.y.z) which is fo
The <code>MINOR</code> version is incremented whenever the inputs or the output of an algorithm changes in a backward-compatible way or new backward-compatible functionality is added.
The <code>PATCH</code> version is incremented for other changes that are noteworthy (bug fixes, test vectors, important clarifications, etc.).
+* '''1.0.1''' (2024-05-14):
+** Fix minor issue in ''PartialSigVerify'' vectors.
* '''1.0.0''' (2023-03-26):
** Number 327 was assigned to this BIP.
* '''1.0.0-rc.4''' (2023-03-02):
diff --git a/bip-0327/vectors/sign_verify_vectors.json b/bip-0327/vectors/sign_verify_vectors.json
index b467640..f71c8dd 100644
--- a/bip-0327/vectors/sign_verify_vectors.json
+++ b/bip-0327/vectors/sign_verify_vectors.json
@@ -157,7 +157,7 @@
],
"verify_fail_test_cases": [
{
- "sig": "97AC833ADCB1AFA42EBF9E0725616F3C9A0D5B614F6FE283CEAAA37A8FFAF406",
+ "sig": "FED54434AD4CFE953FC527DC6A5E5BE8F6234907B7C187559557CE87A0541C46",
"key_indices": [0, 1, 2],
"nonce_indices": [0, 1, 2],
"msg_index": 0,
@@ -165,7 +165,7 @@
"comment": "Wrong signature (which is equal to the negation of valid signature)"
},
{
- "sig": "68537CC5234E505BD14061F8DA9E90C220A181855FD8BDB7F127BB12403B4D3B",
+ "sig": "012ABBCB52B3016AC03AD82395A1A415C48B93DEF78718E62A7A90052FE224FB",
"key_indices": [0, 1, 2],
"nonce_indices": [0, 1, 2],
"msg_index": 0,
@@ -183,7 +183,7 @@
],
"verify_error_test_cases": [
{
- "sig": "68537CC5234E505BD14061F8DA9E90C220A181855FD8BDB7F127BB12403B4D3B",
+ "sig": "012ABBCB52B3016AC03AD82395A1A415C48B93DEF78718E62A7A90052FE224FB",
"key_indices": [0, 1, 2],
"nonce_indices": [4, 1, 2],
"msg_index": 0,
@@ -196,7 +196,7 @@
"comment": "Invalid pubnonce"
},
{
- "sig": "68537CC5234E505BD14061F8DA9E90C220A181855FD8BDB7F127BB12403B4D3B",
+ "sig": "012ABBCB52B3016AC03AD82395A1A415C48B93DEF78718E62A7A90052FE224FB",
"key_indices": [3, 1, 2],
"nonce_indices": [0, 1, 2],
"msg_index": 0,
diff --git a/bip-0330/minisketch.py b/bip-0330/minisketch.py
index f64286f..5e39779 100755
--- a/bip-0330/minisketch.py
+++ b/bip-0330/minisketch.py
@@ -120,7 +120,7 @@ def find_roots_inner(p, a):
return []
elif len(p) == 2:
return [p[0]]
- # Otherwise, split p in left*right using paramater a_vals[0].
+ # Otherwise, split p in left*right using parameter a_vals[0].
t = poly_monic(poly_trace(p, a))
left = poly_gcd(list(p), t)
right = poly_divmod(list(left), p)
diff --git a/bip-0340.mediawiki b/bip-0340.mediawiki
index c941916..85b7bac 100644
--- a/bip-0340.mediawiki
+++ b/bip-0340.mediawiki
@@ -62,7 +62,7 @@ Since we would like to avoid the fragility that comes with short hashes, the ''e
'''Key prefixing''' Using the verification rule above directly makes Schnorr signatures vulnerable to "related-key attacks" in which a third party can convert a signature ''(R, s)'' for public key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for public key ''P + a⋅G'' and the same message ''m'', for any given additive tweak ''a'' to the signing key. This would render signatures insecure when keys are generated using [[bip-0032.mediawiki#public-parent-key--public-child-key|BIP32's unhardened derivation]] and other methods that rely on additive tweaks to existing keys such as Taproot.
-To protect against these attacks, we choose ''key prefixed''<ref>A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification.</ref> Schnorr signatures which means that the public key is prefixed to the message in the challenge hash input. This changes the equation to ''s⋅G = R + hash(R || P || m)⋅P''. [https://eprint.iacr.org/2015/1135.pdf It can be shown] that key prefixing protects against related-key attacks with additive tweaks. In general, key prefixing increases robustness in multi-user settings, e.g., it seems to be a requirement for proving the MuSig multisignature scheme secure (see Applications below).
+To protect against these attacks, we choose ''key prefixed''<ref>A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification.</ref> Schnorr signatures which means that the public key is prefixed to the message in the challenge hash input. This changes the equation to ''s⋅G = R + hash(R || P || m)⋅P''. [https://eprint.iacr.org/2015/1135.pdf It can be shown] that key prefixing protects against related-key attacks with additive tweaks. In general, key prefixing increases robustness in multi-user settings, e.g., it seems to be a requirement for proving multiparty signing protocols (such as MuSig, MuSig2, and FROST) secure (see Applications below).
We note that key prefixing is not strictly necessary for transaction signatures as used in Bitcoin currently, because signed transactions indirectly commit to the public keys already, i.e., ''m'' contains a commitment to ''pk''. However, this indirect commitment should not be relied upon because it may change with proposals such as SIGHASH_NOINPUT ([[bip-0118.mediawiki|BIP118]]), and would render the signature scheme unsuitable for other purposes than signing transactions, e.g., [https://bitcoin.org/en/developer-reference#signmessage signing ordinary messages].
@@ -165,7 +165,7 @@ It should be noted that various alternative signing algorithms can be used to pr
'''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the secret key through its nonce selection.
-'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple secret keys to participate in signing (see Applications below).
+'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2020/1261.pdf MuSig2], where a single public key requires holders of multiple secret keys to participate in signing (see Applications below).
'''It is important to note that multisignature signing schemes in general are insecure with the ''rand'' generation from the default signing algorithm above (or any other deterministic method).'''
'''Precomputed public key data''' For many uses the compressed 33-byte encoding of the public key corresponding to the secret key may already be known, making it easy to evaluate ''has_even_y(P)'' and ''bytes(P)''. As such, having signers supply this directly may be more efficient than recalculating the public key from the secret key. However, if this optimization is used and additionally the signature verification at the end of the signing algorithm is dropped for increased efficiency, signers must ensure the public key is correctly calculated and not taken from untrusted sources.
@@ -264,9 +264,9 @@ While recent academic papers claim that they are also possible with ECDSA, conse
=== Multisignatures and Threshold Signatures ===
-By means of an interactive scheme such as [https://eprint.iacr.org/2018/068 MuSig], participants can aggregate their public keys into a single public key which they can jointly sign for. This allows ''n''-of-''n'' multisignatures which, from a verifier's perspective, are no different from ordinary signatures, giving improved privacy and efficiency versus ''CHECKMULTISIG'' or other means.
+By means of an interactive scheme such as [https://eprint.iacr.org/2020/1261.pdf MuSig2] ([[bip-0327.mediawiki|BIP327]]), participants can aggregate their public keys into a single public key which they can jointly sign for. This allows ''n''-of-''n'' multisignatures which, from a verifier's perspective, are no different from ordinary signatures, giving improved privacy and efficiency versus ''CHECKMULTISIG'' or other means.
-Moreover, Schnorr signatures are compatible with [https://web.archive.org/web/20031003232851/http://www.research.ibm.com/security/dkg.ps distributed key generation], which enables interactive threshold signatures schemes, e.g., the schemes described by [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps Stinson and Strobl (2001)] or [https://web.archive.org/web/20060911151529/http://theory.lcs.mit.edu/~stasio/Papers/gjkr03.pdf Gennaro, Jarecki and Krawczyk (2003)]. These protocols make it possible to realize ''k''-of-''n'' threshold signatures, which ensure that any subset of size ''k'' of the set of ''n'' signers can sign but no subset of size less than ''k'' can produce a valid Schnorr signature. However, the practicality of the existing schemes is limited: most schemes in the literature have been proven secure only for the case ''k-1 < n/2'', are not secure when used concurrently in multiple sessions, or require a reliable broadcast mechanism to be secure. Further research is necessary to improve this situation.
+Moreover, Schnorr signatures are compatible with [https://en.wikipedia.org/wiki/Distributed_key_generation distributed key generation], which enables interactive threshold signatures schemes, e.g., the schemes by [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps Stinson and Strobl (2001)], by [https://link.springer.com/content/pdf/10.1007/s00145-006-0347-3.pdf Gennaro, Jarecki, Krawczyk, and Rabin (2007)], or the [https://eprint.iacr.org/2020/852.pdf FROST] scheme including its variants such as [https://eprint.iacr.org/2023/899.pdf FROST3]. These protocols make it possible to realize ''k''-of-''n'' threshold signatures, which ensure that any subset of size ''k'' of the set of ''n'' signers can sign but no subset of size less than ''k'' can produce a valid Schnorr signature.
=== Adaptor Signatures ===
@@ -278,7 +278,7 @@ Adaptor signatures, beyond the efficiency and privacy benefits of encoding scrip
=== Blind Signatures ===
-A blind signature protocol is an interactive protocol that enables a signer to sign a message at the behest of another party without learning any information about the signed message or the signature. Schnorr signatures admit a very [http://publikationen.ub.uni-frankfurt.de/files/4292/schnorr.blind_sigs_attack.2001.pdf simple blind signature scheme] which is however insecure because it's vulnerable to [https://www.iacr.org/archive/crypto2002/24420288/24420288.pdf Wagner's attack]. A known mitigation is to let the signer abort a signing session with a certain probability, and the resulting scheme can be [https://eprint.iacr.org/2019/877 proven secure under non-standard cryptographic assumptions].
+A blind signature protocol is an interactive protocol that enables a signer to sign a message at the behest of another party without learning any information about the signed message or the signature. Schnorr signatures admit a very [http://publikationen.ub.uni-frankfurt.de/files/4292/schnorr.blind_sigs_attack.2001.pdf simple blind signature scheme] which is however insecure because it's vulnerable to [https://www.iacr.org/archive/crypto2002/24420288/24420288.pdf Wagner's attack]. Known mitigations are to let the signer abort a signing session with a certain probability, which can be [https://eprint.iacr.org/2019/877 proven secure under non-standard cryptographic assumptions], or [https://eprint.iacr.org/2022/1676.pdf to use zero-knowledge proofs].
Blind Schnorr signatures could for example be used in [https://github.com/ElementsProject/scriptless-scripts/blob/master/md/partially-blind-swap.md Partially Blind Atomic Swaps], a construction to enable transferring of coins, mediated by an untrusted escrow agent, without connecting the transactors in the public blockchain transaction graph.
@@ -293,6 +293,7 @@ To help implementors understand updates to this BIP, we keep a list of substanti
* 2022-08: Fix function signature of lift_x in reference code
* 2023-04: Allow messages of arbitrary size
+* 2024-05: Update "Applications" section with more recent references
== Footnotes ==
diff --git a/bip-0347.mediawiki b/bip-0347.mediawiki
new file mode 100644
index 0000000..981af81
--- /dev/null
+++ b/bip-0347.mediawiki
@@ -0,0 +1,113 @@
+<pre>
+ BIP: 347
+ Layer: Consensus (soft fork)
+ Title: OP_CAT in Tapscript
+ Author: Ethan Heilman <ethan.r.heilman@gmail.com>
+ Armin Sabouri <arminsdev@gmail.com>
+ Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0347
+ Status: Draft
+ Type: Standards Track
+ Created: 2023-12-11
+ License: BSD-3-Clause
+ Post-History: 2023-10-21: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-October/022049.html [bitcoin-dev] Proposed BIP for OP_CAT
+</pre>
+
+==Abstract==
+
+This BIP introduces OP_CAT as a tapscript opcode which allows the concatenation of two values on the stack. OP_CAT would be activated via a soft fork by redefining the opcode OP_SUCCESS126 (126 in decimal and 0x7e in hexadecimal). This is the same opcode value used by the original OP_CAT.
+
+== Copyright ==
+
+This document is licensed under the 3-clause BSD license.
+
+==Specification==
+
+When evaluated, the OP_CAT instruction:
+# Pops the top two values off the stack,
+# concatenates the popped values together in stack order,
+# and then pushes the concatenated value on the top of the stack.
+
+Given the stack ''<nowiki>[x1, x2]</nowiki>'', where ''x2'' is at the top of the stack, OP_CAT will push ''x1 || x2'' onto the stack. By ''||'' we denote concatenation. OP_CAT fails if there are fewer than two values on the stack or if a concatenated value would have a combined size greater than the maximum script element size of 520 bytes.
+
+This opcode would be activated via a soft fork by redefining the tapscript opcode OP_SUCCESS126 (126 in decimal and 0x7e in hexadecimal) to OP_CAT.
+
+==Motivation==
+
+Bitcoin Tapscript lacks a general purpose way of combining objects on the stack, restricting the expressiveness and power of Tapscript. This prevents, among many other things, the ability to construct and evaluate merkle trees and other hashed data structures in Tapscript. OP_CAT, by adding a general purpose way to concatenate stack values, would overcome this limitation and greatly increase the functionality of Tapscript.
+
+OP_CAT aims to expand the toolbox of the tapscript developer with a simple, modular, and useful opcode in the spirit of Unix <ref>R. Pike and B. Kernighan, "Program design in the UNIX environment", 1983, https://harmful.cat-v.org/cat-v/unix_prog_design.pdf</ref>. To demonstrate the usefulness of OP_CAT below we provide a non-exhaustive list of some usecases that OP_CAT would enable:
+
+* Bitstream, a protocol for the atomic swap (fair exchange) of bitcoins for decryption keys, that enables decentralized file hosting systems paid in Bitcoin. While such swaps are currently possible on Bitcoin without OP_CAT, they require the use of complex and computationally expensive Verifiable Computation cryptographic techniques. OP_CAT would remove this requirement on Verifiable Computation, making such protocols far more practical to build in Bitcoin. <ref>R. Linus, "BitStream: Decentralized File Hosting Incentivised via Bitcoin Payments", 2023, https://robinlinus.com/bitstream.pdf</ref>
+* Tree signatures provide a multisignature script whose size can be logarithmic in the number of public keys and can encode spend conditions beyond n-of-m. For instance a transaction less than 1KB in size could support tree signatures with up to 4,294,967,296 public keys. This also enables generalized logical spend conditions. <ref> P. Wuille, "Multisig on steroids using tree signatures", 2015, https://blog.blockstream.com/en-treesignatures/</ref>
+* Post-Quantum Lamport signatures in Bitcoin transactions. Lamport signatures merely require the ability to hash and concatenate values on the stack. <ref>J. Rubin, "[bitcoin-dev] OP_CAT Makes Bitcoin Quantum Secure [was CheckSigFromStack for Arithmetic Values]", 2021, https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-July/019233.html</ref> It has been proposed that if ECDSA is broken or a powerful computer was on the horizon, there might be an effort to protect ownership of bitcoins by allowing people to mark their taproot outputs as "script-path only" and then move their coins into such outputs with a leaf in the script tree requiring a Lamport signature. It is an open question if a tapscript commitment would preserve the quantum resistance of Lamport signatures. Beyond this question, the use of Lamport Signatures in taproot outputs is unlikely to be quantum resistant even if the script spend-path is made quantum resistant. This is because taproot outputs can also be spent with a key. An attacker with a sufficiently powerful quantum computer could bypass the taproot script spend-path by finding the discrete log of the taproot output and thus spending the output using the key spend-path. The use of "Nothing Up My Sleeve" (NUMS) points as described in [[bip-0341.mediawiki|BIP341]] to disable the key spend-path does not disable the key spend-path against a quantum attacker as NUMS relies on the hardness of finding discrete logs. We are not aware of any mechanism which could disable the key spend-path in a taproot output without a softfork change to taproot.
+* Non-equivocation contracts <ref>T. Ruffing, A. Kate, D. Schröder, "Liar, Liar, Coins on Fire: Penalizing Equivocation by Loss of Bitcoins", 2015, https://web.archive.org/web/20221023121048/https://publications.cispa.saarland/565/1/penalizing.pdf</ref> in tapscript provide a mechanism to punish equivocation/double spending in Bitcoin payment channels. OP_CAT enables this by enforcing rules on the spending transaction's nonce. The capability is a useful building block for payment channels and other Bitcoin protocols.
+* Vaults <ref>M. Moser, I. Eyal, and E. G. Sirer, Bitcoin Covenants, http://fc16.ifca.ai/bitcoin/papers/MES16.pdf</ref> which are a specialized covenant that allows a user to block a malicious party who has compromised the user's secret key from stealing the funds in that output. As shown in <ref>A. Poelstra, "CAT and Schnorr Tricks II", 2021, https://www.wpsoftware.net/andrew/blog/cat-and-schnorr-tricks-ii.html</ref> OP_CAT is sufficient to build vaults in Bitcoin.
+* Replicating CheckSigFromStack <ref>A. Poelstra, "CAT and Schnorr Tricks I", 2021, https://medium.com/blockstream/cat-and-schnorr-tricks-i-faf1b59bd298</ref> which would allow the creation of simple covenants and other advanced contracts without having to presign spending transactions, possibly reducing complexity and the amount of data that needs to be stored. Originally shown to work with Schnorr signatures, this result has been extended to ECDSA signatures <ref>R. Linus, "Covenants with CAT and ECDSA", 2023, https://gist.github.com/RobinLinus/9a69f5552be94d13170ec79bf34d5e85#file-covenants_cat_ecdsa-md</ref>.
+
+OP_CAT was available in early versions of Bitcoin.
+In 2010, a single commit disabled OP_CAT, along with another 15 opcodes.
+Folklore states that OP_CAT was removed in this commit because it enabled the construction of a script whose evaluation could have memory usage exponential in the size of the script.
+For example, a script that pushed a 1-byte value on the stack and then repeated the opcodes OP_DUP, OP_CAT 40 times would result in a stack element whose size was greater than 1 terabyte assuming no maximum stack element size. As Bitcoin at that time had a maximum stack element size of 5000 bytes, the effect of this expansion was limited to 5000 bytes.
+This is no longer an issue because tapscript enforces a maximum stack element size of 520 bytes.
+
+
+==Rationale==
+
+Our decision to reenable OP_CAT by redefining a tapscript OP_SUCCESSx opcode to OP_CAT was motivated to leverage the tapscript softfork opcode upgrade path introduced in [[bip-0342.mediawiki|BIP342]].
+
+We specifically choose to use OP_SUCCESS126 rather than another OP_SUCCESSx as OP_SUCCESS126 uses the same opcode value (126 in decimal and 0x7e in hexadecimal) that was used for OP_CAT prior to it being disabled in Bitcoin. This removes a potential source of confusion that would exist if we had a opcode value different from the one used in the original OP_CAT opcode.
+
+While the OP_SUCCESSx opcode upgrade path could enable us to increase the stack element size while reenabling OP_CAT, we wanted to separate the decision to change the stack element size limit from the decision to reenable OP_CAT. This BIP takes no position in favor or against increasing the stack element size limit.
+
+==Backwards Compatibility==
+
+OP_CAT usage in a non-tapscript script will continue to trigger the SCRIPT_ERR_DISABLED_OPCODE. The only change would be to OP_CAT usage in tapscript. This change to tapscript would be activated as a soft fork that redefines an OP_SUCCESSx opcode (OP_SUCCESS126) to OP_CAT.
+
+==Reference implementation==
+
+<pre>
+case OP_CAT:
+{
+ if (stack.size() < 2)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype& vch1 = stacktop(-2);
+ valtype& vch2 = stacktop(-1);
+ if (vch1.size() + vch2.size() > MAX_SCRIPT_ELEMENT_SIZE)
+ return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
+ vch1.insert(vch1.end(), vch2.begin(), vch2.end());
+ stack.pop_back();
+}
+break;
+</pre>
+
+
+The value of <code>MAX_SCRIPT_ELEMENT_SIZE</code> is 520.
+
+This implementation is inspired by the original implementation of [https://github.com/bitcoin/bitcoin/blob/01cd2fdaf3ac6071304ceb80fb7436ac02b1059e/script.cpp#L381-L393 OP_CAT as it existed in the Bitcoin codebase] prior to the commit "misc changes" 4bd188c<ref>S. Nakamoto, "misc changes", Aug 25 2010, https://github.com/bitcoin/bitcoin/commit/4bd188c4383d6e614e18f79dc337fbabe8464c82#diff-27496895958ca30c47bbb873299a2ad7a7ea1003a9faa96b317250e3b7aa1fefR94</ref> which disabled it:
+
+<pre>
+case OP_CAT:
+{
+ // (x1 x2 -- out)
+ if (stack.size() < 2)
+ return false;
+ valtype& vch1 = stacktop(-2);
+ valtype& vch2 = stacktop(-1);
+ vch1.insert(vch1.end(), vch2.begin(), vch2.end());
+ stack.pop_back();
+ if (stacktop(-1).size() > 5000)
+ return false;
+}
+break;
+</pre>
+
+An alternative implementation of OP_CAT can be found in Elements <ref>Roose S., Elements Project, "Re-enable several disabled opcodes", 2019, https://github.com/ElementsProject/elements/commit/13e1103abe3e328c5a4e2039b51a546f8be6c60a#diff-a0337ffd7259e8c7c9a7786d6dbd420c80abfa1afdb34ebae3261109d9ae3c19R740-R759</ref>.
+
+==References==
+
+<references/>
+
+==Acknowledgements==
+
+We wish to acknowledge Dan Gould for encouraging and helping review this effort. We also want to thank Madars Virza, Jeremy Rubin, Andrew Poelstra, Bob Summerwill,
+Tim Ruffing and Johan T. Halseth for their feedback, review and helpful comments.
diff --git a/bip-0352.mediawiki b/bip-0352.mediawiki
new file mode 100644
index 0000000..0eff355
--- /dev/null
+++ b/bip-0352.mediawiki
@@ -0,0 +1,493 @@
+<pre>
+ BIP: 352
+ Layer: Applications
+ Title: Silent Payments
+ Author: josibake <josibake@protonmail.com>
+ Ruben Somsen <rsomsen@gmail.com>
+ Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0352
+ Status: Proposed
+ Type: Standards Track
+ Created: 2023-03-09
+ License: BSD-2-Clause
+ Post-History: 2022-03-13: https://gist.github.com/RubenSomsen/c43b79517e7cb701ebf77eec6dbb46b8 [gist] Original proposal
+ 2022-03-28: https://gnusha.org/pi/bitcoindev/CAPv7TjbXm953U2h+-12MfJ24YqOM5Kcq77_xFTjVK+R2nf-nYg@mail.gmail.com/ [bitcoin-dev] Silent Payments – Non-interactive private payments with no on-chain overhead
+ 2022-10-11: https://gnusha.org/pi/bitcoindev/P_21MLHGJicZ-hkbC4DGu86c5BtNKiH8spY4TOw5FJsfimdi_6VyHzU_y-s1mZsOcC2FA3EW_6w6W5qfV9dRK_7AvTAxDlwVfU-yhWZPEuo=@protonmail.com/ [bitcoin-dev] Silent Payment v4 (coinjoin support added)
+ 2023-08-04: https://gnusha.org/pi/bitcoindev/ZM03twumu88V2NFH@petertodd.org/ [bitcoin-dev] BIP-352 Silent Payments addresses should have an expiration time
+</pre>
+
+== Introduction ==
+
+=== Abstract ===
+
+This document specifies a protocol for static payment addresses in Bitcoin without on-chain linkability of payments or a need for on-chain notifications.
+
+=== Copyright ===
+
+This BIP is licensed under the BSD 2-clause license.
+
+=== Motivation ===
+
+Using a new address for each Bitcoin transaction is a crucial aspect of maintaining privacy. This often requires a secure interaction between sender and receiver, so that the receiver can hand out a fresh address, a batch of fresh addresses, or a method for the sender to generate addresses on-demand, such as an xpub.
+
+However, interaction is often infeasible and in many cases undesirable. To solve for this, various protocols have been proposed which use a static payment address and notifications sent via the blockchain<ref name="out_of_band_notifications">'''Why not use out-of-band notifications''' Out-of-band notifications (e.g. using something other than the Bitcoin blockchain) have been proposed as a way of addressing the privacy and cost concerns of using the Bitcoin blockchain as a messaging layer. This, however, simply moves the privacy and cost concerns somewhere else and increases the risk of losing money due to a notification not being reliably delivered, or even censored, and makes this notification data critical for backup to recover funds.</ref>. These protocols eliminate the need for interaction, but at the expense of increased costs for one-time payments and a noticeable footprint in the blockchain, potentially revealing metadata about the sender and receiver. Notification schemes also allow the receiver to link all payments from the same sender, compromising sender privacy.
+
+This proposal aims to address the limitations of these current approaches by presenting a solution that eliminates the need for interaction, eliminates the need for notifications, and protects both sender and receiver privacy. These benefits come at the cost of requiring wallets to scan the blockchain in order to detect payments. This added requirement is generally feasible for full nodes but poses a challenge for light clients. While it is possible today to implement a privacy-preserving light client at the cost of increased bandwidth, light client support is considered an area of open research (see [[#appendix-a-light-client-support|Appendix A: Light Client Support]]).
+
+The design keeps collaborative transactions such as CoinJoins and inputs with MuSig and FROST keys in mind, but it is recommended that the keys of all inputs of a transaction belong to the same entity as there is no formal proof that the protocol is secure in a collaborative setting.
+
+== Goals ==
+
+We aim to present a protocol which satisfies the following properties:
+
+* No increase in the size or cost of transactions
+* Resulting transactions blend in with other bitcoin transactions and can't be distinguished
+* Transactions can't be linked to a silent payment address by an outside observer
+* No sender-receiver interaction required
+* No linking of multiple payments to the same sender
+* Each silent payment goes to a unique address, avoiding accidental address reuse
+* Supports payment labeling
+* Uses existing seed phrase or descriptor methods for backup and recovery
+* Separates scanning and spending responsibilities
+* Compatible with other spending protocols, such as CoinJoin
+* Light client/SPV wallet support
+* Protocol is upgradeable
+
+== Overview ==
+
+We first present an informal overview of the protocol. In what follows, uppercase letters represent public keys, lowercase letters represent private keys, ''||'' refers to byte concatenation, ''·'' refers to elliptic curve scalar multiplication, ''G'' represents the generator point for secp256k1, and ''n'' represents the curve order for secp256k1. Each section of the overview is incomplete on its own and is meant to build on the previous section in order to introduce and briefly explain each aspect of the protocol. For the full protocol specification, see [[#specification|Specification]].
+
+''' Simple case '''
+
+Bob publishes a public key ''B'' as a silent payment address. Alice discovers Bob's silent payment address, selects a UTXO with private key ''a'', public key ''A'' and creates a destination output ''P'' for Bob in the following manner:
+
+* Let ''P = B + hash(a·B)·G''
+* Encode ''P'' as a [https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki BIP341] taproot output
+
+Since ''a·B == b·A'' ([https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman Elliptic-curve Diffie–Hellman]), Bob scans with his private key ''b'' by collecting the input public keys for each transaction with at least one unspent taproot output and performing the ECDH calculation until ''P'' is found (i.e. calculating ''P = B + hash(b·A)·G'' and seeing that ''P'' is present in the transaction outputs).
+
+''' Creating more than one output '''
+
+In order to allow Alice to create more than one output for Bob<ref name="why_more_than_one_output">'''Why allow for more than one output?''' Allowing Alice to break her payment to Bob into multiple amounts opens up a number of privacy improving techniques for Alice, making the transaction look like a CoinJoin or better hiding the change amount by splitting both the payment and change outputs into multiple amounts. It also allows for Alice and Carol to both have their own unique output paying Bob in the event they are in a collaborative transaction and both paying Bob's silent payment address.</ref>, we include an integer in the following manner:
+
+* Let ''k = 0''
+* Let ''P<sub>0</sub> = B + hash(a·B || k)·G''
+* For additional outputs:
+** Increment ''k'' by one (''k++'')
+** Let ''P<sub>i</sub> = B + hash(a·B || k)·G''
+
+Bob detects this output the same as before by searching for ''P<sub>0</sub> = B + hash(b·A || 0)·G''. Once he detects the first output, he must:
+
+* Check for ''P<sub>1</sub> = B + hash(b·A || 1)·G''
+* If ''P<sub>1</sub>'' is not found, stop
+* If ''P<sub>1</sub>'' is found, continue to check for ''P<sub>2</sub>'' and so on until an additional output is not found
+
+Since Bob will only perform these subsequent checks after a transaction with at least one output paying him is found, the increase to his overall scanning requirement is negligible. It should also be noted that the order in which these outputs appear in the transaction does not affect the outcome.
+
+''' Preventing address reuse '''
+
+If Alice were to use a different UTXO from the same public key ''A'' for a subsequent payment to Bob, she would end up deriving the same destinations ''P<sub>i</sub>''. To prevent this, Alice should include an input hash in the following manner:
+
+* Let ''input_hash = hash(outpoint || A)''<ref name="why_include_A">'''Why include A in the input hash calculation?''' By committing to A in input hash, this ensures that the sender cannot maliciously choose a private key ''a&prime;'' in a subsequent transaction where ''a&prime; = input_hash·a / input_hash&prime;'', which would force address reuse in the protocol.</ref>
+* Let ''P<sub>0</sub> = B + hash(input_hash·a·B || 0)·G''
+
+Bob must calculate the same ''input_hash'' when scanning.
+
+''' Using all inputs '''
+
+In our simplified example we have been referring to Alice's transactions as having only one input ''A'', but in reality a Bitcoin transaction can have many inputs. Instead of requiring Alice to pick a particular input and requiring Bob to check each input separately, we can instead require Alice to perform the tweak with the sum of the input public keys<ref name="other_inputs">'''What about inputs without public keys?''' Inputs without public keys can still be spent in the transaction but are simply ignored in the silent payments protocol.</ref>. This significantly reduces Bob's scanning requirement, makes light client support more feasible<ref name="using_all_inputs">'''How does using all inputs help light clients?''' If Alice uses a random input for the tweak, Bob necessarily has to have access to and check all transaction inputs, which requires performing an ECC multiplication per input. If instead Alice performs the tweak with the sum of the input public keys, Bob only needs the summed 33 byte public key per transaction and only does one ECC multiplication per transaction. Bob can then use BIP158 block filters to determine if any of the outputs exist in a block and thus avoids downloading transactions which don't belong to him. It is still an open question as to how Bob can source the 33 bytes per transaction in a trustless manner, see [[#appendix-a-light-client-support|Appendix A: Light Client Support]] for more details.</ref>, and protects Alice's privacy in collaborative transaction protocols such as CoinJoin<ref name=""all_inputs_and_coinjoin">'''Why does using all inputs matter for CoinJoin?''' If Alice uses a random input to create the output for Bob, this necessarily reveals to Bob which input Alice has control of. If Alice is paying Bob as part of a CoinJoin, this would reveal which input belongs to her, degrading the anonymity set of the CoinJoin and giving Bob more information about Alice. If instead all inputs are used, Bob has no way of knowing which input(s) belong to Alice. This comes at the cost of increased complexity as the CoinJoin participants now need to coordinate to create the silent payment output and would need to use [https://gist.github.com/RubenSomsen/be7a4760dd4596d06963d67baf140406 Blind Diffie–Hellman] to prevent the other participants from learning who Alice is paying. Note it is currently not recommended to use this protocol for CoinJoins due to a lack of a formal security proof.</ref>.
+
+Alice performs the tweak with the sum of her input private keys in the following manner:
+
+* Let ''A = A<sub>1</sub> + A<sub>2</sub> + ... + A<sub>n</sub>''
+* Let ''input_hash = hash(outpoint<sub>L</sub> || A)'', where ''outpoint<sub>L</sub>'' is the smallest outpoint lexicographically<ref name="why_smallest_outpoint">'''Why use the lexicographically smallest outpoint for the hash?''' Recall that the purpose of including the input hash is so that the sender and receiver can both come up with a deterministic nonce that ensures that a unique address is generated each time, even when reusing the same scriptPubKey as an input. Choosing the smallest outpoint lexicographically satisifes this requirement, while also ensuring that the generated output is not dependent on the final ordering of inputs in the transaction. Using a single outpoint also works well with memory constrained devices (such as hardware signing devices) as it does not require the device to have the entire transaction in memory in order to generate the silent payment output.</ref>
+* Let ''a = a<sub>1</sub> + a<sub>2</sub> + ... + a<sub>n</sub>''
+* Let ''P<sub>0</sub> = B + hash(input_hash·a·B || 0)·G''
+
+''' Spend and Scan Key '''
+
+Since Bob needs his private key ''b'' to check for incoming payments, this requires ''b'' to be exposed to an online device. To minimize the risks involved, Bob can instead publish an address of the form ''(B<sub>scan</sub>, B<sub>spend</sub>)''. This allows Bob to keep ''b<sub>spend</sub>'' in offline cold storage and perform the scanning with the public key ''B<sub>spend</sub>'' and private key ''b<sub>scan</sub>''. Alice performs the tweak using both of Bob's public keys in the following manner:
+
+* Let ''P<sub>0</sub> = B<sub>spend</sub> + hash(input_hash·a·B<sub>scan</sub> || 0)·G''
+
+Bob detects this payment by calculating ''P<sub>0</sub> = B<sub>spend</sub> + hash(input_hash·b<sub>scan</sub>·A || 0)·G'' with his online device and can spend from his cold storage signing device using ''(b<sub>spend</sub> + hash(input_hash·b<sub>scan</sub>·A || 0)) mod n'' as the private key.
+
+''' Labels '''
+
+For a single silent payment address of the form ''(B<sub>scan</sub>, B<sub>spend</sub>)'', Bob may wish to differentiate incoming payments. Naively, Bob could publish multiple silent payment addresses, but this would require him to scan for each one, which becomes prohibitively expensive. Instead, Bob can label his spend public key ''B<sub>spend</sub>'' with an integer ''m'' in the following way:
+
+* Let ''B<sub>m</sub> = B<sub>spend</sub> + hash(b<sub>scan</sub> || m)·G'' where m is an incrementable integer starting from 1
+* Publish ''(B<sub>scan</sub>, B<sub>1</sub>)'', ''(B<sub>scan</sub>, B<sub>2</sub>)'' etc.
+
+Alice performs the tweak as before using one of the published ''(B<sub>scan</sub>, B<sub>m</sub>)'' pairs. Bob detects the labeled payment in the following manner:
+
+* Let ''P<sub>0</sub> = B<sub>spend</sub> + hash(input_hash·b<sub>scan</sub>·A || 0)·G''
+* Subtract ''P<sub>0</sub>'' from each of the transaction outputs and check if the remainder matches any of the labels (''hash(b<sub>scan</sub> || 1)·G'', ''hash(b<sub>scan</sub> || 2)·G'' etc.) that the wallet has previously used
+
+It is important to note that an outside observer can easily deduce that each published ''(B<sub>scan</sub>, B<sub>m</sub>)'' pair is owned by the same entity as each published address will have ''B<sub>scan</sub>'' in common. As such, labels are not meant as a way for Bob to manage separate identities, but rather a way for Bob to determine the source of an incoming payment.
+
+''' Labels for change '''
+
+Bob can also use labels for managing his own change outputs. We reserve ''m = 0'' for this use case. This gives Bob an alternative to using BIP32 for managing change, while still allowing him to know which of his unspent outputs were change when recovering his wallet from the master key. It is important that the wallet never hands out the label with ''m = 0'' in order to ensure nobody else can create payments that are wrongly labeled as change.
+
+While the use of labels is optional, every receiving silent payments wallet should at least scan for the change label when recovering from backup in order to ensure maximum cross-compatibility.
+
+== Specification ==
+
+We use the following functions and conventions:
+
+* ''outpoint'' (36 bytes): the <code>COutPoint</code> of an input (32-byte txid, least significant byte first || 4-byte vout, least significant byte first)<ref name="why_little_endian">'''Why are outpoints little-endian?''' Despite using big endian throughout the rest of the BIP, outpoints are sorted and hashed matching their transaction serialization, which is little-endian. This allows a wallet to parse a serialized transaction for use in silent payments without needing to re-order the bytes when computing the input hash. Note: despite outpoints being stored and serialized as little-endian, the transaction hash (txid) is always displayed as big-endian.</ref>
+* ser<sub>32</sub>(i): serializes a 32-bit unsigned integer ''i'' as a 4-byte sequence, most significant byte first.
+* ser<sub>256</sub>(p): serializes the integer p as a 32-byte sequence, most significant byte first.
+* ser<sub>P</sub>(P): serializes the coordinate pair P = (x,y) as a byte sequence using SEC1's compressed form: (0x02 or 0x03) || ser<sub>256</sub>(x), where the header byte depends on the parity of the omitted Y coordinate.
+
+For everything not defined above, we use the notation from [https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki#specification BIP340]. This includes the ''hash<sub>tag</sub>(x)'' notation to refer to ''SHA256(SHA256(tag) || SHA256(tag) || x)''.
+
+=== Versions ===
+
+This document defines version 0 (''sp1q''). Version is communicated through the address in the same way as bech32 addresses (see [https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32 BIP173]. Future upgrades to silent payments will require a new version. As much as possible, future upgrades should support receiving from older wallets (e.g. a silent payments v0 wallet can send to both v0 and v1 addresses). Any changes that break compatibility with older silent payment versions should be a new BIP.
+
+Future silent payments versions will use the following scheme:
+
+{| class="wikitable"
+|-
+!
+!0
+!1
+!2
+!3
+!4
+!5
+!6
+!7
+!Compatibility
+|-
+!+0
+|q||p||z||r||y||9||x||8||rowspan="4" | backwards compatible
+|-
+!+8
+|g||f||2||t||v||d||w||0
+|-
+!+16
+|s||3||j||n||5||4||k||h
+|-
+!+24
+|c||e||6||m||u||a||7|| -
+|}
+
+''v31'' (l) is reserved for a backwards incompatible change, if needed. For silent payments v0:
+
+* If the receiver's silent payment address version is:
+** ''v0'': check that the data part is exactly 66-bytes. Otherwise, fail
+** ''v1'' through ''v30'': read the first 66-bytes of the data part and discard the remaining bytes
+** ''v31'': fail
+* Receiver addresses are always [https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki BIP341] taproot outputs<ref name="why_taproot">'''Why only taproot outputs?''' Providing too much optionality for the protocol makes it difficult to implement and can be at odds with the goal of providing the best privacy. Limiting to taproot outputs helps simplify the implementation significantly while also putting users in the best eventual anonymity set.</ref>
+* The sender should sign with one of the sighash flags ''DEFAULT'', ''ALL'', ''SINGLE'', ''NONE'' (''ANYONECANPAY'' is unsafe). It is strongly recommended implementations use ''SIGHASH_ALL'' (''SIGHASH_DEFAULT'' for taproot inputs) when possible<ref name="why_not_sighash_anyonecanpay">'''Why is it unsafe to use ''SIGHASH_ANYONECANPAY''?''' Since the output address for the receiver is derived from the sum of the [[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]] public keys, the inputs must not change once the sender has signed the transaction. If the inputs are allowed to change after the fact, the receiver will not be able to calculate the shared secret needed to find and spend the output. It is currently an open question on how a future version of silent payments could be made to work with new sighash flags such as ''SIGHASH_GROUP'' and ''SIGHASH_ANYPREVOUT''.</ref>
+* Inputs used to derive the shared secret are from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list
+
+=== Scanning silent payment eligible transactions ===
+
+For silent payments v0 a transaction MUST be scanned if and only if all of the following are true:
+
+* The transaction contains at least one BIP341 taproot output (note: spent transactions optionally can be skipped by only considering transactions with at least one unspent taproot output)
+* The transaction has at least one input from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list
+* The transaction does not spend an output with SegWit version > 1<ref name="skip_txs_with_unknown_prevouts">'''Why skip transactions that spend SegWit version > 1?''' Skipping transactions that spend unknown output scripts allows us to have a clean upgrade path for silent payments by avoiding the need to scan the same transaction multiple times with different rule sets. If a new SegWit version is added in the future and silent payments v1 is released with support, we would want to avoid having to first scan the transaction with the silent payment v0 rules and then again with the silent payment v1 rules. Note: this restriction only applies to the inputs of a transaction.</ref>
+
+=== Address encoding ===
+
+A silent payment address is constructed in the following manner:
+
+* Let ''B<sub>scan</sub>, b<sub>scan</sub> = Receiver's scan public key and corresponding private key''
+* Let ''B<sub>spend</sub>, b<sub>spend</sub> = Receiver's spend public key and corresponding private key''
+* Let ''B<sub>m</sub> = B<sub>spend</sub> + hash<sub>BIP0352/Label</sub>(ser<sub>256</sub>(b<sub>scan</sub>) || ser<sub>32</sub>(m))·G'', where ''hash<sub>BIP0352/Label</sub>(ser<sub>256</sub>(b<sub>scan</sub>) || ser<sub>32</sub>(m))·G'' is an optional integer tweak for labeling
+** If no label is applied then ''B<sub>m</sub> = B<sub>spend</sub>''
+* The final address is a [https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki Bech32m] encoding of:
+** The human-readable part "sp" for mainnet, "tsp" for testnets (e.g. signet, testnet)
+** The data-part values:
+*** The character "q", to represent a silent payment address of version 0
+*** The 66-byte concatenation of the receiver's public keys, ''ser<sub>P</sub>(B<sub>scan</sub>) || ser<sub>P</sub>(B<sub>m</sub>)''
+
+Note: [https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki BIP173] imposes a 90 character limit for Bech32 segwit addresses and limits versions to 0 through 16, whereas a silent payment address requires ''at least'' 117 characters<ref name="why_117_chars"> ''' Why do silent payment addresses need at least 117 characters?''' A silent payment address is a bech32m encoding comprised of the following parts:
+
+
+* HRP [2-3 characters]
+* separator [1 character]
+* version [1-2 characters]
+* payload, 66 bytes concatenated pubkeys [ceil(66*8/5) = 106 characters]
+* checksum [6 characters]
+
+
+For a silent payments v0 address, this results in a 117-character address when using a 3-character HRP. Future versions of silent payment addresses may add to the payload, which is why a 1023-character limit is suggested.</ref> and allows versions up to 31. Additionally, since higher versions may add to the data field, it is recommended implementations use a limit of 1023 characters (see [https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#checksum-design BIP173: Checksum design] for more details).
+
+=== Inputs For Shared Secret Derivation ===
+
+While any UTXO with known output scripts can be used to fund the transaction, the sender and receiver MUST use inputs from the following list when deriving the shared secret:
+
+* ''P2TR''
+* ''P2WPKH''
+* ''P2SH-P2WPKH''
+* ''P2PKH''
+
+Inputs with conditional branches or multiple public keys (e.g. ''CHECKMULTISIG'') are excluded from shared secret derivation as this introduces malleability and would allow a sender to re-sign with a different set of public keys after the silent payment output has been derived. This is not a concern when the sender controls all of the inputs, but is an issue for CoinJoins and other collaborative protocols, where a malicious participant can participate in deriving the silent payment address with one set of keys and then re-broadcast the transaction with signatures for a different set of public keys. P2TR can have hidden conditional branches (script path), but we work around this by using only the output public key.
+
+For all of the output types listed, only X-only and compressed public keys are permitted<ref name="why_only_compressed_public_keys">''' Why only compressed public keys ''' Uncompressed and hybrid public keys are less common than compressed keys and generally considered to be a bad idea due to their blockspace inefficiency. Additionally, [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#restrictions-on-public-key-type BIP143] recommends restricting P2WPKH inputs to compressed keys as a default policy.</ref>.
+
+''' P2TR '''
+
+'' Keypath spend ''
+
+ witness: <signature>
+ scriptSig: (empty)
+ scriptPubKey: 1 <32-byte-x-only-key>
+ (0x5120{32-byte-x-only-key})
+
+The sender uses the private key corresponding to the taproot output key (i.e. the tweaked private key). This can be a single private key or an aggregate key (e.g. taproot outputs using MuSig or FROST)<ref name="musig_frost_support">'''Are key aggregation techniques like FROST and MuSig supported?''' While we do not recommend it due to lack of a security proof (except if all participants are trusted or are the same entity), any taproot output able to do a key path theoretically is supported. Any offline key aggregation technique can be used, such as FROST or MuSig. This would require participants to perform the ECDH step collaboratively e.g. ''ECDH = a<sub>1</sub>·B<sub>scan</sub> + a<sub>2</sub>·B<sub>scan</sub> + ... + a<sub>t</sub>·B<sub>scan</sub>'' and ''P = B<sub>spend</sub> + hash(input_hash·ECDH || 0)·G''. Additionally, it may be necessary for the participants to provide a DLEQ proof to ensure they are not acting maliciously.</ref>. The receiver obtains the public key from the ''scriptPubKey'' (i.e. the taproot output key).
+
+'' Script path spend ''
+
+ witness: <optional witness items> <leaf script> <control block>
+ scriptSig: (empty)
+ scriptPubKey: 1 <32-byte-x-only-key>
+ (0x5120{32-byte-x-only-key})
+
+Same as a keypath spend, the sender MUST use the private key corresponding to the taproot output key. If this key is not available, the output cannot be included as an input to the transaction. Same as a keypath spend, the receiver obtains the public key from the ''scriptPubKey'' (i.e. the taproot output key)<ref name="why_always_output_pubkey">''' Why not skip all taproot script path spends? ''' This causes malleability issues for CoinJoins. If the silent payments protocol skipped taproot script path spends, this would allow an attacker to join a CoinJoin round, participate in deriving the silent payment address using the tweaked private key for a key path spend, and then broadcast their own version of the transaction using the script path spend. If the receiver were to only consider key path spends, they would skip the attacker's script path spend input when deriving the shared secret and not be able to find the funds. Additionally, there may be scenarios where the sender can perform ECDH with the key path private key but spends the output using the script path.</ref>.
+
+The one exception is script path spends that use NUMS point ''H'' as their internal key (where ''H'' is constructed by taking the hash of the standard uncompressed encoding of the secp256k1 base point ''G'' as X coordinate, see [https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#constructing-and-spending-taproot-outputs BIP341: Constructing and spending Taproot outputs] for more details), in which case the input will be skipped for the purposes of shared secret derivation<ref name="why_ignore_h">'''Why skip outputs with H as the internal taproot key?''' If use cases get popularized where the taproot key path cannot be used, these outputs can still be included without getting in the way of making a silent payment, provided they specifically use H as their internal taproot key.</ref>. The receiver determines whether or not to skip the input by checking in the control block if the taproot internal key is equal to ''H''.
+
+''' P2WPKH '''
+
+ witness: <signature> <33-byte-compressed-key>
+ scriptSig: (empty)
+ scriptPubKey: 0 <20-byte-key-hash>
+ (0x0014{20-byte-key-hash})
+
+The sender performs the tweak using the private key for the output and the receiver obtains the public key as the last witness item.
+
+''' P2SH-P2WPKH '''
+
+ witness: <signature> <33-byte-compressed-key>
+ scriptSig: <0 <20-byte-key-hash>>
+ (0x160014{20-byte-key-hash})
+ scriptPubKey: HASH160 <20-byte-script-hash> EQUAL
+ (0xA914{20-byte-script-hash}87)
+
+The sender performs the tweak using the private key for the nested ''P2WPKH'' output and the receiver obtains the public key as the last witness item.
+
+''' P2PKH '''
+
+ scriptSig: <signature> <33-byte-compressed-key>
+ scriptPubKey: OP_DUP HASH160 <20-byte-key-hash> OP_EQUALVERIFY OP_CHECKSIG
+ (0x76A914{20-byte-key-hash}88AC)
+
+The receiver obtains the public key from the ''scriptSig''. The receiver MUST parse the ''scriptSig'' for the public key, even if the ''scriptSig'' does not match the template specified (e.g. <code><dummy> OP_DROP <Signature> <Public Key></code>). This is to address the [https://en.bitcoin.it/wiki/Transaction_malleability third-party malleability of ''P2PKH'' ''scriptSigs''].
+
+=== Input hash ===
+
+The sender and receiver MUST calculate an input hash for the transaction in the following manner:
+
+* Let ''A = A<sub>1</sub> + A<sub>2</sub> + ... + A<sub>n</sub>'', where each ''A<sub>i</sub>'' is the public key of an input from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list<ref name="why_include_A"></ref>
+* Let ''input_hash = hash<sub>BIP0352/Inputs</sub>(outpoint<sub>L</sub> || A)'', where ''outpoint<sub>L</sub>'' is the smallest outpoint lexicographically by txid and vout used in the transaction<ref name="why_smallest_outpoint"></ref>
+
+=== Sender ===
+
+==== Selecting inputs ====
+
+The sending wallet performs coin selection as usual with the following restrictions:
+
+* At least one input MUST be from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list
+* Exclude inputs with SegWit version > 1 (see ''[[#scanning-silent-payment-eligible-transactions|Scanning silent payment eligible transactions]]'')
+* For each taproot output spent the sending wallet MUST have access to the private key corresponding to the taproot output key, unless ''H'' is used as the internal public key
+
+==== Creating outputs ====
+
+After the inputs have been selected, the sender can create one or more outputs for one or more silent payment addresses in the following manner:
+
+* Generate the ''input_hash'' with the smallest outpoint lexicographically, using the method described above
+* Collect the private keys for each input from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list
+* For each private key ''a<sub>i</sub>'' corresponding to a [https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki BIP341] taproot output, check that the private key produces a point with an even Y coordinate and negate the private key if not<ref name="why_negate_taproot_private_keys">'''Why do taproot private keys need to be checked?''' Recall from [https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki BIP340] that each X-only public key has two corresponding private keys, ''d'' and ''n - d''. To maintain parity between sender and receiver, it is necessary to use the private key corresponding to the even Y coordinate when performing the ECDH step since the receiver will assume the even Y coordinate when summing the taproot X-only public keys.</ref>
+* Let ''a = a<sub>1</sub> + a<sub>2</sub> + ... + a<sub>n</sub>'', where each ''a<sub>i</sub>'' has been negated if necessary
+* Group receiver silent payment addresses by ''B<sub>scan</sub>'' (e.g. each group consists of one ''B<sub>scan</sub>'' and one or more ''B<sub>m</sub>'')
+* For each group:
+** Let ''ecdh_shared_secret = input_hash·a·B<sub>scan</sub>''
+** Let ''k = 0''
+** For each ''B<sub>m</sub>'' in the group:
+*** Let ''t<sub>k</sub> = hash<sub>BIP0352/SharedSecret</sub>(ser<sub>P</sub>(ecdh_shared_secret) || ser<sub>32</sub>(k))''
+**** If ''t<sub>k</sub>'' is not valid tweak, i.e., if ''t<sub>k</sub> = 0'' or ''t<sub>k</sub>'' is larger or equal to the secp256k1 group order, fail
+*** Let ''P<sub>mn</sub> = B<sub>m</sub> + t<sub>k</sub>·G''
+*** Encode ''P<sub>mn</sub>'' as a [https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki BIP341] taproot output
+*** Optionally, repeat with k++ to create additional outputs for the current ''B<sub>m</sub>''
+*** If no additional outputs are required, continue to the next ''B<sub>m</sub>'' with ''k++''<ref name="why_not_the_same_tn">''' Why not re-use ''t<sub>k</sub>'' when paying different labels to the same receiver?''' If paying the same entity but to two separate labeled addresses in the same transaction without incrementing ''k'', an outside observer could subtract the two output values and observe that this value is the same as the difference between two published silent payment addresses and learn who the recipient is.</ref>
+** Optionally, if the sending wallet implements receiving silent payments, it can create change outputs by sending to its own silent payment address using label ''m = 0'', following the steps above
+
+=== Receiver ===
+
+==== Key Derivation ====
+
+Two keys are needed to create a silent payments address: the spend key and the scan key. To ensure compatibility, wallets MAY use BIP32 derivation with the following derivation paths for the spend and scan key. When using BIP32 derivation, wallet software MUST use hardened derivation<ref name="bip32_derivation">'''Why use BIP32 hardened derivation?''' Using BIP32 derivation allows users to add silent payments to an existing master seed. It also ensures that a user's silent payment funds are recoverable in any BIP32/BIP43 compatible wallet. Using hardened derivation ensures that it is safe to export the scan private key without exposing the master key or spend private key.</ref> for both the spend and scan key.
+
+A scan and spend key pair using BIP32 derivation are defined (taking inspiration from [https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki BIP44]) in the following manner:
+
+ scan_private_key: m / purpose' / coin_type' / account' / 1' / 0
+ spend_private_key: m / purpose' / coin_type' / account' / 0' / 0
+
+<code>purpose</code> is a constant set to ''352'' following the BIP43 recommendation. Refer to [https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki BIP43] and [https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki BIP44] for more details.
+
+==== Scanning ====
+
+If each of the checks in ''[[#scanning-silent-payment-eligible-transactions|Scanning silent payment eligible transactions]]'' passes, the receiving wallet must:
+
+* Generate the ''input_hash'' with the smallest outpoint lexicographically, using the method described above
+* Let ''A = A<sub>1</sub> + A<sub>2</sub> + ... + A<sub>n</sub>'', where each ''A<sub>i</sub>'' is the public key of an input from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list
+* Let ''ecdh_shared_secret = input_hash·b<sub>scan</sub>·A''
+* Check for outputs:
+** Let ''outputs_to_check'' be the taproot output keys from all taproot outputs in the transaction (spent and unspent).
+** Starting with ''k = 0'':
+*** Let ''t<sub>k</sub> = hash<sub>BIP0352/SharedSecret</sub>(ser<sub>P</sub>(ecdh_shared_secret) || ser<sub>32</sub>(k))''
+**** If ''t<sub>k</sub>'' is not valid tweak, i.e., if ''t<sub>k</sub> = 0'' or ''t<sub>k</sub>'' is larger or equal to the secp256k1 group order, fail
+*** Compute ''P<sub>k</sub> = B<sub>spend</sub> + t<sub>k</sub>·G''
+*** For each ''output'' in ''outputs_to_check'':
+**** If ''P<sub>k</sub>'' equals ''output'':
+***** Add ''P<sub>k</sub>'' to the wallet
+***** Remove ''output'' from ''outputs_to_check'' and rescan ''outputs_to_check'' with ''k++''
+**** Else, check for labels (always check for the change label, i.e. ''hash<sub>BIP0352/Label</sub>(ser<sub>256</sub>(b<sub>scan</sub>) || ser<sub>32</sub>(m))'' where ''m = 0'')<ref name="precompute_labels">''' Why precompute labels?''' Precomputing the labels is not strictly necessary: a wallet could track the max number of labels it has used (call it ''M'') and scan for labels by adding ''hash(b<sub>scan</sub> || m)·G'' to ''P<sub>0</sub>'' for each label ''m'' up to ''M'' and comparing to the transaction outputs. This is more performant than precomputing the labels and checking via subtraction in cases where the number of eligible outputs exceeds the number of labels in use. In practice this will mainly apply to users that choose never to use labels, or users that use a single label for generating silent payment change outputs. If using a large number of labels, the wallet would need to add all possible labels to each output. This ends up being ''n·M'' additions, where ''n'' is the number of outputs in the transaction and ''M'' is the number of labels in the wallet. By precomputing the labels, the wallet only needs to compute ''hash(b<sub>scan</sub> || m)·G'' once when creating the labeled address and can determine if a label was used via a lookup, rather than adding each label to each output.</ref>:
+***** Compute ''label = output - P<sub>k</sub>''
+***** Check if ''label'' exists in the list of labels used by the wallet
+***** If a match is found:
+****** Add ''P<sub>k</sub> + label'' to the wallet
+****** Remove ''output'' from ''outputs_to_check'' and rescan ''outputs_to_check'' with ''k++''
+***** If a label is not found, negate ''output'' and check a second time<ref name="negate_output">''' Why negate the output?''' Unfortunately taproot outputs are X-only, meaning we don't know what the correct Y coordinate is. This causes this specific calculation to fail 50% of the time, so we need to repeat it with the other Y coordinate by negating the output.</ref>
+*** If no matches are found, stop
+
+==== Spending ====
+
+Recall that a silent payment output is of the form ''B<sub>spend</sub> + t<sub>k</sub>·G + hash<sub>BIP0352/Label</sub>(ser<sub>256</sub>(b<sub>scan</sub>) || ser<sub>32</sub>(m))·G'', where ''hash<sub>BIP0352/Label</sub>(ser<sub>256</sub>(b<sub>scan</sub>) || ser<sub>32</sub>(m))·G'' is an optional label. To spend a silent payment output:
+
+* Let ''d = (b<sub>spend</sub> + t<sub>k</sub> + hash<sub>BIP0352/Label</sub>(ser<sub>256</sub>(b<sub>scan</sub>) || ser<sub>32</sub>(m))) mod n'', where ''hash<sub>BIP0352/Label</sub>(ser<sub>256</sub>(b<sub>scan</sub>) || ser<sub>32</sub>(m))'' is the optional label
+* Spend the [https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki BIP341] output with the private key ''d''
+
+==== Backup and Recovery ====
+
+Since each silent payment output address is derived independently, regular backups are recommended. When recovering from a backup, the wallet will need to scan since the last backup to detect new payments.
+
+If using a seed/seed phrase only style backup, the user can recover the wallet's unspent outputs from the UTXO set (i.e. only scanning transactions with at least one unspent taproot output) and can recover the full wallet history by scanning the blockchain starting from the wallet birthday. If a wallet uses labels, this information SHOULD be included in the backup. If the user does not know whether labels were used, it is strongly recommended they always precompute and check a large number of labels (e.g. 100k labels) to use when re-scanning. This ensures that the wallet can recover all funds from only a seed/seed phrase backup. The change label should simply always be scanned for, even when no other labels were used. This ensures the use of a change label is not critical for backups and maximizes cross-compatibility.
+
+== Backward Compatibility ==
+
+Silent payments introduces a new address format and protocol for sending and as such is not compatible with older wallet software or wallets which have not implemented the silent payments protocol.
+
+== Test Vectors ==
+
+A [[bip-0352/send_and_receive_test_vectors.json|collection of test vectors in JSON format]] are provided, along with a [[bip-0352/reference.py|python reference implementation]]. Each test vector consists of a sending test case and corresponding receiving test case. This is to allow sending and receiving to be implemented separately. To ensure determinism while testing, sort the array of ''B<sub>m</sub>'' by amount (see the [[bip-0352/reference.py|reference implementation]]). Test cases use the following schema:
+
+''' test_case '''
+
+ {
+ "comment": "Comment describing the behavior being tested",
+ "sending": [<array of sender test objects>],
+ "receiving": [<array of recipient test objects>],
+ }
+
+''' sender '''
+
+ {
+ "given": {
+ "vin": [<array of vin objects with an added field for the private key. These objects are structured to match the `vin` output field from `getrawtransaction verbosity=2`>],
+ "recipients": [<array of strings, where each string is a bech32m encoding representing a silent payment address>]
+ },
+ "expected": {
+ "outputs": [<array of strings, where each string is a hex encoding of 32-byte X-only public key; contains all possible output sets, test must match a subset of size `n_outputs`>],
+ "n_outputs": <integer for the exact number of expected outputs>,
+ },
+ }
+
+''' recipient '''
+
+ {
+ "given": {
+ "vin": [<array of vin objects. These objects are structured to match the `vin` output field from `getrawtransaction verbosity=2`>],
+ "key_material": {
+ "scan_priv_key": <hex encoded scan private key>,
+ "spend_priv_key": <hex encoded spend private key>,
+ }
+ "labels": [<array of ints, representing labels the receiver has used>],
+ },
+ "expected": {
+ "addresses": [<array of bech32m strings, one for the silent payment address and each labeled address (if used)>],
+ "outputs": [<array of outputs with tweak and signature; contains all possible output sets, tester must match a subset of size `n_outputs`>
+ {
+ "priv_key_tweak": <hex encoded private key tweak data>,
+ "pub_key": <hex encoded X-only public key>,
+ "signature": <hex encoded signature for the output (produced with spend_priv_key + priv_key_tweak)>
+ },
+ ...
+ ],
+ "n_outputs": <integer for the exact number of expected outputs>
+ }
+ }
+
+Wallets should include inputs not in the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list when testing to ensure that only inputs from the list are being used for shared secret derivation. Additionally, receiving wallets should include non-silent payment outputs for themselves in testing to ensure silent payments scanning does not interfere with regular outputs detection.
+
+=== Functional tests ===
+
+Below is a list of functional tests which should be included in sending and receiving implementations.
+
+==== Sending ====
+
+* Ensure taproot outputs are excluded during coin selection if the sender does not have access to the key path private key (unless using ''H'' as the taproot internal key)
+* Ensure the silent payment address is re-derived if inputs are added or removed during RBF
+
+==== Receiving ====
+
+* Ensure the public key can be extracted from non-standard ''P2PKH'' scriptSigs
+* Ensure taproot script path spends are included, using the taproot output key (unless ''H'' is used as the taproot internal key)
+* Ensure the scanner can extract the public key from each of the input types supported (e.g. ''P2WPKH'', ''P2SH-P2WPKH'', etc.)
+
+== Appendix A: Light Client Support ==
+
+This section proposes a few ideas for how light clients could support scanning for incoming silent payments (sending is fairly straightforward) in ways that preserve bandwidth and privacy. While this is out of scope for the current BIP, it is included to motivate further research into this topic. In this context, a light client refers to any bitcoin wallet client which does not process blocks and does not have a direct connection to a node which does process blocks (e.g. a full node). Based on this definition, clients that directly connect to a personal electrum server or a bitcoin node are not light clients.
+
+This distinction makes the problem for light clients more clear: light clients need a way to source the necessary data for performing the tweaks and a way of determining if any of the generated outputs exist in a block.
+
+=== Tweak Data ===
+
+Recall that a silent payment eligible transaction follows [[#scanning-silent-payment-eligible-transactions|certain conditions]] and should have at least one unspent taproot output. Full nodes (or any index server backed by a full node, such as electrum server) can build an index which collects all of the eligible public keys for a silent payments eligible transaction, sums them up, multiplies the sum by the ''input_hash'', and serves them to clients. This would be 33 bytes per silent payment eligible transaction.
+
+For a typical bitcoin block of ~3500 txs, lets assume every transaction is a silent payments eligible transaction. This means a client would need to request ''33 bytes * 3500'' of data per block (roughly 100 kB per block). If a client were to request data for every block, this would amount to ~450 MB per month, assuming 100% taproot usage and all outputs remain unspent for > 1 month. As of today, these numbers are closer to 2–10 kB per block (10–50 MB per month)<ref name="appendix_data">''' Data for Appendix A ''' These numbers are based on data from January 2023 until June 2023 (the last 6 months of data at time time of writing). See [https://github.com/josibake/bitcoin-data-analysis/blob/main/notebooks/silent-payments-light-client-data.ipynb Silent payments light client data] for the full analysis.</ref>.
+
+=== Transaction cut-through ===
+
+It is unlikely a light client would need to scan every block and as such can take advantage of transaction cut-through, depending on how often they choose to scan for new blocks. Empirically, ~75% of transactions with at least one unspent taproot output will have spent all taproot UTXOs in 326 blocks or less<ref name="appendix_data"></ref>. This means a client which only scans once every 3 days could ''significantly'' cut down on the number of blocks and the number of transactions per block that they need to request by only asking for data on transactions that were created since their last scan and that still have at least one unspent taproot output as of the current block height. Assuming 100% taproot usage, a client that scans once a month would likely only need around 50 MB worth of data. Based on current taproot adoption, a light client scanning once every 3 days would use roughly 15 MB per month and a client scanning once per month would use less than 5 MB per month.
+
+[[File:bip-0352/scan_data_downloader_per_month.png]]
+
+=== BIP158 ===
+
+Once a light client has the tweak data for a block, they can determine whether or not an output to them exists in the block using BIP158 block filters. Per BIP158, they would then request the entire block and add the transaction to their wallet, though it maybe be possible to only request the prevout txids and vouts for all transactions with at least one taproot output, along with the scriptPubKeys and amounts. This would allow the client to download the necessary data for constructing a spending transaction, without downloading the entire block. How this affects the security assumptions of BIP158 is an open question.
+
+=== Out-of-band notifications ===
+
+Assuming a secure messaging protocol exists, the sender can send an encrypted (using the scan public key of the silent payment address) notification to the receiver with the following information:
+* The spend public key (communicates the label)
+* The shared secret portion of the private key (i.e ''hash(ecdh_shared_secret || k)'')
+* The outpoint and amount (so it's immediately spendable)
+
+It is important to note that these notifications are not required. At any point, the receiver can fall back to scanning for silent payment transactions if they don't trust the notifications they are receiving, are being spammed with fake notifications, or if they are concerned that they are not receiving notifications.
+
+A malicious notification could potentially cause the following issues:
+
+* You did not actually receive money to the stated key
+** This can be probabilistically resolved by matching the key against the BIP158 block filters and assuming it's not a false positive, or fully resolved by downloading the block
+* You received money but the outpoint or amount is incorrect, so attempts to spend it will fail or cause you to overpay fees
+** There doesn't seem to be much motivation for malicious senders to ever do this, but light clients need to take into account that this can occur and should ideally check for it by downloading the block
+* The private key is correct but it wasn't actually derived using the silent payment protocol, causing recovery from back-up to fail (unsafe - no implementation should ever allow this)
+** This can be detected by downloading the tweak data of the corresponding block and should be resolved by immediately spending the output
+
+Wallet designers can choose which tradeoffs they find appropriate. For example, a wallet could check the block filter to at least probabilistically confirm the likely existence of the UTXO, thus efficiently cutting down on spam. The payment could then be marked as unconfirmed until a scan is performed and the existence of the UTXO in accordance to the silent payment specification is verified.
+
+
+== Acknowledgements ==
+
+This document is the result of many discussions and contains contributions by a number of people. The authors wish to thank all those who provided valuable feedback and reviews, including the participants of the [https://gist.github.com/RubenSomsen/21c477c90c942acf45f8e8f5c1ad4fae BIP47 Prague discussion], the [https://github.com/josibake/silent-payments-workshop Advancing Bitcoin silent payments Workshop], and [https://btctranscripts.com/bitcoin-core-dev-tech/2023-04/2023-04-26-silent-payments/ coredev]. The authors would like to also thank [https://github.com/w0xlt w0xlt] for writing the initial implementation of silent payments.
+
+== Rationale and References ==
+<references/>
+
diff --git a/bip-0352/bech32m.py b/bip-0352/bech32m.py
new file mode 100644
index 0000000..795e153
--- /dev/null
+++ b/bip-0352/bech32m.py
@@ -0,0 +1,135 @@
+# Copyright (c) 2017, 2020 Pieter Wuille
+#
+# 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.
+
+"""Reference implementation for Bech32/Bech32m and segwit addresses."""
+
+
+from enum import Enum
+
+class Encoding(Enum):
+ """Enumeration type to list the various supported encodings."""
+ BECH32 = 1
+ BECH32M = 2
+
+CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
+BECH32M_CONST = 0x2bc830a3
+
+def bech32_polymod(values):
+ """Internal function that computes the Bech32 checksum."""
+ generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
+ chk = 1
+ for value in values:
+ top = chk >> 25
+ chk = (chk & 0x1ffffff) << 5 ^ value
+ for i in range(5):
+ chk ^= generator[i] if ((top >> i) & 1) else 0
+ return chk
+
+
+def bech32_hrp_expand(hrp):
+ """Expand the HRP into values for checksum computation."""
+ return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp]
+
+
+def bech32_verify_checksum(hrp, data):
+ """Verify a checksum given HRP and converted data characters."""
+ const = bech32_polymod(bech32_hrp_expand(hrp) + data)
+ if const == 1:
+ return Encoding.BECH32
+ if const == BECH32M_CONST:
+ return Encoding.BECH32M
+ return None
+
+def bech32_create_checksum(hrp, data, spec):
+ """Compute the checksum values given HRP and data."""
+ values = bech32_hrp_expand(hrp) + data
+ const = BECH32M_CONST if spec == Encoding.BECH32M else 1
+ polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ const
+ return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]
+
+
+def bech32_encode(hrp, data, spec):
+ """Compute a Bech32 string given HRP and data values."""
+ combined = data + bech32_create_checksum(hrp, data, spec)
+ return hrp + '1' + ''.join([CHARSET[d] for d in combined])
+
+def bech32_decode(bech):
+ """Validate a Bech32/Bech32m string, and determine HRP and data."""
+ if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or
+ (bech.lower() != bech and bech.upper() != bech)):
+ return (None, None, None)
+ bech = bech.lower()
+ pos = bech.rfind('1')
+
+ # remove the requirement that bech32m be less than 90 chars
+ if pos < 1 or pos + 7 > len(bech):
+ return (None, None, None)
+ if not all(x in CHARSET for x in bech[pos+1:]):
+ return (None, None, None)
+ hrp = bech[:pos]
+ data = [CHARSET.find(x) for x in bech[pos+1:]]
+ spec = bech32_verify_checksum(hrp, data)
+ if spec is None:
+ return (None, None, None)
+ return (hrp, data[:-6], spec)
+
+def convertbits(data, frombits, tobits, pad=True):
+ """General power-of-2 base conversion."""
+ acc = 0
+ bits = 0
+ ret = []
+ maxv = (1 << tobits) - 1
+ max_acc = (1 << (frombits + tobits - 1)) - 1
+ for value in data:
+ if value < 0 or (value >> frombits):
+ return None
+ acc = ((acc << frombits) | value) & max_acc
+ bits += frombits
+ while bits >= tobits:
+ bits -= tobits
+ ret.append((acc >> bits) & maxv)
+ if pad:
+ if bits:
+ ret.append((acc << (tobits - bits)) & maxv)
+ elif bits >= frombits or ((acc << (tobits - bits)) & maxv):
+ return None
+ return ret
+
+
+def decode(hrp, addr):
+ """Decode a segwit address."""
+ hrpgot, data, spec = bech32_decode(addr)
+ if hrpgot != hrp:
+ return (None, None)
+ decoded = convertbits(data[1:], 5, 8, False)
+ if decoded is None or len(decoded) < 2:
+ return (None, None)
+ if data[0] > 16:
+ return (None, None)
+ return (data[0], decoded)
+
+
+def encode(hrp, witver, witprog):
+ """Encode a segwit address."""
+ spec = Encoding.BECH32 if witver == 0 else Encoding.BECH32M
+ ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5), spec)
+ if decode(hrp, ret) == (None, None):
+ return None
+ return ret
diff --git a/bip-0352/bitcoin_utils.py b/bip-0352/bitcoin_utils.py
new file mode 100644
index 0000000..443c096
--- /dev/null
+++ b/bip-0352/bitcoin_utils.py
@@ -0,0 +1,158 @@
+import hashlib
+import struct
+from io import BytesIO
+from secp256k1 import ECKey
+from typing import Union
+
+
+def from_hex(hex_string):
+ """Deserialize from a hex string representation (e.g. from RPC)"""
+ return BytesIO(bytes.fromhex(hex_string))
+
+
+def ser_uint32(u: int) -> bytes:
+ return u.to_bytes(4, "big")
+
+
+def ser_uint256(u):
+ return u.to_bytes(32, 'little')
+
+
+def deser_uint256(f):
+ return int.from_bytes(f.read(32), 'little')
+
+
+def deser_txid(txid: str):
+ # recall that txids are serialized little-endian, but displayed big-endian
+ # this means when converting from a human readable hex txid, we need to first
+ # reverse it before deserializing it
+ dixt = "".join(map(str.__add__, txid[-2::-2], txid[-1::-2]))
+ return bytes.fromhex(dixt)
+
+
+def deser_compact_size(f: BytesIO):
+ view = f.getbuffer()
+ nbytes = view.nbytes;
+ view.release()
+ if (nbytes == 0):
+ return 0 # end of stream
+
+ nit = struct.unpack("<B", f.read(1))[0]
+ if nit == 253:
+ nit = struct.unpack("<H", f.read(2))[0]
+ elif nit == 254:
+ nit = struct.unpack("<I", f.read(4))[0]
+ elif nit == 255:
+ nit = struct.unpack("<Q", f.read(8))[0]
+ return nit
+
+
+def deser_string(f: BytesIO):
+ nit = deser_compact_size(f)
+ return f.read(nit)
+
+
+def deser_string_vector(f: BytesIO):
+ nit = deser_compact_size(f)
+ r = []
+ for _ in range(nit):
+ t = deser_string(f)
+ r.append(t)
+ return r
+
+
+class COutPoint:
+ __slots__ = ("hash", "n",)
+
+ def __init__(self, hash=b"", n=0,):
+ self.hash = hash
+ self.n = n
+
+ def serialize(self):
+ r = b""
+ r += self.hash
+ r += struct.pack("<I", self.n)
+ return r
+
+ def deserialize(self, f):
+ self.hash = f.read(32)
+ self.n = struct.unpack("<I", f.read(4))[0]
+
+
+class VinInfo:
+ __slots__ = ("outpoint", "scriptSig", "txinwitness", "prevout", "private_key")
+
+ def __init__(self, outpoint=None, scriptSig=b"", txinwitness=None, prevout=b"", private_key=None):
+ if outpoint is None:
+ self.outpoint = COutPoint()
+ else:
+ self.outpoint = outpoint
+ if txinwitness is None:
+ self.txinwitness = CTxInWitness()
+ else:
+ self.txinwitness = txinwitness
+ if private_key is None:
+ self.private_key = ECKey()
+ else:
+ self.private_key = private_key
+ self.scriptSig = scriptSig
+ self.prevout = prevout
+
+
+class CScriptWitness:
+ __slots__ = ("stack",)
+
+ def __init__(self):
+ # stack is a vector of strings
+ self.stack = []
+
+ def is_null(self):
+ if self.stack:
+ return False
+ return True
+
+
+class CTxInWitness:
+ __slots__ = ("scriptWitness",)
+
+ def __init__(self):
+ self.scriptWitness = CScriptWitness()
+
+ def deserialize(self, f: BytesIO):
+ self.scriptWitness.stack = deser_string_vector(f)
+ return self
+
+ def is_null(self):
+ return self.scriptWitness.is_null()
+
+
+def hash160(s: Union[bytes, bytearray]) -> bytes:
+ return hashlib.new("ripemd160", hashlib.sha256(s).digest()).digest()
+
+
+def is_p2tr(spk: bytes) -> bool:
+ if len(spk) != 34:
+ return False
+ # OP_1 OP_PUSHBYTES_32 <32 bytes>
+ return (spk[0] == 0x51) & (spk[1] == 0x20)
+
+
+def is_p2wpkh(spk: bytes) -> bool:
+ if len(spk) != 22:
+ return False
+ # OP_0 OP_PUSHBYTES_20 <20 bytes>
+ return (spk[0] == 0x00) & (spk[1] == 0x14)
+
+
+def is_p2sh(spk: bytes) -> bool:
+ if len(spk) != 23:
+ return False
+ # OP_HASH160 OP_PUSHBYTES_20 <20 bytes> OP_EQUAL
+ return (spk[0] == 0xA9) & (spk[1] == 0x14) & (spk[-1] == 0x87)
+
+
+def is_p2pkh(spk: bytes) -> bool:
+ if len(spk) != 25:
+ return False
+ # OP_DUP OP_HASH160 OP_PUSHBYTES_20 <20 bytes> OP_EQUALVERIFY OP_CHECKSIG
+ return (spk[0] == 0x76) & (spk[1] == 0xA9) & (spk[2] == 0x14) & (spk[-2] == 0x88) & (spk[-1] == 0xAC)
diff --git a/bip-0352/reference.py b/bip-0352/reference.py
new file mode 100755
index 0000000..c98dac8
--- /dev/null
+++ b/bip-0352/reference.py
@@ -0,0 +1,335 @@
+#!/usr/bin/env python3
+# For running the test vectors, run this script:
+# ./reference.py send_and_receive_test_vectors.json
+
+import hashlib
+import json
+from typing import List, Tuple, Dict, cast
+from sys import argv, exit
+from functools import reduce
+from itertools import permutations
+
+# local files
+from bech32m import convertbits, bech32_encode, decode, Encoding
+from secp256k1 import ECKey, ECPubKey, TaggedHash, NUMS_H
+from bitcoin_utils import (
+ deser_txid,
+ from_hex,
+ hash160,
+ is_p2pkh,
+ is_p2sh,
+ is_p2wpkh,
+ is_p2tr,
+ ser_uint32,
+ COutPoint,
+ CTxInWitness,
+ VinInfo,
+ )
+
+
+def get_pubkey_from_input(vin: VinInfo) -> ECPubKey:
+ if is_p2pkh(vin.prevout):
+ # skip the first 3 op_codes and grab the 20 byte hash
+ # from the scriptPubKey
+ spk_hash = vin.prevout[3:3 + 20]
+ for i in range(len(vin.scriptSig), 0, -1):
+ if i - 33 >= 0:
+ # starting from the back, we move over the scriptSig with a 33 byte
+ # window (to match a compressed pubkey). we hash this and check if it matches
+ # the 20 byte has from the scriptPubKey. for standard scriptSigs, this will match
+ # right away because the pubkey is the last item in the scriptSig.
+ # if its a non-standard (malleated) scriptSig, we will still find the pubkey if its
+ # a compressed pubkey.
+ #
+ # note: this is an incredibly inefficient implementation, for demonstration purposes only.
+ pubkey_bytes = vin.scriptSig[i - 33:i]
+ pubkey_hash = hash160(pubkey_bytes)
+ if pubkey_hash == spk_hash:
+ pubkey = ECPubKey().set(pubkey_bytes)
+ if (pubkey.valid) & (pubkey.compressed):
+ return pubkey
+ if is_p2sh(vin.prevout):
+ redeem_script = vin.scriptSig[1:]
+ if is_p2wpkh(redeem_script):
+ pubkey = ECPubKey().set(vin.txinwitness.scriptWitness.stack[-1])
+ if (pubkey.valid) & (pubkey.compressed):
+ return pubkey
+ if is_p2wpkh(vin.prevout):
+ txin = vin.txinwitness
+ pubkey = ECPubKey().set(txin.scriptWitness.stack[-1])
+ if (pubkey.valid) & (pubkey.compressed):
+ return pubkey
+ if is_p2tr(vin.prevout):
+ witnessStack = vin.txinwitness.scriptWitness.stack
+ if (len(witnessStack) >= 1):
+ if (len(witnessStack) > 1 and witnessStack[-1][0] == 0x50):
+ # Last item is annex
+ witnessStack.pop()
+
+ if (len(witnessStack) > 1):
+ # Script-path spend
+ control_block = witnessStack[-1]
+ # control block is <control byte> <32 byte internal key> and 0 or more <32 byte hash>
+ internal_key = control_block[1:33]
+ if (internal_key == NUMS_H.to_bytes(32, 'big')):
+ # Skip if NUMS_H
+ return ECPubKey()
+
+ pubkey = ECPubKey().set(vin.prevout[2:])
+ if (pubkey.valid) & (pubkey.compressed):
+ return pubkey
+
+
+ return ECPubKey()
+
+
+def get_input_hash(outpoints: List[COutPoint], sum_input_pubkeys: ECPubKey) -> bytes:
+ lowest_outpoint = sorted(outpoints, key=lambda outpoint: outpoint.serialize())[0]
+ return TaggedHash("BIP0352/Inputs", lowest_outpoint.serialize() + cast(bytes, sum_input_pubkeys.get_bytes(False)))
+
+
+
+def encode_silent_payment_address(B_scan: ECPubKey, B_m: ECPubKey, hrp: str = "tsp", version: int = 0) -> str:
+ data = convertbits(cast(bytes, B_scan.get_bytes(False)) + cast(bytes, B_m.get_bytes(False)), 8, 5)
+ return bech32_encode(hrp, [version] + cast(List[int], data), Encoding.BECH32M)
+
+
+def generate_label(b_scan: ECKey, m: int) -> bytes:
+ return TaggedHash("BIP0352/Label", b_scan.get_bytes() + ser_uint32(m))
+
+
+def create_labeled_silent_payment_address(b_scan: ECKey, B_spend: ECPubKey, m: int, hrp: str = "tsp", version: int = 0) -> str:
+ G = ECKey().set(1).get_pubkey()
+ B_scan = b_scan.get_pubkey()
+ B_m = B_spend + generate_label(b_scan, m) * G
+ labeled_address = encode_silent_payment_address(B_scan, B_m, hrp, version)
+
+ return labeled_address
+
+
+def decode_silent_payment_address(address: str, hrp: str = "tsp") -> Tuple[ECPubKey, ECPubKey]:
+ _, data = decode(hrp, address)
+ if data is None:
+ return ECPubKey(), ECPubKey()
+ B_scan = ECPubKey().set(data[:33])
+ B_spend = ECPubKey().set(data[33:])
+
+ return B_scan, B_spend
+
+
+def create_outputs(input_priv_keys: List[Tuple[ECKey, bool]], input_hash: bytes, recipients: List[str], hrp="tsp") -> List[str]:
+ G = ECKey().set(1).get_pubkey()
+ negated_keys = []
+ for key, is_xonly in input_priv_keys:
+ k = ECKey().set(key.get_bytes())
+ if is_xonly and k.get_pubkey().get_y() % 2 != 0:
+ k.negate()
+ negated_keys.append(k)
+
+ a_sum = sum(negated_keys)
+ silent_payment_groups: Dict[ECPubKey, List[ECPubKey]] = {}
+ for recipient in recipients:
+ B_scan, B_m = decode_silent_payment_address(recipient, hrp=hrp)
+ if B_scan in silent_payment_groups:
+ silent_payment_groups[B_scan].append(B_m)
+ else:
+ silent_payment_groups[B_scan] = [B_m]
+
+ outputs = []
+ for B_scan, B_m_values in silent_payment_groups.items():
+ ecdh_shared_secret = input_hash * a_sum * B_scan
+ k = 0
+ for B_m in B_m_values:
+ t_k = TaggedHash("BIP0352/SharedSecret", ecdh_shared_secret.get_bytes(False) + ser_uint32(k))
+ P_km = B_m + t_k * G
+ outputs.append(P_km.get_bytes().hex())
+ k += 1
+
+ return list(set(outputs))
+
+
+def scanning(b_scan: ECKey, B_spend: ECPubKey, A_sum: ECPubKey, input_hash: bytes, outputs_to_check: List[ECPubKey], labels: Dict[str, str] = {}) -> List[Dict[str, str]]:
+ G = ECKey().set(1).get_pubkey()
+ ecdh_shared_secret = input_hash * b_scan * A_sum
+ k = 0
+ wallet = []
+ while True:
+ t_k = TaggedHash("BIP0352/SharedSecret", ecdh_shared_secret.get_bytes(False) + ser_uint32(k))
+ P_k = B_spend + t_k * G
+ for output in outputs_to_check:
+ if P_k == output:
+ wallet.append({"pub_key": P_k.get_bytes().hex(), "priv_key_tweak": t_k.hex()})
+ outputs_to_check.remove(output)
+ k += 1
+ break
+ elif labels:
+ m_G_sub = output - P_k
+ if m_G_sub.get_bytes(False).hex() in labels:
+ P_km = P_k + m_G_sub
+ wallet.append({
+ "pub_key": P_km.get_bytes().hex(),
+ "priv_key_tweak": (ECKey().set(t_k).add(
+ bytes.fromhex(labels[m_G_sub.get_bytes(False).hex()])
+ )).get_bytes().hex(),
+ })
+ outputs_to_check.remove(output)
+ k += 1
+ break
+ else:
+ output.negate()
+ m_G_sub = output - P_k
+ if m_G_sub.get_bytes(False).hex() in labels:
+ P_km = P_k + m_G_sub
+ wallet.append({
+ "pub_key": P_km.get_bytes().hex(),
+ "priv_key_tweak": (ECKey().set(t_k).add(
+ bytes.fromhex(labels[m_G_sub.get_bytes(False).hex()])
+ )).get_bytes().hex(),
+ })
+ outputs_to_check.remove(output)
+ k += 1
+ break
+ else:
+ break
+ return wallet
+
+
+if __name__ == "__main__":
+ if len(argv) != 2 or argv[1] in ('-h', '--help'):
+ print("Usage: ./reference.py send_and_receive_test_vectors.json")
+ exit(0)
+
+ with open(argv[1], "r") as f:
+ test_data = json.loads(f.read())
+
+ # G , needed for generating the labels "database"
+ G = ECKey().set(1).get_pubkey()
+ for case in test_data:
+ print(case["comment"])
+ # Test sending
+ for sending_test in case["sending"]:
+ given = sending_test["given"]
+ expected = sending_test["expected"]
+
+ vins = [
+ VinInfo(
+ outpoint=COutPoint(hash=deser_txid(input["txid"]), n=input["vout"]),
+ scriptSig=bytes.fromhex(input["scriptSig"]),
+ txinwitness=CTxInWitness().deserialize(from_hex(input["txinwitness"])),
+ prevout=bytes.fromhex(input["prevout"]["scriptPubKey"]["hex"]),
+ private_key=ECKey().set(bytes.fromhex(input["private_key"])),
+ )
+ for input in given["vin"]
+ ]
+ # Conver the tuples to lists so they can be easily compared to the json list of lists from the given test vectors
+ input_priv_keys = []
+ input_pub_keys = []
+ for vin in vins:
+ pubkey = get_pubkey_from_input(vin)
+ if not pubkey.valid:
+ continue
+ input_priv_keys.append((
+ vin.private_key,
+ is_p2tr(vin.prevout),
+ ))
+ input_pub_keys.append(pubkey)
+
+ sending_outputs = []
+ if (len(input_pub_keys) > 0):
+ A_sum = reduce(lambda x, y: x + y, input_pub_keys)
+ input_hash = get_input_hash([vin.outpoint for vin in vins], A_sum)
+ sending_outputs = create_outputs(input_priv_keys, input_hash, given["recipients"], hrp="sp")
+
+ # Note: order doesn't matter for creating/finding the outputs. However, different orderings of the recipient addresses
+ # will produce different generated outputs if sending to multiple silent payment addresses belonging to the
+ # same sender but with different labels. Because of this, expected["outputs"] contains all possible valid output sets,
+ # based on all possible permutations of recipient address orderings. Must match exactly one of the possible output sets.
+ assert(any(set(sending_outputs) == set(lst) for lst in expected["outputs"])), "Sending test failed"
+ else:
+ assert(sending_outputs == expected["outputs"][0] == []), "Sending test failed"
+
+ # Test receiving
+ msg = hashlib.sha256(b"message").digest()
+ aux = hashlib.sha256(b"random auxiliary data").digest()
+ for receiving_test in case["receiving"]:
+ given = receiving_test["given"]
+ expected = receiving_test["expected"]
+ outputs_to_check = [
+ ECPubKey().set(bytes.fromhex(p)) for p in given["outputs"]
+ ]
+ vins = [
+ VinInfo(
+ outpoint=COutPoint(hash=deser_txid(input["txid"]), n=input["vout"]),
+ scriptSig=bytes.fromhex(input["scriptSig"]),
+ txinwitness=CTxInWitness().deserialize(from_hex(input["txinwitness"])),
+ prevout=bytes.fromhex(input["prevout"]["scriptPubKey"]["hex"]),
+ )
+ for input in given["vin"]
+ ]
+ # Check that the given inputs for the receiving test match what was generated during the sending test
+ receiving_addresses = []
+ b_scan = ECKey().set(bytes.fromhex(given["key_material"]["scan_priv_key"]))
+ b_spend = ECKey().set(
+ bytes.fromhex(given["key_material"]["spend_priv_key"])
+ )
+ B_scan = b_scan.get_pubkey()
+ B_spend = b_spend.get_pubkey()
+ receiving_addresses.append(
+ encode_silent_payment_address(B_scan, B_spend, hrp="sp")
+ )
+ if given["labels"]:
+ for label in given["labels"]:
+ receiving_addresses.append(
+ create_labeled_silent_payment_address(
+ b_scan, B_spend, m=label, hrp="sp"
+ )
+ )
+
+ # Check that the silent payment addresses match for the given BIP32 seed and labels dictionary
+ assert (receiving_addresses == expected["addresses"]), "Receiving addresses don't match"
+ input_pub_keys = []
+ for vin in vins:
+ pubkey = get_pubkey_from_input(vin)
+ if not pubkey.valid:
+ continue
+ input_pub_keys.append(pubkey)
+
+ add_to_wallet = []
+ if (len(input_pub_keys) > 0):
+ A_sum = reduce(lambda x, y: x + y, input_pub_keys)
+ input_hash = get_input_hash([vin.outpoint for vin in vins], A_sum)
+ pre_computed_labels = {
+ (generate_label(b_scan, label) * G).get_bytes(False).hex(): generate_label(b_scan, label).hex()
+ for label in given["labels"]
+ }
+ add_to_wallet = scanning(
+ b_scan=b_scan,
+ B_spend=B_spend,
+ A_sum=A_sum,
+ input_hash=input_hash,
+ outputs_to_check=outputs_to_check,
+ labels=pre_computed_labels,
+ )
+
+ # Check that the private key is correct for the found output public key
+ for output in add_to_wallet:
+ pub_key = ECPubKey().set(bytes.fromhex(output["pub_key"]))
+ full_private_key = b_spend.add(bytes.fromhex(output["priv_key_tweak"]))
+ if full_private_key.get_pubkey().get_y() % 2 != 0:
+ full_private_key.negate()
+
+ sig = full_private_key.sign_schnorr(msg, aux)
+ assert pub_key.verify_schnorr(sig, msg), f"Invalid signature for {pub_key}"
+ output["signature"] = sig.hex()
+
+ # Note: order doesn't matter for creating/finding the outputs. However, different orderings of the recipient addresses
+ # will produce different generated outputs if sending to multiple silent payment addresses belonging to the
+ # same sender but with different labels. Because of this, expected["outputs"] contains all possible valid output sets,
+ # based on all possible permutations of recipient address orderings. Must match exactly one of the possible found output
+ # sets in expected["outputs"]
+ generated_set = {frozenset(d.items()) for d in add_to_wallet}
+ expected_set = {frozenset(d.items()) for d in expected["outputs"]}
+ assert generated_set == expected_set, "Receive test failed"
+
+
+ print("All tests passed")
diff --git a/bip-0352/scan_data_downloader_per_month.png b/bip-0352/scan_data_downloader_per_month.png
new file mode 100644
index 0000000..ffcd0dd
--- /dev/null
+++ b/bip-0352/scan_data_downloader_per_month.png
Binary files differ
diff --git a/bip-0352/secp256k1.py b/bip-0352/secp256k1.py
new file mode 100644
index 0000000..0ccbc4e
--- /dev/null
+++ b/bip-0352/secp256k1.py
@@ -0,0 +1,696 @@
+# Copyright (c) 2019 Pieter Wuille
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test-only secp256k1 elliptic curve implementation
+
+WARNING: This code is slow, uses bad randomness, does not properly protect
+keys, and is trivially vulnerable to side channel attacks. Do not use for
+anything but tests."""
+import random
+import hashlib
+import hmac
+
+def TaggedHash(tag, data):
+ ss = hashlib.sha256(tag.encode('utf-8')).digest()
+ ss += ss
+ ss += data
+ return hashlib.sha256(ss).digest()
+
+def modinv(a, n):
+ """Compute the modular inverse of a modulo n
+
+ See https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Modular_integers.
+ """
+ t1, t2 = 0, 1
+ r1, r2 = n, a
+ while r2 != 0:
+ q = r1 // r2
+ t1, t2 = t2, t1 - q * t2
+ r1, r2 = r2, r1 - q * r2
+ if r1 > 1:
+ return None
+ if t1 < 0:
+ t1 += n
+ return t1
+
+def jacobi_symbol(n, k):
+ """Compute the Jacobi symbol of n modulo k
+
+ See http://en.wikipedia.org/wiki/Jacobi_symbol
+
+ For our application k is always prime, so this is the same as the Legendre symbol."""
+ assert k > 0 and k & 1, "jacobi symbol is only defined for positive odd k"
+ n %= k
+ t = 0
+ while n != 0:
+ while n & 1 == 0:
+ n >>= 1
+ r = k & 7
+ t ^= (r == 3 or r == 5)
+ n, k = k, n
+ t ^= (n & k & 3 == 3)
+ n = n % k
+ if k == 1:
+ return -1 if t else 1
+ return 0
+
+def modsqrt(a, p):
+ """Compute the square root of a modulo p when p % 4 = 3.
+
+ The Tonelli-Shanks algorithm can be used. See https://en.wikipedia.org/wiki/Tonelli-Shanks_algorithm
+
+ Limiting this function to only work for p % 4 = 3 means we don't need to
+ iterate through the loop. The highest n such that p - 1 = 2^n Q with Q odd
+ is n = 1. Therefore Q = (p-1)/2 and sqrt = a^((Q+1)/2) = a^((p+1)/4)
+
+ secp256k1's is defined over field of size 2**256 - 2**32 - 977, which is 3 mod 4.
+ """
+ if p % 4 != 3:
+ raise NotImplementedError("modsqrt only implemented for p % 4 = 3")
+ sqrt = pow(a, (p + 1)//4, p)
+ if pow(sqrt, 2, p) == a % p:
+ return sqrt
+ return None
+
+def int_or_bytes(s):
+ "Convert 32-bytes to int while accepting also int and returning it as is."
+ if isinstance(s, bytes):
+ assert(len(s) == 32)
+ s = int.from_bytes(s, 'big')
+ elif not isinstance(s, int):
+ raise TypeError
+ return s
+
+class EllipticCurve:
+ def __init__(self, p, a, b):
+ """Initialize elliptic curve y^2 = x^3 + a*x + b over GF(p)."""
+ self.p = p
+ self.a = a % p
+ self.b = b % p
+
+ def affine(self, p1):
+ """Convert a Jacobian point tuple p1 to affine form, or None if at infinity.
+
+ An affine point is represented as the Jacobian (x, y, 1)"""
+ x1, y1, z1 = p1
+ if z1 == 0:
+ return None
+ inv = modinv(z1, self.p)
+ inv_2 = (inv**2) % self.p
+ inv_3 = (inv_2 * inv) % self.p
+ return ((inv_2 * x1) % self.p, (inv_3 * y1) % self.p, 1)
+
+ def has_even_y(self, p1):
+ """Whether the point p1 has an even Y coordinate when expressed in affine coordinates."""
+ return not (p1[2] == 0 or self.affine(p1)[1] & 1)
+
+ def negate(self, p1):
+ """Negate a Jacobian point tuple p1."""
+ x1, y1, z1 = p1
+ return (x1, (self.p - y1) % self.p, z1)
+
+ def on_curve(self, p1):
+ """Determine whether a Jacobian tuple p is on the curve (and not infinity)"""
+ x1, y1, z1 = p1
+ z2 = pow(z1, 2, self.p)
+ z4 = pow(z2, 2, self.p)
+ return z1 != 0 and (pow(x1, 3, self.p) + self.a * x1 * z4 + self.b * z2 * z4 - pow(y1, 2, self.p)) % self.p == 0
+
+ def is_x_coord(self, x):
+ """Test whether x is a valid X coordinate on the curve."""
+ x_3 = pow(x, 3, self.p)
+ return jacobi_symbol(x_3 + self.a * x + self.b, self.p) != -1
+
+ def lift_x(self, x):
+ """Given an X coordinate on the curve, return a corresponding affine point."""
+ x_3 = pow(x, 3, self.p)
+ v = x_3 + self.a * x + self.b
+ y = modsqrt(v, self.p)
+ if y is None:
+ return None
+ return (x, y, 1)
+
+ def double(self, p1):
+ """Double a Jacobian tuple p1
+
+ See https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates - Point Doubling"""
+ x1, y1, z1 = p1
+ if z1 == 0:
+ return (0, 1, 0)
+ y1_2 = (y1**2) % self.p
+ y1_4 = (y1_2**2) % self.p
+ x1_2 = (x1**2) % self.p
+ s = (4*x1*y1_2) % self.p
+ m = 3*x1_2
+ if self.a:
+ m += self.a * pow(z1, 4, self.p)
+ m = m % self.p
+ x2 = (m**2 - 2*s) % self.p
+ y2 = (m*(s - x2) - 8*y1_4) % self.p
+ z2 = (2*y1*z1) % self.p
+ return (x2, y2, z2)
+
+ def add_mixed(self, p1, p2):
+ """Add a Jacobian tuple p1 and an affine tuple p2
+
+ See https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates - Point Addition (with affine point)"""
+ x1, y1, z1 = p1
+ x2, y2, z2 = p2
+ assert(z2 == 1)
+ # Adding to the point at infinity is a no-op
+ if z1 == 0:
+ return p2
+ z1_2 = (z1**2) % self.p
+ z1_3 = (z1_2 * z1) % self.p
+ u2 = (x2 * z1_2) % self.p
+ s2 = (y2 * z1_3) % self.p
+ if x1 == u2:
+ if (y1 != s2):
+ # p1 and p2 are inverses. Return the point at infinity.
+ return (0, 1, 0)
+ # p1 == p2. The formulas below fail when the two points are equal.
+ return self.double(p1)
+ h = u2 - x1
+ r = s2 - y1
+ h_2 = (h**2) % self.p
+ h_3 = (h_2 * h) % self.p
+ u1_h_2 = (x1 * h_2) % self.p
+ x3 = (r**2 - h_3 - 2*u1_h_2) % self.p
+ y3 = (r*(u1_h_2 - x3) - y1*h_3) % self.p
+ z3 = (h*z1) % self.p
+ return (x3, y3, z3)
+
+ def add(self, p1, p2):
+ """Add two Jacobian tuples p1 and p2
+
+ See https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates - Point Addition"""
+ x1, y1, z1 = p1
+ x2, y2, z2 = p2
+ # Adding the point at infinity is a no-op
+ if z1 == 0:
+ return p2
+ if z2 == 0:
+ return p1
+ # Adding an Affine to a Jacobian is more efficient since we save field multiplications and squarings when z = 1
+ if z1 == 1:
+ return self.add_mixed(p2, p1)
+ if z2 == 1:
+ return self.add_mixed(p1, p2)
+ z1_2 = (z1**2) % self.p
+ z1_3 = (z1_2 * z1) % self.p
+ z2_2 = (z2**2) % self.p
+ z2_3 = (z2_2 * z2) % self.p
+ u1 = (x1 * z2_2) % self.p
+ u2 = (x2 * z1_2) % self.p
+ s1 = (y1 * z2_3) % self.p
+ s2 = (y2 * z1_3) % self.p
+ if u1 == u2:
+ if (s1 != s2):
+ # p1 and p2 are inverses. Return the point at infinity.
+ return (0, 1, 0)
+ # p1 == p2. The formulas below fail when the two points are equal.
+ return self.double(p1)
+ h = u2 - u1
+ r = s2 - s1
+ h_2 = (h**2) % self.p
+ h_3 = (h_2 * h) % self.p
+ u1_h_2 = (u1 * h_2) % self.p
+ x3 = (r**2 - h_3 - 2*u1_h_2) % self.p
+ y3 = (r*(u1_h_2 - x3) - s1*h_3) % self.p
+ z3 = (h*z1*z2) % self.p
+ return (x3, y3, z3)
+
+ def mul(self, ps):
+ """Compute a (multi) point multiplication
+
+ ps is a list of (Jacobian tuple, scalar) pairs.
+ """
+ r = (0, 1, 0)
+ for i in range(255, -1, -1):
+ r = self.double(r)
+ for (p, n) in ps:
+ if ((n >> i) & 1):
+ r = self.add(r, p)
+ return r
+
+SECP256K1_FIELD_SIZE = 2**256 - 2**32 - 977
+SECP256K1 = EllipticCurve(SECP256K1_FIELD_SIZE, 0, 7)
+SECP256K1_G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8, 1)
+SECP256K1_ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
+SECP256K1_ORDER_HALF = SECP256K1_ORDER // 2
+NUMS_H = 0x50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0
+
+class ECPubKey():
+ """A secp256k1 public key"""
+
+ def __init__(self):
+ """Construct an uninitialized public key"""
+ self.valid = False
+
+ def __repr__(self):
+ return self.get_bytes().hex()
+
+ def __eq__(self, other):
+ assert isinstance(other, ECPubKey)
+ return self.get_bytes() == other.get_bytes()
+
+ def __hash__(self):
+ return hash(self.get_bytes())
+
+ def set(self, data):
+ """Construct a public key from a serialization in compressed or uncompressed DER format or BIP340 format"""
+ if (len(data) == 65 and data[0] == 0x04):
+ p = (int.from_bytes(data[1:33], 'big'), int.from_bytes(data[33:65], 'big'), 1)
+ self.valid = SECP256K1.on_curve(p)
+ if self.valid:
+ self.p = p
+ self.compressed = False
+ elif (len(data) == 33 and (data[0] == 0x02 or data[0] == 0x03)):
+ x = int.from_bytes(data[1:33], 'big')
+ if SECP256K1.is_x_coord(x):
+ p = SECP256K1.lift_x(x)
+ # if the oddness of the y co-ord isn't correct, find the other
+ # valid y
+ if (p[1] & 1) != (data[0] & 1):
+ p = SECP256K1.negate(p)
+ self.p = p
+ self.valid = True
+ self.compressed = True
+ else:
+ self.valid = False
+ elif (len(data) == 32):
+ x = int.from_bytes(data[0:32], 'big')
+ if SECP256K1.is_x_coord(x):
+ p = SECP256K1.lift_x(x)
+ # if the oddness of the y co-ord isn't correct, find the other
+ # valid y
+ if p[1]%2 != 0:
+ p = SECP256K1.negate(p)
+ self.p = p
+ self.valid = True
+ self.compressed = True
+ else:
+ self.valid = False
+ else:
+ self.valid = False
+ return self
+
+ @property
+ def is_compressed(self):
+ return self.compressed
+
+ @property
+ def is_valid(self):
+ return self.valid
+
+ def get_y(self):
+ return SECP256K1.affine(self.p)[1]
+
+ def get_x(self):
+ return SECP256K1.affine(self.p)[0]
+
+ def get_bytes(self, bip340=True):
+ assert(self.valid)
+ p = SECP256K1.affine(self.p)
+ if p is None:
+ return None
+ if bip340:
+ return bytes(p[0].to_bytes(32, 'big'))
+ elif self.compressed:
+ return bytes([0x02 + (p[1] & 1)]) + p[0].to_bytes(32, 'big')
+ else:
+ return bytes([0x04]) + p[0].to_bytes(32, 'big') + p[1].to_bytes(32, 'big')
+
+ def verify_ecdsa(self, sig, msg, low_s=True):
+ """Verify a strictly DER-encoded ECDSA signature against this pubkey.
+
+ See https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm for the
+ ECDSA verifier algorithm"""
+ assert(self.valid)
+
+ # Extract r and s from the DER formatted signature. Return false for
+ # any DER encoding errors.
+ if (sig[1] + 2 != len(sig)):
+ return False
+ if (len(sig) < 4):
+ return False
+ if (sig[0] != 0x30):
+ return False
+ if (sig[2] != 0x02):
+ return False
+ rlen = sig[3]
+ if (len(sig) < 6 + rlen):
+ return False
+ if rlen < 1 or rlen > 33:
+ return False
+ if sig[4] >= 0x80:
+ return False
+ if (rlen > 1 and (sig[4] == 0) and not (sig[5] & 0x80)):
+ return False
+ r = int.from_bytes(sig[4:4+rlen], 'big')
+ if (sig[4+rlen] != 0x02):
+ return False
+ slen = sig[5+rlen]
+ if slen < 1 or slen > 33:
+ return False
+ if (len(sig) != 6 + rlen + slen):
+ return False
+ if sig[6+rlen] >= 0x80:
+ return False
+ if (slen > 1 and (sig[6+rlen] == 0) and not (sig[7+rlen] & 0x80)):
+ return False
+ s = int.from_bytes(sig[6+rlen:6+rlen+slen], 'big')
+
+ # Verify that r and s are within the group order
+ if r < 1 or s < 1 or r >= SECP256K1_ORDER or s >= SECP256K1_ORDER:
+ return False
+ if low_s and s >= SECP256K1_ORDER_HALF:
+ return False
+ z = int.from_bytes(msg, 'big')
+
+ # Run verifier algorithm on r, s
+ w = modinv(s, SECP256K1_ORDER)
+ u1 = z*w % SECP256K1_ORDER
+ u2 = r*w % SECP256K1_ORDER
+ R = SECP256K1.affine(SECP256K1.mul([(SECP256K1_G, u1), (self.p, u2)]))
+ if R is None or R[0] != r:
+ return False
+ return True
+
+ def verify_schnorr(self, sig, msg):
+ assert(len(msg) == 32)
+ assert(len(sig) == 64)
+ assert(self.valid)
+ r = int.from_bytes(sig[0:32], 'big')
+ if r >= SECP256K1_FIELD_SIZE:
+ return False
+ s = int.from_bytes(sig[32:64], 'big')
+ if s >= SECP256K1_ORDER:
+ return False
+ e = int.from_bytes(TaggedHash("BIP0340/challenge", sig[0:32] + self.get_bytes() + msg), 'big') % SECP256K1_ORDER
+ R = SECP256K1.mul([(SECP256K1_G, s), (self.p, SECP256K1_ORDER - e)])
+ if not SECP256K1.has_even_y(R):
+ return False
+ if ((r * R[2] * R[2]) % SECP256K1_FIELD_SIZE) != R[0]:
+ return False
+ return True
+
+ def __add__(self, other):
+ """Adds two ECPubKey points."""
+ assert isinstance(other, ECPubKey)
+ assert self.valid
+ assert other.valid
+ ret = ECPubKey()
+ ret.p = SECP256K1.add(other.p, self.p)
+ ret.valid = True
+ ret.compressed = self.compressed
+ return ret
+
+ def __radd__(self, other):
+ """Allows this ECPubKey to be added to 0 for sum()"""
+ if other == 0:
+ return self
+ else:
+ return self + other
+
+ def __mul__(self, other):
+ """Multiplies ECPubKey point with a scalar(int/32bytes/ECKey)."""
+ if isinstance(other, ECKey):
+ assert self.valid
+ assert other.secret is not None
+ multiplier = other.secret
+ else:
+ # int_or_bytes checks that other is `int` or `bytes`
+ multiplier = int_or_bytes(other)
+
+ assert multiplier < SECP256K1_ORDER
+ multiplier = multiplier % SECP256K1_ORDER
+ ret = ECPubKey()
+ ret.p = SECP256K1.mul([(self.p, multiplier)])
+ ret.valid = True
+ ret.compressed = self.compressed
+ return ret
+
+ def __rmul__(self, other):
+ """Multiplies a scalar(int/32bytes/ECKey) with an ECPubKey point"""
+ return self * other
+
+ def __sub__(self, other):
+ """Subtract one point from another"""
+ assert isinstance(other, ECPubKey)
+ assert self.valid
+ assert other.valid
+ ret = ECPubKey()
+ ret.p = SECP256K1.add(self.p, SECP256K1.negate(other.p))
+ ret.valid = True
+ ret.compressed = self.compressed
+ return ret
+
+ def tweak_add(self, tweak):
+ assert(self.valid)
+ t = int_or_bytes(tweak)
+ if t >= SECP256K1_ORDER:
+ return None
+ tweaked = SECP256K1.affine(SECP256K1.mul([(self.p, 1), (SECP256K1_G, t)]))
+ if tweaked is None:
+ return None
+ ret = ECPubKey()
+ ret.p = tweaked
+ ret.valid = True
+ ret.compressed = self.compressed
+ return ret
+
+ def mul(self, data):
+ """Multiplies ECPubKey point with scalar data."""
+ assert self.valid
+ other = ECKey()
+ other.set(data, True)
+ return self * other
+
+ def negate(self):
+ self.p = SECP256K1.affine(SECP256K1.negate(self.p))
+
+def rfc6979_nonce(key):
+ """Compute signing nonce using RFC6979."""
+ v = bytes([1] * 32)
+ k = bytes([0] * 32)
+ k = hmac.new(k, v + b"\x00" + key, 'sha256').digest()
+ v = hmac.new(k, v, 'sha256').digest()
+ k = hmac.new(k, v + b"\x01" + key, 'sha256').digest()
+ v = hmac.new(k, v, 'sha256').digest()
+ return hmac.new(k, v, 'sha256').digest()
+
+class ECKey():
+ """A secp256k1 private key"""
+
+ def __init__(self):
+ self.valid = False
+
+ def __repr__(self):
+ return str(self.secret)
+
+ def __eq__(self, other):
+ assert isinstance(other, ECKey)
+ return self.secret == other.secret
+
+ def __hash__(self):
+ return hash(self.secret)
+
+ def set(self, secret, compressed=True):
+ """Construct a private key object from either 32-bytes or an int secret and a compressed flag."""
+ secret = int_or_bytes(secret)
+
+ self.valid = (secret > 0 and secret < SECP256K1_ORDER)
+ if self.valid:
+ self.secret = secret
+ self.compressed = compressed
+ return self
+
+ def generate(self, compressed=True):
+ """Generate a random private key (compressed or uncompressed)."""
+ self.set(random.randrange(1, SECP256K1_ORDER).to_bytes(32, 'big'), compressed)
+ return self
+
+ def get_bytes(self):
+ """Retrieve the 32-byte representation of this key."""
+ assert(self.valid)
+ return self.secret.to_bytes(32, 'big')
+
+ def as_int(self):
+ return self.secret
+
+ def from_int(self, secret, compressed=True):
+ self.valid = (secret > 0 and secret < SECP256K1_ORDER)
+ if self.valid:
+ self.secret = secret
+ self.compressed = compressed
+
+ def __add__(self, other):
+ """Add key secrets. Returns compressed key."""
+ assert isinstance(other, ECKey)
+ assert other.secret > 0 and other.secret < SECP256K1_ORDER
+ assert self.valid is True
+ ret_data = ((self.secret + other.secret) % SECP256K1_ORDER).to_bytes(32, 'big')
+ ret = ECKey()
+ ret.set(ret_data, True)
+ return ret
+
+ def __radd__(self, other):
+ """Allows this ECKey to be added to 0 for sum()"""
+ if other == 0:
+ return self
+ else:
+ return self + other
+
+ def __sub__(self, other):
+ """Subtract key secrets. Returns compressed key."""
+ assert isinstance(other, ECKey)
+ assert other.secret > 0 and other.secret < SECP256K1_ORDER
+ assert self.valid is True
+ ret_data = ((self.secret - other.secret) % SECP256K1_ORDER).to_bytes(32, 'big')
+ ret = ECKey()
+ ret.set(ret_data, True)
+ return ret
+
+ def __mul__(self, other):
+ """Multiply a private key by another private key or multiply a public key by a private key. Returns compressed key."""
+ if isinstance(other, ECKey):
+ assert other.secret > 0 and other.secret < SECP256K1_ORDER
+ assert self.valid is True
+ ret_data = ((self.secret * other.secret) % SECP256K1_ORDER).to_bytes(32, 'big')
+ ret = ECKey()
+ ret.set(ret_data, True)
+ return ret
+ elif isinstance(other, ECPubKey):
+ return other * self
+ else:
+ # ECKey().set() checks that other is an `int` or `bytes`
+ assert self.valid
+ second = ECKey().set(other, self.compressed)
+ return self * second
+
+ def __rmul__(self, other):
+ return self * other
+
+ def add(self, data):
+ """Add key to scalar data. Returns compressed key."""
+ other = ECKey()
+ other.set(data, True)
+ return self + other
+
+ def mul(self, data):
+ """Multiply key secret with scalar data. Returns compressed key."""
+ other = ECKey()
+ other.set(data, True)
+ return self * other
+
+ def negate(self):
+ """Negate a private key."""
+ assert self.valid
+ self.secret = SECP256K1_ORDER - self.secret
+
+ @property
+ def is_valid(self):
+ return self.valid
+
+ @property
+ def is_compressed(self):
+ return self.compressed
+
+ def get_pubkey(self):
+ """Compute an ECPubKey object for this secret key."""
+ assert(self.valid)
+ ret = ECPubKey()
+ p = SECP256K1.mul([(SECP256K1_G, self.secret)])
+ ret.p = p
+ ret.valid = True
+ ret.compressed = self.compressed
+ return ret
+
+ def sign_ecdsa(self, msg, low_s=True, rfc6979=False):
+ """Construct a DER-encoded ECDSA signature with this key.
+
+ See https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm for the
+ ECDSA signer algorithm."""
+ assert(self.valid)
+ z = int.from_bytes(msg, 'big')
+ # Note: no RFC6979 by default, but a simple random nonce (some tests rely on distinct transactions for the same operation)
+ if rfc6979:
+ k = int.from_bytes(rfc6979_nonce(self.secret.to_bytes(32, 'big') + msg), 'big')
+ else:
+ k = random.randrange(1, SECP256K1_ORDER)
+ R = SECP256K1.affine(SECP256K1.mul([(SECP256K1_G, k)]))
+ r = R[0] % SECP256K1_ORDER
+ s = (modinv(k, SECP256K1_ORDER) * (z + self.secret * r)) % SECP256K1_ORDER
+ if low_s and s > SECP256K1_ORDER_HALF:
+ s = SECP256K1_ORDER - s
+ # Represent in DER format. The byte representations of r and s have
+ # length rounded up (255 bits becomes 32 bytes and 256 bits becomes 33
+ # bytes).
+ rb = r.to_bytes((r.bit_length() + 8) // 8, 'big')
+ sb = s.to_bytes((s.bit_length() + 8) // 8, 'big')
+ return b'\x30' + bytes([4 + len(rb) + len(sb), 2, len(rb)]) + rb + bytes([2, len(sb)]) + sb
+
+ def sign_schnorr(self, msg, aux=None):
+ """Create a Schnorr signature (see BIP340)."""
+ if aux is None:
+ aux = bytes(32)
+
+ assert self.valid
+ assert len(msg) == 32
+ assert len(aux) == 32
+
+ t = (self.secret ^ int.from_bytes(TaggedHash("BIP0340/aux", aux), 'big')).to_bytes(32, 'big')
+ kp = int.from_bytes(TaggedHash("BIP0340/nonce", t + self.get_pubkey().get_bytes() + msg), 'big') % SECP256K1_ORDER
+ assert kp != 0
+ R = SECP256K1.affine(SECP256K1.mul([(SECP256K1_G, kp)]))
+ k = kp if SECP256K1.has_even_y(R) else SECP256K1_ORDER - kp
+ e = int.from_bytes(TaggedHash("BIP0340/challenge", R[0].to_bytes(32, 'big') + self.get_pubkey().get_bytes() + msg), 'big') % SECP256K1_ORDER
+ return R[0].to_bytes(32, 'big') + ((k + e * self.secret) % SECP256K1_ORDER).to_bytes(32, 'big')
+
+ def tweak_add(self, tweak):
+ """Return a tweaked version of this private key."""
+ assert(self.valid)
+ t = int_or_bytes(tweak)
+ if t >= SECP256K1_ORDER:
+ return None
+ tweaked = (self.secret + t) % SECP256K1_ORDER
+ if tweaked == 0:
+ return None
+ ret = ECKey()
+ ret.set(tweaked.to_bytes(32, 'big'), self.compressed)
+ return ret
+
+def generate_key_pair(secret=None, compressed=True):
+ """Convenience function to generate a private-public key pair."""
+ d = ECKey()
+ if secret:
+ d.set(secret, compressed)
+ else:
+ d.generate(compressed)
+
+ P = d.get_pubkey()
+ return d, P
+
+def generate_bip340_key_pair():
+ """Convenience function to generate a BIP0340 private-public key pair."""
+ d = ECKey()
+ d.generate()
+ P = d.get_pubkey()
+ if P.get_y()%2 != 0:
+ d.negate()
+ P.negate()
+ return d, P
+
+def generate_schnorr_nonce():
+ """Generate a random valid BIP340 nonce.
+
+ See https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki.
+ This implementation ensures the y-coordinate of the nonce point is even."""
+ kp = random.randrange(1, SECP256K1_ORDER)
+ assert kp != 0
+ R = SECP256K1.affine(SECP256K1.mul([(SECP256K1_G, kp)]))
+ k = kp if R[1] % 2 == 0 else SECP256K1_ORDER - kp
+ k_key = ECKey()
+ k_key.set(k.to_bytes(32, 'big'), True)
+ return k_key
diff --git a/bip-0352/send_and_receive_test_vectors.json b/bip-0352/send_and_receive_test_vectors.json
new file mode 100644
index 0000000..f9b205b
--- /dev/null
+++ b/bip-0352/send_and_receive_test_vectors.json
@@ -0,0 +1,2673 @@
+[
+ {
+ "comment": "Simple send: two inputs",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac"
+ }
+ },
+ "private_key": "93f5ed907ad5b2bdbbdcb5d9116ebc0a4e1f92f910d5260237fa45a9408aad16"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "3e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "3e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "f438b40179a3c4262de12986c0e6cce0634007cdc79c1dcd3e20b9ebc2e7eef6",
+ "pub_key": "3e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1",
+ "signature": "74f85b856337fbe837643b86f462118159f93ac4acc2671522f27e8f67b079959195ccc7a5dbee396d2909f5d680d6e30cda7359aa2755822509b70d6b0687a1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Simple send: two inputs, order reversed",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac"
+ }
+ },
+ "private_key": "93f5ed907ad5b2bdbbdcb5d9116ebc0a4e1f92f910d5260237fa45a9408aad16"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "3e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "3e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "f438b40179a3c4262de12986c0e6cce0634007cdc79c1dcd3e20b9ebc2e7eef6",
+ "pub_key": "3e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1",
+ "signature": "74f85b856337fbe837643b86f462118159f93ac4acc2671522f27e8f67b079959195ccc7a5dbee396d2909f5d680d6e30cda7359aa2755822509b70d6b0687a1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Simple send: two inputs from the same transaction",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 3,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 7,
+ "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac"
+ }
+ },
+ "private_key": "93f5ed907ad5b2bdbbdcb5d9116ebc0a4e1f92f910d5260237fa45a9408aad16"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "79e71baa2ba3fc66396de3a04f168c7bf24d6870ec88ca877754790c1db357b6"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 3,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 7,
+ "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "79e71baa2ba3fc66396de3a04f168c7bf24d6870ec88ca877754790c1db357b6"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "4851455bfbe1ab4f80156570aa45063201aa5c9e1b1dcd29f0f8c33d10bf77ae",
+ "pub_key": "79e71baa2ba3fc66396de3a04f168c7bf24d6870ec88ca877754790c1db357b6",
+ "signature": "10332eea808b6a13f70059a8a73195808db782012907f5ba32b6eae66a2f66b4f65147e2b968a1678c5f73d57d5d195dbaf667b606ff80c8490eac1f3b710657"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Simple send: two inputs from the same transaction, order reversed",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 7,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 3,
+ "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac"
+ }
+ },
+ "private_key": "93f5ed907ad5b2bdbbdcb5d9116ebc0a4e1f92f910d5260237fa45a9408aad16"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "f4c2da807f89cb1501f1a77322a895acfb93c28e08ed2724d2beb8e44539ba38"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 7,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 3,
+ "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "f4c2da807f89cb1501f1a77322a895acfb93c28e08ed2724d2beb8e44539ba38"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "ab0c9b87181bf527879f48db9f14a02233619b986f8e8f2d5d408ce68a709f51",
+ "pub_key": "f4c2da807f89cb1501f1a77322a895acfb93c28e08ed2724d2beb8e44539ba38",
+ "signature": "398a9790865791a9db41a8015afad3a47d60fec5086c50557806a49a1bc038808632b8fe679a7bb65fc6b455be994502eed849f1da3729cd948fc7be73d67295"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Outpoint ordering byte-lexicographically vs. vout-integer",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 1,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 256,
+ "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac"
+ }
+ },
+ "private_key": "93f5ed907ad5b2bdbbdcb5d9116ebc0a4e1f92f910d5260237fa45a9408aad16"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "a85ef8701394b517a4b35217c4bd37ac01ebeed4b008f8d0879f9e09ba95319c"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 1,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 256,
+ "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "a85ef8701394b517a4b35217c4bd37ac01ebeed4b008f8d0879f9e09ba95319c"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "c8ac0292997b5bca98b3ebd99a57e253071137550f270452cd3df8a3e2266d36",
+ "pub_key": "a85ef8701394b517a4b35217c4bd37ac01ebeed4b008f8d0879f9e09ba95319c",
+ "signature": "c036ee38bfe46aba03234339ae7219b31b824b52ef9d5ce05810a0d6f62330dedc2b55652578aa5bdabf930fae941acd839d5a66f8fce7caa9710ccb446bddd1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Single recipient: multiple UTXOs from the same public key",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "548ae55c8eec1e736e8d3e520f011f1f42a56d166116ad210b3937599f87f566"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "548ae55c8eec1e736e8d3e520f011f1f42a56d166116ad210b3937599f87f566"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "f032695e2636619efa523fffaa9ef93c8802299181fd0461913c1b8daf9784cd",
+ "pub_key": "548ae55c8eec1e736e8d3e520f011f1f42a56d166116ad210b3937599f87f566",
+ "signature": "f238386c5d5e5444f8d2c75aabbcb28c346f208c76f60823f5de3b67b79e0ec72ea5de2d7caec314e0971d3454f122dda342b3eede01b3857e83654e36b25f76"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Single recipient: taproot only inputs with even y-values",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "0140bd1e708f92dbeaf24a6b8dd22e59c6274355424d62baea976b449e220fd75b13578e262ab11b7aa58e037f0c6b0519b66803b7d9decaa1906dedebfb531c56c1",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "5120782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338"
+ }
+ },
+ "private_key": "fc8716a97a48ba9a05a98ae47b5cd201a25a7fd5d8b73c203c5f7b6b6b3b6ad7"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "de88bea8e7ffc9ce1af30d1132f910323c505185aec8eae361670421e749a1fb"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "0140bd1e708f92dbeaf24a6b8dd22e59c6274355424d62baea976b449e220fd75b13578e262ab11b7aa58e037f0c6b0519b66803b7d9decaa1906dedebfb531c56c1",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "5120782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "de88bea8e7ffc9ce1af30d1132f910323c505185aec8eae361670421e749a1fb"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "3fb9ce5ce1746ced103c8ed254e81f6690764637ddbc876ec1f9b3ddab776b03",
+ "pub_key": "de88bea8e7ffc9ce1af30d1132f910323c505185aec8eae361670421e749a1fb",
+ "signature": "c5acd25a8f021a4192f93bc34403fd8b76484613466336fb259c72d04c169824f2690ca34e96cee86b69f376c8377003268fda56feeb1b873e5783d7e19bcca5"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Single recipient: taproot only with mixed even/odd y-values",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "01400a4d0dca6293f40499394d7eefe14a1de11e0e3454f51de2e802592abf5ee549042a1b1a8fb2e149ee9dd3f086c1b69b2f182565ab6ecf599b1ec9ebadfda6c5",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "51208c8d23d4764feffcd5e72e380802540fa0f88e3d62ad5e0b47955f74d7b283c4"
+ }
+ },
+ "private_key": "1d37787c2b7116ee983e9f9c13269df29091b391c04db94239e0d2bc2182c3bf"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "77cab7dd12b10259ee82c6ea4b509774e33e7078e7138f568092241bf26b99f1"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "01400a4d0dca6293f40499394d7eefe14a1de11e0e3454f51de2e802592abf5ee549042a1b1a8fb2e149ee9dd3f086c1b69b2f182565ab6ecf599b1ec9ebadfda6c5",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "51208c8d23d4764feffcd5e72e380802540fa0f88e3d62ad5e0b47955f74d7b283c4"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "77cab7dd12b10259ee82c6ea4b509774e33e7078e7138f568092241bf26b99f1"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "f5382508609771068ed079b24e1f72e4a17ee6d1c979066bf1d4e2a5676f09d4",
+ "pub_key": "77cab7dd12b10259ee82c6ea4b509774e33e7078e7138f568092241bf26b99f1",
+ "signature": "ff65833b8fd1ed3ef9d0443b4f702b45a3f2dd457ba247687e8207745c3be9d2bdad0ab3f07118f8b2efc6a04b95f7b3e218daf8a64137ec91bd2fc67fc137a5"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Single recipient: taproot input with even y-value and non-taproot input",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "463044021f24e010c6e475814740ba24c8cf9362c4db1276b7f46a7b1e63473159a80ec30221008198e8ece7b7f88e6c6cc6bb8c86f9f00b7458222a8c91addf6e1577bcf7697e2103e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9148cbc7dfe44f1579bff3340bbef1eddeaeb1fc97788ac"
+ }
+ },
+ "private_key": "8d4751f6e8a3586880fb66c19ae277969bd5aa06f61c4ee2f1e2486efdf666d3"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "30523cca96b2a9ae3c98beb5e60f7d190ec5bc79b2d11a0b2d4d09a608c448f0"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "463044021f24e010c6e475814740ba24c8cf9362c4db1276b7f46a7b1e63473159a80ec30221008198e8ece7b7f88e6c6cc6bb8c86f9f00b7458222a8c91addf6e1577bcf7697e2103e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9148cbc7dfe44f1579bff3340bbef1eddeaeb1fc97788ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "30523cca96b2a9ae3c98beb5e60f7d190ec5bc79b2d11a0b2d4d09a608c448f0"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "b40017865c79b1fcbed68896791be93186d08f47e416b289b8c063777e14e8df",
+ "pub_key": "30523cca96b2a9ae3c98beb5e60f7d190ec5bc79b2d11a0b2d4d09a608c448f0",
+ "signature": "d1edeea28cf1033bcb3d89376cabaaaa2886cbd8fda112b5c61cc90a4e7f1878bdd62180b07d1dfc8ffee1863c525a0c7b5bcd413183282cfda756cb65787266"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Single recipient: taproot input with odd y-value and non-taproot input",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "01400a4d0dca6293f40499394d7eefe14a1de11e0e3454f51de2e802592abf5ee549042a1b1a8fb2e149ee9dd3f086c1b69b2f182565ab6ecf599b1ec9ebadfda6c5",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "51208c8d23d4764feffcd5e72e380802540fa0f88e3d62ad5e0b47955f74d7b283c4"
+ }
+ },
+ "private_key": "1d37787c2b7116ee983e9f9c13269df29091b391c04db94239e0d2bc2182c3bf"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "463044021f24e010c6e475814740ba24c8cf9362c4db1276b7f46a7b1e63473159a80ec30221008198e8ece7b7f88e6c6cc6bb8c86f9f00b7458222a8c91addf6e1577bcf7697e2103e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9148cbc7dfe44f1579bff3340bbef1eddeaeb1fc97788ac"
+ }
+ },
+ "private_key": "8d4751f6e8a3586880fb66c19ae277969bd5aa06f61c4ee2f1e2486efdf666d3"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "359358f59ee9e9eec3f00bdf4882570fd5c182e451aa2650b788544aff012a3a"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "01400a4d0dca6293f40499394d7eefe14a1de11e0e3454f51de2e802592abf5ee549042a1b1a8fb2e149ee9dd3f086c1b69b2f182565ab6ecf599b1ec9ebadfda6c5",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "51208c8d23d4764feffcd5e72e380802540fa0f88e3d62ad5e0b47955f74d7b283c4"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "463044021f24e010c6e475814740ba24c8cf9362c4db1276b7f46a7b1e63473159a80ec30221008198e8ece7b7f88e6c6cc6bb8c86f9f00b7458222a8c91addf6e1577bcf7697e2103e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9148cbc7dfe44f1579bff3340bbef1eddeaeb1fc97788ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "359358f59ee9e9eec3f00bdf4882570fd5c182e451aa2650b788544aff012a3a"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "a2f9dd05d1d398347c885d9c61a64d18a264de6d49cea4326bafc2791d627fa7",
+ "pub_key": "359358f59ee9e9eec3f00bdf4882570fd5c182e451aa2650b788544aff012a3a",
+ "signature": "96038ad233d8befe342573a6e54828d863471fb2afbad575cc65271a2a649480ea14912b6abbd3fbf92efc1928c036f6e3eef927105af4ec1dd57cb909f360b8"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Multiple outputs: multiple outputs, same recipient",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ },
+ "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "e976a58fbd38aeb4e6093d4df02e9c1de0c4513ae0c588cef68cda5b2f8834ca",
+ "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "e976a58fbd38aeb4e6093d4df02e9c1de0c4513ae0c588cef68cda5b2f8834ca",
+ "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "d97e442d110c0bdd31161a7bb6e7862e038d02a09b1484dfbb463f2e0f7c9230",
+ "pub_key": "e976a58fbd38aeb4e6093d4df02e9c1de0c4513ae0c588cef68cda5b2f8834ca",
+ "signature": "29bd25d0f808d7fcd2aa6d5ed206053899198397506c301b218a9e47a3d7070af03e903ff718978d50d1b6b9af8cc0e313d84eda5d5b1e8e85e5516d630bbeb9"
+ },
+ {
+ "priv_key_tweak": "33ce085c3c11eaad13694aae3c20301a6c83382ec89a7cde96c6799e2f88805a",
+ "pub_key": "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac",
+ "signature": "335667ca6cae7a26438f5cfdd73b3d48fa832fa9768521d7d5445f22c203ab0d74ed85088f27d29959ba627a4509996676f47df8ff284d292567b1beef0e3912"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Multiple outputs: multiple outputs, multiple recipients",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ },
+ "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv",
+ "sp1qqgrz6j0lcqnc04vxccydl0kpsj4frfje0ktmgcl2t346hkw30226xqupawdf48k8882j0strrvcmgg2kdawz53a54dd376ngdhak364hzcmynqtn",
+ "sp1qqgrz6j0lcqnc04vxccydl0kpsj4frfje0ktmgcl2t346hkw30226xqupawdf48k8882j0strrvcmgg2kdawz53a54dd376ngdhak364hzcmynqtn"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "2e847bb01d1b491da512ddd760b8509617ee38057003d6115d00ba562451323a",
+ "841792c33c9dc6193e76744134125d40add8f2f4a96475f28ba150be032d64e8",
+ "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "2e847bb01d1b491da512ddd760b8509617ee38057003d6115d00ba562451323a",
+ "841792c33c9dc6193e76744134125d40add8f2f4a96475f28ba150be032d64e8",
+ "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac"
+ ],
+ "key_material": {
+ "spend_priv_key": "9902c3c56e84002a7cd410113a9ab21d142be7f53cf5200720bb01314c5eb920",
+ "scan_priv_key": "060b751d7892149006ed7b98606955a29fe284a1e900070c0971f5fb93dbf422"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgrz6j0lcqnc04vxccydl0kpsj4frfje0ktmgcl2t346hkw30226xqupawdf48k8882j0strrvcmgg2kdawz53a54dd376ngdhak364hzcmynqtn"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "72cd082cccb633bf85240a83494b32dc943a4d05647a6686d23ad4ca59c0ebe4",
+ "pub_key": "2e847bb01d1b491da512ddd760b8509617ee38057003d6115d00ba562451323a",
+ "signature": "38745f3d9f5eef0b1cfb17ca314efa8c521efab28a23aa20ec5e3abb561d42804d539906dce60c4ee7977966184e6f2cab1faa0e5377ceb7148ec5218b4e7878"
+ },
+ {
+ "priv_key_tweak": "2f17ea873a0047fc01ba8010fef0969e76d0e4283f600d48f735098b1fee6eb9",
+ "pub_key": "841792c33c9dc6193e76744134125d40add8f2f4a96475f28ba150be032d64e8",
+ "signature": "c26f4e3cf371b90b840f48ea0e761b5ec31883ed55719f9ef06a90e282d85f565790ab780a3f491bc2668cc64e944dca849d1022a878cdadb8d168b8da4a6da3"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Receiving with labels: label with even parity",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ },
+ "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjex54dmqmmv6rw353tsuqhs99ydvadxzrsy9nuvk74epvee55drs734pqq"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "d014d4860f67d607d60b1af70e0ee236b99658b61bb769832acbbe87c374439a"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "d014d4860f67d607d60b1af70e0ee236b99658b61bb769832acbbe87c374439a"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": [
+ 2,
+ 3,
+ 1001337
+ ]
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjex54dmqmmv6rw353tsuqhs99ydvadxzrsy9nuvk74epvee55drs734pqq",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqsg59z2rppn4qlkx0yz9sdltmjv3j8zgcqadjn4ug98m3t6plujsq9qvu5n",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq7c2zfthc6x3a5yecwc52nxa0kfd20xuz08zyrjpfw4l2j257yq6qgnkdh5"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "51d4e9d0d482b5700109b4b2e16ff508269b03d800192a043d61dca4a0a72a52",
+ "pub_key": "d014d4860f67d607d60b1af70e0ee236b99658b61bb769832acbbe87c374439a",
+ "signature": "c30fa63bad6f0a317f39a773a5cbf0b0f8193c71dfebba05ee6ae4ed28e3775e6e04c3ea70a83703bb888122855dc894cab61692e7fd10c9b3494d479a60785e"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Receiving with labels: label with odd parity",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ },
+ "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqsg59z2rppn4qlkx0yz9sdltmjv3j8zgcqadjn4ug98m3t6plujsq9qvu5n"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "67626aebb3c4307cf0f6c39ca23247598fabf675ab783292eb2f81ae75ad1f8c"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "67626aebb3c4307cf0f6c39ca23247598fabf675ab783292eb2f81ae75ad1f8c"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": [
+ 2,
+ 3,
+ 1001337
+ ]
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjex54dmqmmv6rw353tsuqhs99ydvadxzrsy9nuvk74epvee55drs734pqq",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqsg59z2rppn4qlkx0yz9sdltmjv3j8zgcqadjn4ug98m3t6plujsq9qvu5n",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq7c2zfthc6x3a5yecwc52nxa0kfd20xuz08zyrjpfw4l2j257yq6qgnkdh5"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "6024ae214876356b8d917716e7707d267ae16a0fdb07de2a786b74a7bbcddead",
+ "pub_key": "67626aebb3c4307cf0f6c39ca23247598fabf675ab783292eb2f81ae75ad1f8c",
+ "signature": "a86d554d0d6b7aa0907155f7e0b47f0182752472fffaeddd68da90e99b9402f166fd9b33039c302c7115098d971c1399e67c19e9e4de180b10ea0b9d6f0db832"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Receiving with labels: large label integer",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ },
+ "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq7c2zfthc6x3a5yecwc52nxa0kfd20xuz08zyrjpfw4l2j257yq6qgnkdh5"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "7efa60ce78ac343df8a013a2027c6c5ef29f9502edcbd769d2c21717fecc5951"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "7efa60ce78ac343df8a013a2027c6c5ef29f9502edcbd769d2c21717fecc5951"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": [
+ 2,
+ 3,
+ 1001337
+ ]
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjex54dmqmmv6rw353tsuqhs99ydvadxzrsy9nuvk74epvee55drs734pqq",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqsg59z2rppn4qlkx0yz9sdltmjv3j8zgcqadjn4ug98m3t6plujsq9qvu5n",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq7c2zfthc6x3a5yecwc52nxa0kfd20xuz08zyrjpfw4l2j257yq6qgnkdh5"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "e336b92330c33030285ce42e4115ad92d5197913c88e06b9072b4a9b47c664a2",
+ "pub_key": "7efa60ce78ac343df8a013a2027c6c5ef29f9502edcbd769d2c21717fecc5951",
+ "signature": "c9e80dd3bdd25ca2d352ce77510f1aed37ba3509dc8cc0677f2d7c2dd04090707950ce9dd6c83d2a428063063aff5c04f1744e334f661f2fc01b4ef80b50f739"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Multiple outputs with labels: un-labeled and labeled address; same recipient",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ },
+ "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c",
+ "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac"
+ ],
+ [
+ "83dc944e61603137294829aed56c74c9b087d80f2c021b98a7fae5799000696c",
+ "e976a58fbd38aeb4e6093d4df02e9c1de0c4513ae0c588cef68cda5b2f8834ca"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c",
+ "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": [
+ 1
+ ]
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "43100f89f1a6bf10081c92b473ffc57ceac7dbed600b6aba9bb3976f17dbb914",
+ "pub_key": "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c",
+ "signature": "15c92509b67a6c211ebb4a51b7528d0666e6720de2343b2e92cfb97942ca14693c1f1fdc8451acfdb2644039f8f5c76114807fdc3d3a002d8a46afab6756bd75"
+ },
+ {
+ "priv_key_tweak": "33ce085c3c11eaad13694aae3c20301a6c83382ec89a7cde96c6799e2f88805a",
+ "pub_key": "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac",
+ "signature": "335667ca6cae7a26438f5cfdd73b3d48fa832fa9768521d7d5445f22c203ab0d74ed85088f27d29959ba627a4509996676f47df8ff284d292567b1beef0e3912"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Multiple outputs with labels: multiple outputs for labeled address; same recipient",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ },
+ "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c",
+ "83dc944e61603137294829aed56c74c9b087d80f2c021b98a7fae5799000696c"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c",
+ "83dc944e61603137294829aed56c74c9b087d80f2c021b98a7fae5799000696c"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": [
+ 1
+ ]
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "43100f89f1a6bf10081c92b473ffc57ceac7dbed600b6aba9bb3976f17dbb914",
+ "pub_key": "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c",
+ "signature": "15c92509b67a6c211ebb4a51b7528d0666e6720de2343b2e92cfb97942ca14693c1f1fdc8451acfdb2644039f8f5c76114807fdc3d3a002d8a46afab6756bd75"
+ },
+ {
+ "priv_key_tweak": "9d5fd3b91cac9ddfea6fc2e6f9386f680e6cee623cda02f53706306c081de87f",
+ "pub_key": "83dc944e61603137294829aed56c74c9b087d80f2c021b98a7fae5799000696c",
+ "signature": "db0dfacc98b6a6fcc67cc4631f080b1ca38c60d8c397f2f19843f8f95ec91594b24e47c5bd39480a861c1209f7e3145c440371f9191fb96e324690101eac8e8e"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Multiple outputs with labels: un-labeled, labeled, and multiple outputs for labeled address; same recipients",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ },
+ "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjyh2ju7hd5gj57jg5r9lev3pckk4n2shtzaq34467erzzdfajfggty6aa5",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjyh2ju7hd5gj57jg5r9lev3pckk4n2shtzaq34467erzzdfajfggty6aa5"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "006a02c308ccdbf3ac49f0638f6de128f875db5a213095cf112b3b77722472ae",
+ "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c",
+ "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701",
+ "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa"
+ ],
+ [
+ "006a02c308ccdbf3ac49f0638f6de128f875db5a213095cf112b3b77722472ae",
+ "3edf1ff6657c6e69568811bd726a7a7f480493aa42161acfe8dd4f44521f99ed",
+ "7ee1543ed5d123ffa66fbebc128c020173eb490d5fa2ba306e0c9573a77db8f3",
+ "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa"
+ ],
+ [
+ "006a02c308ccdbf3ac49f0638f6de128f875db5a213095cf112b3b77722472ae",
+ "7ee1543ed5d123ffa66fbebc128c020173eb490d5fa2ba306e0c9573a77db8f3",
+ "83dc944e61603137294829aed56c74c9b087d80f2c021b98a7fae5799000696c",
+ "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701"
+ ],
+ [
+ "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c",
+ "3c54444944d176437644378c23efb999ab6ab1cacdfe1dc1537b607e3df330e2",
+ "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa",
+ "f4569fc5f69c10f0082cfbb8e072e6266ec55f69fba8cffca4cbb4c144b7e59b"
+ ],
+ [
+ "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c",
+ "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701",
+ "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac",
+ "f4569fc5f69c10f0082cfbb8e072e6266ec55f69fba8cffca4cbb4c144b7e59b"
+ ],
+ [
+ "3c54444944d176437644378c23efb999ab6ab1cacdfe1dc1537b607e3df330e2",
+ "602e10e6944107c9b48bd885b493676578c935723287e0ab2f8b7f136862568e",
+ "7ee1543ed5d123ffa66fbebc128c020173eb490d5fa2ba306e0c9573a77db8f3",
+ "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa"
+ ],
+ [
+ "3c54444944d176437644378c23efb999ab6ab1cacdfe1dc1537b607e3df330e2",
+ "7ee1543ed5d123ffa66fbebc128c020173eb490d5fa2ba306e0c9573a77db8f3",
+ "83dc944e61603137294829aed56c74c9b087d80f2c021b98a7fae5799000696c",
+ "f4569fc5f69c10f0082cfbb8e072e6266ec55f69fba8cffca4cbb4c144b7e59b"
+ ],
+ [
+ "3edf1ff6657c6e69568811bd726a7a7f480493aa42161acfe8dd4f44521f99ed",
+ "7ee1543ed5d123ffa66fbebc128c020173eb490d5fa2ba306e0c9573a77db8f3",
+ "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac",
+ "f4569fc5f69c10f0082cfbb8e072e6266ec55f69fba8cffca4cbb4c144b7e59b"
+ ],
+ [
+ "3edf1ff6657c6e69568811bd726a7a7f480493aa42161acfe8dd4f44521f99ed",
+ "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa",
+ "e976a58fbd38aeb4e6093d4df02e9c1de0c4513ae0c588cef68cda5b2f8834ca",
+ "f4569fc5f69c10f0082cfbb8e072e6266ec55f69fba8cffca4cbb4c144b7e59b"
+ ],
+ [
+ "602e10e6944107c9b48bd885b493676578c935723287e0ab2f8b7f136862568e",
+ "7ee1543ed5d123ffa66fbebc128c020173eb490d5fa2ba306e0c9573a77db8f3",
+ "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701",
+ "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac"
+ ],
+ [
+ "602e10e6944107c9b48bd885b493676578c935723287e0ab2f8b7f136862568e",
+ "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701",
+ "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa",
+ "e976a58fbd38aeb4e6093d4df02e9c1de0c4513ae0c588cef68cda5b2f8834ca"
+ ],
+ [
+ "83dc944e61603137294829aed56c74c9b087d80f2c021b98a7fae5799000696c",
+ "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701",
+ "e976a58fbd38aeb4e6093d4df02e9c1de0c4513ae0c588cef68cda5b2f8834ca",
+ "f4569fc5f69c10f0082cfbb8e072e6266ec55f69fba8cffca4cbb4c144b7e59b"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "006a02c308ccdbf3ac49f0638f6de128f875db5a213095cf112b3b77722472ae",
+ "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c",
+ "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701",
+ "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": [
+ 1,
+ 1337
+ ]
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj",
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjyh2ju7hd5gj57jg5r9lev3pckk4n2shtzaq34467erzzdfajfggty6aa5"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "4e3352fbe0505c25e718d96007c259ef08db34f8c844e4ff742d9855ff03805a",
+ "pub_key": "006a02c308ccdbf3ac49f0638f6de128f875db5a213095cf112b3b77722472ae",
+ "signature": "6eeae1ea9eb826e3d0e812f65937100e0836ea188c04f36fabc4981eda29de8d3d3529390a0a8b3d830f7bca4f5eae5994b9788ddaf05ad259ffe26d86144b4b"
+ },
+ {
+ "priv_key_tweak": "43100f89f1a6bf10081c92b473ffc57ceac7dbed600b6aba9bb3976f17dbb914",
+ "pub_key": "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c",
+ "signature": "15c92509b67a6c211ebb4a51b7528d0666e6720de2343b2e92cfb97942ca14693c1f1fdc8451acfdb2644039f8f5c76114807fdc3d3a002d8a46afab6756bd75"
+ },
+ {
+ "priv_key_tweak": "bf709f98d4418f8a67e738154ae48818dad44689cd37fbc070891a396dd1c633",
+ "pub_key": "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701",
+ "signature": "42a19fd8a63dde1824966a95d65a28203e631e49bf96ca5dae1b390e7a0ace2cc8709c9b0c5715047032f57f536a3c80273cbecf4c05be0b5456c183fa122c06"
+ },
+ {
+ "priv_key_tweak": "736f05e4e3072c3b8656bedef2e9bf54cbcaa2b6fe5320d3e86f5b96874dda71",
+ "pub_key": "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa",
+ "signature": "2e61bb3d79418ecf55f68847cf121bfc12d397b39d1da8643246b2f0a9b96c3daa4bfe9651beb5c9ce20e1f29282c4566400a4b45ee6657ec3b18fdc554da0b4"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Single recipient: use silent payments for sender change",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ },
+ "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv",
+ "sp1qqw6vczcfpdh5nf5y2ky99kmqae0tr30hgdfg88parz50cp80wd2wqqlv6saelkk5snl4wfutyxrchpzzwm8rjp3z6q7apna59z9huq4x754e5atr"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "be368e28979d950245d742891ae6064020ba548c1e2e65a639a8bb0675d95cff",
+ "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "be368e28979d950245d742891ae6064020ba548c1e2e65a639a8bb0675d95cff",
+ "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac"
+ ],
+ "key_material": {
+ "spend_priv_key": "b8f87388cbb41934c50daca018901b00070a5ff6cc25a7e9e716a9d5b9e4d664",
+ "scan_priv_key": "11b7a82e06ca2648d5fded2366478078ec4fc9dc1d8ff487518226f229d768fd"
+ },
+ "labels": [
+ 0
+ ]
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqw6vczcfpdh5nf5y2ky99kmqae0tr30hgdfg88parz50cp80wd2wqqauj52ymtc4xdkmx3tgyhrsemg2g3303xk2gtzfy8h8ejet8fz8jcw23zua",
+ "sp1qqw6vczcfpdh5nf5y2ky99kmqae0tr30hgdfg88parz50cp80wd2wqqlv6saelkk5snl4wfutyxrchpzzwm8rjp3z6q7apna59z9huq4x754e5atr"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "80cd767ed20bd0bb7d8ea5e803f8c381293a62e8a073cf46fb0081da46e64e1f",
+ "pub_key": "be368e28979d950245d742891ae6064020ba548c1e2e65a639a8bb0675d95cff",
+ "signature": "7fbd5074cf1377273155eefafc7c330cb61b31da252f22206ac27530d2b2567040d9af7808342ed4a09598c26d8307446e4ed77079e6a2e61fea736e44da5f5a"
+ }
+ ]
+ }
+ },
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "be368e28979d950245d742891ae6064020ba548c1e2e65a639a8bb0675d95cff",
+ "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "33ce085c3c11eaad13694aae3c20301a6c83382ec89a7cde96c6799e2f88805a",
+ "pub_key": "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac",
+ "signature": "335667ca6cae7a26438f5cfdd73b3d48fa832fa9768521d7d5445f22c203ab0d74ed85088f27d29959ba627a4509996676f47df8ff284d292567b1beef0e3912"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Single recipient: taproot input with NUMS point",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "0440c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b22205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5ac21c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac00150",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "5120da6f0595ecb302bbe73e2f221f05ab10f336b06817d36fd28fc6691725ddaa85"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "0140bd1e708f92dbeaf24a6b8dd22e59c6274355424d62baea976b449e220fd75b13578e262ab11b7aa58e037f0c6b0519b66803b7d9decaa1906dedebfb531c56c1",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "5120782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338"
+ }
+ },
+ "private_key": "fc8716a97a48ba9a05a98ae47b5cd201a25a7fd5d8b73c203c5f7b6b6b3b6ad7"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 1,
+ "scriptSig": "",
+ "txinwitness": "0340268d31a9276f6380107d5321cafa6d9e8e5ea39204318fdc8206b31507c891c3bbcea3c99e2208d73bd127a8e8c5f1e45a54f1bd217205414ddb566ab7eda0092220e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85dac21c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "51200a3c9365ceb131f89b0a4feb6896ebd67bb15a98c31eaa3da143bb955a0f3fcb"
+ }
+ },
+ "private_key": "8d4751f6e8a3586880fb66c19ae277969bd5aa06f61c4ee2f1e2486efdf666d3"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "79e79897c52935bfd97fc6e076a6431a0c7543ca8c31e0fc3cf719bb572c842d"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "0440c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b22205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5ac21c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac00150",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "5120da6f0595ecb302bbe73e2f221f05ab10f336b06817d36fd28fc6691725ddaa85"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "0140bd1e708f92dbeaf24a6b8dd22e59c6274355424d62baea976b449e220fd75b13578e262ab11b7aa58e037f0c6b0519b66803b7d9decaa1906dedebfb531c56c1",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "5120782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 1,
+ "scriptSig": "",
+ "txinwitness": "0340268d31a9276f6380107d5321cafa6d9e8e5ea39204318fdc8206b31507c891c3bbcea3c99e2208d73bd127a8e8c5f1e45a54f1bd217205414ddb566ab7eda0092220e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85dac21c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "51200a3c9365ceb131f89b0a4feb6896ebd67bb15a98c31eaa3da143bb955a0f3fcb"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "79e79897c52935bfd97fc6e076a6431a0c7543ca8c31e0fc3cf719bb572c842d"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "3ddec3232609d348d6b8b53123b4f40f6d4f5398ca586f087b0416ec3b851496",
+ "pub_key": "79e79897c52935bfd97fc6e076a6431a0c7543ca8c31e0fc3cf719bb572c842d",
+ "signature": "d7d06e3afb68363031e4eb18035c46ceae41bdbebe7888a4754bc9848c596436869aeaecff0527649a1f458b71c9ceecec10b535c09d01d720229aa228547706"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Pubkey extraction from malleated p2pkh",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 1,
+ "scriptSig": "0075473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ },
+ "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a"
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 2,
+ "scriptSig": "5163473045022100e7d26e77290b37128f5215ade25b9b908ce87cc9a4d498908b5bb8fd6daa1b8d022002568c3a8226f4f0436510283052bfb780b76f3fe4aa60c4c5eb118e43b187372102e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d67483046022100c0d3c851d3bd562ae93d56bcefd735ea57c027af46145a4d5e9cac113bfeb0c2022100ee5b2239af199fa9b7aa1d98da83a29d0a2cf1e4f29e2f37134ce386d51c544c2102ad0f26ddc7b3fcc340155963b3051b85289c1869612ecb290184ac952e2864ec68",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a914c82c5ec473cbc6c86e5ef410e36f9495adcf979988ac"
+ }
+ },
+ "private_key": "72b8ae09175ca7977f04993e651d88681ed932dfb92c5158cdf0161dd23fda6e"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "4612cdbf845c66c7511d70aab4d9aed11e49e48cdb8d799d787101cdd0d53e4f"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 1,
+ "scriptSig": "0075473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ }
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 2,
+ "scriptSig": "5163473045022100e7d26e77290b37128f5215ade25b9b908ce87cc9a4d498908b5bb8fd6daa1b8d022002568c3a8226f4f0436510283052bfb780b76f3fe4aa60c4c5eb118e43b187372102e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d67483046022100c0d3c851d3bd562ae93d56bcefd735ea57c027af46145a4d5e9cac113bfeb0c2022100ee5b2239af199fa9b7aa1d98da83a29d0a2cf1e4f29e2f37134ce386d51c544c2102ad0f26ddc7b3fcc340155963b3051b85289c1869612ecb290184ac952e2864ec68",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a914c82c5ec473cbc6c86e5ef410e36f9495adcf979988ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "4612cdbf845c66c7511d70aab4d9aed11e49e48cdb8d799d787101cdd0d53e4f"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "10bde9781def20d7701e7603ef1b1e5e71c67bae7154818814e3c81ef5b1a3d3",
+ "pub_key": "4612cdbf845c66c7511d70aab4d9aed11e49e48cdb8d799d787101cdd0d53e4f",
+ "signature": "6137969f810e9e8ef6c9755010e808f5dd1aed705882e44d7f0ae64eb0c509ec8b62a0671bee0d5914ac27d2c463443e28e999d82dc3d3a4919f093872d947bb"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "P2PKH and P2WPKH Uncompressed Keys are skipped",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b974104782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233387c5343bf58e23269e903335b958a12182f9849297321e8d710e49a8727129cab",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9144b92ac4ac6fe6212393894addda332f2e47a315688ac"
+ }
+ },
+ "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 1,
+ "scriptSig": "",
+ "txinwitness": "02473045022100e7d26e77290b37128f5215ade25b9b908ce87cc9a4d498908b5bb8fd6daa1b8d022002568c3a8226f4f0436510283052bfb780b76f3fe4aa60c4c5eb118e43b187374104e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d6fe8190e189be57d0d5bcd17dbcbcd04c9b4a1c5f605b10d5c90abfcc0d12884",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "00140423f731a07491364e8dce98b7c00bda63336950"
+ }
+ },
+ "private_key": "72b8ae09175ca7977f04993e651d88681ed932dfb92c5158cdf0161dd23fda6e"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "67fee277da9e8542b5d2e6f32d660a9bbd3f0e107c2d53638ab1d869088882d6"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac"
+ }
+ }
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b974104782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233387c5343bf58e23269e903335b958a12182f9849297321e8d710e49a8727129cab",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9144b92ac4ac6fe6212393894addda332f2e47a315688ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 1,
+ "scriptSig": "",
+ "txinwitness": "02473045022100e7d26e77290b37128f5215ade25b9b908ce87cc9a4d498908b5bb8fd6daa1b8d022002568c3a8226f4f0436510283052bfb780b76f3fe4aa60c4c5eb118e43b187374104e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d6fe8190e189be57d0d5bcd17dbcbcd04c9b4a1c5f605b10d5c90abfcc0d12884",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "00140423f731a07491364e8dce98b7c00bda63336950"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "67fee277da9e8542b5d2e6f32d660a9bbd3f0e107c2d53638ab1d869088882d6"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "688fa3aeb97d2a46ae87b03591921c2eaf4b505eb0ddca2733c94701e01060cf",
+ "pub_key": "67fee277da9e8542b5d2e6f32d660a9bbd3f0e107c2d53638ab1d869088882d6",
+ "signature": "72e7ad573ac23255d4651d5b0326a200496588acb7a4894b22092236d5eda6a0a9a4d8429b022c2219081fefce5b33795cae488d10f5ea9438849ed8353624f2"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Skip invalid P2SH inputs",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "16001419c2f3ae0ca3b642bd3e49598b8da89f50c14161",
+ "txinwitness": "02483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "a9148629db5007d5fcfbdbb466637af09daf9125969387"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 1,
+ "scriptSig": "1600144b92ac4ac6fe6212393894addda332f2e47a3156",
+ "txinwitness": "02473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b974104782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233387c5343bf58e23269e903335b958a12182f9849297321e8d710e49a8727129cab",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "a9146c9bf136fbb7305fd99d771a95127fcf87dedd0d87"
+ }
+ },
+ "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a"
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 2,
+ "scriptSig": "00493046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d601483045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b97014c695221025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be52103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233382102e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d53ae",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "a9141044ddc6cea09e4ac40fbec2ba34ad62de6db25b87"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "67fee277da9e8542b5d2e6f32d660a9bbd3f0e107c2d53638ab1d869088882d6"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "16001419c2f3ae0ca3b642bd3e49598b8da89f50c14161",
+ "txinwitness": "02483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "a9148629db5007d5fcfbdbb466637af09daf9125969387"
+ }
+ }
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 1,
+ "scriptSig": "1600144b92ac4ac6fe6212393894addda332f2e47a3156",
+ "txinwitness": "02473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b974104782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233387c5343bf58e23269e903335b958a12182f9849297321e8d710e49a8727129cab",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "a9146c9bf136fbb7305fd99d771a95127fcf87dedd0d87"
+ }
+ }
+ },
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 2,
+ "scriptSig": "00493046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d601483045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b97014c695221025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be52103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233382102e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d53ae",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "a9141044ddc6cea09e4ac40fbec2ba34ad62de6db25b87"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "67fee277da9e8542b5d2e6f32d660a9bbd3f0e107c2d53638ab1d869088882d6"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": [
+ {
+ "priv_key_tweak": "688fa3aeb97d2a46ae87b03591921c2eaf4b505eb0ddca2733c94701e01060cf",
+ "pub_key": "67fee277da9e8542b5d2e6f32d660a9bbd3f0e107c2d53638ab1d869088882d6",
+ "signature": "72e7ad573ac23255d4651d5b0326a200496588acb7a4894b22092236d5eda6a0a9a4d8429b022c2219081fefce5b33795cae488d10f5ea9438849ed8353624f2"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "comment": "Recipient ignores unrelated outputs",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ },
+ "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a"
+ }
+ ],
+ "recipients": [
+ "sp1qqgrz6j0lcqnc04vxccydl0kpsj4frfje0ktmgcl2t346hkw30226xqupawdf48k8882j0strrvcmgg2kdawz53a54dd376ngdhak364hzcmynqtn"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ [
+ "841792c33c9dc6193e76744134125d40add8f2f4a96475f28ba150be032d64e8"
+ ]
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "",
+ "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "841792c33c9dc6193e76744134125d40add8f2f4a96475f28ba150be032d64e8",
+ "782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": []
+ }
+ }
+ ]
+ },
+ {
+ "comment": "No valid inputs, sender generates no outputs",
+ "sending": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d641045a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5c61836c9b1688ba431f7ea3039742251f62f0dca3da1bee58a47fa9b456c2d52",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a914460e8b41545d2dbe7e0671f0f573e2232814260a88ac"
+ }
+ },
+ "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1"
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b974104782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233387c5343bf58e23269e903335b958a12182f9849297321e8d710e49a8727129cab",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9144b92ac4ac6fe6212393894addda332f2e47a315688ac"
+ }
+ },
+ "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a"
+ }
+ ],
+ "recipients": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ]
+ },
+ "expected": {
+ "outputs": [
+ []
+ ]
+ }
+ }
+ ],
+ "receiving": [
+ {
+ "given": {
+ "vin": [
+ {
+ "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
+ "vout": 0,
+ "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d641045a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5c61836c9b1688ba431f7ea3039742251f62f0dca3da1bee58a47fa9b456c2d52",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a914460e8b41545d2dbe7e0671f0f573e2232814260a88ac"
+ }
+ }
+ },
+ {
+ "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
+ "vout": 0,
+ "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b974104782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233387c5343bf58e23269e903335b958a12182f9849297321e8d710e49a8727129cab",
+ "txinwitness": "",
+ "prevout": {
+ "scriptPubKey": {
+ "hex": "76a9144b92ac4ac6fe6212393894addda332f2e47a315688ac"
+ }
+ }
+ }
+ ],
+ "outputs": [
+ "782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338",
+ "e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d"
+ ],
+ "key_material": {
+ "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3",
+ "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c"
+ },
+ "labels": []
+ },
+ "expected": {
+ "addresses": [
+ "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv"
+ ],
+ "outputs": []
+ }
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/bip-0370.mediawiki b/bip-0370.mediawiki
index cd448cc..98f1800 100644
--- a/bip-0370.mediawiki
+++ b/bip-0370.mediawiki
@@ -248,7 +248,7 @@ Before any input or output may be added, the constructor must check the PSBT_GLO
Inputs may only be added if the Inputs Modifiable flag is True.
Outputs may only be added if the Outputs Modifiable flag is True.
-When an input or output is added, the corresponding PSBT_GLOBAL_INPUT_COUNT or PSBT_GLOBAL_OUTPUT_COUNT must be incremeted to reflect the number of inputs and outputs in the PSBT.
+When an input or output is added, the corresponding PSBT_GLOBAL_INPUT_COUNT or PSBT_GLOBAL_OUTPUT_COUNT must be incremented to reflect the number of inputs and outputs in the PSBT.
When an input is added, it must have PSBT_IN_PREVIOUS_TXID and PSBT_IN_OUTPUT_INDEX set.
When an output is added, it must have PSBT_OUT_VALUE and PSBT_OUT_OUTPUT_SCRIPT set.
If the input has a required timelock, Constructors must set the requisite timelock field.
diff --git a/bip-0387.mediawiki b/bip-0387.mediawiki
new file mode 100644
index 0000000..5c039b8
--- /dev/null
+++ b/bip-0387.mediawiki
@@ -0,0 +1,101 @@
+<pre>
+ BIP: 387
+ Layer: Applications
+ Title: Tapscript Multisig Output Script Descriptors
+ Author: Pieter Wuille <pieter@wuille.net>
+ Ava Chow <me@achow101.com>
+ Comments-Summary: No comments yet.
+ Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0387
+ Status: Draft
+ Type: Informational
+ Created: 2024-04-17
+ License: BSD-2-Clause
+</pre>
+
+==Abstract==
+
+This document specifies <tt>multi_a()</tt> and <tt>sortedmulti_a()</tt> output script descriptors.
+Like BIP 383's <tt>multi()</tt> and <tt>sortedmulti()</tt>, both functions take a threshold and one
+or more public keys and produce a multisig script. The primary distinction is that <tt>multi_a()</tt>
+and <tt>sortedmulti_a()</tt> only produce tapscripts and are only allowed in a tapscript context.
+
+==Copyright==
+
+This BIP is licensed under the BSD 2-clause license.
+
+==Motivation==
+
+The most common complex script used in Bitcoin is a threshold multisig.
+These expressions allow specifying multisig scripts as a descriptor.
+
+==Specification==
+
+Two new script expressions are defined: <tt>multi_a()</tt> and <tt>sortedmulti_a()</tt>.
+Both expressions produce the scripts of the same template and take the same arguments.
+They are written as <tt>multi_a(k,KEY_1,KEY_2,...,KEY_n)</tt>.
+<tt>k</tt> is the threshold - the number of keys that must sign the input for the script to be valid.
+<tt>KEY_1,KEY_2,...,KEY_n</tt> are the key expressions for the multisig. <tt>k</tt> must be less than or equal to <tt>n</tt>.
+
+<tt>multi_a()</tt> and <tt>sortedmulti_a()</tt> expressions can only be used inside of a <tt>tr()</tt> descriptor.
+The maximum number of keys is 999.
+
+The output script produced also depends on the value of <tt>k</tt>. If <tt>k</tt> is less than or equal to 16:
+<pre>
+KEY_1 OP_CHECKSIG KEY_2 OP_CHECKSIGADD ... KEY_n OP_CHECKSIGADD OP_k OP_NUMEQUAL
+</pre>
+
+if <tt>k</tt> is greater than 16:
+<pre>
+KEY_1 OP_CHECKSIG KEY_2 OP_CHECKSIGADD ... KEY_n OP_CHECKSIGADD k OP_NUMEQUAL
+</pre>
+
+===<tt>sortedmulti_a()</tt>===
+
+The only change for <tt>sortedmulti_a()</tt> is that the x-only public keys are sorted lexicographically prior to the creation of the output script.
+This sorting is on the keys that are to be put into the output script, i.e. after all extended keys are derived.
+
+===Multiple Extended Keys</tt>===
+
+When one or more of the key expressions in a <tt>multi_a()</tt> or <tt>sortedmulti_a()</tt> expression are extended keys, the derived keys use the same child index.
+This changes the keys in lockstep and allows for output scripts to be indexed in the same way that the derived keys are indexed.
+
+==Test Vectors==
+
+Valid descriptors followed by the scripts they produce. Descriptors involving derived child keys will have the 0th, 1st, and 2nd scripts listed.
+
+* <tt>tr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,multi_a(1,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy))</tt>
+** <tt>5120eb5bd3894327d75093891cc3a62506df7d58ec137fcd104cdd285d67816074f3</tt>
+* <tt>tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,multi_a(1,669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0))</tt>
+** <tt>5120eb5bd3894327d75093891cc3a62506df7d58ec137fcd104cdd285d67816074f3</tt>
+* <tt>tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,multi_a(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))</tt>
+** <tt>51202eea93581594a43c0c8423b70dc112e5651df63984d108d4fc8ccd3b63b4eafa</tt>
+* <tt>tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,sortedmulti_a(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))</tt>
+** <tt>512016fa6a6ba7e98c54b5bf43b3144912b78a61b60b02f6a74172b8dcb35b12bc30</tt>
+* <tt>tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,sortedmulti_a(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*))</tt>
+** <tt>5120abd47468515223f58a1a18edfde709a7a2aab2b696d59ecf8c34f0ba274ef772</tt>
+** <tt>5120fe62e7ed20705bd1d3678e072bc999acb014f07795fa02cb8f25a7aa787e8cbd</tt>
+** <tt>51201311093750f459039adaa2a5ed23b0f7a8ae2c2ffb07c5390ea37e2fb1050b41</tt>
+* <tt>tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,multi_a(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))</tt>
+** <tt>5120e4c8f2b0a7d3a688ac131cb03248c0d4b0a59bbd4f37211c848cfbd22a981192</tt>
+** <tt>5120827faedaa21e52fca2ac83b53afd1ab7d4d1e6ce67ff42b19f2723d48b5a19ab</tt>
+** <tt>5120647495ed09de61a3a324704f9203c130d655bf3141f9b748df8f7be7e9af55a4</tt>
+
+Invalid descriptors
+
+* Unsupported top level: <tt>multi_a(1,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0)</tt>
+* Unsupported <tt>sh()</tt> context: <tt>sh(multi_a(1,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0))</tt>
+* Unsupported <tt>wsh()</tt> context: <tt>wsh(multi_a(1,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0))</tt>
+* Invalid threshold: <tt>tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,multi_a(a,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))</tt>
+* Threshold of 0: <tt>tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,multi_a(0,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))</tt>
+* Uncompressed pubkey: <tt>tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,multi_a(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))</tt>
+* Threshold larger than keys: <tt>tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,multi_a(3,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss))</tt>
+
+==Backwards Compatibility==
+
+<tt>multi_a()</tt> and <tt>sortedmulti_a()</tt> descriptors use the format and general operation specified in [[bip-0380.mediawiki|380]].
+As these are wholly new descriptors, they are not compatible with any implementation.
+However, the scripts produced are standard scripts, so existing software are likely to be familiar with them.
+
+==Reference Implementation==
+
+<tt>multi_a()</tt> and <tt>sortedmulti_a()</tt> descriptors were implemented in Bitcoin Core in https://github.com/bitcoin/bitcoin/pull/24043 and have been available since version 24.0.
diff --git a/bip-0388.mediawiki b/bip-0388.mediawiki
new file mode 100644
index 0000000..dc1b508
--- /dev/null
+++ b/bip-0388.mediawiki
@@ -0,0 +1,306 @@
+<pre>
+ BIP: 388
+ Layer: Applications
+ Title: Wallet Policies for Descriptor Wallets
+ Author: Salvatore Ingala <salvatoshi@protonmail.com>
+ Comments-Summary: No comments yet.
+ Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0388
+ Status: Proposed
+ Type: Standards Track
+ Created: 2022-11-16
+ License: BSD-2-Clause
+ Post-History: 2022-05-10: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-May/020423.html
+</pre>
+
+== Abstract ==
+
+Wallet policies build on top of output script descriptors to represent the types of descriptors that are typically used to represent "accounts" in a software wallet, or a hardware signing device, in a compact, reviewable way. A wallet policy always represents exactly two descriptors, which produce the receive and change addresses that are logically part of the same account.
+
+We simplify the language to suit devices with limited memory, where even keeping the entire descriptor in memory could be a major hurdle, by reducing the generality of descriptors to just the essential features and by separating the extended pubkeys and other key information from the descriptor.
+
+This results in a more compact representation and simplifies the inspection of the policy by the user.
+
+The compilation of wallet policies to the corresponding descriptor is trivial, and the reverse process is easy for supported descriptors, because the language is kept similar to that of output script descriptors.
+
+== Copyright ==
+
+This BIP is licensed under the BSD 2-clause license.
+
+== Motivation ==
+
+''[[bip-0380.mediawiki|Output Script Descriptors]]'' were introduced in Bitcoin Core as a way to represent collections of output scripts. It is a general and flexible language, designed to catch all the possible use-cases of bitcoin wallets (that is, if you know the script and you have the necessary keys, it will be possible to sign transactions with any descriptor-based software wallet).
+
+Unfortunately, descriptors are not a perfect match for the typical usage of hardware signing devices (often also called ''hardware wallets''). Most of them have some of the following limitations when compared to a general-purpose machine running Bitcoin Core:
+
+* they are embedded devices with limited RAM, and computational power;
+* they cannot import additional private keys (that is, they can only sign with keys derived from a single seed via [[bip-0032.mediawiki|BIP-32]]);
+* they have limited storage, or they might not have persistent storage at all (''stateless design'').
+
+Moreover, other limitations like the limited size of the screen might affect what design choices are available in practice. Therefore, minimizing the amount of information shown on-screen is important for a good user experience. The ability for the user to completely validate on-screen the kind of script used (and each of the involved keys) is crucial for secure usage, as the machine that is interacting with the hardware signer (and running the software wallet) is considered untrusted.
+
+A more native, compact representation of the wallet receive and change addresses might also benefit the UX of software wallets when they use descriptors (possibly with miniscript) for representing complex locking conditions.
+
+We remark that wallet policies are not related to the ''policy'' language, a higher level language that can be compiled to miniscript.
+
+=== Security and UX concerns for hardware signing devices ===
+
+The usage of complex scripts presents challenges in terms of both security and user experience for a hardware signing device.
+
+==== Security issues ====
+
+Hardware signing devices strive to guarantee that no action can be performed without the user’s consent as long as the user correctly verifies the information that is shown on the device’s screen before approving.
+
+This must hold even in scenarios where the attacker has full control of the machine that is connected to the signing device, and can execute arbitrary requests, or tamper with the legitimate user's requests.
+
+Therefore, it is not at all trivial to allow complex scripts, especially if they contain keys that belong to third parties.
+The hardware signing device must guarantee that the user knows precisely what "policy" is being used to spend the funds, and that any "unspent" funds (if any) that is sent to a change address will be protected by the same policy.
+
+This makes it impossible for an attacker to surreptitiously modify the policy, therefore stealing or burning the user's funds.
+
+==== UX issues ====
+
+Miniscript (and taproot trees) allow substantially more complex spending policies. It is a challenge to ensure that the user can practically verify such spending policies per the screen.
+
+We set two fundamental design goals:
+* Minimize the amount of information that is shown on screen - so that the user can actually validate it.
+* Minimize the number of times the user has to validate such information.
+
+Designing a secure protocol for the coordination of a descriptor wallet among distant parties is also a challenging problem that is out of scope in this document. See [[bip-0129.mediawiki|BIP-129 (Bitcoin Secure Multisig Setup)]] for an approach designed for multisignature wallets. Regardless of the approach, the ability for the user to carefully verify all the details of the spending policies using the hardware signer's screen is a prerequisite for security in adversarial environments.
+
+=== Policy registration as a solution ===
+
+A solution to address the security concerns, and part of the UX concerns, is to have a registration flow for the wallet policy in the hardware signing device. The ''wallet policy'' must contain enough information to generate all the relevant addresses/scripts, and for the hardware signing device to identify the keys that it controls and that are needed to spend the funds sent to those addresses.
+
+Before a new policy is used for the first time, the user will register a wallet policy into the hardware device. While the details of the process are out of scope in this document, the flow should be something similar to the following:
+
+# The software wallet initiates a ''wallet policy registration'' on the hardware signing device; the information should include the wallet policy, but also a unique ''name'' that identifies the policy.
+# The device shows the wallet policy to the user using the secure screen.
+# After inspecting the policy and comparing it with a trusted source (for example a printed backup), the user approves the policy.
+# If stateful, the hardware signing device persists the policy in its permanent memory; if stateless, it returns a "proof of registration".
+
+The '''proof of registration''' will allow the hardware signer to verify that a certain policy was indeed previously approved by the user, and is therefore safe to use without repeating the expensive user verification procedure. The details of how to create a proof of registration are out of scope for this document; using a Message Authentication Code on a hash committing to the wallet policy, its name and any additional metadata is an effective solution if correctly executed.
+
+Once a policy is registered, the hardware signing device can perform the typical operations securely:
+* generating receive and change addresses;
+* showing addresses on the secure screen;
+* sign transactions spending from a wallet, while correctly identifying change addresses and computing the transaction fees.
+
+Before any of the actions mentioned above, the hardware signing device will retrieve the policy from its permanent storage if stateful; if stateless it will validate the proof of registration before using the wallet policy provided by the client.
+
+Once the previously registered policy is correctly identified and approved by the user (for example by showing its name), and as long as the policy registration was executed securely, hardware signing devices can provide a user experience similar to the usual one for single-signature transactions.
+
+=== Avoiding blowup in descriptor size ===
+
+While reusing a pubkey in different branches of a miniscript is explicitly forbidden by miniscript (as it has certain negative security implications), it is still reasonable to reuse the same xpub in multiple places, albeit with different final steps of derivation (so that the actual pubkeys that are used in the script are indeed different).
+
+In fact, there are many reasonable spending policies with a quadratic size in the number of participants. For example, using Taproot, a 3-of-5 multisignature wallet could use:
+* a key path with a 5-of-5 MuSig2 aggregated key
+* a script tree with 11 leaves:
+** 10 different scripts using a 3-of-3 MuSig2 aggregated key, plus
+** a final leaf with a fallback 3-of-5 multisignature using <tt>multi_a</tt> (in case interactive signing is not available).
+
+With each xpub being 118 bytes long, the repetition of xpubs makes the descriptor become extremely large.
+
+Replacing the common part of the key with a short key placeholder and organizing all the key expressions in a separate list helps to keep the size of the wallet policy small, which is crucial to allow human inspection during the registration flow.
+
+== Specification ==
+
+This section formally defines wallet policies, and how they relate to output script descriptors.
+
+=== Formal definition ===
+
+A ''wallet policy'' is composed by a ''wallet descriptor template'', together with a vector of ''key information items''.
+
+==== Wallet descriptor template ====
+
+A ''wallet descriptor template'' is a <tt>SCRIPT</tt> expression.
+
+<tt>SCRIPT</tt> expressions:
+* <tt>sh(SCRIPT)</tt> (top level only): P2SH embed the argument.
+* <tt>wsh(SCRIPT)</tt> (top level or inside <tt>sh</tt> only): P2WSH embed the argument.
+* <tt>pkh(KP)</tt> (not inside <tt>tr</tt>): P2PKH output for the given public key.
+* <tt>wpkh(KP)</tt> (top level or inside <tt>sh</tt> only): P2WPKH output for the given compressed pubkey.
+* <tt>multi(k,KP_1,KP_2,...,KP_n)</tt> (inside <tt>sh</tt> or <tt>wsh</tt> only): ''k''-of-''n'' multisig script.
+* <tt>sortedmulti(k,KP_1,KP_2,...,KP_n)</tt> (inside <tt>sh</tt> or <tt>wsh</tt> only): ''k''-of-''n'' multisig script with keys sorted lexicographically in the resulting script.
+* <tt>tr(KP)</tt> or <tt>tr(KP,TREE)</tt> (top level only): P2TR output with the specified key as internal key, and optionally a tree of script paths.
+* any valid miniscript template (inside <tt>wsh</tt> or <tt>tr</tt> only).
+
+<tt>TREE</tt> expressions:
+* any <tt>SCRIPT</tt> expression
+* An open brace <tt>{</tt>, a <tt>TREE</tt> expression, a comma <tt>,</tt>, a <tt>TREE</tt> expression, and a closing brace <tt>}</tt>
+
+
+<tt>KP</tt> expressions (key placeholders) consist of
+* a single character <tt>@</tt>
+* followed by a non-negative decimal number, with no leading zeros (except for <tt>@0</tt>)
+* ''always'' followed by either:
+** the string <tt>/**</tt>, or
+** a string of the form <tt>/<NUM;NUM>/*</tt>, for two distinct decimal numbers <tt>NUM</tt> representing unhardened derivations, or
+** any of the additional, implementation-specific valid derivation path patterns (see [[#optional-derivation-paths|Optional derivation paths]] below).
+
+The <tt>/**</tt> in the placeholder template represents commonly used paths for receive/change addresses, and is equivalent to <tt><0;1>/*</tt>.
+
+Note that while [[bip-0389.mediawiki|BIP-389]] allows multipath <tt>/<NUM;NUM;...;NUM></tt> expressions with an arbitrary number of options, this specification restricts it to exactly 2 choices (with the typical meaning of receive/change addresses).
+
+The placeholder <tt>@i</tt> for some number ''i'' represents the ''i''-th key in the vector of key information items (which must be of size at least ''i + 1'', or the wallet policy is invalid).
+
+Note: while descriptor templates for miniscript are not formally defined in this version of the document (pending standardization), it is straightforward to adapt this approach by adding additional <tt>SCRIPT</tt> expressions.
+
+==== Key information vector ====
+
+Each element of the key origin information vector is a <tt>KEY</tt> expression.
+
+* Optionally, key origin information, consisting of:
+** An open bracket <tt>[</tt>
+** Exactly 8 hex characters for the fingerprint of the master key from which this key is derived from (see [[bip-0032.mediawiki|BIP-32]] for details)
+** Followed by zero or more <tt>/NUM'</tt> or <tt>/NUM</tt> path elements to indicate hardened or unhardened derivation steps between the fingerprint and the xpub that follows
+** A closing bracket <tt>]</tt>
+* Followed by the actual key, which is a serialized extended public key (as defined in [[bip-0032.mediawiki|BIP-32]]).
+
+==== Additional rules ====
+
+A wallet policy must have at least one key placeholder and the corresponding key.
+
+The public keys obtained by deserializing elements of the key information vector must be pairwise distinct<ref>'''Why must public keys be distinct?''' Reusing pubkeys could be insecure in the context of wallet policies containing [https://bitcoin.sipa.be/miniscript/ miniscript]. Avoiding repeated public keys altogether avoids the problem at the source.</ref>.
+
+If two key placeholders are <tt>@i/<M;N>/*</tt> and <tt>@i/<P;Q>/*</tt> for the same index <tt>i</tt>, then the sets <tt>{M, N}</tt> and <tt>{P, Q}</tt> must be disjoint.
+
+The key information vector should be ordered so that placeholder <tt>@i</tt> never appears for the first time before an occurrence of <tt>@j</tt> for some <tt>j < i</tt>; for example, the first placeholder is always <tt>@0</tt>, the next one is <tt>@1</tt>, etc.
+
+=== Descriptor derivation ===
+
+From a wallet descriptor template (and the associated vector of key information items), one can therefore obtain the corresponding multipath descriptor by:
+
+* replacing each key placeholder with the corresponding key origin
+information;
+* replacing every <tt>/**</tt> with <tt>/<0;1>/*</tt>.
+
+For example, the wallet descriptor <tt>pkh(@0/**)</tt> with key information
+<tt>["[d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"]</tt>
+produces the following multipath descriptor:
+
+<tt>pkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/<0;1>/*)</tt>
+
+=== Implementation guidelines ===
+
+It is acceptable to implement only a subset of the possible wallet policies defined by this standard. It is recommended that any limitations are clearly documented.
+
+Implementations can add additional metadata that is stored together with the wallet policy for the purpose of wallet policy registration and later usage. Metadata can be vendor-specific and is out of the scope of this document.
+
+Any implementation in a software wallet that allows wallet policies not matching any of the specifications in [[bip-0044.mediawiki|BIP-44]], [[bip-0049.mediawiki|BIP-49]], [[bip-0084.mediawiki|BIP-84]], [[bip-0086.mediawiki|BIP-86]] (especially if involving external cosigners) should put great care into a process for backing up the wallet policy that represents the account. In fact, unlike standard single-signature scenarios, the seed alone is no longer enough to discover wallet policies with existing funds, and the loss of the backup is likely to lead to permanent loss of funds. Unlike the seed, leaking such backups only affects the privacy of the user, but it does not allow the attacker to steal funds.
+
+Avoiding key reuse among different wallet accounts is also extremely important, but out of scope for this document.
+
+=== Optional derivation paths ===
+
+In order to allow supporting legacy derivation schemes (for example, using simply <tt>/*</tt> instead of the more common <tt>/<M;N>/*</tt> scheme most software wallets use today), or other schemes that are not covered in this document, implementations might choose to permit additional derivation patterns for the key placeholder (<tt>KP</tt>) expressions.
+
+However, care needs to be taken in view of the following considerations:
+
+* Allowing derivation schemes with a different length or cardinality in the same wallet policy would make it difficult to guarantee that there are no repeated pubkeys for every possible address generated by the policy. For example, <tt>@0/<0;1>/*</tt> and <tt>@1/*</tt> would generate the same pubkeys if the second public key in the key information vector is one of the first two unhardened children of the first public key. This could cause malleability with potential security implications (for example, in policies containing miniscript).
+* Allowing naked pubkeys with no <tt>/*</tt> suffix (for example a descriptor template like <tt>wsh(multi(2,@0,@1/<0;1>/*))</tt>) would cause a pubkey to be repeated in every output generated from the policy, which would result in a total loss of privacy.
+
+== Examples ==
+
+In the examples in this section, the vector of key information items is omitted. See the test vectors below for complete examples.
+
+Common single-signature account patterns:
+* <tt>pkh(@0/**)</tt> (legacy).
+* <tt>wpkh(@0/**)</tt> (native segwit).
+* <tt>sh(wpkh(@0/**))</tt> (nested segwit).
+* <tt>tr(@0/**)</tt> (taproot single-signature account).
+
+Common multisignature schemes:
+* <tt>wsh(multi(2,@0/**,@1/**))</tt> - SegWit 2-of-2 multisignature, keys in order.
+* <tt>sh(sortedmulti(2,@0/**,@1/**,@2/**))</tt> - Legacy 2-of-3 multisignature, sorted keys.
+
+Some miniscript policies in <tt>wsh</tt>:
+* <tt>wsh(and_v(v:pk(@0/**),or_d(pk(@1/**),older(12960))))</tt> - Trust-minimized second factor, degrading to a single signature after about 90 days.
+* <tt>wsh(thresh(3,pk(@0/**),s:pk(@1/**),s:pk(@2/**),sln:older(12960)))</tt> - A 3-of-3 wallet that becomes a 2-of-3 if coins are not spent for about 90 days.
+* <tt>wsh(or_d(pk(@0/**),and_v(v:multi(2,@1/**,@2/**,@3/**),older(65535))))</tt> - A singlesig wallet with automatic inheritance to a timelocked 2-of-3 multisig of family members.
+
+== Test Vectors ==
+
+=== Valid policies ===
+
+[[bip-0044.mediawiki|BIP-44]], first account
+ Descriptor template: pkh(@0/**)
+ Keys info: ["[6738736c/44'/0'/0']xpub6Br37sWxruYfT8ASpCjVHKGwgdnYFEn98DwiN76i2oyY6fgH1LAPmmDcF46xjxJr22gw4jmVjTE2E3URMnRPEPYyo1zoPSUba563ESMXCeb"]
+ Descriptor: pkh([6738736c/44'/0'/0']xpub6Br37sWxruYfT8ASpCjVHKGwgdnYFEn98DwiN76i2oyY6fgH1LAPmmDcF46xjxJr22gw4jmVjTE2E3URMnRPEPYyo1zoPSUba563ESMXCeb)
+<br>
+[[bip-0049.mediawiki|BIP-49]], second account
+ Descriptor template: sh(wpkh(@0/**))
+ Keys info: ["[6738736c/49'/0'/1']xpub6Bex1CHWGXNNwGVKHLqNC7kcV348FxkCxpZXyCWp1k27kin8sRPayjZUKDjyQeZzGUdyeAj2emoW5zStFFUAHRgd5w8iVVbLgZ7PmjAKAm9"]
+ Descriptor: sh(wpkh([6738736c/49'/0'/1']xpub6Bex1CHWGXNNwGVKHLqNC7kcV348FxkCxpZXyCWp1k27kin8sRPayjZUKDjyQeZzGUdyeAj2emoW5zStFFUAHRgd5w8iVVbLgZ7PmjAKAm9))
+<br>
+[[bip-0084.mediawiki|BIP-84]], third account
+ Descriptor template: wpkh(@0/**)
+ Keys info: ["[6738736c/84'/0'/2']xpub6CRQzb8u9dmMcq5XAwwRn9gcoYCjndJkhKgD11WKzbVGd932UmrExWFxCAvRnDN3ez6ZujLmMvmLBaSWdfWVn75L83Qxu1qSX4fJNrJg2Gt"]
+ Descriptor: wpkh([6738736c/84'/0'/2']xpub6CRQzb8u9dmMcq5XAwwRn9gcoYCjndJkhKgD11WKzbVGd932UmrExWFxCAvRnDN3ez6ZujLmMvmLBaSWdfWVn75L83Qxu1qSX4fJNrJg2Gt)
+<br>
+[[bip-0086.mediawiki|BIP-86]], first account
+ Descriptor template: tr(@0/**)
+ Keys info: ["[6738736c/86'/0'/0']xpub6CryUDWPS28eR2cDyojB8G354izmx294BdjeSvH469Ty3o2E6Tq5VjBJCn8rWBgesvTJnyXNAJ3QpLFGuNwqFXNt3gn612raffLWfdHNkYL"]
+ Descriptor: tr([6738736c/86'/0'/0']xpub6CryUDWPS28eR2cDyojB8G354izmx294BdjeSvH469Ty3o2E6Tq5VjBJCn8rWBgesvTJnyXNAJ3QpLFGuNwqFXNt3gn612raffLWfdHNkYL)
+<br>
+[[bip-0048.mediawiki|BIP-48]] P2WSH multisig
+ Descriptor template: wsh(sortedmulti(2,@0/**,@1/**))
+ Keys info: ["[6738736c/48'/0'/0'/2']xpub6FC1fXFP1GXLX5TKtcjHGT4q89SDRehkQLtbKJ2PzWcvbBHtyDsJPLtpLtkGqYNYZdVVAjRQ5kug9CsapegmmeRutpP7PW4u4wVF9JfkDhw", "[b2b1f0cf/48'/0'/0'/2']xpub6EWhjpPa6FqrcaPBuGBZRJVjzGJ1ZsMygRF26RwN932Vfkn1gyCiTbECVitBjRCkexEvetLdiqzTcYimmzYxyR1BZ79KNevgt61PDcukmC7"]
+ Descriptor: wsh(sortedmulti(2,[6738736c/48'/0'/0'/2']xpub6FC1fXFP1GXLX5TKtcjHGT4q89SDRehkQLtbKJ2PzWcvbBHtyDsJPLtpLtkGqYNYZdVVAjRQ5kug9CsapegmmeRutpP7PW4u4wVF9JfkDhw,[b2b1f0cf/48'/0'/0'/2']xpub6EWhjpPa6FqrcaPBuGBZRJVjzGJ1ZsMygRF26RwN932Vfkn1gyCiTbECVitBjRCkexEvetLdiqzTcYimmzYxyR1BZ79KNevgt61PDcukmC7))
+<br>
+Miniscript: A 3-of-3 that becomes a 2-of-3 after 90 days
+ Descriptor template: wsh(thresh(3,pk(@0/**),s:pk(@1/**),s:pk(@2/**),sln:older(12960)))
+ Keys info: ["[6738736c/48'/0'/0'/100']xpub6FC1fXFP1GXQpyRFfSE1vzzySqs3Vg63bzimYLeqtNUYbzA87kMNTcuy9ubr7MmavGRjW2FRYHP4WGKjwutbf1ghgkUW9H7e3ceaPLRcVwa", "[b2b1f0cf/44'/0'/0'/100']xpub6EYajCJHe2CK53RLVXrN14uWoEttZgrRSaRztujsXg7yRhGtHmLBt9ot9Pd5ugfwWEu6eWyJYKSshyvZFKDXiNbBcoK42KRZbxwjRQpm5Js", "[a666a867/44'/0'/0'/100']xpub6Dgsze3ujLi1EiHoCtHFMS9VLS1UheVqxrHGfP7sBJ2DBfChEUHV4MDwmxAXR2ayeytpwm3zJEU3H3pjCR6q6U5sP2p2qzAD71x9z5QShK2"]
+ Descriptor: wsh(thresh(3,pk([6738736c/48'/0'/0'/100']xpub6FC1fXFP1GXQpyRFfSE1vzzySqs3Vg63bzimYLeqtNUYbzA87kMNTcuy9ubr7MmavGRjW2FRYHP4WGKjwutbf1ghgkUW9H7e3ceaPLRcVwa/<0,1>/*),s:pk([b2b1f0cf/44'/0'/0'/100']xpub6EYajCJHe2CK53RLVXrN14uWoEttZgrRSaRztujsXg7yRhGtHmLBt9ot9Pd5ugfwWEu6eWyJYKSshyvZFKDXiNbBcoK42KRZbxwjRQpm5Js/<0,1>/*),s:pk([a666a867/44'/0'/0'/100']xpub6Dgsze3ujLi1EiHoCtHFMS9VLS1UheVqxrHGfP7sBJ2DBfChEUHV4MDwmxAXR2ayeytpwm3zJEU3H3pjCR6q6U5sP2p2qzAD71x9z5QShK2/<0,1>/*),sln:older(12960)))
+<br>
+Miniscript: A singlesig wallet with automatic inheritance to a timelocked 2-of-3 multisig
+ Descriptor template: wsh(or_d(pk(@0/**),and_v(v:multi(2,@1/**,@2/**,@3/**),older(65535))))
+ Keys info: ["[6738736c/48'/0'/0'/100']xpub6FC1fXFP1GXQpyRFfSE1vzzySqs3Vg63bzimYLeqtNUYbzA87kMNTcuy9ubr7MmavGRjW2FRYHP4WGKjwutbf1ghgkUW9H7e3ceaPLRcVwa", "[b2b1f0cf/44'/0'/0'/100']xpub6EYajCJHe2CK53RLVXrN14uWoEttZgrRSaRztujsXg7yRhGtHmLBt9ot9Pd5ugfwWEu6eWyJYKSshyvZFKDXiNbBcoK42KRZbxwjRQpm5Js", "[a666a867/44'/0'/0'/100']xpub6Dgsze3ujLi1EiHoCtHFMS9VLS1UheVqxrHGfP7sBJ2DBfChEUHV4MDwmxAXR2ayeytpwm3zJEU3H3pjCR6q6U5sP2p2qzAD71x9z5QShK2", "[bb641298/44'/0'/0'/100']xpub6Dz8PHFmXkYkykQ83ySkruky567XtJb9N69uXScJZqweYiQn6FyieajdiyjCvWzRZ2GoLHMRE1cwDfuJZ6461YvNRGVBJNnLA35cZrQKSRJ"]
+ Descriptor: wsh(or_d(pk([6738736c/48'/0'/0'/100']xpub6FC1fXFP1GXQpyRFfSE1vzzySqs3Vg63bzimYLeqtNUYbzA87kMNTcuy9ubr7MmavGRjW2FRYHP4WGKjwutbf1ghgkUW9H7e3ceaPLRcVwa),and_v(v:multi(2,[b2b1f0cf/44'/0'/0'/100']xpub6EYajCJHe2CK53RLVXrN14uWoEttZgrRSaRztujsXg7yRhGtHmLBt9ot9Pd5ugfwWEu6eWyJYKSshyvZFKDXiNbBcoK42KRZbxwjRQpm5Js,[a666a867/44'/0'/0'/100']xpub6Dgsze3ujLi1EiHoCtHFMS9VLS1UheVqxrHGfP7sBJ2DBfChEUHV4MDwmxAXR2ayeytpwm3zJEU3H3pjCR6q6U5sP2p2qzAD71x9z5QShK2,[bb641298/44'/0'/0'/100']xpub6Dz8PHFmXkYkykQ83ySkruky567XtJb9N69uXScJZqweYiQn6FyieajdiyjCvWzRZ2GoLHMRE1cwDfuJZ6461YvNRGVBJNnLA35cZrQKSRJ),older(65535))))
+<br>
+Taproot wallet policy with sortedmulti_a and a miniscript leaf
+ Descriptor template: tr(@0/**,{sortedmulti_a(1,@0/<2;3>/*,@1/**),or_b(pk(@2/**),s:pk(@3/**))})
+ Keys info: ["[6738736c/48'/0'/0'/100']xpub6FC1fXFP1GXQpyRFfSE1vzzySqs3Vg63bzimYLeqtNUYbzA87kMNTcuy9ubr7MmavGRjW2FRYHP4WGKjwutbf1ghgkUW9H7e3ceaPLRcVwa", "xpub6Fc2TRaCWNgfT49nRGG2G78d1dPnjhW66gEXi7oYZML7qEFN8e21b2DLDipTZZnfV6V7ivrMkvh4VbnHY2ChHTS9qM3XVLJiAgcfagYQk6K", "xpub6GxHB9kRdFfTqYka8tgtX9Gh3Td3A9XS8uakUGVcJ9NGZ1uLrGZrRVr67DjpMNCHprZmVmceFTY4X4wWfksy8nVwPiNvzJ5pjLxzPtpnfEM", "xpub6GjFUVVYewLj5no5uoNKCWuyWhQ1rKGvV8DgXBG9Uc6DvAKxt2dhrj1EZFrTNB5qxAoBkVW3wF8uCS3q1ri9fueAa6y7heFTcf27Q4gyeh6"]
+ Descriptor: tr([6738736c/48'/0'/0'/100']xpub6FC1fXFP1GXQpyRFfSE1vzzySqs3Vg63bzimYLeqtNUYbzA87kMNTcuy9ubr7MmavGRjW2FRYHP4WGKjwutbf1ghgkUW9H7e3ceaPLRcVwa/<0;1>/*,{sortedmulti_a(1,xpub6FC1fXFP1GXQpyRFfSE1vzzySqs3Vg63bzimYLeqtNUYbzA87kMNTcuy9ubr7MmavGRjW2FRYHP4WGKjwutbf1ghgkUW9H7e3ceaPLRcVwa/<2;3>/*,xpub6Fc2TRaCWNgfT49nRGG2G78d1dPnjhW66gEXi7oYZML7qEFN8e21b2DLDipTZZnfV6V7ivrMkvh4VbnHY2ChHTS9qM3XVLJiAgcfagYQk6K/<0;1>/*),or_b(pk(xpub6GxHB9kRdFfTqYka8tgtX9Gh3Td3A9XS8uakUGVcJ9NGZ1uLrGZrRVr67DjpMNCHprZmVmceFTY4X4wWfksy8nVwPiNvzJ5pjLxzPtpnfEM/<0;1>/*),s:pk(xpub6GjFUVVYewLj5no5uoNKCWuyWhQ1rKGvV8DgXBG9Uc6DvAKxt2dhrj1EZFrTNB5qxAoBkVW3wF8uCS3q1ri9fueAa6y7heFTcf27Q4gyeh6/<0;1>/*))})
+<br>
+
+=== Invalid policies ===
+
+The following descriptor templates are invalid:
+
+* <tt>pkh(@0)</tt>: Key placeholder with no path following it
+* <tt>pkh(@0/0/**)</tt>: Key placeholder with an explicit path present
+* <tt>sh(multi(1,@1/**,@0/**))</tt>: Key placeholders out of order
+* <tt>sh(multi(1,@0/**,@2/**))</tt>: Skipped key placeholder <tt>@1</tt>
+* <tt>sh(multi(1,@0/**,@0/**))</tt>: Repeated keys with the same path expression
+* <tt>sh(multi(1,@0/<0;1>/*,@0/<1;2>/*))</tt>: Non-disjoint multipath expressions (<tt>@0/1/*</tt> appears twice)
+* <tt>sh(multi(1,@0/**,xpub6AHA9hZDN11k2ijHMeS5QqHx2KP9aMBRhTDqANMnwVtdyw2TDYRmF8PjpvwUFcL1Et8Hj59S3gTSMcUQ5gAqTz3Wd8EsMTmF3DChhqPQBnU/<0;1>/*))</tt>: Expression with a non-KP key present
+* <tt>pkh(@0/<0;1;2>/*)</tt>: Solved cardinality > 2
+
+Remark: some of the examples of invalid descriptor templates may be valid via optional extensions.
+
+== Backwards Compatibility ==
+
+The <tt>@</tt> character used for key placeholders is not part of the syntax of output script descriptors, therefore any valid descriptor with at least one <tt>KEY</tt> expression is not a valid descriptor template. Vice versa, any descriptor template with at least one key placeholder is not a valid output script descriptor.
+
+Adoption of wallet policies in software and hardware wallets is opt-in. Conversion from wallet policies to the corresponding descriptors is programmatically extremely easy, and conversion from descriptors to wallet policies (when respecting the required patterns) can be automated. See the reference implementation below for some examples of conversion.
+
+Software wallets are recommended to allow exporting plain descriptors for the purposes of interoperability with software not using wallet policies.
+
+== Reference Implementation ==
+
+Wallet policies are implemented in
+* the [https://github.com/LedgerHQ/app-bitcoin-new Ledger bitcoin application] since version 2.1.0;
+* the [https://github.com/digitalbitbox/bitbox02-firmware BitBox02 firmware] since version v9.15.0;
+* [https://github.com/Blockstream/Jade Blockstream Jade] since version v1.0.24, via [https://github.com/ElementsProject/libwally-core libwally-core] v1.0.0.
+
+For development and testing purposes, we provide a [[bip-0388/wallet_policies.py|Python 3.7 reference implementation]] of simple classes to handle wallet policies, and the conversion to/from output script descriptors.
+The reference implementation is for demonstration purposes only and not to be used in production environments.
+
+==Footnotes==
+
+<references />
+
+== Acknowledgments ==
+
+The authors would like to thank the people who provided feedback in the bitcoin-dev list, and in person.
diff --git a/bip-0388/wallet_policies.py b/bip-0388/wallet_policies.py
new file mode 100755
index 0000000..4cd5031
--- /dev/null
+++ b/bip-0388/wallet_policies.py
@@ -0,0 +1,202 @@
+#!/usr/bin/env python3
+
+from typing import Iterable, List, Mapping, Tuple, Generator
+
+
+def find_all(text: str, pattern: str, start: int = 0) -> Generator[int, None, None]:
+ """Generates all the positions of `pattern` as a substring of `text`, starting from index at least `start`."""
+ while True:
+ start = text.find(pattern, start)
+ if start == -1:
+ return
+ yield start
+ start += len(pattern)
+
+
+def find_first(text: str, start_pos: int, patterns: Iterable[str]) -> int:
+ """Returns the position of the first occurrence of any of the elements in `patterns` as a substring of `text`,
+ or -1 if none of the patterns is found."""
+ matches = (text.find(x, start_pos) for x in patterns)
+ return min((x for x in matches if x != -1), default=-1)
+
+
+def find_key_end_position(desc: str, start_pos: int) -> int:
+ """Assuming that `start_pos` is the beginning of a KEY expression (and not musig), finds the position of the end
+ of the key expression, excluding (if present) the final derivation steps after an xpub. This is the information
+ that goes into an entry of the vector of key information of the wallet policy."""
+
+ has_orig_info = True if desc[start_pos] == '[' else False
+
+ if has_orig_info:
+ closing_bracket_pos = desc.find("]", start_pos)
+ if closing_bracket_pos == -1:
+ raise Exception("Invalid descriptor: could not find closing ']'")
+ key_pos_start = closing_bracket_pos + 1
+ else:
+ key_pos_start = start_pos
+
+ # find the earliest occurrence of ",", a ")" or a "/" (it must find at least 1)
+ end_pos = find_first(desc, key_pos_start, [",", ")", "/"])
+ if end_pos == -1:
+ raise Exception(
+ "Invalid descriptor: cannot find the end of key expression")
+
+ return end_pos
+
+
+class WalletPolicy(object):
+ """Simple class to represent wallet policies. This is a toy implementation that does not parse the descriptor
+ template. A more robust implementation would build the abstract syntax tree of the template and of the descriptor,
+ allowing one to detect errors, and manipulate it semantically instead of relying on string manipulation."""
+
+ def __init__(self, descriptor_template: str, keys_info: List[str]):
+ self.descriptor_template = descriptor_template
+ self.keys_info = keys_info
+
+ def to_descriptor(self) -> str:
+ """Converts a wallet policy into the descriptor (with the /<M,N> syntax, if present)."""
+
+ desc = self.descriptor_template
+
+ # replace each "/**" with "/<0;1>/*"
+ desc = desc.replace("/**", "/<0;1>/*")
+
+ # process all the @N expressions in decreasing order. This guarantees that string replacements
+ # works as expected (as any prefix expression is processed after).
+ for i in reversed(range(len(self.keys_info))):
+ desc = desc.replace(f"@{i}", self.keys_info[i])
+
+ # there should not be any remaining "@" expressions
+ if desc.find("@") != -1:
+ return Exception("Invalid descriptor template: contains invalid key index")
+
+ return desc
+
+ @classmethod
+ def from_descriptor(cls, descriptor: str) -> 'WalletPolicy':
+ """Converts a "reasonable" descriptor (with the /<M,N> syntax) into the corresponding wallet policy."""
+
+ # list of pairs of integers, where the tuple (m,n) with m < n means a key expression starts at
+ # m (inclusive) and at n (exclusive)
+ key_expressions: List[Tuple[int, int]] = []
+
+ key_with_orig_pos_start = None
+
+ def parse_key_expressions(only_first=False, handle_musig=False):
+ # Starting at the position in `key_with_orig_pos_start`, parses a number of key expressions, and updates
+ # the `key_expressions` array accordingly.
+ # If `only_first` is `True`, it stops after parsing a single key expression.
+ # If `handle_musig` is `True`, and a key expression is a `musig` operator, it recursively parses
+ # the keys in the musig expression. `musig` inside `musig` is not allowed.
+
+ nonlocal key_with_orig_pos_start
+ if key_with_orig_pos_start is None:
+ raise Exception("Unexpected error")
+
+ while True:
+ if handle_musig and descriptor[key_with_orig_pos_start:].startswith("musig"):
+ closing_parenthesis_pos = find_first(
+ descriptor, key_with_orig_pos_start, [")"])
+ if closing_parenthesis_pos == -1:
+ raise Exception(
+ "Invalid descriptor: musig without closing parenthesis")
+ key_with_orig_pos_start = key_with_orig_pos_start + \
+ len("musig(")
+ parse_key_expressions(
+ only_first=False, handle_musig=False)
+
+ key_pos_end = closing_parenthesis_pos + 1
+ else:
+ key_pos_end = find_key_end_position(
+ descriptor, key_with_orig_pos_start)
+ key_expressions.append(
+ (key_with_orig_pos_start, key_pos_end))
+
+ if descriptor[key_pos_end] == '/':
+ # find the actual end (comma or closing parenthesis)
+ key_pos_end = find_first(
+ descriptor, key_pos_end, [",", ")"])
+ if key_pos_end == -1:
+ raise Exception(
+ "Invalid descriptor: unterminated key expression")
+
+ if descriptor[key_pos_end] == ',':
+ # There is another key expression, repeat from after the comma
+ key_with_orig_pos_start = key_pos_end + 1
+ else:
+ break
+
+ if only_first:
+ break
+
+ # operators for which the KEY is the first argument
+ operators_key_first = ["pk", "pkh", "pk_h", "pk_k", "tr"]
+ # operators for which the KEY is everything except the first argument
+ operators_key_all_but_first = [
+ "multi", "sortedmulti", "multi_a", "sortedmulti_a"]
+ for op in operators_key_first + operators_key_all_but_first:
+ for op_pos_start in find_all(descriptor, op + "("):
+
+ # ignore if not a whole word (otherwise "sortedmulti" would be found inside "multi")
+ if op_pos_start > 0 and 'a' <= desc[op_pos_start - 1] <= 'z':
+ continue
+
+ if op in operators_key_all_but_first:
+ # skip the first argument (we now it's not a KEY expression, so it does not have a comma)
+ first_comma_pos = descriptor.find(",", op_pos_start)
+ if first_comma_pos == -1:
+ raise Exception(
+ "Invalid descriptor: multi, sortedmulti, multi_a and sortedmulti_a must have at least two arguments")
+ key_with_orig_pos_start = 1 + first_comma_pos
+ else:
+ # other operators, the first argument is already a KEY expression
+ key_with_orig_pos_start = op_pos_start + len(op) + 1
+
+ only_first = op in operators_key_first
+ parse_key_expressions(
+ only_first=only_first, handle_musig=True)
+
+ result: List[str] = []
+ keys: List[str] = []
+ keys_to_idx: Mapping[str, int] = {}
+
+ prev_end = 0
+ for start, end in sorted(key_expressions):
+ result.append(descriptor[prev_end:start])
+
+ key = descriptor[start:end]
+ if key not in keys_to_idx:
+ idx = len(keys)
+ keys.append(key)
+ keys_to_idx[key] = idx
+ else:
+ idx = keys_to_idx[key]
+ result.append(f"@{idx}")
+
+ prev_end = end
+
+ result.append(descriptor[prev_end:])
+
+ return cls("".join(result), keys)
+
+
+if __name__ == "__main__":
+ descriptors = [
+ "pkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/**)",
+ "wsh(multi(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/**,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/**))",
+ "tr([12345678/44'/0'/0']xpub6BVZ6JrGsWsUbpP74S8rnz13hVFDtYtKyuTTEYPNSF6GFpDFpL1YXWg3BpwpUWAnsZZ7Qe3XKz7GL3BEx3RQVq61cxqSkjceq25S1xFKFVa,{pk(xpub6AGdromjXf5yf3m7ndaCoR9Ac3UjwTvQ7QQkZoyoh2vfGE9i1AwB2vCbvjTpBL1KRERUsGszg63SVNXsHZU3CiykQqtZPrdXKMdaG2vs6uu),pk(xpub6AnhdkteWC4kPQvkY3QQXGmDCMfmFoYzEQ7FwRFa4BQ1a22k4VL4BD3Jdcog2Sf2KzBscXXAdPRMgjCBDeq6bAryqnMaWX2FaVUGPxWMLDh)})",
+ "tr(xpub6AEWqA1MNRzBBXenkug4NtNguDKTNcXoKQj8fU9VQyid38yikruFRffjoDm9UEaHGEJ6jQxjYdWWZRxR7Xy5ePrQNjohXJuNzkRNSiiBUcE,sortedmulti_a(2,[11223344/44'/0'/0']xpub6AyJhEKxcPaPnYNuA7VBeUQ24v6mEzzPSX5AJm3TSyg1Zsti7rnGKy1Hg6JAdXKF4QUmFZbby9p97AjBNm2VFCEec2ip5C9JntyxosmCeMW,xpub6AQVHBgieCHpGo4GhpGAo4v9v7hfr2Kr4D8ZQJqJwbEyZwtW3pWYSLRQyrNYbTzpoq6XpFtaKZGnEGUMtiydCgqsJDAZNqs9L5QDNKqUBsV))",
+ "tr([11111111/44'/0'/0']xpub6CLZSUDtcUhJVDoPSY8pSRKi4W1RSSLBgwZ2AYmwTH9Yv5tPVFHZxJBUQ27QLLwHej6kfo9DQQbwaHmpXsQq59CjtsE2gNLHmojwgMrsQNe/**,{and_v(v:pk([22222222/44'/0'/0']xpub6CiztfGsUxmpwkWe6gvz8d5VHyFLDoiPpeUfWmQ2vWAhQL3Z1hhEc6PE4irFs4bzjS7dCB4yyinaubrCpFJq4bcKGCD4jjqTxaWiKAJ7mvJ/**),older(52596)),multi_a(2,[33333333/44'/0'/0']xpub6DTZd6od7is2wxXndmE7zaUifzFPwVKshVSGEZedfTJtUjfLyhy4hgCW15hvxRpGaDmtiFoJKaCEaSRfXrQBuYRx18zwquy46dwBsJnsrz2/**,[44444444/44'/0'/0']xpub6BnK4wFbPeLZM4VNjoUA4yLCru6kCT3bhDJNBhbzHLGp1fmgK6muz27h4drixJZeHG8vSS5U5EYyE3gE8ozG94iNg3NDYE8M5YafvhzhMR9/**)})",
+ "tr(musig([33333333/44'/0'/0']xpub6DTZd6od7is2wxXndmE7zaUifzFPwVKshVSGEZedfTJtUjfLyhy4hgCW15hvxRpGaDmtiFoJKaCEaSRfXrQBuYRx18zwquy46dwBsJnsrz2,[44444444/44'/0'/0']xpub6BnK4wFbPeLZM4VNjoUA4yLCru6kCT3bhDJNBhbzHLGp1fmgK6muz27h4drixJZeHG8vSS5U5EYyE3gE8ozG94iNg3NDYE8M5YafvhzhMR9)/**,{and_v(v:pk([22222222/44'/0'/0']xpub6CiztfGsUxmpwkWe6gvz8d5VHyFLDoiPpeUfWmQ2vWAhQL3Z1hhEc6PE4irFs4bzjS7dCB4yyinaubrCpFJq4bcKGCD4jjqTxaWiKAJ7mvJ/**),older(52596)),pk([11111111/44'/0'/0']xpub6CLZSUDtcUhJVDoPSY8pSRKi4W1RSSLBgwZ2AYmwTH9Yv5tPVFHZxJBUQ27QLLwHej6kfo9DQQbwaHmpXsQq59CjtsE2gNLHmojwgMrsQNe/**)})",
+ ]
+
+ for desc in descriptors:
+ # Demoes the conversion from a "sane" descriptor to a wallet policy
+ print(f"Descriptor:\n{desc}")
+ wp = WalletPolicy.from_descriptor(desc)
+ print(f"Policy descriptor template:\n{wp.descriptor_template}")
+ print(f"Keys:\n{wp.keys_info}")
+ print("======================================================\n")
+
+ # Converting back to descriptors also works, as long as we take care of /**
+ assert wp.to_descriptor().replace("/<0;1>/*", "/**") == desc
diff --git a/scripts/buildtable.pl b/scripts/buildtable.pl
index 292f1ee..4923a9e 100755
--- a/scripts/buildtable.pl
+++ b/scripts/buildtable.pl
@@ -96,6 +96,9 @@ my %emails;
my $bipnum = 0;
while (++$bipnum <= $topbip) {
my $fn = sprintf "bip-%04d.mediawiki", $bipnum;
+ if (!-e $fn) {
+ $fn = sprintf "bip-%04d.md", $bipnum;
+ }
-e $fn || next;
open my $F, "<$fn";
while (<$F> !~ m[^(?:\xef\xbb\xbf)?<pre>$]) {
diff --git a/scripts/diffcheck.sh b/scripts/diffcheck.sh
index 4e4c459..aa9f557 100755
--- a/scripts/diffcheck.sh
+++ b/scripts/diffcheck.sh
@@ -1,5 +1,6 @@
#!/bin/bash
+scripts/buildtable.pl >/tmp/table.mediawiki 2> /dev/null
diff README.mediawiki /tmp/table.mediawiki | grep '^[<>] |' >/tmp/after.diff || true
if git checkout HEAD^ && scripts/buildtable.pl >/tmp/table.mediawiki 2>/dev/null; then
diff README.mediawiki /tmp/table.mediawiki | grep '^[<>] |' >/tmp/before.diff || true
@@ -8,6 +9,8 @@ if git checkout HEAD^ && scripts/buildtable.pl >/tmp/table.mediawiki 2>/dev/null
echo "$newdiff"
exit 1
fi
+ echo "README table matches expected table from BIP files"
else
echo 'Cannot build previous commit table for comparison'
+ exit 1
fi
diff --git a/scripts/link-format-chk.sh b/scripts/link-format-chk.sh
index e3f0f6d..9493765 100755
--- a/scripts/link-format-chk.sh
+++ b/scripts/link-format-chk.sh
@@ -8,16 +8,14 @@
ECODE=0
FILES=""
-for fname in $(git diff --name-only HEAD $(git merge-base HEAD master)); do
- if [[ $fname == *.mediawiki ]]; then
- GRES=$(grep -n '](http' $fname)
- if [ "$GRES" != "" ]; then
- if [ $ECODE -eq 0 ]; then
- >&2 echo "Github Mediawiki format writes link as [URL text], not as [text](url):"
- fi
- ECODE=1
- echo "- $fname:$GRES"
+for fname in *.mediawiki; do
+ GRES=$(grep -n '](http' $fname)
+ if [ "$GRES" != "" ]; then
+ if [ $ECODE -eq 0 ]; then
+ >&2 echo "Github Mediawiki format writes link as [URL text], not as [text](url):"
fi
+ ECODE=1
+ echo "- $fname:$GRES"
fi
done
exit $ECODE