Merge pull request #444 from harding/hardware-wallets

Add Subsection About Wallet Programs, Incl. Hardware Wallets
This commit is contained in:
saivann 2014-06-09 13:20:41 -04:00
commit 8e2b00b548
12 changed files with 750 additions and 10 deletions

View file

@ -36,6 +36,7 @@ change output:
change outputs: change output change outputs: change output
child key: child key:
child keys: child key child keys: child key
child private and public keys: child key
child public key: child public key:
child public keys: child public key child public keys: child public key
coinbase: coinbase transaction coinbase: coinbase transaction
@ -122,7 +123,9 @@ p2pkh:
p2sh: p2sh:
p2sh multisig: p2sh multisig:
parent chain code: parent chain code:
parent key:
parent private key: parent private key:
parent private and public keys: parent key
parent public key: parent public key:
Payment message: pp payment Payment message: pp payment
payment protocol: payment protocol:

View file

@ -2,11 +2,259 @@
{% autocrossref %} {% autocrossref %}
Bitcoin wallets at their core are a collection of private keys. These collections are stored digitally in a file, or can even be physically stored on pieces of paper. A Bitcoin wallet can refer to either a wallet program or a wallet file.
Wallet programs create public keys to receive satoshis and use the
corresponding private keys to spend those satoshis. Wallet files
store private keys and (optionally) other information related to
transactions for the wallet program.
Wallet programs and wallet files are addressed below in separate
subsections, and this document attempts to always make it clear whether
we're talking about wallet programs or wallet files.
{% endautocrossref %} {% endautocrossref %}
### Private Key Formats ### Wallet Programs
{% autocrossref %}
Permitting receiving and spending of satoshis is the only essential
feature of wallet software---but a particular wallet program doesn't
need to do both things. Two wallet programs can work together, one
program distributing public keys in order to receive satoshis and
another program signing transactions spending those satoshis.
Wallet programs also need to interact with the peer-to-peer network to
get information from the block chain and to broadcast new transactions.
However, the programs which distribute public keys or sign transactions
don't need to interact with the peer-to-peer network themselves.
This leaves us with three necessary, but separable, parts of a wallet
system: a public key distribution program, a signing program, and a
networked program. In the subsections below, we will describe common
combinations of these parts.
Note: we speak about distributing public keys generically. In many
cases, P2PKH or P2SH hashes will be distributed instead of public keys,
with the actual public keys only being distributed when the outputs
they control are spent.
{% endautocrossref %}
#### Full-Service Wallets
{% autocrossref %}
The simplest wallet is a program which performs all three functions: it
generates private keys, derives the corresponding public keys, helps
distribute those public keys as necessary, monitors for outputs spent to
those public keys, creates and signs transactions spending those
outputs, and broadcasts the signed transactions.
![Full-Service Wallets](/img/dev/en-wallets-full-service.svg)
As of this writing, almost all popular wallets can be used as
full-service wallets.
The main advantage of full-service wallets is that they are easy to use.
A single program does everything the user needs to receive and spend
satoshis.
The main disadvantage of full-service wallets is that they store the
private keys on a device connected to the Internet. The compromise of
such devices is a common occurrence, and an Internet connection makes it
easy to transmit private keys from a compromised device to an attacker.
To help protect against theft, many wallet programs offer users the
option of encrypting the wallet files which contain the private keys.
This protects the private keys when they aren't being used, but it
cannot protect against an attack designed to capture the encryption
key or to read the decrypted keys from memory.
{% endautocrossref %}
#### Signing-Only Wallets
{% autocrossref %}
To increase security, private keys can be generated and stored by a
separate wallet program operating in a more secure environment. These
signing-only wallets work in conjunction with a networked wallet which
interacts with the peer-to-peer network.
Signing-only wallets programs typically use deterministic key creation
(described in a later subsection) to create parent private and public
keys which can create child private and public keys.
![Signing-Only Wallets](/img/dev/en-wallets-signing-only.svg)
When first run, the signing-only wallet creates a parent private key and
transfers the corresponding parent public key to the networked wallet.
The networked wallet uses the parent public key to derive child public
keys, optionally helps distribute them, monitors for outputs spent to
those public keys, creates unsigned transactions spending those outputs,
and transfers the unsigned transactions to the signing-only wallet.
Often, users are given a chance to review the unsigned transactions' details
(particularly the output details) using the signing-only wallet.
After the optional review step, the offline wallet uses the parent
private key to derive the appropriate child private keys and signs the
transactions, giving the signed transactions back to the networked wallet.
The networked wallet then broadcasts the signed transactions to the
peer-to-peer network.
The following subsections describe the two most common variants of
signing-only wallets: offline wallets and hardware wallets.
{% endautocrossref %}
##### Offline Wallets
{% autocrossref %}
Several full-service wallets programs will also operate as two separate
wallets: one program instance acting as a signing-only wallet (often called an
"offline wallet") and the other program instance acting as the networked
wallet (often called an "online wallet" or "watching-only wallet").
The offline wallet is so named because it is intended to be run on a
device which does not connect to any network, greatly reducing the
number of attack vectors. If this is the case, it is usually up to the
user to handle all data transfer using removable media such as USB
drives. The user's workflow is something like:
1. (Offline) Disable all network connections on a device and install the wallet
software. Start the wallet software in offline mode to create the
parent private and public keys. Copy the parent public key to
removable media.
2. (Online) Install the wallet software on another device, this one
connected to the Internet, and import the parent public key from the
removable media. As you would with a full-service wallet, distribute
public keys to receive payment. When ready to spend satoshis, fill in
the output details and save the unsigned transaction generated by the
wallet to removable media.
3. (Offline) Open the unsigned transaction in the offline instance,
review the output details to make sure they spend the correct
amount to the correct address. This prevents malware on the online
wallet from tricking the user into signing a transaction which pays
an attacker. After review, sign the transaction and save it to
removable media.
4. (Online) Open the signed transaction in the online instance so it can
broadcast it to the peer-to-peer network.
The primary advantage of offline wallets is their possibility for
greatly improved security over full-service wallets. As long as the
offline wallet is not compromised (or flawed) and the user reviews all outgoing
transactions before signing, the user's satoshis are safe even if the
online wallet is compromised.
The primary disadvantage of offline wallets is hassle. For maximum
security, they require the user dedicate a device to only offline tasks.
The offline device must be booted up whenever funds are to be spent, and
the user must physically copy data from the online device to the offline
device and back.
{% endautocrossref %}
##### Hardware Wallets
{% autocrossref %}
Hardware wallets are devices dedicated to running a signing-only wallet.
Their dedication lets them eliminate many of the vulnerabilities
present in operating systems designed for general use, allowing them
to safely communicate directly with other devices so users don't need to
transfer data manually. The user's workflow is something like:
1. (Hardware) Create parent private and public keys. Connect hardware
wallet to a networked device so it can get the parent public key.
2. (Networked) As you would with a full-service wallet, distribute
public keys to receive payment. When ready to spend satoshis, fill in
the transaction details, connect the hardware wallet, and click
Spend. The networked wallet will automatically send the transaction
details to the hardware wallet.
3. (Hardware) Review the transaction details on the hardware wallet's
screen. Some hardware wallets may prompt for a passphrase or PIN
number. The hardware wallet signs the transaction and uploads it to
the networked wallet.
4. (Networked) The networked wallet receives the signed transaction from
the hardware wallet and broadcasts it to the network.
The primary advantage of hardware wallets is their possibility for
greatly improved security over full-service wallets with much less
hassle than offline wallets.
The primary disadvantage of hardware wallets is their hassle. Even
though the hassle is less than that of offline wallets, the user must
still purchase a hardware wallet device and carry it with them whenever
they need to make a transaction using the signing-only wallet.
An additional (hopefully temporary) disadvantage is that, as of this
writing, very few popular wallet programs support hardware
wallets---although almost all popular wallet programs have announced
their intention to support at least one model of hardware wallet.
{% endautocrossref %}
#### Distributing-Only Wallets
{% autocrossref %}
Wallet programs which run in difficult-to-secure environments, such as
webservers, can be designed to distribute public keys (including P2PKH
or P2SH addresses) and nothing more. There are two common ways to
design these minimalist wallets:
![Distributing-Only Wallets](/img/dev/en-wallets-distributing-only.svg)
* Pre-populate a database with a number of public keys or addresses, and
then distribute on request an output script or address using one of
the database entries. To [avoid key reuse][devguide avoiding key
resuse], webservers should keep track
of used keys and never run out of public keys. This can be made easier
by using parent public keys as suggested in the next method.
* Use a parent public key to create child public keys. To avoid key
reuse, a method must be used to ensure the same public key isn't
distributed twice. This can be a database entry for each key
distributed or an incrementing pointer to the current child key
index number.
Neither method adds a significant amount of overhead, especially if a
database is used anyway to associate each incoming payment with a
separate public key for payment tracking. See the [Payment
Processing][devguide payment processing] section for details.
{% endautocrossref %}
### Wallet Files
{% autocrossref %}
Bitcoin wallets at their core are a collection of private keys. These
collections are stored digitally in a file, or can even be physically
stored on pieces of paper.
{% endautocrossref %}
#### Private Key Formats
{% autocrossref %} {% autocrossref %}
@ -16,7 +264,7 @@ Private keys are what are used to unlock satoshis from a particular address. In
{% endautocrossref %} {% endautocrossref %}
#### Wallet Import Format (WIF) ##### Wallet Import Format (WIF)
{% autocrossref %} {% autocrossref %}
@ -40,7 +288,7 @@ The process is easily reversible, using the Base58 decoding function, and removi
{% endautocrossref %} {% endautocrossref %}
#### Mini Private Key Format ##### Mini Private Key Format
{% autocrossref %} {% autocrossref %}
@ -62,7 +310,7 @@ address utility].
{% endautocrossref %} {% endautocrossref %}
### Hierarchical Deterministic Key Creation #### Hierarchical Deterministic Key Creation
<!-- <!--
For consistent word ordering: For consistent word ordering:
@ -109,7 +357,7 @@ sum divided by a global constant used by all Bitcoin software (*G*):
This means that two or more independent programs which agree on a This means that two or more independent programs which agree on a
sequence of integers can create a series of unique [child key][]{:#term-child-key}{:.term} pairs from sequence of integers can create a series of unique [child key][]{:#term-child-key}{:.term} pairs from
a single parent key pair without any further communication. a single [parent key][]{:#term-parent-key}{:.term} pair without any further communication.
Moreover, the program which distributes new public keys for receiving Moreover, the program which distributes new public keys for receiving
payment can do so without any access to the private keys, allowing the payment can do so without any access to the private keys, allowing the
public key distribution program to run on a possibly-insecure platform such as public key distribution program to run on a possibly-insecure platform such as
@ -211,7 +459,7 @@ which makes them special.
{% endautocrossref %} {% endautocrossref %}
#### Hardened Keys ##### Hardened Keys
{% autocrossref %} {% autocrossref %}
@ -300,7 +548,7 @@ for the full HD protocol specification.
{% endautocrossref %} {% endautocrossref %}
#### Storing Root Seeds ##### Storing Root Seeds
{% autocrossref %} {% autocrossref %}
@ -335,7 +583,7 @@ For implementation details, please see BIP39.
### Loose-Key Wallets #### Loose-Key Wallets
{% autocrossref %} {% autocrossref %}

View file

@ -86,6 +86,7 @@
[P2SH]: /en/developer-guide#term-p2sh "A script which Pays To Script Hashes (P2SH), allowing convenient spending of satoshis to an address referencing a script" [P2SH]: /en/developer-guide#term-p2sh "A script which Pays To Script Hashes (P2SH), allowing convenient spending of satoshis to an address referencing a script"
[P2SH multisig]: /en/developer-guide#term-p2sh-multisig "A multisig script embedded in the redeemScript of a pay-to-script-hash (P2SH) transaction" [P2SH multisig]: /en/developer-guide#term-p2sh-multisig "A multisig script embedded in the redeemScript of a pay-to-script-hash (P2SH) transaction"
[parent chain code]: /en/developer-guide#term-parent-chain-code "A chain code which has helped create child public or private keys" [parent chain code]: /en/developer-guide#term-parent-chain-code "A chain code which has helped create child public or private keys"
[parent key]: /en/developer-guide#term-parent-key "In HD wallets, a key capable of deriving child keys"
[parent private key]: /en/developer-guide#term-parent-private-key "A private key which has created child private keys" [parent private key]: /en/developer-guide#term-parent-private-key "A private key which has created child private keys"
[parent public key]: /en/developer-guide#term-parent-public-key "A public key corresponding to a parent private key which has child private keys" [parent public key]: /en/developer-guide#term-parent-public-key "A public key corresponding to a parent private key which has child private keys"
[payment protocol]: /en/developer-guide#term-payment-protocol "The protocol defined in BIP70 which lets spenders get signed payment details from receivers" [payment protocol]: /en/developer-guide#term-payment-protocol "The protocol defined in BIP70 which lets spenders get signed payment details from receivers"
@ -101,7 +102,6 @@
[private keys]: /en/developer-guide#term-private-key "The private portion of a keypair which can create signatures which other people can verify using the public key" [private keys]: /en/developer-guide#term-private-key "The private portion of a keypair which can create signatures which other people can verify using the public key"
[pubkey hash]: /en/developer-guide#term-pubkey-hash "The hash of a public key which can be included in a P2PKH output" [pubkey hash]: /en/developer-guide#term-pubkey-hash "The hash of a public key which can be included in a P2PKH output"
[public key]: /en/developer-guide#term-public-key "The public portion of a keypair which can be safely distributed to other people so they can verify a signature created with the corresponding private key" [public key]: /en/developer-guide#term-public-key "The public portion of a keypair which can be safely distributed to other people so they can verify a signature created with the corresponding private key"
[public keys]: /en/developer-guide#term-public-key "The public portion of a keypair which can be safely distributed to other people so they can verify a signature created with the corresponding private key"
[pp amount]: /en/developer-guide#term-pp-amount "Part of the Output part of the PaymentDetails part of a payment protocol where receivers can specify the amount of satoshis they want paid to a particular output script" [pp amount]: /en/developer-guide#term-pp-amount "Part of the Output part of the PaymentDetails part of a payment protocol where receivers can specify the amount of satoshis they want paid to a particular output script"
[pp expires]: /en/developer-guide#term-pp-expires "The expires field of a PaymentDetails where the receiver tells the spender when the PaymentDetails expires" [pp expires]: /en/developer-guide#term-pp-expires "The expires field of a PaymentDetails where the receiver tells the spender when the PaymentDetails expires"
[pp memo]: /en/developer-guide#term-pp-memo "The memo fields of PaymentDetails, Payment, and PaymentACK which allow spenders and receivers to send each other memos" [pp memo]: /en/developer-guide#term-pp-memo "The memo fields of PaymentDetails, Payment, and PaymentACK which allow spenders and receivers to send each other memos"
@ -180,6 +180,8 @@
[core paymentrequest.proto]: https://github.com/bitcoin/bitcoin/blob/master/src/qt/paymentrequest.proto [core paymentrequest.proto]: https://github.com/bitcoin/bitcoin/blob/master/src/qt/paymentrequest.proto
[core script.h]: https://github.com/bitcoin/bitcoin/blob/master/src/script.h [core script.h]: https://github.com/bitcoin/bitcoin/blob/master/src/script.h
[DER]: https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One [DER]: https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One
[devguide avoiding key reuse]: /en/developer-guide#avoiding-key-reuse
[devguide payment processing]: /en/developer-guide#payment-processing
[devguide wallets]: /en/developer-guide#wallets [devguide wallets]: /en/developer-guide#wallets
[devref wallets]: /en/developer-reference#wallets [devref wallets]: /en/developer-reference#wallets
[docs issue]: https://github.com/bitcoin/bitcoin.org/issues [docs issue]: https://github.com/bitcoin/bitcoin.org/issues

View file

@ -0,0 +1,50 @@
digraph wallet_program {
size="6.25";
rankdir=LR;
//ratio=fill;
splines=true;
fontname=Sans
ranksep=0.3;
penwidth=1.75;
overlap = false;
edge [ fontname=Sans, penwidth=1.75, style = "invis" ];
node [ fontname=Sans, shape = box, penwidth=1.75 ];
subgraph cluster_distributing {
penwidth=0;
distributing_priv [ label = "Create\nParent\nPrivate\nKey", style="invis" ];
distributing_pub [ label = "Derive\nChild\nPublic\nKeys" ];
distributing_distribute [ label = "Distribute\nPublic\nKeys" ];
distributing_monitor [ label = "Monitor\nFor\nOutputs", style="invis" ];
distributing_create [ label = "Create\nUnsigned\nTxes", style="invis" ];
distributing_sign [ label = "Sign\nTxes", style="invis" ];
distributing_broadcast [ label = "Broadcast\nTxes", style="invis" ];
distributing_priv -> distributing_pub -> distributing_distribute -> distributing_monitor -> distributing_create -> distributing_sign -> distributing_broadcast;
label = "Distributing-Only Wallet"
}
subgraph cluster_networked {
penwidth=0;
networked_priv [ label = "Create\nParent\nPrivate\nKey" ];
networked_pub [ label = "Derive\nParent\nPublic\nKey" ];
networked_distribute [ label = "Distribute\nPublic\nKeys", style="invis" ];
networked_monitor [ label = "Monitor\nFor\nOutputs" ];
networked_create [ label = "Create\nUnsigned\nTxes" ];
networked_sign [ label = "Sign\nTxes" ];
networked_broadcast [ label = "Broadcast\nTxes" ];
networked_priv -> networked_pub -> networked_distribute -> networked_monitor -> networked_create -> networked_sign -> networked_broadcast;
label = " Other Wallet(s)"
}
networked_priv -> networked_pub [style=""];
networked_pub -> distributing_pub [ constraint = false, style = ""];
distributing_pub -> distributing_distribute -> networked_monitor -> networked_create -> networked_sign -> networked_broadcast [style=""];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View file

@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.26.3 (20100126.1600)
-->
<!-- Title: wallet_program Pages: 1 -->
<svg width="450pt" height="176pt"
viewBox="0.00 0.00 450.00 176.03" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(0.661765 0.661765) rotate(0) translate(4 262)">
<title>wallet_program</title>
<polygon fill="white" stroke="white" points="-4,5 -4,-262 677,-262 677,5 -4,5"/>
<g id="graph2" class="cluster"><title>cluster_distributing</title>
<polygon fill="none" stroke="black" stroke-width="0" points="8,-133 8,-250 664,-250 664,-133 8,-133"/>
<text text-anchor="middle" x="336" y="-233.4" font-family="Sans" font-size="14.00">Distributing&#45;Only Wallet</text>
</g>
<g id="graph3" class="cluster"><title>cluster_networked</title>
<polygon fill="none" stroke="black" stroke-width="0" points="8,-8 8,-125 664,-125 664,-8 8,-8"/>
<text text-anchor="middle" x="336" y="-108.4" font-family="Sans" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;Other Wallet(s)</text>
</g>
<!-- distributing_priv -->
<!-- distributing_pub -->
<g id="node3" class="node"><title>distributing_pub</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="166,-217 104,-217 104,-141 166,-141 166,-217"/>
<text text-anchor="middle" x="135" y="-200.4" font-family="Sans" font-size="14.00">Derive</text>
<text text-anchor="middle" x="135" y="-183.4" font-family="Sans" font-size="14.00">Child</text>
<text text-anchor="middle" x="135" y="-166.4" font-family="Sans" font-size="14.00">Public</text>
<text text-anchor="middle" x="135" y="-149.4" font-family="Sans" font-size="14.00">Keys</text>
</g>
<!-- distributing_priv&#45;&gt;distributing_pub -->
<!-- distributing_distribute -->
<g id="node4" class="node"><title>distributing_distribute</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="274,-208.5 188,-208.5 188,-149.5 274,-149.5 274,-208.5"/>
<text text-anchor="middle" x="231" y="-191.9" font-family="Sans" font-size="14.00">Distribute</text>
<text text-anchor="middle" x="231" y="-174.9" font-family="Sans" font-size="14.00">Public</text>
<text text-anchor="middle" x="231" y="-157.9" font-family="Sans" font-size="14.00">Keys</text>
</g>
<!-- distributing_pub&#45;&gt;distributing_distribute -->
<!-- distributing_pub&#45;&gt;distributing_distribute -->
<g id="edge22" class="edge"><title>distributing_pub&#45;&gt;distributing_distribute</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M166.168,-185.367C169.833,-185.54 173.648,-185.655 177.51,-185.711"/>
<polygon fill="black" stroke="black" points="177.774,-189.211 187.778,-185.72 177.781,-182.211 177.774,-189.211"/>
</g>
<!-- distributing_monitor -->
<!-- distributing_distribute&#45;&gt;distributing_monitor -->
<!-- networked_monitor -->
<g id="node14" class="node"><title>networked_monitor</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="369,-89.5 297,-89.5 297,-30.5 369,-30.5 369,-89.5"/>
<text text-anchor="middle" x="333" y="-72.9" font-family="Sans" font-size="14.00">Monitor</text>
<text text-anchor="middle" x="333" y="-55.9" font-family="Sans" font-size="14.00">For</text>
<text text-anchor="middle" x="333" y="-38.9" font-family="Sans" font-size="14.00">Outputs</text>
</g>
<!-- distributing_distribute&#45;&gt;networked_monitor -->
<g id="edge23" class="edge"><title>distributing_distribute&#45;&gt;networked_monitor</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M256.025,-149.929C261.924,-143.069 268.187,-135.779 274,-129 282.912,-118.608 292.568,-107.324 301.438,-96.9504"/>
<polygon fill="black" stroke="black" points="304.205,-99.1003 308.042,-89.2249 298.884,-94.5518 304.205,-99.1003"/>
</g>
<!-- distributing_create -->
<!-- distributing_monitor&#45;&gt;distributing_create -->
<!-- distributing_sign -->
<!-- distributing_create&#45;&gt;distributing_sign -->
<!-- distributing_broadcast -->
<!-- distributing_sign&#45;&gt;distributing_broadcast -->
<!-- networked_priv -->
<g id="node11" class="node"><title>networked_priv</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="82,-92 16,-92 16,-16 82,-16 82,-92"/>
<text text-anchor="middle" x="49" y="-75.4" font-family="Sans" font-size="14.00">Create</text>
<text text-anchor="middle" x="49" y="-58.4" font-family="Sans" font-size="14.00">Parent</text>
<text text-anchor="middle" x="49" y="-41.4" font-family="Sans" font-size="14.00">Private</text>
<text text-anchor="middle" x="49" y="-24.4" font-family="Sans" font-size="14.00">Key</text>
</g>
<!-- networked_pub -->
<g id="node12" class="node"><title>networked_pub</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="166,-92 104,-92 104,-16 166,-16 166,-92"/>
<text text-anchor="middle" x="135" y="-75.4" font-family="Sans" font-size="14.00">Derive</text>
<text text-anchor="middle" x="135" y="-58.4" font-family="Sans" font-size="14.00">Parent</text>
<text text-anchor="middle" x="135" y="-41.4" font-family="Sans" font-size="14.00">Public</text>
<text text-anchor="middle" x="135" y="-24.4" font-family="Sans" font-size="14.00">Key</text>
</g>
<!-- networked_priv&#45;&gt;networked_pub -->
<g id="edge18" class="edge"><title>networked_priv&#45;&gt;networked_pub</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M82.0039,-47.4148C85.8289,-47.2866 89.7655,-47.2332 93.6836,-47.2546"/>
<polygon fill="black" stroke="black" points="93.845,-50.7591 103.922,-47.4861 94.0033,-43.7608 93.845,-50.7591"/>
</g>
<!-- networked_priv&#45;&gt;networked_pub -->
<!-- networked_pub&#45;&gt;distributing_pub -->
<g id="edge20" class="edge"><title>networked_pub&#45;&gt;distributing_pub</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M135,-92.0859C135,-104.945 135,-117.804 135,-130.663"/>
<polygon fill="black" stroke="black" points="131.5,-130.975 135,-140.975 138.5,-130.975 131.5,-130.975"/>
</g>
<!-- networked_distribute -->
<!-- networked_pub&#45;&gt;networked_distribute -->
<!-- networked_distribute&#45;&gt;networked_monitor -->
<!-- networked_create -->
<g id="node15" class="node"><title>networked_create</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="472,-89.5 392,-89.5 392,-30.5 472,-30.5 472,-89.5"/>
<text text-anchor="middle" x="432" y="-72.9" font-family="Sans" font-size="14.00">Create</text>
<text text-anchor="middle" x="432" y="-55.9" font-family="Sans" font-size="14.00">Unsigned</text>
<text text-anchor="middle" x="432" y="-38.9" font-family="Sans" font-size="14.00">Txes</text>
</g>
<!-- networked_monitor&#45;&gt;networked_create -->
<g id="edge24" class="edge"><title>networked_monitor&#45;&gt;networked_create</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M369.583,-53.4586C373.559,-53.3274 377.655,-53.2581 381.757,-53.2507"/>
<polygon fill="black" stroke="black" points="381.868,-56.752 391.905,-53.3595 381.943,-49.7524 381.868,-56.752"/>
</g>
<!-- networked_monitor&#45;&gt;networked_create -->
<!-- networked_sign -->
<g id="node16" class="node"><title>networked_sign</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="548,-81 494,-81 494,-39 548,-39 548,-81"/>
<text text-anchor="middle" x="521" y="-64.4" font-family="Sans" font-size="14.00">Sign</text>
<text text-anchor="middle" x="521" y="-47.4" font-family="Sans" font-size="14.00">Txes</text>
</g>
<!-- networked_create&#45;&gt;networked_sign -->
<!-- networked_create&#45;&gt;networked_sign -->
<g id="edge25" class="edge"><title>networked_create&#45;&gt;networked_sign</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M472.074,-66.7202C475.996,-66.7731 479.964,-66.7555 483.855,-66.6674"/>
<polygon fill="black" stroke="black" points="484.036,-70.163 493.889,-66.2694 483.758,-63.1685 484.036,-70.163"/>
</g>
<!-- networked_broadcast -->
<g id="node17" class="node"><title>networked_broadcast</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="655,-81 571,-81 571,-39 655,-39 655,-81"/>
<text text-anchor="middle" x="613" y="-64.4" font-family="Sans" font-size="14.00">Broadcast</text>
<text text-anchor="middle" x="613" y="-47.4" font-family="Sans" font-size="14.00">Txes</text>
</g>
<!-- networked_sign&#45;&gt;networked_broadcast -->
<!-- networked_sign&#45;&gt;networked_broadcast -->
<g id="edge26" class="edge"><title>networked_sign&#45;&gt;networked_broadcast</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M548.105,-66.2161C551.932,-66.4447 555.969,-66.5999 560.082,-66.6817"/>
<polygon fill="black" stroke="black" points="560.366,-70.1831 570.383,-66.7337 560.401,-63.1832 560.366,-70.1831"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.6 KiB

View file

@ -0,0 +1,30 @@
digraph wallet_program {
size="6.25";
rankdir=LR;
//ratio=fill;
splines=true;
fontname=Sans
ranksep=0.3;
penwidth=1.75;
overlap = false;
edge [ fontname=Sans, penwidth=1.75, style = "invis" ];
node [ fontname=Sans, shape = box, penwidth=1.75 ];
subgraph cluster_networked {
penwidth=0;
networked_priv [ label = "Create\nPrivate\nKeys" ];
networked_pub [ label = "Derive\nPublic\nKeys" ];
networked_distribute [ label = "Distribute\nPublic\nKeys" ];
networked_monitor [ label = "Monitor\nFor\nOutputs" ];
networked_create [ label = "Create\nUnsigned\nTxes" ];
networked_sign [ label = "Sign\nTxes" ];
networked_broadcast [ label = "Broadcast\nTxes" ];
networked_priv -> networked_pub -> networked_distribute -> networked_monitor -> networked_create -> networked_sign -> networked_broadcast [ style = "" ];
label = " \nFull-Service Wallet"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.26.3 (20100126.1600)
-->
<!-- Title: wallet_program Pages: 1 -->
<svg width="450pt" height="93pt"
viewBox="0.00 0.00 450.00 92.65" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(0.661765 0.661765) rotate(0) translate(4 136)">
<title>wallet_program</title>
<polygon fill="white" stroke="white" points="-4,5 -4,-136 677,-136 677,5 -4,5"/>
<g id="graph2" class="cluster"><title>cluster_networked</title>
<polygon fill="none" stroke="black" stroke-width="0" points="8,-8 8,-124 664,-124 664,-8 8,-8"/>
<text text-anchor="middle" x="336" y="-107.4" font-family="Sans" font-size="14.00"> </text>
<text text-anchor="middle" x="336" y="-90.4" font-family="Sans" font-size="14.00">Full&#45;Service Wallet</text>
</g>
<!-- networked_priv -->
<g id="node2" class="node"><title>networked_priv</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="82,-74.5 16,-74.5 16,-15.5 82,-15.5 82,-74.5"/>
<text text-anchor="middle" x="49" y="-57.9" font-family="Sans" font-size="14.00">Create</text>
<text text-anchor="middle" x="49" y="-40.9" font-family="Sans" font-size="14.00">Private</text>
<text text-anchor="middle" x="49" y="-23.9" font-family="Sans" font-size="14.00">Keys</text>
</g>
<!-- networked_pub -->
<g id="node3" class="node"><title>networked_pub</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="166,-74.5 104,-74.5 104,-15.5 166,-15.5 166,-74.5"/>
<text text-anchor="middle" x="135" y="-57.9" font-family="Sans" font-size="14.00">Derive</text>
<text text-anchor="middle" x="135" y="-40.9" font-family="Sans" font-size="14.00">Public</text>
<text text-anchor="middle" x="135" y="-23.9" font-family="Sans" font-size="14.00">Keys</text>
</g>
<!-- networked_priv&#45;&gt;networked_pub -->
<g id="edge3" class="edge"><title>networked_priv&#45;&gt;networked_pub</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M82.0039,-45C85.8289,-45 89.7655,-45 93.6836,-45"/>
<polygon fill="black" stroke="black" points="93.9217,-48.5001 103.922,-45 93.9216,-41.5001 93.9217,-48.5001"/>
</g>
<!-- networked_distribute -->
<g id="node4" class="node"><title>networked_distribute</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="274,-74.5 188,-74.5 188,-15.5 274,-15.5 274,-74.5"/>
<text text-anchor="middle" x="231" y="-57.9" font-family="Sans" font-size="14.00">Distribute</text>
<text text-anchor="middle" x="231" y="-40.9" font-family="Sans" font-size="14.00">Public</text>
<text text-anchor="middle" x="231" y="-23.9" font-family="Sans" font-size="14.00">Keys</text>
</g>
<!-- networked_pub&#45;&gt;networked_distribute -->
<g id="edge4" class="edge"><title>networked_pub&#45;&gt;networked_distribute</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M166.168,-45C169.833,-45 173.648,-45 177.51,-45"/>
<polygon fill="black" stroke="black" points="177.778,-48.5001 187.778,-45 177.777,-41.5001 177.778,-48.5001"/>
</g>
<!-- networked_monitor -->
<g id="node5" class="node"><title>networked_monitor</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="369,-74.5 297,-74.5 297,-15.5 369,-15.5 369,-74.5"/>
<text text-anchor="middle" x="333" y="-57.9" font-family="Sans" font-size="14.00">Monitor</text>
<text text-anchor="middle" x="333" y="-40.9" font-family="Sans" font-size="14.00">For</text>
<text text-anchor="middle" x="333" y="-23.9" font-family="Sans" font-size="14.00">Outputs</text>
</g>
<!-- networked_distribute&#45;&gt;networked_monitor -->
<g id="edge5" class="edge"><title>networked_distribute&#45;&gt;networked_monitor</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M274.257,-45C278.18,-45 282.166,-45 286.118,-45"/>
<polygon fill="black" stroke="black" points="286.437,-48.5001 296.437,-45 286.437,-41.5001 286.437,-48.5001"/>
</g>
<!-- networked_create -->
<g id="node6" class="node"><title>networked_create</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="472,-74.5 392,-74.5 392,-15.5 472,-15.5 472,-74.5"/>
<text text-anchor="middle" x="432" y="-57.9" font-family="Sans" font-size="14.00">Create</text>
<text text-anchor="middle" x="432" y="-40.9" font-family="Sans" font-size="14.00">Unsigned</text>
<text text-anchor="middle" x="432" y="-23.9" font-family="Sans" font-size="14.00">Txes</text>
</g>
<!-- networked_monitor&#45;&gt;networked_create -->
<g id="edge6" class="edge"><title>networked_monitor&#45;&gt;networked_create</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M369.583,-45C373.559,-45 377.655,-45 381.757,-45"/>
<polygon fill="black" stroke="black" points="381.905,-48.5001 391.905,-45 381.905,-41.5001 381.905,-48.5001"/>
</g>
<!-- networked_sign -->
<g id="node7" class="node"><title>networked_sign</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="548,-66 494,-66 494,-24 548,-24 548,-66"/>
<text text-anchor="middle" x="521" y="-49.4" font-family="Sans" font-size="14.00">Sign</text>
<text text-anchor="middle" x="521" y="-32.4" font-family="Sans" font-size="14.00">Txes</text>
</g>
<!-- networked_create&#45;&gt;networked_sign -->
<g id="edge7" class="edge"><title>networked_create&#45;&gt;networked_sign</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M472.074,-45C475.996,-45 479.964,-45 483.855,-45"/>
<polygon fill="black" stroke="black" points="483.889,-48.5001 493.889,-45 483.889,-41.5001 483.889,-48.5001"/>
</g>
<!-- networked_broadcast -->
<g id="node8" class="node"><title>networked_broadcast</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="655,-66 571,-66 571,-24 655,-24 655,-66"/>
<text text-anchor="middle" x="613" y="-49.4" font-family="Sans" font-size="14.00">Broadcast</text>
<text text-anchor="middle" x="613" y="-32.4" font-family="Sans" font-size="14.00">Txes</text>
</g>
<!-- networked_sign&#45;&gt;networked_broadcast -->
<g id="edge8" class="edge"><title>networked_sign&#45;&gt;networked_broadcast</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M548.105,-45C551.932,-45 555.969,-45 560.082,-45"/>
<polygon fill="black" stroke="black" points="560.383,-48.5001 570.383,-45 560.383,-41.5001 560.383,-48.5001"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View file

@ -0,0 +1,50 @@
digraph wallet_program {
size="6.25";
rankdir=LR;
//ratio=fill;
splines=true;
fontname=Sans
ranksep=0.3;
penwidth=1.75;
overlap = false;
edge [ fontname=Sans, penwidth=1.75, style = "invis" ];
node [ fontname=Sans, shape = box, penwidth=1.75 ];
subgraph cluster_signing {
penwidth=0;
signing_priv [ label = "Create\nParent\nPrivate\nKey" ];
signing_pub [ label = "Derive\nParent\nPublic\nKey" ];
signing_distribute [ label = "Distribute\nPublic\nKeys", style="invis" ];
signing_monitor [ label = "Monitor\nFor\nOutputs", style="invis" ];
signing_create [ label = "Create\nUnsigned\nTxes", style="invis" ];
signing_sign [ label = "Sign\nTxes" ];
signing_broadcast [ label = "Broadcast\nTxes", style="invis" ];
signing_priv -> signing_pub -> signing_distribute -> signing_monitor -> signing_create -> signing_sign -> signing_broadcast;
label = "Signing-Only Wallet"
}
subgraph cluster_networked {
penwidth=0;
networked_priv [ label = "Create\nPrivate\nKeys", style="invis" ];
networked_pub [ label = "Derive\nChild\nPublic\nKeys" ];
networked_distribute [ label = "Distribute\nPublic\nKeys" ];
networked_monitor [ label = "Monitor\nFor\nOutputs" ];
networked_create [ label = "Create\nUnsigned\nTxes" ];
networked_sign [ label = "Sign\nTxes", style="invis" ];
networked_broadcast [ label = "Broadcast\nTxes" ];
networked_priv -> networked_pub -> networked_distribute -> networked_monitor -> networked_create -> networked_sign -> networked_broadcast;
label = "Networked Wallet"
}
signing_priv -> signing_pub [style=""];
signing_pub -> networked_pub [ constraint = false, style = ""];
networked_pub -> networked_distribute -> networked_monitor -> networked_create -> signing_sign -> networked_broadcast [style=""];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View file

@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.26.3 (20100126.1600)
-->
<!-- Title: wallet_program Pages: 1 -->
<svg width="450pt" height="176pt"
viewBox="0.00 0.00 450.00 176.03" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(0.661765 0.661765) rotate(0) translate(4 262)">
<title>wallet_program</title>
<polygon fill="white" stroke="white" points="-4,5 -4,-262 677,-262 677,5 -4,5"/>
<g id="graph2" class="cluster"><title>cluster_signing</title>
<polygon fill="none" stroke="black" stroke-width="0" points="8,-133 8,-250 664,-250 664,-133 8,-133"/>
<text text-anchor="middle" x="336" y="-233.4" font-family="Sans" font-size="14.00">Signing&#45;Only Wallet</text>
</g>
<g id="graph3" class="cluster"><title>cluster_networked</title>
<polygon fill="none" stroke="black" stroke-width="0" points="8,-8 8,-125 664,-125 664,-8 8,-8"/>
<text text-anchor="middle" x="336" y="-108.4" font-family="Sans" font-size="14.00">Networked Wallet</text>
</g>
<!-- signing_priv -->
<g id="node2" class="node"><title>signing_priv</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="82,-217 16,-217 16,-141 82,-141 82,-217"/>
<text text-anchor="middle" x="49" y="-200.4" font-family="Sans" font-size="14.00">Create</text>
<text text-anchor="middle" x="49" y="-183.4" font-family="Sans" font-size="14.00">Parent</text>
<text text-anchor="middle" x="49" y="-166.4" font-family="Sans" font-size="14.00">Private</text>
<text text-anchor="middle" x="49" y="-149.4" font-family="Sans" font-size="14.00">Key</text>
</g>
<!-- signing_pub -->
<g id="node3" class="node"><title>signing_pub</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="166,-217 104,-217 104,-141 166,-141 166,-217"/>
<text text-anchor="middle" x="135" y="-200.4" font-family="Sans" font-size="14.00">Derive</text>
<text text-anchor="middle" x="135" y="-183.4" font-family="Sans" font-size="14.00">Parent</text>
<text text-anchor="middle" x="135" y="-166.4" font-family="Sans" font-size="14.00">Public</text>
<text text-anchor="middle" x="135" y="-149.4" font-family="Sans" font-size="14.00">Key</text>
</g>
<!-- signing_priv&#45;&gt;signing_pub -->
<!-- signing_priv&#45;&gt;signing_pub -->
<g id="edge18" class="edge"><title>signing_priv&#45;&gt;signing_pub</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M82.0039,-185.585C85.8289,-185.713 89.7655,-185.767 93.6836,-185.745"/>
<polygon fill="black" stroke="black" points="94.0033,-189.239 103.922,-185.514 93.845,-182.241 94.0033,-189.239"/>
</g>
<!-- signing_distribute -->
<!-- signing_pub&#45;&gt;signing_distribute -->
<!-- networked_pub -->
<g id="node12" class="node"><title>networked_pub</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="166,-92 104,-92 104,-16 166,-16 166,-92"/>
<text text-anchor="middle" x="135" y="-75.4" font-family="Sans" font-size="14.00">Derive</text>
<text text-anchor="middle" x="135" y="-58.4" font-family="Sans" font-size="14.00">Child</text>
<text text-anchor="middle" x="135" y="-41.4" font-family="Sans" font-size="14.00">Public</text>
<text text-anchor="middle" x="135" y="-24.4" font-family="Sans" font-size="14.00">Keys</text>
</g>
<!-- signing_pub&#45;&gt;networked_pub -->
<g id="edge20" class="edge"><title>signing_pub&#45;&gt;networked_pub</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M135,-140.975C135,-128.116 135,-115.257 135,-102.398"/>
<polygon fill="black" stroke="black" points="138.5,-102.086 135,-92.0859 131.5,-102.086 138.5,-102.086"/>
</g>
<!-- signing_monitor -->
<!-- signing_distribute&#45;&gt;signing_monitor -->
<!-- signing_create -->
<!-- signing_monitor&#45;&gt;signing_create -->
<!-- signing_sign -->
<g id="node7" class="node"><title>signing_sign</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="548,-183 494,-183 494,-141 548,-141 548,-183"/>
<text text-anchor="middle" x="521" y="-166.4" font-family="Sans" font-size="14.00">Sign</text>
<text text-anchor="middle" x="521" y="-149.4" font-family="Sans" font-size="14.00">Txes</text>
</g>
<!-- signing_create&#45;&gt;signing_sign -->
<!-- signing_broadcast -->
<!-- signing_sign&#45;&gt;signing_broadcast -->
<!-- networked_broadcast -->
<g id="node17" class="node"><title>networked_broadcast</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="655,-89 571,-89 571,-47 655,-47 655,-89"/>
<text text-anchor="middle" x="613" y="-72.4" font-family="Sans" font-size="14.00">Broadcast</text>
<text text-anchor="middle" x="613" y="-55.4" font-family="Sans" font-size="14.00">Txes</text>
</g>
<!-- signing_sign&#45;&gt;networked_broadcast -->
<g id="edge26" class="edge"><title>signing_sign&#45;&gt;networked_broadcast</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M541.876,-140.67C554.698,-127.57 571.275,-110.632 585.2,-96.404"/>
<polygon fill="black" stroke="black" points="587.713,-98.8405 592.206,-89.2456 582.71,-93.9442 587.713,-98.8405"/>
</g>
<!-- networked_priv -->
<!-- networked_priv&#45;&gt;networked_pub -->
<!-- networked_distribute -->
<g id="node13" class="node"><title>networked_distribute</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="274,-84.5 188,-84.5 188,-25.5 274,-25.5 274,-84.5"/>
<text text-anchor="middle" x="231" y="-67.9" font-family="Sans" font-size="14.00">Distribute</text>
<text text-anchor="middle" x="231" y="-50.9" font-family="Sans" font-size="14.00">Public</text>
<text text-anchor="middle" x="231" y="-33.9" font-family="Sans" font-size="14.00">Keys</text>
</g>
<!-- networked_pub&#45;&gt;networked_distribute -->
<g id="edge22" class="edge"><title>networked_pub&#45;&gt;networked_distribute</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M166.168,-47.9579C169.833,-47.8225 173.648,-47.7476 177.51,-47.7322"/>
<polygon fill="black" stroke="black" points="177.745,-51.2345 187.778,-47.8296 177.811,-44.2348 177.745,-51.2345"/>
</g>
<!-- networked_pub&#45;&gt;networked_distribute -->
<!-- networked_monitor -->
<g id="node14" class="node"><title>networked_monitor</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="369,-88.5 297,-88.5 297,-29.5 369,-29.5 369,-88.5"/>
<text text-anchor="middle" x="333" y="-71.9" font-family="Sans" font-size="14.00">Monitor</text>
<text text-anchor="middle" x="333" y="-54.9" font-family="Sans" font-size="14.00">For</text>
<text text-anchor="middle" x="333" y="-37.9" font-family="Sans" font-size="14.00">Outputs</text>
</g>
<!-- networked_distribute&#45;&gt;networked_monitor -->
<g id="edge23" class="edge"><title>networked_distribute&#45;&gt;networked_monitor</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M274.257,-50.016C278.18,-50.0988 282.166,-50.2384 286.118,-50.4311"/>
<polygon fill="black" stroke="black" points="286.242,-53.9451 296.437,-51.0625 286.669,-46.9582 286.242,-53.9451"/>
</g>
<!-- networked_distribute&#45;&gt;networked_monitor -->
<!-- networked_create -->
<g id="node15" class="node"><title>networked_create</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="472,-90.5 392,-90.5 392,-31.5 472,-31.5 472,-90.5"/>
<text text-anchor="middle" x="432" y="-73.9" font-family="Sans" font-size="14.00">Create</text>
<text text-anchor="middle" x="432" y="-56.9" font-family="Sans" font-size="14.00">Unsigned</text>
<text text-anchor="middle" x="432" y="-39.9" font-family="Sans" font-size="14.00">Txes</text>
</g>
<!-- networked_monitor&#45;&gt;networked_create -->
<g id="edge24" class="edge"><title>networked_monitor&#45;&gt;networked_create</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M369.583,-53.1976C373.559,-53.1468 377.655,-53.1603 381.757,-53.2357"/>
<polygon fill="black" stroke="black" points="381.801,-56.7386 391.905,-53.5495 382.018,-49.742 381.801,-56.7386"/>
</g>
<!-- networked_monitor&#45;&gt;networked_create -->
<!-- networked_create&#45;&gt;signing_sign -->
<g id="edge25" class="edge"><title>networked_create&#45;&gt;signing_sign</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M457.742,-90.2134C469.673,-103.752 483.805,-119.79 495.683,-133.269"/>
<polygon fill="black" stroke="black" points="493.144,-135.683 502.382,-140.871 498.396,-131.055 493.144,-135.683"/>
</g>
<!-- networked_sign -->
<!-- networked_create&#45;&gt;networked_sign -->
<!-- networked_sign&#45;&gt;networked_broadcast -->
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.3 KiB