Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 76 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,20 @@ should be followed.
The recovery tool supports recovering from both types of subaccounts.

## 2of2 Recovery
Coins held in a 2of2 account need to be signed by both you and GreenAddress.
Provided you have nLocktime emails enabled in your settings, the service
automatically generates special "nLockTime" transactions, pre-signed by
GreenAddress but not spendable until some time in the future (the nLockTime).

Coins held in 2of2 accounts need to be signed by both you and Blockstream
Green (also known with the previous name Greenaddress).
At the moment, provided you have nLocktime emails enabled in your settings, the
service automatically generates special "nLockTime" transactions, pre-signed by
Blockstream Green but not spendable until some time in the future (the
nLockTime).
To recover these coins, refer to the 'nLocktime' section.
In the future, thanks to a new type of script (CSV) the coins will be spendable
by your keys only after a chosen amount of blocks has passed.
To recover these coins, refer to the 'CSV (Check Sequence Verify)' section.
Note that, in some cases, it may be needed to follow both procedures to recover
all coins.

### nLocktime
To recover coins from a 2of2 account you simply wait until each nLockTime
transaction becomes spendable (90 days by default), then countersign using
the recovery tool and broadcast. The coins are sent to a key derived
Expand Down Expand Up @@ -88,6 +97,33 @@ using your full node via RPC or online tools such as:
https://blockexplorer.com/tx/send
https://www.smartbit.com.au/txs/pushtx

### CSV (Check Sequence Verify)
Unspent coins locked by CSV scripts (OP_CHECK_SEQUENCE_VERIFY, not to be
confused with the file extension `.csv`) in 2of2 subaccounts are discoverable
by scanning the blockchain to look for them. The recovery tool connects to your
Bitcoin Core full node in order to perform this scanning for you when
recovering.

You will need:

- A Bitcoin Core full node configured for local RPC access; the node wallet
functionality must not be disabled, indeed the coins will be sent to
addresses owned obtained from the node.
- The recovery tool
- Your Blockstream Green/GreenAddress mnemonic

To run the recovery tool in 2of2-csv mode:
```
$ garecovery-cli 2of2-csv -o garecovery.csv
```

Enter your mnemonic when prompted. The recovery tool will print a summary of the
recovery transactions and also write them to a file `garecovery.csv`.

If any recoverable coins were found the tool will display a summary of
them on the console and write the details to the output csv file ready for
broadcasting using the same steps as detailed above for 2of2 nLocktime.

## 2of3 Recovery
*Note for 0.17 users:* it is now possible to specify `--ignore-mempool`,
which makes the procedure much faster (by using `scantxoutset`).
Expand Down Expand Up @@ -141,6 +177,41 @@ If any recoverable coins were found the tool will display a summary of
them on the console and write the details to the output csv file ready for
broadcasting using the same steps as detailed above for 2of2 subaccounts.

## Liquid Recovery

In the case of Liquid subaccounts the outputs are locked by CSV
(OP_CHECK_SEQUENCE_VERIFY) scripts. Which means that coins can be spent either
by signing with your default key and the Green/GreenAddress key under
normal circumstances, or by signing with your default key only after a certain
amount of blocks.

Unspent coins in Liquid subaccounts are only discoverable by scanning the
blockchain to look for them. The recovery tool connects to your Liquid/Elements
core full node in order to perform this scanning for you when recovering.

You will need:

- A Liquid/Elements core full node configured for local RPC access
- The recovery tool
- Your Green/GreenAddress Liquid mnemonic

Instructions to run a Liquid node can be found
[here](https://docs.blockstream.com/liquid/quickstart.html). Ensure your node
is running, fully synced and you are able to connect to the RPC interface. You
can verify this using a command like:

$ /path/to/elements-core/bin/elements-cli getblockchaininfo

Run the recovery tool in CSV mode:

$ garecovery-liquid-cli csv --network=liquid

The tool will prompt you for your mnemonic.

Unlike 2of3, wallet functionality must be available on your node. Indeed the
tool will create transactions sending the recovered funds to addresses obtained
from the node.

# Troubleshooting

If you find any bugs, or have suggestions or patches, please raise them on
Expand Down
7 changes: 7 additions & 0 deletions garecovery/bin/garecovery-liquid-cli
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env python3
# PYTHON_ARGCOMPLETE_OK

import sys
from garecovery import recoverycli

sys.exit(recoverycli.main(sys.argv, is_liquid=True))
9 changes: 6 additions & 3 deletions garecovery/bitcoin_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@
import configparser


DEFAULT_CONFIG_FILENAME = "~/.bitcoin/bitcoin.conf"
DEFAULT_CONFIG_FILENAME = {
False: "~/.bitcoin/bitcoin.conf",
True: "~/.elements/elements.conf",
}
DUMMY_SECTION = 'X'


class Config:
"""Parse bitcoin configuration file"""

def __init__(self, config_filename=None):
def __init__(self, config_filename=None, is_liquid=False):
if config_filename is None:
config_filename = os.path.expanduser(DEFAULT_CONFIG_FILENAME)
config_filename = os.path.expanduser(DEFAULT_CONFIG_FILENAME[is_liquid])

self.config = configparser.ConfigParser()
try:
Expand Down
7 changes: 6 additions & 1 deletion garecovery/bitcoincore.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from . import bitcoin_config
from . import exceptions
from gaservices.utils import gacommon

import bitcoinrpc.authproxy

Expand Down Expand Up @@ -54,7 +55,7 @@ class Connection:

@staticmethod
def read_config(keys, options):
config = bitcoin_config.Config(options.config_filename)
config = bitcoin_config.Config(options.config_filename, gacommon.is_liquid(options.network))
return {key: config.get_val(key) for key in keys}

@staticmethod
Expand All @@ -75,6 +76,8 @@ def get_http_auth_header(config, network):
default_rpc_cookies = {
'testnet': '~/.bitcoin/testnet3/.cookie',
'mainnet': '~/.bitcoin/.cookie',
'liquid': '~/.elements/liquidv1/.cookie',
'localtest-liquid': '~/.elements/elementsregtest/.cookie',
}
rpccookiefile = os.path.expanduser(default_rpc_cookies[network])
logging.info('Reading bitcoin authentication cookie from "{}"'.format(rpccookiefile))
Expand Down Expand Up @@ -105,6 +108,8 @@ def __init__(self, args):
default_rpc_ports = {
'testnet': 18332,
'mainnet': 8332,
'liquid': 7041,
'localtest-liquid': 7040,
}
config['rpcport'] = default_rpc_ports[args.network]
logging.info('Defaulting rpc port to {}'.format(config['rpcport']))
Expand Down
Loading