daemon: check and use routing info in HTLC packet.

We only support being the end node for the moment.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2016-06-30 09:08:10 +09:30
parent f4f0c1aa18
commit b2fdc86740
3 changed files with 104 additions and 23 deletions

View File

@ -188,9 +188,10 @@ void queue_pkt_htlc_add(struct peer *peer,
if (!blocks_to_abs_locktime(expiry, &locktime))
fatal("Invalid locktime?");
u->expiry = abs_locktime_to_proto(u, &locktime);
/* FIXME: routing! */
u->route = tal(u, Routing);
routing__init(u->route);
u->route->info.data = tal_dup_arr(u, u8, route, tal_count(route), 0);
u->route->info.len = tal_count(u->route->info.data);
/* BOLT #2:
*

View File

@ -534,6 +534,7 @@ static void state_event(struct peer *peer,
}
}
/* FIXME: Reason! */
static bool command_htlc_fail(struct peer *peer, u64 id)
{
if (!state_can_remove_htlc(peer->state))
@ -2251,6 +2252,96 @@ static const char *owner_name(enum channel_side side)
return side == OURS ? "our" : "their";
}
static void route_htlc_onwards(struct peer *peer,
const struct channel_htlc *htlc,
u64 msatoshis,
const BitcoinPubkey *pb_id,
const u8 *rest_of_route)
{
/* FIXME: implement */
}
static void their_htlc_added(struct peer *peer, const struct channel_htlc *htlc)
{
RouteStep *step;
const u8 *rest_of_route;
struct payment *payment;
if (abs_locktime_is_seconds(&htlc->expiry)) {
log_unusual(peer->log, "HTLC %"PRIu64" is in seconds", htlc->id);
command_htlc_fail(peer, htlc->id);
return;
}
if (abs_locktime_to_blocks(&htlc->expiry) <=
get_block_height(peer->dstate) + peer->dstate->config.min_htlc_expiry) {
log_unusual(peer->log, "HTLC %"PRIu64" expires too soon:"
" block %u",
htlc->id, abs_locktime_to_blocks(&htlc->expiry));
command_htlc_fail(peer, htlc->id);
return;
}
if (abs_locktime_to_blocks(&htlc->expiry) >
get_block_height(peer->dstate) + peer->dstate->config.max_htlc_expiry) {
log_unusual(peer->log, "HTLC %"PRIu64" expires too far:"
" block %u",
htlc->id, abs_locktime_to_blocks(&htlc->expiry));
command_htlc_fail(peer, htlc->id);
return;
}
step = onion_unwrap(peer, htlc->routing, tal_count(htlc->routing),
&rest_of_route);
if (!step) {
log_unusual(peer->log, "Bad onion, failing HTLC %"PRIu64,
htlc->id);
command_htlc_fail(peer, htlc->id);
return;
}
switch (step->next_case) {
case ROUTE_STEP__NEXT_END:
payment = find_payment(peer->dstate, &htlc->rhash);
if (!payment) {
log_unusual(peer->log, "No payment for HTLC %"PRIu64,
htlc->id);
log_add_struct(peer->log, " rhash=%s",
struct sha256, &htlc->rhash);
if (unlikely(!peer->dstate->dev_never_routefail))
command_htlc_fail(peer, htlc->id);
goto free_rest;
}
if (htlc->msatoshis != payment->msatoshis) {
log_unusual(peer->log, "Short payment for HTLC %"PRIu64
": %"PRIu64" not %"PRIu64 " satoshi!",
htlc->id,
htlc->msatoshis,
payment->msatoshis);
command_htlc_fail(peer, htlc->id);
return;
}
log_info(peer->log, "Immediately resolving HTLC %"PRIu64,
htlc->id);
command_htlc_fulfill(peer, htlc->id, &payment->r);
goto free_rest;
case ROUTE_STEP__NEXT_BITCOIN:
route_htlc_onwards(peer, htlc, step->amount, step->bitcoin,
rest_of_route);
goto free_rest;
default:
log_info(peer->log, "Unknown step type %u", step->next_case);
command_htlc_fail(peer, htlc->id);
goto free_rest;
}
free_rest:
tal_free(rest_of_route);
}
/* When changes are committed to. */
void peer_both_committed_to(struct peer *peer,
const union htlc_staging *changes,
@ -2311,29 +2402,9 @@ void peer_both_committed_to(struct peer *peer,
return;
for (i = 0; i < n; i++) {
struct payment *payment;
switch (changes[i].type) {
case HTLC_ADD:
payment = find_payment(peer->dstate, &changes[i].add.htlc.rhash);
if (payment) {
if (changes[i].add.htlc.msatoshis != payment->msatoshis) {
log_unusual(peer->log, "Got payment for %"PRIu64
" not %"PRIu64 " satoshi!",
changes[i].add.htlc.msatoshis,
payment->msatoshis);
command_htlc_fail(peer,
changes[i].add.htlc.id);
} else {
log_info(peer->log,
"Immediately resolving HTLC %"PRIu64,
changes[i].add.htlc.id);
command_htlc_fulfill(peer,
changes[i].add.htlc.id,
&payment->r);
}
}
/* FIXME: Otherwise, route. */
their_htlc_added(peer, &changes[i].add.htlc);
break;
case HTLC_FULFILL:
/* FIXME: resolve_one_htlc(peer, id, preimage); */

View File

@ -358,6 +358,10 @@ $CLI generate 3
check_peerstate lcli1 STATE_NORMAL
check_peerstate lcli2 STATE_NORMAL
# We turn off routing failure for the moment.
lcli1 dev-routefail false
lcli2 dev-routefail false
if [ -n "$DIFFERENT_FEES" ]; then
# This is 100,000 satoshi, so covers fees.
HTLC_AMOUNT=100000000
@ -731,6 +735,8 @@ B_AMOUNT=$(($B_AMOUNT + $HTLC_AMOUNT * 2))
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
# Now, use automatic payment redemption
lcli1 dev-routefail true
lcli2 dev-routefail true
RHASH3=`lcli2 accept-payment $HTLC_AMOUNT | sed 's/.*"\([0-9a-f]*\)".*/\1/'`
lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH3
@ -748,6 +754,9 @@ check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
# Now, failed payment (didn't pay enough)
RHASH4=`lcli2 accept-payment $HTLC_AMOUNT | sed 's/.*"\([0-9a-f]*\)".*/\1/'`
# Shouldn't have this already.
if lcli2 getlog | $FGREP 'Short payment for HTLC'; then exit 1; fi
lcli1 newhtlc $ID2 $(($HTLC_AMOUNT - 1)) $EXPIRY $RHASH4
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
@ -755,7 +764,7 @@ lcli1 newhtlc $ID2 $(($HTLC_AMOUNT - 1)) $EXPIRY $RHASH4
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
check lcli2 "getlog | $FGREP 'Got payment for '$(($HTLC_AMOUNT - 1))' not '$HTLC_AMOUNT"
check lcli2 "getlog | $FGREP 'Short payment for HTLC'"
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
lcli1 close $ID2