Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Watchtower #54

Open
wants to merge 3 commits into
base: watchtower
Choose a base branch
from
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
5 changes: 5 additions & 0 deletions frontend/modules/account/operations.js
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,11 @@ function initAccount(login, newAccount = false) {
if (!response.ok) {
return handleError(dispatch, getState, response.error);
}
response = await window.ipcClient("connectWT");
logger.log("Connect watchtower");
if (!response.ok) {
return handleError(dispatch, getState, response.error);
}
response = await dispatch(getLightningID());
logger.log("Have got lightning id");
logger.log(response);
Expand Down
190 changes: 153 additions & 37 deletions server/binaries/proto/rpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ syntax = "proto3";
import "google/api/annotations.proto";

package lnrpc;

option go_package = "github.com/lightningnetwork/lnd/lnrpc";

/**
* Comments in this file will be directly parsed into the API
* Documentation as descriptions of the associated method, message, or field.
Expand Down Expand Up @@ -217,17 +220,6 @@ service Lightning {
};
}

/** lncli: `estimatefee`
EstimateFee asks the chain backend to estimate the fee rate and total fees
for a transaction that pays to multiple specified outputs.
*/
rpc EstimateFee (EstimateFeeRequest) returns (EstimateFeeResponse) {
option (google.api.http) = {
post: "/v1/transactions/fee"
body: "*"
};
}

/** lncli: `sendcoins`
SendCoins executes a request to send coins to a particular address. Unlike
SendMany, this RPC call only allows creating a single output at a time. If
Expand All @@ -242,6 +234,16 @@ service Lightning {
};
}

/** lncli: `listunspent`
ListUnspent returns a list of all utxos spendable by the wallet with a
number of confirmations between the specified minimum and maximum.
*/
rpc ListUnspent (ListUnspentRequest) returns (ListUnspentResponse) {
option (google.api.http) = {
get: "/v1/utxos"
};
}

/**
SubscribeTransactions creates a uni-directional stream from the server to
the client in which any newly discovered transactions relevant to the
Expand Down Expand Up @@ -401,7 +403,7 @@ service Lightning {
*/
rpc CloseChannel (CloseChannelRequest) returns (stream CloseStatusUpdate) {
option (google.api.http) = {
delete: "/v1/channels/{channel_point.funding_txid_str}/{channel_point.output_index}/{force}"
delete: "/v1/channels/{channel_point.funding_txid_str}/{channel_point.output_index}"
};
}

Expand Down Expand Up @@ -589,7 +591,7 @@ service Lightning {
*/
rpc QueryRoutes(QueryRoutesRequest) returns (QueryRoutesResponse) {
option (google.api.http) = {
get: "/v1/graph/routes/{pub_key}/{amt}/{num_routes}"
get: "/v1/graph/routes/{pub_key}/{amt}"
};
}

Expand Down Expand Up @@ -666,6 +668,64 @@ service Lightning {
body: "*"
};
};

/** lncli: `sendrevdatatowt`
SendRevDataToWt allows the caller to send any of the previous revocation
data to watchtower.
*/
rpc SendRevDataToWt(SendRevDataToWtRequest) returns (SendRevDataToWtResponse);

/** lncli: `addwatchtower`
AddWatchtower allows the caller to connect to a remote lnd watchtower.
*/
rpc AddWatchtower (AddWatchtowerRequest) returns (AddWatchtowerResponse) {
option (google.api.http) = {
post: "/v1/watchtowers"
body: "*"
};
}

/** lncli: `listwatchtowers`
ListWatchtowers returns a verbose listing of all connected watchtowers
active and inactive.
*/
rpc ListWatchtowers (ListWatchtowersRequest) returns (ListWatchtowersResponse) {
option (google.api.http) = {
get: "/v1/watchtowers"
};
}

/** lncli: `disconnect`
DisconnectWatchtower allows the caller to close connection to specified
remote watchtower and removes related info from the database.
*/
rpc DisconnectWatchtower (DisconnectWatchtowerRequest) returns (DisconnectWatchtowerResponse) {
option (google.api.http) = {
delete: "/v1/watchtowers/{pub_key}"
};
}
}

