GithubHelp home page GithubHelp logo

aquarium's Introduction

Aquarium πŸ§™ 🐟

A Revault sandbox

About

Being a complete custody solution, configuring all the parts of a Revault deployment is a bit tedious. Aquarium is a Python script re-using revaultd's functional testing framework to provide a turnkey solution to deploy a Revault setup on a regtest network.

The aquarium.py script will fetch the source of the different Revault binaries (revaultd, revault-gui, coordinatord, cosignerd) at a given version, compile them using Cargo, start a (single) bitcoind in regtest mode, hook into the test_framework to write all the configuration (Bitcoin keys, communication keys, script descriptors, connections, ..) and finally drop you in a shell with pre-defined aliases.

The aquarium only runs on Unix systems for now.

Usage

Clone the aquarium repo first:

git clone https://github.com/revault/aquarium
cd aquarium

Dependencies

If you don't already have bitcoind installed, you can get it from bitcoincore.org or compile it from the source. The minimum supported version is 22.0. You'll need to have an accessible bitcoind via your environment or to set the BITCOIND_PATH variable.

The testing framework has a few dependencies (for key generation, DB connection and bitcoind RPC mocking specifically). The recommended method for installing them is by using a venv.

python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt

Also, you will need to install Cargo which you very likely already have installed if you have a Rust toolchain.

You will need a version of at least 1.43 for building revaultd, miradord and cosignerd. If you are going to use the GUI or coordinatord, the latest stable version is required to build both. You can check your version with:

cargo --version

Finally, the GUI has a few dependencies.

Running

To deploy Revault you'll need to specify the number of Stakeholders (participants not taking actively part in spendings but pre-signing authorizations of spending), Managers (participants taking part in spending using the pre-signed transactions) and Stakeholders-Managers (participants acting as both), and the Unvault timelock duration (number of blocks during which any participant or watchtower can Cancel a spending attempt). Optionally, you can also set a threshold for the managers (eg 2 out of the 3 managers are enough to Spend a pre-signed Unvault):

$ ./aquarium.py --help
usage: aquarium.py [-h] -stks STAKEHOLDERS -mans MANAGERS -stkmans
                   STAKEHOLDER_MANAGERS -csv TIMELOCK
                   [-mansthresh MANAGERS_THRESHOLD] [-cosigs]
                   [-policy POLICIES]

optional arguments:
  -h, --help            show this help message and exit

Deployment configuration:
  -stks STAKEHOLDERS, --stakeholders STAKEHOLDERS
                        The number of only-stakeholder
  -mans MANAGERS, --managers MANAGERS
                        The number of only-manager
  -stkmans STAKEHOLDER_MANAGERS, --stakeholder-managers STAKEHOLDER_MANAGERS
                        The number of both stakeholder-manager
  -csv TIMELOCK, --timelock TIMELOCK
                        The number of blocks during which an Unvault attempt
                        can be canceled
  -mansthresh MANAGERS_THRESHOLD, --managers-threshold MANAGERS_THRESHOLD
  -cosigs, --with-cosigning-servers
                        Enable cosigning servers to allow Spend policies at
                        the cost of weaker assumptions
  -policy POLICIES, --spending-policy POLICIES
                        Enforce a spending policy on all watchtowers by
                        specifying a path to a watchtower plugin. Specify this
                        option multiple times to enable multiple policies.

Assuming you want to deploy a Revault setup with 1 Stakeholder, 1 Manager and 2 Stakeholder-Managers who can Spend with a threshold of 2 after 6 blocks (and no automated spending policy):

./aquarium.py --stakeholders 1 --managers 1 --stakeholder-managers 2 --timelock 6 --managers-threshold 2

You will get into a shell where you can use the aliases to start messing around (you can consult them at any time using the alias command):

