Merge #103: README.md and CONTRIBUTING.md

b4f6bbd8ffa722c48725fc724ca6cb1a4cf0b116 Add a README, finally. (Antoine Poinsot)
2663d970c77c7c13da8f39c3059123ef231b1787 Add a CONTRIBUTING.md (Antoine Poinsot)
f5ff0fad362a20d97d4ccc7fc5926bbfab50ec3a daemon: 'revaultd' name usage leftovers (Antoine Poinsot)

Pull request description:

  Starting the documentation effort with those two main files. I'll address both a dedicated document about building the software and another dedicated document about recovering from descriptor backup in a follow-up.

ACKs for top commit:
  darosior:
    self-ACK b4f6bbd8ffa722c48725fc724ca6cb1a4cf0b116

Tree-SHA512: 58172527d6c09b718f9b15989fe976ceb4c20192bd8dfc7ee2cc9c683f8add19ef184869e1ab285c3d025b5ed6d69c6e9f3eaf5fc3f8e9a29ba632c0e3cae2d9
This commit is contained in:
Antoine Poinsot 2022-11-19 12:24:30 +01:00
commit 18771b62a8
No known key found for this signature in database
GPG Key ID: E13FC145CD3F4304
6 changed files with 264 additions and 4 deletions

75
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,75 @@
# Contributing to Liana
Anyone is welcome to contribute to Liana regardless of any arbitrary criterion. Contribution are
only judged based on their technical relevance and quality.
Note that the development of Bitcoin software requires a high level of rigor, so it could take some
time (and backs and forths) to polish a contribution before it's ready for merge.
## Communication
Most of the communication is done on GitHub or on the [`#revault` IRC channel on
Libera](https://web.libera.chat/?channels=#revault).
If you plan to contribute a non-trivial change, consider discussing it in the IRC channel or in a
Github issue before going forward with the implementation.
## Looking for contributions
If you are looking for first time contributions, you can `git grep` for `FIXME`s and `TODO`s
as well as checking out the [good first issues](https://github.com/revault/liana/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
on the issue tracker.
# Workflow
The codebase is maintained using the "contributor workflow" where everyone
without exception contributes patch proposals using "pull requests" (PRs). This
facilitates social contribution, easy testing and peer review.
In general, [commits should be atomic](https://en.wikipedia.org/wiki/Atomic_commit#Atomic_commit_convention)
and diffs should be easy to read. For this reason, do not mix any formatting
fixes or code moves with actual code changes.
Make sure each individual commit is hygienic: that it builds successfully
on its own without warnings, errors, regressions, or test failures.
Commit messages should be verbose by default consisting of a short subject line,
a blank line and detailed explanatory text as separate paragraph(s), unless the
title alone is self-explanatory. Commit messages should be helpful to people
reading your code in the future, so explain the reasoning for your decisions. For
more guidelines about writing commit messages, see this [blog post](https://cbea.ms/git-commit/).
If your pull request contains fixup commits (commits that change the same line of code repeatedly) or too fine-grained
commits, you may be asked to [squash](https://git-scm.com/docs/git-rebase#_interactive_mode) your commits
before it will be merged.
Patchsets should always be focused. For example, a pull request could add a
feature, fix a bug, or refactor code; but not a mixture. Please also avoid super
pull requests which attempt to do too much, are overly large, or overly complex
as this makes review difficult. Instead, prefer opening different focused pull requests.
Anyone may participate in peer review which is expressed by comments in the pull
request. Typically reviewers will review the code for obvious errors, as well as
test out the patch set and opine on the technical merits of the patch. PR should
be reviewed first on the conceptual level before focusing on code style or grammar
fixes.
Any new contributed feature must come with tests. Preferably both an integration/functional tests
demonstrating its usage in a blackbox manner (for instance calling an RPC command under different
conditions), as well as unit tests exercising specific parts of the logic (for instance a database
query).
# Code
## Minimum Supported Rust Version
`minisafed` should always compile and pass tests using **Rust 1.48**.
## Style
To avoid endless bikeshedding, just use [`rustfmt`](https://github.com/rust-lang/rustfmt).
[Clippy](https://github.com/rust-lang/rust-clippy) is also often your friend.

147
README.md Normal file
View File

@ -0,0 +1,147 @@
# Liana
*The missing safety net for your bitcoins*.
## About
Liana is a simple Bitcoin wallet that features a timelocked recovery path for all your coins. That
is, your coins are spendable as with a regular wallet but a secondary key becomes available after a
configurable period of time should the primary one not be accessible anymore.
Liana can be used for inheritance, where the owner of the coins is holding the primary key and the
heir the secondary one. It can also be leveraged for recovery where a single person is holding both
but different tradeoffs can be made between the backup(s) of the directly accessible and timelocked
keys.
Liana is still under heavy development. Apart from the regular wallet features that are planned, we
intend to implement the possibility to have multiple keys per spending path (multisig) as well as
multiple timelocked paths (for instance for decaying multisigs). We also intend to switch to using
Taproot as soon as possible, for enhanced privacy.
**As such please consider Liana to be beta software.**
## Usage
As a Bitcoin wallet, Liana needs to be able to connect to the Bitcoin network. The software has been
developed such as multiple ways to connect to the Bitcoin network may be available. However for now
only the connection through `bitcoind` is implemented.
Therefore in order to use Liana you need to have Bitcoin Core running on your machine for the
desired network. The `bitcoind` installation may be pruned (note this may affect block chain
rescans) up to the maximum (around 550MB of blocks).
The minimum supported version of Bitcoin Core is `24.0`. If you don't have Bitcoin Core installed on
your machine yet, you can download it [there](https://bitcoincore.org/en/download/).
### Installing the software
TODO: download links
TODO: link to a longer-form document in the doc/ folder containing the different build methods.
### Setting up a wallet
If you are using the GUI, you can just start the program. It will spawn an installer that will guide
you through the process of setting up a new wallet.
If you are using the daemon, you will need to specify its configuration as a TOML file. There is a
documented example of such a configuration file in the [`contrib/` folder](contrib/lianad_config_example.toml).
Then you can start the daemon like so:
```
lianad --conf /path/to/your/conf.toml
```
#### The script descriptor
**MAKE SURE TO BACK UP YOUR DESCRIPTOR**
In Bitcoin, the conditions for spending a certain amount of coins are expressed using a
[Script](https://en.bitcoin.it/wiki/Script). In order to be able to recover your coins, you need to
back up both:
- The Script template, in the form of a standard [Output Script
Descriptor](https://github.com/bitcoin/bips/blob/master/bip-0380.mediawiki)
- The private key corresponding to the public key used in the Script
By so doing, any software that understands the Output Script Descriptor standard will be able to
retrieve your coins. By using your private key you would then be able to sign a transaction spending
them.
But **without the descriptor you won't be able to recover from your backup**. Note however it is
simpler to have redundancy for your descriptor backup. A thief getting access to it will be able to
learn your balance (and transaction history), but **will not be able to steal your funds**.
Therefore you may afford a greater number of backups of your descriptor(s) and using less secure
mediums than for storing your private key.
### Using a wallet
You can use Liana just like a regular wallet. Just be aware that if you are using a relative
timelock (the only type of timelocks supported for now), time starts ticking when you receive a
payment. That is if you want the recovery path to never be available, all coins must be spent
at least once every `N` blocks. (With `N` the configured value of the timelock.)
For now, only the Ledger and Specter DIY signing devices are supported. We may add the possibility
to use Liana as a "hot" wallet in the future (i.e. with a private key directly on the laptop).
If you are using the GUI, it should be intuitive what menu to use depending on your intention. If it
is not, bug report are very welcome so [feel free to report it](https://github.com/revault/liana/issues)! :)
If you are using the daemon, you can use the `liana-cli` binary to send commands to it. It will need
the path to the same configuration as the daemon. You can find a full documentation of the JSONRPC
API exposed by `lianad` at [`doc/API.md`](doc/API.md). For instance:
```
$ liana-cli --conf ./testnet_config.toml getinfo
{
"result": {
"blockheight": 2406973,
"descriptors": {
"main": {
"change_desc": "wsh(or_d(pk([92162c45]tpubD6NzVbkrYhZ4WzTf9SsD6h7AH7oQEippXK2KP8qvhMMqFoNeN5YFVi7vRyeRSDGtgd2bPyMxUNmHui8t5yCgszxPPxMafu1VVzDpg9aruYW/1/*),and_v(v:pkh(tpubD6NzVbkrYhZ4Wdgu2yfdmrce5g4fiH1ZLmKhewsnNKupbi4sxjH1ZVAorkBLWSkhsjhg8kiq8C4BrBjMy3SjAKDyDdbuvUa1ToAHbiR98js/1/*),older(2))))#5rx53ql7",
"multi_desc": "wsh(or_d(pk([92162c45]tpubD6NzVbkrYhZ4WzTf9SsD6h7AH7oQEippXK2KP8qvhMMqFoNeN5YFVi7vRyeRSDGtgd2bPyMxUNmHui8t5yCgszxPPxMafu1VVzDpg9aruYW/<0;1>/*),and_v(v:pkh(tpubD6NzVbkrYhZ4Wdgu2yfdmrce5g4fiH1ZLmKhewsnNKupbi4sxjH1ZVAorkBLWSkhsjhg8kiq8C4BrBjMy3SjAKDyDdbuvUa1ToAHbiR98js/<0;1>/*),older(2))))#uact7s3g",
"receive_desc": "wsh(or_d(pk([92162c45]tpubD6NzVbkrYhZ4WzTf9SsD6h7AH7oQEippXK2KP8qvhMMqFoNeN5YFVi7vRyeRSDGtgd2bPyMxUNmHui8t5yCgszxPPxMafu1VVzDpg9aruYW/0/*),and_v(v:pkh(tpubD6NzVbkrYhZ4Wdgu2yfdmrce5g4fiH1ZLmKhewsnNKupbi4sxjH1ZVAorkBLWSkhsjhg8kiq8C4BrBjMy3SjAKDyDdbuvUa1ToAHbiR98js/0/*),older(2))))#d693mvvd"
}
},
"network": "testnet",
"rescan_progress": null,
"sync": 1.0,
"version": "0.1"
}
}
```
Note also that you might connect the GUI to a running `lianad`. If the GUI detects a daemon is
already running, it will plug to it and communicate through the JSONRPC API.
### Wallet recovery
TODO: have a longer form document on recovery through the recovery path.
## About the software project
Liana is an open source project. It is [hosted at Github](https://github.com/revault/liana).
Contributions are very welcome. For guidelines, see [CONTRIBUTING.md](CONTRIBUTING.md).
Liana is separated in two main components: the daemon and the Graphical User Interface.
### Liana daemon
The daemon contains the core logic of the wallet. It is both a library (a Rust crate) that exposes a
command interface and a standalone UNIX daemon that exposes a JSONRPC API through a Unix Domain
Socket.
The code for the daemon can be found in the [`src/`](src/) folder at the root of this repository.
### Liana GUI
The GUI contains both an installer that guides a user through setting up a Liana wallet, as well as
a graphical interface to the daemon using the [`iced`](https://github.com/iced-rs/iced/) library.
The code for the GUI can be found in the [`gui/src/`](gui/src) folder.
## License
Released under the BSD 3-Clause Licence. See the [LICENCE](LICENCE) file.

View File

@ -0,0 +1,38 @@
# Whether to run the process as a UNIX daemon (double fork magic)
daemon = false
# (Optional) Path to the folder where we should store the application data.
# Defaults to `.lianad` in your home folder.
data_dir = "/home/wizardsardine/.lianad"
# How verbose logging should be (one of "error", "warn", "info", "debug", "trace")
log_level = "debug"
# The wallet descriptor. It must be a Segwit v0 Pay-To-Witness-Script-Hash (`wsh()`) descriptor
# corresponding to a `or(pk(A),and(pk(B),older(X)))` policy (either public key A can spend immediately
# or public key B can spend after X blocks).
# The public keys must be valid extend keys ("xpubs") ending with a wildcard (i.e. can be derived
# from). The public keys must be multipath expressions with exactly the `0` and `1` derivation indexes,
# that is having a derivation step which is `/<0;1>` before the last step. This is in order to be able
# to derive deposit and change addresses from the same descriptor.
# The extended public keys must be encoded for the network the daemon is to be run (i.e. "xpub"s for the
# main network and "tpub"s for everything else).
#
# YOUR DESCRIPTOR IS UNIQUE AND MUST BE BACKED UP, WITHOUT IT YOU WONT BE ABLE TO RECOVER YOUR FUNDS.
#
main_descriptor = "wsh(or_d(pk([92162c45]tpubD6NzVbkrYhZ4WzTf9SsD6h7AH7oQEippXK2KP8qvhMMqFoNeN5YFVi7vRyeRSDGtgd2bPyMxUNmHui8t5yCgszxPPxMafu1VVzDpg9aruYW/<0;1>/*),and_v(v:pkh(tpubD6NzVbkrYhZ4Wdgu2yfdmrce5g4fiH1ZLmKhewsnNKupbi4sxjH1ZVAorkBLWSkhsjhg8kiq8C4BrBjMy3SjAKDyDdbuvUa1ToAHbiR98js/<0;1>/*),older(2))))#uact7s3g"
# This section is the configuration related to the Bitcoin backend.
# On what network shall it operate?
# How often should it poll the Bitcoin backend for updates?
[bitcoin_config]
network = "testnet"
poll_interval_secs = 30
# This section is specific to the bitcoind implementation of the Bitcoin backend. This is the only
# implementation available for now.
# In order to be able to connect to bitcoind, it needs to know on what port it is listening as well
# as where the authentication cookie is located.
[bitcoind_config]
addr = "127.0.0.1:18332"
cookie_path = "/home/wizardsardine/.bitcoin/testnet3/.cookie"

View File

@ -24,7 +24,7 @@ const RPC_SOCKET_TIMEOUT: u64 = 180;
// A retry happens every 1 second, this makes us give up after one minute.
const BITCOIND_RETRY_LIMIT: usize = 60;
// The minimum bitcoind version that can be used with revaultd.
// The minimum bitcoind version that can be used with lianad.
const MIN_BITCOIND_VERSION: u64 = 239900;
/// An error in the bitcoind interface.
@ -591,7 +591,7 @@ impl BitcoinD {
}
pub fn sync_progress(&self) -> f64 {
// TODO: don't harass revaultd, be smarter like in revaultd.
// TODO: don't harass lianad, be smarter like in revaultd.
roundup_progress(
self.block_chain_info()
.get("verificationprogress")

View File

@ -305,7 +305,7 @@ impl DaemonHandle {
if config.daemon {
log::info!("Daemonizing");
let log_file = data_dir.as_path().join("log");
let pid_file = data_dir.as_path().join("revaultd.pid");
let pid_file = data_dir.as_path().join("lianad.pid");
unsafe {
daemonize::daemonize(&data_dir, &log_file, &pid_file)
.map_err(StartupError::Daemonization)?;

View File

@ -174,7 +174,7 @@ class UnixDomainSocketRpc(object):
return json.loads(buff)
except json.JSONDecodeError:
# There is more to read, continue
# FIXME: this is a workaround for large reads taken from revaultd.
# FIXME: this is a workaround for large reads taken from lianad.
# We should use the '\n' marker instead since lianad uses that.
continue