message Utxo {
/// The type of address
AddressType type = 1 [json_name = "address_type"];

/// The address
string address = 2 [json_name = "address"];

/// The value of the unspent coin in satoshis
int64 amount_sat = 3 [json_name = "amount_sat"];

/// The scriptpubkey in hex
string script_pubkey = 4 [json_name = "script_pubkey"];

/// The outpoint in format txid:n
/// Note that this reuses the `ChannelPoint` message but
/// is not actually a channel related outpoint, of course
ChannelPoint outpoint = 5 [json_name = "outpoint"];

/// The number of confirmations for the Utxo
int64 confirmations = 6 [json_name = "confirmations"];
}

message Transaction {
Expand Down Expand Up @@ -751,6 +811,7 @@ message SendResponse {
string payment_error = 1 [json_name = "payment_error"];
bytes payment_preimage = 2 [json_name = "payment_preimage"];
Route payment_route = 3 [json_name = "payment_route"];
bytes payment_hash = 4 [json_name = "payment_hash"];
}

message SendToRouteRequest {
Expand Down Expand Up @@ -785,22 +846,6 @@ message LightningAddress {
string host = 2 [json_name = "host"];
}

message EstimateFeeRequest {
/// The map from addresses to amounts for the transaction.
map<string, int64> AddrToAmount = 1;

/// The target number of blocks that this transaction should be confirmed by.
int32 target_conf = 2;
}

message EstimateFeeResponse {
/// The total fee in satoshis.
int64 fee_sat = 1;

/// The fee rate in satoshi/byte.
int64 feerate_sat_per_kw = 2;
}

message SendManyRequest {
/// The map from addresses to amounts
map<string, int64> AddrToAmount = 1;
Expand Down Expand Up @@ -834,18 +879,31 @@ message SendCoinsResponse {
string txid = 1 [json_name = "txid"];
}

message ListUnspentRequest {
/// The minimum number of confirmations to be included.
int32 min_confs = 1;

/// The maximum number of confirmations to be included.
int32 max_confs = 2;
}
message ListUnspentResponse {
/// A list of utxos
repeated Utxo utxos = 1 [json_name = "utxos"];

}

/**
`AddressType` has to be one of:

- `p2wkh`: Pay to witness key hash (`WITNESS_PUBKEY_HASH` = 0)
- `np2wkh`: Pay to nested witness key hash (`NESTED_PUBKEY_HASH` = 1)
*/
message NewAddressRequest {
enum AddressType {
WITNESS_PUBKEY_HASH = 0;
NESTED_PUBKEY_HASH = 1;
}
enum AddressType {
WITNESS_PUBKEY_HASH = 0;
NESTED_PUBKEY_HASH = 1;
}

message NewAddressRequest {
/// The address type
AddressType type = 1;
}
Expand Down Expand Up @@ -1990,15 +2048,18 @@ message ForwardingEvent {
/// The outgoing channel ID that carried the preimage that completed the circuit.
uint64 chan_id_out = 4 [json_name = "chan_id_out"];

/// The total amount of the incoming HTLC that created half the circuit.
/// The total amount (in satoshis) of the incoming HTLC that created half the circuit.
uint64 amt_in = 5 [json_name = "amt_in"];

/// The total amount of the outgoign HTLC that created the second half of the circuit.
/// The total amount (in satoshis) of the outgoing HTLC that created the second half of the circuit.
uint64 amt_out = 6 [json_name = "amt_out"];

/// The total fee that this payment circuit carried.
/// The total fee (in satoshis) that this payment circuit carried.
uint64 fee = 7 [json_name = "fee"];

/// The total fee (in milli-satoshis) that this payment circuit carried.
uint64 fee_msat = 8 [json_name = "fee_msat"];

// TODO(roasbeef): add settlement latency?
// * use FPE on the chan id?
// * also list failures?
Expand All @@ -2010,3 +2071,58 @@ message ForwardingHistoryResponse {
/// The index of the last time in the set of returned forwarding events. Can be used to seek further, pagination style.
uint32 last_offset_index = 2 [json_name = "last_offset_index"];
}

message SendRevDataToWtRequest {
/// The channel for which the revocation data will be sent.
ChannelPoint channel_point = 1 [json_name = "channel_point"];

/// start_height is the first state number for which revocation data will be sent.
uint64 start_height = 2 [json_name = "start_height"];

/// end_height is the last state number for which revocation data will be sent.
uint64 end_height = 3 [json_name = "end_height"];
}

message SendRevDataToWtResponse {
/// The total number of state numbers for which revocation data could be successfully generated/retrieved and sent.
uint64 successfully_sent = 1 [json_name = "successfully_sent"];

/// The total number of state numbers for which revocation data could not be successfully generated/retrieved and sent.
uint64 failed_to_send = 2 [json_name = "failed_to_send"];
}

message AddWatchtowerRequest {
/// Lightning address of the peer, in the format `<pubkey>@host`
LightningAddress addr = 1;
}
message AddWatchtowerResponse {
}

message ListWatchtowersRequest {
bool active_only = 1;
bool inactive_only = 2;
}
message ListWatchtowersResponse {
/// The list of active channels
repeated Watchtower watchtowers = 1 [json_name = "watchtowers"];
}
message Watchtower {
/// Whether this watchtower is active or not
bool active = 1 [json_name = "active"];

/// The identity pubkey of the watchtower
string pub_key = 2 [json_name = "pub_key"];

string address = 3 [json_name = "address"];

/// Ping time to this peer
int64 ping_time = 4 [json_name = "ping_time"];

// TODO(ys): add time connected and bytes sent/received
}
message DisconnectWatchtowerRequest {
/// The pubkey of the watchtower to disconnect from
string pub_key = 1 [json_name = "pub_key"];
}
message DisconnectWatchtowerResponse {
}
7 changes: 7 additions & 0 deletions server/ipc.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ registerIpc("signMessage", async (event, arg) => lnd.call("SignMessage", {
msg: Buffer.from(arg.message, "hex"),
}));

registerIpc("connectWT", async () => lnd.call("AddWatchtower", {
addr: {
pubkey: settings.get.peach.pubKey,
host: `${settings.get.peach.host}:${settings.get.peach.watchtowerPort}`,
},
}));

registerIpc("genSeed", async () => lnd.call("GenSeed"));

// Peers
Expand Down
4 changes: 2 additions & 2 deletions settings.ini
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ maxpendingchannels = 5
[bitcoin]
active = true
node = neutrino
network = mainnet
network = testnet

[neutrino]
connect = proxy.lightningpeach.com:8333
connect = testnetwallet.lightningpeach.com:18333

[btcd]
rpcuser = rpcuser
Expand Down
9 changes: 5 additions & 4 deletions settings.peach.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
"appUrl": "https://peach-wallet.local.com"
},
"peach": {
"pubKey": "02a0bc43557fae6af7be8e3a29fdebda819e439bea9c0f8eb8ed6a0201f3471ca9",
"host": "hub.lightningpeach.com",
"peerPort": "29735",
"replenishUrl": "proxy.lightningpeach.com:7000",
"pubKey": "028596a962501f39f33f0d6f05f024dbafc0dcbde046e9e3bb55ae63767b85f681",
"host": "10.102.2.114",
"peerPort": "9735",
"watchtowerPort": "4127",
"replenishUrl": "testnetwallet.lightningpeach.com",
"replenishTLS": true
}
}
7 changes: 4 additions & 3 deletions settings.testnet.peach.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
"appUrl": "https://peach-wallet.local.com"
},
"peach": {
"pubKey": "0389a4d10d30e6176ea7cd0a7060344108061fc9ca88b02fa52dacea4b0114b316",
"host": "testnetwallet.lightningpeach.com",
"pubKey": "028596a962501f39f33f0d6f05f024dbafc0dcbde046e9e3bb55ae63767b85f681",
"host": "10.102.2.114",
"peerPort": "9735",
"watchtowerPort": "4127",
"replenishUrl": "testnetwallet.lightningpeach.com",
"replenishTLS": true
}
}
}