Available aliases: 
alias bd="bitcoind -datadir='/home/darosior/projects/revault/aquarium/demo/bitcoind'"
alias bcli="bitcoin-cli -datadir='/home/darosior/projects/revault/aquarium/demo/bitcoind' -rpcwallet='revaultd-tests'"
alias stk0cli="/home/darosior/projects/revault/aquarium/src/revaultd/target/debug/revault-cli --conf /home/darosior/projects/revault/aquarium/demo/revaultd-stk-0/config.toml"
alias stk0d="/home/darosior/projects/revault/aquarium/test_framework/../../target/debug/revaultd --conf /home/darosior/projects/revault/aquarium/demo/revaultd-stk-0/config.toml"
alias stk0gui='/home/darosior/projects/revault/aquarium/src/revault-gui/target/debug/revault-gui --conf /home/darosior/projects/revault/aquarium/demo/revaultd-stk-0/regtest/gui_config.toml'
alias man0cli="/home/darosior/projects/revault/aquarium/src/revaultd/target/debug/revault-cli --conf /home/darosior/projects/revault/aquarium/demo/revaultd-man-0/config.toml"
alias man0d="/home/darosior/projects/revault/aquarium/test_framework/../../target/debug/revaultd --conf /home/darosior/projects/revault/aquarium/demo/revaultd-man-0/config.toml"
alias man0gui='/home/darosior/projects/revault/aquarium/src/revault-gui/target/debug/revault-gui --conf /home/darosior/projects/revault/aquarium/demo/revaultd-man-0/regtest/gui_config.toml'
alias stkman0cli="/home/darosior/projects/revault/aquarium/src/revaultd/target/debug/revault-cli --conf /home/darosior/projects/revault/aquarium/demo/revaultd-stkman-0/config.toml"
alias stkman0d="/home/darosior/projects/revault/aquarium/test_framework/../../target/debug/revaultd --conf /home/darosior/projects/revault/aquarium/demo/revaultd-stkman-0/config.toml"
alias stkman0gui='/home/darosior/projects/revault/aquarium/src/revault-gui/target/debug/revault-gui --conf /home/darosior/projects/revault/aquarium/demo/revaultd-stkman-0/regtest/gui_config.toml'
alias stkman1cli="/home/darosior/projects/revault/aquarium/src/revaultd/target/debug/revault-cli --conf /home/darosior/projects/revault/aquarium/demo/revaultd-stkman-1/config.toml"
alias stkman1d="/home/darosior/projects/revault/aquarium/test_framework/../../target/debug/revaultd --conf /home/darosior/projects/revault/aquarium/demo/revaultd-stkman-1/config.toml"
alias stkman1gui='/home/darosior/projects/revault/aquarium/src/revault-gui/target/debug/revault-gui --conf /home/darosior/projects/revault/aquarium/demo/revaultd-stkman-1/regtest/gui_config.toml'
alias hw='/home/darosior/projects/revault/aquarium/src/revault-gui/contrib/tools/dummysigner/target/debug/dummysigner --conf /home/darosior/projects/revault/aquarium/demo/dummysigner.toml'

Here is an example funding a new deposit using the CLI (you can also get an address using the GUI):

(Revault demo) darosior@darosior:~/projects/revault/aquarium$ stkman1cli getdepositaddress
{
  "result": {
    "address": "bcrt1qsnaqyq4lj8s4jlvafsl33fhcxgcctv2wwvluycyhxlzsg0zfeqrqxdr0t9"
  }
}

So we got a deposit address. Let's send some coins to it.

(Revault demo) darosior@darosior:~/projects/revault/aquarium$ stkman1cli listvaults
{
  "result": {
    "vaults": []
  }
}
(Revault demo) darosior@darosior:~/projects/revault/aquarium$ bcli sendtoaddress bcrt1qsnaqyq4lj8s4jlvafsl33fhcxgcctv2wwvluycyhxlzsg0zfeqrqxdr0t9 0.42
9b617d207ee528d50cbcc94a25243a44aefa8234632f98dc1aa84ff9deba4dde

The daemon won't consider unconfirmed deposit (a single confirmation for aquarium's configuration, but the default is higher).

