[WIP] Wallet documentation (#1302)

* doc update

* change and reorganise wallet documentation

* Redo wallet arch document, update design document with current info, move older design document into 'goals.md'

* Redo wallet arch document, update design document with current info, move older design document into 'goals.md'
This commit is contained in:
Yeastplume 2018-07-30 17:10:43 +01:00 committed by GitHub
parent 76f4915bf9
commit 658a686cc1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 495 additions and 93 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

View file

@ -1,63 +0,0 @@
# Grin - Basic Wallet
## Wallet Files
A Grin wallet maintains its state in the following files -
```
wallet.seed # *** passphrase protected seed file (keep this private) ***
wallet.dat # wallet outputs (both spent and unspent)
wallet.lock # lock file, prevents multiple processes writing to wallet.dat
```
By default Grin will look for these in the current working directory.
## Basic Wallet Commands
`grin wallet --help` will display usage info about the following.
### grin wallet init
Before using a wallet a new seed file `wallet.seed` needs to be generated via `grin wallet init` -
```
grin wallet init
Generating wallet seed file at: ./wallet.seed
```
### grin wallet info
Some (very) basic information about current wallet outputs can be displayed with `grin wallet info` -
```
grin wallet -p "password" info
Using wallet seed file at: ./wallet.seed
Outputs -
key_id, height, lock_height, status, spendable?, coinbase?, value
----------------------------------
96805837571719c692b6, 21, 24, Spent, false, true, 50000000000
...
```
### grin wallet listen
Starts a listening wallet server. This is needed for the `grin wallet send -d <destination wallet server>` command to work.
### grin wallet send
Builds a transaction to send someone some coins. Creates and outputs a transaction.
- add -d <destination server> to request a destination wallet from the given server address and port, and then push the transaction to the network
- add -s <strategy> to choose between selection strategies. If you're experimenting, or the destination is not reliable, it is currently recommendable to use the strategy `smallest`
### grin wallet receive
Replaced by `listen` (see above). The `receive` command might later be recycled to actively accept one or several specific transactions.
### grin wallet request
(tbd)
### grin wallet burn
*TESTING ONLY*: Burns the provided amount to a known key. Similar to send but burns an output to allow single-party
transactions.

View file

@ -0,0 +1,93 @@
### Grin Wallet + Library Design
![wallet design](wallet-arch.png)
**High Level Wallet Design Overview**
The current Grin `wallet` crate provides several layers of libraries, services, and traits that can be mixed, matched and reimplemented to support
various needs within the default Grin wallet as well as provide a set of useful library functions for 3rd-party implementors. At a very high level,
the code is organized into the following components (from highest-level to lowest):
* **Command Line Client** - The command line client invoked by `grin wallet [command]`, simply instantiates the other components below
and parses command line arguments as needed.
* **Web Wallet Client** - [Work In Progress] A web wallet client accessible from the local machine only. Current code can be viewed here:
https://github.com/mimblewimble/grin-web-wallet
* **Static File Server** - [TBD] A means of serving up the web wallet client above to the user (still under consideration)
* **libWallet** - A high level wallet library that provides functions for the default grin wallet. The functions in here can be somewhat
specific to how the grin wallet does things, but could still be reused by 3rd party implementors following the same basic principles as grin
does. Major functionality is split into:
* **Owner API** - An API that provides information that should only be viewable by the wallet owner
* **Foreign API** - An API to communicate with other wallets and external grin nodes
* **Service Controller** - A Controller that instantiates the above APIs (either locally or via web services)
* **Internal Functions** Helper functions to perform needed wallet tasks, such as selecting coins, updating wallet outputs with
results from a Grin node, etc.
* **libTx** - Library that provides lower-level transaction building, rangeproof and signing functions, highly-reusable by wallet implementors.
* **Wallet Traits** - A set of generic traits defined within libWallet and the `keychain` crate . A wallet implementation such as Grin's current
default only needs to implement these traits in order to provide a wallet:
* **WalletClient** - Defines communication between the wallet, a running grin node and/or other wallets
* **WalletBackend** - Defines the storage implementation of the wallet
* **KeyChain** - Defines key derivation operations
### Module-Specific Notes
A full API-Description for each of these parts is still TBD (and should be generated by rustdoc rather than repeated here). However a few design
notes on each module are worth mentioning here.
##### Web Wallet Client / Static File Server
This component is not a 3rd-party hosted 'Web Wallet' , but a client meant to be run on the local machine only by the wallet owner. It should provide
a usable browser interface into the wallet, that should be functionally equivalent to using the command line but (hopefully) far easier to use.
It is currently not being included by a default grin build, although the required listener is currently being run by default. To build and test this
component, see instructions on the [project page](https://github.com/mimblewimble/grin-web-wallet). The 'Static File Server' is still under
discussion, and concerns how to provide the web-wallet to the user in a default Grin build.
##### Owner API / Foreign API
The high-level wallet API has been split into two, to allow for different requirements on each. For instance, the Foreign API would listen on
an external-facing port, and therefore potentially has different security requirements from the Owner API, which can simply be bound to localhost
only.
##### libTX
Transactions are built using the concept of a 'Slate', which is a data structure that gets passed around to all participants in a transaction,
with each appending their Inputs, Outputs or Signatures to it to build a completed wallet transaction. Although the current mode of operation in
the default client only supports single-user - single recipient, an arbitrary number of participants to a transaction is supported within libTX.
##### Wallet Traits
In the current code, a Wallet implementation is just a combination of these three traits. The vast majority of functions within libwallet
and libTX have a signature similar to the following:
```
pub fn retrieve_outputs<T: ?Sized, C, K>(
!·wallet: &mut T,
!·show_spent: bool,
!·tx_id: Option<u32>,
) -> Result<Vec<OutputData>, Error>
where
!·T: WalletBackend<C, K>,
!·C: WalletClient,
!·K: Keychain,
{
```
With `T` in this instance being a class that implements the `WalletBackend` trait, which is further parameterized with implementations of
`WalletClient` and `Keychain`.
There is currently only a single implementation of the Keychain trait within the Grin code, in the `keychain` crate exported as `ExtKeyChain`.
The `Keychain` trait makes several assumptions about the underlying implementation, particularly that it will adhere to a
[BIP-38 style](https://github.com/bitcoin/bips/blob/master/bip-0038.mediawiki) 'master key -> child key' model.
There are two implementations of `WalletClient` within the code, the main version being the `HTTPWalletClient` found within `wallet/src/client.rs` and
the seconds a test client that communicates with an in-process instance of a chain. The WalletClient isolates all network calls, so upgrading wallet
communication from the current simple http interaction to a more secure protocol (or allowing for many options) should be a simple
matter of dropping in different `WalletClient` implementations.
There are also two implementations of `WalletBackend` within the code at the base of the `wallet` crate. `LMDBBackend` found within
`wallet/src/lmdb_wallet.rs` is the main implementation, and is now used by all grin wallet commands. The earlier `FileWallet` still exists
within the code, however it is not invoked, and given there are no real advantages to running it over a DB implementation, development on it
has been dropped in favour of the LMDB implementation.

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

View file

@ -0,0 +1,110 @@
@startuml grin-wallet-overview
skinparam componentStyle uml2
[Grin Node] as grin_node
folder "Provided by Grin" as services {
component foreign_api [
**Foreign API**
External-Facing functions
- receive_tx, build coinbase
]
component owner_api [
**Owner API**
Functions used by wallet owner only
- retrieve outputs, retrieve txs,
get balances, send, etc. . .
]
component libtx [
**Transaction Library (libTx)**
Lower-Level transaction functions
- Build transaction (via Slate), sign,
build reward, fees, etc. . .
]
component libwallet [
**Wallet Library (libWallet) **
- Higher level wallet functions (select coins,
update wallet from node, etc)
- Service Controller
(instantiate libs, start listeners)
]
() "Owner HTTP Listener (localhost only)" as owner_http
() "Foreign HTTP Listener" as foreign_http
() "Owner Single-Use" as owner_single
() "Foreign Single-Use" as foreign_single
}
' Trait definitions
package "Traits Implemented by Wallets" as traits {
database "WalletBackend" as wallet_backend
database "KeyChain" as keychain
component "WalletClient" as wallet_client
}
note left of wallet_client
- Communication layer implementation
- Handles underlying communication with grin node
or other wallets
- HTTP implementation provided currently, (Other,
more secure protocols possible.)
end note
note bottom of keychain
- Handles all key derivation operations
end note
note bottom of wallet_backend
- Implements underlying storage for wallet data
- LMDB storage provided in default client, others
possible (Flat-file, other DBs, etc)
end note
libtx <--> traits
libwallet <--> traits
note right of traits
**Default Wallet simply a struct that provides**
**implementations for these 3 traits**
end note
' Client Side
'package "Provided as reference implementation" {
[Pure JS Wallet Client Implementation] as js_client
[Command Line Wallet Client] as cl_client
component web_server [
V. Light Rust Web Server - Serve static files (TBD)
(Provided by default - localhost only)
(Serve up pure JS client)
]
'}
[External Wallets] as external_wallets
[External Wallets] as external_wallets_2
wallet_client <--> grin_node
wallet_client <--> external_wallets_2
web_server <--> owner_http
js_client <-- web_server
cl_client <--> owner_single
cl_client <--> foreign_single
owner_single <--> owner_api
foreign_single <--> foreign_api
libwallet <--> libtx
foreign_api --> libwallet
owner_api --> libwallet
js_client <--> owner_http
owner_http <--> owner_api
external_wallets <--> foreign_http
foreign_http <--> foreign_api
'layout fix
'grin_node -[hidden]- wallet_backend
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

View file

@ -2,14 +2,14 @@
title title
**Current Grin Tranaction Workflow** **Current Grin Tranaction Workflow**
Accurate as of Feb 12th, 2018 - Master branch only Accurate as of Aug 1, 2018 - Master branch only
end title end title
actor "Sender" as sender actor "Sender" as sender
actor "Recipient" as recipient actor "Recipient" as recipient
entity "Grin Node" as grin_node entity "Grin Node" as grin_node
== Phase 1 - Sender Initiation == == Round 1 ==
note left of sender note left of sender
1: Create Transaction **UUID** (for reference and maintaining correct state) 1: Create Transaction **UUID** (for reference and maintaining correct state)
@ -17,66 +17,68 @@ note left of sender
3: Select **inputs** using desired selection strategy 3: Select **inputs** using desired selection strategy
4: Create **change_output** 4: Create **change_output**
5: Select blinding factor for **change_output** 5: Select blinding factor for **change_output**
6: Create lock function **sF** that locks **inputs** and stores **change_output** in wallet
and identifying wallet transaction log entry **TS** linking **inputs + outputs**
(Not executed at this point)
end note end note
sender -> sender: Lock **inputs** in wallet
sender -> sender: Store **change_output** in wallet with status "Unconfirmed"
note left of sender note left of sender
6: Calculate **tx_weight**: MAX(-1 * **num_inputs** + 4 * **num_change_outputs** + 1, 1) 7: Calculate **tx_weight**: MAX(-1 * **num_inputs** + 4 * **num_change_outputs** + 1, 1)
(+1 covers a single output on the receiver's side) (+1 covers a single output on the receiver's side)
7: Calculate **fee**: **tx_weight** * 1_000_000 nG 8: Calculate **fee**: **tx_weight** * 1_000_000 nG
8: Calculate total blinding excess sum for all inputs and outputs **xS** (private scalar) 9: Calculate total blinding excess sum for all inputs and outputs **xS** (private scalar)
9: Select a random nonce **kS** (private scalar) 10: Select a random nonce **kS1** (private scalar)
10: Multiply **xS** and **kS** by generator G to create public curve points **xSG** and **kSG** 11: Subtract random value **oS** from **kS1** to create kernel offset **oS**. Calculate **kS** = **kS1** - **oS**
12: Multiply **xS** and **kS** by generator G to create public curve points **xSG** and **kSG**
13: Add values to **Slate** for passing to other participants: **UUID, inputs, change_outputs,**
**fee, amount, lock_height, kSG, xSG, oS**
end note end note
sender -> recipient: **UUID**, **inputs**, **change_output**, **fee**, **lock_height**, **kSG**, **xSG** sender -> recipient: **Slate**
== Phase 2 - Receiver Initiation == == Round 2 ==
note right of recipient note right of recipient
1: Check fee against number of **inputs**, **change_outputs** +1 * **receiver_output**) 1: Check fee against number of **inputs**, **change_outputs** +1 * **receiver_output**)
2: Create **receiver_output** 2: Create **receiver_output**
3: Choose random blinding factor for **receiver_output** **xR** (private scalar) 3: Choose random blinding factor for **receiver_output** **xR** (private scalar)
end note end note
recipient -> recipient: Store **receiver_output** in wallet with status "Unconfirmed"
note right of recipient note right of recipient
4: Calculate message **M** = **fee | lock_height ** 4: Calculate message **M** = **fee | lock_height **
5: Choose random nonce **kR** (private scalar) 5: Choose random nonce **kR** (private scalar)
6: Multiply **xR** and **kR** by generator G to create public curve points **xRG** and **kRG** 6: Multiply **xR** and **kR** by generator G to create public curve points **xRG** and **kRG**
7: Compute Schnorr challenge **e** = Blake2(**M** | **kRG** + **kSG**) 7: Compute Schnorr challenge **e** = Blake2(**M** | **kRG** + **kSG**)
8: Compute Recipient Schnorr signature **sR** = **kR** + **e** * **xR** 8: Compute Recipient Schnorr signature **sR** = **kR** + **e** * **xR**
9: Add **sR, xRG, kRG** to **Slate**
10: Create wallet output function **rF** that stores **receiver_output** in wallet with status "Unconfirmed"
and identifying transaction log entry **TR** linking **receiver_output** with transaction.
end note end note
alt All Okay alt All Okay
recipient --> sender: Okay - **UUID**, **sR**, **xRG**, **kRG** recipient --> sender: Okay - **Slate**
recipient -> recipient: execute wallet output function **rF**
else Any Failure else Any Failure
recipient -> recipient: Remove **receiver_output** from wallet
recipient ->x]: Abort recipient ->x]: Abort
recipient --> sender: Error recipient --> sender: Error
sender -> sender: Roll back **inputs** and **change_output**
[x<- sender: Abort [x<- sender: Abort
end end
== Phase 3 - Sender Confirmation == == Finalize Transaction ==
note left of sender note left of sender
1: Calculate message **M** = **fee | lock_height ** 1: Calculate message **M** = **fee | lock_height **
2: Compute Schnorr challenge **e** = Blake2(**M** | **kRG** + **kSG**) 2: Compute Schnorr challenge **e** = Blake2(**M** | **kRG** + **kSG**)
3: Verify **sR** by verifying **kRG** + **e** * **xRG** = **sRG** 3: Verify **sR** by verifying **kRG** + **e** * **xRG** = **sRG**
4: Compute Sender Schnorr signature **sS** = **kS** + **e** * **xS** 4: Compute Sender Schnorr signature **sS** = **kS** + **e** * **xS**
end note 5: Calculate final signature **s** = (**sS**+**sR**, **kSG**+**kRG**)
sender -> recipient: **UUID**, **sS** 6: Calculate public key for **s**: **xG** = **xRG** + **xSG**
== Phase 4 - Receiver Confirmation == 7: Verify **s** against excess values in final transaction using **xG**
note right of recipient 8: Create Transaction Kernel Containing:
1: Verify **sS** by verifying **kSG** + **e** * **xSG** = **sSG** Signature **s**
2: Calculate final signature **s** = (**sS**+**sR**, **kSG**+**kRG**)
3: Calculate public key for **s**: **xG** = **xRG** + **xSG**
3: Verify **s** against excess values in final transaction using **xG**
4: Create Transaction Kernel Containing:
Signature **s**
Public key **xG** Public key **xG**
**fee** **fee**
**lock_height** **lock_height**
excess value **oS**
end note end note
recipient -> recipient: Create final transaction **tx** sender -> sender: Create final transaction **tx** from **Slate**
recipient -> grin_node: Post **tx** to mempool sender -> grin_node: Post **tx** to mempool
grin_node --> recipient: "Ok" grin_node --> recipient: "Ok"
alt All Okay alt All Okay
recipient --> sender: "Ok" - **UUID** recipient --> sender: "Ok" - **UUID**
sender -> sender: Execute wallet lock function **sF**
...Await confirmation... ...Await confirmation...
recipient -> grin_node: Confirm **receiver_output** recipient -> grin_node: Confirm **receiver_output**
recipient -> recipient: Change status of **reciever_output** to "Confirmed" recipient -> recipient: Change status of **reciever_output** to "Confirmed"
@ -84,10 +86,10 @@ sender -> grin_node: Confirm **change_output**
sender -> sender: Change status of **inputs** to "Spent" sender -> sender: Change status of **inputs** to "Spent"
sender -> sender: Change status of **change_output** to "Confirmed" sender -> sender: Change status of **change_output** to "Confirmed"
else Any Error else Any Error
recipient -> recipient: Remove **receiver_output** from wallet recipient -> recipient: Manually remove **receiver_output** from wallet using transaction log entry **TR**
recipient ->x]: Abort recipient ->x]: Abort
recipient --> sender: Error recipient --> sender: Error
sender -> sender: Roll back **inputs** and **change_output** sender -> sender: Unlock **inputs** and delete **change_output** identified in transaction log entry **TS**
[x<- sender: Abort [x<- sender: Abort
end end

260
doc/wallet/usage.md Normal file
View file

@ -0,0 +1,260 @@
# Grin - Basic Wallet
## Wallet Files
A Grin wallet maintains its state in an LMDB database, with the master seed stored in a separate file.
A wallet directory should contain:
```
wallet.seed # *** passphrase protected seed file (keep this private) ***
wallet_data # The lmdb data directory in which wallet outputs and transaction information are stored
```
By default Grin will look for these in the current working directory.
### Logging + Output
Logging configuration for the wallet is read from `grin.toml`. To modify the wallet's logging output, copy `grin.toml` from the main grin directory
into the current wallet directory, and modify logging parameters. (Only parameters relevant to the wallet will be read.)
### Switches common to all wallet commands
##### Grin Node Address
The wallet generally needs to talk to a running grin node in order to remain up-to-date and verify its contents. By default, the wallet
tries to contact a node at `127.0.0.1:13413`. To change this, provide the `-a` switch to the wallet command, e.g.:
```
[host]$ grin wallet -a "http://192.168.0.2:1341" info
```
If commands that need to update from a grin node can't find one, they will generally inform you that the node couldn't be reached
and the results verified against the latest chain information.
##### Password
All keys generated by your wallet are combinations of the master seed + a password. If no password is provided, it's assumed this
password is blank. If you do provide a password, all operations will use the seed+password and you will need to password to view or
spend any generated outputs. The password is specified with `-p`
```
[host]$ grin wallet -p mypassword info
```
##### Data Directory
You can override the directory to use for wallet files with the `-d` flag, e.g:
```
[host]$ grin wallet -d ./path/to/other/dir info
```
## Basic Wallet Commands
`grin wallet --help` will display usage info and all flags.
`grin wallet help [command]` will deplay flags specific to the command, e.g `grin wallet help listen`
### init
Before using a wallet a new seed file `wallet.seed` and storage database needs to be generated via `grin wallet init` -
```
[host]$ grin wallet init
Jul 30 15:25:20.999 INFO This is Grin version 0.3.0 (git testnet3-47-gaa64854), built for x86_64-unknown-linux-gnu by rustc 1.27.0 (3eda71b00 2018-06-19).
Jul 30 15:25:20.999 DEBG Built with profile "debug", features "" on Tue, 24 Jul 2018 14:53:51 GMT.
Jul 30 15:25:20.999 DEBG Generating wallet seed file at: ./wallet.seed
Jul 30 15:25:20.999 INFO Wallet seed file created
Jul 30 15:25:21.085 INFO Wallet database backend created
```
### info
A summary of the wallet's contents can be retrieved from the wallet using the `info` command. Note that the `Total` sum may appear
inflated if you have a lot of unconfirmed outputs in your wallet (especially ones where a transaction is initiated by other parties
who then never it by posting to the chain). `Currently Spendable` is the most accurate field to look at here.
```
____ Wallet Summary Info as of 49 ____
Total | 3000.000000000
Awaiting Confirmation | 60.000000000
Immature Coinbase | 180.000000000
Currently Spendable | 2760.000000000
--------- | ---------
(Locked by previous transaction) | 0.000000000
```
### listen
This opens a listener on the specified port, which will listen for:
* Coinbase Transaction from a mining server
* Transactions initiated by other parties
By default the `listen` commands runs in a manner that only allows access from the local machine. To open this port up
to other machines, use the `-e` switch:
```
[host]$ grin wallet -e listen
```
To change the port on which the wallet is listening, use the `-l` flag, e.g:
```
[host]$ grin wallet -l 14000 listen
```
The wallet will listen for requests until the process is cancelled with `<Ctrl-C>`. Note that external ports/firewalls need to be configured
properly if you're expecting requests from outside your local network (well out of the scope of this document).
### send
This builds a transaction interactively with another running wallet, then posts the final transaction to the chain. As the name suggests,
this is how you send Grins to another party.
The most important fields here are the destination (`-d`) and the amount itself. To send an amount to another listening wallet:
```
[host]$ grin wallet send -d "http://192.168.0.10:13415" 60.00
```
This will create a transaction with the other wallet listening at 192.168.0.10, port 13415 which credits the other wallet 60 grins
while debiting the 60 Grin + fees from your wallet.
It's important to understand exactly what happens during a send command, so at a very basic level the `send` interaction goes as follows:
1) Your wallet selects a number of unspent inputs from your wallet, enough to cover the 60 grins + fees.
2) Your wallet locks these inputs so as not to select them for other transactions, and creates a change output in your wallet for the difference.
3) Your wallet adds these inputs and outputs to a transaction, and sends the transaction to the recipient.
4) The recipient adds their output for 60 grins to the transaction, and returns it to the sender.
5) The sender completes signing of the transaction.
6) The sender posts the transaction to the chain.
Outputs in your wallet will appear as unconfirmed or locked until the transaction hits the chain and is mined and validated.
Other flags here are:
* `-s` 'Selection strategy', which can be 'all' or 'smallest'. Since it's advantageous for outputs to be removed from the Grin chain,
the default strategy for selecting inputs in Step 1 above is to use as many outputs as possible to consolidate your balance into a
couple of outputs. This also drastically reduces your wallet size, so everyone wins. The downside is that the entire contents of
your wallet remains locked until the transaction is mined validated on the chain. To instead only select just enough inputs to
cover the amount you want to send + fees, use:
```
[host]$ grin wallet send -d "http://192.168.0.10:13415" -s smallest 60.00
```
* `-f` 'Fluff' Grin uses a protocol called 'Dandelion' which bounces your transaction directly through several listening nodes in a
'Stem Phase' before randomly 'Fluffing', i.e. broadcasting it to the entire network. This reduces traceability at the cost of lengthening
the time before your transaction appears on the chain. To ignore the stem phase and broadcast immediately:
```
[host]$ grin wallet send -f -d "http://192.168.0.10:13415" 60.00
```
### outputs
Simply displays all the the outputs in your wallet: e.g:
```
[host]$ grin wallet outputs
Wallet Outputs - Block Height: 49
------------------------------------------------------------------------------------------------------------------------------------------------
Key Id Child Key Index Block Height Locked Until Status Is Coinbase? Num. of Confirmations Value Transaction
================================================================================================================================================
13aea76c742ec6298360 2 1 4 Unspent true 49 60.000000000 37
------------------------------------------------------------------------------------------------------------------------------------------------
ef619c4cdda170f9a4eb 3 2 5 Unspent true 48 60.000000000 38
------------------------------------------------------------------------------------------------------------------------------------------------
be5a6f68db3ff4b88786 4 3 6 Unspent true 47 60.000000000 1
------------------------------------------------------------------------------------------------------------------------------------------------
753a4086bf73246f8206 5 4 7 Unspent true 46 60.000000000 2
------------------------------------------------------------------------------------------------------------------------------------------------
b2bf4c3e64a67158989f 6 5 8 Unspent true 45 60.000000000 4
------------------------------------------------------------------------------------------------------------------------------------------------
db427d890fe59824ee64 7 6 9 Unspent true 44 60.000000000 11
```
Spent outputs are not shown by default. To show them, provide the `-s` flag.
```
[host]$ grin wallet -s outputs
```
### txs
Every time an operation is performed in your wallet (recieve coinbase, send, receive), an entry is added to an internal transaction log
containing vital information about the transaction. Because the Mimblewimble chain contains no identifying information whatsoever,
this transaction log is necessary in order to allow your wallet to keep track of what was sent and received. To view the contents of the
transaction log, use the `txs`
```
[host]$ grin wallet txs
Transaction Log - Block Height: 49
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Id Type Shared Transaction Id Creation Time Confirmed? Confirmation Time Num. Inputs Num. Outputs Amount Credited Amount Debited Fee Net Difference
==========================================================================================================================================================================================================================================
1 Confirmed Coinbase None 2018-07-20 19:46:45.658263284 UTC true 2018-07-20 19:46:45.658264768 UTC 0 1 60.000000000 0.000000000 None 60.000000000
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2 Confirmed Coinbase None 2018-07-20 19:46:45.658424352 UTC true 2018-07-20 19:46:45.658425102 UTC 0 1 60.000000000 0.000000000 None 60.000000000
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3 Confirmed Coinbase None 2018-07-20 19:46:45.658541297 UTC true 2018-07-20 19:46:45.658542029 UTC 0 1 60.000000000 0.000000000 None 60.000000000
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4 Confirmed Coinbase None 2018-07-20 19:46:45.658657246 UTC true 2018-07-20 19:46:45.658657970 UTC 0 1 60.000000000 0.000000000 None 60.000000000
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5 Confirmed Coinbase None 2018-07-20 19:46:45.658864074 UTC true 2018-07-20 19:46:45.658864821 UTC 0 1 60.000000000 0.000000000 None 60.000000000
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6 Recieved Tx 03715cf6-f29b-4a3a-bda5-b02cba6bf0d9 2018-07-20 19:46:46.120244904 UTC false None 0 1 60.000000000 0.000000000 None 60.000000000
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
```
To see the inputs/outputs associated with a particular transaction, use the `-i` switch providing the Id of the given transaction, e.g:
```
[host]$ grin wallet txs -i 6
Transaction Log - Block Height: 49
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Id Type Shared Transaction Id Creation Time Confirmed? Confirmation Time Num. Inputs Num. Outputs Amount Credited Amount Debited Fee Net Difference
===========================================================================================================================================================================================================
6 Recieved Tx 03715cf6-f29b-4a3a-bda5-b02cba6bf0d9 2018-07-20 19:46:46.120244904 UTC false None 0 1 60.000000000 0.000000000 None 60.000000000
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Wallet Outputs - Block Height: 49
------------------------------------------------------------------------------------------------------------------------------------------------
Key Id Child Key Index Block Height Locked Until Status Is Coinbase? Num. of Confirmations Value Transaction
================================================================================================================================================
a7aebee71fdd78396ae6 9 5 0 Unconfirmed false 0 60.000000000 6
------------------------------------------------------------------------------------------------------------------------------------------------
```
##### cancel
Everything before Step 6 in the send phase above happens completely locally in the wallets' data storage and separately from the chain.
Since it's very easy for a sender, (through error or malice,) to fail to post a transaction to the chain, it's very possible for the contents
of a wallet to become locked, with all outputs unable to be selected because the wallet is waiting for a transaction that will never hit
the chain to complete. For example, in the output from `grin wallet txs -i 6` above, the transaction is showing as `confirmed == false`
meaning the wallet has not seen any of the associated outputs on the chain. If it's evident that this transaction will never be posted, locked
outputs can be unlocked and associate unconfirmed outputs removed with the `cancel` command.
Running against the data above:
```
[host]$ grin wallet cancel -i 6
[host]$ grin wallet txs -i 6
Transaction Log - Block Height: 49
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Id Type Shared Transaction Id Creation Time Confirmed? Confirmation Time Num. Inputs Num. Outputs Amount Credited Amount Debited Fee Net Difference
=======================================================================================================================================================================================================================
6 Received Tx - Cancelled 03715cf6-f29b-4a3a-bda5-b02cba6bf0d9 2018-07-20 19:46:46.120244904 UTC false None 0 1 60.000000000 0.000000000 None 60.000000000
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
```
Note that the Receive transaction has been cancelled, and the corresponding output was removed from the wallet. If I were the sender, my change
output would have been deleted, and any outputs that were locked for the transaction would again be available for use in another transaction.
Be sure to use this command with caution, as there are many edge cases and possible attacks that still need to be dealt with, particularly if you're
the recipient of a transaction. For the time being please be 100% certain that the relevant transaction is never, ever going to be posted before
running `grin wallet cancel`