mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-02 18:35:00 +01:00
lightningd: track balance in way which matches channeld.
Currently it's fairly ad-hoc, but we need to tell it to channeld when it restarts, so we define it as the non-HTLC balance. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
f918c3a0e7
commit
a55b58d0d5
4 changed files with 63 additions and 20 deletions
|
@ -587,11 +587,11 @@ static void json_getpeers(struct command *cmd,
|
||||||
if (p->scid)
|
if (p->scid)
|
||||||
json_add_short_channel_id(response, "channel", p->scid);
|
json_add_short_channel_id(response, "channel", p->scid);
|
||||||
if (p->balance) {
|
if (p->balance) {
|
||||||
json_add_u64(response, "msatoshi_to_us",
|
json_add_u64(response, "msatoshi_to_us", *p->balance);
|
||||||
p->balance[LOCAL]);
|
json_add_u64(response, "msatoshi_total",
|
||||||
json_add_u64(response, "msatoshi_to_them",
|
p->funding_satoshi * 1000);
|
||||||
p->balance[REMOTE]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (leveltok) {
|
if (leveltok) {
|
||||||
info.response = response;
|
info.response = response;
|
||||||
json_array_start(response, "log");
|
json_array_start(response, "log");
|
||||||
|
@ -982,9 +982,11 @@ static void peer_start_channeld(struct peer *peer, enum peer_state oldstate,
|
||||||
log_debug(peer->log, "Waiting for HSM file descriptor");
|
log_debug(peer->log, "Waiting for HSM file descriptor");
|
||||||
|
|
||||||
/* Now we can consider balance set. */
|
/* Now we can consider balance set. */
|
||||||
peer->balance = tal_arr(peer, u64, NUM_SIDES);
|
peer->balance = tal(peer, u64);
|
||||||
peer->balance[peer->funder] = peer->funding_satoshi * 1000 - peer->push_msat;
|
if (peer->funder == LOCAL)
|
||||||
peer->balance[!peer->funder] = peer->push_msat;
|
*peer->balance = peer->funding_satoshi * 1000 - peer->push_msat;
|
||||||
|
else
|
||||||
|
*peer->balance = peer->push_msat;
|
||||||
|
|
||||||
peer_set_condition(peer, oldstate, GETTING_HSMFD);
|
peer_set_condition(peer, oldstate, GETTING_HSMFD);
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ struct peer {
|
||||||
u16 funding_outnum;
|
u16 funding_outnum;
|
||||||
u64 funding_satoshi, push_msat;
|
u64 funding_satoshi, push_msat;
|
||||||
|
|
||||||
/* Channel balance (LOCAL and REMOTE); if we have one. */
|
/* Amount going to us, not counting unfinished HTLCs; if we have one. */
|
||||||
u64 *balance;
|
u64 *balance;
|
||||||
|
|
||||||
/* Keys for channel. */
|
/* Keys for channel. */
|
||||||
|
|
|
@ -175,8 +175,8 @@ static void fulfill_htlc(struct htlc_in *hin, const struct preimage *preimage)
|
||||||
{
|
{
|
||||||
u8 *msg;
|
u8 *msg;
|
||||||
|
|
||||||
hin->key.peer->balance[LOCAL] += hin->msatoshi;
|
hin->preimage = tal_dup(hin, struct preimage, preimage);
|
||||||
hin->key.peer->balance[REMOTE] -= hin->msatoshi;
|
htlc_in_check(hin, __func__);
|
||||||
|
|
||||||
/* FIXME: fail the peer if it doesn't tell us that htlc fulfill is
|
/* FIXME: fail the peer if it doesn't tell us that htlc fulfill is
|
||||||
* committed before deadline.
|
* committed before deadline.
|
||||||
|
@ -628,10 +628,6 @@ static bool peer_fulfilled_our_htlc(struct peer *peer,
|
||||||
|
|
||||||
/* FIXME: Save to db */
|
/* FIXME: Save to db */
|
||||||
|
|
||||||
/* They fulfilled our HTLC. Credit them, forward immediately. */
|
|
||||||
peer->balance[REMOTE] += hout->msatoshi;
|
|
||||||
peer->balance[LOCAL] -= hout->msatoshi;
|
|
||||||
|
|
||||||
if (hout->in)
|
if (hout->in)
|
||||||
fulfill_htlc(hout->in, &fulfilled->payment_preimage);
|
fulfill_htlc(hout->in, &fulfilled->payment_preimage);
|
||||||
else
|
else
|
||||||
|
@ -665,16 +661,30 @@ static bool peer_failed_our_htlc(struct peer *peer,
|
||||||
static void remove_htlc_in(struct peer *peer, struct htlc_in *hin)
|
static void remove_htlc_in(struct peer *peer, struct htlc_in *hin)
|
||||||
{
|
{
|
||||||
htlc_in_check(hin, __func__);
|
htlc_in_check(hin, __func__);
|
||||||
log_debug(peer->log, "Removing in HTLC %"PRIu64" state %s",
|
assert(hin->failuremsg || hin->preimage);
|
||||||
hin->key.id, htlc_state_name(hin->hstate));
|
|
||||||
|
log_debug(peer->log, "Removing in HTLC %"PRIu64" state %s %s",
|
||||||
|
hin->key.id, htlc_state_name(hin->hstate),
|
||||||
|
hin->failuremsg ? "FAILED" : "FULFILLED");
|
||||||
|
|
||||||
|
/* If we fulfilled their HTLC, credit us. */
|
||||||
|
if (hin->preimage) {
|
||||||
|
log_debug(peer->log, "Balance %"PRIu64" -> %"PRIu64,
|
||||||
|
*peer->balance,
|
||||||
|
*peer->balance + hin->msatoshi);
|
||||||
|
*peer->balance += hin->msatoshi;
|
||||||
|
}
|
||||||
|
|
||||||
tal_free(hin);
|
tal_free(hin);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_htlc_out(struct peer *peer, struct htlc_out *hout)
|
static void remove_htlc_out(struct peer *peer, struct htlc_out *hout)
|
||||||
{
|
{
|
||||||
htlc_out_check(hout, __func__);
|
htlc_out_check(hout, __func__);
|
||||||
log_debug(peer->log, "Removing out HTLC %"PRIu64" state %s",
|
assert(hout->failuremsg || hout->preimage);
|
||||||
hout->key.id, htlc_state_name(hout->hstate));
|
log_debug(peer->log, "Removing out HTLC %"PRIu64" state %s %s",
|
||||||
|
hout->key.id, htlc_state_name(hout->hstate),
|
||||||
|
hout->failuremsg ? "FAILED" : "FULFILLED");
|
||||||
|
|
||||||
/* If it's failed, now we can forward since it's completely locked-in */
|
/* If it's failed, now we can forward since it's completely locked-in */
|
||||||
if (hout->failuremsg) {
|
if (hout->failuremsg) {
|
||||||
|
@ -687,6 +697,9 @@ static void remove_htlc_out(struct peer *peer, struct htlc_out *hout)
|
||||||
} else {
|
} else {
|
||||||
payment_failed(peer->ld, hout);
|
payment_failed(peer->ld, hout);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* We paid for this HTLC, so deduct balance. */
|
||||||
|
*peer->balance -= hout->msatoshi;
|
||||||
}
|
}
|
||||||
|
|
||||||
tal_free(hout);
|
tal_free(hout);
|
||||||
|
|
|
@ -204,6 +204,18 @@ class LightningDTests(BaseLightningDTests):
|
||||||
assert p1['owner'] == 'lightningd_gossip'
|
assert p1['owner'] == 'lightningd_gossip'
|
||||||
assert p2['owner'] == 'lightningd_gossip'
|
assert p2['owner'] == 'lightningd_gossip'
|
||||||
|
|
||||||
|
def test_balance(self):
|
||||||
|
l1,l2 = self.connect()
|
||||||
|
|
||||||
|
self.fund_channel(l1, l2, 10**6)
|
||||||
|
|
||||||
|
p1 = l1.rpc.getpeer(l2.info['id'], 'info')
|
||||||
|
p2 = l2.rpc.getpeer(l1.info['id'], 'info')
|
||||||
|
assert p1['msatoshi_to_us'] == 10**6 * 1000
|
||||||
|
assert p1['msatoshi_total'] == 10**6 * 1000
|
||||||
|
assert p2['msatoshi_to_us'] == 0
|
||||||
|
assert p2['msatoshi_total'] == 10**6 * 1000
|
||||||
|
|
||||||
def test_sendpay(self):
|
def test_sendpay(self):
|
||||||
l1,l2 = self.connect()
|
l1,l2 = self.connect()
|
||||||
|
|
||||||
|
@ -246,10 +258,27 @@ class LightningDTests(BaseLightningDTests):
|
||||||
self.assertRaises(ValueError, l1.rpc.sendpay, to_json([rs]), rhash)
|
self.assertRaises(ValueError, l1.rpc.sendpay, to_json([rs]), rhash)
|
||||||
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == False
|
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == False
|
||||||
|
|
||||||
|
# FIXME: test paying via another node, should fail to pay twice.
|
||||||
|
p1 = l1.rpc.getpeer(l2.info['id'], 'info')
|
||||||
|
p2 = l2.rpc.getpeer(l1.info['id'], 'info')
|
||||||
|
assert p1['msatoshi_to_us'] == 10**6 * 1000
|
||||||
|
assert p1['msatoshi_total'] == 10**6 * 1000
|
||||||
|
assert p2['msatoshi_to_us'] == 0
|
||||||
|
assert p2['msatoshi_total'] == 10**6 * 1000
|
||||||
|
|
||||||
# This works.
|
# This works.
|
||||||
l1.rpc.sendpay(to_json([routestep]), rhash)
|
l1.rpc.sendpay(to_json([routestep]), rhash)
|
||||||
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == True
|
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == True
|
||||||
|
|
||||||
|
# Balances should reflect it.
|
||||||
|
time.sleep(1)
|
||||||
|
p1 = l1.rpc.getpeer(l2.info['id'], 'info')
|
||||||
|
p2 = l2.rpc.getpeer(l1.info['id'], 'info')
|
||||||
|
assert p1['msatoshi_to_us'] == 10**6 * 1000 - amt
|
||||||
|
assert p1['msatoshi_total'] == 10**6 * 1000
|
||||||
|
assert p2['msatoshi_to_us'] == amt
|
||||||
|
assert p2['msatoshi_total'] == 10**6 * 1000
|
||||||
|
|
||||||
# Repeat will "succeed", but won't actually send anything (duplicate)
|
# Repeat will "succeed", but won't actually send anything (duplicate)
|
||||||
assert not l1.daemon.is_in_log('... succeeded')
|
assert not l1.daemon.is_in_log('... succeeded')
|
||||||
l1.rpc.sendpay(to_json([routestep]), rhash)
|
l1.rpc.sendpay(to_json([routestep]), rhash)
|
||||||
|
@ -263,7 +292,6 @@ class LightningDTests(BaseLightningDTests):
|
||||||
l1.rpc.sendpay(to_json([routestep]), rhash)
|
l1.rpc.sendpay(to_json([routestep]), rhash)
|
||||||
assert l2.rpc.listinvoice('testpayment3')[0]['complete'] == True
|
assert l2.rpc.listinvoice('testpayment3')[0]['complete'] == True
|
||||||
|
|
||||||
# FIXME: test paying via another node, should fail to pay twice.
|
|
||||||
|
|
||||||
def test_gossip_jsonrpc(self):
|
def test_gossip_jsonrpc(self):
|
||||||
l1,l2 = self.connect()
|
l1,l2 = self.connect()
|
||||||
|
|
Loading…
Add table
Reference in a new issue