(Revault demo) darosior@darosior:~/projects/revault/aquarium$ bcli generatetoaddress 7 $(bcli getnewaddress) 
[
  "03dedb10899ac34bc0e36d56c69689e6b50d4bca94d6d9e6f85a51be0f10e692"
]
(Revault demo) darosior@darosior:~/projects/revault/aquarium$ stkman1cli listvaults
{
  "result": {
    "vaults": [
      {
        "address": "bcrt1qsnaqyq4lj8s4jlvafsl33fhcxgcctv2wwvluycyhxlzsg0zfeqrqxdr0t9",
        "amount": 42000000,
        "blockheight": 102,
        "delegated_at": null,
        "derivation_index": 0,
        "funded_at": 1640009724,
        "moved_at": null,
        "secured_at": null,
        "status": "funded",
        "txid": "9b617d207ee528d50cbcc94a25243a44aefa8234632f98dc1aa84ff9deba4dde",
        "vout": 1
      }
    ]
  }
}

To launch the GUI for one of the participants:

stk0gui &

(redirecting stdout here to avoid getting annoyed by the logs)

The above line will start the GUI of the first stakeholder. You can then create a vault out of a deposit by signing the revocation transactions. screenshot

For testing purposes revault-gui provides a dummy signer mocking the flow of signing the transactions on a compatible hardware wallet. Because a dummy signer to manage in addition to each participants' GUI would be too much, by default Aquarium configures a single dummy signer for all the keys (and you can choose which keys to sign for at runtime). Start the dummy signer with the following alias:

hw &

We'll directly sign with all the stakeholders' keys. For "The Real Revault Experience" (tm) or testing purposes, you can sign for each stakeholder by starting each of their GUI and selecting their key on the dummy signer. screenshot screenshot

The same goes for delegation. Let's create two new vaults, secure them and delegate only 2 out of the 3 secured vaults.

$ bcli sendtoaddress bcrt1qest4mk20cs77m7mhv9us0f0ta76lljtke25w0lqs5zqrgjp8v9uq7z2wy2 0.21
2164a2ce3790d06dbd1c2b44bb7a36680399de706214dd25238503f9f8dc0ac9
$ bcli sendtoaddress bcrt1qest4mk20cs77m7mhv9us0f0ta76lljtke25w0lqs5zqrgjp8v9uq7z2wy2 1.2
d1e15483e5d1c1415f4e52b2921b0246fa890d2f6fe40b23c8ecdc46e7785028
$ bcli generatetoaddress 1 $(bcli getnewaddress)
[
  "5ee061f2e178a455be458dd7629e60f0d5b235940ebe4c1fa7bbfce4c3cebc76"
]

We now have 1.83 BTC under custody, with 0.63 available to managers in 2 vaults. Availability here depends of course of hypothetical spending policy we could enforce manually or with watchtowers (but we didn't in order to keep this walkthrough concise). screenshot

Now we can start 2 managers (remember, there are 3 managers but the threshold for spending is only of 2).

$ man0gui &
$ stkman0gui &
$ bcli getnewaddress
bcrt1q2zn3znj8v5s2tp9v9pt9jvwxder8sv2ve9yc09

Thend create a Spend transaction and sign it with the first one, make the second sign and then broadcast it. screenshot screenshot screenshot

Now let's confirm the Unvault transactions.

$ bcli generatetoaddress 1 $(bcli getnewaddress)
[
  "0588055b747847ecf0281d708e16378f60f0944dcaff5d7926374e5f3f14c897"
]

And back on the stakeholder's screen. We have 6 blocks to Cancel the unvaulting but choose to let it go through. screenshot

By then mining the 6 blocks for the locktime to mature and 1 block to confirm the Spend after it was broadcast, the spending is finalized.

$ bcli generatetoaddress 6 $(bcli getnewaddress)
[
  "0780bb19c7f2bf51e54b517e261e5b3097447789f01488e743d5d8620b726953",
  "6c8dbc310b9034670cc353e1a8081d34d7275c03d286f3a253abbfa36d9c243f",
  "5282fe85d891d479dc6bb8a163e345f1e828e2791b0e0ff472b0e374d5045aa3",
  "0f9a31ff7ee459f949d416d1d05b04e7d6fb7c5881edb4003f4768d491e668b4",
  "767d4b951c25a18ac290d4421203daf224e43a1dbcd8eb4817196208dfba0abc",
  "717f66acb946e222d94107f2574a630afb5f14f842264b193b03b5b54845293d"
]
$ bcli generatetoaddress 1 $(bcli getnewaddress)
[
  "3659cb6fd76c646ed9f59e64646cea738718acc4ac55271bf4ea1d7480c09b39"
]

screenshot

Running with coordinatord

By default, Aquarium will use a dummy fully in-RAM coordinator. If you are willing to use the "real" coordinator, you first need to set up a PostgreSQL backend.

The easiest way to do so is by using Docker:

docker run --rm -d -p 5432:5432 --name postgres-coordinatord -e POSTGRES_PASSWORD=revault -e POSTGRES_USER=revault -e POSTGRES_DB=coordinator_db postgres:alpine

If you already have a Postgre backend set up, the script will just need credentials (and optionally a POSTGRES_HOST) and will take care of creating the database (and removing it at teardown).

Assuming you've set a PostgreSQL backend with credentials revault:revault as with the Docker example above, and you want to deploy a Revault setup with 1 Stakeholder, 1 Manager and 2 Stakeholder-Managers who can Spend with a threshold of 2 after 6 blocks (and no automated spending policy):

POSTGRES_USER=revault POSTGRES_PASS=revault ./aquarium.py --stakeholders 1 --managers 1 --stakeholder-managers 2 --timelock 6 --managers-threshold 2

Tweaking

You can disable the GUI by setting the WITH_GUI environment variable to 0. This saves a considerable amount of time (revault-gui compilation).

The shell you are being dropped in is set to bash by default. This can be modified using the SHELL environment variable, however this has only been tested with bash. In fact, it would most likely break at the moment with another shell as we are using --init-file to provide aliases.

By default, all data directories are created in a demo parent directory created in the current working directory. This can be changed using the BASE_DIR environment variable.

You can adjust the logging level using the LOG_LEVEL environment variable. This will affect the daemons logs and test framework verbosity.

You can set a single dummy signer for each participant and have an alias for each by setting WITH_ALL_HWS=1.

See [aquarium.py] for more environment variable. Notably, you can change the source code version being fetched, and the directory in which repos are git cloned.

Contributing

Contributions are very welcome, and especially for documentation that may be unclear to someone external to the project or fixups to the aquarium.py script for environments we haven't tested in ourselves!

For code modification, please bear in mind that we want to keep the divergence between this repo's test_framework and revaultd's one as low as possible to reduce the maintenance burden of maintaining this repo up-to-date. If you have a fix for the test_framework itself, prefer proposing it upstream to revaultd.

aquarium's People

Contributors

danielabrozzoni avatar darosior avatar edouardparis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

aquarium's Issues

Don't spin up cosigning servers by default

After revault/revault_tx#112 they are not mandatory anymore. Cosigning servers aren't needed for any of the feature we currently provide and even eventually i don't think they should be used for the vast majority of the deployments. Therefore they should not be used by default.

BUG: zsh not supported

Describe the bug

When using non-bash shell say zsh, shell does not open.

In file aquarium.py,
executing subprocess.call([SHELL, "--init-file", f"{aliases_file}", "-i"])
produces error
/usr/bin/zsh: no such option: init_file

this is because zsh dont support providing init-file yet.

Expected Results

  1. Since zsh don't support init-file, it should always start bash insteed
  2. we can start bash only when default shell is zsh ie. if SHELL.endswith('zsh').
  3. make it work for zsh

Solution1.

SHELL="/usr/bin/bash"
subprocess.call([SHELL, "--init-file", f"{aliases_file}", "-i"])

Solution2.

if SHELL.endswith('zsh'):
subprocess.call(["/usr/bin/bash", "--init-file", f"{aliases_file}", "-i"])
else:
subprocess.call([SHELL, "--init-file", f"{aliases_file}", "-i"])

Solution3.

since zsh dont support init-file this has to be done the hard-way.

Any solution to support zsh with aliases is most welcome.

Installation: MarkupSafe==0.23 required

Describe the bug

soft_unicode is removed from MarkupSafe version 2.1.0, and this project uses it

I got an error with this versions 2.1.1 & 2.1.0

ImportError: cannot import name 'soft_unicode' from 'markupsafe'

Any version >=0.23 and <2.1.0 will work.

Solution

This project works well with MarkupSafe>=0.23,<2.1.0
Mentioning this in requirements.txt will solve the problem.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.